Qt 4.8
qpaintengineex.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 
42 #include "qpaintengineex_p.h"
43 #include "qpainter_p.h"
44 #include "qstroker_p.h"
45 #include "qbezier_p.h"
46 #include <private/qpainterpath_p.h>
47 #include <private/qfontengine_p.h>
48 #include <private/qstatictext_p.h>
49 
50 #include <qvarlengtharray.h>
51 #include <qdebug.h>
52 
53 
55 
56 /*******************************************************************************
57  *
58  * class QVectorPath
59  *
60  */
62 {
64  CacheEntry *e = m_cache;
65  while (e) {
66  if (e->data)
67  e->cleanup(e->engine, e->data);
68  CacheEntry *n = e->next;
69  delete e;
70  e = n;
71  }
72  }
73 }
74 
75 
77 {
80 
81  if (m_count == 0) {
85  }
86  Q_ASSERT(m_points && m_count > 0);
87 
88  const qreal *pts = m_points;
89  m_cp_rect.x1 = m_cp_rect.x2 = *pts;
90  ++pts;
91  m_cp_rect.y1 = m_cp_rect.y2 = *pts;
92  ++pts;
93 
94  const qreal *epts = m_points + (m_count << 1);
95  while (pts < epts) {
96  qreal x = *pts;
97  if (x < m_cp_rect.x1) m_cp_rect.x1 = x;
98  else if (x > m_cp_rect.x2) m_cp_rect.x2 = x;
99  ++pts;
100 
101  qreal y = *pts;
102  if (y < m_cp_rect.y1) m_cp_rect.y1 = y;
103  else if (y > m_cp_rect.y2) m_cp_rect.y2 = y;
104  ++pts;
105  }
106 
109 }
110 
111 
114  Q_ASSERT(!lookupCacheData(engine));
115  if ((m_hints & IsCachedHint) == 0) {
116  m_cache = 0;
118  }
119  CacheEntry *e = new CacheEntry;
120  e->engine = engine;
121  e->data = data;
122  e->cleanup = cleanup;
123  e->next = m_cache;
124  m_cache = e;
125  return m_cache;
126 }
127 
128 
130 {
131  Q_ASSERT(path.d_func());
132  return path.d_func()->vectorPath();
133 }
134 
135 #ifndef QT_NO_DEBUG_STREAM
137 {
138  QRectF rf = path.controlPointRect();
139  s << "QVectorPath(size:" << path.elementCount()
140  << " hints:" << hex << path.hints()
141  << rf << ')';
142  return s;
143 }
144 #endif
145 
146 /*******************************************************************************
147  *
148  * class QPaintEngineExPrivate:
149  *
150  */
151 
152 
154  StrokeHandler(int reserve) : pts(reserve), types(reserve) {}
157 };
158 
159 
161  : dasher(&stroker),
162  strokeHandler(0),
163  activeStroker(0),
164  strokerPen(Qt::NoPen)
165 {
166 }
167 
168 
170 {
171  delete strokeHandler;
172 }
173 
174 
176 {
178 
179  QPainter *p = q->painter();
180  if (!p || !p->d_ptr)
181  return;
182 
184 
185  QTransform transform = q->state()->matrix;
186 
187  for (int i = 0; i < clipInfo.size(); ++i) {
188  const QPainterClipInfo &info = clipInfo.at(i);
189 
190  if (info.matrix != q->state()->matrix) {
191  q->state()->matrix = info.matrix;
192  q->transformChanged();
193  }
194 
195  switch (info.clipType) {
197  q->clip(info.region, info.operation);
198  break;
200  q->clip(info.path, info.operation);
201  break;
203  q->clip(info.rect, info.operation);
204  break;
206  qreal right = info.rectf.x() + info.rectf.width();
207  qreal bottom = info.rectf.y() + info.rectf.height();
208  qreal pts[] = { info.rectf.x(), info.rectf.y(),
209  right, info.rectf.y(),
210  right, bottom,
211  info.rectf.x(), bottom };
213  q->clip(vp, info.operation);
214  break;
215  }
216  }
217  }
218 
219  if (transform != q->state()->matrix) {
220  q->state()->matrix = transform;
221  q->transformChanged();
222  }
223 }
224 
225 
227 {
228  Q_Q(const QPaintEngineEx);
229 
230  QPainter *p = q->painter();
231  if (!p || !p->d_ptr)
232  return false;
233 
235 
236  return !clipInfo.isEmpty();
237 }
238 
239 /*******************************************************************************
240  *
241  * class QPaintEngineEx:
242  *
243  */
244 
250 
254 
258 
261  QPainterPath::CurveToDataElement
262 };
263 
280  QPainterPath::MoveToElement, QPainterPath::LineToElement
281 };
282 
316 };
317 
318 
336  QPainterPath::CurveToDataElement
337 };
338 
339 
340 
341 static void qpaintengineex_moveTo(qreal x, qreal y, void *data) {
342  ((StrokeHandler *) data)->pts.add(x);
343  ((StrokeHandler *) data)->pts.add(y);
344  ((StrokeHandler *) data)->types.add(QPainterPath::MoveToElement);
345 }
346 
347 static void qpaintengineex_lineTo(qreal x, qreal y, void *data) {
348  ((StrokeHandler *) data)->pts.add(x);
349  ((StrokeHandler *) data)->pts.add(y);
350  ((StrokeHandler *) data)->types.add(QPainterPath::LineToElement);
351 }
352 
353 static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal ex, qreal ey, void *data) {
354  ((StrokeHandler *) data)->pts.add(c1x);
355  ((StrokeHandler *) data)->pts.add(c1y);
356  ((StrokeHandler *) data)->types.add(QPainterPath::CurveToElement);
357 
358  ((StrokeHandler *) data)->pts.add(c2x);
359  ((StrokeHandler *) data)->pts.add(c2y);
360  ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
361 
362  ((StrokeHandler *) data)->pts.add(ex);
363  ((StrokeHandler *) data)->pts.add(ey);
364  ((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
365 }
366 
368  : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures)
369 {
370  extended = true;
371 }
372 
374  : QPaintEngine(data, AllFeatures)
375 {
376  extended = true;
377 }
378 
380 {
381  if (!orig)
382  return new QPainterState;
383  return new QPainterState(orig);
384 }
385 
386 Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
387 
388 void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
389 {
390 #ifdef QT_DEBUG_DRAW
391  qDebug() << "QPaintEngineEx::stroke()" << pen;
392 #endif
393 
395 
396  if (path.isEmpty())
397  return;
398 
399  if (!d->strokeHandler) {
400  d->strokeHandler = new StrokeHandler(path.elementCount()+4);
401  d->stroker.setMoveToHook(qpaintengineex_moveTo);
402  d->stroker.setLineToHook(qpaintengineex_lineTo);
403  d->stroker.setCubicToHook(qpaintengineex_cubicTo);
404  }
405 
406  if (!qpen_fast_equals(pen, d->strokerPen)) {
407  d->strokerPen = pen;
408  d->stroker.setJoinStyle(pen.joinStyle());
409  d->stroker.setCapStyle(pen.capStyle());
410  d->stroker.setMiterLimit(pen.miterLimit());
411  qreal penWidth = pen.widthF();
412  if (penWidth == 0)
413  d->stroker.setStrokeWidth(1);
414  else
415  d->stroker.setStrokeWidth(penWidth);
416 
417  Qt::PenStyle style = pen.style();
418  if (style == Qt::SolidLine) {
419  d->activeStroker = &d->stroker;
420  } else if (style == Qt::NoPen) {
421  d->activeStroker = 0;
422  } else {
423  d->dasher.setDashPattern(pen.dashPattern());
424  d->dasher.setDashOffset(pen.dashOffset());
425  d->activeStroker = &d->dasher;
426  }
427  }
428 
429  if (!d->activeStroker) {
430  return;
431  }
432 
433  if (pen.style() > Qt::SolidLine) {
434  if (pen.isCosmetic()) {
435  d->activeStroker->setClipRect(d->exDeviceRect);
436  } else {
437  QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect));
438  d->activeStroker->setClipRect(clipRect);
439  }
440  }
441 
442  const QPainterPath::ElementType *types = path.elements();
443  const qreal *points = path.points();
444  int pointCount = path.elementCount();
445 
446  const qreal *lastPoint = points + (pointCount<<1);
447 
448  d->strokeHandler->types.reset();
449  d->strokeHandler->pts.reset();
450 
451  // Some engines might decide to optimize for the non-shape hint later on...
453 
454  if (path.elementCount() > 2)
456 
457  if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin)
459 
460  // ### Perspective Xforms are currently not supported...
461  if (!pen.isCosmetic()) {
462  // We include cosmetic pens in this case to avoid having to
463  // change the current transform. Normal transformed,
464  // non-cosmetic pens will be transformed as part of fill
465  // later, so they are also covered here..
466  d->activeStroker->setCurveThresholdFromTransform(state()->matrix);
467  d->activeStroker->begin(d->strokeHandler);
468  if (types) {
469  while (points < lastPoint) {
470  switch (*types) {
472  d->activeStroker->moveTo(points[0], points[1]);
473  points += 2;
474  ++types;
475  break;
477  d->activeStroker->lineTo(points[0], points[1]);
478  points += 2;
479  ++types;
480  break;
482  d->activeStroker->cubicTo(points[0], points[1],
483  points[2], points[3],
484  points[4], points[5]);
485  points += 6;
486  types += 3;
488  break;
489  default:
490  break;
491  }
492  }
493  if (path.hasImplicitClose())
494  d->activeStroker->lineTo(path.points()[0], path.points()[1]);
495 
496  } else {
497  d->activeStroker->moveTo(points[0], points[1]);
498  points += 2;
499  while (points < lastPoint) {
500  d->activeStroker->lineTo(points[0], points[1]);
501  points += 2;
502  }
503  if (path.hasImplicitClose())
504  d->activeStroker->lineTo(path.points()[0], path.points()[1]);
505  }
506  d->activeStroker->end();
507 
508  if (!d->strokeHandler->types.size()) // an empty path...
509  return;
510 
511  QVectorPath strokePath(d->strokeHandler->pts.data(),
512  d->strokeHandler->types.size(),
513  d->strokeHandler->types.data(),
514  flags);
515  fill(strokePath, pen.brush());
516  } else {
517  // For cosmetic pens we need a bit of trickery... We to process xform the input points
518  if (state()->matrix.type() >= QTransform::TxProject) {
519  QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath());
520  d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform());
521  } else {
522  d->activeStroker->setCurveThresholdFromTransform(QTransform());
523  d->activeStroker->begin(d->strokeHandler);
524  if (types) {
525  while (points < lastPoint) {
526  switch (*types) {
528  QPointF pt = (*(QPointF *) points) * state()->matrix;
529  d->activeStroker->moveTo(pt.x(), pt.y());
530  points += 2;
531  ++types;
532  break;
533  }
535  QPointF pt = (*(QPointF *) points) * state()->matrix;
536  d->activeStroker->lineTo(pt.x(), pt.y());
537  points += 2;
538  ++types;
539  break;
540  }
542  QPointF c1 = ((QPointF *) points)[0] * state()->matrix;
543  QPointF c2 = ((QPointF *) points)[1] * state()->matrix;
544  QPointF e = ((QPointF *) points)[2] * state()->matrix;
545  d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
546  points += 6;
547  types += 3;
549  break;
550  }
551  default:
552  break;
553  }
554  }
555  if (path.hasImplicitClose()) {
556  QPointF pt = * ((QPointF *) path.points()) * state()->matrix;
557  d->activeStroker->lineTo(pt.x(), pt.y());
558  }
559 
560  } else {
561  QPointF p = ((QPointF *)points)[0] * state()->matrix;
562  d->activeStroker->moveTo(p.x(), p.y());
563  points += 2;
564  while (points < lastPoint) {
565  QPointF p = ((QPointF *)points)[0] * state()->matrix;
566  d->activeStroker->lineTo(p.x(), p.y());
567  points += 2;
568  }
569  if (path.hasImplicitClose())
570  d->activeStroker->lineTo(p.x(), p.y());
571  }
572  d->activeStroker->end();
573  }
574 
575  QVectorPath strokePath(d->strokeHandler->pts.data(),
576  d->strokeHandler->types.size(),
577  d->strokeHandler->types.data(),
578  flags);
579 
580  QTransform xform = state()->matrix;
581  state()->matrix = QTransform();
583 
584  QBrush brush = pen.brush();
585  if (qbrush_style(brush) != Qt::SolidPattern)
586  brush.setTransform(brush.transform() * xform);
587 
588  fill(strokePath, brush);
589 
590  state()->matrix = xform;
592  }
593 }
594 
596 {
597  const QBrush &brush = state()->brush;
598  if (qbrush_style(brush) != Qt::NoBrush)
599  fill(path, brush);
600 
601  const QPen &pen = state()->pen;
602  if (qpen_style(pen) != Qt::NoPen && qbrush_style(qpen_brush(pen)) != Qt::NoBrush)
603  stroke(path, pen);
604 }
605 
606 
608 {
609  qreal right = r.x() + r.width();
610  qreal bottom = r.y() + r.height();
611  qreal pts[] = { qreal(r.x()), qreal(r.y()),
612  right, qreal(r.y()),
613  right, bottom,
614  qreal(r.x()), bottom,
615  qreal(r.x()), qreal(r.y()) };
617  clip(vp, op);
618 }
619 
621 {
622  if (region.rectCount() == 1)
623  clip(region.boundingRect(), op);
624 
625  QVector<QRect> rects = region.rects();
626  if (rects.size() <= 32) {
627  qreal pts[2*32*4];
628  int pos = 0;
629  for (QVector<QRect>::const_iterator i = rects.constBegin(); i != rects.constEnd(); ++i) {
630  qreal x1 = i->x();
631  qreal y1 = i->y();
632  qreal x2 = i->x() + i->width();
633  qreal y2 = i->y() + i->height();
634 
635  pts[pos++] = x1;
636  pts[pos++] = y1;
637 
638  pts[pos++] = x2;
639  pts[pos++] = y1;
640 
641  pts[pos++] = x2;
642  pts[pos++] = y2;
643 
644  pts[pos++] = x1;
645  pts[pos++] = y2;
646  }
647  QVectorPath vp(pts, rects.size() * 4, qpaintengineex_rect4_types_32);
648  clip(vp, op);
649  } else {
650  QVarLengthArray<qreal> pts(rects.size() * 2 * 4);
652  int ppos = 0;
653  int tpos = 0;
654 
655  for (QVector<QRect>::const_iterator i = rects.constBegin(); i != rects.constEnd(); ++i) {
656  qreal x1 = i->x();
657  qreal y1 = i->y();
658  qreal x2 = i->x() + i->width();
659  qreal y2 = i->y() + i->height();
660 
661  pts[ppos++] = x1;
662  pts[ppos++] = y1;
663 
664  pts[ppos++] = x2;
665  pts[ppos++] = y1;
666 
667  pts[ppos++] = x2;
668  pts[ppos++] = y2;
669 
670  pts[ppos++] = x1;
671  pts[ppos++] = y2;
672 
677  }
678 
679  QVectorPath vp(pts.data(), rects.size() * 4, types.data());
680  clip(vp, op);
681  }
682 
683 }
684 
686 {
687  if (path.isEmpty()) {
688  QVectorPath vp(0, 0);
689  clip(vp, op);
690  } else {
691  clip(qtVectorPathForPath(path), op);
692  }
693 }
694 
695 void QPaintEngineEx::fillRect(const QRectF &r, const QBrush &brush)
696 {
697  qreal pts[] = { r.x(), r.y(), r.x() + r.width(), r.y(),
698  r.x() + r.width(), r.y() + r.height(), r.x(), r.y() + r.height() };
700  fill(vp, brush);
701 }
702 
703 void QPaintEngineEx::fillRect(const QRectF &r, const QColor &color)
704 {
705  fillRect(r, QBrush(color));
706 }
707 
708 void QPaintEngineEx::drawRects(const QRect *rects, int rectCount)
709 {
710  for (int i=0; i<rectCount; ++i) {
711  const QRect &r = rects[i];
712  // ### Is there a one off here?
713  qreal right = r.x() + r.width();
714  qreal bottom = r.y() + r.height();
715  qreal pts[] = { qreal(r.x()), qreal(r.y()),
716  right, qreal(r.y()),
717  right, bottom,
718  qreal(r.x()), bottom,
719  qreal(r.x()), qreal(r.y()) };
721  draw(vp);
722  }
723 }
724 
725 void QPaintEngineEx::drawRects(const QRectF *rects, int rectCount)
726 {
727  for (int i=0; i<rectCount; ++i) {
728  const QRectF &r = rects[i];
729  qreal right = r.x() + r.width();
730  qreal bottom = r.y() + r.height();
731  qreal pts[] = { r.x(), r.y(),
732  right, r.y(),
733  right, bottom,
734  r.x(), bottom,
735  r.x(), r.y() };
737  draw(vp);
738  }
739 }
740 
741 
742 void QPaintEngineEx::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
743  Qt::SizeMode mode)
744 {
745  qreal x1 = rect.left();
746  qreal x2 = rect.right();
747  qreal y1 = rect.top();
748  qreal y2 = rect.bottom();
749 
750  if (mode == Qt::RelativeSize) {
751  xRadius = xRadius * rect.width() / qreal(200.);
752  yRadius = yRadius * rect.height() / qreal(200.);
753  }
754 
755  xRadius = qMin(xRadius, rect.width() / 2);
756  yRadius = qMin(yRadius, rect.height() / 2);
757 
758  qreal pts[] = {
759  x1 + xRadius, y1, // MoveTo
760  x2 - xRadius, y1, // LineTo
761  x2 - (1 - KAPPA) * xRadius, y1, // CurveTo
762  x2, y1 + (1 - KAPPA) * yRadius,
763  x2, y1 + yRadius,
764  x2, y2 - yRadius, // LineTo
765  x2, y2 - (1 - KAPPA) * yRadius, // CurveTo
766  x2 - (1 - KAPPA) * xRadius, y2,
767  x2 - xRadius, y2,
768  x1 + xRadius, y2, // LineTo
769  x1 + (1 - KAPPA) * xRadius, y2, // CurveTo
770  x1, y2 - (1 - KAPPA) * yRadius,
771  x1, y2 - yRadius,
772  x1, y1 + yRadius, // LineTo
773  x1, y1 + (1 - KAPPA) * yRadius, // CurveTo
774  x1 + (1 - KAPPA) * xRadius, y1,
775  x1 + xRadius, y1
776  };
777 
779  draw(path);
780 }
781 
782 
783 
784 void QPaintEngineEx::drawLines(const QLine *lines, int lineCount)
785 {
786  int elementCount = lineCount << 1;
787  while (elementCount > 0) {
788  int count = qMin(elementCount, 32);
789 
790  qreal pts[64];
791  int count2 = count<<1;
792 #ifdef Q_WS_MAC
793  for (int i=0; i<count2; i+=2) {
794  pts[i] = ((int *) lines)[i+1];
795  pts[i+1] = ((int *) lines)[i];
796  }
797 #else
798  for (int i=0; i<count2; ++i)
799  pts[i] = ((int *) lines)[i];
800 #endif
801 
803  stroke(path, state()->pen);
804 
805  elementCount -= 32;
806  lines += 16;
807  }
808 }
809 
810 void QPaintEngineEx::drawLines(const QLineF *lines, int lineCount)
811 {
812  int elementCount = lineCount << 1;
813  while (elementCount > 0) {
814  int count = qMin(elementCount, 32);
815 
816  QVectorPath path((qreal *) lines, count, qpaintengineex_line_types_16,
818  stroke(path, state()->pen);
819 
820  elementCount -= 32;
821  lines += 16;
822  }
823 }
824 
826 {
827  qreal pts[26]; // QPointF[13] without constructors...
828  union {
829  qreal *ptr;
830  QPointF *points;
831  } x;
832  x.ptr = pts;
833 
834  int point_count = 0;
835  x.points[0] = qt_curves_for_arc(r, 0, -360, x.points + 1, &point_count);
837  draw(vp);
838 }
839 
841 {
842  drawEllipse(QRectF(r));
843 }
844 
846 {
847  if (!path.isEmpty())
848  draw(qtVectorPathForPath(path));
849 }
850 
851 
852 void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount)
853 {
854  QPen pen = state()->pen;
855  if (pen.capStyle() == Qt::FlatCap)
857 
858  if (pen.brush().isOpaque()) {
859  while (pointCount > 0) {
860  int count = qMin(pointCount, 16);
861  qreal pts[64];
862  int oset = -1;
863  for (int i=0; i<count; ++i) {
864  pts[++oset] = points[i].x();
865  pts[++oset] = points[i].y();
866  pts[++oset] = points[i].x() + 1/qreal(63.);
867  pts[++oset] = points[i].y();
868  }
870  stroke(path, pen);
871  pointCount -= 16;
872  points += 16;
873  }
874  } else {
875  for (int i=0; i<pointCount; ++i) {
876  qreal pts[] = { points[i].x(), points[i].y(), points[i].x() + 1/qreal(63.), points[i].y() };
877  QVectorPath path(pts, 2, 0);
878  stroke(path, pen);
879  }
880  }
881 }
882 
883 void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
884 {
885  QPen pen = state()->pen;
886  if (pen.capStyle() == Qt::FlatCap)
888 
889  if (pen.brush().isOpaque()) {
890  while (pointCount > 0) {
891  int count = qMin(pointCount, 16);
892  qreal pts[64];
893  int oset = -1;
894  for (int i=0; i<count; ++i) {
895  pts[++oset] = points[i].x();
896  pts[++oset] = points[i].y();
897  pts[++oset] = points[i].x() + 1/qreal(63.);
898  pts[++oset] = points[i].y();
899  }
901  stroke(path, pen);
902  pointCount -= 16;
903  points += 16;
904  }
905  } else {
906  for (int i=0; i<pointCount; ++i) {
907  qreal pts[] = { qreal(points[i].x()), qreal(points[i].y()),
908  qreal(points[i].x() +1/qreal(63.)), qreal(points[i].y()) };
909  QVectorPath path(pts, 2, 0);
910  stroke(path, pen);
911  }
912  }
913 }
914 
915 
916 void QPaintEngineEx::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
917 {
918  QVectorPath path((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
919 
920  if (mode == PolylineMode)
921  stroke(path, state()->pen);
922  else
923  draw(path);
924 }
925 
926 void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
927 {
928  int count = pointCount<<1;
929  QVarLengthArray<qreal> pts(count);
930 
931 #ifdef Q_WS_MAC
932  for (int i=0; i<count; i+=2) {
933  pts[i] = ((int *) points)[i+1];
934  pts[i+1] = ((int *) points)[i];
935  }
936 #else
937  for (int i=0; i<count; ++i)
938  pts[i] = ((int *) points)[i];
939 #endif
940 
941  QVectorPath path(pts.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
942 
943  if (mode == PolylineMode)
944  stroke(path, state()->pen);
945  else
946  draw(path);
947 
948 }
949 
950 void QPaintEngineEx::drawPixmap(const QPointF &pos, const QPixmap &pm)
951 {
952  drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
953 }
954 
955 void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
956 {
957  drawImage(QRectF(pos, image.size()), image, image.rect());
958 }
959 
960 void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
961 {
962  QBrush brush(state()->pen.color(), pixmap);
963  QTransform xform = QTransform::fromTranslate(r.x() - s.x(), r.y() - s.y());
964  brush.setTransform(xform);
965 
966  qreal pts[] = { r.x(), r.y(),
967  r.x() + r.width(), r.y(),
968  r.x() + r.width(), r.y() + r.height(),
969  r.x(), r.y() + r.height() };
970 
971  QVectorPath path(pts, 4, 0, QVectorPath::RectangleHint);
972  fill(path, brush);
973 }
974 
975 void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount,
976  const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/)
977 {
978  if (pixmap.isNull())
979  return;
980 
981  qreal oldOpacity = state()->opacity;
982  QTransform oldTransform = state()->matrix;
983 
984  for (int i = 0; i < fragmentCount; ++i) {
985  QTransform transform = oldTransform;
986  transform.translate(fragments[i].x, fragments[i].y);
987  transform.rotate(fragments[i].rotation);
988  state()->opacity = oldOpacity * fragments[i].opacity;
989  state()->matrix = transform;
990  opacityChanged();
992 
993  qreal w = fragments[i].scaleX * fragments[i].width;
994  qreal h = fragments[i].scaleY * fragments[i].height;
995  QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
996  fragments[i].width, fragments[i].height);
997  drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
998  }
999 
1000  state()->opacity = oldOpacity;
1001  state()->matrix = oldTransform;
1002  opacityChanged();
1003  transformChanged();
1004 }
1005 
1006 void QPaintEngineEx::drawPixmapFragments(const QRectF *targetRects, const QRectF *sourceRects, int fragmentCount,
1007  const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/)
1008 {
1009  if (pixmap.isNull())
1010  return;
1011 
1012  if (sourceRects) {
1013  for (int i = 0; i < fragmentCount; ++i)
1014  drawPixmap(targetRects[i], pixmap, sourceRects[i]);
1015  } else {
1016  QRectF sourceRect = pixmap.rect();
1017  for (int i = 0; i < fragmentCount; ++i)
1018  drawPixmap(targetRects[i], pixmap, sourceRect);
1019  }
1020 }
1021 
1023 {
1024  QPaintEngine::state = s;
1025 }
1026 
1027 
1029 {
1030  // do nothing...
1031 }
1032 
1034 {
1035  const qreal *points = path.points();
1036  const QPainterPath::ElementType *types = path.elements();
1037 
1038  QPainterPath p;
1039  if (types) {
1040  int id = 0;
1041  for (int i=0; i<path.elementCount(); ++i) {
1042  switch(types[i]) {
1044  p.moveTo(QPointF(points[id], points[id+1]));
1045  id+=2;
1046  break;
1048  p.lineTo(QPointF(points[id], points[id+1]));
1049  id+=2;
1050  break;
1052  QPointF p1(points[id], points[id+1]);
1053  QPointF p2(points[id+2], points[id+3]);
1054  QPointF p3(points[id+4], points[id+5]);
1055  p.cubicTo(p1, p2, p3);
1056  id+=6;
1057  break;
1058  }
1060  ;
1061  break;
1062  }
1063  }
1064  } else {
1065  p.moveTo(QPointF(points[0], points[1]));
1066  int id = 2;
1067  for (int i=1; i<path.elementCount(); ++i) {
1068  p.lineTo(QPointF(points[id], points[id+1]));
1069  id+=2;
1070  }
1071  }
1072  if (path.hints() & QVectorPath::WindingFill)
1074 
1075  return p;
1076 }
1077 
1079 {
1080  QPainterPath path;
1081 #ifndef Q_WS_MAC
1083 #endif
1084 
1085  if (staticTextItem->numGlyphs == 0)
1086  return;
1087 
1088  QFontEngine *fontEngine = staticTextItem->fontEngine();
1089  fontEngine->addGlyphsToPath(staticTextItem->glyphs, staticTextItem->glyphPositions,
1090  staticTextItem->numGlyphs, &path, 0);
1091  if (!path.isEmpty()) {
1092  QPainterState *s = state();
1093  QPainter::RenderHints oldHints = s->renderHints;
1094  bool changedHints = false;
1095  if (bool(oldHints & QPainter::TextAntialiasing)
1096  && !bool(fontEngine->fontDef.styleStrategy & QFont::NoAntialias)
1097  && !bool(oldHints & QPainter::Antialiasing)) {
1100  changedHints = true;
1101  }
1102 
1103  fill(qtVectorPathForPath(path), s->pen.color());
1104 
1105  if (changedHints) {
1106  s->renderHints = oldHints;
1108  }
1109  }
1110 }
1111 
1113 {
1114  Q_UNUSED(pixelSize);
1115 
1116  if (!m.isAffine())
1117  return true;
1118 
1119  return false;
1120 }
1121 
virtual void drawPoints(const QPointF *points, int pointCount)
Draws the first pointCount points in the buffer points.
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
const int m_count
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
ElementType
This enum describes the types of elements used to connect vertices in subpaths.
Definition: qpainterpath.h:70
QDataBuffer< QPainterPath::ElementType > types
qreal scaleY
the vertical scale of the target rectangle.
Definition: qpainter.h:112
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
qreal width
the width of the source rectangle and is used to calculate the width of the target rectangle...
Definition: qpainter.h:109
double qreal
Definition: qglobal.h:1193
static mach_timebase_info_data_t info
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
QFontEngine * fontEngine() const
CacheEntry * m_cache
static void qpaintengineex_lineTo(qreal x, qreal y, void *data)
QSize size() const
Returns the size of the pixmap.
Definition: qpixmap.cpp:661
Qt::ClipOperation operation
Definition: qpainter_p.h:119
int elementCount() const
virtual void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
virtual void transformChanged()=0
The QLine class provides a two-dimensional vector using integer precision.
Definition: qline.h:57
QPainter::RenderHints renderHints
Definition: qpainter_p.h:158
bool isEmpty() const
Qt::BrushStyle qbrush_style(const QBrush &b)
Definition: qpainter_p.h:96
QFixedPoint * glyphPositions
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
QPaintEngineState * state
Definition: qpaintengine.h:239
void setTransform(const QTransform &)
Sets matrix as an explicit transformation matrix on the current brush.
Definition: qbrush.cpp:968
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor)=0
Reimplement this function to draw the part of the image specified by the sr rectangle in the given re...
void setCapStyle(Qt::PenCapStyle pcs)
Sets the pen&#39;s cap style to the given style.
Definition: qpen.cpp:723
Qt::PenStyle style() const
Returns the pen style.
Definition: qpen.cpp:428
StrokeHandler(int reserve)
QPainterState * state
Definition: qpainter_p.h:204
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints)
Q_GUI_EXPORT QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path)
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
Reimplement this function to draw the pixmap in the given rect, starting at the given p...
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:252
bool hasClipOperations() const
static QPainterPath::ElementType qpaintengineex_rect4_types_32[]
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static QPainterPath::ElementType qpaintengineex_line_types_16[]
virtual uint flags() const
virtual void draw(const QVectorPath &path)
ClipType clipType
Definition: qpainter_p.h:117
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
void(* qvectorpath_cache_cleanup)(QPaintEngineEx *engine, void *data)
Definition: qvectorpath_p.h:71
const QVectorPath & qtVectorPathForPath(const QPainterPath &path)
QTransform matrix
Definition: qpainter_p.h:161
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
Definition: qtransform.cpp:417
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
QRect rect() const
Returns the enclosing rectangle (0, 0, width(), height()) of the image.
Definition: qimage.cpp:1603
qreal opacity
the opacity of the target rectangle, where 0.0 is fully transparent and 1.0 is fully opaque...
Definition: qpainter.h:114
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
TransformationType type() const
Returns the transformation type of this matrix.
#define Q_D(Class)
Definition: qglobal.h:2482
QTransform transform() const
Returns the current transformation matrix for the brush.
Definition: qbrush.h:185
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
const QPainterPath::ElementType * elements() const
bool qpen_fast_equals(const QPen &a, const QPen &b)
Definition: qpainter_p.h:86
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
int rectCount() const
Returns the number of rectangles that will be returned in rects().
Definition: qregion.cpp:4461
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
PenStyle
Definition: qnamespace.h:1134
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
virtual void fillRect(const QRectF &rect, const QBrush &brush)
#define Q_Q(Class)
Definition: qglobal.h:2483
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
QDataBuffer< qreal > pts
virtual void renderHintsChanged()=0
virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
Q_CORE_EXPORT void qDebug(const char *,...)
QRectF controlPointRect() const
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
virtual void stroke(const QVectorPath &path, const QPen &pen)
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:249
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
QPaintEngineEx * engine
#define KAPPA
Definition: qbezier.cpp:370
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
QPainterPathData * d_func() const
Definition: qpainterpath.h:221
static float pixelSize(const QFontDef &request, int dpi)
Definition: qfont_win.cpp:80
virtual void updateState(const QPaintEngineState &state)
Reimplement this function to update the state of a paint engine.
QBrush qpen_brush(const QPen &p)
Definition: qpainter_p.h:87
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition: qpen.cpp:840
QPainterPath path
Definition: qpainter_p.h:120
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
CacheEntry * lookupCacheData(QPaintEngineEx *engine) const
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis)
Rotates the coordinate system counterclockwise by the given angle about the specified axis and return...
Definition: qtransform.cpp:615
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
static uint polygonFlags(QPaintEngine::PolygonDrawMode mode)
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...
CacheEntry * addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup) const
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
const QVectorPath & vectorPath()
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
QList< QPainterClipInfo > clipInfo
Definition: qpainter_p.h:159
static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal ex, qreal ey, void *data)
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
const T * ptr(const T &t)
virtual void setState(QPainterState *s)
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition: qpen.cpp:797
bool isOpaque() const
Returns true if the brush is fully opaque otherwise false.
Definition: qbrush.cpp:910
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
uint hints() const
const QPainterPath convertToPainterPath() const
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
static void qpaintengineex_moveTo(qreal x, qreal y, void *data)
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...
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags)
virtual void opacityChanged()=0
virtual void drawLines(const QLine *lines, int lineCount)
The default implementation converts the first lineCount lines in lines to a QLineF and calls the floa...
qvectorpath_cache_cleanup cleanup
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
bool isAffine() const
Returns true if the matrix represent an affine transformation, otherwise returns false.
Definition: qtransform.h:200
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
virtual void drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, Qt::SizeMode mode)
static const struct @32 types[]
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)=0
Reimplement this function to draw the part of the pm specified by the sr rectangle in the given r...
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
This class is used in conjunction with the QPainter::drawPixmapFragments() function to specify how a ...
Definition: qpainter.h:103
qreal scaleX
the horizontal scale of the target rectangle.
Definition: qpainter.h:111
qreal miterLimit() const
Returns the miter limit of the pen.
Definition: qpen.cpp:589
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
virtual void drawStaticTextItem(QStaticTextItem *)
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
const qreal * points() const
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
static void cleanup()
Definition: qpicture.cpp:1508
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
Definition: qnamespace.h:54
bool hasImplicitClose() const
StrokeHandler * strokeHandler
QRect rect() const
Returns the pixmap&#39;s enclosing rectangle.
Definition: qpixmap.cpp:676
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
QTransform matrix
Definition: qpainter_p.h:118
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
virtual void fill(const QVectorPath &path, const QBrush &brush)=0
void cubicTo(const QPointF &ctrlPt1, const QPointF &ctrlPt2, const QPointF &endPt)
Adds a cubic Bezier curve between the current position and the given endPoint using the control point...
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
qreal dashOffset() const
Returns the dash offset for the pen.
Definition: qpen.cpp:547
The QPaintEngineState class provides information about the active paint engine&#39;s current state...
Definition: qpaintengine.h:289
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
QBrush brush
Definition: qpainter_p.h:153
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
virtual void drawRects(const QRect *rects, int rectCount)
The default implementation converts the first rectCount rectangles in the buffer rects to a QRectF an...
SizeMode
Definition: qnamespace.h:1187
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength, QPointF *curves, int *point_count)
Creates a number of curves for a given arc definition.
Definition: qstroker.cpp:859
QFontDef fontDef
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
static QPainterPath::ElementType qpaintengineex_roundedrect_types[]
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
Qt::PenStyle qpen_style(const QPen &p)
Definition: qpainter_p.h:89
qreal height
the height of the source rectangle and is used to calculate the height of the target rectangle...
Definition: qpainter.h:110
uint styleStrategy
Definition: qfont_p.h:92
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QRealRect m_cp_rect
QPainterState * state()
virtual void drawEllipse(const QRectF &r)
Reimplement this function to draw the largest ellipse that can be contained within rectangle rect...
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
static QPainterPath::ElementType qpaintengineex_ellipse_types[]
QScopedPointer< QPainterPrivate > d_ptr
Definition: qpainter.h:546
ClipOperation
Definition: qnamespace.h:1495
virtual void clip(const QVectorPath &path, Qt::ClipOperation op)=0
const qreal * m_points
glyph_t * glyphs
virtual QPainterState * createState(QPainterState *orig) const