⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qprintengine_pdf.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 <QtGui/qprintengine.h>#include <qiodevice.h>#include <qpainter.h>#include <qbitmap.h>#include <qpainterpath.h>#include <qpaintdevice.h>#include <qfile.h>#include <qdebug.h>#include <qimagewriter.h>#include <qbuffer.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 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 | QPaintEngine::PerspectiveTransform#ifndef USE_NATIVE_GRADIENTS           | QPaintEngine::LinearGradientFill#endif           | QPaintEngine::RadialGradientFill           | QPaintEngine::ConicalGradientFill);    return f;}QPdfEngine::QPdfEngine(QPrinter::PrinterMode m)    : QPdfBaseEngine(*new QPdfEnginePrivate(m), qt_pdf_decide_features()){    state = QPrinter::Idle;}QPdfEngine::~QPdfEngine(){}bool QPdfEngine::begin(QPaintDevice *pdev){    Q_D(QPdfEngine);    if(!QPdfBaseEngine::begin(pdev))        return false;    d->stream->setDevice(d->outDevice);    d->streampos = 0;    d->hasPen = true;    d->hasBrush = false;    d->clipEnabled = false;    d->allClipped = false;    d->xrefPositions.clear();    d->pageRoot = 0;    d->catalog = 0;    d->info = 0;    d->graphicsState = 0;    d->patternColorSpace = 0;    d->pages.clear();    d->imageCache.clear();    setActive(true);    state = QPrinter::Active;    d->writeHeader();    newPage();    return true;}bool QPdfEngine::end(){    Q_D(QPdfEngine);    d->writeTail();    d->stream->unsetDevice();    QPdfBaseEngine::end();    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(QTransform(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(),                                           rectangle.x(), rectangle.y()) * (d->simplePen ? QTransform() : d->stroker.matrix));    bool bitmap = true;    int object = d->addImage(image, &bitmap, pm.cacheKey());    if (bitmap) {        // 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(sourceRect) : image;    *d->currentPage << "q\n";    *d->currentPage        << QPdf::generateMatrix(QTransform(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(),                                           rectangle.x(), rectangle.y()) * (d->simplePen ? QTransform() : d->stroker.matrix));    bool bitmap = false;    int object = d->addImage(im, &bitmap, im.cacheKey());    d->currentPage->streamImage(im.width(), im.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;    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);    Qt::BrushStyle style = d->brush.style();    if (style == Qt::NoBrush)        return;    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";}QPaintEngine::Type QPdfEngine::type() const{    return QPaintEngine::User;}bool QPdfEngine::newPage(){    Q_D(QPdfEngine);    if (!isActive())        return false;    d->newPage();    return QPdfBaseEngine::newPage();}QPdfEnginePrivate::QPdfEnginePrivate(QPrinter::PrinterMode m)    : QPdfBaseEnginePrivate(m){    streampos = 0;    stream = new QDataStream;    pageOrder = QPrinter::FirstPageFirst;    orientation = QPrinter::Portrait;    fullPage = false;}QPdfEnginePrivate::~QPdfEnginePrivate(){    delete stream;}#ifdef USE_NATIVE_GRADIENTSint QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject){    const QGradient *gradient = b.gradient();    if (!gradient)        return 0;    QTransform inv = matrix.inverted();    QPointF page_rect[4] = { inv.map(QPointF(0, 0)),                             inv.map(QPointF(width_, 0)),                             inv.map(QPointF(0, height_)),                             inv.map(QPointF(width_, height_)) };    bool opaque = b.isOpaque();    QByteArray shader;    QByteArray alphaShader;    if (gradient->type() == QGradient::LinearGradient) {        const QLinearGradient *lg = static_cast<const QLinearGradient *>(gradient);        shader = QPdf::generateLinearGradientShader(lg, page_rect);        if (!opaque)            alphaShader = QPdf::generateLinearGradientShader(lg, page_rect, true);    } else {        // #############        return 0;    }    int shaderObject = addXrefEntry(-1);    write(shader);    QByteArray str;    QPdf::ByteStream s(&str);    s << "<<\n"        "/Type /Pattern\n"        "/PatternType 2\n"        "/Shading " << shaderObject << "0 R\n"        "/Matrix ["      << matrix.m11()      << matrix.m12()      << matrix.m21()      << matrix.m22()      << matrix.dx()      << matrix.dy() << "]\n";    s << ">>\n"        "endobj\n";    int patternObj = addXrefEntry(-1);    write(str);    currentPage->patterns.append(patternObj);    if (!opaque) {        bool ca = true;        QGradientStops stops = gradient->stops();        int a = stops.at(0).second.alpha();        for (int i = 1; i < stops.size(); ++i) {            if (stops.at(i).second.alpha() != a) {                ca = false;                break;            }        }        if (ca) {            *gStateObject = addConstantAlphaObject(stops.at(0).second.alpha());        } else {            int alphaShaderObject = addXrefEntry(-1);            write(alphaShader);            QByteArray content;            QPdf::ByteStream c(&content);            c << "/Shader" << alphaShaderObject << "sh\n";            QByteArray form;            QPdf::ByteStream f(&form);            f << "<<\n"                "/Type /XObject\n"                "/Subtype /Form\n"                "/BBox [0 0 " << width_ << height_ << "]\n"                "/Group <</S /Transparency >>\n"                "/Resources <<\n"                "/Shading << /Shader" << alphaShaderObject << alphaShaderObject << "0 R >>\n"                ">>\n";            f << "/Length " << content.length() << "\n"                ">>\n"                "stream\n"              << content              << "endstream\n"                "endobj\n";            int softMaskFormObject = addXrefEntry(-1);            write(form);            *gStateObject = addXrefEntry(-1);            xprintf("<< /SMask << /S /Alpha /G %d 0 R >> >>\n"                    "endobj\n", softMaskFormObject);            currentPage->graphicStates.append(*gStateObject);        }    }    return patternObj;}#endifint QPdfEnginePrivate::addConstantAlphaObject(int alpha){    if (alpha == 255)        return 0;    int object = alphaCache.value(alpha, 0);    if (!object) {        object = addXrefEntry(-1);        QByteArray alphaDef;        QPdf::ByteStream s(&alphaDef);        s << "<< /ca " << (alpha/qreal(255.)) << ">>";        xprintf("%s\nendobj\n", alphaDef.constData());    }    currentPage->graphicStates.append(object);    return object;}int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject){    int paintType = 2; // Uncolored tiling    int w = 8;    int h = 8;    *specifyColor = true;    *gStateObject = 0;    QTransform matrix = m;    matrix.translate(brushOrigin.x(), brushOrigin.y());    matrix = matrix * pageMatrix();    //qDebug() << brushOrigin << matrix;    Qt::BrushStyle style = brush.style();    if (style == Qt::LinearGradientPattern) {// && style <= Qt::ConicalGradientPattern) {#ifdef USE_NATIVE_GRADIENTS        *specifyColor = false;        return gradientBrush(b, matrix, gStateObject);#else        return 0;#endif    }    if (!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern)        *gStateObject = addConstantAlphaObject(brush.color().alpha());    int imageObject = 0;    QByteArray pattern = QPdf::patternForBrush(brush);    if (pattern.isEmpty()) {        if (brush.style() != Qt::TexturePattern)            return 0;        QImage image = brush.texture().toImage();        bool bitmap = true;        imageObject = addImage(image, &bitmap, qt_pixmap_id(brush.texture()));        QImage::Format f = image.format();        if (f != QImage::Format_MonoLSB && f != QImage::Format_Mono) {            paintType = 1; // Colored tiling            *specifyColor = false;        }        w = image.width();        h = image.height();        QTransform m(w, 0, 0, -h, 0, h);        QPdf::ByteStream s(&pattern);        s << QPdf::generateMatrix(m);        s << "/Im" << imageObject << " Do\n";    }    QByteArray str;    QPdf::ByteStream s(&str);    s << "<<\n"        "/Type /Pattern\n"        "/PatternType 1\n"        "/PaintType " << paintType << "\n"        "/TilingType 1\n"        "/BBox [0 0 " << w << h << "]\n"        "/XStep " << w << "\n"        "/YStep " << h << "\n"        "/Matrix ["      << matrix.m11()      << matrix.m12()      << matrix.m21()      << matrix.m22()      << matrix.dx()      << matrix.dy() << "]\n"        "/Resources \n<< "; // open resource tree    if (imageObject) {        s << "/XObject << /Im" << imageObject << ' ' << imageObject << "0 R >> ";    }    s << ">>\n"        "/Length " << pattern.length() << "\n"        ">>\n"        "stream\n"      << pattern      << "endstream\n"        "endobj\n";    int patternObj = addXrefEntry(-1);    write(str);    currentPage->patterns.append(patternObj);    return patternObj;}int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_no){    if (img.isNull())        return -1;    int object = imageCache.value(serial_no);    if(object)        return object;    QImage image = img;    QImage::Format format = image.format();    if (image.depth() == 1 && *bitmap) {        if (format == QImage::Format_MonoLSB)            image = image.convertToFormat(QImage::Format_Mono);        format = QImage::Format_Mono;    } else {        *bitmap = false;        if (format != QImage::Format_RGB32 && format != QImage::Format_ARGB32) {            image = image.convertToFormat(QImage::Format_ARGB32);            format = QImage::Format_ARGB32;        }    }    int w = image.width();    int h = image.height();    int d = image.depth();    if (format == QImage::Format_Mono) {        int bytesPerLine = (w + 7) >> 3;        QByteArray data;        data.resize(bytesPerLine * h);        char *rawdata = data.data();        for (int y = 0; y < h; ++y) {            memcpy(rawdata, image.scanLine(y), bytesPerLine);            rawdata += bytesPerLine;        }        object = writeImage(data, w, h, d, 0, 0);    } else {        QByteArray softMaskData;        bool dct = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -