📄 qpdf.cpp
字号:
ort_min -= 1; ort_max += 1; start += off_min * offset + ort_min * orthogonal; orthogonal *= (ort_max - ort_min); int num = off_max - off_min; QPointF gradient_rect[4] = { start, start + orthogonal, start + num*offset, start + num*offset + orthogonal }; qreal xmin = gradient_rect[0].x(); qreal xmax = gradient_rect[0].x(); qreal ymin = gradient_rect[0].y(); qreal ymax = gradient_rect[0].y(); for (int i = 1; i < 4; ++i) { xmin = qMin(xmin, gradient_rect[i].x()); xmax = qMax(xmax, gradient_rect[i].x()); ymin = qMin(ymin, gradient_rect[i].y()); ymax = qMax(ymax, gradient_rect[i].y()); } xmin -= 1000; xmax += 1000; ymin -= 1000; ymax += 1000; start -= QPointF(xmin, ymin); qreal factor_x = qreal(1<<24)/(xmax - xmin); qreal factor_y = qreal(1<<24)/(ymax - ymin); int xoff = (int)(orthogonal.x()*factor_x); int yoff = (int)(orthogonal.y()*factor_y); QByteArray triangles; triangles.resize(spread == QGradient::PadSpread ? 20*(stops.size()+2) : 20*num*stops.size()); uchar *data = (uchar *) triangles.data(); if (spread == QGradient::PadSpread) { if (off_min > 0 || off_max < 1) { // linear gradient outside of page const QGradientStop ¤t_stop = off_min > 0 ? stops.at(stops.size()-1) : stops.at(0); uint rgb = current_stop.second.rgba(); int xpos = (int)(start.x()*factor_x); int ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 0, alpha); start += num*offset; xpos = (int)(start.x()*factor_x); ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 1, alpha); } else { int flag = 0; if (off_min < 0) { uint rgb = stops.at(0).second.rgba(); int xpos = (int)(start.x()*factor_x); int ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha); start -= off_min*offset; flag = 1; } for (int s = 0; s < stops.size(); ++s) { const QGradientStop ¤t_stop = stops.at(s); uint rgb = current_stop.second.rgba(); int xpos = (int)(start.x()*factor_x); int ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha); if (s < stops.size()-1) start += offset*(stops.at(s+1).first - stops.at(s).first); flag = 1; } if (off_max > 1) { start += (off_max - 1)*offset; uint rgb = stops.at(stops.size()-1).second.rgba(); int xpos = (int)(start.x()*factor_x); int ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha); } } } else { for (int i = 0; i < num; ++i) { uchar flag = 0; for (int s = 0; s < stops.size(); ++s) { uint rgb = stops.at(s).second.rgba(); int xpos = (int)(start.x()*factor_x); int ypos = (int)(start.y()*factor_y); writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha); if (s < stops.size()-1) start += offset*(stops.at(s+1).first - stops.at(s).first); flag = 1; } } } triangles.resize((char *)data - triangles.constData()); QByteArray shader; QPdf::ByteStream s(&shader); s << "<<\n" "/ShadingType 4\n" "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") << "/AntiAlias true\n" "/BitsPerCoordinate 24\n" "/BitsPerComponent 8\n" "/BitsPerFlag 8\n" "/Decode [" << xmin << xmax << ymin << ymax << (alpha ? "0 1]\n" : "0 1 0 1 0 1]\n") << "/AntiAlias true\n" "/Length " << triangles.length() << "\n" ">>\n" "stream\n" << triangles << "endstream\n" "endobj\n"; return shader;}#endifstatic void moveToHook(qfixed x, qfixed y, void *data){ QPdf::Stroker *t = (QPdf::Stroker *)data; if (!t->first) *t->stream << "h\n"; if (!t->cosmeticPen) t->matrix.map(x, y, &x, &y); *t->stream << x << y << "m\n"; t->first = false;}static void lineToHook(qfixed x, qfixed y, void *data){ QPdf::Stroker *t = (QPdf::Stroker *)data; if (!t->cosmeticPen) t->matrix.map(x, y, &x, &y); *t->stream << x << y << "l\n";}static void cubicToHook(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey, void *data){ QPdf::Stroker *t = (QPdf::Stroker *)data; if (!t->cosmeticPen) { t->matrix.map(c1x, c1y, &c1x, &c1y); t->matrix.map(c2x, c2y, &c2x, &c2y); t->matrix.map(ex, ey, &ex, &ey); } *t->stream << c1x << c1y << c2x << c2y << ex << ey << "c\n";}QPdf::Stroker::Stroker() : dashStroker(&basicStroker){ stroker = &basicStroker; basicStroker.setMoveToHook(moveToHook); basicStroker.setLineToHook(lineToHook); basicStroker.setCubicToHook(cubicToHook); cosmeticPen = true; basicStroker.setStrokeWidth(.1);}void QPdf::Stroker::setPen(const QPen &pen){ if (pen.style() == Qt::NoPen) { stroker = 0; return; } qreal w = pen.widthF(); bool zeroWidth = w < 0.0001; cosmeticPen = pen.isCosmetic(); if (zeroWidth) w = .1; basicStroker.setStrokeWidth(w); basicStroker.setCapStyle(pen.capStyle()); basicStroker.setJoinStyle(pen.joinStyle()); basicStroker.setMiterLimit(pen.miterLimit()); QVector<qreal> dashpattern = pen.dashPattern(); if (zeroWidth) { for (int i = 0; i < dashpattern.size(); ++i) dashpattern[i] *= 10.; } if (!dashpattern.isEmpty()) { dashStroker.setDashPattern(dashpattern); dashStroker.setDashOffset(pen.dashOffset()); stroker = &dashStroker; } else { stroker = &basicStroker; }}void QPdf::Stroker::strokePath(const QPainterPath &path){ if (!stroker) return; first = true; stroker->strokePath(path, this, cosmeticPen ? matrix : QTransform()); *stream << "h f\n";}QByteArray QPdf::ascii85Encode(const QByteArray &input){ int isize = input.size()/4*4; QByteArray output; output.resize(input.size()*5/4+7); char *out = output.data(); const uchar *in = (const uchar *)input.constData(); for (int i = 0; i < isize; i += 4) { uint val = (((uint)in[i])<<24) + (((uint)in[i+1])<<16) + (((uint)in[i+2])<<8) + (uint)in[i+3]; if (val == 0) { *out = 'z'; ++out; } else { char base[5]; base[4] = val % 85; val /= 85; base[3] = val % 85; val /= 85; base[2] = val % 85; val /= 85; base[1] = val % 85; val /= 85; base[0] = val % 85; *(out++) = base[0] + '!'; *(out++) = base[1] + '!'; *(out++) = base[2] + '!'; *(out++) = base[3] + '!'; *(out++) = base[4] + '!'; } } //write the last few bytes int remaining = input.size() - isize; if (remaining) { uint val = 0; for (int i = isize; i < input.size(); ++i) val = (val << 8) + in[i]; val <<= 8*(4-remaining); char base[5]; base[4] = val % 85; val /= 85; base[3] = val % 85; val /= 85; base[2] = val % 85; val /= 85; base[1] = val % 85; val /= 85; base[0] = val % 85; for (int i = 0; i < remaining+1; ++i) *(out++) = base[i] + '!'; } *(out++) = '~'; *(out++) = '>'; output.resize(out-output.data()); return output;}const char *QPdf::toHex(ushort u, char *buffer){ int i = 3; while (i >= 0) { ushort hex = (u & 0x000f); if (hex < 0x0a) buffer[i] = '0'+hex; else buffer[i] = 'A'+(hex-0x0a); u = u >> 4; i--; } buffer[4] = '\0'; return buffer;}const char *QPdf::toHex(uchar u, char *buffer){ int i = 1; while (i >= 0) { ushort hex = (u & 0x000f); if (hex < 0x0a) buffer[i] = '0'+hex; else buffer[i] = 'A'+(hex-0x0a); u = u >> 4; i--; } buffer[2] = '\0'; return buffer;}#define Q_MM(n) int((n * 720 + 127) / 254)#define Q_IN(n) int(n * 72)static const QPdf::PaperSize paperSizes[QPrinter::NPageSize] ={ { Q_MM(210), Q_MM(297) }, // A4 { Q_MM(176), Q_MM(250) }, // B5 { Q_IN(8.5), Q_IN(11) }, // Letter { Q_IN(8.5), Q_IN(14) }, // Legal { Q_IN(7.5), Q_IN(10) }, // Executive { Q_MM(841), Q_MM(1189) }, // A0 { Q_MM(594), Q_MM(841) }, // A1 { Q_MM(420), Q_MM(594) }, // A2 { Q_MM(297), Q_MM(420) }, // A3 { Q_MM(148), Q_MM(210) }, // A5 { Q_MM(105), Q_MM(148) }, // A6 { Q_MM(74), Q_MM(105)}, // A7 { Q_MM(52), Q_MM(74) }, // A8 { Q_MM(37), Q_MM(52) }, // A9 { Q_MM(1000), Q_MM(1414) }, // B0 { Q_MM(707), Q_MM(1000) }, // B1 { Q_MM(31), Q_MM(44) }, // B10 { Q_MM(500), Q_MM(707) }, // B2 { Q_MM(353), Q_MM(500) }, // B3 { Q_MM(250), Q_MM(353) }, // B4 { Q_MM(125), Q_MM(176) }, // B6 { Q_MM(88), Q_MM(125) }, // B7 { Q_MM(62), Q_MM(88) }, // B8 { Q_MM(44), Q_MM(62) }, // B9 { Q_MM(162), Q_MM(229) }, // C5E { Q_IN(4.125), Q_IN(9.5) }, // Comm10E { Q_MM(110), Q_MM(220) }, // DLE { Q_IN(8.5), Q_IN(13) }, // Folio { Q_IN(17), Q_IN(11) }, // Ledger { Q_IN(11), Q_IN(17) } // Tabloid};static const char * const psToStr[QPrinter::NPageSize+1] ={ "A4", "B5", "Letter", "Legal", "Executive", "A0", "A1", "A2", "A3", "A5", "A6", "A7", "A8", "A9", "B0", "B1", "B10", "B2", "B3", "B4", "B6", "B7", "B8", "B9", "C5E", "Comm10E", "DLE", "Folio", "Ledger", "Tabloid", 0};QPdf::PaperSize QPdf::paperSize(QPrinter::PageSize pageSize){ return paperSizes[pageSize];}const char *QPdf::paperSizeToString(QPrinter::PageSize pageSize){ return psToStr[pageSize];}QByteArray QPdf::stripSpecialCharacters(const QByteArray &string){ QByteArray s = string; s.replace(" ", ""); s.replace("(", ""); s.replace(")", ""); s.replace("<", ""); s.replace(">", ""); s.replace("[", ""); s.replace("]", ""); s.replace("{", ""); s.replace("}", ""); s.replace("/", ""); s.replace("%", ""); return s;}// -------------------------- base engine, shared code between PS and PDF -----------------------QPdfBaseEngine::QPdfBaseEngine(QPdfBaseEnginePrivate &dd, PaintEngineFeatures f) : QPaintEngine(dd, f){ Q_D(QPdfBaseEngine);#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY) if (QCUPSSupport::isAvailable()) { QCUPSSupport cups; const cups_dest_t* printers = cups.availablePrinters(); int prnCount = cups.availablePrintersCount(); for (int i = 0; i < prnCount; ++i) { if (printers[i].is_default) { d->printerName = QString::fromLocal8Bit(printers[i].name); break; } } } else#endif { d->printerName = QString::fromLocal8Bit(qgetenv("PRINTER")); if (d->printerName.isEmpty()) d->printerName = QString::fromLocal8Bit(qgetenv("LPDEST")); if (d->printerName.isEmpty()) d->printerName = QString::fromLocal8Bit(qgetenv("NPRINTER")); if (d->printerName.isEmpty()) d->printerName = QString::fromLocal8Bit(qgetenv("NGPRINTER")); }}void QPdfBaseEngine::drawPoints (const QPointF *points, int pointCount){ Q_D(QPdfBaseEngine); if (!points || !d->hasPen) return; QPainterPath p; for (int i=0; i!=pointCount;++i) { p.moveTo(points[i]); p.lineTo(points[i] + QPointF(0, 0.001)); } drawPath(p);}void QPdfBaseEngine::drawLines (const QLineF *lines, int lineCount){ if (!lines) return; QPainterPath p; for (int i=0; i!=lineCount;++i) { p.moveTo(lines[i].p1()); p.lineTo(lines[i].p2()); } drawPath(p);}void QPdfBaseEngine::drawRects (const QRectF *rects, int rectCount){ if (!rects) return; Q_D(QPdfBaseEngine); if (d->clipEnabled && d->allClipped) return; if (!d->hasPen && !d->hasBrush) return; QBrush penBrush = d->pen.brush(); if (d->simplePen || !d->hasPen) { // draw strokes natively in this case for better output if(!d->simplePen && !d->stroker.matrix.isIdentity()) *d->currentPage << "q\n" << QPdf::generateMatrix(d->stroker.matrix); for (int i = 0; i < rectCount; ++i) *d->currentPage << rects[i].x() << rects[i].y() << rects[i].width() << rects[i].height() << "re\n"; *d->currentPage << (d->hasPen ? (d->hasBrush ? "B\n" : "S\n") : "f\n"); if(!d->simplePen && !d->stroker.matrix.isIdentity()) *d->currentPage << "Q\n"; } else { QPainterPath p; for (int i=0; i!=rectCount; ++i) p.addRect(rects[i]); drawPath(p); }}void QPdfBaseEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode){ if (!points || !pointCount) return; Q_D(QPdfBaseEngine);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -