source: wkhtmltox/trunk/fuentes/src/lib/imageconverter.cc @ 51

Last change on this file since 51 was 51, checked in by mabarracus, 4 years ago

wip

File size: 7.5 KB
Line 
1// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2// vi:set ts=4 sts=4 sw=4 noet :
3//
4// Copyright 2010, 2011 wkhtmltopdf authors
5//
6// This file is part of wkhtmltopdf.
7//
8// wkhtmltopdf is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Lesser General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12//
13// wkhtmltopdf is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public License
19// along with wkhtmltopdf.  If not, see <http://www.gnu.org/licenses/>.
20
21
22#include "imageconverter_p.hh"
23#include "imagesettings.hh"
24#include <QBuffer>
25#include <QDebug>
26#include <QEventLoop>
27#include <QFileInfo>
28#include <QImage>
29#include <QObject>
30#include <QObject>
31#include <QPainter>
32#include <QSvgGenerator>
33#include <QUrl>
34#include <QWebElement>
35#include <QWebFrame>
36#include <QWebPage>
37#include <qapplication.h>
38
39#ifdef Q_OS_WIN32
40#include <fcntl.h>
41#include <io.h>
42#endif
43
44namespace wkhtmltopdf {
45
46ImageConverterPrivate::ImageConverterPrivate(ImageConverter & o, wkhtmltopdf::settings::ImageGlobal & s, const QString * data):
47        settings(s),
48        loader(s.loadGlobal, true),
49        out(o) {
50        out.emitCheckboxSvgs(s.loadPage);
51        if (data) inputData = *data;
52
53        phaseDescriptions.push_back("Loading page");
54        phaseDescriptions.push_back("Rendering");
55        phaseDescriptions.push_back("Done");
56
57        connect(&loader, SIGNAL(loadProgress(int)), this, SLOT(loadProgress(int)));
58        connect(&loader, SIGNAL(loadFinished(bool)), this, SLOT(pagesLoaded(bool)));
59        connect(&loader, SIGNAL(error(QString)), this, SLOT(forwardError(QString)));
60        connect(&loader, SIGNAL(warning(QString)), this, SLOT(forwardWarning(QString)));
61}
62
63void ImageConverterPrivate::beginConvert() {
64        error = false;
65        convertionDone = false;
66        errorCode = 0;
67        progressString = "0%";
68        loaderObject = loader.addResource(settings.in, settings.loadPage, &inputData);
69        updateWebSettings(loaderObject->page.settings(), settings.web);
70        currentPhase=0;
71        emit out. phaseChanged();
72        loadProgress(0);
73        loader.load();
74}
75
76
77void ImageConverterPrivate::clearResources() {
78        loader.clearResources();
79}
80
81void ImageConverterPrivate::pagesLoaded(bool ok) {
82        if (errorCode == 0) errorCode = loader.httpErrorCode();
83        if (!ok) {
84                fail();
85                return;
86        }
87        // if fmt is empty try to get it from file extension in out
88        if (settings.fmt=="") {
89                if (settings.out == "-")
90                        settings.fmt = "jpg";
91                else {
92                        QFileInfo fi(settings.out);
93                        settings.fmt = fi.suffix();
94                }
95        }
96
97        // check whether image format is supported (for writing)
98//      QImageWriter test;
99//      test.setFormat(settings.fmt);
100//      if (!test.canWrite()) {
101//              if (!settings.quiet)printf("error: file format not supported\n");
102//              httpErrorCode=DEFAULT;
103//              return false;
104//      }
105        // create webkit frame and load website
106
107        currentPhase=1;
108        emit out. phaseChanged();
109        loadProgress(0);
110
111        QWebFrame * frame = loaderObject->page.mainFrame();
112        loaderObject->page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
113
114        loadProgress(25);
115        // Calculate a good width for the image
116        int highWidth=settings.screenWidth;
117        loaderObject->page.setViewportSize(QSize(highWidth, 10));
118        if (settings.smartWidth && frame->scrollBarMaximum(Qt::Horizontal) > 0) {
119                if (highWidth < 10) highWidth=10;
120                int lowWidth=highWidth;
121                while (frame->scrollBarMaximum(Qt::Horizontal) > 0 && highWidth < 32000) {
122                        lowWidth = highWidth;
123                        highWidth *= 2;
124                        loaderObject->page.setViewportSize(QSize(highWidth, 10));
125                }
126                while (highWidth - lowWidth > 10) {
127                        int t = lowWidth + (highWidth - lowWidth)/2;
128                        loaderObject->page.setViewportSize(QSize(t, 10));
129                        if (frame->scrollBarMaximum(Qt::Horizontal) > 0)
130                                lowWidth = t;
131                        else
132                                highWidth = t;
133                }
134                loaderObject->page.setViewportSize(QSize(highWidth, 10));
135        }
136        loaderObject->page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
137        //Set the right height
138        if (settings.screenHeight > 0)
139                loaderObject->page.setViewportSize(QSize(highWidth, settings.screenHeight));
140        else
141                loaderObject->page.setViewportSize(QSize(highWidth, frame->contentsSize().height()));
142
143        QPainter painter;
144        QSvgGenerator generator;
145        QImage image;
146        QFile file;
147        QBuffer buffer(&outputData);
148        QIODevice * dev = &file;
149
150        bool openOk=true;
151        // output image
152        if (settings.out.isEmpty())
153                dev =  &buffer;
154        else if (settings.out != "-" ) {
155                file.setFileName(settings.out);
156                openOk = file.open(QIODevice::WriteOnly);
157        } else {
158#ifdef Q_OS_WIN32
159                _setmode(_fileno(stdout), _O_BINARY);
160#endif
161                openOk = file.open(stdout, QIODevice::WriteOnly);
162    }
163
164        if (!openOk) {
165                emit out.error("Could not write to output file");
166                fail();
167        }
168
169        if (settings.crop.left < 0) settings.crop.left = 0;
170        if (settings.crop.top < 0) settings.crop.top = 0;
171        if (settings.crop.width < 0) settings.crop.width = 1000000;
172        if (settings.crop.height < 0) settings.crop.height = 1000000;
173        QRect rect = QRect(QPoint(0,0), loaderObject->page.viewportSize()).intersected(
174                QRect(settings.crop.left,settings.crop.top,settings.crop.width,settings.crop.height));
175        if (rect.width() == 0 || rect.height() == 0) {
176                emit out.error("Will not output an empty image");
177                fail();
178        }
179
180        if (settings.fmt != "svg") {
181                image = QImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
182                painter.begin(&image);
183        } else {
184                generator.setOutputDevice(dev);
185                generator.setSize(rect.size());
186                generator.setViewBox(QRect(QPoint(0,0),rect.size()));
187#ifdef __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
188                generator.setViewBoxClip(true);
189#endif
190                painter.begin(&generator);
191        }
192
193        if (settings.transparent && (settings.fmt == "png" || settings.fmt == "svg")) {
194                QWebElement e = frame->findFirstElement("body");
195                e.setStyleProperty("background-color", "transparent");
196                e.setStyleProperty("background-image", "none");
197                QPalette pal = loaderObject->page.palette();
198                pal.setBrush(QPalette::Base, Qt::transparent);
199                loaderObject->page.setPalette(pal);
200        } else {
201                painter.fillRect(QRect(QPoint(0,0),loaderObject->page.viewportSize()), Qt::white);
202        }
203        painter.translate(-rect.left(), -rect.top());
204        frame->render(&painter);
205        painter.end();
206
207        //loadProgress(30);
208        // perform filter(s)
209        //if (settings.crop.width > 0 && settings.crop.height > 0)
210        //      image=image.copy(settings.crop.left,settings.crop.top,settings.crop.width,settings.crop.height);
211        //loadProgress(50);
212        //if (settings.scale.width > 0 && settings.scale.height > 0) {
213                // todo: perhaps get more user options to change aspect ration and scaling mode?
214        //      image=image.scaled(settings.scale.width,settings.scale.height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
215        //}
216        //loadProgress(80);
217
218        if (settings.fmt != "svg") {
219                QByteArray fmt=settings.fmt.toLatin1();
220                if (!image.save(dev,fmt.data(), settings.quality)) {
221                        emit out.error("Could not save image");
222                        fail();
223                }
224        }
225        loadProgress(100);
226
227        currentPhase = 2;
228        emit out.phaseChanged();
229        convertionDone = true;
230        emit out.finished(true);
231
232        qApp->exit(0); // quit qt's event handling
233}
234
235Converter & ImageConverterPrivate::outer() {
236        return out;
237}
238
239ImageConverter::~ImageConverter() {
240        delete d;
241}
242
243ConverterPrivate & ImageConverter::priv() {
244        return *d;
245}
246
247
248ImageConverter::ImageConverter(wkhtmltopdf::settings::ImageGlobal & s, const QString * data) {
249        d = new ImageConverterPrivate(*this, s, data);
250}
251
252const QByteArray & ImageConverter::output() {
253        return d->outputData;
254}
255
256}
Note: See TracBrowser for help on using the repository browser.