Qt 4.8
qpainter.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 // QtCore
43 #include <qdebug.h>
44 #include <qmath.h>
45 #include <qmutex.h>
46 
47 // QtGui
48 #include "qbitmap.h"
49 #include "qimage.h"
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
52 #include "qpainter.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
55 #include "qpicture.h"
56 #include "qpixmapcache.h"
57 #include "qpolygon.h"
58 #include "qtextlayout.h"
59 #include "qwidget.h"
60 #include "qapplication.h"
61 #include "qstyle.h"
62 #include "qthread.h"
63 #include "qvarlengtharray.h"
64 #include "qstatictext.h"
65 #include "qglyphrun.h"
66 
67 #include <private/qfontengine_p.h>
68 #include <private/qpaintengine_p.h>
69 #include <private/qemulationpaintengine_p.h>
70 #include <private/qpainterpath_p.h>
71 #include <private/qtextengine_p.h>
72 #include <private/qwidget_p.h>
73 #include <private/qpaintengine_raster_p.h>
74 #include <private/qmath_p.h>
75 #include <private/qstatictext_p.h>
76 #include <private/qglyphrun_p.h>
77 #include <private/qstylehelper_p.h>
78 #include <private/qrawfont_p.h>
79 
81 
82 #define QGradient_StretchToDevice 0x10000000
83 #define QPaintEngine_OpaqueBackground 0x40000000
84 
85 // #define QT_DEBUG_DRAW
86 #ifdef QT_DEBUG_DRAW
87 bool qt_show_painter_debug_output = true;
88 #endif
89 
90 extern QPixmap qt_pixmapForBrush(int style, bool invert);
91 
92 void qt_format_text(const QFont &font,
93  const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
94  int tabstops, int* tabarray, int tabarraylen,
95  QPainter *painter);
96 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
97  QTextCharFormat::UnderlineStyle underlineStyle,
98  QTextItem::RenderFlags flags, qreal width,
99  const QTextCharFormat &charFormat);
100 // Helper function to calculate left most position, width and flags for decoration drawing
101 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
102  const QFixedPoint *positions, int glyphCount,
103  QFontEngine *fontEngine, const QFont &font,
104  const QTextCharFormat &charFormat);
105 
107 {
108  switch (brush.style()) {
112  return brush.gradient()->coordinateMode();
113  default:
114  ;
115  }
116  return QGradient::LogicalMode;
117 }
118 
119 /* Returns true if the gradient requires stretch to device...*/
120 static inline bool check_gradient(const QBrush &brush)
121 {
123 }
124 
125 extern bool qHasPixmapTexture(const QBrush &);
126 
127 static inline bool is_brush_transparent(const QBrush &brush) {
128  Qt::BrushStyle s = brush.style();
129  bool brushBitmap = qHasPixmapTexture(brush)
130  ? brush.texture().isQBitmap()
131  : (brush.textureImage().depth() == 1);
132  return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
133  || (s == Qt::TexturePattern && brushBitmap));
134 }
135 
136 static inline bool is_pen_transparent(const QPen &pen) {
137  return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
138 }
139 
140 /* Discards the emulation flags that are not relevant for line drawing
141  and returns the result
142 */
143 static inline uint line_emulation(uint emulation)
144 {
145  return emulation & (QPaintEngine::PrimitiveTransform
153 }
154 
155 #ifndef QT_NO_DEBUG
156 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
157 {
158  switch (devType) {
159  case QInternal::Image:
160  case QInternal::Printer:
161  case QInternal::Picture:
162  // can be drawn onto these devices safely from any thread
163 #ifndef Q_WS_WIN
164  if (extraCondition)
165 #endif
166  break;
167  default:
168 #ifdef Q_WS_X11
170  return true;
171 #endif
172  if (!extraCondition && QThread::currentThread() != qApp->thread()) {
173  qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
174  return false;
175  }
176  break;
177  }
178  return true;
179 }
180 #endif
181 
183 {
186  return;
187 
188  bool doEmulation = false;
189  if (state->bgMode == Qt::OpaqueMode)
190  doEmulation = true;
191 
192  const QGradient *bg = state->brush.gradient();
193  if (bg && bg->coordinateMode() > QGradient::LogicalMode)
194  doEmulation = true;
195 
196  const QGradient *pg = qpen_brush(state->pen).gradient();
197  if (pg && pg->coordinateMode() > QGradient::LogicalMode)
198  doEmulation = true;
199 
200  if (doEmulation) {
201  if (extended != emulationEngine) {
202  if (!emulationEngine)
206  }
207  } else if (emulationEngine == extended) {
209  }
210 }
211 
212 
214 {
215  delete emulationEngine;
216  for (int i=0; i<states.size(); ++i)
217  delete states.at(i);
218 
219  if (dummyState)
220  delete dummyState;
221 }
222 
223 
225 {
226  if (state->VxF) {
227  qreal scaleW = qreal(state->vw)/qreal(state->ww);
228  qreal scaleH = qreal(state->vh)/qreal(state->wh);
229  return QTransform(scaleW, 0, 0, scaleH,
230  state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
231  }
232  return QTransform();
233 }
234 
235 
236 /*
237  \internal
238  Returns true if using a shared painter; otherwise false.
239 */
241 {
242  Q_ASSERT(q);
243  Q_ASSERT(pdev);
244 
245  if (pdev->devType() != QInternal::Widget)
246  return false;
247 
248  QWidget *widget = static_cast<QWidget *>(pdev);
249  Q_ASSERT(widget);
250 
251  // Someone either called QPainter::setRedirected in the widget's paint event
252  // right before this painter was created (or begin was called) or
253  // sent a paint event directly to the widget.
254  if (!widget->d_func()->redirectDev)
255  return false;
256 
257  QPainter *sp = widget->d_func()->sharedPainter();
258  if (!sp || !sp->isActive())
259  return false;
260 
261  if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
262  return false;
263 
264  // Check if we're attempting to paint outside a paint event.
268 
269  qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
270  return false;
271  }
272 
273  // Save the current state of the shared painter and assign
274  // the current d_ptr to the shared painter's d_ptr.
275  sp->save();
276  if (!sp->d_ptr->d_ptrs) {
277  // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
278  // redirections within the same paintEvent(), which should be enough
279  // in 99% of all cases). E.g: A renders B which renders C which renders D.
280  sp->d_ptr->d_ptrs_size = 4;
281  sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
282  Q_CHECK_PTR(sp->d_ptr->d_ptrs);
283  } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
284  // However, to support corner cases we grow the array dynamically if needed.
285  sp->d_ptr->d_ptrs_size <<= 1;
286  const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
287  sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
288  }
289  sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
290  q->d_ptr.take();
291  q->d_ptr.reset(sp->d_ptr.data());
292 
293  Q_ASSERT(q->d_ptr->state);
294 
295  // Now initialize the painter with correct widget properties.
296  q->initFrom(widget);
297  QPoint offset;
298  widget->d_func()->redirected(&offset);
299  offset += q->d_ptr->engine->coordinateOffset();
300 
301  // Update system rect.
302  q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
303  q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
304 
305  // Update matrix.
306  if (q->d_ptr->state->WxF) {
308  q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
310  q->d_ptr->state->WxF = false;
311  } else {
312  q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
313  }
314  q->d_ptr->updateMatrix();
315 
316  QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
317  if (enginePrivate->currentClipWidget == widget) {
318  enginePrivate->systemStateChanged();
319  return true;
320  }
321 
322  // Update system transform and clip.
323  enginePrivate->currentClipWidget = widget;
324  enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
325  return true;
326 }
327 
329 {
330  Q_ASSERT(refcount > 1);
331  Q_ASSERT(q);
332 
333  QPainterPrivate *original = d_ptrs[--refcount - 1];
334  if (inDestructor) {
335  inDestructor = false;
336  if (original)
337  original->inDestructor = true;
338  } else if (!original) {
339  original = new QPainterPrivate(q);
340  }
341 
342  d_ptrs[refcount - 1] = 0;
343  q->restore();
344  q->d_ptr.take();
345  q->d_ptr.reset(original);
346 
347  if (emulationEngine) {
349  delete emulationEngine;
350  emulationEngine = 0;
351  }
352 }
353 
354 
356 {
357 #ifdef QT_DEBUG_DRAW
358  if (qt_show_painter_debug_output) {
359  printf("QPainter::drawHelper\n");
360  }
361 #endif
362 
363  if (originalPath.isEmpty())
364  return;
365 
366  QPaintEngine::PaintEngineFeatures gradientStretch =
367  QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
369 
370  const bool mustEmulateObjectBoundingModeGradients = extended
373 
374  if (!(state->emulationSpecifier & ~gradientStretch)
375  && !mustEmulateObjectBoundingModeGradients) {
376  drawStretchedGradient(originalPath, op);
377  return;
379  drawOpaqueBackground(originalPath, op);
380  return;
381  }
382 
383  Q_Q(QPainter);
384 
385  qreal strokeOffsetX = 0, strokeOffsetY = 0;
386 
387  QPainterPath path = originalPath * state->matrix;
388  QRectF pathBounds = path.boundingRect();
389  QRectF strokeBounds;
390  bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
391  if (doStroke) {
392  qreal penWidth = state->pen.widthF();
393  if (penWidth == 0) {
394  strokeOffsetX = 1;
395  strokeOffsetY = 1;
396  } else {
397  // In case of complex xform
399  QPainterPathStroker stroker;
400  stroker.setWidth(penWidth);
401  stroker.setJoinStyle(state->pen.joinStyle());
402  stroker.setCapStyle(state->pen.capStyle());
403  QPainterPath stroke = stroker.createStroke(originalPath);
404  strokeBounds = (stroke * state->matrix).boundingRect();
405  } else {
406  strokeOffsetX = qAbs(penWidth * state->matrix.m11() / qreal(2.0));
407  strokeOffsetY = qAbs(penWidth * state->matrix.m22() / qreal(2.0));
408  }
409  }
410  }
411 
412  QRect absPathRect;
413  if (!strokeBounds.isEmpty()) {
414  absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
415  } else {
416  absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
418  }
419 
420  if (q->hasClipping()) {
421  bool hasPerspectiveTransform = false;
422  for (int i = 0; i < state->clipInfo.size(); ++i) {
423  const QPainterClipInfo &info = state->clipInfo.at(i);
424  if (info.matrix.type() == QTransform::TxProject) {
425  hasPerspectiveTransform = true;
426  break;
427  }
428  }
429  // avoid mapping QRegions with perspective transforms
430  if (!hasPerspectiveTransform) {
431  // The trick with txinv and invMatrix is done in order to
432  // avoid transforming the clip to logical coordinates, and
433  // then back to device coordinates. This is a problem with
434  // QRegion/QRect based clips, since they use integer
435  // coordinates and converting to/from logical coordinates will
436  // lose precision.
437  bool old_txinv = txinv;
438  QTransform old_invMatrix = invMatrix;
439  txinv = true;
440  invMatrix = QTransform();
441  QPainterPath clipPath = q->clipPath();
442  QRectF r = clipPath.boundingRect().intersected(absPathRect);
443  absPathRect = r.toAlignedRect();
444  txinv = old_txinv;
445  invMatrix = old_invMatrix;
446  }
447  }
448 
449 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
450 // devMinX, devMinY, device->width(), device->height());
451 // qDebug() << " - matrix" << state->matrix;
452 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
453 // qDebug() << " - path.bounds" << path.boundingRect();
454 
455  if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
456  return;
457 
458  QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
459  image.fill(0);
460 
461  QPainter p(&image);
462 
464 
466  p.translate(-absPathRect.x(), -absPathRect.y());
467  p.setTransform(state->matrix, true);
468  p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
469  p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
473 
477 
478  p.drawPath(originalPath);
479 
480 #ifndef QT_NO_DEBUG
481  static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
482  if (do_fallback_overlay) {
484  QPainter pt(&block);
485  pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
486  pt.drawLine(0, 0, 8, 8);
487  pt.end();
488  p.resetTransform();
490  p.setOpacity(0.5);
491  p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
492  }
493 #endif
494 
495  p.end();
496 
497  q->save();
498  state->matrix = QTransform();
499  if (extended) {
501  } else {
504  }
505  engine->drawImage(absPathRect,
506  image,
507  QRectF(0, 0, absPathRect.width(), absPathRect.height()),
509  q->restore();
510 }
511 
513 {
514  Q_Q(QPainter);
515 
516  q->setBackgroundMode(Qt::TransparentMode);
517 
518  if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
519  q->fillPath(path, state->bgBrush.color());
520  q->fillPath(path, state->brush);
521  }
522 
523  if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
524  q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
525  q->strokePath(path, state->pen);
526  }
527 
528  q->setBackgroundMode(Qt::OpaqueMode);
529 }
530 
531 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
532 {
534  && brush.style() <= Qt::ConicalGradientPattern);
535 
536  QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
537  boundingRect.x(), boundingRect.y());
538 
539  QGradient g = *brush.gradient();
541 
542  QBrush b(g);
543  b.setTransform(gradientToUser * b.transform());
544  return b;
545 }
546 
548 {
549  Q_Q(QPainter);
550 
551  const qreal sw = helper_device->width();
552  const qreal sh = helper_device->height();
553 
554  bool changedPen = false;
555  bool changedBrush = false;
556  bool needsFill = false;
557 
558  const QPen pen = state->pen;
559  const QBrush brush = state->brush;
560 
561  const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
562  const QGradient::CoordinateMode brushMode = coordinateMode(brush);
563 
565 
566  // Draw the xformed fill if the brush is a stretch gradient.
567  if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
568  if (brushMode == QGradient::StretchToDeviceMode) {
569  q->setPen(Qt::NoPen);
570  changedPen = pen.style() != Qt::NoPen;
571  q->scale(sw, sh);
573 
574  const qreal isw = 1.0 / sw;
575  const qreal ish = 1.0 / sh;
576  QTransform inv(isw, 0, 0, ish, 0, 0);
577  engine->drawPath(path * inv);
578  q->scale(isw, ish);
579  } else {
580  needsFill = true;
581 
582  if (brushMode == QGradient::ObjectBoundingMode) {
584  boundingRect = path.boundingRect();
585  q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
586  changedBrush = true;
587  }
588  }
589  }
590 
591  if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
592  // Draw the xformed outline if the pen is a stretch gradient.
593  if (penMode == QGradient::StretchToDeviceMode) {
594  q->setPen(Qt::NoPen);
595  changedPen = true;
596 
597  if (needsFill) {
599  engine->drawPath(path);
600  }
601 
602  q->scale(sw, sh);
603  q->setBrush(pen.brush());
604  changedBrush = true;
606 
607  QPainterPathStroker stroker;
608  stroker.setDashPattern(pen.style());
609  stroker.setWidth(pen.widthF());
610  stroker.setJoinStyle(pen.joinStyle());
611  stroker.setCapStyle(pen.capStyle());
612  stroker.setMiterLimit(pen.miterLimit());
613  QPainterPath stroke = stroker.createStroke(path);
614 
615  const qreal isw = 1.0 / sw;
616  const qreal ish = 1.0 / sh;
617  QTransform inv(isw, 0, 0, ish, 0, 0);
618  engine->drawPath(stroke * inv);
619  q->scale(isw, ish);
620  } else {
621  if (!needsFill && brush.style() != Qt::NoBrush) {
622  q->setBrush(Qt::NoBrush);
623  changedBrush = true;
624  }
625 
626  if (penMode == QGradient::ObjectBoundingMode) {
628 
629  // avoid computing the bounding rect twice
630  if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
631  boundingRect = path.boundingRect();
632 
633  QPen p = pen;
635  q->setPen(p);
636  changedPen = true;
637  } else if (changedPen) {
638  q->setPen(pen);
639  changedPen = false;
640  }
641 
643  engine->drawPath(path);
644  }
645  } else if (needsFill) {
646  if (pen.style() != Qt::NoPen) {
647  q->setPen(Qt::NoPen);
648  changedPen = true;
649  }
650 
652  engine->drawPath(path);
653  }
654 
655  if (changedPen)
656  q->setPen(pen);
657  if (changedBrush)
658  q->setBrush(brush);
659 }
660 
661 
663 {
665  if (state->VxF)
666  state->matrix *= viewTransform();
667 
668  txinv = false; // no inverted matrix
670  if (extended)
672  else
674 
675 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
676 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
677 }
678 
681 {
682  Q_ASSERT(txinv == false);
683  txinv = true; // creating inverted matrix
685 }
686 
688 
690 {
691  bool alpha = false;
692  bool linearGradient = false;
693  bool radialGradient = false;
694  bool extendedRadialGradient = false;
695  bool conicalGradient = false;
696  bool patternBrush = false;
697  bool xform = false;
698  bool complexXform = false;
699 
700  bool skip = true;
701 
702  // Pen and brush properties (we have to check both if one changes because the
703  // one that's unchanged can still be in a state which requires emulation)
705  // Check Brush stroke emulation
708  else
710 
711  skip = false;
712 
713  QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
714  Qt::BrushStyle brushStyle = qbrush_style(s->brush);
715  Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
716  alpha = (penBrushStyle != Qt::NoBrush
717  && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
718  && !penBrush.isOpaque())
719  || (brushStyle != Qt::NoBrush
720  && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
721  && !s->brush.isOpaque());
722  linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
723  (brushStyle == Qt::LinearGradientPattern));
724  radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
725  (brushStyle == Qt::RadialGradientPattern));
726  extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
727  conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
728  (brushStyle == Qt::ConicalGradientPattern));
729  patternBrush = (((penBrushStyle > Qt::SolidPattern
730  && penBrushStyle < Qt::LinearGradientPattern)
731  || penBrushStyle == Qt::TexturePattern) ||
732  ((brushStyle > Qt::SolidPattern
733  && brushStyle < Qt::LinearGradientPattern)
734  || brushStyle == Qt::TexturePattern));
735 
736  bool penTextureAlpha = false;
737  if (penBrush.style() == Qt::TexturePattern)
738  penTextureAlpha = qHasPixmapTexture(penBrush)
739  ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
740  : penBrush.textureImage().hasAlphaChannel();
741  bool brushTextureAlpha = false;
742  if (s->brush.style() == Qt::TexturePattern) {
743  brushTextureAlpha = qHasPixmapTexture(s->brush)
744  ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
746  }
747  if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
748  || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
751  else
753  }
754 
755  if (s->state() & (QPaintEngine::DirtyHints
758  skip = false;
759  }
760 
761  if (skip)
762  return;
763 
764 #if 0
765  qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
766  " - alpha: %d\n"
767  " - linearGradient: %d\n"
768  " - radialGradient: %d\n"
769  " - conicalGradient: %d\n"
770  " - patternBrush: %d\n"
771  " - hints: %x\n"
772  " - xform: %d\n",
773  s,
774  alpha,
775  linearGradient,
776  radialGradient,
777  conicalGradient,
778  patternBrush,
779  uint(s->renderHints),
780  xform);
781 #endif
782 
783  // XForm properties
784  if (s->state() & QPaintEngine::DirtyTransform) {
785  xform = !s->matrix.isIdentity();
786  complexXform = !s->matrix.isAffine();
787  } else if (s->matrix.type() >= QTransform::TxTranslate) {
788  xform = true;
789  complexXform = !s->matrix.isAffine();
790  }
791 
792  const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
793  const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
794 
795  const bool patternXform = patternBrush && (xform || brushXform || penXform);
796 
797  // Check alphablending
800  else
802 
803  // Linear gradient emulation
806  else
808 
809  // Radial gradient emulation
810  if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
812  else
813  s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
814 
815  // Conical gradient emulation
816  if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
818  else
820 
821  // Pattern brushes
822  if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
824  else
826 
827  // Pattern XForms
830  else
832 
833  // Primitive XForms
836  else
838 
839  // Perspective XForms
842  else
844 
845  // Constant opacity
848  else
850 
851  bool gradientStretch = false;
852  bool objectBoundingMode = false;
853  if (linearGradient || conicalGradient || radialGradient) {
856 
857  gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
858  gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
859 
860  objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
861  objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
862  }
863  if (gradientStretch)
865  else
867 
868  if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
870  else
872 
873  // Opaque backgrounds...
874  if (s->bgMode == Qt::OpaqueMode &&
877  else
879 
880 #if 0
881  //won't be correct either way because the device can already have
882  // something rendered to it in which case subsequent emulation
883  // on a fully transparent qimage and then blitting the results
884  // won't produce correct results
885  // Blend modes
889  else
891 #endif
892 }
893 
895 {
896  // ### we might have to call QPainter::begin() here...
897  if (!engine->state) {
898  engine->state = newState;
900  }
901 
902  if (engine->state->painter() != newState->painter)
903  // ### this could break with clip regions vs paths.
905 
906  // Upon restore, revert all changes since last save
907  else if (engine->state != newState)
908  newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
909 
910  // We need to store all changes made so that restore can deal with them
911  else
912  newState->changeFlags |= newState->dirtyFlags;
913 
914  updateEmulationSpecifier(newState);
915 
916  // Unset potential dirty background mode
919 
920  engine->state = newState;
921  engine->updateState(*newState);
923 
924 }
925 
927 {
928 
929  if (!newState) {
930  engine->state = newState;
931 
932  } else if (newState->state() || engine->state!=newState) {
933  bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
934  && newState->pen.widthF() == 0;
935  if (setNonCosmeticPen) {
936  // Override the default pen's cosmetic state if the
937  // NonCosmeticDefaultPen render hint is used.
938  QPen oldPen = newState->pen;
939  newState->pen.setWidth(1);
940  newState->pen.setCosmetic(false);
941  newState->dirtyFlags |= QPaintEngine::DirtyPen;
942 
943  updateStateImpl(newState);
944 
945  // Restore the state pen back to its default to preserve visible
946  // state.
947  newState->pen = oldPen;
948  } else {
949  updateStateImpl(newState);
950  }
951  }
952 }
953 
954 
1460  : d_ptr(new QPainterPrivate(this))
1461 {
1462 }
1463 
1489  : d_ptr(0)
1490 {
1491  Q_ASSERT(pd != 0);
1492  if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1493  d_ptr.reset(new QPainterPrivate(this));
1494  begin(pd);
1495  }
1496  Q_ASSERT(d_ptr);
1497 }
1498 
1503 {
1504  d_ptr->inDestructor = true;
1505  QT_TRY {
1506  if (isActive())
1507  end();
1508  else if (d_ptr->refcount > 1)
1509  d_ptr->detachPainterPrivate(this);
1510  } QT_CATCH(...) {
1511  // don't throw anything in the destructor.
1512  }
1513  if (d_ptr) {
1514  // Make sure we haven't messed things up.
1516  d_ptr->inDestructor = false;
1517  Q_ASSERT(d_ptr->refcount == 1);
1518  if (d_ptr->d_ptrs)
1519  free(d_ptr->d_ptrs);
1520  }
1521 }
1522 
1531 {
1532  Q_D(const QPainter);
1533  if (isActive() && d->engine->d_func()->currentClipWidget)
1534  return d->engine->d_func()->currentClipWidget;
1535  return d->original_device;
1536 }
1537 
1546 {
1547  Q_D(const QPainter);
1548  return d->engine;
1549 }
1550 
1559 {
1560  Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
1561  Q_D(QPainter);
1562  if (!d->engine) {
1563  qWarning("QPainter::initFrom: Painter not active, aborted");
1564  return;
1565  }
1566 
1567  const QPalette &pal = widget->palette();
1568  d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
1569  d->state->bgBrush = pal.brush(widget->backgroundRole());
1570  d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
1571  d->state->font = d->state->deviceFont;
1572  if (d->extended) {
1573  d->extended->penChanged();
1574  } else if (d->engine) {
1575  d->engine->setDirty(QPaintEngine::DirtyPen);
1576  d->engine->setDirty(QPaintEngine::DirtyBrush);
1577  d->engine->setDirty(QPaintEngine::DirtyFont);
1578  }
1579 }
1580 
1581 
1591 {
1592 #ifdef QT_DEBUG_DRAW
1593  if (qt_show_painter_debug_output)
1594  printf("QPainter::save()\n");
1595 #endif
1596  Q_D(QPainter);
1597  if (!d->engine) {
1598  qWarning("QPainter::save: Painter not active");
1599  return;
1600  }
1601 
1602  if (d->extended) {
1603  d->state = d->extended->createState(d->states.back());
1604  d->extended->setState(d->state);
1605  } else {
1606  d->updateState(d->state);
1607  d->state = new QPainterState(d->states.back());
1608  d->engine->state = d->state;
1609  }
1610  d->states.push_back(d->state);
1611 }
1612 
1621 {
1622 #ifdef QT_DEBUG_DRAW
1623  if (qt_show_painter_debug_output)
1624  printf("QPainter::restore()\n");
1625 #endif
1626  Q_D(QPainter);
1627  if (d->states.size()<=1) {
1628  qWarning("QPainter::restore: Unbalanced save/restore");
1629  return;
1630  } else if (!d->engine) {
1631  qWarning("QPainter::restore: Painter not active");
1632  return;
1633  }
1634 
1635  QPainterState *tmp = d->state;
1636  d->states.pop_back();
1637  d->state = d->states.back();
1638  d->txinv = false;
1639 
1640  if (d->extended) {
1641  d->checkEmulation();
1642  d->extended->setState(d->state);
1643  delete tmp;
1644  return;
1645  }
1646 
1647  // trigger clip update if the clip path/region has changed since
1648  // last save
1649  if (!d->state->clipInfo.isEmpty()
1651  // reuse the tmp state to avoid any extra allocs...
1653  tmp->clipOperation = Qt::NoClip;
1654  tmp->clipPath = QPainterPath();
1655  d->engine->updateState(*tmp);
1656  // replay the list of clip states,
1657  for (int i=0; i<d->state->clipInfo.size(); ++i) {
1658  const QPainterClipInfo &info = d->state->clipInfo.at(i);
1659  tmp->matrix = info.matrix;
1660  tmp->matrix *= d->state->redirectionMatrix;
1661  tmp->clipOperation = info.operation;
1662  if (info.clipType == QPainterClipInfo::RectClip) {
1664  tmp->clipRegion = info.rect;
1665  } else if (info.clipType == QPainterClipInfo::RegionClip) {
1667  tmp->clipRegion = info.region;
1668  } else { // clipType == QPainterClipInfo::PathClip
1670  tmp->clipPath = info.path;
1671  }
1672  d->engine->updateState(*tmp);
1673  }
1674 
1675 
1676  //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1677  d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1680  }
1681 
1682  d->updateState(d->state);
1683  delete tmp;
1684 }
1685 
1686 
1715 {
1716  d->states.clear();
1717  delete d->state;
1718  d->state = 0;
1719  d->engine = 0;
1720  d->device = 0;
1721 }
1722 
1724 {
1725  Q_ASSERT(pd);
1726 
1727  if (pd->painters > 0) {
1728  qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1729  return false;
1730  }
1731 
1732  if (d_ptr->engine) {
1733  qWarning("QPainter::begin: Painter already active");
1734  return false;
1735  }
1736 
1738  return true;
1739 
1740  Q_D(QPainter);
1741 
1742  d->helper_device = pd;
1743  d->original_device = pd;
1744  QPaintDevice *rpd = 0;
1745 
1746  QPoint redirectionOffset;
1747  // We know for sure that redirection is broken when the widget is inside
1748  // its paint event, so it's safe to use our hard-coded redirection. However,
1749  // there IS one particular case we still need to support, and that's
1750  // when people call QPainter::setRedirected in the widget's paint event right
1751  // before any painter is created (or QPainter::begin is called). In that
1752  // particular case our hard-coded redirection is restored and the redirection
1753  // is retrieved from QPainter::redirected (as before).
1754  if (pd->devType() == QInternal::Widget)
1755  rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
1756 
1757  if (!rpd)
1758  rpd = redirected(pd, &redirectionOffset);
1759 
1760  if (rpd)
1761  pd = rpd;
1762 
1763 #ifdef QT_DEBUG_DRAW
1764  if (qt_show_painter_debug_output)
1765  printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1766 #endif
1767 
1768  if (pd->devType() == QInternal::Pixmap)
1769  static_cast<QPixmap *>(pd)->detach();
1770  else if (pd->devType() == QInternal::Image)
1771  static_cast<QImage *>(pd)->detach();
1772 
1773  d->engine = pd->paintEngine();
1774 
1775  if (!d->engine) {
1776  qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1777  return false;
1778  }
1779 
1780  d->device = pd;
1781 
1782  d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1783  if (d->emulationEngine)
1784  d->emulationEngine->real_engine = d->extended;
1785 
1786  // Setup new state...
1787  Q_ASSERT(!d->state);
1788  d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1789  d->state->painter = this;
1790  d->states.push_back(d->state);
1791 
1792  d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1793  d->state->brushOrigin = QPointF();
1794 
1795  // Slip a painter state into the engine before we do any other operations
1796  if (d->extended)
1797  d->extended->setState(d->state);
1798  else
1799  d->engine->state = d->state;
1800 
1801  switch (pd->devType()) {
1802  case QInternal::Widget:
1803  {
1804  const QWidget *widget = static_cast<const QWidget *>(pd);
1805  Q_ASSERT(widget);
1806 
1807  const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1808  const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1809  if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
1810  && !paintOutsidePaintEvent && !inPaintEvent) {
1811  qWarning("QPainter::begin: Widget painting can only begin as a "
1812  "result of a paintEvent");
1814  return false;
1815  }
1816 
1817  // Adjust offset for alien widgets painting outside the paint event.
1818  if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1819  && widget->testAttribute(Qt::WA_WState_Created)) {
1820  const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1821  d->state->redirectionMatrix.translate(offset.x(), offset.y());
1822  }
1823  break;
1824  }
1825  case QInternal::Pixmap:
1826  {
1827  QPixmap *pm = static_cast<QPixmap *>(pd);
1828  Q_ASSERT(pm);
1829  if (pm->isNull()) {
1830  qWarning("QPainter::begin: Cannot paint on a null pixmap");
1832  return false;
1833  }
1834 
1835  if (pm->depth() == 1) {
1836  d->state->pen = QPen(Qt::color1);
1837  d->state->brush = QBrush(Qt::color0);
1838  }
1839  break;
1840  }
1841  case QInternal::Image:
1842  {
1843  QImage *img = static_cast<QImage *>(pd);
1844  Q_ASSERT(img);
1845  if (img->isNull()) {
1846  qWarning("QPainter::begin: Cannot paint on a null image");
1848  return false;
1849  } else if (img->format() == QImage::Format_Indexed8) {
1850  // Painting on indexed8 images is not supported.
1851  qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1853  return false;
1854  }
1855  if (img->depth() == 1) {
1856  d->state->pen = QPen(Qt::color1);
1857  d->state->brush = QBrush(Qt::color0);
1858  }
1859  break;
1860  }
1861  default:
1862  break;
1863  }
1864  if (d->state->ww == 0) // For compat with 3.x painter defaults
1865  d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1866 
1867  d->engine->setPaintDevice(pd);
1868 
1869  bool begun = d->engine->begin(pd);
1870  if (!begun) {
1871  qWarning("QPainter::begin(): Returned false");
1872  if (d->engine->isActive()) {
1873  end();
1874  } else {
1876  }
1877  return false;
1878  } else {
1879  d->engine->setActive(begun);
1880  }
1881 
1882  // Copy painter properties from original paint device,
1883  // required for QPixmap::grabWidget()
1884  if (d->original_device->devType() == QInternal::Widget) {
1885  QWidget *widget = static_cast<QWidget *>(d->original_device);
1886  initFrom(widget);
1887  } else {
1888  d->state->layoutDirection = Qt::LayoutDirectionAuto;
1889  // make sure we have a font compatible with the paintdevice
1890  d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1891  }
1892 
1893  QRect systemRect = d->engine->systemRect();
1894  if (!systemRect.isEmpty()) {
1895  d->state->ww = d->state->vw = systemRect.width();
1896  d->state->wh = d->state->vh = systemRect.height();
1897  } else {
1898  d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1899  d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1900  }
1901 
1902  const QPoint coordinateOffset = d->engine->coordinateOffset();
1903  d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1904 
1905  Q_ASSERT(d->engine->isActive());
1906 
1907  if (!d->state->redirectionMatrix.isIdentity())
1908  d->updateMatrix();
1909 
1910  Q_ASSERT(d->engine->isActive());
1911  d->state->renderHints = QPainter::TextAntialiasing;
1912  ++d->device->painters;
1913 
1914  d->state->emulationSpecifier = 0;
1915 
1916  return true;
1917 }
1918 
1930 {
1931 #ifdef QT_DEBUG_DRAW
1932  if (qt_show_painter_debug_output)
1933  printf("QPainter::end()\n");
1934 #endif
1935  Q_D(QPainter);
1936 
1937  if (!d->engine) {
1938  qWarning("QPainter::end: Painter not active, aborted");
1940  return false;
1941  }
1942 
1943  if (d->refcount > 1) {
1944  d->detachPainterPrivate(this);
1945  return true;
1946  }
1947 
1948  bool ended = true;
1949 
1950  if (d->engine->isActive()) {
1951  ended = d->engine->end();
1952  d->updateState(0);
1953 
1954  --d->device->painters;
1955  if (d->device->painters == 0) {
1956  d->engine->setPaintDevice(0);
1957  d->engine->setActive(false);
1958  }
1959  }
1960 
1961  if (d->states.size() > 1) {
1962  qWarning("QPainter::end: Painter ended with %d saved states",
1963  d->states.size());
1964  }
1965 
1966  if (d->engine->autoDestruct()) {
1967  delete d->engine;
1968  }
1969 
1970  if (d->emulationEngine) {
1971  delete d->emulationEngine;
1972  d->emulationEngine = 0;
1973  }
1974 
1975  if (d->extended) {
1976  d->extended = 0;
1977  }
1978 
1980 
1981  return ended;
1982 }
1983 
1984 
1992 {
1993  Q_D(const QPainter);
1994  return d->engine;
1995 }
1996 
2033 {
2034  Q_D(QPainter);
2035  if (!d->engine) {
2036  qWarning("QPainter::beginNativePainting: Painter not active");
2037  return;
2038  }
2039 
2040  if (d->extended)
2041  d->extended->beginNativePainting();
2042 }
2043 
2057 {
2058  Q_D(const QPainter);
2059  if (!d->engine) {
2060  qWarning("QPainter::beginNativePainting: Painter not active");
2061  return;
2062  }
2063 
2064  if (d->extended)
2065  d->extended->endNativePainting();
2066  else
2067  d->engine->syncState();
2068 }
2069 
2078 {
2079  Q_D(const QPainter);
2080  if (!d->engine) {
2081  qWarning("QPainter::fontMetrics: Painter not active");
2082  return QFontMetrics(QFont());
2083  }
2084  return QFontMetrics(d->state->font);
2085 }
2086 
2087 
2096 {
2097  Q_D(const QPainter);
2098  if (!d->engine) {
2099  qWarning("QPainter::fontInfo: Painter not active");
2100  return QFontInfo(QFont());
2101  }
2102  return QFontInfo(d->state->font);
2103 }
2104 
2116 {
2117  Q_D(const QPainter);
2118  if (!d->engine) {
2119  qWarning("QPainter::opacity: Painter not active");
2120  return 1.0;
2121  }
2122  return d->state->opacity;
2123 }
2124 
2140 {
2141  Q_D(QPainter);
2142 
2143  if (!d->engine) {
2144  qWarning("QPainter::setOpacity: Painter not active");
2145  return;
2146  }
2147 
2148  opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2149 
2150  if (opacity == d->state->opacity)
2151  return;
2152 
2153  d->state->opacity = opacity;
2154 
2155  if (d->extended)
2156  d->extended->opacityChanged();
2157  else
2158  d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2159 }
2160 
2161 
2169 {
2170  Q_D(const QPainter);
2171  if (!d->engine) {
2172  qWarning("QPainter::brushOrigin: Painter not active");
2173  return QPoint();
2174  }
2175  return QPointF(d->state->brushOrigin).toPoint();
2176 }
2177 
2199 {
2200  Q_D(QPainter);
2201 #ifdef QT_DEBUG_DRAW
2202  if (qt_show_painter_debug_output)
2203  printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2204 #endif
2205 
2206  if (!d->engine) {
2207  qWarning("QPainter::setBrushOrigin: Painter not active");
2208  return;
2209  }
2210 
2211  d->state->brushOrigin = p;
2212 
2213  if (d->extended) {
2214  d->extended->brushOriginChanged();
2215  return;
2216  }
2217 
2218  d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2219 }
2220 
2423 {
2424  Q_D(QPainter);
2425  if (!d->engine) {
2426  qWarning("QPainter::setCompositionMode: Painter not active");
2427  return;
2428  }
2429  if (d->state->composition_mode == mode)
2430  return;
2431  if (d->extended) {
2432  d->state->composition_mode = mode;
2433  d->extended->compositionModeChanged();
2434  return;
2435  }
2436 
2438  if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2439  qWarning("QPainter::setCompositionMode: "
2440  "Raster operation modes not supported on device");
2441  return;
2442  }
2443  } else if (mode >= QPainter::CompositionMode_Plus) {
2444  if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2445  qWarning("QPainter::setCompositionMode: "
2446  "Blend modes not supported on device");
2447  return;
2448  }
2449  } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2450  if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2451  qWarning("QPainter::setCompositionMode: "
2452  "PorterDuff modes not supported on device");
2453  return;
2454  }
2455  }
2456 
2457  d->state->composition_mode = mode;
2458  d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2459 }
2460 
2467 {
2468  Q_D(const QPainter);
2469  if (!d->engine) {
2470  qWarning("QPainter::compositionMode: Painter not active");
2472  }
2473  return d->state->composition_mode;
2474 }
2475 
2483 {
2484  Q_D(const QPainter);
2485  if (!d->engine) {
2486  qWarning("QPainter::background: Painter not active");
2487  return d->fakeState()->brush;
2488  }
2489  return d->state->bgBrush;
2490 }
2491 
2492 
2500 {
2501  Q_D(const QPainter);
2502  if (!d->engine) {
2503  qWarning("QPainter::hasClipping: Painter not active");
2504  return false;
2505  }
2506  return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2507 }
2508 
2509 
2517 void QPainter::setClipping(bool enable)
2518 {
2519  Q_D(QPainter);
2520 #ifdef QT_DEBUG_DRAW
2521  if (qt_show_painter_debug_output)
2522  printf("QPainter::setClipping(), enable=%s, was=%s\n",
2523  enable ? "on" : "off",
2524  hasClipping() ? "on" : "off");
2525 #endif
2526  if (!d->engine) {
2527  qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2528  return;
2529  }
2530 
2531  if (hasClipping() == enable)
2532  return;
2533 
2534  // we can't enable clipping if we don't have a clip
2535  if (enable
2536  && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2537  return;
2538  d->state->clipEnabled = enable;
2539 
2540  if (d->extended) {
2541  d->extended->clipEnabledChanged();
2542  return;
2543  }
2544 
2545  d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2546  d->updateState(d->state);
2547 }
2548 
2549 
2563 {
2564  Q_D(const QPainter);
2565  if (!d->engine) {
2566  qWarning("QPainter::clipRegion: Painter not active");
2567  return QRegion();
2568  }
2569 
2570  QRegion region;
2571  bool lastWasNothing = true;
2572 
2573  if (!d->txinv)
2574  const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2575 
2576  // ### Falcon: Use QPainterPath
2577  for (int i=0; i<d->state->clipInfo.size(); ++i) {
2578  const QPainterClipInfo &info = d->state->clipInfo.at(i);
2579  switch (info.clipType) {
2580 
2582  QTransform matrix = (info.matrix * d->invMatrix);
2583  if (lastWasNothing) {
2584  region = info.region * matrix;
2585  lastWasNothing = false;
2586  continue;
2587  }
2588  if (info.operation == Qt::IntersectClip)
2589  region &= info.region * matrix;
2590  else if (info.operation == Qt::UniteClip)
2591  region |= info.region * matrix;
2592  else if (info.operation == Qt::NoClip) {
2593  lastWasNothing = true;
2594  region = QRegion();
2595  } else
2596  region = info.region * matrix;
2597  break;
2598  }
2599 
2601  QTransform matrix = (info.matrix * d->invMatrix);
2602  if (lastWasNothing) {
2603  region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2604  info.path.fillRule());
2605  lastWasNothing = false;
2606  continue;
2607  }
2608  if (info.operation == Qt::IntersectClip) {
2609  region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2610  info.path.fillRule());
2611  } else if (info.operation == Qt::UniteClip) {
2612  region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2613  info.path.fillRule());
2614  } else if (info.operation == Qt::NoClip) {
2615  lastWasNothing = true;
2616  region = QRegion();
2617  } else {
2618  region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2619  info.path.fillRule());
2620  }
2621  break;
2622  }
2623 
2625  QTransform matrix = (info.matrix * d->invMatrix);
2626  if (lastWasNothing) {
2627  region = QRegion(info.rect) * matrix;
2628  lastWasNothing = false;
2629  continue;
2630  }
2631  if (info.operation == Qt::IntersectClip) {
2632  // Use rect intersection if possible.
2633  if (matrix.type() <= QTransform::TxScale)
2634  region &= matrix.mapRect(info.rect);
2635  else
2636  region &= matrix.map(QRegion(info.rect));
2637  } else if (info.operation == Qt::UniteClip) {
2638  region |= QRegion(info.rect) * matrix;
2639  } else if (info.operation == Qt::NoClip) {
2640  lastWasNothing = true;
2641  region = QRegion();
2642  } else {
2643  region = QRegion(info.rect) * matrix;
2644  }
2645  break;
2646  }
2647 
2649  QTransform matrix = (info.matrix * d->invMatrix);
2650  if (lastWasNothing) {
2651  region = QRegion(info.rectf.toRect()) * matrix;
2652  lastWasNothing = false;
2653  continue;
2654  }
2655  if (info.operation == Qt::IntersectClip) {
2656  // Use rect intersection if possible.
2657  if (matrix.type() <= QTransform::TxScale)
2658  region &= matrix.mapRect(info.rectf.toRect());
2659  else
2660  region &= matrix.map(QRegion(info.rectf.toRect()));
2661  } else if (info.operation == Qt::UniteClip) {
2662  region |= QRegion(info.rectf.toRect()) * matrix;
2663  } else if (info.operation == Qt::NoClip) {
2664  lastWasNothing = true;
2665  region = QRegion();
2666  } else {
2667  region = QRegion(info.rectf.toRect()) * matrix;
2668  }
2669  break;
2670  }
2671  }
2672  }
2673 
2674  return region;
2675 }
2676 
2678 
2691 {
2692  Q_D(const QPainter);
2693 
2694  // ### Since we do not support path intersections and path unions yet,
2695  // we just use clipRegion() here...
2696  if (!d->engine) {
2697  qWarning("QPainter::clipPath: Painter not active");
2698  return QPainterPath();
2699  }
2700 
2701  // No clip, return empty
2702  if (d->state->clipInfo.size() == 0) {
2703  return QPainterPath();
2704  } else {
2705 
2706  // Update inverse matrix, used below.
2707  if (!d->txinv)
2708  const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2709 
2710  // For the simple case avoid conversion.
2711  if (d->state->clipInfo.size() == 1
2712  && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2713  QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2714  return d->state->clipInfo.at(0).path * matrix;
2715 
2716  } else if (d->state->clipInfo.size() == 1
2717  && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2718  QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2719  QPainterPath path;
2720  path.addRect(d->state->clipInfo.at(0).rect);
2721  return path * matrix;
2722  } else {
2723  // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2724  return qt_regionToPath(clipRegion());
2725  }
2726  }
2727 }
2728 
2742 {
2743  Q_D(const QPainter);
2744 
2745  if (!d->engine) {
2746  qWarning("QPainter::clipBoundingRect: Painter not active");
2747  return QRectF();
2748  }
2749 
2750  // Accumulate the bounding box in device space. This is not 100%
2751  // precise, but it fits within the guarantee and it is reasonably
2752  // fast.
2753  QRectF bounds;
2754  for (int i=0; i<d->state->clipInfo.size(); ++i) {
2755  QRectF r;
2756  const QPainterClipInfo &info = d->state->clipInfo.at(i);
2757 
2759  r = info.rect;
2760  else if (info.clipType == QPainterClipInfo::RectFClip)
2761  r = info.rectf;
2762  else if (info.clipType == QPainterClipInfo::RegionClip)
2763  r = info.region.boundingRect();
2764  else
2765  r = info.path.boundingRect();
2766 
2767  r = info.matrix.mapRect(r);
2768 
2769  if (i == 0)
2770  bounds = r;
2771  else if (info.operation == Qt::IntersectClip)
2772  bounds &= r;
2773  else if (info.operation == Qt::UniteClip)
2774  bounds |= r;
2775  }
2776 
2777 
2778  // Map the rectangle back into logical space using the inverse
2779  // matrix.
2780  if (!d->txinv)
2781  const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2782 
2783  return d->invMatrix.mapRect(bounds);
2784 }
2785 
2802 {
2803  Q_D(QPainter);
2804 
2805  if (d->extended) {
2806  if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2807  op = Qt::ReplaceClip;
2808 
2809  if (!d->engine) {
2810  qWarning("QPainter::setClipRect: Painter not active");
2811  return;
2812  }
2813  qreal right = rect.x() + rect.width();
2814  qreal bottom = rect.y() + rect.height();
2815  qreal pts[] = { rect.x(), rect.y(),
2816  right, rect.y(),
2817  right, bottom,
2818  rect.x(), bottom };
2819  QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2820  d->state->clipEnabled = true;
2821  d->extended->clip(vp, op);
2822  if (op == Qt::ReplaceClip || op == Qt::NoClip)
2823  d->state->clipInfo.clear();
2824  d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2825  d->state->clipOperation = op;
2826  return;
2827  }
2828 
2829  if (qreal(int(rect.top())) == rect.top()
2830  && qreal(int(rect.bottom())) == rect.bottom()
2831  && qreal(int(rect.left())) == rect.left()
2832  && qreal(int(rect.right())) == rect.right())
2833  {
2834  setClipRect(rect.toRect(), op);
2835  return;
2836  }
2837 
2838  if (rect.isEmpty()) {
2839  setClipRegion(QRegion(), op);
2840  return;
2841  }
2842 
2843  QPainterPath path;
2844  path.addRect(rect);
2845  setClipPath(path, op);
2846 }
2847 
2859 {
2860  Q_D(QPainter);
2861 
2862  if (!d->engine) {
2863  qWarning("QPainter::setClipRect: Painter not active");
2864  return;
2865  }
2866 
2867  if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2868  op = Qt::ReplaceClip;
2869 
2870  if (d->extended) {
2871  d->state->clipEnabled = true;
2872  d->extended->clip(rect, op);
2873  if (op == Qt::ReplaceClip || op == Qt::NoClip)
2874  d->state->clipInfo.clear();
2875  d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2876  d->state->clipOperation = op;
2877  return;
2878  }
2879 
2880  if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2881  op = Qt::ReplaceClip;
2882 
2883  d->state->clipRegion = rect;
2884  d->state->clipOperation = op;
2885  if (op == Qt::NoClip || op == Qt::ReplaceClip)
2886  d->state->clipInfo.clear();
2887  d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2888  d->state->clipEnabled = true;
2890  d->updateState(d->state);
2891 }
2892 
2918 {
2919  Q_D(QPainter);
2920 #ifdef QT_DEBUG_DRAW
2921  QRect rect = r.boundingRect();
2922  if (qt_show_painter_debug_output)
2923  printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2924  r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2925 #endif
2926  if (!d->engine) {
2927  qWarning("QPainter::setClipRegion: Painter not active");
2928  return;
2929  }
2930 
2931  if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2932  op = Qt::ReplaceClip;
2933 
2934  if (d->extended) {
2935  d->state->clipEnabled = true;
2936  d->extended->clip(r, op);
2937  if (op == Qt::NoClip || op == Qt::ReplaceClip)
2938  d->state->clipInfo.clear();
2939  d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2940  d->state->clipOperation = op;
2941  return;
2942  }
2943 
2944  if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2945  op = Qt::ReplaceClip;
2946 
2947  d->state->clipRegion = r;
2948  d->state->clipOperation = op;
2949  if (op == Qt::NoClip || op == Qt::ReplaceClip)
2950  d->state->clipInfo.clear();
2951  d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2952  d->state->clipEnabled = true;
2954  d->updateState(d->state);
2955 }
2956 
3003 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
3004 {
3005  setWorldTransform(QTransform(matrix), combine);
3006 }
3007 
3025 {
3026  Q_D(const QPainter);
3027  if (!d->engine) {
3028  qWarning("QPainter::worldMatrix: Painter not active");
3029  return d->fakeState()->transform.toAffine();
3030  }
3031  return d->state->worldMatrix.toAffine();
3032 }
3033 
3045 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
3046 {
3047  setWorldTransform(QTransform(matrix), combine);
3048 }
3049 
3062 {
3063  return worldMatrix();
3064 }
3065 
3066 
3083 {
3084  return combinedTransform().toAffine();
3085 }
3086 
3087 
3111 {
3112  Q_D(const QPainter);
3113  if (!d->engine) {
3114  qWarning("QPainter::deviceMatrix: Painter not active");
3115  return d->fakeState()->transform.toAffine();
3116  }
3117  return d->state->matrix.toAffine();
3118 }
3119 
3138 {
3139  resetTransform();
3140 }
3141 
3142 
3158 {
3159  Q_D(QPainter);
3160 #ifdef QT_DEBUG_DRAW
3161  if (qt_show_painter_debug_output)
3162  printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3163 #endif
3164 
3165  if (!d->engine) {
3166  qWarning("QPainter::setMatrixEnabled: Painter not active");
3167  return;
3168  }
3169  if (enable == d->state->WxF)
3170  return;
3171 
3172  d->state->WxF = enable;
3173  d->updateMatrix();
3174 }
3175 
3189 {
3190  Q_D(const QPainter);
3191  if (!d->engine) {
3192  qWarning("QPainter::worldMatrixEnabled: Painter not active");
3193  return false;
3194  }
3195  return d->state->WxF;
3196 }
3197 
3210 {
3211  setWorldMatrixEnabled(enable);
3212 }
3213 
3223 {
3224  return worldMatrixEnabled();
3225 }
3226 
3235 {
3236 #ifdef QT_DEBUG_DRAW
3237  if (qt_show_painter_debug_output)
3238  printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3239 #endif
3240  Q_D(QPainter);
3241  if (!d->engine) {
3242  qWarning("QPainter::scale: Painter not active");
3243  return;
3244  }
3245 
3246  d->state->worldMatrix.scale(sx,sy);
3247  d->state->WxF = true;
3248  d->updateMatrix();
3249 }
3250 
3259 {
3260 #ifdef QT_DEBUG_DRAW
3261  if (qt_show_painter_debug_output)
3262  printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3263 #endif
3264  Q_D(QPainter);
3265  if (!d->engine) {
3266  qWarning("QPainter::shear: Painter not active");
3267  return;
3268  }
3269 
3270  d->state->worldMatrix.shear(sh, sv);
3271  d->state->WxF = true;
3272  d->updateMatrix();
3273 }
3274 
3288 {
3289 #ifdef QT_DEBUG_DRAW
3290  if (qt_show_painter_debug_output)
3291  printf("QPainter::rotate(), angle=%f\n", a);
3292 #endif
3293  Q_D(QPainter);
3294  if (!d->engine) {
3295  qWarning("QPainter::rotate: Painter not active");
3296  return;
3297  }
3298 
3299  d->state->worldMatrix.rotate(a);
3300  d->state->WxF = true;
3301  d->updateMatrix();
3302 }
3303 
3311 void QPainter::translate(const QPointF &offset)
3312 {
3313  qreal dx = offset.x();
3314  qreal dy = offset.y();
3315 #ifdef QT_DEBUG_DRAW
3316  if (qt_show_painter_debug_output)
3317  printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3318 #endif
3319  Q_D(QPainter);
3320  if (!d->engine) {
3321  qWarning("QPainter::translate: Painter not active");
3322  return;
3323  }
3324 
3325  d->state->worldMatrix.translate(dx, dy);
3326  d->state->WxF = true;
3327  d->updateMatrix();
3328 }
3329 
3366 {
3367 #ifdef QT_DEBUG_DRAW
3368  if (qt_show_painter_debug_output) {
3369  QRectF b = path.boundingRect();
3370  printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3371  path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3372  }
3373 #endif
3374  Q_D(QPainter);
3375 
3376  if (!d->engine) {
3377  qWarning("QPainter::setClipPath: Painter not active");
3378  return;
3379  }
3380 
3381  if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3382  op = Qt::ReplaceClip;
3383 
3384  if (d->extended) {
3385  d->state->clipEnabled = true;
3386  d->extended->clip(path, op);
3387  if (op == Qt::NoClip || op == Qt::ReplaceClip)
3388  d->state->clipInfo.clear();
3389  d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3390  d->state->clipOperation = op;
3391  return;
3392  }
3393 
3394  if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3395  op = Qt::ReplaceClip;
3396 
3397  d->state->clipPath = path;
3398  d->state->clipOperation = op;
3399  if (op == Qt::NoClip || op == Qt::ReplaceClip)
3400  d->state->clipInfo.clear();
3401  d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3402  d->state->clipEnabled = true;
3404  d->updateState(d->state);
3405 }
3406 
3413 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3414 {
3415  Q_D(QPainter);
3416 
3417  if (!d->engine) {
3418  qWarning("QPainter::strokePath: Painter not active");
3419  return;
3420  }
3421 
3422  if (path.isEmpty())
3423  return;
3424 
3425  if (d->extended) {
3426  const QGradient *g = qpen_brush(pen).gradient();
3427  if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3428  d->extended->stroke(qtVectorPathForPath(path), pen);
3429  return;
3430  }
3431  }
3432 
3433  QBrush oldBrush = d->state->brush;
3434  QPen oldPen = d->state->pen;
3435 
3436  setPen(pen);
3438 
3439  drawPath(path);
3440 
3441  // Reset old state
3442  setPen(oldPen);
3443  setBrush(oldBrush);
3444 }
3445 
3456 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3457 {
3458  Q_D(QPainter);
3459 
3460  if (!d->engine) {
3461  qWarning("QPainter::fillPath: Painter not active");
3462  return;
3463  }
3464 
3465  if (path.isEmpty())
3466  return;
3467 
3468  if (d->extended) {
3469  const QGradient *g = brush.gradient();
3470  if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3471  d->extended->fill(qtVectorPathForPath(path), brush);
3472  return;
3473  }
3474  }
3475 
3476  QBrush oldBrush = d->state->brush;
3477  QPen oldPen = d->state->pen;
3478 
3479  setPen(Qt::NoPen);
3480  setBrush(brush);
3481 
3482  drawPath(path);
3483 
3484  // Reset old state
3485  setPen(oldPen);
3486  setBrush(oldBrush);
3487 }
3488 
3503 {
3504 #ifdef QT_DEBUG_DRAW
3505  QRectF pathBounds = path.boundingRect();
3506  if (qt_show_painter_debug_output)
3507  printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3508  path.elementCount(),
3509  pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3510 #endif
3511 
3512  Q_D(QPainter);
3513 
3514  if (!d->engine) {
3515  qWarning("QPainter::drawPath: Painter not active");
3516  return;
3517  }
3518 
3519  if (d->extended) {
3520  d->extended->drawPath(path);
3521  return;
3522  }
3523  d->updateState(d->state);
3524 
3525  if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3526  d->engine->drawPath(path);
3527  } else {
3528  d->draw_helper(path);
3529  }
3530 }
3531 
3641 void QPainter::drawRects(const QRectF *rects, int rectCount)
3642 {
3643 #ifdef QT_DEBUG_DRAW
3644  if (qt_show_painter_debug_output)
3645  printf("QPainter::drawRects(), count=%d\n", rectCount);
3646 #endif
3647  Q_D(QPainter);
3648 
3649  if (!d->engine) {
3650  qWarning("QPainter::drawRects: Painter not active");
3651  return;
3652  }
3653 
3654  if (rectCount <= 0)
3655  return;
3656 
3657  if (d->extended) {
3658  d->extended->drawRects(rects, rectCount);
3659  return;
3660  }
3661 
3662  d->updateState(d->state);
3663 
3664  if (!d->state->emulationSpecifier) {
3665  d->engine->drawRects(rects, rectCount);
3666  return;
3667  }
3668 
3669  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3670  && d->state->matrix.type() == QTransform::TxTranslate) {
3671  for (int i=0; i<rectCount; ++i) {
3672  QRectF r(rects[i].x() + d->state->matrix.dx(),
3673  rects[i].y() + d->state->matrix.dy(),
3674  rects[i].width(),
3675  rects[i].height());
3676  d->engine->drawRects(&r, 1);
3677  }
3678  } else {
3679  if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3680  for (int i=0; i<rectCount; ++i) {
3681  QPainterPath rectPath;
3682  rectPath.addRect(rects[i]);
3683  d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3684  }
3685  } else {
3686  QPainterPath rectPath;
3687  for (int i=0; i<rectCount; ++i)
3688  rectPath.addRect(rects[i]);
3689  d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3690  }
3691  }
3692 }
3693 
3701 void QPainter::drawRects(const QRect *rects, int rectCount)
3702 {
3703 #ifdef QT_DEBUG_DRAW
3704  if (qt_show_painter_debug_output)
3705  printf("QPainter::drawRects(), count=%d\n", rectCount);
3706 #endif
3707  Q_D(QPainter);
3708 
3709  if (!d->engine) {
3710  qWarning("QPainter::drawRects: Painter not active");
3711  return;
3712  }
3713 
3714  if (rectCount <= 0)
3715  return;
3716 
3717  if (d->extended) {
3718  d->extended->drawRects(rects, rectCount);
3719  return;
3720  }
3721 
3722  d->updateState(d->state);
3723 
3724  if (!d->state->emulationSpecifier) {
3725  d->engine->drawRects(rects, rectCount);
3726  return;
3727  }
3728 
3729  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3730  && d->state->matrix.type() == QTransform::TxTranslate) {
3731  for (int i=0; i<rectCount; ++i) {
3732  QRectF r(rects[i].x() + d->state->matrix.dx(),
3733  rects[i].y() + d->state->matrix.dy(),
3734  rects[i].width(),
3735  rects[i].height());
3736 
3737  d->engine->drawRects(&r, 1);
3738  }
3739  } else {
3740  if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3741  for (int i=0; i<rectCount; ++i) {
3742  QPainterPath rectPath;
3743  rectPath.addRect(rects[i]);
3744  d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3745  }
3746  } else {
3747  QPainterPath rectPath;
3748  for (int i=0; i<rectCount; ++i)
3749  rectPath.addRect(rects[i]);
3750 
3751  d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3752  }
3753  }
3754 }
3755 
3816 void QPainter::drawPoints(const QPointF *points, int pointCount)
3817 {
3818 #ifdef QT_DEBUG_DRAW
3819  if (qt_show_painter_debug_output)
3820  printf("QPainter::drawPoints(), count=%d\n", pointCount);
3821 #endif
3822  Q_D(QPainter);
3823 
3824  if (!d->engine) {
3825  qWarning("QPainter::drawPoints: Painter not active");
3826  return;
3827  }
3828 
3829  if (pointCount <= 0)
3830  return;
3831 
3832  if (d->extended) {
3833  d->extended->drawPoints(points, pointCount);
3834  return;
3835  }
3836 
3837  d->updateState(d->state);
3838 
3839  if (!d->state->emulationSpecifier) {
3840  d->engine->drawPoints(points, pointCount);
3841  return;
3842  }
3843 
3844  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3845  && d->state->matrix.type() == QTransform::TxTranslate) {
3846  // ### use drawPoints function
3847  for (int i=0; i<pointCount; ++i) {
3848  QPointF pt(points[i].x() + d->state->matrix.dx(),
3849  points[i].y() + d->state->matrix.dy());
3850  d->engine->drawPoints(&pt, 1);
3851  }
3852  } else {
3853  QPen pen = d->state->pen;
3854  bool flat_pen = pen.capStyle() == Qt::FlatCap;
3855  if (flat_pen) {
3856  save();
3858  setPen(pen);
3859  }
3860  QPainterPath path;
3861  for (int i=0; i<pointCount; ++i) {
3862  path.moveTo(points[i].x(), points[i].y());
3863  path.lineTo(points[i].x() + 0.0001, points[i].y());
3864  }
3865  d->draw_helper(path, QPainterPrivate::StrokeDraw);
3866  if (flat_pen)
3867  restore();
3868  }
3869 }
3870 
3881 void QPainter::drawPoints(const QPoint *points, int pointCount)
3882 {
3883 #ifdef QT_DEBUG_DRAW
3884  if (qt_show_painter_debug_output)
3885  printf("QPainter::drawPoints(), count=%d\n", pointCount);
3886 #endif
3887  Q_D(QPainter);
3888 
3889  if (!d->engine) {
3890  qWarning("QPainter::drawPoints: Painter not active");
3891  return;
3892  }
3893 
3894  if (pointCount <= 0)
3895  return;
3896 
3897  if (d->extended) {
3898  d->extended->drawPoints(points, pointCount);
3899  return;
3900  }
3901 
3902  d->updateState(d->state);
3903 
3904  if (!d->state->emulationSpecifier) {
3905  d->engine->drawPoints(points, pointCount);
3906  return;
3907  }
3908 
3909  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3910  && d->state->matrix.type() == QTransform::TxTranslate) {
3911  // ### use drawPoints function
3912  for (int i=0; i<pointCount; ++i) {
3913  QPointF pt(points[i].x() + d->state->matrix.dx(),
3914  points[i].y() + d->state->matrix.dy());
3915  d->engine->drawPoints(&pt, 1);
3916  }
3917  } else {
3918  QPen pen = d->state->pen;
3919  bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3920  if (flat_pen) {
3921  save();
3923  setPen(pen);
3924  }
3925  QPainterPath path;
3926  for (int i=0; i<pointCount; ++i) {
3927  path.moveTo(points[i].x(), points[i].y());
3928  path.lineTo(points[i].x() + 0.0001, points[i].y());
3929  }
3930  d->draw_helper(path, QPainterPrivate::StrokeDraw);
3931  if (flat_pen)
3932  restore();
3933  }
3934 }
3935 
3999 {
4000 #ifdef QT_DEBUG_DRAW
4001  if (qt_show_painter_debug_output)
4002  printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
4003 #endif
4004 
4005  Q_D(QPainter);
4006  if (!d->engine) {
4007  qWarning("QPainter::setBackgroundMode: Painter not active");
4008  return;
4009  }
4010  if (d->state->bgMode == mode)
4011  return;
4012 
4013  d->state->bgMode = mode;
4014  if (d->extended) {
4015  d->checkEmulation();
4016  } else {
4017  d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
4018  }
4019 }
4020 
4027 {
4028  Q_D(const QPainter);
4029  if (!d->engine) {
4030  qWarning("QPainter::backgroundMode: Painter not active");
4031  return Qt::TransparentMode;
4032  }
4033  return d->state->bgMode;
4034 }
4035 
4036 
4047 void QPainter::setPen(const QColor &color)
4048 {
4049 #ifdef QT_DEBUG_DRAW
4050  if (qt_show_painter_debug_output)
4051  printf("QPainter::setPen(), color=%04x\n", color.rgb());
4052 #endif
4053  Q_D(QPainter);
4054  if (!d->engine) {
4055  qWarning("QPainter::setPen: Painter not active");
4056  return;
4057  }
4058 
4059  if (d->state->pen.style() == Qt::SolidLine
4060  && d->state->pen.widthF() == 0
4061  && d->state->pen.isSolid()
4062  && d->state->pen.color() == color)
4063  return;
4064 
4065  QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
4066 
4067  d->state->pen = pen;
4068  if (d->extended)
4069  d->extended->penChanged();
4070  else
4071  d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4072 }
4073 
4084 {
4085 
4086 #ifdef QT_DEBUG_DRAW
4087  if (qt_show_painter_debug_output)
4088  printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
4089  pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
4090 #endif
4091  Q_D(QPainter);
4092  if (!d->engine) {
4093  qWarning("QPainter::setPen: Painter not active");
4094  return;
4095  }
4096 
4097  if (d->state->pen == pen)
4098  return;
4099 
4100  d->state->pen = pen;
4101 
4102  if (d->extended) {
4103  d->checkEmulation();
4104  d->extended->penChanged();
4105  return;
4106  }
4107 
4108  d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4109 }
4110 
4122 {
4123  Q_D(QPainter);
4124  if (!d->engine) {
4125  qWarning("QPainter::setPen: Painter not active");
4126  return;
4127  }
4128 
4129  if (d->state->pen.style() == style
4130  && (style == Qt::NoPen || (d->state->pen.widthF() == 0
4131  && d->state->pen.isSolid()
4132  && d->state->pen.color() == QColor(Qt::black))))
4133  return;
4134 
4135  // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
4136  // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
4137  d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
4138 
4139  if (d->extended)
4140  d->extended->penChanged();
4141  else
4142  d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4143 
4144 }
4145 
4152 const QPen &QPainter::pen() const
4153 {
4154  Q_D(const QPainter);
4155  if (!d->engine) {
4156  qWarning("QPainter::pen: Painter not active");
4157  return d->fakeState()->pen;
4158  }
4159  return d->state->pen;
4160 }
4161 
4162 
4171 void QPainter::setBrush(const QBrush &brush)
4172 {
4173 #ifdef QT_DEBUG_DRAW
4174  if (qt_show_painter_debug_output)
4175  printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4176 #endif
4177  Q_D(QPainter);
4178  if (!d->engine) {
4179  qWarning("QPainter::setBrush: Painter not active");
4180  return;
4181  }
4182 
4183  if (d->state->brush.d == brush.d)
4184  return;
4185 
4186  if (d->extended) {
4187  d->state->brush = brush;
4188  d->checkEmulation();
4189  d->extended->brushChanged();
4190  return;
4191  }
4192 
4193  d->state->brush = brush;
4194  d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4195 }
4196 
4197 
4209 {
4210  Q_D(QPainter);
4211  if (!d->engine) {
4212  qWarning("QPainter::setBrush: Painter not active");
4213  return;
4214  }
4215  if (d->state->brush.style() == style &&
4216  (style == Qt::NoBrush
4217  || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4218  return;
4219  d->state->brush = QBrush(Qt::black, style);
4220  if (d->extended)
4221  d->extended->brushChanged();
4222  else
4223  d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4224 }
4225 
4232 const QBrush &QPainter::brush() const
4233 {
4234  Q_D(const QPainter);
4235  if (!d->engine) {
4236  qWarning("QPainter::brush: Painter not active");
4237  return d->fakeState()->brush;
4238  }
4239  return d->state->brush;
4240 }
4241 
4259 {
4260 #ifdef QT_DEBUG_DRAW
4261  if (qt_show_painter_debug_output)
4262  printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4263 #endif
4264 
4265  Q_D(QPainter);
4266  if (!d->engine) {
4267  qWarning("QPainter::setBackground: Painter not active");
4268  return;
4269  }
4270  d->state->bgBrush = bg;
4271  if (!d->extended)
4272  d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4273 }
4274 
4289 {
4290  Q_D(QPainter);
4291 
4292 #ifdef QT_DEBUG_DRAW
4293  if (qt_show_painter_debug_output)
4294  printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4295 #endif
4296 
4297  if (!d->engine) {
4298  qWarning("QPainter::setFont: Painter not active");
4299  return;
4300  }
4301 
4302  d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4303  if (!d->extended)
4304  d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4305 }
4306 
4312 const QFont &QPainter::font() const
4313 {
4314  Q_D(const QPainter);
4315  if (!d->engine) {
4316  qWarning("QPainter::font: Painter not active");
4317  return d->fakeState()->font;
4318  }
4319  return d->state->font;
4320 }
4321 
4348 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4349 {
4350 #ifdef QT_DEBUG_DRAW
4351  if (qt_show_painter_debug_output)
4352  printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4353 #endif
4354  Q_D(QPainter);
4355 
4356  if (!d->engine)
4357  return;
4358 
4359  if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4360  drawRect(rect);
4361  return;
4362  }
4363 
4364  if (d->extended) {
4365  d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4366  return;
4367  }
4368 
4369  QPainterPath path;
4370  path.addRoundedRect(rect, xRadius, yRadius, mode);
4371  drawPath(path);
4372 }
4373 
4414 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4415 {
4416  drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4417 }
4418 
4419 
4465 {
4466 #ifdef QT_DEBUG_DRAW
4467  if (qt_show_painter_debug_output)
4468  printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4469 #endif
4470  Q_D(QPainter);
4471 
4472  if (!d->engine)
4473  return;
4474 
4475  QRectF rect(r.normalized());
4476 
4477  if (d->extended) {
4478  d->extended->drawEllipse(rect);
4479  return;
4480  }
4481 
4482  d->updateState(d->state);
4483  if (d->state->emulationSpecifier) {
4484  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4485  && d->state->matrix.type() == QTransform::TxTranslate) {
4486  rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4487  } else {
4488  QPainterPath path;
4489  path.addEllipse(rect);
4490  d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4491  return;
4492  }
4493  }
4494 
4495  d->engine->drawEllipse(rect);
4496 }
4497 
4509 {
4510 #ifdef QT_DEBUG_DRAW
4511  if (qt_show_painter_debug_output)
4512  printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4513 #endif
4514  Q_D(QPainter);
4515 
4516  if (!d->engine)
4517  return;
4518 
4519  QRect rect(r.normalized());
4520 
4521  if (d->extended) {
4522  d->extended->drawEllipse(rect);
4523  return;
4524  }
4525 
4526  d->updateState(d->state);
4527 
4528  if (d->state->emulationSpecifier) {
4529  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4530  && d->state->matrix.type() == QTransform::TxTranslate) {
4531  rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4532  } else {
4533  QPainterPath path;
4534  path.addEllipse(rect);
4535  d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4536  return;
4537  }
4538  }
4539 
4540  d->engine->drawEllipse(rect);
4541 }
4542 
4602 void QPainter::drawArc(const QRectF &r, int a, int alen)
4603 {
4604 #ifdef QT_DEBUG_DRAW
4605  if (qt_show_painter_debug_output)
4606  printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4607  r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4608 #endif
4609  Q_D(QPainter);
4610 
4611  if (!d->engine)
4612  return;
4613 
4614  QRectF rect = r.normalized();
4615 
4616  QPainterPath path;
4617  path.arcMoveTo(rect, a/qreal(16.0));
4618  path.arcTo(rect, a/qreal(16.0), alen/qreal(16.0));
4619  strokePath(path, d->state->pen);
4620 }
4621 
4670 void QPainter::drawPie(const QRectF &r, int a, int alen)
4671 {
4672 #ifdef QT_DEBUG_DRAW
4673  if (qt_show_painter_debug_output)
4674  printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4675  r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4676 #endif
4677  Q_D(QPainter);
4678 
4679  if (!d->engine)
4680  return;
4681 
4682  if (a > (360*16)) {
4683  a = a % (360*16);
4684  } else if (a < 0) {
4685  a = a % (360*16);
4686  if (a < 0) a += (360*16);
4687  }
4688 
4689  QRectF rect = r.normalized();
4690 
4691  QPainterPath path;
4692  path.moveTo(rect.center());
4693  path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/qreal(16.0), alen/qreal(16.0));
4694  path.closeSubpath();
4695  drawPath(path);
4696 
4697 }
4698 
4744 void QPainter::drawChord(const QRectF &r, int a, int alen)
4745 {
4746 #ifdef QT_DEBUG_DRAW
4747  if (qt_show_painter_debug_output)
4748  printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4749  r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4750 #endif
4751  Q_D(QPainter);
4752 
4753  if (!d->engine)
4754  return;
4755 
4756  QRectF rect = r.normalized();
4757 
4758  QPainterPath path;
4759  path.arcMoveTo(rect, a/qreal(16.0));
4760  path.arcTo(rect, a/qreal(16.0), alen/qreal(16.0));
4761  path.closeSubpath();
4762  drawPath(path);
4763 }
4790 #ifdef QT3_SUPPORT
4791 
4813 void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
4814 {
4815 #ifdef QT_DEBUG_DRAW
4816  if (qt_show_painter_debug_output)
4817  printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
4818 #endif
4819  Q_D(QPainter);
4820 
4821  if (!d->engine)
4822  return;
4823 
4824  if (nlines < 0)
4825  nlines = a.size()/2 - index/2;
4826  if (index + nlines*2 > (int)a.size())
4827  nlines = (a.size() - index)/2;
4828  if (nlines < 1 || index < 0)
4829  return;
4830 
4831  if (d->extended) {
4832  // FALCON: Use QVectorPath
4833  QVector<QLineF> lines;
4834  for (int i=index; i<index + nlines*2; i+=2)
4835  lines << QLineF(a.at(i), a.at(i+1));
4836  d->extended->drawLines(lines.data(), lines.size());
4837  return;
4838  }
4839 
4840  d->updateState(d->state);
4841 
4842  QVector<QLineF> lines;
4843  if (d->state->emulationSpecifier) {
4844  if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4845  && d->state->matrix.type() == QTransform::TxTranslate) {
4846  QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
4847  for (int i=index; i<index + nlines*2; i+=2)
4848  lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
4849  } else {
4850  QPainterPath linesPath;
4851  for (int i=index; i<index + nlines*2; i+=2) {
4852  linesPath.moveTo(a.at(i));
4853  linesPath.lineTo(a.at(i+1));
4854  }
4855  d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
4856  return;
4857  }
4858  } else {
4859  for (int i=index; i<index + nlines*2; i+=2)
4860  lines << QLineF(a.at(i), a.at(i+1));
4861  }
4862 
4863  d->engine->drawLines(lines.data(), lines.size());
4864 }
4865 #endif // QT3_SUPPORT
4866 
4873 void QPainter::drawLines(const QLineF *lines, int lineCount)
4874 {
4875 #ifdef QT_DEBUG_DRAW
4876  if (qt_show_painter_debug_output)
4877  printf("QPainter::drawLines(), line count=%d\n", lineCount);
4878 #endif
4879 
4880  Q_D(QPainter);
4881 
4882  if (!d->engine || lineCount < 1)
4883  return;
4884 
4885  if (d->extended) {
4886  d->extended->drawLines(lines, lineCount);
4887  return;
4888  }
4889 
4890  d->updateState(d->state);
4891 
4892  uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4893 
4894  if (lineEmulation) {
4895  if (lineEmulation == QPaintEngine::PrimitiveTransform
4896  && d->state->matrix.type() == QTransform::TxTranslate) {
4897  for (int i = 0; i < lineCount; ++i) {
4898  QLineF line = lines[i];
4899  line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4900  d->engine->drawLines(&line, 1);
4901  }
4902  } else {
4903  QPainterPath linePath;
4904  for (int i = 0; i < lineCount; ++i) {
4905  linePath.moveTo(lines[i].p1());
4906  linePath.lineTo(lines[i].p2());
4907  }
4908  d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4909  }
4910  return;
4911  }
4912  d->engine->drawLines(lines, lineCount);
4913 }
4914 
4922 void QPainter::drawLines(const QLine *lines, int lineCount)
4923 {
4924 #ifdef QT_DEBUG_DRAW
4925  if (qt_show_painter_debug_output)
4926  printf("QPainter::drawLine(), line count=%d\n", lineCount);
4927 #endif
4928 
4929  Q_D(QPainter);
4930 
4931  if (!d->engine || lineCount < 1)
4932  return;
4933 
4934  if (d->extended) {
4935  d->extended->drawLines(lines, lineCount);
4936  return;
4937  }
4938 
4939  d->updateState(d->state);
4940 
4941  uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4942 
4943  if (lineEmulation) {
4944  if (lineEmulation == QPaintEngine::PrimitiveTransform
4945  && d->state->matrix.type() == QTransform::TxTranslate) {
4946  for (int i = 0; i < lineCount; ++i) {
4947  QLineF line = lines[i];
4948  line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4949  d->engine->drawLines(&line, 1);
4950  }
4951  } else {
4952  QPainterPath linePath;
4953  for (int i = 0; i < lineCount; ++i) {
4954  linePath.moveTo(lines[i].p1());
4955  linePath.lineTo(lines[i].p2());
4956  }
4957  d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4958  }
4959  return;
4960  }
4961  d->engine->drawLines(lines, lineCount);
4962 }
4963 
4972 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4973 {
4974  Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4975 
4976  drawLines((QLineF*)pointPairs, lineCount);
4977 }
4978 
4988 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4989 {
4990  Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4991 
4992  drawLines((QLine*)pointPairs, lineCount);
4993 }
4994 
4995 
5055 void QPainter::drawPolyline(const QPointF *points, int pointCount)
5056 {
5057 #ifdef QT_DEBUG_DRAW
5058  if (qt_show_painter_debug_output)
5059  printf("QPainter::drawPolyline(), count=%d\n", pointCount);
5060 #endif
5061  Q_D(QPainter);
5062 
5063  if (!d->engine || pointCount < 2)
5064  return;
5065 
5066  if (d->extended) {
5067  d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
5068  return;
5069  }
5070 
5071  d->updateState(d->state);
5072 
5073  uint lineEmulation = line_emulation(d->state->emulationSpecifier);
5074 
5075  if (lineEmulation) {
5076  // ###
5077 // if (lineEmulation == QPaintEngine::PrimitiveTransform
5078 // && d->state->matrix.type() == QTransform::TxTranslate) {
5079 // } else {
5080  QPainterPath polylinePath(points[0]);
5081  for (int i=1; i<pointCount; ++i)
5082  polylinePath.lineTo(points[i]);
5083  d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
5084 // }
5085  } else {
5086  d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
5087  }
5088 }
5089 
5099 void QPainter::drawPolyline(const QPoint *points, int pointCount)
5100 {
5101 #ifdef QT_DEBUG_DRAW
5102  if (qt_show_painter_debug_output)
5103  printf("QPainter::drawPolyline(), count=%d\n", pointCount);
5104 #endif
5105  Q_D(QPainter);
5106 
5107  if (!d->engine || pointCount < 2)
5108  return;
5109 
5110  if (d->extended) {
5111  d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
5112  return;
5113  }
5114 
5115  d->updateState(d->state);
5116 
5117  uint lineEmulation = line_emulation(d->state->emulationSpecifier);
5118 
5119  if (lineEmulation) {
5120  // ###
5121 // if (lineEmulation == QPaintEngine::PrimitiveTransform
5122 // && d->state->matrix.type() == QTransform::TxTranslate) {
5123 // } else {
5124  QPainterPath polylinePath(points[0]);
5125  for (int i=1; i<pointCount; ++i)
5126  polylinePath.lineTo(points[i]);
5127  d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
5128 // }
5129  } else {
5130  d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
5131  }
5132 }
5133 
5205 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
5206 {
5207 #ifdef QT_DEBUG_DRAW
5208  if (qt_show_painter_debug_output)
5209  printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5210 #endif
5211 
5212  Q_D(QPainter);
5213 
5214  if (!d->engine || pointCount < 2)
5215  return;
5216 
5217  if (d->extended) {
5218  d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5219  return;
5220  }
5221 
5222  d->updateState(d->state);
5223 
5224  uint emulationSpecifier = d->state->emulationSpecifier;
5225 
5226  if (emulationSpecifier) {
5227  QPainterPath polygonPath(points[0]);
5228  for (int i=1; i<pointCount; ++i)
5229  polygonPath.lineTo(points[i]);
5230  polygonPath.closeSubpath();
5231  polygonPath.setFillRule(fillRule);
5232  d->draw_helper(polygonPath);
5233  return;
5234  }
5235 
5236  d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5237 }
5238 
5247 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
5248 {
5249 #ifdef QT_DEBUG_DRAW
5250  if (qt_show_painter_debug_output)
5251  printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5252 #endif
5253 
5254  Q_D(QPainter);
5255 
5256  if (!d->engine || pointCount < 2)
5257  return;
5258 
5259  if (d->extended) {
5260  d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5261  return;
5262  }
5263 
5264  d->updateState(d->state);
5265 
5266  uint emulationSpecifier = d->state->emulationSpecifier;
5267 
5268  if (emulationSpecifier) {
5269  QPainterPath polygonPath(points[0]);
5270  for (int i=1; i<pointCount; ++i)
5271  polygonPath.lineTo(points[i]);
5272  polygonPath.closeSubpath();
5273  polygonPath.setFillRule(fillRule);
5274  d->draw_helper(polygonPath);
5275  return;
5276  }
5277 
5278  d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5279 }
5280 
5450 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5451 {
5452 #ifdef QT_DEBUG_DRAW
5453  if (qt_show_painter_debug_output)
5454  printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5455 #endif
5456 
5457  Q_D(QPainter);
5458 
5459  if (!d->engine || pointCount < 2)
5460  return;
5461 
5462  if (d->extended) {
5463  d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5464  return;
5465  }
5466 
5467  d->updateState(d->state);
5468 
5469  uint emulationSpecifier = d->state->emulationSpecifier;
5470 
5471  if (emulationSpecifier) {
5472  QPainterPath polygonPath(points[0]);
5473  for (int i=1; i<pointCount; ++i)
5474  polygonPath.lineTo(points[i]);
5475  polygonPath.closeSubpath();
5476  polygonPath.setFillRule(Qt::WindingFill);
5477  d->draw_helper(polygonPath);
5478  return;
5479  }
5480 
5481  d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5482 }
5483 
5484 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5485 {
5486 #ifdef QT_DEBUG_DRAW
5487  if (qt_show_painter_debug_output)
5488  printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5489 #endif
5490 
5491  Q_D(QPainter);
5492 
5493  if (!d->engine || pointCount < 2)
5494  return;
5495 
5496  if (d->extended) {
5497  d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5498  return;
5499  }
5500 
5501  d->updateState(d->state);
5502 
5503  uint emulationSpecifier = d->state->emulationSpecifier;
5504 
5505  if (emulationSpecifier) {
5506  QPainterPath polygonPath(points[0]);
5507  for (int i=1; i<pointCount; ++i)
5508  polygonPath.lineTo(points[i]);
5509  polygonPath.closeSubpath();
5510  polygonPath.setFillRule(Qt::WindingFill);
5511  d->draw_helper(polygonPath);
5512  return;
5513  }
5514 
5515  d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5516 }
5517 
5518 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5519 {
5520  return m.inverted().map(QPointF(m.map(p).toPoint()));
5521 }
5522 
5548 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5549 {
5550 #if defined QT_DEBUG_DRAW
5551  if (qt_show_painter_debug_output)
5552  printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5553  p.x(), p.y(),
5554  pm.width(), pm.height());
5555 #endif
5556 
5557  Q_D(QPainter);
5558 
5559  if (!d->engine || pm.isNull())
5560  return;
5561 
5562 #ifndef QT_NO_DEBUG
5563  qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5564 #endif
5565 
5566  if (d->extended) {
5567  d->extended->drawPixmap(p, pm);
5568  return;
5569  }
5570 
5571  qreal x = p.x();
5572  qreal y = p.y();
5573 
5574  int w = pm.width();
5575  int h = pm.height();
5576 
5577  if (w <= 0)
5578  return;
5579 
5580  // Emulate opaque background for bitmaps
5581  if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5582  fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5583  }
5584 
5585  d->updateState(d->state);
5586 
5587  if ((d->state->matrix.type() > QTransform::TxTranslate
5588  && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5589  || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5590  || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5591  {
5592  save();
5593  // If there is no rotation involved we have to make sure we use the
5594  // antialiased and not the aliased coordinate system by rounding the coordinates.
5595  if (d->state->matrix.type() <= QTransform::TxScale) {
5596  const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5597  x = p.x();
5598  y = p.y();
5599  }
5600  translate(x, y);
5603  QBrush brush(d->state->pen.color(), pm);
5604  setBrush(brush);
5605  setPen(Qt::NoPen);
5606  setBrushOrigin(QPointF(0, 0));
5607 
5608  drawRect(pm.rect());
5609  restore();
5610  } else {
5611  if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5612  x += d->state->matrix.dx();
5613  y += d->state->matrix.dy();
5614  }
5615  d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5616  }
5617 }
5618 
5619 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5620 {
5621 #if defined QT_DEBUG_DRAW
5622  if (qt_show_painter_debug_output)
5623  printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5624  r.x(), r.y(), r.width(), r.height(),
5625  pm.width(), pm.height(),
5626  sr.x(), sr.y(), sr.width(), sr.height());
5627 #endif
5628 
5629  Q_D(QPainter);
5630  if (!d->engine || pm.isNull())
5631  return;
5632 #ifndef QT_NO_DEBUG
5633  qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5634 #endif
5635 
5636  qreal x = r.x();
5637  qreal y = r.y();
5638  qreal w = r.width();
5639  qreal h = r.height();
5640  qreal sx = sr.x();
5641  qreal sy = sr.y();
5642  qreal sw = sr.width();
5643  qreal sh = sr.height();
5644 
5645  // Sanity-check clipping
5646  if (sw <= 0)
5647  sw = pm.width() - sx;
5648 
5649  if (sh <= 0)
5650  sh = pm.height() - sy;
5651 
5652  if (w < 0)
5653  w = sw;
5654  if (h < 0)
5655  h = sh;
5656 
5657  if (sx < 0) {
5658  qreal w_ratio = sx * w/sw;
5659  x -= w_ratio;
5660  w += w_ratio;
5661  sw += sx;
5662  sx = 0;
5663  }
5664 
5665  if (sy < 0) {
5666  qreal h_ratio = sy * h/sh;
5667  y -= h_ratio;
5668  h += h_ratio;
5669  sh += sy;
5670  sy = 0;
5671  }
5672 
5673  if (sw + sx > pm.width()) {
5674  qreal delta = sw - (pm.width() - sx);
5675  qreal w_ratio = delta * w/sw;
5676  sw -= delta;
5677  w -= w_ratio;
5678  }
5679 
5680  if (sh + sy > pm.height()) {
5681  qreal delta = sh - (pm.height() - sy);
5682  qreal h_ratio = delta * h/sh;
5683  sh -= delta;
5684  h -= h_ratio;
5685  }
5686 
5687  if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5688  return;
5689 
5690  if (d->extended) {
5691  d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5692  return;
5693  }
5694 
5695  // Emulate opaque background for bitmaps
5696  if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5697  fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5698 
5699  d->updateState(d->state);
5700 
5701  if ((d->state->matrix.type() > QTransform::TxTranslate
5702  && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5703  || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5704  || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5705  || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5706  {
5707  save();
5708  // If there is no rotation involved we have to make sure we use the
5709  // antialiased and not the aliased coordinate system by rounding the coordinates.
5710  if (d->state->matrix.type() <= QTransform::TxScale) {
5711  const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5712  x = p.x();
5713  y = p.y();
5714  }
5715 
5716  if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5717  sx = qRound(sx);
5718  sy = qRound(sy);
5719  sw = qRound(sw);
5720  sh = qRound(sh);
5721  }
5722 
5723  translate(x, y);
5724  scale(w / sw, h / sh);
5727  QBrush brush;
5728 
5729  if (sw == pm.width() && sh == pm.height())
5730  brush = QBrush(d->state->pen.color(), pm);
5731  else
5732  brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5733 
5734  setBrush(brush);
5735  setPen(Qt::NoPen);
5736 
5737  drawRect(QRectF(0, 0, sw, sh));
5738  restore();
5739  } else {
5740  if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5741  x += d->state->matrix.dx();
5742  y += d->state->matrix.dy();
5743  }
5744  d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5745  }
5746 }
5747 
5748 
5881 void QPainter::drawImage(const QPointF &p, const QImage &image)
5882 {
5883  Q_D(QPainter);
5884 
5885  if (!d->engine || image.isNull())
5886  return;
5887 
5888  if (d->extended) {
5889  d->extended->drawImage(p, image);
5890  return;
5891  }
5892 
5893  qreal x = p.x();
5894  qreal y = p.y();
5895 
5896  int w = image.width();
5897  int h = image.height();
5898 
5899  d->updateState(d->state);
5900 
5901  if (((d->state->matrix.type() > QTransform::TxTranslate)
5902  && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5903  || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5904  || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5905  {
5906  save();
5907  // If there is no rotation involved we have to make sure we use the
5908  // antialiased and not the aliased coordinate system by rounding the coordinates.
5909  if (d->state->matrix.type() <= QTransform::TxScale) {
5910  const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5911  x = p.x();
5912  y = p.y();
5913  }
5914  translate(x, y);
5917  QBrush brush(image);
5918  setBrush(brush);
5919  setPen(Qt::NoPen);
5920  setBrushOrigin(QPointF(0, 0));
5921 
5922  drawRect(image.rect());
5923  restore();
5924  return;
5925  }
5926 
5927  if (d->state->matrix.type() == QTransform::TxTranslate
5928  && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5929  x += d->state->matrix.dx();
5930  y += d->state->matrix.dy();
5931  }
5932 
5933  d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5934 }
5935 
5936 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5937  Qt::ImageConversionFlags flags)
5938 {
5939  Q_D(QPainter);
5940 
5941  if (!d->engine || image.isNull())
5942  return;
5943 
5944  qreal x = targetRect.x();
5945  qreal y = targetRect.y();
5946  qreal w = targetRect.width();
5947  qreal h = targetRect.height();
5948  qreal sx = sourceRect.x();
5949  qreal sy = sourceRect.y();
5950  qreal sw = sourceRect.width();
5951  qreal sh = sourceRect.height();
5952 
5953  // Sanity-check clipping
5954  if (sw <= 0)
5955  sw = image.width() - sx;
5956 
5957  if (sh <= 0)
5958  sh = image.height() - sy;
5959 
5960  if (w < 0)
5961  w = sw;
5962  if (h < 0)
5963  h = sh;
5964 
5965  if (sx < 0) {
5966  qreal w_ratio = sx * w/sw;
5967  x -= w_ratio;
5968  w += w_ratio;
5969  sw += sx;
5970  sx = 0;
5971  }
5972 
5973  if (sy < 0) {
5974  qreal h_ratio = sy * h/sh;
5975  y -= h_ratio;
5976  h += h_ratio;
5977  sh += sy;
5978  sy = 0;
5979  }
5980 
5981  if (sw + sx > image.width()) {
5982  qreal delta = sw - (image.width() - sx);
5983  qreal w_ratio = delta * w/sw;
5984  sw -= delta;
5985  w -= w_ratio;
5986  }
5987 
5988  if (sh + sy > image.height()) {
5989  qreal delta = sh - (image.height() - sy);
5990  qreal h_ratio = delta * h/sh;
5991  sh -= delta;
5992  h -= h_ratio;
5993  }
5994 
5995  if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5996  return;
5997 
5998  if (d->extended) {
5999  d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
6000  return;
6001  }
6002 
6003  d->updateState(d->state);
6004 
6005  if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
6006  && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6007  || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
6008  || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6009  {
6010  save();
6011  // If there is no rotation involved we have to make sure we use the
6012  // antialiased and not the aliased coordinate system by rounding the coordinates.
6013  if (d->state->matrix.type() <= QTransform::TxScale) {
6014  const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
6015  x = p.x();
6016  y = p.y();
6017  }
6018 
6019  if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
6020  sx = qRound(sx);
6021  sy = qRound(sy);
6022  sw = qRound(sw);
6023  sh = qRound(sh);
6024  }
6025  translate(x, y);
6026  scale(w / sw, h / sh);
6029  QBrush brush(image);
6030  setBrush(brush);
6031  setPen(Qt::NoPen);
6032  setBrushOrigin(QPointF(-sx, -sy));
6033 
6034  drawRect(QRectF(0, 0, sw, sh));
6035  restore();
6036  return;
6037  }
6038 
6039  if (d->state->matrix.type() == QTransform::TxTranslate
6040  && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6041  x += d->state->matrix.dx();
6042  y += d->state->matrix.dy();
6043  }
6044 
6045  d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
6046 }
6047 
6048 #if !defined(QT_NO_RAWFONT)
6049 
6064 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
6065 {
6066  Q_D(QPainter);
6067 
6068  QRawFont font = glyphRun.rawFont();
6069  if (!font.isValid())
6070  return;
6071 
6072  QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
6073 
6074  const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
6075  const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
6076 
6077  int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
6078  QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
6079 
6080  QRawFontPrivate *fontD = QRawFontPrivate::get(font);
6081  bool supportsTransformations;
6082  if (d->extended != 0) {
6083  supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
6084  d->state->matrix);
6085  } else {
6086  supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
6087  || d->state->matrix.isAffine();
6088  }
6089 
6090  for (int i=0; i<count; ++i) {
6091  QPointF processedPosition = position + glyphPositions[i];
6092  if (!supportsTransformations)
6093  processedPosition = d->state->transform().map(processedPosition);
6094  fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
6095  }
6096 
6097  d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
6098  glyphRun.underline(), glyphRun.strikeOut());
6099 }
6100 
6102  int glyphCount,
6103  const QRawFont &font, bool overline, bool underline,
6104  bool strikeOut)
6105 {
6106  Q_Q(QPainter);
6107 
6108  updateState(state);
6109 
6110  QRawFontPrivate *fontD = QRawFontPrivate::get(font);
6111  QFontEngine *fontEngine = fontD->fontEngine;
6112 
6113  QFixed leftMost;
6114  QFixed rightMost;
6115  QFixed baseLine;
6116  for (int i=0; i<glyphCount; ++i) {
6117  glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6118  if (i == 0 || leftMost > positions[i].x)
6119  leftMost = positions[i].x;
6120 
6121  // We don't support glyphs that do not share a common baseline. If this turns out to
6122  // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6123  // and do a drawTextItemDecorations call per cluster.
6124  if (i == 0 || baseLine < positions[i].y)
6125  baseLine = positions[i].y;
6126 
6127  // We use the advance rather than the actual bounds to match the algorithm in drawText()
6128  if (i == 0 || rightMost < positions[i].x + gm.xoff)
6129  rightMost = positions[i].x + gm.xoff;
6130  }
6131 
6132  QFixed width = rightMost - leftMost;
6133 
6134  if (extended != 0 && state->matrix.isAffine()) {
6135  QStaticTextItem staticTextItem;
6136  staticTextItem.color = state->pen.color();
6137  staticTextItem.font = state->font;
6138  staticTextItem.setFontEngine(fontEngine);
6139  staticTextItem.numGlyphs = glyphCount;
6140  staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
6141  staticTextItem.glyphPositions = positions;
6142 
6143  extended->drawStaticTextItem(&staticTextItem);
6144  } else {
6145  QTextItemInt textItem;
6146  textItem.fontEngine = fontEngine;
6147 
6148  QVarLengthArray<QFixed, 128> advances(glyphCount);
6149  QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
6150  QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
6151  qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
6152  qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
6153  qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
6154 
6155  textItem.glyphs.numGlyphs = glyphCount;
6156  textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
6157  textItem.glyphs.offsets = positions;
6158  textItem.glyphs.advances_x = advances.data();
6159  textItem.glyphs.advances_y = advances.data();
6160  textItem.glyphs.justifications = glyphJustifications.data();
6161  textItem.glyphs.attributes = glyphAttributes.data();
6162 
6163  engine->drawTextItem(QPointF(0, 0), textItem);
6164  }
6165 
6166  QTextItemInt::RenderFlags flags;
6167  if (underline)
6168  flags |= QTextItemInt::Underline;
6169  if (overline)
6170  flags |= QTextItemInt::Overline;
6171  if (strikeOut)
6172  flags |= QTextItemInt::StrikeOut;
6173 
6174  drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
6175  fontEngine,
6176  (underline
6179  flags, width.toReal(), QTextCharFormat());
6180 }
6181 #endif // QT_NO_RAWFONT
6182 
6231 void QPainter::drawText(const QPointF &p, const QString &str)
6232 {
6233  drawText(p, str, 0, 0);
6234 }
6235 
6260 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
6261 {
6262  Q_D(QPainter);
6263  if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
6264  return;
6265 
6266  QStaticTextPrivate *staticText_d =
6267  const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
6268 
6269  if (font() != staticText_d->font) {
6270  staticText_d->font = font();
6271  staticText_d->needsRelayout = true;
6272  }
6273 
6274  // If we don't have an extended paint engine, or if the painter is projected,
6275  // we go through standard code path
6276  if (d->extended == 0 || !d->state->matrix.isAffine()) {
6277  staticText_d->paintText(topLeftPosition, this);
6278  return;
6279  }
6280 
6281  bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
6282  d->state->matrix);
6283  if (supportsTransformations && !staticText_d->untransformedCoordinates) {
6284  staticText_d->untransformedCoordinates = true;
6285  staticText_d->needsRelayout = true;
6286  } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
6287  staticText_d->untransformedCoordinates = false;
6288  staticText_d->needsRelayout = true;
6289  }
6290 
6291  // Don't recalculate entire layout because of translation, rather add the dx and dy
6292  // into the position to move each text item the correct distance.
6293  QPointF transformedPosition = topLeftPosition;
6294  if (!staticText_d->untransformedCoordinates)
6295  transformedPosition = transformedPosition * d->state->matrix;
6296  QTransform oldMatrix;
6297 
6298  // The translation has been applied to transformedPosition. Remove translation
6299  // component from matrix.
6300  if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
6301  qreal m11 = d->state->matrix.m11();
6302  qreal m12 = d->state->matrix.m12();
6303  qreal m13 = d->state->matrix.m13();
6304  qreal m21 = d->state->matrix.m21();
6305  qreal m22 = d->state->matrix.m22();
6306  qreal m23 = d->state->matrix.m23();
6307  qreal m33 = d->state->matrix.m33();
6308 
6309  oldMatrix = d->state->matrix;
6310  d->state->matrix.setMatrix(m11, m12, m13,
6311  m21, m22, m23,
6312  0.0, 0.0, m33);
6313  }
6314 
6315  // If the transform is not identical to the text transform,
6316  // we have to relayout the text (for other transformations than plain translation)
6317  bool staticTextNeedsReinit = staticText_d->needsRelayout;
6318  if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
6319  staticText_d->matrix = d->state->matrix;
6320  staticTextNeedsReinit = true;
6321  }
6322 
6323  // Recreate the layout of the static text because the matrix or font has changed
6324  if (staticTextNeedsReinit)
6325  staticText_d->init();
6326 
6327  if (transformedPosition != staticText_d->position) { // Translate to actual position
6328  QFixed fx = QFixed::fromReal(transformedPosition.x());
6329  QFixed fy = QFixed::fromReal(transformedPosition.y());
6330  QFixed oldX = QFixed::fromReal(staticText_d->position.x());
6331  QFixed oldY = QFixed::fromReal(staticText_d->position.y());
6332  for (int item=0; item<staticText_d->itemCount;++item) {
6333  QStaticTextItem *textItem = staticText_d->items + item;
6334  for (int i=0; i<textItem->numGlyphs; ++i) {
6335  textItem->glyphPositions[i].x += fx - oldX;
6336  textItem->glyphPositions[i].y += fy - oldY;
6337  }
6338  textItem->userDataNeedsUpdate = true;
6339  }
6340 
6341  staticText_d->position = transformedPosition;
6342  }
6343 
6344  QPen oldPen = d->state->pen;
6345  QColor currentColor = oldPen.color();
6346  for (int i=0; i<staticText_d->itemCount; ++i) {
6347  QStaticTextItem *item = staticText_d->items + i;
6348  if (item->color.isValid() && currentColor != item->color) {
6349  setPen(item->color);
6350  currentColor = item->color;
6351  }
6352  d->extended->drawStaticTextItem(item);
6353 
6355  item->numGlyphs, item->fontEngine(), staticText_d->font,
6356  QTextCharFormat());
6357  }
6358  if (currentColor != oldPen.color())
6359  setPen(oldPen);
6360 
6361  if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
6362  d->state->matrix = oldMatrix;
6363 }
6364 
6368 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
6369 {
6370 #ifdef QT_DEBUG_DRAW
6371  if (qt_show_painter_debug_output)
6372  printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
6373 #endif
6374 
6375  Q_D(QPainter);
6376 
6377  if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
6378  return;
6379 
6380  if (tf & Qt::TextBypassShaping) {
6381  // Skip harfbuzz complex shaping, shape using glyph advances only
6382  int len = str.length();
6383  int numGlyphs = len;
6384  QVarLengthGlyphLayoutArray glyphs(len);
6385  QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
6386  if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
6387  glyphs.resize(numGlyphs);
6388  if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
6389  Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
6390  }
6391 
6392  QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
6393  drawTextItem(p, gf);
6394  return;
6395  }
6396 
6397  QStackTextEngine engine(str, d->state->font);
6398  engine.option.setTextDirection(d->state->layoutDirection);
6400  engine.ignoreBidi = true;
6402  }
6403  engine.itemize();
6404  QScriptLine line;
6405  line.length = str.length();
6406  engine.shapeLine(line);
6407 
6408  int nItems = engine.layoutData->items.size();
6409  QVarLengthArray<int> visualOrder(nItems);
6410  QVarLengthArray<uchar> levels(nItems);
6411  for (int i = 0; i < nItems; ++i)
6412  levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6413  QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6414 
6415  if (justificationPadding > 0) {
6417  engine.forceJustification = true;
6418  // this works because justify() is only interested in the difference between width and textWidth
6419  line.width = justificationPadding;
6420  engine.justify(line);
6421  }
6422  QFixed x = QFixed::fromReal(p.x());
6423 
6424  for (int i = 0; i < nItems; ++i) {
6425  int item = visualOrder[i];
6426  const QScriptItem &si = engine.layoutData->items.at(item);
6428  x += si.width;
6429  continue;
6430  }
6431  QFont f = engine.font(si);
6432  QTextItemInt gf(si, &f);
6433  gf.glyphs = engine.shapedGlyphs(&si);
6434  gf.chars = engine.layoutData->string.unicode() + si.position;
6435  gf.num_chars = engine.length(item);
6436  if (engine.forceJustification) {
6437  for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6438  gf.width += gf.glyphs.effectiveAdvance(j);
6439  } else {
6440  gf.width = si.width;
6441  }
6442  gf.logClusters = engine.logClusters(&si);
6443 
6444  drawTextItem(QPointF(x.toReal(), p.y()), gf);
6445 
6446  x += gf.width;
6447  }
6448 }
6449 
6450 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6451 {
6452 #ifdef QT_DEBUG_DRAW
6453  if (qt_show_painter_debug_output)
6454  printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6455  r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6456 #endif
6457 
6458  Q_D(QPainter);
6459 
6460  if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6461  return;
6462 
6463  if (!d->extended)
6464  d->updateState(d->state);
6465 
6466  QRectF bounds;
6467  qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6468  if (br)
6469  *br = bounds.toAlignedRect();
6470 }
6471 
6528 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6529 {
6530 #ifdef QT_DEBUG_DRAW
6531  if (qt_show_painter_debug_output)
6532  printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6533  r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6534 #endif
6535 
6536  Q_D(QPainter);
6537 
6538  if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6539  return;
6540 
6541  if (!d->extended)
6542  d->updateState(d->state);
6543 
6544  qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6545 }
6546 
6627 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6628 {
6629 #ifdef QT_DEBUG_DRAW
6630  if (qt_show_painter_debug_output)
6631  printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6632  r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6633 #endif
6634 
6635  Q_D(QPainter);
6636 
6637  if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6638  return;
6639 
6640  if (!d->extended)
6641  d->updateState(d->state);
6642 
6643  qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6644 }
6645 
6687 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6688 {
6689  const qreal radiusBase = qMax(qreal(1), maxRadius);
6690 
6691  QString key = QLatin1Literal("WaveUnderline-")
6692  % pen.color().name()
6693  % HexString<qreal>(radiusBase);
6694 
6695  QPixmap pixmap;
6696  if (QPixmapCache::find(key, pixmap))
6697  return pixmap;
6698 
6699  const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6700  const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6701  const int radius = qFloor(radiusBase);
6702 
6703  QPainterPath path;
6704 
6705  qreal xs = 0;
6706  qreal ys = radius;
6707 
6708  while (xs < width) {
6709  xs += halfPeriod;
6710  ys = -ys;
6711  path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6712  }
6713 
6714  pixmap = QPixmap(width, radius * 2);
6715  pixmap.fill(Qt::transparent);
6716  {
6717  QPen wavePen = pen;
6718  wavePen.setCapStyle(Qt::SquareCap);
6719 
6720  // This is to protect against making the line too fat, as happens on Mac OS X
6721  // due to it having a rather thick width for the regular underline.
6722  const qreal maxPenWidth = .8 * radius;
6723  if (wavePen.widthF() > maxPenWidth)
6724  wavePen.setWidth(maxPenWidth);
6725 
6726  QPainter imgPainter(&pixmap);
6727  imgPainter.setPen(wavePen);
6729  imgPainter.translate(0, radius);
6730  imgPainter.drawPath(path);
6731  }
6732 
6733  QPixmapCache::insert(key, pixmap);
6734 
6735  return pixmap;
6736 }
6737 
6738 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6739  QTextCharFormat::UnderlineStyle underlineStyle,
6740  QTextItem::RenderFlags flags, qreal width,
6741  const QTextCharFormat &charFormat)
6742 {
6743  if (underlineStyle == QTextCharFormat::NoUnderline
6744  && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6745  return;
6746 
6747  const QPen oldPen = painter->pen();
6748  const QBrush oldBrush = painter->brush();
6749  painter->setBrush(Qt::NoBrush);
6750  QPen pen = oldPen;
6751  pen.setStyle(Qt::SolidLine);
6752  pen.setWidthF(fe->lineThickness().toReal());
6753  pen.setCapStyle(Qt::FlatCap);
6754 
6755  QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6756 
6757  qreal underlineOffset = fe->underlinePosition().toReal();
6758  qreal y = pos.y();
6759  // compensate for different rounding rule in Core Graphics paint engine,
6760  // ideally code like this should be moved to respective engines.
6761  if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics) {
6762  y = qCeil(y);
6763  }
6764  // deliberately ceil the offset to avoid the underline coming too close to
6765  // the text above it.
6766  const qreal underlinePos = y + qCeil(underlineOffset);
6767 
6768  if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6770  }
6771 
6772  if (underlineStyle == QTextCharFormat::WaveUnderline) {
6773  painter->save();
6774  painter->translate(0, pos.y() + 1);
6775 
6776  QColor uc = charFormat.underlineColor();
6777  if (uc.isValid())
6778  pen.setColor(uc);
6779 
6780  // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6781  const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6782  const int descent = (int) fe->descent().toReal();
6783 
6784  painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6785  painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6786  painter->restore();
6787  } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6788  QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6789 
6790  QColor uc = charFormat.underlineColor();
6791  if (uc.isValid())
6792  pen.setColor(uc);
6793 
6794  pen.setStyle((Qt::PenStyle)(underlineStyle));
6795  painter->setPen(pen);
6796  painter->drawLine(underLine);
6797  }
6798 
6799  pen.setStyle(Qt::SolidLine);
6800  pen.setColor(oldPen.color());
6801 
6802  if (flags & QTextItem::StrikeOut) {
6803  QLineF strikeOutLine = line;
6804  strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6805  painter->setPen(pen);
6806  painter->drawLine(strikeOutLine);
6807  }
6808 
6809  if (flags & QTextItem::Overline) {
6810  QLineF overLine = line;
6811  overLine.translate(0., - fe->ascent().toReal());
6812  painter->setPen(pen);
6813  painter->drawLine(overLine);
6814  }
6815 
6816  painter->setPen(oldPen);
6817  painter->setBrush(oldBrush);
6818 }
6819 
6821  const QFixedPoint *positions, int glyphCount,
6822  QFontEngine *fontEngine, const QFont &font,
6823  const QTextCharFormat &charFormat)
6824 {
6825  if (!(font.underline() || font.strikeOut() || font.overline()))
6826  return;
6827 
6828  QFixed leftMost;
6829  QFixed rightMost;
6830  QFixed baseLine;
6831  for (int i=0; i<glyphCount; ++i) {
6832  glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6833  if (i == 0 || leftMost > positions[i].x)
6834  leftMost = positions[i].x;
6835 
6836  // We don't support glyphs that do not share a common baseline. If this turns out to
6837  // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6838  // and do a drawTextItemDecorations call per cluster.
6839  if (i == 0 || baseLine < positions[i].y)
6840  baseLine = positions[i].y;
6841 
6842  // We use the advance rather than the actual bounds to match the algorithm in drawText()
6843  if (i == 0 || rightMost < positions[i].x + gm.xoff)
6844  rightMost = positions[i].x + gm.xoff;
6845  }
6846 
6847  QFixed width = rightMost - leftMost;
6848  QTextItem::RenderFlags flags = 0;
6849 
6850  if (font.underline())
6851  flags |= QTextItem::Underline;
6852  if (font.overline())
6853  flags |= QTextItem::Overline;
6854  if (font.strikeOut())
6855  flags |= QTextItem::StrikeOut;
6856 
6857  drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6858  fontEngine,
6861  width.toReal(), charFormat);
6862 }
6863 
6864 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6865 {
6866 #ifdef QT_DEBUG_DRAW
6867  if (qt_show_painter_debug_output)
6868  printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6869  p.x(), p.y(), qPrintable(_ti.text()));
6870 #endif
6871 
6872  Q_D(QPainter);
6873 
6874  if (!d->engine)
6875  return;
6876 
6877 #ifndef QT_NO_DEBUG
6878  qt_painter_thread_test(d->device->devType(),
6879  "text and fonts",
6881 #endif
6882 
6883  QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6884 
6885  if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6886  QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6887  fillRect(rect, d->state->bgBrush);
6888  }
6889 
6890  if (pen().style() == Qt::NoPen)
6891  return;
6892 
6893  const RenderHints oldRenderHints = d->state->renderHints;
6894  if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6895  // draw antialias decoration (underline/overline/strikeout) with
6896  // transformed text
6897 
6898  bool aa = true;
6899  const QTransform &m = d->state->matrix;
6900  if (d->state->matrix.type() < QTransform::TxShear) {
6901  bool isPlain90DegreeRotation =
6902  (qFuzzyIsNull(m.m11())
6903  && qFuzzyIsNull(m.m12() - qreal(1))
6904  && qFuzzyIsNull(m.m21() + qreal(1))
6905  && qFuzzyIsNull(m.m22())
6906  )
6907  ||
6908  (qFuzzyIsNull(m.m11() + qreal(1))
6909  && qFuzzyIsNull(m.m12())
6910  && qFuzzyIsNull(m.m21())
6911  && qFuzzyIsNull(m.m22() + qreal(1))
6912  )
6913  ||
6914  (qFuzzyIsNull(m.m11())
6915  && qFuzzyIsNull(m.m12() + qreal(1))
6916  && qFuzzyIsNull(m.m21() - qreal(1))
6917  && qFuzzyIsNull(m.m22())
6918  )
6919  ;
6920  aa = !isPlain90DegreeRotation;
6921  }
6922  if (aa)
6924  }
6925 
6926  if (!d->extended)
6927  d->updateState(d->state);
6928 
6929  if (!ti.glyphs.numGlyphs) {
6930  // nothing to do
6931  } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6932  QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6933 
6934  const QGlyphLayout &glyphs = ti.glyphs;
6935  int which = glyphs.glyphs[0] >> 24;
6936 
6937  qreal x = p.x();
6938  qreal y = p.y();
6939 
6940  bool rtl = ti.flags & QTextItem::RightToLeft;
6941  if (rtl)
6942  x += ti.width.toReal();
6943 
6944  int start = 0;
6945  int end, i;
6946  for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6947  const int e = glyphs.glyphs[end] >> 24;
6948  if (e == which)
6949  continue;
6950 
6951 
6952  QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6953  ti2.width = 0;
6954  // set the high byte to zero and calc the width
6955  for (i = start; i < end; ++i) {
6956  glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6957  ti2.width += ti.glyphs.effectiveAdvance(i);
6958  }
6959 
6960  if (rtl)
6961  x -= ti2.width.toReal();
6962 
6963  d->engine->drawTextItem(QPointF(x, y), ti2);
6964 
6965  if (!rtl)
6966  x += ti2.width.toReal();
6967 
6968  // reset the high byte for all glyphs and advance to the next sub-string
6969  const int hi = which << 24;
6970  for (i = start; i < end; ++i) {
6971  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6972  }
6973 
6974  // change engine
6975  start = end;
6976  which = e;
6977  }
6978 
6979  QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6980  ti2.width = 0;
6981  // set the high byte to zero and calc the width
6982  for (i = start; i < end; ++i) {
6983  glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6984  ti2.width += ti.glyphs.effectiveAdvance(i);
6985  }
6986 
6987  if (rtl)
6988  x -= ti2.width.toReal();
6989 
6990  if (d->extended)
6991  d->extended->drawTextItem(QPointF(x, y), ti2);
6992  else
6993  d->engine->drawTextItem(QPointF(x,y), ti2);
6994 
6995  // reset the high byte for all glyphs
6996  const int hi = which << 24;
6997  for (i = start; i < end; ++i)
6998  glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6999 
7000  } else {
7001  if (d->extended)
7002  d->extended->drawTextItem(p, ti);
7003  else
7004  d->engine->drawTextItem(p, ti);
7005  }
7006  drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
7007  ti.charFormat);
7008 
7009  if (d->state->renderHints != oldRenderHints) {
7010  d->state->renderHints = oldRenderHints;
7011  if (d->extended)
7012  d->extended->renderHintsChanged();
7013  else
7014  d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7015  }
7016 }
7017 
7082 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
7083 {
7084  if (str.isEmpty())
7085  return QRect(rect.x(),rect.y(), 0,0);
7086  QRect brect;
7087  drawText(rect, flags | Qt::TextDontPrint, str, &brect);
7088  return brect;
7089 }
7090 
7091 
7092 
7093 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
7094 {
7095  if (str.isEmpty())
7096  return QRectF(rect.x(),rect.y(), 0,0);
7097  QRectF brect;
7098  drawText(rect, flags | Qt::TextDontPrint, str, &brect);
7099  return brect;
7100 }
7101 
7119 {
7120  Q_D(QPainter);
7121 
7122  if (!d->engine || text.length() == 0)
7123  return QRectF(r.x(),r.y(), 0,0);
7124 
7125  QRectF br;
7126  qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
7127  return br;
7128 }
7129 
7146 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
7147 {
7148 #ifdef QT_DEBUG_DRAW
7149  if (qt_show_painter_debug_output)
7150  printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
7151  r.x(), r.y(), r.width(), r.height(),
7152  pixmap.width(), pixmap.height(),
7153  sp.x(), sp.y());
7154 #endif
7155 
7156  Q_D(QPainter);
7157  if (!d->engine || pixmap.isNull() || r.isEmpty())
7158  return;
7159 
7160 #ifndef QT_NO_DEBUG
7161  qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
7162 #endif
7163 
7164  qreal sw = pixmap.width();
7165  qreal sh = pixmap.height();
7166  qreal sx = sp.x();
7167  qreal sy = sp.y();
7168  if (sx < 0)
7169  sx = qRound(sw) - qRound(-sx) % qRound(sw);
7170  else
7171  sx = qRound(sx) % qRound(sw);
7172  if (sy < 0)
7173  sy = qRound(sh) - -qRound(sy) % qRound(sh);
7174  else
7175  sy = qRound(sy) % qRound(sh);
7176 
7177 
7178  if (d->extended) {
7179  d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
7180  return;
7181  }
7182 
7183  if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
7184  fillRect(r, d->state->bgBrush);
7185 
7186  d->updateState(d->state);
7187  if ((d->state->matrix.type() > QTransform::TxTranslate
7188  && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
7189  || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
7190  {
7191  save();
7194  setBrush(QBrush(d->state->pen.color(), pixmap));
7195  setPen(Qt::NoPen);
7196 
7197  // If there is no rotation involved we have to make sure we use the
7198  // antialiased and not the aliased coordinate system by rounding the coordinates.
7199  if (d->state->matrix.type() <= QTransform::TxScale) {
7200  const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
7201 
7202  if (d->state->matrix.type() <= QTransform::TxTranslate) {
7203  sx = qRound(sx);
7204  sy = qRound(sy);
7205  }
7206 
7207  setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
7208  drawRect(QRectF(p, r.size()));
7209  } else {
7210  setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
7211  drawRect(r);
7212  }
7213  restore();
7214  return;
7215  }
7216 
7217  qreal x = r.x();
7218  qreal y = r.y();
7219  if (d->state->matrix.type() == QTransform::TxTranslate
7220  && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
7221  x += d->state->matrix.dx();
7222  y += d->state->matrix.dy();
7223  }
7224 
7225  d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
7226 }
7227 
7256 #ifndef QT_NO_PICTURE
7257 
7282 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
7283 {
7284  Q_D(QPainter);
7285 
7286  if (!d->engine)
7287  return;
7288 
7289  if (!d->extended)
7290  d->updateState(d->state);
7291 
7292  save();
7293  translate(p);
7294  const_cast<QPicture *>(&picture)->play(this);
7295  restore();
7296 }
7297 
7318 #endif // QT_NO_PICTURE
7319 
7333 {
7334  Q_D(QPainter);
7335 
7336  fillRect(r, d->state->bgBrush);
7337 }
7338 
7339 static inline bool needsResolving(const QBrush &brush)
7340 {
7341  Qt::BrushStyle s = brush.style();
7342  return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
7345 }
7346 
7420 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
7421 {
7422  Q_D(QPainter);
7423 
7424  if (!d->engine)
7425  return;
7426 
7427  if (d->extended) {
7428  const QGradient *g = brush.gradient();
7429  if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7430  d->extended->fillRect(r, brush);
7431  return;
7432  }
7433  }
7434 
7435  QPen oldPen = pen();
7436  QBrush oldBrush = this->brush();
7437  setPen(Qt::NoPen);
7438  if (brush.style() == Qt::SolidPattern) {
7439  d->colorBrush.setStyle(Qt::SolidPattern);
7440  d->colorBrush.setColor(brush.color());
7441  setBrush(d->colorBrush);
7442  } else {
7443  setBrush(brush);
7444  }
7445 
7446  drawRect(r);
7447  setBrush(oldBrush);
7448  setPen(oldPen);
7449 }
7450 
7461 void QPainter::fillRect(const QRect &r, const QBrush &brush)
7462 {
7463  Q_D(QPainter);
7464 
7465  if (!d->engine)
7466  return;
7467 
7468  if (d->extended) {
7469  const QGradient *g = brush.gradient();
7470  if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7471  d->extended->fillRect(r, brush);
7472  return;
7473  }
7474  }
7475 
7476  QPen oldPen = pen();
7477  QBrush oldBrush = this->brush();
7478  setPen(Qt::NoPen);
7479  if (brush.style() == Qt::SolidPattern) {
7480  d->colorBrush.setStyle(Qt::SolidPattern);
7481  d->colorBrush.setColor(brush.color());
7482  setBrush(d->colorBrush);
7483  } else {
7484  setBrush(brush);
7485  }
7486 
7487  drawRect(r);
7488  setBrush(oldBrush);
7489  setPen(oldPen);
7490 }
7491 
7492 
7493 
7505 void QPainter::fillRect(const QRect &r, const QColor &color)
7506 {
7507  Q_D(QPainter);
7508 
7509  if (!d->engine)
7510  return;
7511 
7512  if (d->extended) {
7513  d->extended->fillRect(r, color);
7514  return;
7515  }
7516 
7517  fillRect(r, QBrush(color));
7518 }
7519 
7520 
7532 void QPainter::fillRect(const QRectF &r, const QColor &color)
7533 {
7534  Q_D(QPainter);
7535 
7536  if (!d->engine)
7537  return;
7538 
7539  if (d->extended) {
7540  d->extended->fillRect(r, color);
7541  return;
7542  }
7543 
7544  fillRect(r, QBrush(color));
7545 }
7546 
7621 {
7622 #ifdef QT_DEBUG_DRAW
7623  if (qt_show_painter_debug_output)
7624  printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7625 #endif
7626 
7627 #ifndef QT_NO_DEBUG
7628  static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7629  if (hint == QPainter::Antialiasing && antialiasingDisabled)
7630  return;
7631 #endif
7632 
7633  setRenderHints(hint, on);
7634 }
7635 
7649 void QPainter::setRenderHints(RenderHints hints, bool on)
7650 {
7651  Q_D(QPainter);
7652 
7653  if (!d->engine) {
7654  qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7655  return;
7656  }
7657 
7658  if (on)
7659  d->state->renderHints |= hints;
7660  else
7661  d->state->renderHints &= ~hints;
7662 
7663  if (d->extended)
7664  d->extended->renderHintsChanged();
7665  else
7666  d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7667 }
7668 
7675 QPainter::RenderHints QPainter::renderHints() const
7676 {
7677  Q_D(const QPainter);
7678 
7679  if (!d->engine)
7680  return 0;
7681 
7682  return d->state->renderHints;
7683 }
7684 
7705 {
7706  Q_D(const QPainter);
7707  if (!d->engine) {
7708  qWarning("QPainter::viewTransformEnabled: Painter not active");
7709  return false;
7710  }
7711  return d->state->VxF;
7712 }
7713 
7746 {
7747 #ifdef QT_DEBUG_DRAW
7748  if (qt_show_painter_debug_output)
7749  printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7750 #endif
7751 
7752  Q_D(QPainter);
7753 
7754  if (!d->engine) {
7755  qWarning("QPainter::setWindow: Painter not active");
7756  return;
7757  }
7758 
7759  d->state->wx = r.x();
7760  d->state->wy = r.y();
7761  d->state->ww = r.width();
7762  d->state->wh = r.height();
7763 
7764  d->state->VxF = true;
7765  d->updateMatrix();
7766 }
7767 
7775 {
7776  Q_D(const QPainter);
7777  if (!d->engine) {
7778  qWarning("QPainter::window: Painter not active");
7779  return QRect();
7780  }
7781  return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7782 }
7783 
7816 {
7817 #ifdef QT_DEBUG_DRAW
7818  if (qt_show_painter_debug_output)
7819  printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7820 #endif
7821 
7822  Q_D(QPainter);
7823 
7824  if (!d->engine) {
7825  qWarning("QPainter::setViewport: Painter not active");
7826  return;
7827  }
7828 
7829  d->state->vx = r.x();
7830  d->state->vy = r.y();
7831  d->state->vw = r.width();
7832  d->state->vh = r.height();
7833 
7834  d->state->VxF = true;
7835  d->updateMatrix();
7836 }
7837 
7845 {
7846  Q_D(const QPainter);
7847  if (!d->engine) {
7848  qWarning("QPainter::viewport: Painter not active");
7849  return QRect();
7850  }
7851  return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7852 }
7853 
7907 {
7908 #ifdef QT_DEBUG_DRAW
7909  if (qt_show_painter_debug_output)
7910  printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7911 #endif
7912 
7913  Q_D(QPainter);
7914 
7915  if (!d->engine) {
7916  qWarning("QPainter::setViewTransformEnabled: Painter not active");
7917  return;
7918  }
7919 
7920  if (enable == d->state->VxF)
7921  return;
7922 
7923  d->state->VxF = enable;
7924  d->updateMatrix();
7925 }
7926 
7927 #ifdef QT3_SUPPORT
7928 
7945 qreal QPainter::translationX() const
7946 {
7947  Q_D(const QPainter);
7948  if (!d->engine) {
7949  qWarning("QPainter::translationX: Painter not active");
7950  return 0.0;
7951  }
7952  return d->state->worldMatrix.dx();
7953 }
7954 
7971 qreal QPainter::translationY() const
7972 {
7973  Q_D(const QPainter);
7974  if (!d->engine) {
7975  qWarning("QPainter::translationY: Painter not active");
7976  return 0.0;
7977  }
7978  return d->state->worldMatrix.dy();
7979 }
7980 
7989 void QPainter::map(int x, int y, int *rx, int *ry) const
7990 {
7991  QPoint p(x, y);
7992  p = p * combinedMatrix();
7993  *rx = p.x();
7994  *ry = p.y();
7995 }
7996 
8006 QPoint QPainter::xForm(const QPoint &p) const
8007 {
8008  Q_D(const QPainter);
8009  if (!d->engine) {
8010  qWarning("QPainter::xForm: Painter not active");
8011  return QPoint();
8012  }
8013  if (d->state->matrix.type() == QTransform::TxNone)
8014  return p;
8015  return p * combinedMatrix();
8016 }
8017 
8018 
8030 QRect QPainter::xForm(const QRect &r) const
8031 {
8032  Q_D(const QPainter);
8033  if (!d->engine) {
8034  qWarning("QPainter::xForm: Painter not active");
8035  return QRect();
8036  }
8037  if (d->state->matrix.type() == QTransform::TxNone)
8038  return r;
8039  return combinedMatrix().mapRect(r);
8040 }
8041 
8052 QPolygon QPainter::xForm(const QPolygon &a) const
8053 {
8054  Q_D(const QPainter);
8055  if (!d->engine) {
8056  qWarning("QPainter::xForm: Painter not active");
8057  return QPolygon();
8058  }
8059  if (d->state->matrix.type() == QTransform::TxNone)
8060  return a;
8061  return a * combinedMatrix();
8062 }
8063 
8079 QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
8080 {
8081  int lastPoint = npoints < 0 ? av.size() : index+npoints;
8082  QPolygon a(lastPoint-index);
8083  memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
8084  return a * combinedMatrix();
8085 }
8086 
8103 QPoint QPainter::xFormDev(const QPoint &p) const
8104 {
8105  Q_D(const QPainter);
8106  if (!d->engine) {
8107  qWarning("QPainter::xFormDev: Painter not active");
8108  return QPoint();
8109  }
8110  if(d->state->matrix.type() == QTransform::TxNone)
8111  return p;
8112  return p * combinedMatrix().inverted();
8113 }
8114 
8132 QRect QPainter::xFormDev(const QRect &r) const
8133 {
8134  Q_D(const QPainter);
8135  if (!d->engine) {
8136  qWarning("QPainter::xFormDev: Painter not active");
8137  return QRect();
8138  }
8139  if (d->state->matrix.type() == QTransform::TxNone)
8140  return r;
8141  return combinedMatrix().inverted().mapRect(r);
8142 }
8143 
8161 QPolygon QPainter::xFormDev(const QPolygon &a) const
8162 {
8163  Q_D(const QPainter);
8164  if (!d->engine) {
8165  qWarning("QPainter::xFormDev: Painter not active");
8166  return QPolygon();
8167  }
8168  if (d->state->matrix.type() == QTransform::TxNone)
8169  return a;
8170  return a * combinedMatrix().inverted();
8171 }
8172 
8189 QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
8190 {
8191  Q_D(const QPainter);
8192  int lastPoint = npoints < 0 ? ad.size() : index+npoints;
8193  QPolygon a(lastPoint-index);
8194  memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
8195  if (d->state->matrix.type() == QTransform::TxNone)
8196  return a;
8197  return a * combinedMatrix().inverted();
8198 }
8199 
8227 void QPainter::drawCubicBezier(const QPolygon &a, int index)
8228 {
8229  Q_D(QPainter);
8230 
8231  if (!d->engine)
8232  return;
8233 
8234  if ((int)a.size() - index < 4) {
8235  qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
8236  "points");
8237  return;
8238  }
8239 
8240  QPainterPath path;
8241  path.moveTo(a.at(index));
8242  path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
8243  strokePath(path, d->state->pen);
8244 }
8245 #endif
8246 
8248 {
8249  QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
8251  const QPoint& offset, int internalWidgetRedirectionIndex)
8252  : device(device), replacement(replacement), offset(offset),
8253  internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
8258  bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
8260 };
8261 
8263 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
8264 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
8265 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
8266 
8267 
8294  QPaintDevice *replacement,
8295  const QPoint &offset)
8296 {
8297  Q_ASSERT(device != 0);
8298 
8299  bool hadInternalWidgetRedirection = false;
8300  if (device->devType() == QInternal::Widget) {
8301  const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
8302  // This is the case when the widget is in a paint event.
8303  if (widgetPrivate->redirectDev) {
8304  // Remove internal redirection and put it back into the global redirection list.
8305  QPoint oldOffset;
8306  QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
8307  const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
8308  setRedirected(device, oldReplacement, oldOffset);
8309  hadInternalWidgetRedirection = true;
8310  }
8311  }
8312 
8313  QPoint roffset;
8314  QPaintDevice *rdev = redirected(replacement, &roffset);
8315 
8316  QMutexLocker locker(globalRedirectionsMutex());
8317  QPaintDeviceRedirectionList *redirections = globalRedirections();
8318  Q_ASSERT(redirections != 0);
8319  *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
8320  hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
8321  globalRedirectionAtomic()->ref();
8322 }
8323 
8345 {
8346  Q_ASSERT(device != 0);
8347  QMutexLocker locker(globalRedirectionsMutex());
8348  QPaintDeviceRedirectionList *redirections = globalRedirections();
8349  Q_ASSERT(redirections != 0);
8350  for (int i = redirections->size()-1; i >= 0; --i) {
8351  if (redirections->at(i) == device) {
8352  globalRedirectionAtomic()->deref();
8353  const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
8354  redirections->removeAt(i);
8355  // Restore the internal widget redirection, i.e. remove it from the global
8356  // redirection list and put it back into QWidgetPrivate. The index is only set when
8357  // someone call QPainter::setRedirected in a widget's paint event and we internally
8358  // have a redirection set (typically set in QWidgetPrivate::drawWidget).
8359  if (internalWidgetRedirectionIndex >= 0) {
8360  Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
8361  const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
8362  QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
8363  widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
8364  redirections->removeAt(internalWidgetRedirectionIndex);
8365  }
8366  return;
8367  }
8368  }
8369 }
8370 
8392 {
8393  Q_ASSERT(device != 0);
8394 
8395  if (device->devType() == QInternal::Widget) {
8396  const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
8397  if (widgetPrivate->redirectDev)
8398  return widgetPrivate->redirected(offset);
8399  }
8400 
8401  if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
8402  return 0;
8403 
8404  QMutexLocker locker(globalRedirectionsMutex());
8405  QPaintDeviceRedirectionList *redirections = globalRedirections();
8406  Q_ASSERT(redirections != 0);
8407  for (int i = redirections->size()-1; i >= 0; --i)
8408  if (redirections->at(i) == device) {
8409  if (offset)
8410  *offset = redirections->at(i).offset;
8411  return redirections->at(i).replacement;
8412  }
8413  if (offset)
8414  *offset = QPoint(0, 0);
8415  return 0;
8416 }
8417 
8418 
8420 {
8421  if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
8422  return;
8423 
8424  QMutex *mutex = 0;
8425  QT_TRY {
8426  mutex = globalRedirectionsMutex();
8427  } QT_CATCH(...) {
8428  // ignore the missing mutex, since we could be called from
8429  // a destructor, and destructors shall not throw
8430  }
8431  QMutexLocker locker(mutex);
8432  QPaintDeviceRedirectionList *redirections = 0;
8433  QT_TRY {
8434  redirections = globalRedirections();
8435  } QT_CATCH(...) {
8436  // do nothing - code below is safe with redirections being 0.
8437  }
8438  if (redirections) {
8439  for (int i = 0; i < redirections->size(); ) {
8440  if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
8441  redirections->removeAt(i);
8442  else
8443  ++i;
8444  }
8445  }
8446 }
8447 
8448 void qt_format_text(const QFont &fnt, const QRectF &_r,
8449  int tf, const QString& str, QRectF *brect,
8450  int tabstops, int *ta, int tabarraylen,
8451  QPainter *painter)
8452 {
8453  qt_format_text(fnt, _r,
8454  tf, 0, str, brect,
8455  tabstops, ta, tabarraylen,
8456  painter);
8457 }
8458 void qt_format_text(const QFont &fnt, const QRectF &_r,
8459  int tf, const QTextOption *option, const QString& str, QRectF *brect,
8460  int tabstops, int *ta, int tabarraylen,
8461  QPainter *painter)
8462 {
8463 
8464  Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
8465 
8466  if (option) {
8467  tf |= option->alignment();
8468  if (option->wrapMode() != QTextOption::NoWrap)
8469  tf |= Qt::TextWordWrap;
8470 
8471  if (option->flags() & QTextOption::IncludeTrailingSpaces)
8473 
8474  if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
8475  tf |= Qt::TextExpandTabs;
8476  }
8477 
8478  // we need to copy r here to protect against the case (&r == brect).
8479  QRectF r(_r);
8480 
8481  bool dontclip = (tf & Qt::TextDontClip);
8482  bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
8483  bool singleline = (tf & Qt::TextSingleLine);
8484  bool showmnemonic = (tf & Qt::TextShowMnemonic);
8485  bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
8486 
8488  if (tf & Qt::TextForceLeftToRight)
8489  layout_direction = Qt::LeftToRight;
8490  else if (tf & Qt::TextForceRightToLeft)
8491  layout_direction = Qt::RightToLeft;
8492  else if (option)
8493  layout_direction = option->textDirection();
8494  else if (painter)
8495  layout_direction = painter->layoutDirection();
8496  else
8497  layout_direction = Qt::LeftToRight;
8498 
8499  tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
8500 
8501  bool isRightToLeft = layout_direction == Qt::RightToLeft;
8502  bool expandtabs = ((tf & Qt::TextExpandTabs) &&
8503  (((tf & Qt::AlignLeft) && !isRightToLeft) ||
8504  ((tf & Qt::AlignRight) && isRightToLeft)));
8505 
8506  if (!painter)
8507  tf |= Qt::TextDontPrint;
8508 
8509  uint maxUnderlines = 0;
8510  int numUnderlines = 0;
8511  QVarLengthArray<int, 32> underlinePositions(1);
8512 
8513  QFontMetricsF fm(fnt);
8514  QString text = str;
8515  int offset = 0;
8516 start_lengthVariant:
8517  bool hasMoreLengthVariants = false;
8518  // compatible behaviour to the old implementation. Replace
8519  // tabs by spaces
8520  int old_offset = offset;
8521  for (; offset < text.length(); offset++) {
8522  QChar chr = text.at(offset);
8523  if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
8524  text[offset] = QLatin1Char(' ');
8525  } else if (chr == QLatin1Char('\n')) {
8526  text[offset] = QChar::LineSeparator;
8527  } else if (chr == QLatin1Char('&')) {
8528  ++maxUnderlines;
8529  } else if (chr == QLatin1Char('\t')) {
8530  if (!expandtabs) {
8531  text[offset] = QLatin1Char(' ');
8532  } else if (!tabarraylen && !tabstops) {
8533  tabstops = qRound(fm.width(QLatin1Char('x'))*8);
8534  }
8535  } else if (chr == QChar(ushort(0x9c))) {
8536  // string with multiple length variants
8537  hasMoreLengthVariants = true;
8538  break;
8539  }
8540  }
8541 
8542  int length = offset - old_offset;
8543  if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
8544  underlinePositions.resize(maxUnderlines + 1);
8545 
8546  QChar *cout = text.data() + old_offset;
8547  QChar *cin = cout;
8548  int l = length;
8549  while (l) {
8550  if (*cin == QLatin1Char('&')) {
8551  ++cin;
8552  --length;
8553  --l;
8554  if (!l)
8555  break;
8556  if (*cin != QLatin1Char('&') && !hidemnmemonic)
8557  underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
8558  }
8559  *cout = *cin;
8560  ++cout;
8561  ++cin;
8562  --l;
8563  }
8564  }
8565 
8566  // no need to do extra work for underlines if we don't paint
8567  if (tf & Qt::TextDontPrint)
8568  numUnderlines = 0;
8569 
8570  underlinePositions[numUnderlines] = -1;
8571  qreal height = 0;
8572  qreal width = 0;
8573 
8574  QString finalText = text.mid(old_offset, length);
8575  QStackTextEngine engine(finalText, fnt);
8576  if (option) {
8577  engine.option = *option;
8578  }
8579 
8580  if (engine.option.tabStop() < 0 && tabstops > 0)
8581  engine.option.setTabStop(tabstops);
8582 
8583  if (engine.option.tabs().isEmpty() && ta) {
8584  QList<qreal> tabs;
8585  for (int i = 0; i < tabarraylen; i++)
8586  tabs.append(qreal(ta[i]));
8587  engine.option.setTabArray(tabs);
8588  }
8589 
8590  engine.option.setTextDirection(layout_direction);
8591  if (tf & Qt::AlignJustify)
8592  engine.option.setAlignment(Qt::AlignJustify);
8593  else
8594  engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
8595 
8596  if (!option && (tf & Qt::TextWrapAnywhere))
8598 
8599  if (tf & Qt::TextJustificationForced)
8600  engine.forceJustification = true;
8601  QTextLayout textLayout(&engine);
8602  textLayout.setCacheEnabled(true);
8603  textLayout.engine()->underlinePositions = underlinePositions.data();
8604 
8605  if (finalText.isEmpty()) {
8606  height = fm.height();
8607  width = 0;
8608  tf |= Qt::TextDontPrint;
8609  } else {
8610  qreal lineWidth = 0x01000000;
8611  if (wordwrap || (tf & Qt::TextJustificationForced))
8612  lineWidth = qMax<qreal>(0, r.width());
8613  if(!wordwrap)
8615  textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
8616  textLayout.beginLayout();
8617 
8618  qreal leading = fm.leading();
8619  height = -leading;
8620 
8621  while (1) {
8622  QTextLine l = textLayout.createLine();
8623  if (!l.isValid())
8624  break;
8625 
8626  l.setLineWidth(lineWidth);
8627  height += leading;
8628  l.setPosition(QPointF(0., height));
8629  height += l.height();
8630  width = qMax(width, l.naturalTextWidth());
8631  if (!dontclip && !brect && height >= r.height())
8632  break;
8633  }
8634  textLayout.endLayout();
8635  }
8636 
8637  qreal yoff = 0;
8638  qreal xoff = 0;
8639  if (tf & Qt::AlignBottom) {
8640  yoff = r.height() - height;
8641  } else if (tf & Qt::AlignVCenter) {
8642  yoff = (r.height() - height)/2;
8643  if (painter) {
8645  if (type <= QTransform::TxScale) {
8646  // do the rounding manually to work around inconsistencies
8647  // in the paint engines when drawing on floating point offsets
8648  const qreal scale = painter->transform().m22();
8649  if (scale != 0)
8650  yoff = -qRound(-yoff * scale) / scale;
8651  }
8652  }
8653  }
8654  if (tf & Qt::AlignRight) {
8655  xoff = r.width() - width;
8656  } else if (tf & Qt::AlignHCenter) {
8657  xoff = (r.width() - width)/2;
8658  if (painter) {
8660  if (type <= QTransform::TxScale) {
8661  // do the rounding manually to work around inconsistencies
8662  // in the paint engines when drawing on floating point offsets
8663  const qreal scale = painter->transform().m11();
8664  if (scale != 0)
8665  xoff = qRound(xoff * scale) / scale;
8666  }
8667  }
8668  }
8669  QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
8670 
8671  if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
8672  offset++;
8673  goto start_lengthVariant;
8674  }
8675  if (brect)
8676  *brect = bounds;
8677 
8678  if (!(tf & Qt::TextDontPrint)) {
8679  bool restore = false;
8680  if (!dontclip && !r.contains(bounds)) {
8681  restore = true;
8682  painter->save();
8683  painter->setClipRect(r, Qt::IntersectClip);
8684  }
8685 
8686  for (int i = 0; i < textLayout.lineCount(); i++) {
8687  QTextLine line = textLayout.lineAt(i);
8688 
8689  qreal advance = line.horizontalAdvance();
8690  xoff = 0;
8691  if (tf & Qt::AlignRight) {
8692  QTextEngine *eng = textLayout.engine();
8693  xoff = r.width() - advance -
8694  eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
8695  }
8696  else if (tf & Qt::AlignHCenter)
8697  xoff = (r.width() - advance) / 2;
8698 
8699  line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
8700  }
8701 
8702  if (restore) {
8703  painter->restore();
8704  }
8705  }
8706 }
8707 
8718 {
8719  Q_D(QPainter);
8720  if (d->state)
8721  d->state->layoutDirection = direction;
8722 }
8723 
8730 {
8731  Q_D(const QPainter);
8732  return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
8733 }
8734 
8736  : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
8737  pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
8739  clipOperation(s->clipOperation),
8740  renderHints(s->renderHints), clipInfo(s->clipInfo),
8741  worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
8742  wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
8743  vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
8744  opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
8745  clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
8747  composition_mode(s->composition_mode),
8748  emulationSpecifier(s->emulationSpecifier), changeFlags(0)
8749 {
8750  dirtyFlags = s->dirtyFlags;
8751 }
8752 
8755  renderHints(0),
8756  wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
8757  opacity(1), WxF(false), VxF(false), clipEnabled(true),
8760  composition_mode(QPainter::CompositionMode_SourceOver),
8762 {
8763  dirtyFlags = 0;
8764 }
8765 
8767 {
8768 }
8769 
8771  bgBrush = Qt::white;
8773  WxF = false;
8774  VxF = false;
8775  clipEnabled = true;
8776  wx = wy = ww = wh = 0;
8777  vx = vy = vw = vh = 0;
8778  painter = p;
8779  pen = QPen();
8780  brushOrigin = QPointF(0, 0);
8781  brush = QBrush();
8782  font = deviceFont = QFont();
8783  clipRegion = QRegion();
8784  clipPath = QPainterPath();
8786  clipInfo.clear();
8787  worldMatrix.reset();
8788  matrix.reset();
8791  emulationSpecifier = 0;
8792  dirtyFlags = 0;
8793  changeFlags = 0;
8794  renderHints = 0;
8795  opacity = 1;
8796 }
8797 
8798 #ifdef QT3_SUPPORT
8799 static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
8800  const QPaintDevice *src, const QRect &sr, bool)
8801 {
8802  Q_ASSERT(dst);
8803  Q_ASSERT(src);
8804 
8805  if (src->devType() == QInternal::Pixmap) {
8806  const QPixmap *pixmap = static_cast<const QPixmap *>(src);
8807  QPainter pt(dst);
8808  pt.drawPixmap(dp, *pixmap, sr);
8809 
8810  } else {
8811  qWarning("QPainter: bitBlt only works when source is of type pixmap");
8812  }
8813 }
8814 
8815 void bitBlt(QPaintDevice *dst, int dx, int dy,
8816  const QPaintDevice *src, int sx, int sy, int sw, int sh,
8817  bool ignoreMask )
8818 {
8819  bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
8820 }
8821 
8822 void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
8823 {
8824  bitBlt_helper(dst, dp, src, sr, ignoreMask);
8825 }
8826 
8827 void bitBlt(QPaintDevice *dst, int dx, int dy,
8828  const QImage *src, int sx, int sy, int sw, int sh, int fl)
8829 {
8830  Qt::ImageConversionFlags flags(fl);
8831  QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
8832  bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
8833 }
8834 
8835 #endif // QT3_SUPPORT
8836 
9260 {
9261  return static_cast<const QPainterState *>(this)->pen;
9262 }
9263 
9274 {
9275  return static_cast<const QPainterState *>(this)->brush;
9276 }
9277 
9288 {
9289  return static_cast<const QPainterState *>(this)->brushOrigin;
9290 }
9291 
9302 {
9303  return static_cast<const QPainterState *>(this)->bgBrush;
9304 }
9305 
9317 {
9318  return static_cast<const QPainterState *>(this)->bgMode;
9319 }
9320 
9332 {
9333  return static_cast<const QPainterState *>(this)->font;
9334 }
9335 
9356 {
9357  const QPainterState *st = static_cast<const QPainterState *>(this);
9358 
9359  return st->matrix.toAffine();
9360 }
9361 
9378 {
9379  const QPainterState *st = static_cast<const QPainterState *>(this);
9380 
9381  return st->matrix;
9382 }
9383 
9384 
9397 {
9398  return static_cast<const QPainterState *>(this)->clipOperation;
9399 }
9400 
9412 {
9413  const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
9414  return needsResolving(brush);
9415 }
9416 
9417 
9429 {
9430  const QPen &pen = static_cast<const QPainterState *>(this)->pen;
9431  return needsResolving(pen.brush());
9432 }
9433 
9444 {
9445  return static_cast<const QPainterState *>(this)->clipRegion;
9446 }
9447 
9458 {
9459  return static_cast<const QPainterState *>(this)->clipPath;
9460 }
9461 
9474 {
9475  return static_cast<const QPainterState *>(this)->clipEnabled;
9476 }
9477 
9488 QPainter::RenderHints QPaintEngineState::renderHints() const
9489 {
9490  return static_cast<const QPainterState *>(this)->renderHints;
9491 }
9492 
9504 {
9505  return static_cast<const QPainterState *>(this)->composition_mode;
9506 }
9507 
9508 
9515 {
9516  return static_cast<const QPainterState *>(this)->painter;
9517 }
9518 
9519 
9530 {
9531  return static_cast<const QPainterState *>(this)->opacity;
9532 }
9533 
9547 void QPainter::setTransform(const QTransform &transform, bool combine )
9548 {
9549  setWorldTransform(transform, combine);
9550 }
9551 
9559 {
9560  return worldTransform();
9561 }
9562 
9563 
9580 {
9581  Q_D(const QPainter);
9582  if (!d->engine) {
9583  qWarning("QPainter::deviceTransform: Painter not active");
9584  return d->fakeState()->transform;
9585  }
9586  return d->state->matrix;
9587 }
9588 
9589 
9599 {
9600  Q_D(QPainter);
9601 #ifdef QT_DEBUG_DRAW
9602  if (qt_show_painter_debug_output)
9603  printf("QPainter::resetMatrix()\n");
9604 #endif
9605  if (!d->engine) {
9606  qWarning("QPainter::resetMatrix: Painter not active");
9607  return;
9608  }
9609 
9610  d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
9611  d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
9612  d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
9613  d->state->worldMatrix = QTransform();
9614  setMatrixEnabled(false);
9615  setViewTransformEnabled(false);
9616  if (d->extended)
9617  d->extended->transformChanged();
9618  else
9619  d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
9620 }
9621 
9630 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
9631 {
9632  Q_D(QPainter);
9633 
9634  if (!d->engine) {
9635  qWarning("QPainter::setWorldTransform: Painter not active");
9636  return;
9637  }
9638 
9639  if (combine)
9640  d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
9641  else
9642  d->state->worldMatrix = matrix; // set new matrix
9643 
9644  d->state->WxF = true;
9645  d->updateMatrix();
9646 }
9647 
9653 {
9654  Q_D(const QPainter);
9655  if (!d->engine) {
9656  qWarning("QPainter::worldTransform: Painter not active");
9657  return d->fakeState()->transform;
9658  }
9659  return d->state->worldMatrix;
9660 }
9661 
9670 {
9671  Q_D(const QPainter);
9672  if (!d->engine) {
9673  qWarning("QPainter::combinedTransform: Painter not active");
9674  return QTransform();
9675  }
9676  return d->state->worldMatrix * d->viewTransform();
9677 }
9678 
9697 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
9698  const QPixmap &pixmap, PixmapFragmentHints hints)
9699 {
9700  Q_D(QPainter);
9701 
9702  if (!d->engine || pixmap.isNull())
9703  return;
9704 
9705 #ifndef QT_NO_DEBUG
9706  for (int i = 0; i < fragmentCount; ++i) {
9707  QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9708  fragments[i].width, fragments[i].height);
9709  if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9710  qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9711  }
9712 #endif
9713 
9714  if (d->engine->isExtended()) {
9715  d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
9716  } else {
9717  qreal oldOpacity = opacity();
9718  QTransform oldTransform = transform();
9719 
9720  for (int i = 0; i < fragmentCount; ++i) {
9721  QTransform transform = oldTransform;
9722  qreal xOffset = 0;
9723  qreal yOffset = 0;
9724  if (fragments[i].rotation == 0) {
9725  xOffset = fragments[i].x;
9726  yOffset = fragments[i].y;
9727  } else {
9728  transform.translate(fragments[i].x, fragments[i].y);
9729  transform.rotate(fragments[i].rotation);
9730  }
9731  setOpacity(oldOpacity * fragments[i].opacity);
9732  setTransform(transform);
9733 
9734  qreal w = fragments[i].scaleX * fragments[i].width;
9735  qreal h = fragments[i].scaleY * fragments[i].height;
9736  QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9737  fragments[i].width, fragments[i].height);
9738  drawPixmap(QRectF(qreal(-0.5) * w + xOffset, qreal(-0.5) * h + yOffset, w, h), pixmap, sourceRect);
9739  }
9740 
9741  setOpacity(oldOpacity);
9742  setTransform(oldTransform);
9743  }
9744 }
9745 
9763 void QPainter::drawPixmapFragments(const QRectF *targetRects, const QRectF *sourceRects, int fragmentCount,
9764  const QPixmap &pixmap, PixmapFragmentHints hints)
9765 {
9766  Q_D(QPainter);
9767 
9768  if (!d->engine || pixmap.isNull())
9769  return;
9770 
9771 #ifndef QT_NO_DEBUG
9772  if (sourceRects) {
9773  for (int i = 0; i < fragmentCount; ++i) {
9774  QRectF sourceRect = sourceRects[i];
9775  if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9776  qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9777  }
9778  }
9779 #endif
9780 
9781  if (d->engine->isExtended()) {
9782  d->extended->drawPixmapFragments(targetRects, sourceRects, fragmentCount, pixmap, hints);
9783  } else {
9784  if (sourceRects) {
9785  for (int i = 0; i < fragmentCount; ++i)
9786  drawPixmap(targetRects[i], pixmap, sourceRects[i]);
9787  } else {
9788  QRectF sourceRect = pixmap.rect();
9789  for (int i = 0; i < fragmentCount; ++i)
9790  drawPixmap(targetRects[i], pixmap, sourceRect);
9791  }
9792  }
9793 }
9794 
9830  qreal scaleX, qreal scaleY, qreal rotation,
9831  qreal opacity)
9832 {
9833  PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
9834  sourceRect.height(), scaleX, scaleY, rotation, opacity};
9835  return fragment;
9836 }
9837 
9938 {
9939  p->draw_helper(path, operation);
9940 }
9941 
QRectF boundingRect(const QRectF &rect, int flags, const QString &text)
Returns the bounding rectangle of the text as it will appear when drawn inside the given rectangle wi...
Definition: qpainter.cpp:7093
QPainterPath clipPath() const
Returns the currently clip as a path.
Definition: qpainter.cpp:2690
void setTransform(const QTransform &transform, bool combine=false)
Sets the world transformation matrix.
Definition: qpainter.cpp:9547
void setBackgroundMode(Qt::BGMode mode)
Sets the background mode of the painter to the given mode.
Definition: qpainter.cpp:3998
void drawChord(const QRectF &rect, int a, int alen)
Draws the chord defined by the given rectangle, startAngle and spanAngle.
Definition: qpainter.cpp:4744
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
void resize(int size)
virtual QFixed lineThickness() const
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or 0 if the painter is not acti...
Definition: qpainter.cpp:1530
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
QRect toAlignedRect() const
Returns a QRect based on the values of this rectangle that is the smallest possible integer rectangle...
Definition: qrect.cpp:2817
Qt::BGMode backgroundMode() const
Returns the background mode in the current paint engine state.
Definition: qpainter.cpp:9316
T * q_check_ptr(T *p)
Definition: qglobal.h:1857
static Qt::LayoutDirection layoutDirection()
QFontEngine * fontEngine
QTextEngine * engine() const
Definition: qtextlayout.h:180
QPalette palette
the widget&#39;s palette
Definition: qwidget.h:180
QPaintDevice * redirected(QPoint *offset) const
Definition: qwidget_p.h:628
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
The QApplication class manages the GUI application&#39;s control flow and main settings.
Definition: qapplication.h:99
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition: qpixmap.cpp:2197
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
QRegion clipRegion
Definition: qpainter_p.h:155
Qt::LayoutDirection layoutDirection
Definition: qpainter_p.h:173
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
QGlyphJustification * justifications
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
void drawPath(const QPainterPath &path)
Draws the given painter path using the current pen for outline and the current brush for filling...
Definition: qpainter.cpp:3502
bool overline() const
Returns true if this QGlyphRun should be painted with an overline decoration.
Definition: qglyphrun.cpp:292
BrushStyle
Definition: qnamespace.h:1162
The QLatin1Literal class provides a thin wrapper around string literals used in source code...
QList< QPaintDeviceRedirection > QPaintDeviceRedirectionList
Definition: qpainter.cpp:8262
QFont font(const QScriptItem &si) const
QFixed * advances_y
static void setWorldTransform(QPainter *painter, const QTransform *const transformPtr, const QTransform *effectTransform)
void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, PixmapFragmentHints hints=0)
This function is used to draw pixmap, or a sub-rectangle of pixmap, at multiple positions with differ...
Definition: qpainter.cpp:9697
void drawPie(const QRectF &rect, int a, int alen)
Draws a pie defined by the given rectangle, startAngle and and spanAngle.
Definition: qpainter.cpp:4670
int type
Definition: qmetatype.cpp:239
#define Q_DUMMY_COMPARISON_OPERATOR(C)
Definition: qglobal.h:2104
qreal width
the width of the source rectangle and is used to calculate the width of the target rectangle...
Definition: qpainter.h:109
The QTextCharFormat class provides formatting information for characters in a QTextDocument.
Definition: qtextformat.h:372
double qreal
Definition: qglobal.h:1193
void draw_helper(const QPainterPath &path, DrawOperation operation=StrokeAndFillDraw)
Definition: qpainter.cpp:355
void drawArc(const QRectF &rect, int a, int alen)
Draws the arc defined by the given rectangle, startAngle and spanAngle.
Definition: qpainter.cpp:4602
The QStaticText class enables optimized drawing of text when the text and its layout is updated rarel...
Definition: qstatictext.h:60
static mach_timebase_info_data_t info
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
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:65
const QTransform & transform() const
Returns the world transformation matrix.
Definition: qpainter.cpp:9558
QPaintEngineEx * extended
Definition: qpainter_p.h:263
qreal opacity() const
Returns the opacity of the painter.
Definition: qpainter.cpp:2115
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const QColor & color() const
Returns the brush color.
Definition: qbrush.h:183
qreal horizontalAdvance() const
Returns the horizontal advance of the text.
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
void setPosition(const QPointF &pos)
Moves the line to position pos.
void drawRoundRect(const QRectF &r, int xround=25, int yround=25)
Draws a rectangle r with rounded corners.
Definition: qpainter.cpp:4414
QFontEngine * fontEngine() const
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
QPaintDevice * paintDevice() const
Returns the device that this engine is painting on, if painting is active; otherwise returns 0...
QPointer< QWidget > widget
ushort painters
Definition: qpaintdevice.h:109
Qt::ClipOperation operation
Definition: qpainter_p.h:119
void setBrush(const QBrush &brush)
Sets the brush used to fill strokes generated with this pen to the given brush.
Definition: qpen.cpp:808
virtual ~QPainterState()
Definition: qpainter.cpp:8766
QFixed * advances_x
virtual void transformChanged()=0
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
CompositionMode
Defines the modes supported for digital image compositing.
Definition: qpainter.h:138
The QLine class provides a two-dimensional vector using integer precision.
Definition: qline.h:57
void drawPoints(const QPointF *points, int pointCount)
Draws the first pointCount points in the array points using the current pen&#39;s color.
Definition: qpainter.cpp:3816
QPainter::RenderHints renderHints
Definition: qpainter_p.h:158
int width
the width of the widget excluding any window frame
Definition: qwidget.h:166
bool brushNeedsResolving() const
Returns whether the coordinate of the fill have been specified as bounded by the current rendering op...
Definition: qpainter.cpp:9411
QPaintDevice * replacement
Definition: qpainter.cpp:8255
int qCeil(qreal v)
Definition: qmath.h:63
const QPaintDevice * device
Definition: qpainter.cpp:8254
T * data() const
Returns the value of the pointer referenced by this object.
QPoint mapTo(QWidget *, const QPoint &) const
Translates the widget coordinate pos to the coordinate system of parent.
Definition: qwidget.cpp:4409
const QGradient * gradient() const
Returns the gradient describing this brush.
Definition: qbrush.cpp:871
const QBrush & background() const
Returns the current background brush.
Definition: qpainter.cpp:2482
void setViewport(const QRect &viewport)
Sets the painter&#39;s viewport rectangle to the given rectangle, and enables view transformations.
Definition: qpainter.cpp:7815
The QMatrix class specifies 2D transformations of a coordinate system.
Definition: qmatrix.h:61
virtual void drawPath(const QPainterPath &path)
The default implementation ignores the path and does nothing.
The QAtomicInt class provides platform-independent atomic operations on integers. ...
Definition: qatomic.h:55
QPainter::CompositionMode composition_mode
Definition: qpainter_p.h:174
static QGradient::CoordinateMode coordinateMode(const QBrush &brush)
Definition: qpainter.cpp:106
The QFlag class is a helper data type for QFlags.
Definition: qglobal.h:2289
Qt::BrushStyle qbrush_style(const QBrush &b)
Definition: qpainter_p.h:96
const QChar * chars
QFixedPoint * glyphPositions
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
HB_Glyph * glyphs
bool underline() const
Returns true if underline has been set; otherwise returns false.
Definition: qfont.cpp:1320
static bool is_brush_transparent(const QBrush &brush)
Definition: qpainter.cpp:127
bool worldMatrixEnabled() const
Returns true if world transformation is enabled; otherwise returns false.
Definition: qpainter.cpp:3188
QPaintEngineState * state
Definition: qpaintengine.h:239
QColor underlineColor() const
Returns the color used to underline the characters with this format.
Definition: qtextformat.h:448
void setTransform(const QTransform &)
Sets matrix as an explicit transformation matrix on the current brush.
Definition: qbrush.cpp:968
void setSystemTransform(const QTransform &xform)
void clearDirty(DirtyFlags df)
Definition: qpaintengine.h:354
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
CoordinateMode coordinateMode() const
Returns the coordinate mode of this gradient.
Definition: qbrush.cpp:1563
int qFloor(qreal v)
Definition: qmath.h:73
bool isValid() const
Returns true if the QRawFont is valid and false otherwise.
Definition: qrawfont.cpp:196
void rotate(qreal a)
Rotates the coordinate system the given angle clockwise.
Definition: qpainter.cpp:3287
static const uchar inv
Definition: qisciicodec.cpp:91
QPainterState * state
Definition: qpainter_p.h:204
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
QScopedPointer< QBrushData, QBrushDataPointerDeleter > d
Definition: qbrush.h:146
void addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode=Qt::AbsoluteSize)
Adds the given rectangle rect with rounded corners to the path.
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
int pixelSize() const
Returns the pixel size of the font if it was set with setPixelSize().
Definition: qfont.cpp:1178
int height() const
Definition: qpaintdevice.h:92
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation...
Definition: qpainter.cpp:2801
QTransform transform() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9377
void shear(qreal sh, qreal sv)
Shears the coordinate system by ({sh}, {sv}).
Definition: qpainter.cpp:3258
unsigned char untransformedCoordinates
QRectF clipBoundingRect() const
Returns the bounding rectangle of the current clip if there is a clip; otherwise returns an empty rec...
Definition: qpainter.cpp:2741
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
virtual void updateState(const QPaintEngineState &state)=0
Reimplement this function to update the state of a paint engine.
void setCapStyle(Qt::PenCapStyle style)
Sets the cap style of the generated outlines to style.
QFont font
the font currently set for the widget
Definition: qwidget.h:181
T * take()
Returns the value of the pointer referenced by this object.
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
void closeSubpath()
Closes the current subpath by drawing a line to the beginning of the subpath, automatically starting ...
FillRule
Definition: qnamespace.h:1485
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
The QTextLine class represents a line of text inside a QTextLayout.
Definition: qtextlayout.h:197
QPainterPrivate(QPainter *painter)
Definition: qpainter_p.h:192
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
static QRawFontPrivate * get(const QRawFont &font)
Definition: qrawfont_p.h:109
void restore()
Restores the current painter state (pops a saved state off the stack).
Definition: qpainter.cpp:1620
~QPainter()
Destroys the painter.
Definition: qpainter.cpp:1502
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
bool matrixEnabled() const
Definition: qpainter.cpp:3222
int * underlinePositions
QRect normalized() const
Returns a normalized rectangle; i.e., a rectangle that has a non-negative width and height...
Definition: qrect.cpp:322
void updateMatrix()
Definition: qpainter.cpp:662
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
void setMatrixEnabled(bool enabled)
Use setWorldMatrixEnabled() instead.
Definition: qpainter.cpp:3209
void updateState(QPainterState *state)
Definition: qpainter.cpp:926
QStaticTextItem * items
void checkEmulation()
Definition: qpainter.cpp:182
QRect window() const
Returns the window rectangle.
Definition: qpainter.cpp:7774
QPointF topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:539
Flags flags() const
Returns the flags associated with the option.
Definition: qtextoption.h:121
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
Definition: qpainter.cpp:9937
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString &str, QRectF *brect, int tabstops, int *tabarray, int tabarraylen, QPainter *painter)
Definition: qpainter.cpp:8458
void reset()
Resets the matrix to an identity matrix, i.e.
Definition: qmatrix.cpp:897
void setCosmetic(bool cosmetic)
Sets this pen to cosmetic or non-cosmetic, depending on the value of cosmetic.
Definition: qpen.cpp:854
virtual uint flags() const
QScriptItemArray items
QPalette::ColorRole backgroundRole() const
Returns the background role of the widget.
Definition: qwidget.cpp:4677
uint changeFlags
Definition: qpainter_p.h:176
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
Definition: qimage.cpp:6495
ClipType clipType
Definition: qpainter_p.h:117
const unsigned short * logClusters
CoordinateMode
This enum specifies how gradient coordinates map to the paint device on which the gradient is used...
Definition: qbrush.h:219
QPaintEngine::DirtyFlags dirtyFlags
Definition: qpaintengine.h:325
long ASN1_INTEGER_get ASN1_INTEGER * a
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
static QStyle * style()
Returns the application&#39;s style object.
void setLineWidth(qreal width)
Lays out the line with the given width.
The QPolygon class provides a vector of points using integer precision.
Definition: qpolygon.h:60
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
void drawLine(const QLineF &line)
Draws a line defined by line.
Definition: qpainter.h:573
int depth() const
Returns the depth of the pixmap.
Definition: qpixmap.cpp:695
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
LayoutData * layoutData
QRectF intersected(const QRectF &other) const
Returns the intersection of this rectangle and the given rectangle.
Definition: qrect.h:818
unsigned short * logClusters(const QScriptItem *si) const
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
QRect rect() const
Returns the enclosing rectangle (0, 0, width(), height()) of the image.
Definition: qimage.cpp:1603
QFontInfo fontInfo() const
Returns the font info for the painter if the painter is active.
Definition: qpainter.cpp:2095
QList< qreal > tabArray() const
Returns a list of tab positions defined for the text layout.
const QMatrix & deviceMatrix() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
Definition: qpainter.cpp:3110
QMatrix matrix() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9355
static QFixed fromReal(qreal r)
Definition: qfixed_p.h:70
void setWorldMatrixEnabled(bool enabled)
Enables transformations if enable is true, or disables transformations if enable is false...
Definition: qpainter.cpp:3157
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const =0
TransformationType type() const
Returns the transformation type of this matrix.
uint forceJustification
QString text() const
Returns the text that should be drawn.
bool penNeedsResolving() const
Returns whether the coordinate of the stroke have been specified as bounded by the current rendering ...
Definition: qpainter.cpp:9428
#define Q_D(Class)
Definition: qglobal.h:2482
static QFixedPoint fromPointF(const QPointF &p)
Definition: qfixed_p.h:195
void qt_painter_removePaintDevice(QPaintDevice *dev)
Definition: qpainter.cpp:8419
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
void setBrushOrigin(int x, int y)
Sets the brush&#39;s origin to point (x, y).
Definition: qpainter.h:825
bool isValid() const
Returns true if this text line is valid; otherwise returns false.
Definition: qtextlayout.h:201
virtual int devType() const
Definition: qpaintdevice.h:167
QPainterDummyState * dummyState
Definition: qpainter_p.h:207
void arcMoveTo(const QRectF &rect, qreal angle)
Creates a move to that lies on the arc that occupies the given rectangle at angle.
void setMiterLimit(qreal length)
Sets the miter limit of the generated outlines to limit.
void init(QPainter *p)
Definition: qpainter.cpp:8770
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation)
Definition: qpainter.cpp:512
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QChar * data()
Returns a pointer to the data stored in the QString.
Definition: qstring.h:710
const quint32 * glyphIndexData
Definition: qglyphrun_p.h:104
QBrush bgBrush
Definition: qpainter_p.h:154
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
QPaintDevice * redirectDev
Definition: qwidget_p.h:706
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
void setFontEngine(QFontEngine *fe)
qreal tabStop() const
Returns the distance in device units between tab stops.
Definition: qtextoption.h:124
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
PenStyle
Definition: qnamespace.h:1134
void save()
Saves the current painter state (pushes the state onto a stack).
Definition: qpainter.cpp:1590
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
static QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
Definition: qpainter.cpp:531
static QPixmap * find(const QString &key)
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
#define Q_Q(Class)
Definition: qglobal.h:2483
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false...
Definition: qpainter.cpp:1723
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision...
Qt::ClipOperation clipOperation
Definition: qpainter_p.h:157
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
bool isIdentity() const
Returns true if the matrix is the identity matrix, otherwise returns false.
Definition: qtransform.h:204
void setDashPattern(Qt::PenStyle)
Sets the dash pattern for the generated outlines to style.
QFont deviceFont
Definition: qpainter_p.h:151
static const QRectF boundingRect(const QPointF *points, int pointCount)
static QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
Definition: qpainter.cpp:5518
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
static QStaticTextPrivate * get(const QStaticText *q)
void setColor(const QColor &color)
Sets the color of this pen&#39;s brush to the given color.
Definition: qpen.cpp:787
QVector< QPainterState * > states
Definition: qpainter_p.h:205
Q_CORE_EXPORT void qDebug(const char *,...)
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
static void qt_cleanup_painter_state(QPainterPrivate *d)
Definition: qpainter.cpp:1714
bool contains(const QPointF &p) const
Returns true if the given point is inside or on the edge of the rectangle; otherwise returns false...
Definition: qrect.cpp:2349
QGlyphLayout glyphs
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
static uint line_emulation(uint emulation)
Definition: qpainter.cpp:143
void resetMatrix()
Resets any transformations that were made using translate(), scale(), shear(), rotate(), setWorldMatrix(), setViewport() and setWindow().
Definition: qpainter.cpp:3137
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition: qfont.cpp:1983
void shapeLine(const QScriptLine &line)
QTransform invMatrix
Definition: qpainter_p.h:209
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
void setAlignment(Qt::Alignment alignment)
Sets the option&#39;s text alignment to the specified alignment.
Definition: qtextoption.h:148
QRegion clipRegion() const
Returns the currently set clip region.
Definition: qpainter.cpp:2562
void drawText(const QPointF &p, const QString &s)
Draws the given text with the currently defined text direction, beginning at the given position...
Definition: qpainter.cpp:6231
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
void translate(const QPointF &p)
Translates this line by the given offset.
Definition: qline.h:339
void setRenderHint(RenderHint hint, bool on=true)
Sets the given render hint on the painter if on is true; otherwise clears the render hint...
Definition: qpainter.cpp:7620
TransformationType
Definition: qtransform.h:68
QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement, const QPoint &offset, int internalWidgetRedirectionIndex)
Definition: qpainter.cpp:8250
void drawRects(const QRectF *rects, int rectCount)
Draws the first rectCount of the given rectangles using the current pen and brush.
Definition: qpainter.cpp:3641
QFuture< void > map(Sequence &sequence, MapFunction function)
const QPen & pen() const
Returns the painter&#39;s current pen.
Definition: qpainter.cpp:4152
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation)
Definition: qpainter.cpp:547
#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
void resetTransform()
Resets any transformations that were made using translate(), scale(), shear(), rotate(), setWorldTransform(), setViewport() and setWindow().
Definition: qpainter.cpp:9598
const QMatrix & toAffine() const
Returns the QTransform as an affine matrix.
QWidget * nativeParentWidget() const
Returns the native parent for this widget, i.
Definition: qwidget.cpp:4514
void drawEllipse(const QRectF &r)
Draws the ellipse defined by the given rectangle.
Definition: qpainter.cpp:4464
static QGlyphRunPrivate * get(const QGlyphRun &glyphRun)
Definition: qglyphrun_p.h:110
QFontMetrics fontMetrics() const
Returns the font metrics for the painter if the painter is active.
Definition: qpainter.cpp:2077
int width() const
Definition: qpaintdevice.h:91
const QMatrix & matrix() const
Use worldTransform() instead.
Definition: qpainter.cpp:3061
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
QFixed y
Definition: qfixed_p.h:191
UnderlineStyle
This enum describes the different ways drawing underlined text.
Definition: qtextformat.h:384
Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
Definition: qregion.cpp:1160
QPainterPath createStroke(const QPainterPath &path) const
Generates a new path that is a fillable area representing the outline of the given path...
static void restoreRedirected(const QPaintDevice *device)
Using QWidget::render() obsoletes the use of this function.
Definition: qpainter.cpp:8344
QPoint brushOrigin() const
Returns the currently set brush origin.
Definition: qpainter.cpp:2168
void updateStateImpl(QPainterState *state)
Definition: qpainter.cpp:894
qreal y
the y coordinate of the center point in the target rectangle.
Definition: qpainter.h:106
bool qHasPixmapTexture(const QBrush &)
Definition: qbrush.cpp:223
void drawLines(const QLineF *lines, int lineCount)
Draws the first lineCount lines in the array lines using the current pen.
Definition: qpainter.cpp:4873
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
Definition: qpainter.cpp:9396
void fillPath(const QPainterPath &path, const QBrush &brush)
Fills the given path using the given brush.
Definition: qpainter.cpp:3456
QPointF brushOrigin() const
Returns the brush origin in the current paint engine state.
Definition: qpainter.cpp:9287
void drawPicture(const QPointF &p, const QPicture &picture)
Replays the given picture at the given point.
Definition: qpainter.cpp:7282
bool overline() const
Returns true if overline has been set; otherwise returns false.
Definition: qfont.cpp:1344
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
QBrush qpen_brush(const QPen &p)
Definition: qpainter_p.h:87
bool hasClipping() const
Returns true if clipping has been set; otherwise returns false.
Definition: qpainter.cpp:2499
QPalette::ColorRole foregroundRole() const
Returns the foreground role.
Definition: qwidget.cpp:4728
int height
the height of the widget excluding any window frame
Definition: qwidget.h:167
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition: qwidget.h:1041
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
void drawConvexPolygon(const QPointF *points, int pointCount)
Draws the convex polygon defined by the first pointCount points in the array points using the current...
Definition: qpainter.cpp:5484
static Qt::LayoutDirection layout_direction
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
bool operator==(const QPaintDevice *pdev) const
Definition: qpainter.cpp:8258
#define qApp
QPainterPath path
Definition: qpainter_p.h:120
void beginNativePainting()
Flushes the painting pipeline and prepares for the user issuing commands directly to the underlying g...
Definition: qpainter.cpp:2032
QPainter * painter
Definition: qpainter_p.h:172
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
QFont font() const
Returns the font in the current paint engine state.
Definition: qpainter.cpp:9331
const QFont & font() const
Returns the currently set font used for drawing text.
Definition: qpainter.cpp:4312
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
qreal x
the x coordinate of center point in the target rectangle.
Definition: qpainter.h:105
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
bool isActive() const
Returns true if begin() has been called and end() has not yet been called; otherwise returns false...
Definition: qpainter.cpp:1545
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
QGlyphLayout shapedGlyphs(const QScriptItem *si) const
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
Definition: qpainter.cpp:240
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
int lineNumber() const
Returns the position of the line in the text engine.
Definition: qtextlayout.h:243
virtual QFixed ascent() const =0
virtual Type type() const =0
Reimplement this function to return the paint engine Type.
LayoutDirection
Definition: qnamespace.h:1580
virtual QFixed descent() const =0
static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder)
CompositionMode compositionMode() const
Returns the current composition mode.
Definition: qpainter.cpp:2466
const char * styleHint(const QFontDef &request)
qreal height() const
Returns the height of the font.
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.
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
QPainter::CompositionMode compositionMode() const
Returns the composition mode in the current paint engine state.
Definition: qpainter.cpp:9503
bool isQBitmap() const
Returns true if this is a QBitmap; otherwise returns false.
Definition: qpixmap.cpp:599
unsigned int uint
Definition: qglobal.h:996
static bool supportsThreadedFontRendering()
Returns true if font rendering is supported outside the GUI thread, false otherwise.
const QTransform & deviceTransform() const
Returns the matrix that transforms from logical coordinates to device coordinates of the platform dep...
Definition: qpainter.cpp:9579
RenderHint
Renderhints are used to specify flags to QPainter that may or may not be respected by any given engin...
Definition: qpainter.h:93
void drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
Draws the specified glyphs at the given position.
Definition: qpainter.cpp:6064
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
QPaintEngine * paintEngine() const
Returns the paint engine that the painter is currently operating on if the painter is active; otherwi...
Definition: qpainter.cpp:1991
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws the polygon defined by the first pointCount points in the array points using the current pen an...
Definition: qpainter.cpp:5205
static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX=1, qreal scaleY=1, qreal rotation=0, qreal opacity=1)
This is a convenience function that returns a QPainter::PixmapFragment that is initialized with the p...
Definition: qpainter.cpp:9829
void setWorldMatrix(const QMatrix &matrix, bool combine=false)
Sets the transformation matrix to matrix and enables transformations.
Definition: qpainter.cpp:3003
QList< QPainterClipInfo > clipInfo
Definition: qpainter_p.h:159
QTransform combinedTransform() const
Returns the transformation matrix combining the current window/viewport and world transformation...
Definition: qpainter.cpp:9669
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
void setDirty(DirtyFlags df)
Definition: qpaintengine.h:349
void setTextDirection(Qt::LayoutDirection aDirection)
Sets the direction of the text layout defined by the option to the given direction.
Definition: qtextoption.h:99
virtual void setState(QPainterState *s)
The QPainterPathStroker class is used to generate fillable outlines for a given painter path...
Definition: qpainterpath.h:264
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Definition: qpainter.cpp:9457
void clear()
Removes all items from the list.
Definition: qlist.h:764
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition: qpen.cpp:797
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
static void setRedirected(const QPaintDevice *device, QPaintDevice *replacement, const QPoint &offset=QPoint())
Please use QWidget::render() instead.
Definition: qpainter.cpp:8293
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)=0
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
Qt::BrushStyle style() const
Returns the brush style.
Definition: qbrush.h:182
QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition: qrect.h:781
QScriptLineArray lines
void itemize() const
QPixmap texture() const
Returns the custom brush pattern, or a null pixmap if no custom brush pattern has been set...
Definition: qbrush.cpp:785
bool isOpaque() const
Returns true if the brush is fully opaque otherwise false.
Definition: qbrush.cpp:910
QTextOption option
The QGlyphRun class provides direct access to the internal glyphs in a font.
Definition: qglyphrun.h:59
QTransform viewTransform() const
Definition: qpainter.cpp:224
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
QRect viewport() const
Returns the viewport rectangle.
Definition: qpainter.cpp:7844
#define QT_CATCH(A)
Definition: qglobal.h:1537
QRawFont rawFont() const
Returns the font selected for this QGlyphRun object.
Definition: qglyphrun.cpp:180
The QFontInfo class provides general information about fonts.
Definition: qfontinfo.h:54
QTextLine lineAt(int i) const
Returns the {i}-th line of text in this text layout.
void strokePath(const QPainterPath &path, const QPen &pen)
Draws the outline (strokes) the path path with the pen specified by pen.
Definition: qpainter.cpp:3413
QRect toRect() const
Returns a QRect based on the values of this rectangle.
Definition: qrect.h:845
QList< Tab > tabs() const
Returns a list of tab positions defined for the text layout.
void reset(T *other=0)
Deletes the existing object it is pointing to if any, and sets its pointer to other.
virtual void systemStateChanged()
qreal pixelSize
Definition: qfont_p.h:90
const QBrush & brush(ColorGroup cg, ColorRole cr) const
Returns the brush in the specified color group, used for the given color role.
Definition: qpalette.cpp:874
void setWindow(const QRect &window)
Sets the painter&#39;s window to the given rectangle, and enables view transformations.
Definition: qpainter.cpp:7745
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, const QFixedPoint *positions, int glyphCount, QFontEngine *fontEngine, const QFont &font, const QTextCharFormat &charFormat)
Definition: qpainter.cpp:6820
void detachPainterPrivate(QPainter *q)
Definition: qpainter.cpp:328
QMatrix combinedMatrix() const
Returns the transformation matrix combining the current window/viewport and world transformation...
Definition: qpainter.cpp:3082
void updateInvMatrix()
Definition: qpainter.cpp:680
QPainter * painter() const
Returns a pointer to the painter currently updating the paint engine.
Definition: qpainter.cpp:9514
const QPointF * glyphPositionData
Definition: qglyphrun_p.h:107
bool isTranslating() const
Returns true if the matrix represents a translating transformation, otherwise returns false...
Definition: qtransform.h:223
unsigned short flags
const QBrush & brush() const
Returns the painter&#39;s current brush.
Definition: qpainter.cpp:4232
Qt::LayoutDirection layoutDirection() const
Returns the layout direction used by the painter when drawing text.
Definition: qpainter.cpp:8729
void drawTiledPixmap(const QRectF &rect, const QPixmap &pm, const QPointF &offset=QPointF())
Draws a tiled pixmap, inside the given rectangle with its origin at the given position.
Definition: qpainter.cpp:7146
int width() const
Returns the pen width with integer precision.
Definition: qpen.cpp:630
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
void setRenderHints(RenderHints hints, bool on=true)
Sets the given render hints on the painter if on is true; otherwise clears the render hints...
Definition: qpainter.cpp:7649
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
QPixmap qt_pixmapForBrush(int style, bool invert)
Definition: qbrush.cpp:99
void reset()
Resets the matrix to an identity matrix, i.e.
QFixed x
Definition: qfixed_p.h:190
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
bool underline() const
Returns true if this QGlyphRun should be painted with an underline decoration.
Definition: qglyphrun.cpp:317
void setTabArray(QList< qreal > tabStops)
Sets the tab positions for the text layout to those specified by tabStops.
virtual QPaintEngine * paintEngine() const =0
QPainter()
Constructs a painter.
Definition: qpainter.cpp:1459
#define Q_CHECK_PTR(p)
Definition: qglobal.h:1853
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
bool isAffine() const
Returns true if the matrix represent an affine transformation, otherwise returns false.
Definition: qtransform.h:200
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
The QTextLayout class is used to lay out and render text.
Definition: qtextlayout.h:105
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
Transforms an alignment of Qt::AlignLeft or Qt::AlignRight without Qt::AlignAbsolute into Qt::AlignLe...
Definition: qstyle.cpp:2149
void updateEmulationSpecifier(QPainterState *s)
Definition: qpainter.cpp:689
void * qMemSet(void *dest, int c, size_t n)
Definition: qglobal.cpp:2509
void setViewTransformEnabled(bool enable)
Enables view transformations if enable is true, or disables view transformations if enable is false...
Definition: qpainter.cpp:7906
void setClipRegion(const QRegion &, Qt::ClipOperation op=Qt::ReplaceClip)
Sets the clip region to the given region using the specified clip operation.
Definition: qpainter.cpp:2917
QPainter::RenderHints renderHints() const
Returns the render hints in the current paint engine state.
Definition: qpainter.cpp:9488
const QTransform & worldTransform() const
Returns the world transformation matrix.
Definition: qpainter.cpp:9652
qreal leading() const
Returns the leading of the font.
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
Definition: qpainter.cpp:2422
void justify(const QScriptLine &si)
The QRawFont class provides access to a single physical instance of a font.
Definition: qrawfont.h:63
ushort alpha
Returns the alpha color component of this color.
Definition: qcolor.h:242
void setClipping(bool enable)
Enables clipping if enable is true, or disables clipping if enable is false.
Definition: qpainter.cpp:2517
The QFont class specifies a font used for drawing text.
Definition: qfont.h:64
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
Qt::BGMode backgroundMode() const
Returns the current background mode.
Definition: qpainter.cpp:4026
The QGradient class is used in combination with QBrush to specify gradient fills. ...
Definition: qbrush.h:201
bool hasAlpha() const
Returns true if this pixmap has an alpha channel, or has a mask, otherwise returns false...
Definition: qpixmap.cpp:1938
void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
Draws the given staticText at the given topLeftPosition.
Definition: qpainter.cpp:6260
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
This class is used in conjunction with the QPainter::drawPixmapFragments() function to specify how a ...
Definition: qpainter.h:103
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor)
Reimplement this function to draw the part of the image specified by the sr rectangle in the given re...
QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition: qpoint.h:376
void setWidthF(qreal width)
Sets the pen width to the given width in pixels with floating point precision.
Definition: qpen.cpp:690
QPainterPrivate ** d_ptrs
Definition: qpainter_p.h:202
static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition=false)
Definition: qpainter.cpp:156
qreal scaleX
the horizontal scale of the target rectangle.
Definition: qpainter.h:111
QTextLine createLine()
Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise ret...
Qt::LayoutDirection textDirection() const
Returns the direction of the text layout defined by the option.
Definition: qtextoption.h:100
qreal naturalTextWidth() const
Returns the width of the line that is occupied by text.
uint clipEnabled
Definition: qpainter_p.h:169
QString family() const
Returns the requested font family name, i.e.
Definition: qfont.cpp:906
qreal miterLimit() const
Returns the miter limit of the pen.
Definition: qpen.cpp:589
void setCoordinateMode(CoordinateMode mode)
Sets the coordinate mode of this gradient to mode.
Definition: qbrush.cpp:1578
void arcTo(const QRectF &rect, qreal startAngle, qreal arcLength)
Creates an arc that occupies the given rectangle, beginning at the specified startAngle and extending...
void eraseRect(const QRectF &)
Erases the area inside the given rectangle.
Definition: qpainter.cpp:7332
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
#define st(var, type, card)
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
void drawTextItem(const QPointF &p, const QTextItem &ti)
Draws the text item ti at position p.
Definition: qpainter.cpp:6864
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style of the generated outlines to style.
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
void setBrush(const QBrush &brush)
Sets the painter&#39;s brush to the given brush.
Definition: qpainter.cpp:4171
QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const
void setMatrix(const QMatrix &matrix, bool combine=false)
Use setWorldTransform() instead.
Definition: qpainter.cpp:3045
unsigned int quint32
Definition: qglobal.h:938
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
int length(int item) const
void setPen(const QColor &color)
Sets the painter&#39;s pen to have style Qt::SolidLine, width 0 and the specified color.
Definition: qpainter.cpp:4047
QPointF brushOrigin
Definition: qpainter_p.h:149
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
Definition: qnamespace.h:54
QTransform redirectionMatrix
Definition: qpainter_p.h:162
#define Q_AUTOTEST_EXPORT
Definition: qglobal.h:1510
WrapMode wrapMode() const
Returns the text wrap mode defined by the option.
Definition: qtextoption.h:110
QFactoryLoader * l
qreal toReal() const
Definition: qfixed_p.h:77
static bool check_gradient(const QBrush &brush)
Definition: qpainter.cpp:120
The QTextOption class provides a description of general rich text properties.
Definition: qtextoption.h:59
void setWorldTransform(const QTransform &matrix, bool combine=false)
Sets the world transformation matrix.
Definition: qpainter.cpp:9630
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
WId internalWinId() const
Returns the window system identifier of the widget, or 0 if the widget is not created yet...
Definition: qwidget.h:244
QSizeF size() const
Returns the size of the rectangle.
Definition: qrect.h:713
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
#define QPaintEngine_OpaqueBackground
Definition: qpainter.cpp:83
virtual int metric(PaintDeviceMetric metric) const
signed int length
void drawRect(const QRectF &rect)
Draws the current rectangle with the current pen and brush.
Definition: qpainter.h:650
void quadTo(const QPointF &ctrlPt, const QPointF &endPt)
Adds a quadratic Bezier curve between the current position and the given endPoint with the control po...
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
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Definition: qpainter.cpp:5936
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
quint16 index
void drawGlyphs(const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount, const QRawFont &font, bool overline=false, bool underline=false, bool strikeOut=false)
Definition: qpainter.cpp:6101
void initFrom(const QWidget *widget)
Initializes the painters pen, background and font to the same as the given widget.
Definition: qpainter.cpp:1558
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
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
Definition: qpainter.cpp:9443
QFixed effectiveAdvance(int item) const
QPainterPath clipPath
Definition: qpainter_p.h:156
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
void scale(qreal sx, qreal sy)
Scales the coordinate system by ({sx}, {sy}).
Definition: qpainter.cpp:3234
QPaintDevice * helper_device
Definition: qpainter_p.h:260
Qt::Alignment alignment() const
Returns the text alignment defined by the option.
Definition: qtextoption.h:97
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device...
Definition: qpainter.cpp:5619
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
HB_GlyphAttributes * attributes
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
#define QGradient_StretchToDevice
Definition: qpainter.cpp:82
void setWrapMode(WrapMode wrap)
Sets the option&#39;s text wrap mode to the given mode.
Definition: qtextoption.h:109
QFontEngine * fontEngine
Definition: qrawfont_p.h:111
The QFontMetricsF class provides font metrics information.
Definition: qfontmetrics.h:145
int pointSize() const
Returns the point size of the font.
Definition: qfont.cpp:981
T * data()
Returns a pointer to the data stored in the vector.
Definition: qvector.h:152
void setFont(const QFont &f)
Sets the painter&#39;s font to the given font.
Definition: qpainter.cpp:4288
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
qreal width(const QString &string) const
Returns the width in pixels of the characters in the given text.
static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
Definition: qpainter.cpp:6687
QPaintDevice * device
Definition: qpainter_p.h:258
unsigned char needsRelayout
uint emulationSpecifier
Definition: qpainter_p.h:175
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
RenderHints renderHints() const
Returns a flag that specifies the rendering hints that are set for this painter.
Definition: qpainter.cpp:7675
void setCacheEnabled(bool enable)
Enables caching of the complete layout information if enable is true; otherwise disables layout cachi...
void setClipPath(const QPainterPath &path, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip path for the painter to the given path, with the clip operation...
Definition: qpainter.cpp:3365
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
Qt::BGMode bgMode
Definition: qpainter_p.h:171
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
void setLayoutDirection(Qt::LayoutDirection direction)
Sets the layout direction used by the painter when drawing text, to the specified direction...
Definition: qpainter.cpp:8717
SizeMode
Definition: qnamespace.h:1187
Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush)
Definition: qbrush.cpp:881
void endLayout()
Ends the layout process.
bool isValid() const
Returns true if the color is valid; otherwise returns false.
Definition: qcolor.h:295
void setOpacity(qreal opacity)
Sets the opacity of the painter to opacity.
Definition: qpainter.cpp:2139
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
QString text() const
Returns the text of the QStaticText.
QFontDef fontDef
QTransform worldMatrix
Definition: qpainter_p.h:160
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode=Qt::AbsoluteSize)
Draws the given rectangle rect with rounded corners.
Definition: qpainter.cpp:4348
QPixmap copy(int x, int y, int width, int height) const
Returns a deep copy of the subset of the pixmap that is specified by the rectangle QRect( x...
Definition: qpixmap.h:302
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:658
bool strikeOut() const
Returns true if strikeout has been set; otherwise returns false.
Definition: qfont.cpp:1367
bool viewTransformEnabled() const
Returns true if view transformation is enabled; otherwise returns false.
Definition: qpainter.cpp:7704
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
QRectF normalized() const
Returns a normalized rectangle; i.e., a rectangle that has a non-negative width and height...
Definition: qrect.cpp:1822
QFixedPoint * offsets
Qt::PenStyle qpen_style(const QPen &p)
Definition: qpainter_p.h:89
QImage textureImage() const
Returns the custom brush pattern, or a null image if no custom brush pattern has been set...
Definition: qbrush.cpp:829
const QMatrix & worldMatrix() const
Returns the world transformation matrix.
Definition: qpainter.cpp:3024
The QPicture class is a paint device that records and replays QPainter commands.
Definition: qpicture.h:58
virtual QPoint coordinateOffset() const
Returns the offset from the painters origo to the engines origo.
void drawPolyline(const QPointF *points, int pointCount)
Draws the polyline defined by the first pointCount points in points using the current pen...
Definition: qpainter.cpp:5055
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
Definition: qmatrix.cpp:389
#define qPrintable(string)
Definition: qglobal.h:1750
qreal height
the height of the source rectangle and is used to calculate the height of the target rectangle...
Definition: qpainter.h:110
QPointF center() const
Returns the center point of the rectangle.
Definition: qrect.h:686
static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat)
Definition: qpainter.cpp:6738
void endNativePainting()
Restores the painter after manually issuing native painting commands.
Definition: qpainter.cpp:2056
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
#define QT_TRY
Definition: qglobal.h:1536
BGMode
Definition: qnamespace.h:588
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection=0) const
Draws a line on the given painter at the specified position.
QString name() const
Returns the name of the color in the format "#RRGGBB"; i.e.
Definition: qcolor.cpp:529
bool strikeOut() const
Returns true if this QGlyphRun should be painted with a strike out decoration.
Definition: qglyphrun.cpp:342
qreal height() const
Returns the line&#39;s height.
unsigned int glyph_t
QRgb rgb() const
Returns the RGB value of the color.
Definition: qcolor.cpp:1051
static QPaintDevice * redirected(const QPaintDevice *device, QPoint *offset=0)
Using QWidget::render() obsoletes the use of this function.
Definition: qpainter.cpp:8391
static bool is_pen_transparent(const QPen &pen)
Definition: qpainter.cpp:136
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
virtual QFixed underlinePosition() const
void setBackground(const QBrush &bg)
Sets the background brush of the painter to the given brush.
Definition: qpainter.cpp:4258
void setTabStop(qreal tabStop)
Sets the default distance in device units between tab stops to the value specified by tabStop...
Definition: qtextoption.h:154
void beginLayout()
Begins the layout process.
QWidget * currentClipWidget
QFixed leadingSpaceWidth(const QScriptLine &line)
void paintText(const QPointF &pos, QPainter *p)
bool end()
Ends painting.
Definition: qpainter.cpp:1929
QFontEngine * engine(int at) const
QEmulationPaintEngine * emulationEngine
Definition: qpainter_p.h:262
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
QMatrix inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qmatrix.cpp:1066
void addEllipse(const QRectF &rect)
Creates an ellipse within the specified boundingRectangle and adds it to the painter path as a closed...
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420
#define text
Definition: qobjectdefs.h:80
int size() const
int lineCount() const
Returns the number of lines in this text layout.
static qreal toReal(Register *reg, int type, bool *ok=0)
void setStyle(Qt::PenStyle)
Sets the pen style to the given style.
Definition: qpen.cpp:450
bool hasFeature(PaintEngineFeatures feature) const
Returns true if the paint engine supports the specified feature; otherwise returns false...
Definition: qpaintengine.h:229
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
static bool needsResolving(const QBrush &brush)
Definition: qpainter.cpp:7339
void setWidth(qreal width)
Sets the width of the generated outline painter path to width.
void setWidth(int width)
Sets the pen width to the given width in pixels with integer precision.
Definition: qpen.cpp:667
QScopedPointer< QPainterPrivate > d_ptr
Definition: qpainter.h:546
QPaintEngine * engine
Definition: qpainter_p.h:261
ClipOperation
Definition: qnamespace.h:1495
bool isSolid() const
Returns true if the pen has a solid fill, otherwise false.
Definition: qpen.cpp:820
Qt::LayoutDirection direction
QScriptAnalysis analysis
#define Q_FUNC_INFO
Definition: qglobal.h:1871
glyph_t * glyphs
QBrush backgroundBrush() const
Returns the background brush in the current paint engine state.
Definition: qpainter.cpp:9301
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311
The QPalette class contains color groups for each widget state.
Definition: qpalette.h:61
void removeAt(int i)
Removes the item at index position i.
Definition: qlist.h:480