📄 qprintengine_pdf.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <qiodevice.h>#include <qpainter.h>#include <qbitmap.h>#include <qpainterpath.h>#include <qpaintdevice.h>#include <qfile.h>#include <qdebug.h>#ifndef QT_NO_PRINTER#include <time.h>#include <limits.h>#include <math.h>#ifndef QT_NO_COMPRESS#include <zlib.h>#endif#include "qprintengine_pdf_p.h"#include "private/qdrawhelper_p.h"extern int qt_defaultDpi();extern qint64 qt_pixmap_id(const QPixmap &pixmap);extern qint64 qt_image_id(const QImage &image);//#define FONT_DUMP// might be helpful for smooth transforms of images// Can't use it though, as gs generates completely wrong images if this is true.static const bool interpolateImages = false;#ifdef QT_NO_COMPRESSstatic const bool do_compress = false;#elsestatic const bool do_compress = true;#endifQPdfPage::QPdfPage() : QPdf::ByteStream(&data){}void QPdfPage::streamImage(int w, int h, int object){ *this << "/GSa gs " << w << "0 0 " << -h << "0 " << h << "cm /Im" << object << " Do\n"; if (!images.contains(object)) images.append(object);}inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features(){ QPaintEngine::PaintEngineFeatures f = QPaintEngine::AllFeatures; f &= ~(QPaintEngine::PorterDuff#ifndef USE_NATIVE_GRADIENTS | QPaintEngine::LinearGradientFill#endif | QPaintEngine::RadialGradientFill | QPaintEngine::ConicalGradientFill); return f;}QPdfEngine::QPdfEngine(QPrinter::PrinterMode m) : QPdfBaseEngine(*new QPdfEnginePrivate, qt_pdf_decide_features()), outFile_(new QFile){ Q_D(QPdfEngine); device_ = 0; state = QPrinter::Idle; pagesize_ = QPrinter::A4; if (m == QPrinter::HighResolution) d->resolution = 1200; else if (m == QPrinter::ScreenResolution) d->resolution = qt_defaultDpi(); QRect r = paperRect(); d->setDimensions(qRound(r.width()*72./d->resolution),qRound(r.height()*72./d->resolution));}QPdfEngine::~QPdfEngine(){ delete outFile_;}void QPdfEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value){ Q_D(QPdfEngine); switch (key) { case PPK_Creator: d->creator = value.toString(); break; case PPK_DocumentName: d->title = value.toString(); break; case PPK_Orientation: { d->orientation = QPrinter::Orientation(value.toInt()); break; } case PPK_OutputFileName: { if (isActive()) { qWarning("QPdfEngine::setFileName: Not possible while painting"); return; } QString filename = value.toString(); if (filename.isEmpty()) return; outFile_->setFileName(filename); setDevice(outFile_); } break; case PPK_PageSize: { pagesize_ = QPrinter::PageSize(value.toInt()); } break; case PPK_Resolution: d->resolution = value.toInt(); case PPK_FullPage: d->fullPage = value.toBool(); break; default: break; } QRect r = paperRect(); d->setDimensions(qRound(r.width()*72./d->resolution),qRound(r.height()*72./d->resolution));}QVariant QPdfEngine::property(PrintEnginePropertyKey key) const{ Q_D(const QPdfEngine); switch (key) { case PPK_ColorMode: return QPrinter::Color; case PPK_Creator: return d->creator; case PPK_DocumentName: return d->title; case PPK_FullPage: return d->fullPage; case PPK_NumberOfCopies: return 1; case PPK_Orientation: return d->orientation; case PPK_OutputFileName: return outFile_->fileName(); case PPK_PageRect: return pageRect(); case PPK_PageSize: return pagesize_; case PPK_PaperRect: return paperRect(); case PPK_PaperSource: return QPrinter::Auto; case PPK_Resolution: return d->resolution; case PPK_SupportedResolutions: return QList<QVariant>() << d->resolution; default: break; } return QVariant();}void QPdfEngine::setAuthor(const QString &author){ Q_D(QPdfEngine); d->author = author;}QString QPdfEngine::author() const{ Q_D(const QPdfEngine); return d->author;}QRect QPdfEngine::paperRect() const{ Q_D(const QPdfEngine); QPdf::PaperSize s = QPdf::paperSize(pagesize_); int w = qRound(s.width*d->resolution/72.); int h = qRound(s.height*d->resolution/72.); if (d->orientation == QPrinter::Portrait) return QRect(0, 0, w, h); else return QRect(0, 0, h, w);}QRect QPdfEngine::pageRect() const{ Q_D(const QPdfEngine); QRect r = paperRect(); if (d->fullPage) return r; // would be nice to get better margins than this. return QRect(d->resolution/3, d->resolution/3, r.width()-2*d->resolution/3, r.height()-2*d->resolution/3);}void QPdfEngine::setDevice(QIODevice* dev){ if (isActive()) { qWarning("QPdfEngine::setDevice: Device cannot be set while painting"); return; } device_ = dev;}bool QPdfEngine::begin(QPaintDevice *){ Q_D(QPdfEngine); if (!device_) { qWarning("QPdfEngine::begin: No valid device"); return false; } if (device_->isOpen()) device_->close(); if(!device_->open(QIODevice::WriteOnly)) { qWarning("QPdfEngine::begin: Cannot open IO device"); return false; } d->hasPen = true; d->hasBrush = false; d->clipEnabled = false; d->allClipped = false; d->unsetDevice(); d->setDevice(device_); setActive(true); state = QPrinter::Active; d->writeHeader(); newPage(); return true;}bool QPdfEngine::end(){ Q_D(QPdfEngine); d->writeTail(); device_->close(); d->unsetDevice(); setActive(false); state = QPrinter::Idle; return true;}void QPdfEngine::drawPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QRectF & sr){ if (sr.isEmpty() || rectangle.isEmpty() || pixmap.isNull()) return; Q_D(QPdfEngine); QBrush b = d->brush; QRect sourceRect = sr.toRect(); QPixmap pm = sourceRect != pixmap.rect() ? pixmap.copy(sourceRect) : pixmap; QImage image = pm.toImage(); *d->currentPage << "q\n"; *d->currentPage << QPdf::generateMatrix(QMatrix(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(), rectangle.x(), rectangle.y()) * d->stroker.matrix); bool bitmap = true; int object = d->addImage(image, &bitmap, qt_pixmap_id(pm)); if (bitmap) { if (d->backgroundMode == Qt::OpaqueMode) { // draw background d->brush = d->backgroundBrush; setBrush(); *d->currentPage << "0 0 " << rectangle.width() << rectangle.height() << "re f\n"; } // set current pen as d->brush d->brush = d->pen.brush(); setBrush(); } d->currentPage->streamImage(image.width(), image.height(), object); *d->currentPage << "Q\n"; d->brush = b;}void QPdfEngine::drawImage(const QRectF & rectangle, const QImage & image, const QRectF & sr, Qt::ImageConversionFlags){ if (sr.isEmpty() || rectangle.isEmpty() || image.isNull()) return; Q_D(QPdfEngine); QRect sourceRect = sr.toRect(); QImage im = sourceRect != image.rect() ? image.copy(sr.toRect()) : image; *d->currentPage << "q\n"; *d->currentPage << QPdf::generateMatrix(QMatrix(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(), rectangle.x(), rectangle.y()) * d->stroker.matrix); bool bitmap = false; int object = d->addImage(im, &bitmap, qt_image_id(im)); d->currentPage->streamImage(image.width(), image.height(), object); *d->currentPage << "Q\n";}void QPdfEngine::drawTiledPixmap (const QRectF &rectangle, const QPixmap &pixmap, const QPointF &point){ Q_D(QPdfEngine); bool bitmap = (pixmap.depth() == 1); QBrush b = d->brush; QPointF bo = d->brushOrigin; bool hp = d->hasPen; d->hasPen = false; bool hb = d->hasBrush; d->hasBrush = true; if (bitmap) { if (d->backgroundMode == Qt::OpaqueMode) { // draw background d->brush = d->backgroundBrush; setBrush(); *d->currentPage << "q\n"; *d->currentPage << QPdf::generateMatrix(d->stroker.matrix); *d->currentPage << rectangle.x() << rectangle.y() << rectangle.width() << rectangle.height() << "re f Q\n"; } } d->brush = QBrush(pixmap); if (bitmap) // #### fix bitmap case where we have a brush pen d->brush.setColor(d->pen.color()); d->brushOrigin = -point; *d->currentPage << "q\n"; setBrush(); drawRects(&rectangle, 1); *d->currentPage << "Q\n"; d->hasPen = hp; d->hasBrush = hb; d->brush = b; d->brushOrigin = bo;}void QPdfEngine::setBrush(){ Q_D(QPdfEngine); bool specifyColor; int gStateObject = 0; int patternObject = d->addBrushPattern(d->stroker.matrix, &specifyColor, &gStateObject); *d->currentPage << (patternObject ? "/PCSp cs " : "/CSp cs "); if (specifyColor) { QColor rgba = d->brush.color(); *d->currentPage << rgba.redF() << rgba.greenF() << rgba.blueF(); } if (patternObject) *d->currentPage << "/Pat" << patternObject; *d->currentPage << "scn\n"; if (gStateObject) *d->currentPage << "/GState" << gStateObject << "gs\n"; else *d->currentPage << "/GSa gs\n";}int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const{ Q_D(const QPdfEngine); int val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -