Qt 4.8
qpdf.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qplatformdefs.h"
42 #include <qdebug.h>
43 #include "qpdf_p.h"
44 #include <qfile.h>
45 #include <qtemporaryfile.h>
46 #include <private/qmath_p.h>
47 #include "private/qcups_p.h"
48 #include "qprinterinfo.h"
49 #include <qnumeric.h>
50 #include "private/qfont_p.h"
51 
52 #ifdef Q_OS_UNIX
53 #include "private/qcore_unix_p.h" // overrides QT_OPEN
54 #endif
55 
57 
58 #ifndef QT_NO_PRINTER
59 
61 
62 /* also adds a space at the end of the number */
63 const char *qt_real_to_string(qreal val, char *buf) {
64  const char *ret = buf;
65 
66  if (qIsNaN(val)) {
67  *(buf++) = '0';
68  *(buf++) = ' ';
69  *buf = 0;
70  return ret;
71  }
72 
73  if (val < 0) {
74  *(buf++) = '-';
75  val = -val;
76  }
77  unsigned int ival = (unsigned int) val;
78  qreal frac = val - (qreal)ival;
79 
80  int ifrac = (int)(frac * 1000000000);
81  if (ifrac == 1000000000) {
82  ++ival;
83  ifrac = 0;
84  }
85  char output[256];
86  int i = 0;
87  while (ival) {
88  output[i] = '0' + (ival % 10);
89  ++i;
90  ival /= 10;
91  }
92  int fact = 100000000;
93  if (i == 0) {
94  *(buf++) = '0';
95  } else {
96  while (i) {
97  *(buf++) = output[--i];
98  fact /= 10;
99  ifrac /= 10;
100  }
101  }
102 
103  if (ifrac) {
104  *(buf++) = '.';
105  while (fact) {
106  *(buf++) = '0' + ((ifrac/fact) % 10);
107  fact /= 10;
108  }
109  }
110  *(buf++) = ' ';
111  *buf = 0;
112  return ret;
113 }
114 
115 const char *qt_int_to_string(int val, char *buf) {
116  const char *ret = buf;
117  if (val < 0) {
118  *(buf++) = '-';
119  val = -val;
120  }
121  char output[256];
122  int i = 0;
123  while (val) {
124  output[i] = '0' + (val % 10);
125  ++i;
126  val /= 10;
127  }
128  if (i == 0) {
129  *(buf++) = '0';
130  } else {
131  while (i)
132  *(buf++) = output[--i];
133  }
134  *(buf++) = ' ';
135  *buf = 0;
136  return ret;
137 }
138 
139 
140 namespace QPdf {
141  ByteStream::ByteStream(QByteArray *byteArray, bool fileBacking)
142  : dev(new QBuffer(byteArray)),
143  fileBackingEnabled(fileBacking),
144  fileBackingActive(false),
145  handleDirty(false)
146  {
148  }
149 
150  ByteStream::ByteStream(bool fileBacking)
151  : dev(new QBuffer(&ba)),
152  fileBackingEnabled(fileBacking),
153  fileBackingActive(false),
154  handleDirty(false)
155  {
157  }
158 
160  {
161  delete dev;
162  }
163 
165  {
166  if (handleDirty) prepareBuffer();
167  dev->write(&chr, 1);
168  return *this;
169  }
170 
172  {
173  if (handleDirty) prepareBuffer();
174  dev->write(str, strlen(str));
175  return *this;
176  }
177 
179  {
180  if (handleDirty) prepareBuffer();
181  dev->write(str);
182  return *this;
183  }
184 
186  {
187  Q_ASSERT(!src.dev->isSequential());
188  if (handleDirty) prepareBuffer();
189  // We do play nice here, even though it looks ugly.
190  // We save the position and restore it afterwards.
191  ByteStream &s = const_cast<ByteStream&>(src);
192  qint64 pos = s.dev->pos();
193  s.dev->reset();
194  while (!s.dev->atEnd()) {
195  QByteArray buf = s.dev->read(chunkSize());
196  dev->write(buf);
197  }
198  s.dev->seek(pos);
199  return *this;
200  }
201 
203  char buf[256];
204  qt_real_to_string(val, buf);
205  *this << buf;
206  return *this;
207  }
208 
210  char buf[256];
211  qt_int_to_string(val, buf);
212  *this << buf;
213  return *this;
214  }
215 
217  char buf[256];
218  qt_real_to_string(p.x(), buf);
219  *this << buf;
220  qt_real_to_string(p.y(), buf);
221  *this << buf;
222  return *this;
223  }
224 
226  {
227  dev->reset();
228  handleDirty = true;
229  return dev;
230  }
231 
233  {
235  }
236 
238  {
239  delete dev;
240  dev = new QBuffer(ba);
242  }
243 
245  {
247  qint64 size = dev->size();
249  && size > maxMemorySize()) {
250  // Switch to file backing.
251  QTemporaryFile *newFile = new QTemporaryFile;
252  newFile->open();
253  dev->reset();
254  while (!dev->atEnd()) {
255  QByteArray buf = dev->read(chunkSize());
256  newFile->write(buf);
257  }
258  delete dev;
259  dev = newFile;
260  ba.clear();
261  fileBackingActive = true;
262  }
263  if (dev->pos() != size) {
264  dev->seek(size);
265  handleDirty = false;
266  }
267  }
268 }
269 
270 #define QT_PATH_ELEMENT(elm)
271 
273 {
274  QByteArray result;
275  if (!path.elementCount())
276  return result;
277 
278  ByteStream s(&result);
279 
280  int start = -1;
281  for (int i = 0; i < path.elementCount(); ++i) {
282  const QPainterPath::Element &elm = path.elementAt(i);
283  switch (elm.type) {
285  if (start >= 0
286  && path.elementAt(start).x == path.elementAt(i-1).x
287  && path.elementAt(start).y == path.elementAt(i-1).y)
288  s << "h\n";
289  s << matrix.map(QPointF(elm.x, elm.y)) << "m\n";
290  start = i;
291  break;
293  s << matrix.map(QPointF(elm.x, elm.y)) << "l\n";
294  break;
298  s << matrix.map(QPointF(elm.x, elm.y))
299  << matrix.map(QPointF(path.elementAt(i+1).x, path.elementAt(i+1).y))
300  << matrix.map(QPointF(path.elementAt(i+2).x, path.elementAt(i+2).y))
301  << "c\n";
302  i += 2;
303  break;
304  default:
305  qFatal("QPdf::generatePath(), unhandled type: %d", elm.type);
306  }
307  }
308  if (start >= 0
309  && path.elementAt(start).x == path.elementAt(path.elementCount()-1).x
310  && path.elementAt(start).y == path.elementAt(path.elementCount()-1).y)
311  s << "h\n";
312 
313  Qt::FillRule fillRule = path.fillRule();
314 
315  const char *op = "";
316  switch (flags) {
317  case ClipPath:
318  op = (fillRule == Qt::WindingFill) ? "W n\n" : "W* n\n";
319  break;
320  case FillPath:
321  op = (fillRule == Qt::WindingFill) ? "f\n" : "f*\n";
322  break;
323  case StrokePath:
324  op = "S\n";
325  break;
326  case FillAndStrokePath:
327  op = (fillRule == Qt::WindingFill) ? "B\n" : "B*\n";
328  break;
329  }
330  s << op;
331  return result;
332 }
333 
335 {
336  QByteArray result;
337  ByteStream s(&result);
338  s << matrix.m11()
339  << matrix.m12()
340  << matrix.m21()
341  << matrix.m22()
342  << matrix.dx()
343  << matrix.dy()
344  << "cm\n";
345  return result;
346 }
347 
349 {
350  QByteArray result;
351  ByteStream s(&result);
352  s << '[';
353 
354  QVector<qreal> dasharray = pen.dashPattern();
355  qreal w = pen.widthF();
356  if (w < 0.001)
357  w = 1;
358  for (int i = 0; i < dasharray.size(); ++i) {
359  qreal dw = dasharray.at(i)*w;
360  if (dw < 0.0001) dw = 0.0001;
361  s << dw;
362  }
363  s << ']';
364  //qDebug() << "dasharray: pen has" << dasharray;
365  //qDebug() << " => " << result;
366  return result;
367 }
368 
369 
370 
371 static const char* pattern_for_brush[] = {
372  0, // NoBrush
373  0, // SolidPattern
374  "0 J\n"
375  "6 w\n"
376  "[] 0 d\n"
377  "4 0 m\n"
378  "4 8 l\n"
379  "0 4 m\n"
380  "8 4 l\n"
381  "S\n", // Dense1Pattern
382 
383  "0 J\n"
384  "2 w\n"
385  "[6 2] 1 d\n"
386  "0 0 m\n"
387  "0 8 l\n"
388  "8 0 m\n"
389  "8 8 l\n"
390  "S\n"
391  "[] 0 d\n"
392  "2 0 m\n"
393  "2 8 l\n"
394  "6 0 m\n"
395  "6 8 l\n"
396  "S\n"
397  "[6 2] -3 d\n"
398  "4 0 m\n"
399  "4 8 l\n"
400  "S\n", // Dense2Pattern
401 
402  "0 J\n"
403  "2 w\n"
404  "[6 2] 1 d\n"
405  "0 0 m\n"
406  "0 8 l\n"
407  "8 0 m\n"
408  "8 8 l\n"
409  "S\n"
410  "[2 2] -1 d\n"
411  "2 0 m\n"
412  "2 8 l\n"
413  "6 0 m\n"
414  "6 8 l\n"
415  "S\n"
416  "[6 2] -3 d\n"
417  "4 0 m\n"
418  "4 8 l\n"
419  "S\n", // Dense3Pattern
420 
421  "0 J\n"
422  "2 w\n"
423  "[2 2] 1 d\n"
424  "0 0 m\n"
425  "0 8 l\n"
426  "8 0 m\n"
427  "8 8 l\n"
428  "S\n"
429  "[2 2] -1 d\n"
430  "2 0 m\n"
431  "2 8 l\n"
432  "6 0 m\n"
433  "6 8 l\n"
434  "S\n"
435  "[2 2] 1 d\n"
436  "4 0 m\n"
437  "4 8 l\n"
438  "S\n", // Dense4Pattern
439 
440  "0 J\n"
441  "2 w\n"
442  "[2 6] -1 d\n"
443  "0 0 m\n"
444  "0 8 l\n"
445  "8 0 m\n"
446  "8 8 l\n"
447  "S\n"
448  "[2 2] 1 d\n"
449  "2 0 m\n"
450  "2 8 l\n"
451  "6 0 m\n"
452  "6 8 l\n"
453  "S\n"
454  "[2 6] 3 d\n"
455  "4 0 m\n"
456  "4 8 l\n"
457  "S\n", // Dense5Pattern
458 
459  "0 J\n"
460  "2 w\n"
461  "[2 6] -1 d\n"
462  "0 0 m\n"
463  "0 8 l\n"
464  "8 0 m\n"
465  "8 8 l\n"
466  "S\n"
467  "[2 6] 3 d\n"
468  "4 0 m\n"
469  "4 8 l\n"
470  "S\n", // Dense6Pattern
471 
472  "0 J\n"
473  "2 w\n"
474  "[2 6] -1 d\n"
475  "0 0 m\n"
476  "0 8 l\n"
477  "8 0 m\n"
478  "8 8 l\n"
479  "S\n", // Dense7Pattern
480 
481  "1 w\n"
482  "0 4 m\n"
483  "8 4 l\n"
484  "S\n", // HorPattern
485 
486  "1 w\n"
487  "4 0 m\n"
488  "4 8 l\n"
489  "S\n", // VerPattern
490 
491  "1 w\n"
492  "4 0 m\n"
493  "4 8 l\n"
494  "0 4 m\n"
495  "8 4 l\n"
496  "S\n", // CrossPattern
497 
498  "1 w\n"
499  "-1 5 m\n"
500  "5 -1 l\n"
501  "3 9 m\n"
502  "9 3 l\n"
503  "S\n", // BDiagPattern
504 
505  "1 w\n"
506  "-1 3 m\n"
507  "5 9 l\n"
508  "3 -1 m\n"
509  "9 5 l\n"
510  "S\n", // FDiagPattern
511 
512  "1 w\n"
513  "-1 3 m\n"
514  "5 9 l\n"
515  "3 -1 m\n"
516  "9 5 l\n"
517  "-1 5 m\n"
518  "5 -1 l\n"
519  "3 9 m\n"
520  "9 3 l\n"
521  "S\n", // DiagCrossPattern
522 };
523 
525 {
526  int style = b.style();
527  if (style > Qt::DiagCrossPattern)
528  return QByteArray();
529  return pattern_for_brush[style];
530 }
531 
532 #ifdef USE_NATIVE_GRADIENTS
533 static void writeTriangleLine(uchar *&data, int xpos, int ypos, int xoff, int yoff, uint rgb, uchar flag, bool alpha)
534 {
535  data[0] = flag;
536  data[1] = (uchar)(xpos >> 16);
537  data[2] = (uchar)(xpos >> 8);
538  data[3] = (uchar)(xpos >> 0);
539  data[4] = (uchar)(ypos >> 16);
540  data[5] = (uchar)(ypos >> 8);
541  data[6] = (uchar)(ypos >> 0);
542  data += 7;
543  if (alpha) {
544  *data++ = (uchar)qAlpha(rgb);
545  } else {
546  *data++ = (uchar)qRed(rgb);
547  *data++ = (uchar)qGreen(rgb);
548  *data++ = (uchar)qBlue(rgb);
549  }
550  xpos += xoff;
551  ypos += yoff;
552  data[0] = flag;
553  data[1] = (uchar)(xpos >> 16);
554  data[2] = (uchar)(xpos >> 8);
555  data[3] = (uchar)(xpos >> 0);
556  data[4] = (uchar)(ypos >> 16);
557  data[5] = (uchar)(ypos >> 8);
558  data[6] = (uchar)(ypos >> 0);
559  data += 7;
560  if (alpha) {
561  *data++ = (uchar)qAlpha(rgb);
562  } else {
563  *data++ = (uchar)qRed(rgb);
564  *data++ = (uchar)qGreen(rgb);
565  *data++ = (uchar)qBlue(rgb);
566  }
567 }
568 
569 
570 QByteArray QPdf::generateLinearGradientShader(const QLinearGradient *gradient, const QPointF *page_rect, bool alpha)
571 {
572  // generate list of triangles with colors
573  QPointF start = gradient->start();
574  QPointF stop = gradient->finalStop();
575  QGradientStops stops = gradient->stops();
576  QPointF offset = stop - start;
577  QGradient::Spread spread = gradient->spread();
578 
579  if (gradient->spread() == QGradient::ReflectSpread) {
580  offset *= 2;
581  for (int i = stops.size() - 2; i >= 0; --i) {
582  QGradientStop stop = stops.at(i);
583  stop.first = 2. - stop.first;
584  stops.append(stop);
585  }
586  for (int i = 0 ; i < stops.size(); ++i)
587  stops[i].first /= 2.;
588  }
589 
590  QPointF orthogonal(offset.y(), -offset.x());
591  qreal length = offset.x()*offset.x() + offset.y()*offset.y();
592 
593  // find the max and min values in offset and orth direction that are needed to cover
594  // the whole page
595  int off_min = INT_MAX;
596  int off_max = INT_MIN;
597  qreal ort_min = INT_MAX;
598  qreal ort_max = INT_MIN;
599  for (int i = 0; i < 4; ++i) {
600  qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length;
601  qreal ort = ((page_rect[i].x() - start.x()) * orthogonal.x() + (page_rect[i].y() - start.y()) * orthogonal.y())/length;
602  off_min = qMin(off_min, qFloor(off));
603  off_max = qMax(off_max, qCeil(off));
604  ort_min = qMin(ort_min, ort);
605  ort_max = qMax(ort_max, ort);
606  }
607  ort_min -= 1;
608  ort_max += 1;
609 
610  start += off_min * offset + ort_min * orthogonal;
611  orthogonal *= (ort_max - ort_min);
612  int num = off_max - off_min;
613 
614  QPointF gradient_rect[4] = { start,
615  start + orthogonal,
616  start + num*offset,
617  start + num*offset + orthogonal };
618  qreal xmin = gradient_rect[0].x();
619  qreal xmax = gradient_rect[0].x();
620  qreal ymin = gradient_rect[0].y();
621  qreal ymax = gradient_rect[0].y();
622  for (int i = 1; i < 4; ++i) {
623  xmin = qMin(xmin, gradient_rect[i].x());
624  xmax = qMax(xmax, gradient_rect[i].x());
625  ymin = qMin(ymin, gradient_rect[i].y());
626  ymax = qMax(ymax, gradient_rect[i].y());
627  }
628  xmin -= 1000;
629  xmax += 1000;
630  ymin -= 1000;
631  ymax += 1000;
632  start -= QPointF(xmin, ymin);
633  qreal factor_x = qreal(1<<24)/(xmax - xmin);
634  qreal factor_y = qreal(1<<24)/(ymax - ymin);
635  int xoff = (int)(orthogonal.x()*factor_x);
636  int yoff = (int)(orthogonal.y()*factor_y);
637 
638  QByteArray triangles;
639  triangles.resize(spread == QGradient::PadSpread ? 20*(stops.size()+2) : 20*num*stops.size());
640  uchar *data = (uchar *) triangles.data();
641  if (spread == QGradient::PadSpread) {
642  if (off_min > 0 || off_max < 1) {
643  // linear gradient outside of page
644  const QGradientStop &current_stop = off_min > 0 ? stops.at(stops.size()-1) : stops.at(0);
645  uint rgb = current_stop.second.rgba();
646  int xpos = (int)(start.x()*factor_x);
647  int ypos = (int)(start.y()*factor_y);
648  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 0, alpha);
649  start += num*offset;
650  xpos = (int)(start.x()*factor_x);
651  ypos = (int)(start.y()*factor_y);
652  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 1, alpha);
653  } else {
654  int flag = 0;
655  if (off_min < 0) {
656  uint rgb = stops.at(0).second.rgba();
657  int xpos = (int)(start.x()*factor_x);
658  int ypos = (int)(start.y()*factor_y);
659  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
660  start -= off_min*offset;
661  flag = 1;
662  }
663  for (int s = 0; s < stops.size(); ++s) {
664  const QGradientStop &current_stop = stops.at(s);
665  uint rgb = current_stop.second.rgba();
666  int xpos = (int)(start.x()*factor_x);
667  int ypos = (int)(start.y()*factor_y);
668  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
669  if (s < stops.size()-1)
670  start += offset*(stops.at(s+1).first - stops.at(s).first);
671  flag = 1;
672  }
673  if (off_max > 1) {
674  start += (off_max - 1)*offset;
675  uint rgb = stops.at(stops.size()-1).second.rgba();
676  int xpos = (int)(start.x()*factor_x);
677  int ypos = (int)(start.y()*factor_y);
678  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
679  }
680  }
681  } else {
682  for (int i = 0; i < num; ++i) {
683  uchar flag = 0;
684  for (int s = 0; s < stops.size(); ++s) {
685  uint rgb = stops.at(s).second.rgba();
686  int xpos = (int)(start.x()*factor_x);
687  int ypos = (int)(start.y()*factor_y);
688  writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
689  if (s < stops.size()-1)
690  start += offset*(stops.at(s+1).first - stops.at(s).first);
691  flag = 1;
692  }
693  }
694  }
695  triangles.resize((char *)data - triangles.constData());
696 
697  QByteArray shader;
698  QPdf::ByteStream s(&shader);
699  s << "<<\n"
700  "/ShadingType 4\n"
701  "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
702  "/AntiAlias true\n"
703  "/BitsPerCoordinate 24\n"
704  "/BitsPerComponent 8\n"
705  "/BitsPerFlag 8\n"
706  "/Decode [" << xmin << xmax << ymin << ymax << (alpha ? "0 1]\n" : "0 1 0 1 0 1]\n") <<
707  "/AntiAlias true\n"
708  "/Length " << triangles.length() << "\n"
709  ">>\n"
710  "stream\n" << triangles << "endstream\n"
711  "endobj\n";
712  return shader;
713 }
714 #endif
715 
716 static void moveToHook(qfixed x, qfixed y, void *data)
717 {
718  QPdf::Stroker *t = (QPdf::Stroker *)data;
719  if (!t->first)
720  *t->stream << "h\n";
721  if (!t->cosmeticPen)
722  t->matrix.map(x, y, &x, &y);
723  *t->stream << x << y << "m\n";
724  t->first = false;
725 }
726 
727 static void lineToHook(qfixed x, qfixed y, void *data)
728 {
729  QPdf::Stroker *t = (QPdf::Stroker *)data;
730  if (!t->cosmeticPen)
731  t->matrix.map(x, y, &x, &y);
732  *t->stream << x << y << "l\n";
733 }
734 
735 static void cubicToHook(qfixed c1x, qfixed c1y,
736  qfixed c2x, qfixed c2y,
737  qfixed ex, qfixed ey,
738  void *data)
739 {
740  QPdf::Stroker *t = (QPdf::Stroker *)data;
741  if (!t->cosmeticPen) {
742  t->matrix.map(c1x, c1y, &c1x, &c1y);
743  t->matrix.map(c2x, c2y, &c2x, &c2y);
744  t->matrix.map(ex, ey, &ex, &ey);
745  }
746  *t->stream << c1x << c1y
747  << c2x << c2y
748  << ex << ey
749  << "c\n";
750 }
751 
753  : stream(0),
754  first(true),
755  dashStroker(&basicStroker)
756 {
761  cosmeticPen = true;
763 }
764 
765 void QPdf::Stroker::setPen(const QPen &pen)
766 {
767  if (pen.style() == Qt::NoPen) {
768  stroker = 0;
769  return;
770  }
771  qreal w = pen.widthF();
772  bool zeroWidth = w < 0.0001;
773  cosmeticPen = pen.isCosmetic();
774  if (zeroWidth)
775  w = .1;
776 
781 
782  QVector<qreal> dashpattern = pen.dashPattern();
783  if (zeroWidth) {
784  for (int i = 0; i < dashpattern.size(); ++i)
785  dashpattern[i] *= 10.;
786  }
787  if (!dashpattern.isEmpty()) {
788  dashStroker.setDashPattern(dashpattern);
790  stroker = &dashStroker;
791  } else {
793  }
794 }
795 
797 {
798  if (!stroker)
799  return;
800  first = true;
801 
802  stroker->strokePath(path, this, cosmeticPen ? matrix : QTransform());
803  *stream << "h f\n";
804 }
805 
807 {
808  int isize = input.size()/4*4;
809  QByteArray output;
810  output.resize(input.size()*5/4+7);
811  char *out = output.data();
812  const uchar *in = (const uchar *)input.constData();
813  for (int i = 0; i < isize; i += 4) {
814  uint val = (((uint)in[i])<<24) + (((uint)in[i+1])<<16) + (((uint)in[i+2])<<8) + (uint)in[i+3];
815  if (val == 0) {
816  *out = 'z';
817  ++out;
818  } else {
819  char base[5];
820  base[4] = val % 85;
821  val /= 85;
822  base[3] = val % 85;
823  val /= 85;
824  base[2] = val % 85;
825  val /= 85;
826  base[1] = val % 85;
827  val /= 85;
828  base[0] = val % 85;
829  *(out++) = base[0] + '!';
830  *(out++) = base[1] + '!';
831  *(out++) = base[2] + '!';
832  *(out++) = base[3] + '!';
833  *(out++) = base[4] + '!';
834  }
835  }
836  //write the last few bytes
837  int remaining = input.size() - isize;
838  if (remaining) {
839  uint val = 0;
840  for (int i = isize; i < input.size(); ++i)
841  val = (val << 8) + in[i];
842  val <<= 8*(4-remaining);
843  char base[5];
844  base[4] = val % 85;
845  val /= 85;
846  base[3] = val % 85;
847  val /= 85;
848  base[2] = val % 85;
849  val /= 85;
850  base[1] = val % 85;
851  val /= 85;
852  base[0] = val % 85;
853  for (int i = 0; i < remaining+1; ++i)
854  *(out++) = base[i] + '!';
855  }
856  *(out++) = '~';
857  *(out++) = '>';
858  output.resize(out-output.data());
859  return output;
860 }
861 
862 const char *QPdf::toHex(ushort u, char *buffer)
863 {
864  int i = 3;
865  while (i >= 0) {
866  ushort hex = (u & 0x000f);
867  if (hex < 0x0a)
868  buffer[i] = '0'+hex;
869  else
870  buffer[i] = 'A'+(hex-0x0a);
871  u = u >> 4;
872  i--;
873  }
874  buffer[4] = '\0';
875  return buffer;
876 }
877 
878 const char *QPdf::toHex(uchar u, char *buffer)
879 {
880  int i = 1;
881  while (i >= 0) {
882  ushort hex = (u & 0x000f);
883  if (hex < 0x0a)
884  buffer[i] = '0'+hex;
885  else
886  buffer[i] = 'A'+(hex-0x0a);
887  u = u >> 4;
888  i--;
889  }
890  buffer[2] = '\0';
891  return buffer;
892 }
893 
894 #define Q_MM(n) int((n * 720 + 127) / 254)
895 #define Q_IN(n) int(n * 72)
896 
897 static const char * const psToStr[QPrinter::NPaperSize+1] =
898 {
899  "A4", "B5", "Letter", "Legal", "Executive",
900  "A0", "A1", "A2", "A3", "A5", "A6", "A7", "A8", "A9", "B0", "B1",
901  "B10", "B2", "B3", "B4", "B6", "B7", "B8", "B9", "C5E", "Comm10E",
902  "DLE", "Folio", "Ledger", "Tabloid", 0
903 };
904 
906 {
907  QSizeF s = qt_paperSizeToQSizeF(paperSize);
908  PaperSize p = { Q_MM(s.width()), Q_MM(s.height()) };
909  return p;
910 }
911 
913 {
914  return psToStr[paperSize];
915 }
916 
917 // -------------------------- base engine, shared code between PS and PDF -----------------------
918 
920  : QAlphaPaintEngine(dd, f)
921 {
923 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
925  QCUPSSupport cups;
926  const cups_dest_t* printers = cups.availablePrinters();
927  int prnCount = cups.availablePrintersCount();
928 
929  for (int i = 0; i < prnCount; ++i) {
930  if (printers[i].is_default) {
931  d->printerName = QString::fromLocal8Bit(printers[i].name);
932  break;
933  }
934  }
935 
936  } else
937 #endif
938  {
939  d->printerName = QString::fromLocal8Bit(qgetenv("PRINTER"));
940  if (d->printerName.isEmpty())
941  d->printerName = QString::fromLocal8Bit(qgetenv("LPDEST"));
942  if (d->printerName.isEmpty())
943  d->printerName = QString::fromLocal8Bit(qgetenv("NPRINTER"));
944  if (d->printerName.isEmpty())
945  d->printerName = QString::fromLocal8Bit(qgetenv("NGPRINTER"));
946  }
947 }
948 
949 void QPdfBaseEngine::drawPoints (const QPointF *points, int pointCount)
950 {
951  if (!points)
952  return;
953 
955  QPainterPath p;
956  for (int i=0; i!=pointCount;++i) {
957  p.moveTo(points[i]);
958  p.lineTo(points[i] + QPointF(0, 0.001));
959  }
960 
961  bool hadBrush = d->hasBrush;
962  d->hasBrush = false;
963  drawPath(p);
964  d->hasBrush = hadBrush;
965 }
966 
967 void QPdfBaseEngine::drawLines (const QLineF *lines, int lineCount)
968 {
969  if (!lines)
970  return;
971 
973  QPainterPath p;
974  for (int i=0; i!=lineCount;++i) {
975  p.moveTo(lines[i].p1());
976  p.lineTo(lines[i].p2());
977  }
978  bool hadBrush = d->hasBrush;
979  d->hasBrush = false;
980  drawPath(p);
981  d->hasBrush = hadBrush;
982 }
983 
984 void QPdfBaseEngine::drawRects (const QRectF *rects, int rectCount)
985 {
986  if (!rects)
987  return;
988 
990  if (d->useAlphaEngine) {
991  QAlphaPaintEngine::drawRects(rects, rectCount);
992  if (!continueCall())
993  return;
994  }
995 
996  if (d->clipEnabled && d->allClipped)
997  return;
998  if (!d->hasPen && !d->hasBrush)
999  return;
1000 
1001  QBrush penBrush = d->pen.brush();
1002  if (d->simplePen || !d->hasPen) {
1003  // draw strokes natively in this case for better output
1004  if(!d->simplePen && !d->stroker.matrix.isIdentity())
1005  *d->currentPage << "q\n" << QPdf::generateMatrix(d->stroker.matrix);
1006  for (int i = 0; i < rectCount; ++i)
1007  *d->currentPage << rects[i].x() << rects[i].y() << rects[i].width() << rects[i].height() << "re\n";
1008  *d->currentPage << (d->hasPen ? (d->hasBrush ? "B\n" : "S\n") : "f\n");
1009  if(!d->simplePen && !d->stroker.matrix.isIdentity())
1010  *d->currentPage << "Q\n";
1011  } else {
1012  QPainterPath p;
1013  for (int i=0; i!=rectCount; ++i)
1014  p.addRect(rects[i]);
1015  drawPath(p);
1016  }
1017 }
1018 
1019 void QPdfBaseEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
1020 {
1022 
1023  if (d->useAlphaEngine) {
1024  QAlphaPaintEngine::drawPolygon(points, pointCount, mode);
1025  if (!continueCall())
1026  return;
1027  }
1028 
1029  if (!points || !pointCount)
1030  return;
1031 
1032  bool hb = d->hasBrush;
1033  QPainterPath p;
1034 
1035  switch(mode) {
1036  case OddEvenMode:
1038  break;
1039  case ConvexMode:
1040  case WindingMode:
1042  break;
1043  case PolylineMode:
1044  d->hasBrush = false;
1045  break;
1046  default:
1047  break;
1048  }
1049 
1050  p.moveTo(points[0]);
1051  for (int i = 1; i < pointCount; ++i)
1052  p.lineTo(points[i]);
1053 
1054  if (mode != PolylineMode)
1055  p.closeSubpath();
1056  drawPath(p);
1057 
1058  d->hasBrush = hb;
1059 }
1060 
1062 {
1064 
1065  if (d->useAlphaEngine) {
1067  if (!continueCall())
1068  return;
1069  }
1070 
1071  if (d->clipEnabled && d->allClipped)
1072  return;
1073  if (!d->hasPen && !d->hasBrush)
1074  return;
1075 
1076  if (d->simplePen) {
1077  // draw strokes natively in this case for better output
1078  *d->currentPage << QPdf::generatePath(p, QTransform(), d->hasBrush ? QPdf::FillAndStrokePath : QPdf::StrokePath);
1079  } else {
1080  if (d->hasBrush)
1081  *d->currentPage << QPdf::generatePath(p, d->stroker.matrix, QPdf::FillPath);
1082  if (d->hasPen) {
1083  *d->currentPage << "q\n";
1084  QBrush b = d->brush;
1085  d->brush = d->pen.brush();
1086  setBrush();
1087  d->stroker.strokePath(p);
1088  *d->currentPage << "Q\n";
1089  d->brush = b;
1090  }
1091  }
1092 }
1093 
1094 void QPdfBaseEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
1095 {
1097 
1098  if (d->useAlphaEngine) {
1099  QAlphaPaintEngine::drawTextItem(p, textItem);
1100  if (!continueCall())
1101  return;
1102  }
1103 
1104  if (!d->hasPen || (d->clipEnabled && d->allClipped))
1105  return;
1106 
1107  if (d->stroker.matrix.type() >= QTransform::TxProject) {
1108  QPaintEngine::drawTextItem(p, textItem);
1109  return;
1110  }
1111 
1112  *d->currentPage << "q\n";
1113  if(!d->simplePen)
1114  *d->currentPage << QPdf::generateMatrix(d->stroker.matrix);
1115 
1116  bool hp = d->hasPen;
1117  d->hasPen = false;
1118  QBrush b = d->brush;
1119  d->brush = d->pen.brush();
1120  setBrush();
1121 
1122  const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
1124  d->drawTextItem(p, ti);
1125  d->hasPen = hp;
1126  d->brush = b;
1127  *d->currentPage << "Q\n";
1128 }
1129 
1130 
1132 {
1134 
1135  if (d->useAlphaEngine) {
1137  if (!continueCall())
1138  return;
1139  }
1140 
1141  QPaintEngine::DirtyFlags flags = state.state();
1142 
1143  if (flags & DirtyTransform)
1144  d->stroker.matrix = state.transform();
1145 
1146  if (flags & DirtyPen) {
1147  d->pen = state.pen();
1148  d->hasPen = d->pen.style() != Qt::NoPen;
1149  d->stroker.setPen(d->pen);
1150  QBrush penBrush = d->pen.brush();
1151  bool oldSimple = d->simplePen;
1152  d->simplePen = (d->hasPen && (penBrush.style() == Qt::SolidPattern) && penBrush.isOpaque());
1153  if (oldSimple != d->simplePen)
1154  flags |= DirtyTransform;
1155  }
1156  if (flags & DirtyBrush) {
1157  d->brush = state.brush();
1158  if (d->brush.color().alpha() == 0 && d->brush.style() == Qt::SolidPattern)
1159  d->brush.setStyle(Qt::NoBrush);
1160  d->hasBrush = d->brush.style() != Qt::NoBrush;
1161  }
1162  if (flags & DirtyBrushOrigin) {
1163  d->brushOrigin = state.brushOrigin();
1164  flags |= DirtyBrush;
1165  }
1166  if (flags & DirtyOpacity)
1167  d->opacity = state.opacity();
1168 
1169  bool ce = d->clipEnabled;
1170  if (flags & DirtyClipPath) {
1171  d->clipEnabled = true;
1172  updateClipPath(state.clipPath(), state.clipOperation());
1173  } else if (flags & DirtyClipRegion) {
1174  d->clipEnabled = true;
1175  QPainterPath path;
1176  QVector<QRect> rects = state.clipRegion().rects();
1177  for (int i = 0; i < rects.size(); ++i)
1178  path.addRect(rects.at(i));
1179  updateClipPath(path, state.clipOperation());
1180  flags |= DirtyClipPath;
1181  } else if (flags & DirtyClipEnabled) {
1182  d->clipEnabled = state.isClipEnabled();
1183  }
1184 
1185  if (ce != d->clipEnabled)
1186  flags |= DirtyClipPath;
1187  else if (!d->clipEnabled)
1188  flags &= ~DirtyClipPath;
1189 
1190  setupGraphicsState(flags);
1191 }
1192 
1193 void QPdfBaseEngine::setupGraphicsState(QPaintEngine::DirtyFlags flags)
1194 {
1196  if (flags & DirtyClipPath)
1198 
1199  if (flags & DirtyTransform) {
1200  *d->currentPage << "Q\n";
1201  flags |= DirtyPen|DirtyBrush;
1202  }
1203 
1204  if (flags & DirtyClipPath) {
1205  *d->currentPage << "Q q\n";
1206 
1207  d->allClipped = false;
1208  if (d->clipEnabled && !d->clips.isEmpty()) {
1209  for (int i = 0; i < d->clips.size(); ++i) {
1210  if (d->clips.at(i).isEmpty()) {
1211  d->allClipped = true;
1212  break;
1213  }
1214  }
1215  if (!d->allClipped) {
1216  for (int i = 0; i < d->clips.size(); ++i) {
1217  *d->currentPage << QPdf::generatePath(d->clips.at(i), QTransform(), QPdf::ClipPath);
1218  }
1219  }
1220  }
1221  }
1222 
1223  if (flags & DirtyTransform) {
1224  *d->currentPage << "q\n";
1225  if (d->simplePen && !d->stroker.matrix.isIdentity())
1226  *d->currentPage << QPdf::generateMatrix(d->stroker.matrix);
1227  }
1228  if (flags & DirtyBrush)
1229  setBrush();
1230  if (d->simplePen && (flags & DirtyPen))
1231  setPen();
1232 }
1233 
1235 
1237 {
1239  QPainterPath path = d->stroker.matrix.map(p);
1240  //qDebug() << "updateClipPath: " << d->stroker.matrix << p.boundingRect() << path.boundingRect() << op;
1241 
1242  if (op == Qt::NoClip) {
1243  d->clipEnabled = false;
1244  d->clips.clear();
1245  } else if (op == Qt::ReplaceClip) {
1246  d->clips.clear();
1247  d->clips.append(path);
1248  } else if (op == Qt::IntersectClip) {
1249  d->clips.append(path);
1250  } else { // UniteClip
1251  // ask the painter for the current clipping path. that's the easiest solution
1252  path = painter()->clipPath();
1253  path = d->stroker.matrix.map(path);
1254  d->clips.clear();
1255  d->clips.append(path);
1256  }
1257 
1258  if (d->useAlphaEngine) {
1259  // if we have an alpha region, we have to subtract that from the
1260  // any existing clip region since that region will be filled in
1261  // later with images
1263  if (!alphaClip.isEmpty()) {
1264  if (!d->clipEnabled) {
1265  QRect r = d->fullPage ? d->paperRect() : d->pageRect();
1266  QPainterPath dev;
1267  dev.addRect(QRect(0, 0, r.width(), r.height()));
1268  if (path.isEmpty())
1269  path = dev;
1270  else
1271  path = path.intersected(dev);
1272  d->clipEnabled = true;
1273  } else {
1274  path = painter()->clipPath();
1275  path = d->stroker.matrix.map(path);
1276  }
1277  path = path.subtracted(alphaClip);
1278  d->clips.clear();
1279  d->clips.append(path);
1280  }
1281  }
1282 }
1283 
1285 {
1287  if (d->pen.style() == Qt::NoPen)
1288  return;
1289  QBrush b = d->pen.brush();
1290  Q_ASSERT(b.style() == Qt::SolidPattern && b.isOpaque());
1291 
1292  QColor rgba = b.color();
1293  if (d->colorMode == QPrinter::GrayScale) {
1294  qreal gray = qGray(rgba.rgba())/255.;
1295  *d->currentPage << gray << gray << gray;
1296  } else {
1297  *d->currentPage << rgba.redF()
1298  << rgba.greenF()
1299  << rgba.blueF();
1300  }
1301  *d->currentPage << "SCN\n";
1302 
1303  *d->currentPage << d->pen.widthF() << "w ";
1304 
1305  int pdfCapStyle = 0;
1306  switch(d->pen.capStyle()) {
1307  case Qt::FlatCap:
1308  pdfCapStyle = 0;
1309  break;
1310  case Qt::SquareCap:
1311  pdfCapStyle = 2;
1312  break;
1313  case Qt::RoundCap:
1314  pdfCapStyle = 1;
1315  break;
1316  default:
1317  break;
1318  }
1319  *d->currentPage << pdfCapStyle << "J ";
1320 
1321  int pdfJoinStyle = 0;
1322  switch(d->pen.joinStyle()) {
1323  case Qt::MiterJoin:
1324  pdfJoinStyle = 0;
1325  break;
1326  case Qt::BevelJoin:
1327  pdfJoinStyle = 2;
1328  break;
1329  case Qt::RoundJoin:
1330  pdfJoinStyle = 1;
1331  break;
1332  default:
1333  break;
1334  }
1335  *d->currentPage << pdfJoinStyle << "j ";
1336 
1337  *d->currentPage << QPdf::generateDashes(d->pen) << " 0 d\n";
1338 }
1339 
1341 {
1344  QFile *outfile = qobject_cast<QFile*> (d->outDevice);
1345  if (outfile && outfile->error() != QFile::NoError)
1346  return false;
1347  return true;
1348 }
1349 
1350 
1352 {
1353  Q_D(const QPdfBaseEngine);
1354  int val;
1355  QRect r = d->fullPage ? d->paperRect() : d->pageRect();
1356  switch (metricType) {
1358  val = r.width();
1359  break;
1361  val = r.height();
1362  break;
1363  case QPaintDevice::PdmDpiX:
1364  case QPaintDevice::PdmDpiY:
1365  val = d->resolution;
1366  break;
1369  val = 1200;
1370  break;
1372  val = qRound(r.width()*25.4/d->resolution);
1373  break;
1375  val = qRound(r.height()*25.4/d->resolution);
1376  break;
1378  val = INT_MAX;
1379  break;
1381  val = 32;
1382  break;
1383  default:
1384  qWarning("QPrinter::metric: Invalid metric command");
1385  return 0;
1386  }
1387  return val;
1388 }
1389 
1391 {
1393  switch (int(key)) {
1394  case PPK_CollateCopies:
1395  d->collate = value.toBool();
1396  break;
1397  case PPK_ColorMode:
1398  d->colorMode = QPrinter::ColorMode(value.toInt());
1399  break;
1400  case PPK_Creator:
1401  d->creator = value.toString();
1402  break;
1403  case PPK_DocumentName:
1404  d->title = value.toString();
1405  break;
1406  case PPK_FullPage:
1407  d->fullPage = value.toBool();
1408  break;
1409  case PPK_CopyCount: // fallthrough
1410  case PPK_NumberOfCopies:
1411  d->copies = value.toInt();
1412  break;
1413  case PPK_Orientation:
1414  d->orientation = QPrinter::Orientation(value.toInt());
1415  break;
1416  case PPK_OutputFileName:
1417  d->outputFileName = value.toString();
1418  break;
1419  case PPK_PageOrder:
1420  d->pageOrder = QPrinter::PageOrder(value.toInt());
1421  break;
1422  case PPK_PaperSize:
1423  d->paperSize = QPrinter::PaperSize(value.toInt());
1424  break;
1425  case PPK_PaperSource:
1426  d->paperSource = QPrinter::PaperSource(value.toInt());
1427  break;
1428  case PPK_PrinterName:
1429  d->printerName = value.toString();
1430  break;
1431  case PPK_PrinterProgram:
1432  d->printProgram = value.toString();
1433  break;
1434  case PPK_Resolution:
1435  d->resolution = value.toInt();
1436  break;
1437  case PPK_SelectionOption:
1438  d->selectionOption = value.toString();
1439  break;
1440  case PPK_FontEmbedding:
1441  d->embedFonts = value.toBool();
1442  break;
1443  case PPK_Duplex:
1444  d->duplex = static_cast<QPrinter::DuplexMode> (value.toInt());
1445  break;
1446  case PPK_CupsPageRect:
1447  d->cupsPageRect = value.toRect();
1448  break;
1449  case PPK_CupsPaperRect:
1450  d->cupsPaperRect = value.toRect();
1451  break;
1452  case PPK_CupsOptions:
1453  d->cupsOptions = value.toStringList();
1454  break;
1456  d->cupsStringPageSize = value.toString();
1457  break;
1458  case PPK_CustomPaperSize:
1459  d->paperSize = QPrinter::Custom;
1460  d->customPaperSize = value.toSizeF();
1461  break;
1462  case PPK_PageMargins:
1463  {
1464  QList<QVariant> margins(value.toList());
1465  Q_ASSERT(margins.size() == 4);
1466  d->leftMargin = margins.at(0).toReal();
1467  d->topMargin = margins.at(1).toReal();
1468  d->rightMargin = margins.at(2).toReal();
1469  d->bottomMargin = margins.at(3).toReal();
1470  d->hasCustomPageMargins = true;
1471  break;
1472  }
1473  default:
1474  break;
1475  }
1476 }
1477 
1479 {
1480  Q_D(const QPdfBaseEngine);
1481 
1482  QVariant ret;
1483  switch (int(key)) {
1484  case PPK_CollateCopies:
1485  ret = d->collate;
1486  break;
1487  case PPK_ColorMode:
1488  ret = d->colorMode;
1489  break;
1490  case PPK_Creator:
1491  ret = d->creator;
1492  break;
1493  case PPK_DocumentName:
1494  ret = d->title;
1495  break;
1496  case PPK_FullPage:
1497  ret = d->fullPage;
1498  break;
1499  case PPK_CopyCount:
1500  ret = d->copies;
1501  break;
1503 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
1505  ret = true;
1506  else
1507 #endif
1508  ret = false;
1509  break;
1510  case PPK_NumberOfCopies:
1511 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
1513  ret = 1;
1514  else
1515 #endif
1516  ret = d->copies;
1517  break;
1518  case PPK_Orientation:
1519  ret = d->orientation;
1520  break;
1521  case PPK_OutputFileName:
1522  ret = d->outputFileName;
1523  break;
1524  case PPK_PageOrder:
1525  ret = d->pageOrder;
1526  break;
1527  case PPK_PaperSize:
1528  ret = d->paperSize;
1529  break;
1530  case PPK_PaperSource:
1531  ret = d->paperSource;
1532  break;
1533  case PPK_PrinterName:
1534  ret = d->printerName;
1535  break;
1536  case PPK_PrinterProgram:
1537  ret = d->printProgram;
1538  break;
1539  case PPK_Resolution:
1540  ret = d->resolution;
1541  break;
1543  ret = QList<QVariant>() << 72;
1544  break;
1545  case PPK_PaperRect:
1546  ret = d->paperRect();
1547  break;
1548  case PPK_PageRect:
1549  ret = d->pageRect();
1550  break;
1551  case PPK_SelectionOption:
1552  ret = d->selectionOption;
1553  break;
1554  case PPK_FontEmbedding:
1555  ret = d->embedFonts;
1556  break;
1557  case PPK_Duplex:
1558  ret = d->duplex;
1559  break;
1560  case PPK_CupsPageRect:
1561  ret = d->cupsPageRect;
1562  break;
1563  case PPK_CupsPaperRect:
1564  ret = d->cupsPaperRect;
1565  break;
1566  case PPK_CupsOptions:
1567  ret = d->cupsOptions;
1568  break;
1570  ret = d->cupsStringPageSize;
1571  break;
1572  case PPK_CustomPaperSize:
1573  ret = d->customPaperSize;
1574  break;
1575  case PPK_PageMargins:
1576  {
1577  QList<QVariant> margins;
1578  if (d->hasCustomPageMargins) {
1579  margins << d->leftMargin << d->topMargin
1580  << d->rightMargin << d->bottomMargin;
1581  } else {
1582  const qreal defaultMargin = 10; // ~3.5 mm
1583  margins << defaultMargin << defaultMargin
1584  << defaultMargin << defaultMargin;
1585  }
1586  ret = margins;
1587  break;
1588  }
1589  default:
1590  break;
1591  }
1592  return ret;
1593 }
1594 
1596  : clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
1597  useAlphaEngine(false),
1598  outDevice(0), fd(-1),
1599  duplex(QPrinter::DuplexNone), collate(false), fullPage(false), embedFonts(true), copies(1),
1600  pageOrder(QPrinter::FirstPageFirst), orientation(QPrinter::Portrait),
1601  paperSize(QPrinter::A4), colorMode(QPrinter::Color), paperSource(QPrinter::Auto),
1602  hasCustomPageMargins(false),
1603  leftMargin(0), topMargin(0), rightMargin(0), bottomMargin(0)
1604 {
1605  resolution = 72;
1606  if (m == QPrinter::HighResolution)
1607  resolution = 1200;
1608  else if (m == QPrinter::ScreenResolution)
1610 
1611  postscript = false;
1612  currentObject = 1;
1613  currentPage = 0;
1614  stroker.stream = 0;
1615 }
1616 
1618 {
1620  d->pdev = pdev;
1621 
1622  d->postscript = false;
1623  d->currentObject = 1;
1624 
1625  d->currentPage = new QPdfPage;
1626  d->stroker.stream = d->currentPage;
1627  d->opacity = 1.0;
1628 
1629  return d->openPrintDevice();
1630 }
1631 
1633 {
1635  qDeleteAll(d->fonts);
1636  d->fonts.clear();
1637  delete d->currentPage;
1638  d->currentPage = 0;
1639 
1640  d->closePrintDevice();
1641  return true;
1642 }
1643 
1644 #ifndef QT_NO_LPR
1645 static void closeAllOpenFds()
1646 {
1647  // hack time... getting the maximum number of open
1648  // files, if possible. if not we assume it's the
1649  // larger of 256 and the fd we got
1650  int i;
1651 #if defined(_SC_OPEN_MAX)
1652  i = (int)sysconf(_SC_OPEN_MAX);
1653 #elif defined(_POSIX_OPEN_MAX)
1654  i = (int)_POSIX_OPEN_MAX;
1655 #elif defined(OPEN_MAX)
1656  i = (int)OPEN_MAX;
1657 #else
1658  i = 256;
1659 #endif
1660  // leave stdin/out/err untouched
1661  while(--i > 2)
1662  QT_CLOSE(i);
1663 }
1664 #endif
1665 
1667 {
1668  if(outDevice)
1669  return false;
1670 
1671  if (!outputFileName.isEmpty()) {
1672  QFile *file = new QFile(outputFileName);
1673  if (! file->open(QFile::WriteOnly|QFile::Truncate)) {
1674  delete file;
1675  return false;
1676  }
1677  outDevice = file;
1678 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
1679  } else if (QCUPSSupport::isAvailable()) {
1680  QCUPSSupport cups;
1681  QPair<int, QString> ret = cups.tempFd();
1682  if (ret.first < 0) {
1683  qWarning("QPdfPrinter: Could not open temporary file to print");
1684  return false;
1685  }
1686  cupsTempFile = ret.second;
1687  outDevice = new QFile();
1688  static_cast<QFile *>(outDevice)->open(ret.first, QIODevice::WriteOnly);
1689  fd = ret.first;
1690 #endif
1691 #ifndef QT_NO_LPR
1692  } else {
1693  QString pr;
1694  if (!printerName.isEmpty())
1695  pr = printerName;
1696  int fds[2];
1697  if (qt_safe_pipe(fds) != 0) {
1698  qWarning("QPdfPrinter: Could not open pipe to print");
1699  return false;
1700  }
1701 
1702  pid_t pid = fork();
1703  if (pid == 0) { // child process
1704  // if possible, exit quickly, so the actual lp/lpr
1705  // becomes a child of init, and ::waitpid() is
1706  // guaranteed not to wait.
1707  if (fork() > 0) {
1708  closeAllOpenFds();
1709 
1710  // try to replace this process with "true" - this prevents
1711  // global destructors from being called (that could possibly
1712  // do wrong things to the parent process)
1713  (void)execlp("true", "true", (char *)0);
1714  (void)execl("/bin/true", "true", (char *)0);
1715  (void)execl("/usr/bin/true", "true", (char *)0);
1716  ::_exit(0);
1717  }
1718  qt_safe_dup2(fds[0], 0, 0);
1719 
1720  closeAllOpenFds();
1721 
1722  if (!printProgram.isEmpty()) {
1723  if (!selectionOption.isEmpty())
1725  else
1726  pr.prepend(QLatin1String("-P"));
1727  (void)execlp(printProgram.toLocal8Bit().data(), printProgram.toLocal8Bit().data(),
1728  pr.toLocal8Bit().data(), (char *)0);
1729  } else {
1730  // if no print program has been specified, be smart
1731  // about the option string too.
1732  QList<QByteArray> lprhack;
1733  QList<QByteArray> lphack;
1734  QByteArray media;
1735  if (!pr.isEmpty() || !selectionOption.isEmpty()) {
1736  if (!selectionOption.isEmpty()) {
1738  for (int i = 0; i < list.size(); ++i)
1739  lprhack.append(list.at(i).toLocal8Bit());
1740  lphack = lprhack;
1741  } else {
1742  lprhack.append("-P");
1743  lphack.append("-d");
1744  }
1745  lprhack.append(pr.toLocal8Bit());
1746  lphack.append(pr.toLocal8Bit());
1747  }
1748  lphack.append("-s");
1749 
1750  char ** lpargs = new char *[lphack.size()+6];
1751  char lp[] = "lp";
1752  lpargs[0] = lp;
1753  int i;
1754  for (i = 0; i < lphack.size(); ++i)
1755  lpargs[i+1] = (char *)lphack.at(i).constData();
1756 #ifndef Q_OS_OSF
1757  char dash_o[] = "-o";
1759  lpargs[++i] = dash_o;
1760  lpargs[++i] = const_cast<char *>(QPdf::paperSizeToString(paperSize));
1761  lpargs[++i] = dash_o;
1762  media = "media=";
1764  lpargs[++i] = media.data();
1765  }
1766 #endif
1767  lpargs[++i] = 0;
1768  char **lprargs = new char *[lprhack.size()+2];
1769  char lpr[] = "lpr";
1770  lprargs[0] = lpr;
1771  for (int i = 0; i < lprhack.size(); ++i)
1772  lprargs[i+1] = (char *)lprhack[i].constData();
1773  lprargs[lprhack.size() + 1] = 0;
1774  (void)execvp("lp", lpargs);
1775  (void)execvp("lpr", lprargs);
1776  (void)execv("/bin/lp", lpargs);
1777  (void)execv("/bin/lpr", lprargs);
1778  (void)execv("/usr/bin/lp", lpargs);
1779  (void)execv("/usr/bin/lpr", lprargs);
1780 
1781  delete []lpargs;
1782  delete []lprargs;
1783  }
1784  // if we couldn't exec anything, close the fd,
1785  // wait for a second so the parent process (the
1786  // child of the GUI process) has exited. then
1787  // exit.
1788  QT_CLOSE(0);
1789  (void)::sleep(1);
1790  ::_exit(0);
1791  }
1792  // parent process
1793  QT_CLOSE(fds[0]);
1794  fd = fds[1];
1795  (void)qt_safe_waitpid(pid, 0, 0);
1796 
1797  if (fd < 0)
1798  return false;
1799 
1800  outDevice = new QFile();
1801  static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly);
1802 #endif
1803  }
1804 
1805  return true;
1806 }
1807 
1809 {
1810  if (!outDevice)
1811  return;
1812  outDevice->close();
1813  if (fd >= 0)
1814 #if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400
1815  ::_close(fd);
1816 #else
1817  ::close(fd);
1818 #endif
1819  fd = -1;
1820  delete outDevice;
1821  outDevice = 0;
1822 
1823 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
1824  if (!cupsTempFile.isEmpty()) {
1825  QString tempFile = cupsTempFile;
1826  cupsTempFile.clear();
1827  QCUPSSupport cups;
1828 
1829  // Set up print options.
1830  QByteArray prnName;
1832  QVector<cups_option_t> cupsOptStruct;
1833 
1834  if (!printerName.isEmpty()) {
1835  prnName = printerName.toLocal8Bit();
1836  } else {
1838  if (def.isNull()) {
1839  qWarning("Could not determine printer to print to");
1840  QFile::remove(tempFile);
1841  return;
1842  }
1843  prnName = def.printerName().toLocal8Bit();
1844  }
1845 
1846  if (!cupsStringPageSize.isEmpty()) {
1848  }
1849 
1850  if (copies > 1) {
1851  options.append(QPair<QByteArray, QByteArray>("copies", QString::number(copies).toLocal8Bit()));
1852  }
1853 
1854  if (collate) {
1855  options.append(QPair<QByteArray, QByteArray>("Collate", "True"));
1856  }
1857 
1858  switch (duplex) {
1859  case QPrinter::DuplexNone:
1860  options.append(QPair<QByteArray, QByteArray>("sides", "one-sided"));
1861  break;
1862  case QPrinter::DuplexAuto:
1864  options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
1865  else
1866  options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
1867  break;
1869  options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
1870  break;
1872  options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
1873  break;
1874  }
1875 
1877  options.append(QPair<QByteArray, QByteArray>("landscape", ""));
1878  }
1879 
1881  while (it != cupsOptions.constEnd()) {
1882  options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit()));
1883  it += 2;
1884  }
1885 
1886  for (int c = 0; c < options.size(); ++c) {
1887  cups_option_t opt;
1888  opt.name = options[c].first.data();
1889  opt.value = options[c].second.data();
1890  cupsOptStruct.append(opt);
1891  }
1892 
1893  // Print the file.
1894  cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0;
1895  cups.printFile(prnName.constData(), tempFile.toLocal8Bit().constData(),
1896  title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr);
1897 
1898  QFile::remove(tempFile);
1899  }
1900 #endif
1901 }
1902 
1904 {
1905  qDeleteAll(fonts);
1906  delete currentPage;
1907 }
1908 
1910 {
1912 
1913  QFontEngine *fe = ti.fontEngine;
1914 
1915  QFontEngine::FaceId face_id = fe->faceId();
1916  bool noEmbed = false;
1917  if (face_id.filename.isEmpty()
1918  || (!postscript && ((fe->fsType & 0x200) /* bitmap embedding only */
1919  || (fe->fsType == 2) /* no embedding allowed */))) {
1920  *currentPage << "Q\n";
1921  q->QPaintEngine::drawTextItem(p, ti);
1922  *currentPage << "q\n";
1923  if (face_id.filename.isEmpty())
1924  return;
1925  noEmbed = true;
1926  }
1927 
1928  QFontSubset *font = fonts.value(face_id, 0);
1929  if (!font) {
1930  font = new QFontSubset(fe, requestObject());
1931  font->noEmbed = noEmbed;
1932  }
1933  fonts.insert(face_id, font);
1934 
1935  if (!currentPage->fonts.contains(font->object_id))
1937 
1938  qreal size = ti.fontEngine->fontDef.pixelSize;
1939 #ifdef Q_WS_WIN
1940  if (ti.fontEngine->type() == QFontEngine::Win) {
1941  QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
1942  size = fe->tm.tmHeight;
1943  }
1944 #endif
1945 
1946  QVarLengthArray<glyph_t> glyphs;
1948  QTransform m = QTransform::fromTranslate(p.x(), p.y());
1949  ti.fontEngine->getGlyphPositions(ti.glyphs, m, ti.flags,
1950  glyphs, positions);
1951  if (glyphs.size() == 0)
1952  return;
1953  int synthesized = ti.fontEngine->synthesized();
1954  qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.;
1955 
1956  *currentPage << "BT\n"
1957  << "/F" << font->object_id << size << "Tf "
1958  << stretch << (synthesized & QFontEngine::SynthesizedItalic
1959  ? "0 .3 -1 0 0 Tm\n"
1960  : "0 0 -1 0 0 Tm\n");
1961 
1962 
1963 #if 0
1964  // #### implement actual text for complex languages
1965  const unsigned short *logClusters = ti.logClusters;
1966  int pos = 0;
1967  do {
1968  int end = pos + 1;
1969  while (end < ti.num_chars && logClusters[end] == logClusters[pos])
1970  ++end;
1971  *currentPage << "/Span << /ActualText <FEFF";
1972  for (int i = pos; i < end; ++i) {
1973  s << toHex((ushort)ti.chars[i].unicode(), buf);
1974  }
1975  *currentPage << "> >>\n"
1976  "BDC\n"
1977  "<";
1978  int ge = end == ti.num_chars ? ti.num_glyphs : logClusters[end];
1979  for (int gs = logClusters[pos]; gs < ge; ++gs)
1980  *currentPage << toHex((ushort)ti.glyphs[gs].glyph, buf);
1981  *currentPage << "> Tj\n"
1982  "EMC\n";
1983  pos = end;
1984  } while (pos < ti.num_chars);
1985 #else
1986  qreal last_x = 0.;
1987  qreal last_y = 0.;
1988  for (int i = 0; i < glyphs.size(); ++i) {
1989  qreal x = positions[i].x.toReal();
1990  qreal y = positions[i].y.toReal();
1991  if (synthesized & QFontEngine::SynthesizedItalic)
1992  x += .3*y;
1993  x /= stretch;
1994  char buf[5];
1995  int g = font->addGlyph(glyphs[i]);
1996  *currentPage << x - last_x << last_y - y << "Td <"
1997  << QPdf::toHex((ushort)g, buf) << "> Tj\n";
1998  last_x = x;
1999  last_y = y;
2000  }
2001  if (synthesized & QFontEngine::SynthesizedBold) {
2002  *currentPage << stretch << (synthesized & QFontEngine::SynthesizedItalic
2003  ? "0 .3 -1 0 0 Tm\n"
2004  : "0 0 -1 0 0 Tm\n");
2005  *currentPage << "/Span << /ActualText <> >> BDC\n";
2006  last_x = 0.5*fe->lineThickness().toReal();
2007  last_y = 0.;
2008  for (int i = 0; i < glyphs.size(); ++i) {
2009  qreal x = positions[i].x.toReal();
2010  qreal y = positions[i].y.toReal();
2011  if (synthesized & QFontEngine::SynthesizedItalic)
2012  x += .3*y;
2013  x /= stretch;
2014  char buf[5];
2015  int g = font->addGlyph(glyphs[i]);
2016  *currentPage << x - last_x << last_y - y << "Td <"
2017  << QPdf::toHex((ushort)g, buf) << "> Tj\n";
2018  last_x = x;
2019  last_y = y;
2020  }
2021  *currentPage << "EMC\n";
2022  }
2023 #endif
2024 
2025  *currentPage << "ET\n";
2026 }
2027 
2029 {
2030  int w;
2031  int h;
2032  if (paperSize == QPrinter::Custom) {
2035  } else {
2036 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
2038  QRect r = cupsPaperRect;
2039  w = r.width();
2040  h = r.height();
2041  } else
2042 #endif
2043  {
2045  w = s.width;
2046  h = s.height;
2047  }
2048  w = qRound(w*resolution/72.);
2049  h = qRound(h*resolution/72.);
2050  }
2052  return QRect(0, 0, w, h);
2053  else
2054  return QRect(0, 0, h, w);
2055 }
2056 
2058 {
2059  if(fullPage)
2060  return paperRect();
2061 
2062  QRect r;
2063 
2064 #if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
2066  r = cupsPageRect;
2067  if (r == cupsPaperRect) {
2068  // if cups doesn't define any margins, give it at least approx 3.5 mm
2069  r = QRect(10, 10, r.width() - 20, r.height() - 20);
2070  }
2071  } else
2072 #endif
2073  {
2074  QPdf::PaperSize s;
2075  if (paperSize == QPrinter::Custom) {
2078  } else {
2080  }
2082  r = QRect(0, 0, s.width, s.height);
2083  else
2084  r = QRect(72/3, 72/3, s.width - 2*72/3, s.height - 2*72/3);
2085  }
2086 
2087  int x = qRound(r.left()*resolution/72.);
2088  int y = qRound(r.top()*resolution/72.);
2089  int w = qRound(r.width()*resolution/72.);
2090  int h = qRound(r.height()*resolution/72.);
2092  r = QRect(x, y, w, h);
2093  else
2094  r = QRect(y, x, h, w);
2095 
2096  if (hasCustomPageMargins) {
2098  qRound(topMargin*(resolution/72.)),
2099  -qRound(rightMargin*(resolution/72.)),
2100  -qRound(bottomMargin*(resolution/72.)));
2101  }
2102  return r;
2103 }
2104 
2105 #endif
2106 
ElementType type
the type of element
Definition: qpainterpath.h:81
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QPainterPath clipPath() const
Returns the currently clip as a path.
Definition: qpainter.cpp:2690
T qobject_cast(QObject *object)
Definition: qobject.h:375
virtual QFixed lineThickness() const
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
QFontEngine * fontEngine
PathFlags
Definition: qpdf_p.h:119
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
Definition: qpainterpath.h:392
QPaintEngine::DirtyFlags state() const
Returns a combination of flags identifying the set of properties that need to be updated when updatin...
Definition: qpaintengine.h:292
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
Definition: qpdf.cpp:1061
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
static QPrinterInfo defaultPrinter()
Returns the default printer on the system.
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
PaperSize paperSize(QPrinter::PaperSize paperSize)
Definition: qpdf.cpp:905
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
qreal opacity() const
Returns the opacity in the current paint engine state.
Definition: qpainter.cpp:9529
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QStringList cupsOptions
Definition: qpdf_p.h:281
const QColor & color() const
Returns the brush color.
Definition: qbrush.h:183
int availablePrintersCount() const
Definition: qcups.cpp:163
static int chunkSize()
Definition: qpdf_p.h:102
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
void setProperty(PrintEnginePropertyKey key, const QVariant &value)
Sets the print engine&#39;s property specified by key to the given value.
Definition: qpdf.cpp:1390
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qiodevice.cpp:590
virtual void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
int qCeil(qreal v)
Definition: qmath.h:63
void strokePath(const QPainterPath &path)
Definition: qpdf.cpp:796
bool fileBackingEnabled
Definition: qpdf_p.h:114
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qchar.h:251
QByteArray generateMatrix(const QTransform &matrix)
Definition: qpdf.cpp:334
#define it(className, varName)
QPrinter::Orientation orientation
Definition: qpdf_p.h:276
const QChar * chars
static int maxMemorySize()
Definition: qpdf_p.h:101
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QTransform matrix
Definition: qpdf_p.h:139
QPaintEngineState * state
Definition: qpaintengine.h:239
void setDashOffset(qreal offset)
Definition: qstroker_p.h:265
Qt::PenStyle style() const
Returns the pen style.
Definition: qpen.cpp:428
int qFloor(qreal v)
Definition: qmath.h:73
int addGlyph(int index)
qreal width() const
Returns the width.
Definition: qsize.h:284
virtual void drawRects(const QRect *rects, int rectCount)
The default implementation converts the first rectCount rectangles in the buffer rects to a QRectF an...
PrinterMode
This enum describes the mode the printer should work in.
Definition: qprinter.h:70
void setupGraphicsState(QPaintEngine::DirtyFlags flags)
Definition: qpdf.cpp:1193
T & first()
Returns a reference to the first item in the vector.
Definition: qvector.h:260
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
RenderFlags flags
QTransform transform() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9377
The QTemporaryFile class is an I/O device that operates on temporary files.
void setStrokeWidth(qfixed width)
Definition: qstroker_p.h:212
QString & prepend(QChar c)
Definition: qstring.h:261
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal height() const
Returns the height.
Definition: qsize.h:287
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
FillRule
Definition: qnamespace.h:1485
T1 first
Definition: qpair.h:65
virtual int synthesized() const
QPainterPath subtracted(const QPainterPath &r) const
Returns a path which is p&#39;s fill area subtracted from this path&#39;s fill area.
QPainterPath intersected(const QPainterPath &r) const
Returns a path which is the intersection of this path&#39;s fill area and p&#39;s fill area.
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
T2 second
Definition: qpair.h:66
Orientation
This enum type (not to be confused with Orientation) is used to specify each page&#39;s orientation...
Definition: qprinter.h:78
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
QString selectionOption
Definition: qpdf_p.h:266
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has type() List or StringList ; otherwise return...
Definition: qvariant.cpp:2751
QPaintDevice * pdev
Definition: qpdf_p.h:256
QString cupsTempFile
Definition: qpdf_p.h:290
bool open()
A QTemporaryFile will always be opened in QIODevice::ReadWrite mode, this allows easy access to the d...
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
void setJoinStyle(Qt::PenJoinStyle style)
Definition: qstroker_p.h:219
quint16 u
const unsigned short * logClusters
QVariant property(PrintEnginePropertyKey key) const
Returns the print engine&#39;s property specified by key.
Definition: qpdf.cpp:1478
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QByteArray generateDashes(const QPen &pen)
Definition: qpdf.cpp:348
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
bool isClipEnabled() const
Returns whether clipping is enabled or not in the current paint engine state.
Definition: qpainter.cpp:9473
The QString class provides a Unicode character string.
Definition: qstring.h:83
virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
Reimplement this virtual function to draw the polygon defined by the pointCount first points in point...
QPdfBaseEnginePrivate(QPrinter::PrinterMode m)
Definition: qpdf.cpp:1595
const char * paperSizeToString(QPrinter::PaperSize paperSize)
Definition: qpdf.cpp:912
void setDashPattern(const QVector< qfixed > &dashPattern)
Definition: qstroker_p.h:262
const cups_dest_t * availablePrinters() const
Definition: qcups.cpp:168
QVector< uint > fonts
Definition: qpdf_p.h:170
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
ByteStream(bool fileBacking=false)
Definition: qpdf.cpp:150
static bool isAvailable()
Definition: qcups.cpp:216
#define Q_D(Class)
Definition: qglobal.h:2482
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i.e.
Definition: qiodevice.cpp:711
static const uint base
Definition: qurl.cpp:268
virtual Type type() const =0
The QSizeF class defines the size of a two-dimensional object using floating point precision...
Definition: qsize.h:202
void setPen()
Definition: qpdf.cpp:1284
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
QVector< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition: qpen.cpp:466
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
static const char *const psToStr[QPrinter::NPaperSize+1]
Definition: qpdf.cpp:897
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
Reimplement this virtual function to draw the polygon defined by the pointCount first points in point...
Definition: qpdf.cpp:1019
void setCubicToHook(qStrokerCubicToHook cubicToHook)
Definition: qstroker_p.h:150
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QSizeF customPaperSize
Definition: qpdf_p.h:285
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
QStroker basicStroker
Definition: qpdf_p.h:142
#define Q_Q(Class)
Definition: qglobal.h:2483
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
const char * qt_real_to_string(qreal val, char *buf)
Definition: qpdf.cpp:63
void closePrintDevice()
Definition: qpdf.cpp:1808
void drawRects(const QRectF *rects, int rectCount)
Draws the first rectCount rectangles in the buffer rects.
Definition: qpdf.cpp:984
void setPen(const QPen &pen)
Definition: qpdf.cpp:765
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
QGradientStops stops() const
Returns the stop points for this gradient.
Definition: qbrush.cpp:1520
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
static void moveToHook(qfixed x, qfixed y, void *data)
Definition: qpdf.cpp:716
bool newPage()
Instructs the print engine to start a new page.
Definition: qpdf.cpp:1340
QGlyphLayout glyphs
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
friend class const_iterator
Definition: qlist.h:264
static char toHex(quint8 c)
Definition: qurl.cpp:4440
unsigned char uchar
Definition: qglobal.h:994
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
DuplexMode
This enum is used to indicate whether printing will occur on one or both sides of each sheet of paper...
Definition: qprinter.h:139
void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
Definition: qpdf.cpp:1094
QPainter * painter() const
Returns the paint engine&#39;s painter.
bool begin(QPaintDevice *pdev)
Reimplement this function to initialise your paint engine when painting is to start on the paint devi...
Definition: qpdf.cpp:1617
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QBrush brush() const
Returns the brush in the current paint engine state.
Definition: qpainter.cpp:9273
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
#define Q_MM(n)
Definition: qpdf.cpp:894
void strokePath(const QPainterPath &path, void *data, const QTransform &matrix)
Convenience function that decomposes path into begin(), moveTo(), lineTo(), curevTo() and end() calls...
Definition: qstroker.cpp:242
bool end()
Reimplement this function to finish painting on the current paint device.
Definition: qpdf.cpp:1632
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
Definition: qpainter.cpp:9396
QPointF brushOrigin() const
Returns the brush origin in the current paint engine state.
Definition: qpainter.cpp:9287
QRect pageRect() const
Definition: qpdf.cpp:2057
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition: qpen.cpp:840
int printFile(const char *printerName, const char *filename, const char *title, int num_options, cups_option_t *options)
Definition: qcups.cpp:394
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static const QCssKnownValue positions[NumKnownPositionModes - 1]
Definition: qcssparser.cpp:329
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
bool first
Definition: qpdf_p.h:138
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
const char * name
The QPrinter class is a paint device that paints on a printer.
Definition: qprinter.h:66
void setCapStyle(Qt::PenCapStyle capStyle)
Definition: qstroker_p.h:215
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void adjust(int x1, int y1, int x2, int y2)
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition: qrect.h:434
QPdf::Stroker stroker
Definition: qpdf_p.h:240
bool fileBackingActive
Definition: qpdf_p.h:115
static const char * pattern_for_brush[]
Definition: qpdf.cpp:371
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
Q_CORE_EXPORT void qWarning(const char *,...)
QPoint map(const QPoint &p) const
Creates and returns a QPoint object that is a copy of the given point, mapped into the coordinate sys...
Internal QTextItem.
int metric(QPaintDevice::PaintDeviceMetric metricType) const
Returns the metric for the given id.
Definition: qpdf.cpp:1351
static int qt_safe_dup2(int oldfd, int newfd, int flags=FD_CLOEXEC)
Definition: qcore_unix_p.h:251
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
uint requestObject()
Definition: qpdf_p.h:231
static int qt_safe_pipe(int pipefd[2], int flags=0)
Definition: qcore_unix_p.h:191
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
QPair< int, QString > tempFd()
Definition: qcups.cpp:386
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
Definition: qregion.cpp:1160
QByteArray ba
Definition: qpdf_p.h:113
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QString printerName
Definition: qpdf_p.h:264
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Definition: qpainter.cpp:9457
virtual FaceId faceId() const
__int64 qint64
Definition: qglobal.h:942
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
bool handleDirty
Definition: qpdf_p.h:116
Qt::BrushStyle style() const
Returns the brush style.
Definition: qbrush.h:182
QPrinter::DuplexMode duplex
Definition: qpdf_p.h:269
bool isOpaque() const
Returns true if the brush is fully opaque otherwise false.
Definition: qbrush.cpp:910
QIODevice * stream()
Definition: qpdf.cpp:225
QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size)
Definition: qprinter.cpp:2615
static void closeAllOpenFds()
Definition: qpdf.cpp:1645
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
QPointF start() const
Returns the start point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1796
Q_CORE_EXPORT bool qIsNaN(double d)
Returns true if the double {d} is not a number (NaN).
Definition: qnumeric.cpp:55
QHash< QFontEngine::FaceId, QFontSubset * > fonts
Definition: qpdf_p.h:254
QString outputFileName
Definition: qpdf_p.h:263
qreal pixelSize
Definition: qfont_p.h:90
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
bool hasCustomPageMargins
Definition: qpdf_p.h:286
const char * toHex(ushort u, char *buffer)
Definition: qpdf.cpp:862
Spread
Specifies how the area outside the gradient area should be filled.
Definition: qbrush.h:213
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
int length() const
Same as size().
Definition: qbytearray.h:356
void drawPoints(const QPointF *points, int pointCount)
Draws the first pointCount points in the buffer points.
Definition: qpdf.cpp:949
QSizeF toSizeF() const
Returns the variant as a QSizeF if the variant has type() SizeF ; otherwise returns an invalid QSizeF...
Definition: qvariant.cpp:2447
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
The QPrinterInfo class gives access to information about existing printers.
Definition: qprinterinfo.h:58
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
Q_GUI_EXPORT_INLINE int qGray(int r, int g, int b)
Definition: qrgb.h:75
QString printerName() const
Returns the name of the printer.
Q_CORE_EXPORT void qFatal(const char *,...)
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
virtual void drawTextItem(const QPointF &p, const QTextItemInt &ti)
Definition: qpdf.cpp:1909
void prepareBuffer()
Definition: qpdf.cpp:244
QPrinter::PaperSize paperSize
Definition: qpdf_p.h:277
#define PPK_CupsStringPageSize
Definition: qpdf_p.h:73
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
The QLinearGradient class is used in combination with QBrush to specify a linear gradient brush...
Definition: qbrush.h:280
static void cubicToHook(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey, void *data)
Definition: qpdf.cpp:735
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
unsigned short ushort
Definition: qglobal.h:995
QRect toRect() const
Returns the variant as a QRect if the variant has type() Rect ; otherwise returns an invalid QRect...
Definition: qvariant.cpp:2416
void clear()
Definition: qpdf.cpp:232
Q_GUI_EXPORT int qt_defaultDpi()
Definition: qfont.cpp:240
qreal miterLimit() const
Returns the miter limit of the pen.
Definition: qpen.cpp:589
void setMiterLimit(qfixed length)
Definition: qstroker_p.h:223
PaperSize
This enum type specifies what paper size QPrinter should use.
Definition: qprinter.h:91
QString printProgram
Definition: qpdf_p.h:265
int last_x
int key
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
QByteArray patternForBrush(const QBrush &b)
Definition: qpdf.cpp:524
void resize(int size)
Sets the size of the byte array to size bytes.
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static void lineToHook(qfixed x, qfixed y, void *data)
Definition: qpdf.cpp:727
bool openPrintDevice()
Definition: qpdf.cpp:1666
ColorMode
This enum type is used to indicate whether QPrinter should print in color or not. ...
Definition: qprinter.h:100
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
#define Q_AUTOTEST_EXPORT
Definition: qglobal.h:1510
virtual bool reset()
Seeks to the start of input for random-access devices.
Definition: qiodevice.cpp:732
Spread spread() const
Returns the spread method use by this gradient.
Definition: qbrush.h:235
qreal toReal() const
Definition: qfixed_p.h:77
uint stretch
Definition: qfont_p.h:98
void constructor_helper(QIODevice *dev)
QIODevice * outDevice
Definition: qpdf_p.h:259
bool isNull() const
Returns whether this QPrinterInfo object holds a printer definition.
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
bool contains(const T &t) const
Returns true if the vector contains an occurrence of value; otherwise returns false.
Definition: qvector.h:731
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
QPdfPage * currentPage
Definition: qpdf_p.h:239
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
Definition: qiodevice.cpp:570
Definition: qpdf.cpp:140
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
PageOrder
This enum type is used by QPrinter to tell the application program how to print.
Definition: qprinter.h:97
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
Definition: qpainter.cpp:9443
qreal dashOffset() const
Returns the dash offset for the pen.
Definition: qpen.cpp:547
#define PPK_CupsPaperRect
Definition: qpdf_p.h:72
The QPaintEngineState class provides information about the active paint engine&#39;s current state...
Definition: qpaintengine.h:289
void setLineToHook(qStrokerLineToHook lineToHook)
Definition: qstroker_p.h:149
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
bool cosmeticPen
Definition: qpdf_p.h:140
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis...
Definition: qtransform.cpp:462
#define PPK_CupsPageRect
Definition: qpdf_p.h:71
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
void drawLines(const QLineF *lines, int lineCount)
The default implementation splits the list of lines in lines into lineCount separate calls to drawPat...
Definition: qpdf.cpp:967
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
const char * qt_int_to_string(int val, char *buf)
Definition: qpdf.cpp:115
QIODevice * dev
Definition: qpdf_p.h:112
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
QRect paperRect() const
Definition: qpdf.cpp:2028
QString cupsStringPageSize
Definition: qpdf_p.h:284
void setMoveToHook(qStrokerMoveToHook moveToHook)
Definition: qstroker_p.h:148
FileError error() const
Returns the file error status.
Definition: qfile.cpp:1984
QFontDef fontDef
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
virtual void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
#define PPK_CupsOptions
Definition: qpdf_p.h:70
int last_y
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
QRegion alphaClipping() const
QByteArray generatePath(const QPainterPath &path, const QTransform &matrix, PathFlags flags)
Definition: qpdf.cpp:272
static const KeyPair *const end
QStrokerOps * stroker
Definition: qpdf_p.h:144
ByteStream & operator<<(char chr)
Definition: qpdf.cpp:164
ByteStream * stream
Definition: qpdf_p.h:137
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
Definition: qpdf.cpp:1131
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
qreal qfixed
Definition: qstroker_p.h:100
static pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
Definition: qcore_unix_p.h:333
#define INT_MAX
const int object_id
Definition: qfontsubset_p.h:84
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
void clear()
Clears the contents of the byte array and makes it empty.
virtual void setBrush()=0
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
static int cupsVersion()
Definition: qcups_p.h:75
int open(const char *, int,...)
QPdfBaseEngine(QPdfBaseEnginePrivate &d, PaintEngineFeatures f)
Definition: qpdf.cpp:919
int size() const
QPointF finalStop() const
Returns the final stop point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1856
PaperSource
This enum type specifies what paper source QPrinter is to use.
Definition: qprinter.h:103
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
QByteArray ascii85Encode(const QByteArray &input)
Definition: qpdf.cpp:806
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
PrintEnginePropertyKey
This enum is used to communicate properties between the print engine and QPrinter.
Definition: qprintengine.h:60
void updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
Definition: qpdf.cpp:1236
ClipOperation
Definition: qnamespace.h:1495
#define QT_CLOSE
Definition: qcore_unix_p.h:304
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
QDashStroker dashStroker
Definition: qpdf_p.h:143