📄 qpdf.cpp
字号:
/******************************************************************************** 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 "qplatformdefs.h"#include <qdebug.h>#include "qpdf_p.h"#include <qfile.h>#include <private/qmath_p.h>#include "private/qcups_p.h"extern int qt_defaultDpi();#ifndef QT_NO_PRINTER/* also adds a space at the end of the number */const char *qt_real_to_string(qreal val, char *buf) { const char *ret = buf; if (val < 0) { *(buf++) = '-'; val = -val; } int ival = (int) val; qreal frac = val - (qreal)ival; int ifrac = (int)(frac * 1000000); if (ifrac == 1000000) { ++ival; ifrac = 0; } char output[256]; int i = 0; while (ival) { output[i] = '0' + (ival % 10); ++i; ival /= 10; } int fact = 100000; if (i == 0) { *(buf++) = '0'; } else { while (i) { *(buf++) = output[--i]; fact /= 10; ifrac /= 10; } } if (ifrac) { *(buf++) = '.'; while (fact) { *(buf++) = '0' + ((ifrac/fact) % 10); fact /= 10; } } *(buf++) = ' '; *buf = 0; return ret;}const char *qt_int_to_string(int val, char *buf) { const char *ret = buf; if (val < 0) { *(buf++) = '-'; val = -val; } char output[256]; int i = 0; while (val) { output[i] = '0' + (val % 10); ++i; val /= 10; } if (i == 0) { *(buf++) = '0'; } else { while (i) *(buf++) = output[--i]; } *(buf++) = ' '; *buf = 0; return ret;}#define QT_PATH_ELEMENT(elm)QByteArray QPdf::generatePath(const QPainterPath &path, const QTransform &matrix, PathFlags flags){ QByteArray result; if (!path.elementCount()) return result; ByteStream s(&result); int start = -1; for (int i = 0; i < path.elementCount(); ++i) { const QPainterPath::Element &elm = path.elementAt(i); switch (elm.type) { case QPainterPath::MoveToElement: if (start >= 0 && path.elementAt(start).x == path.elementAt(i-1).x && path.elementAt(start).y == path.elementAt(i-1).y) s << "h\n"; s << matrix.map(QPointF(elm.x, elm.y)) << "m\n"; start = i; break; case QPainterPath::LineToElement: s << matrix.map(QPointF(elm.x, elm.y)) << "l\n"; break; case QPainterPath::CurveToElement: Q_ASSERT(path.elementAt(i+1).type == QPainterPath::CurveToDataElement); Q_ASSERT(path.elementAt(i+2).type == QPainterPath::CurveToDataElement); s << matrix.map(QPointF(elm.x, elm.y)) << matrix.map(QPointF(path.elementAt(i+1).x, path.elementAt(i+1).y)) << matrix.map(QPointF(path.elementAt(i+2).x, path.elementAt(i+2).y)) << "c\n"; i += 2; break; default: qFatal("QPdf::generatePath(), unhandled type: %d", elm.type); } } if (start >= 0 && path.elementAt(start).x == path.elementAt(path.elementCount()-1).x && path.elementAt(start).y == path.elementAt(path.elementCount()-1).y) s << "h\n"; Qt::FillRule fillRule = path.fillRule(); const char *op = 0; switch (flags) { case ClipPath: op = (fillRule == Qt::WindingFill) ? "W n\n" : "W* n\n"; break; case FillPath: op = (fillRule == Qt::WindingFill) ? "f\n" : "f*\n"; break; case StrokePath: op = "S\n"; break; case FillAndStrokePath: op = (fillRule == Qt::WindingFill) ? "B\n" : "B*\n"; break; } s << op; return result;}QByteArray QPdf::generateMatrix(const QTransform &matrix){ QByteArray result; ByteStream s(&result); s << matrix.m11() << matrix.m12() << matrix.m21() << matrix.m22() << matrix.dx() << matrix.dy() << "cm\n"; return result;}QByteArray QPdf::generateDashes(const QPen &pen){ QByteArray result; ByteStream s(&result); s << "["; QVector<qreal> dasharray = pen.dashPattern(); qreal w = pen.widthF(); if (w < 0.001) w = 1; for (int i = 0; i < dasharray.size(); ++i) { qreal dw = dasharray.at(i)*w; if (dw < 0.0001) dw = 0.0001; s << dw; } s << "]"; //qDebug() << "dasharray: pen has" << dasharray; //qDebug() << " => " << result; return result;}static const char* pattern_for_brush[] = { 0, // NoBrush 0, // SolidPattern "0 J\n" "6 w\n" "[] 0 d\n" "4 0 m\n" "4 8 l\n" "0 4 m\n" "8 4 l\n" "S\n", // Dense1Pattern "0 J\n" "2 w\n" "[6 2] 1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n" "[] 0 d\n" "2 0 m\n" "2 8 l\n" "6 0 m\n" "6 8 l\n" "S\n" "[6 2] -3 d\n" "4 0 m\n" "4 8 l\n" "S\n", // Dense2Pattern "0 J\n" "2 w\n" "[6 2] 1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n" "[2 2] -1 d\n" "2 0 m\n" "2 8 l\n" "6 0 m\n" "6 8 l\n" "S\n" "[6 2] -3 d\n" "4 0 m\n" "4 8 l\n" "S\n", // Dense3Pattern "0 J\n" "2 w\n" "[2 2] 1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n" "[2 2] -1 d\n" "2 0 m\n" "2 8 l\n" "6 0 m\n" "6 8 l\n" "S\n" "[2 2] 1 d\n" "4 0 m\n" "4 8 l\n" "S\n", // Dense4Pattern "0 J\n" "2 w\n" "[2 6] -1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n" "[2 2] 1 d\n" "2 0 m\n" "2 8 l\n" "6 0 m\n" "6 8 l\n" "S\n" "[2 6] 3 d\n" "4 0 m\n" "4 8 l\n" "S\n", // Dense5Pattern "0 J\n" "2 w\n" "[2 6] -1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n" "[2 6] 3 d\n" "4 0 m\n" "4 8 l\n" "S\n", // Dense6Pattern "0 J\n" "2 w\n" "[2 6] -1 d\n" "0 0 m\n" "0 8 l\n" "8 0 m\n" "8 8 l\n" "S\n", // Dense7Pattern "1 w\n" "0 4 m\n" "8 4 l\n" "S\n", // HorPattern "1 w\n" "4 0 m\n" "4 8 l\n" "S\n", // VerPattern "1 w\n" "4 0 m\n" "4 8 l\n" "0 4 m\n" "8 4 l\n" "S\n", // CrossPattern "1 w\n" "-1 5 m\n" "5 -1 l\n" "3 9 m\n" "9 3 l\n" "S\n", // BDiagPattern "1 w\n" "-1 3 m\n" "5 9 l\n" "3 -1 m\n" "9 5 l\n" "S\n", // FDiagPattern "1 w\n" "-1 3 m\n" "5 9 l\n" "3 -1 m\n" "9 5 l\n" "-1 5 m\n" "5 -1 l\n" "3 9 m\n" "9 3 l\n" "S\n", // DiagCrossPattern};QByteArray QPdf::patternForBrush(const QBrush &b){ int style = b.style(); if (style > Qt::DiagCrossPattern) return QByteArray(); return pattern_for_brush[style];}#ifdef USE_NATIVE_GRADIENTSstatic void writeTriangleLine(uchar *&data, int xpos, int ypos, int xoff, int yoff, uint rgb, uchar flag, bool alpha){ data[0] = flag; data[1] = (uchar)(xpos >> 16); data[2] = (uchar)(xpos >> 8); data[3] = (uchar)(xpos >> 0); data[4] = (uchar)(ypos >> 16); data[5] = (uchar)(ypos >> 8); data[6] = (uchar)(ypos >> 0); data += 7; if (alpha) { *data++ = (uchar)qAlpha(rgb); } else { *data++ = (uchar)qRed(rgb); *data++ = (uchar)qGreen(rgb); *data++ = (uchar)qBlue(rgb); } xpos += xoff; ypos += yoff; data[0] = flag; data[1] = (uchar)(xpos >> 16); data[2] = (uchar)(xpos >> 8); data[3] = (uchar)(xpos >> 0); data[4] = (uchar)(ypos >> 16); data[5] = (uchar)(ypos >> 8); data[6] = (uchar)(ypos >> 0); data += 7; if (alpha) { *data++ = (uchar)qAlpha(rgb); } else { *data++ = (uchar)qRed(rgb); *data++ = (uchar)qGreen(rgb); *data++ = (uchar)qBlue(rgb); }}QByteArray QPdf::generateLinearGradientShader(const QLinearGradient *gradient, const QPointF *page_rect, bool alpha){ // generate list of triangles with colors QPointF start = gradient->start(); QPointF stop = gradient->finalStop(); QGradientStops stops = gradient->stops(); QPointF offset = stop - start; QGradient::Spread spread = gradient->spread(); if (gradient->spread() == QGradient::ReflectSpread) { offset *= 2; for (int i = stops.size() - 2; i >= 0; --i) { QGradientStop stop = stops.at(i); stop.first = 2. - stop.first; stops.append(stop); } for (int i = 0 ; i < stops.size(); ++i) stops[i].first /= 2.; } QPointF orthogonal(offset.y(), -offset.x()); qreal length = offset.x()*offset.x() + offset.y()*offset.y(); // find the max and min values in offset and orth direction that are needed to cover // the whole page int off_min = INT_MAX; int off_max = INT_MIN; qreal ort_min = INT_MAX; qreal ort_max = INT_MIN; for (int i = 0; i < 4; ++i) { qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length; qreal ort = ((page_rect[i].x() - start.x()) * orthogonal.x() + (page_rect[i].y() - start.y()) * orthogonal.y())/length; off_min = qMin(off_min, qFloor(off)); off_max = qMax(off_max, qCeil(off)); ort_min = qMin(ort_min, ort); ort_max = qMax(ort_max, ort); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -