📄 qprintengine_ps.cpp
字号:
written += size; } state = Undef; start = i; if (i == input.size()) break; } last = data[i]; ++i; }; out.append((char)(uchar)128); return out;}enum format { Raw, Runlength, DCT};static const char *const filters[3] = { " ", "/RunLengthDecode filter ", "/DCTDecode filter "};static QByteArray compress(const QImage &img, bool gray, int *format){ // we can't use premultiplied here QImage image = img; if (image.format() == QImage::Format_ARGB32_Premultiplied) image = image.convertToFormat(QImage::Format_ARGB32); QByteArray pixelData; int depth = image.depth(); if (depth != 1 && !gray && QImageWriter::supportedImageFormats().contains("jpeg")) { QBuffer buffer(&pixelData); QImageWriter writer(&buffer, "jpeg"); writer.setQuality(94); writer.write(img); *format = DCT; } else { int width = image.width(); int height = image.height(); int size = width*height; if (depth == 1) size = (width+7)/8*height; else if (!gray) size = size*3; pixelData.resize(size); uchar *pixel = (uchar *)pixelData.data(); int i = 0; if (depth == 1) { QImage::Format format = image.format(); memset(pixel, 0xff, size); for(int y=0; y < height; y++) { const uchar * s = image.scanLine(y); for(int x=0; x < width; x++) { // need to copy bit for bit... bool b = (format == QImage::Format_MonoLSB) ? (*(s + (x >> 3)) >> (x & 7)) & 1 : (*(s + (x >> 3)) << (x & 7)) & 0x80 ; if (b) pixel[i >> 3] ^= (0x80 >> (i & 7)); i++; } // we need to align to 8 bit here i = (i+7) & 0xffffff8; } } else if (depth == 8) { for(int y=0; y < height; y++) { const uchar * s = image.scanLine(y); for(int x=0; x < width; x++) { QRgb rgb = image.color(s[x]); if (gray) { pixel[i] = (unsigned char) qGray(rgb); i++; } else { pixel[i] = (unsigned char) qRed(rgb); pixel[i+1] = (unsigned char) qGreen(rgb); pixel[i+2] = (unsigned char) qBlue(rgb); i += 3; } } } } else { for(int y=0; y < height; y++) { QRgb * s = (QRgb*)(image.scanLine(y)); for(int x=0; x < width; x++) { QRgb rgb = (*s++); if (gray) { pixel[i] = (unsigned char) qGray(rgb); i++; } else { pixel[i] = (unsigned char) qRed(rgb); pixel[i+1] = (unsigned char) qGreen(rgb); pixel[i+2] = (unsigned char) qBlue(rgb); i += 3; } } } } *format = Raw; if (depth == 1) { pixelData = runlengthEncode(pixelData); *format = Runlength; } } QByteArray outarr = QPdf::ascii85Encode(pixelData); return outarr;}void QPSPrintEnginePrivate::drawImage(qreal x, qreal y, qreal w, qreal h, const QImage &img, const QImage &mask){ if (!w || !h || img.isNull()) return; int width = img.width(); int height = img.height(); qreal scaleX = width/w; qreal scaleY = height/h; bool gray = (colorMode == QPrinter::GrayScale) || img.allGray(); int splitSize = 21830 * (gray ? 3 : 1); if (width * height > splitSize) { // 65535/3, tolerance for broken printers int images, subheight; images = (width * height + splitSize - 1) / splitSize; subheight = (height + images-1) / images; while (subheight * width > splitSize) { images++; subheight = (height + images-1) / images; } int suby = 0; while(suby < height) { drawImage(x, y + suby/scaleY, w, qMin(subheight, height-suby)/scaleY, img.copy(0, suby, width, qMin(subheight, height-suby)), mask.isNull() ? mask : mask.copy(0, suby, width, qMin(subheight, height-suby))); suby += subheight; } } else { QByteArray out; int size = 0; const char *bits; if (!mask.isNull()) { int format; out = ::compress(mask, true, &format); size = (width+7)/8*height; *currentPage << "/mask currentfile/ASCII85Decode filter" << filters[format] << size << " string readstring\n"; ps_r7(*currentPage, out, out.size()); *currentPage << " pop def\n"; } if (img.depth() == 1) { size = (width+7)/8*height; bits = "1 "; } else if (gray) { size = width*height; bits = "8 "; } else { size = width*height*3; bits = "24 "; } int format; out = ::compress(img, gray, &format); *currentPage << "/sl currentfile/ASCII85Decode filter" << filters[format] << size << " string readstring\n"; ps_r7(*currentPage, out, out.size()); *currentPage << " pop def\n"; *currentPage << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl " << bits << (!mask.isNull() ? "mask " : "false ") << x << ' ' << y << " di\n"; }}void QPSPrintEnginePrivate::emitHeader(bool finished){ QPSPrintEngine *q = static_cast<QPSPrintEngine *>(q_ptr); QPrinter *printer = static_cast<QPrinter*>(pdev); if (creator.isEmpty()) creator = QLatin1String("Qt " QT_VERSION_STR); outDevice = new QFile(); static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly); QByteArray header; QPdf::ByteStream s(&header); s << "%!PS-Adobe-1.0"; qreal scale = 72. / ((qreal) q->metric(QPaintDevice::PdmDpiY)); QRect pageRect = this->pageRect(); QRect paperRect = this->paperRect(); uint mtop = pageRect.top() - paperRect.top(); uint mleft = pageRect.left() - paperRect.left(); uint mbottom = paperRect.bottom() - pageRect.bottom(); uint mright = paperRect.right() - pageRect.right(); int width = pageRect.width(); int height = pageRect.height(); if (finished && pageCount == 1 && copies == 1 && ((fullPage && qt_gen_epsf) || (outputFileName.endsWith(".eps"))) ) { if (!boundingBox.isValid()) boundingBox.setRect(0, 0, width, height); if (orientation == QPrinter::Landscape) { if (!fullPage) boundingBox.translate(-mleft, -mtop); s << " EPSF-3.0\n%%BoundingBox: " << (int)(printer->height() - boundingBox.bottom())*scale // llx << (int)(printer->width() - boundingBox.right())*scale - 1 // lly << (int)(printer->height() - boundingBox.top())*scale + 1 // urx << (int)(printer->width() - boundingBox.left())*scale; // ury } else { if (!fullPage) boundingBox.translate(mleft, -mtop); s << " EPSF-3.0\n%%BoundingBox: " << (int)(boundingBox.left())*scale << (int)(printer->height() - boundingBox.bottom())*scale - 1 << (int)(boundingBox.right())*scale + 1 << (int)(printer->height() - boundingBox.top())*scale; } } else { int w = width + (fullPage ? 0 : mleft + mright); int h = height + (fullPage ? 0 : mtop + mbottom); w = (int)(w*scale); h = (int)(h*scale); // set a bounding box according to the DSC if (orientation == QPrinter::Landscape) s << "\n%%BoundingBox: 0 0 " << h << w; else s << "\n%%BoundingBox: 0 0 " << w << h; } s << "\n" << wrapDSC("%%Creator: " + creator.toUtf8()); if (!title.isEmpty()) s << wrapDSC("%%Title: " + title.toUtf8());#ifndef QT_NO_DATESTRING s << "%%CreationDate: " << QDateTime::currentDateTime().toString().toUtf8();#endif s << "\n%%Orientation: "; if (orientation == QPrinter::Landscape) s << "Landscape"; else s << "Portrait"; s << "\n%%Pages: (atend)" "\n%%DocumentFonts: (atend)" "\n%%EndComments\n" "%%BeginProlog\n" "% Prolog copyright 1994-2003 Trolltech. You may copy this prolog in any way\n" "% that is directly related to this document. For other use of this prolog,\n" "% see your licensing agreement for Qt.\n" << ps_header << "\n"; s << "/pageinit {\n"; if (!fullPage) { if (orientation == QPrinter::Portrait) s << mleft*scale << mbottom*scale << "translate\n"; else s << mtop*scale << mleft*scale << "translate\n"; } if (orientation == QPrinter::Portrait) { s << "% " << printer->widthMM() << "*" << printer->heightMM() << "mm (portrait)\n0 " << height*scale << "translate " << scale << "-" << scale << "scale } def\n"; } else { s << "% " << printer->heightMM() << "*" << printer->widthMM() << " mm (landscape)\n 90 rotate " << scale << "-" << scale << "scale } def\n"; } s << "%%EndProlog\n"; s << "%%BeginSetup\n"; if (copies > 1) { s << "/#copies " << copies << " def\n"; s << "/NumCopies " << copies << " SPD\n"; s << "/Collate " << (collate ? "true" : "false") << " SPD\n"; } s << "%%EndSetup\n"; outDevice->write(header);}void QPSPrintEnginePrivate::emitPages(){ // ############# fix fonts for huge documents for (QHash<QFontEngine::FaceId, QFontSubset *>::Iterator it = fonts.begin(); it != fonts.end(); ++it) outDevice->write((*it)->toType1()); outDevice->write(buffer); buffer = QByteArray(); qDeleteAll(fonts); fonts.clear();}#ifdef Q_WS_QWSconst int max_in_memory_size = 50000000;#elseconst int max_in_memory_size = 2000000;#endifvoid QPSPrintEnginePrivate::flushPage(bool last){ if (!last && currentPage->content().isEmpty()) return; QPdf::ByteStream s(&buffer); s << "%%Page: " << pageCount << pageCount << "\n" << "QI\n" << currentPage->content() << "\nQP\n"; if (last) { // ############## || buffer.size() > max_in_memory_size) {// qDebug("emiting header at page %d", pageCount); if (!outDevice) emitHeader(last); emitPages(); } pageCount++;}// ================ PSPrinter class ========================QPSPrintEngine::QPSPrintEngine(QPrinter::PrinterMode m) : QPdfBaseEngine(*(new QPSPrintEnginePrivate(m)), PrimitiveTransform | PatternTransform | PixmapTransform | PainterPaths | PatternBrush ){}static void ignoreSigPipe(bool b){ static struct sigaction *users_sigpipe_handler = 0; if (b) { if (users_sigpipe_handler != 0) return; // already ignoring sigpipe users_sigpipe_handler = new struct sigaction; struct sigaction tmp_sigpipe_handler; tmp_sigpipe_handler.sa_handler = SIG_IGN; sigemptyset(&tmp_sigpipe_handler.sa_mask); tmp_sigpipe_handler.sa_flags = 0; if (sigaction(SIGPIPE, &tmp_sigpipe_handler, users_sigpipe_handler) == -1) { delete users_sigpipe_handler; users_sigpipe_handler = 0; } } else { if (users_sigpipe_handler == 0) return; // not ignoring sigpipe if (sigaction(SIGPIPE, users_sigpipe_handler, 0) == -1) qWarning("QPSPrintEngine: could not restore SIGPIPE handler"); delete users_sigpipe_handler; users_sigpipe_handler = 0; }}QPSPrintEngine::~QPSPrintEngine(){ Q_D(QPSPrintEngine); if (d->fd >= 0) ::close(d->fd);}static void closeAllOpenFds(){ // hack time... getting the maximum number of open // files, if possible. if not we assume it's the // larger of 256 and the fd we got int i;#if defined(_SC_OPEN_MAX) i = (int)sysconf(_SC_OPEN_MAX);#elif defined(_POSIX_OPEN_MAX) i = (int)_POSIX_OPEN_MAX;#elif defined(OPEN_MAX) i = (int)OPEN_MAX;#else i = 256;#endif while(--i > 0) ::close(i);}bool QPSPrintEngine::begin(QPaintDevice *pdev){ Q_D(QPSPrintEngine); if (d->fd >= 0) return true; d->pdev = pdev; if (!d->outputFileName.isEmpty()) { d->fd = QT_OPEN(d->outputFileName.toLocal8Bit().constData(), O_CREAT | O_NOCTTY | O_TRUNC | O_WRONLY,#if defined(Q_OS_WIN) _S_IREAD | _S_IWRITE#else 0666#endif ); } else { QString pr; if (!d->printerName.isEmpty()) pr = d->printerName; int fds[2]; if (pipe(fds) != 0) { qWarning("QPSPrinter: could not open pipe to print"); return false; } d->pid = fork(); if (d->pid == 0) { // child process // if possible, exit quickly, so the actual lp/lpr // becomes a child of init, and ::waitpid() is // guaranteed not to wait. if (fork() > 0) { closeAllOpenFds(); // try to replace this process with "true" - this prevents // global destructors from being called (that could possibly // do wrong things to the parent process) (void)execlp("true", "true", (char *)0); (void)execl("/bin/true", "true", (char *)0); (void)execl("/usr/bin/true", "true", (char *)0); ::exit(0); } dup2(fds[0], 0); closeAllOpenFds(); if (!d->printProgram.isEmpty()) { if (!d->selectionOption.isEmpty()) pr.prepend(d->selectionOption); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -