Qt 4.8
qpaintengine_raster.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <QtCore/qglobal.h>
43 #include <QtCore/qmutex.h>
44 
45 #define QT_FT_BEGIN_HEADER
46 #define QT_FT_END_HEADER
47 
48 #include <private/qrasterdefs_p.h>
49 #include <private/qgrayraster_p.h>
50 
51 #include <qpainterpath.h>
52 #include <qdebug.h>
53 #include <qhash.h>
54 #include <qlabel.h>
55 #include <qbitmap.h>
56 #include <qmath.h>
57 
58 #if defined (Q_WS_X11)
59 # include <private/qfontengine_ft_p.h>
60 #endif
61 
62 // #include <private/qdatabuffer_p.h>
63 // #include <private/qpainter_p.h>
64 #include <private/qmath_p.h>
65 #include <private/qtextengine_p.h>
66 #include <private/qfontengine_p.h>
67 #include <private/qpixmap_raster_p.h>
68 // #include <private/qpolygonclipper_p.h>
69 // #include <private/qrasterizer_p.h>
70 #include <private/qimage_p.h>
71 #include <private/qstatictext_p.h>
72 #include <private/qcosmeticstroker_p.h>
73 #include "qmemrotate_p.h"
74 
75 #include "qpaintengine_raster_p.h"
76 // #include "qbezier_p.h"
77 #include "qoutlinemapper_p.h"
78 
79 #if defined(Q_WS_WIN)
80 # include <qt_windows.h>
81 # include <qvarlengtharray.h>
82 # include <private/qfontengine_p.h>
83 # if defined(Q_OS_WINCE)
84 # include "qguifunctions_wince.h"
85 # endif
86 #elif defined(Q_WS_MAC)
87 # include <private/qt_mac_p.h>
88 # include <private/qpixmap_mac_p.h>
89 # include <private/qpaintengine_mac_p.h>
90 #elif defined(Q_WS_QWS)
91 # if !defined(QT_NO_FREETYPE)
92 # include <private/qfontengine_ft_p.h>
93 # endif
94 # if !defined(QT_NO_QWS_QPF2)
95 # include <private/qfontengine_qpf_p.h>
96 # endif
97 # include <private/qabstractfontengine_p.h>
98 #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
99 # include <private/qfontengine_s60_p.h>
100 #elif defined(Q_WS_QPA)
101 # include <private/qfontengine_ft_p.h>
102 #endif
103 
104 #if defined(Q_WS_WIN64)
105 # include <malloc.h>
106 #endif
107 #include <limits.h>
108 
110 
111 Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
112 
113 #define qreal_to_fixed_26_6(f) (int(f * 64))
114 #define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; }
115 #define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; }
116 
117 // #define QT_DEBUG_DRAW
118 #ifdef QT_DEBUG_DRAW
119 void dumpClip(int width, int height, const QClipData *clip);
120 #endif
121 
122 #define QT_FAST_SPANS
123 
124 
125 // A little helper macro to get a better approximation of dimensions.
126 // If we have a rect that starting at 0.5 of width 3.5 it should span
127 // 4 pixels.
128 #define int_dim(pos, dim) (int(pos+dim) - int(pos))
129 
130 // use the same rounding as in qrasterizer.cpp (6 bit fixed point)
131 static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
132 
133 #ifdef Q_WS_WIN
134 extern bool qt_cleartype_enabled;
135 #endif
136 
137 #ifdef Q_WS_MAC
139 #endif
140 
141 
142 /********************************************************************************
143  * Span functions
144  */
145 static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
146 static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
147 static void qt_span_clip(int count, const QSpan *spans, void *userData);
148 static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result);
149 
150 struct ClipData
151 {
155 };
156 
161 };
162 
163 static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
164  ProcessSpans pen_func, ProcessSpans brush_func,
165  QSpanData *pen_data, QSpanData *brush_data);
166 
170 };
171 
172 #ifdef QT_DEBUG_DRAW
173 static const QRectF boundingRect(const QPointF *points, int pointCount)
174 {
175  const QPointF *e = points;
176  const QPointF *last = points + pointCount;
177  qreal minx, maxx, miny, maxy;
178  minx = maxx = e->x();
179  miny = maxy = e->y();
180  while (++e < last) {
181  if (e->x() < minx)
182  minx = e->x();
183  else if (e->x() > maxx)
184  maxx = e->x();
185  if (e->y() < miny)
186  miny = e->y();
187  else if (e->y() > maxy)
188  maxy = e->y();
189  }
190  return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
191 }
192 #endif
193 
194 template <typename T> static inline bool isRect(const T *pts, int elementCount) {
195  return (elementCount == 5 // 5-point polygon, check for closed rect
196  && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point
197  && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
198  && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
199  && pts[0] < pts[4] && pts[1] < pts[5]
200  ) ||
201  (elementCount == 4 // 4-point polygon, check for unclosed rect
202  && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
203  && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
204  && pts[0] < pts[4] && pts[1] < pts[5]
205  );
206 }
207 
208 
209 static void qt_ft_outline_move_to(qfixed x, qfixed y, void *data)
210 {
211  ((QOutlineMapper *) data)->moveTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y)));
212 }
213 
214 static void qt_ft_outline_line_to(qfixed x, qfixed y, void *data)
215 {
216  ((QOutlineMapper *) data)->lineTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y)));
217 }
218 
219 static void qt_ft_outline_cubic_to(qfixed c1x, qfixed c1y,
220  qfixed c2x, qfixed c2y,
221  qfixed ex, qfixed ey,
222  void *data)
223 {
224  ((QOutlineMapper *) data)->curveTo(QPointF(qt_fixed_to_real(c1x), qt_fixed_to_real(c1y)),
227 }
228 
229 
230 #if !defined(QT_NO_DEBUG) && 0
231 static void qt_debug_path(const QPainterPath &path)
232 {
233  const char *names[] = {
234  "MoveTo ",
235  "LineTo ",
236  "CurveTo ",
237  "CurveToData"
238  };
239 
240  fprintf(stderr,"\nQPainterPath: elementCount=%d\n", path.elementCount());
241  for (int i=0; i<path.elementCount(); ++i) {
242  const QPainterPath::Element &e = path.elementAt(i);
244  fprintf(stderr," - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y);
245  }
246 }
247 #endif
248 
251  cachedLines(0)
252 {
253 }
254 
255 
322 {
323  d_func()->device = device;
324  init();
325 }
326 
331  : QPaintEngineEx(dd)
332 {
333  d_func()->device = device;
334  init();
335 }
336 
338 {
340 
341 
342 #ifdef Q_WS_WIN
343  d->hdc = 0;
344 #endif
345 
346  // The antialiasing raster.
347  d->grayRaster.reset(new QT_FT_Raster);
348  Q_CHECK_PTR(d->grayRaster.data());
349  if (qt_ft_grays_raster.raster_new(d->grayRaster.data()))
350  QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc
351 
352 
353  d->rasterizer.reset(new QRasterizer);
354  d->rasterBuffer.reset(new QRasterBuffer());
355  d->outlineMapper.reset(new QOutlineMapper);
356  d->outlinemapper_xform_dirty = true;
357 
358  d->basicStroker.setMoveToHook(qt_ft_outline_move_to);
359  d->basicStroker.setLineToHook(qt_ft_outline_line_to);
360  d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to);
361 
362  d->baseClip.reset(new QClipData(d->device->height()));
363  d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height()));
364 
365  d->image_filler.init(d->rasterBuffer.data(), this);
366  d->image_filler.type = QSpanData::Texture;
367 
368  d->image_filler_xform.init(d->rasterBuffer.data(), this);
369  d->image_filler_xform.type = QSpanData::Texture;
370 
371  d->solid_color_filler.init(d->rasterBuffer.data(), this);
372  d->solid_color_filler.type = QSpanData::Solid;
373 
374  d->deviceDepth = d->device->depth();
375 
376  d->mono_surface = false;
377  gccaps &= ~PorterDuff;
378 
380 
381  switch (d->device->devType()) {
382  case QInternal::Pixmap:
383  qWarning("QRasterPaintEngine: unsupported for pixmaps...");
384  break;
385  case QInternal::Image:
386  format = d->rasterBuffer->prepare(static_cast<QImage *>(d->device));
387  break;
388 #ifdef Q_WS_QWS
390  d->rasterBuffer->prepare(static_cast<QCustomRasterPaintDevice*>(d->device));
391  break;
392 #endif
393  default:
394  qWarning("QRasterPaintEngine: unsupported target device %d\n", d->device->devType());
395  d->device = 0;
396  return;
397  }
398 
399  switch (format) {
401  case QImage::Format_Mono:
402  d->mono_surface = true;
403  break;
410  gccaps |= PorterDuff;
411  break;
418  break;
419  default:
420  break;
421  }
422 }
423 
424 
425 
426 
431 {
433 
434  qt_ft_grays_raster.raster_done(*d->grayRaster.data());
435 }
436 
441 {
443 
444  if (device->devType() == QInternal::Pixmap) {
445  QPixmap *pixmap = static_cast<QPixmap *>(device);
446  QPixmapData *pd = pixmap->pixmapData();
448  d->device = pd->buffer();
449  } else {
450  d->device = device;
451  }
452 
453  // Make sure QPaintEngine::paintDevice() returns the proper device.
454  d->pdev = d->device;
455 
456  Q_ASSERT(d->device->devType() == QInternal::Image
457  || d->device->devType() == QInternal::CustomRaster);
458 
459  d->systemStateChanged();
460 
463  d->outlineMapper->m_clip_rect = d->deviceRect;
464 
465  if (d->outlineMapper->m_clip_rect.width() > QT_RASTER_COORD_LIMIT)
466  d->outlineMapper->m_clip_rect.setWidth(QT_RASTER_COORD_LIMIT);
467  if (d->outlineMapper->m_clip_rect.height() > QT_RASTER_COORD_LIMIT)
468  d->outlineMapper->m_clip_rect.setHeight(QT_RASTER_COORD_LIMIT);
469 
470  d->rasterizer->setClipRect(d->deviceRect);
471 
472  s->penData.init(d->rasterBuffer.data(), this);
474  s->stroker = &d->basicStroker;
475  d->basicStroker.setClipRect(d->deviceRect);
476 
477  s->brushData.init(d->rasterBuffer.data(), this);
479 
480  d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver;
481 
483 
484 #ifdef QT_DEBUG_DRAW
485  qDebug() << "QRasterPaintEngine::begin(" << (void *) device
486  << ") devType:" << device->devType()
487  << "devRect:" << d->deviceRect;
488  if (d->baseClip) {
489  dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip);
490  }
491 #endif
492 
493 #if defined(Q_WS_WIN)
494  d->isPlain45DegreeRotation = true;
495 #endif
496 
497  if (d->mono_surface)
498  d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono;
499 #if defined(Q_WS_WIN)
500  else if (qt_cleartype_enabled)
501 #elif defined (Q_WS_MAC)
503 #else
504  else if (false)
505 #endif
506  {
507  QImage::Format format = static_cast<QImage *>(d->device)->format();
509  d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
510  else
511  d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
512  } else
513  d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
514 
515  setActive(true);
516  return true;
517 }
518 
523 {
524 #ifdef QT_DEBUG_DRAW
526  qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect;
527  if (d->baseClip) {
528  dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip);
529  }
530 #endif
531 
532  return true;
533 }
534 
539 {
541  d->rasterBuffer.reset(new QRasterBuffer);
542 }
543 
548 {
549  Q_D(const QRasterPaintEngine);
550  return QSize(d->rasterBuffer->width(), d->rasterBuffer->height());
551 }
552 
556 #ifndef QT_NO_DEBUG
558 {
559  Q_D(const QRasterPaintEngine);
560  d->rasterBuffer->bufferImage().save(s, "PNG");
561 }
562 #endif
563 
568 {
570  // FALCON: get rid of this line, see drawImage call below.
571  s->matrix = matrix;
573 
574  switch (txop) {
575 
576  case QTransform::TxNone:
577  s->flags.int_xform = true;
578  break;
579 
581  s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
582  && qreal(int(s->matrix.dy())) == s->matrix.dy();
583  break;
584 
585  case QTransform::TxScale:
586  s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
587  && qreal(int(s->matrix.dy())) == s->matrix.dy()
588  && qreal(int(s->matrix.m11())) == s->matrix.m11()
589  && qreal(int(s->matrix.m22())) == s->matrix.m22();
590  break;
591 
592  default: // shear / perspective...
593  s->flags.int_xform = false;
594  break;
595  }
596 
598 
600 
601 #ifdef Q_WS_WIN
603  d->isPlain45DegreeRotation = false;
604  if (txop >= QTransform::TxRotate) {
605  d->isPlain45DegreeRotation =
606  (qFuzzyIsNull(matrix.m11())
607  && qFuzzyIsNull(matrix.m12() - qreal(1))
608  && qFuzzyIsNull(matrix.m21() + qreal(1))
609  && qFuzzyIsNull(matrix.m22())
610  )
611  ||
612  (qFuzzyIsNull(matrix.m11() + qreal(1))
613  && qFuzzyIsNull(matrix.m12())
614  && qFuzzyIsNull(matrix.m21())
615  && qFuzzyIsNull(matrix.m22() + qreal(1))
616  )
617  ||
618  (qFuzzyIsNull(matrix.m11())
619  && qFuzzyIsNull(matrix.m12() + qreal(1))
620  && qFuzzyIsNull(matrix.m21() - qreal(1))
621  && qFuzzyIsNull(matrix.m22())
622  )
623  ;
624  }
625 #endif
626 
627 }
628 
629 
630 
632 {
633  if (flags.has_clip_ownership)
634  delete clip;
635 }
636 
637 
639 {
640  stroker = 0;
641 
642  fillFlags = 0;
643  strokeFlags = 0;
644  pixmapFlags = 0;
645 
646  intOpacity = 256;
647 
648  txscale = 1.;
649 
650  flags.fast_pen = true;
651  flags.antialiased = false;
652  flags.bilinear = false;
653  flags.fast_text = true;
654  flags.int_xform = true;
655  flags.tx_noshear = true;
656  flags.fast_images = true;
657 
658  clip = 0;
659  flags.has_clip_ownership = false;
660 
661  dirty = 0;
662 }
663 
665  : QPainterState(s)
666  , lastPen(s.lastPen)
667  , penData(s.penData)
668  , stroker(s.stroker)
669  , strokeFlags(s.strokeFlags)
670  , lastBrush(s.lastBrush)
671  , brushData(s.brushData)
672  , fillFlags(s.fillFlags)
673  , pixmapFlags(s.pixmapFlags)
674  , intOpacity(s.intOpacity)
675  , txscale(s.txscale)
676  , clip(s.clip)
677  , dirty(s.dirty)
678  , flag_bits(s.flag_bits)
679 {
680  brushData.tempImage = 0;
681  penData.tempImage = 0;
682  flags.has_clip_ownership = false;
683 }
684 
689 {
691  if (!orig)
692  s = new QRasterPaintEngineState();
693  else
694  s = new QRasterPaintEngineState(*static_cast<QRasterPaintEngineState *>(orig));
695 
696  return s;
697 }
698 
703 {
706  d->rasterBuffer->compositionMode = s->composition_mode;
707 }
708 
723 {
724 #ifdef QT_DEBUG_DRAW
725  qDebug() << "QRasterPaintEngine::penChanged():" << state()->pen;
726 #endif
728  s->strokeFlags |= DirtyPen;
729  s->dirty |= DirtyPen;
730 }
731 
736 {
739 #ifdef QT_DEBUG_DRAW
740  qDebug() << "QRasterPaintEngine::updatePen():" << s->pen;
741 #endif
742 
743  Qt::PenStyle pen_style = qpen_style(pen);
744 
745  s->lastPen = pen;
746  s->strokeFlags = 0;
747 
748  s->penData.clip = d->clip();
749  s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode);
750 
752  || pen.brush().transform().type() >= QTransform::TxNone) {
753  d->updateMatrixData(&s->penData, pen.brush(), s->matrix);
754  }
755 
756  // Slightly ugly handling of an uncommon case... We need to change
757  // the pen because it is reused in draw_midpoint to decide dashed
758  // or non-dashed.
759  if (pen_style == Qt::CustomDashLine && pen.dashPattern().size() == 0) {
760  pen_style = Qt::SolidLine;
762  }
763 
764  d->basicStroker.setJoinStyle(qpen_joinStyle(pen));
765  d->basicStroker.setCapStyle(qpen_capStyle(pen));
766  d->basicStroker.setMiterLimit(pen.miterLimit());
767 
768  qreal penWidth = qpen_widthf(pen);
769  if (penWidth == 0)
770  d->basicStroker.setStrokeWidth(1);
771  else
772  d->basicStroker.setStrokeWidth(penWidth);
773 
774  if(pen_style == Qt::SolidLine) {
775  s->stroker = &d->basicStroker;
776  } else if (pen_style != Qt::NoPen) {
777  if (!d->dashStroker)
778  d->dashStroker.reset(new QDashStroker(&d->basicStroker));
779  if (pen.isCosmetic()) {
780  d->dashStroker->setClipRect(d->deviceRect);
781  } else {
782  // ### I've seen this inverted devrect multiple places now...
783  QRectF clipRect = s->matrix.inverted().mapRect(QRectF(d->deviceRect));
784  d->dashStroker->setClipRect(clipRect);
785  }
786  d->dashStroker->setDashPattern(pen.dashPattern());
787  d->dashStroker->setDashOffset(pen.dashOffset());
788  s->stroker = d->dashStroker.data();
789  } else {
790  s->stroker = 0;
791  }
792 
793  ensureState(); // needed because of tx_noshear...
794  s->flags.fast_pen = pen_style > Qt::NoPen
795  && s->penData.blend
796  && ((pen.isCosmetic() && penWidth <= 1)
797  || (!pen.isCosmetic() && s->flags.tx_noshear && penWidth * s->txscale <= 1));
798 
800 
801  s->strokeFlags = 0;
802 }
803 
804 
805 
810 {
812 #ifdef QT_DEBUG_DRAW
813  qDebug() << "QRasterPaintEngine::brushOriginChanged()" << s->brushOrigin;
814 #endif
815 
816  s->fillFlags |= DirtyBrushOrigin;
817 }
818 
819 
824 {
826 #ifdef QT_DEBUG_DRAW
827  qDebug() << "QRasterPaintEngine::brushChanged():" << s->brush;
828 #endif
829  s->fillFlags |= DirtyBrush;
830 }
831 
832 
833 
834 
839 {
840 #ifdef QT_DEBUG_DRAW
841  qDebug() << "QRasterPaintEngine::updateBrush()" << brush;
842 #endif
845  // must set clip prior to setup, as setup uses it...
846  s->brushData.clip = d->clip();
847  s->brushData.setup(brush, s->intOpacity, s->composition_mode);
848  if (s->fillFlags & DirtyTransform
849  || brush.transform().type() >= QTransform::TxNone)
850  d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix());
851  s->lastBrush = brush;
852  s->fillFlags = 0;
853 }
854 
856 {
858  d->outlineMapper->setMatrix(state()->matrix);
859 }
860 
862 {
864 
865  if (s->dirty & DirtyTransform)
866  updateMatrix(s->matrix);
867 
868  if (s->dirty & (DirtyPen|DirtyCompositionMode|DirtyOpacity)) {
871  && s->intOpacity == 256
874  && qAlpha(s->penData.solid.color) == 255));
875  }
876 
877  s->dirty = 0;
878 }
879 
880 
885 {
887 
888 #ifdef QT_DEBUG_DRAW
889  qDebug() << "QRasterPaintEngine::opacityChanged()" << s->opacity;
890 #endif
891 
892  s->fillFlags |= DirtyOpacity;
893  s->strokeFlags |= DirtyOpacity;
894  s->pixmapFlags |= DirtyOpacity;
895  s->dirty |= DirtyOpacity;
896  s->intOpacity = (int) (s->opacity * 256);
897 }
898 
903 {
906 
907 #ifdef QT_DEBUG_DRAW
908  qDebug() << "QRasterPaintEngine::compositionModeChanged()" << s->composition_mode;
909 #endif
910 
911  s->fillFlags |= DirtyCompositionMode;
912  s->dirty |= DirtyCompositionMode;
913 
914  s->strokeFlags |= DirtyCompositionMode;
915  d->rasterBuffer->compositionMode = s->composition_mode;
916 
917  d->recalculateFastImages();
918 }
919 
924 {
926 
927 #ifdef QT_DEBUG_DRAW
928  qDebug() << "QRasterPaintEngine::renderHintsChanged()" << hex << s->renderHints;
929 #endif
930 
931  bool was_aa = s->flags.antialiased;
932  bool was_bilinear = s->flags.bilinear;
933 
936 
937  if (was_aa != s->flags.antialiased)
938  s->strokeFlags |= DirtyHints;
939 
940  if (was_bilinear != s->flags.bilinear) {
941  s->strokeFlags |= DirtyPen;
942  s->fillFlags |= DirtyBrush;
943  }
944 
946  d->recalculateFastImages();
947 }
948 
953 {
955 
956 #ifdef QT_DEBUG_DRAW
957  qDebug() << "QRasterPaintEngine::transformChanged()" << s->matrix;
958 #endif
959 
960  s->fillFlags |= DirtyTransform;
961  s->strokeFlags |= DirtyTransform;
962 
963  s->dirty |= DirtyTransform;
964 
966  d->recalculateFastImages();
967 }
968 
973 {
975 
976 #ifdef QT_DEBUG_DRAW
977  qDebug() << "QRasterPaintEngine::clipEnabledChanged()" << s->clipEnabled;
978 #endif
979 
980  if (s->clip) {
981  s->clip->enabled = s->clipEnabled;
982  s->fillFlags |= DirtyClipEnabled;
983  s->strokeFlags |= DirtyClipEnabled;
984  s->pixmapFlags |= DirtyClipEnabled;
985  }
986 }
987 
988 #ifdef Q_WS_QWS
990 {
991  rasterBuffer->prepare(device);
992 }
993 #endif
994 
996  const QImage &img,
997  SrcOverBlendFunc func,
998  const QRect &clip,
999  int alpha,
1000  const QRect &sr)
1001 {
1002  if (alpha == 0 || !clip.isValid())
1003  return;
1004 
1005  Q_ASSERT(img.depth() >= 8);
1006 
1007  int srcBPL = img.bytesPerLine();
1008  const uchar *srcBits = img.bits();
1009  int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit..
1010  int iw = img.width();
1011  int ih = img.height();
1012 
1013  if (!sr.isEmpty()) {
1014  iw = sr.width();
1015  ih = sr.height();
1016  // Adjust the image according to the source offset...
1017  srcBits += ((sr.y() * srcBPL) + sr.x() * srcSize);
1018  }
1019 
1020  // adapt the x parameters
1021  int x = qRound(pt.x());
1022  int cx1 = clip.x();
1023  int cx2 = clip.x() + clip.width();
1024  if (x < cx1) {
1025  int d = cx1 - x;
1026  srcBits += srcSize * d;
1027  iw -= d;
1028  x = cx1;
1029  }
1030  if (x + iw > cx2) {
1031  int d = x + iw - cx2;
1032  iw -= d;
1033  }
1034  if (iw <= 0)
1035  return;
1036 
1037  // adapt the y paremeters...
1038  int cy1 = clip.y();
1039  int cy2 = clip.y() + clip.height();
1040  int y = qRound(pt.y());
1041  if (y < cy1) {
1042  int d = cy1 - y;
1043  srcBits += srcBPL * d;
1044  ih -= d;
1045  y = cy1;
1046  }
1047  if (y + ih > cy2) {
1048  int d = y + ih - cy2;
1049  ih -= d;
1050  }
1051  if (ih <= 0)
1052  return;
1053 
1054  // call the blend function...
1055  int dstSize = rasterBuffer->bytesPerPixel();
1056  int dstBPL = rasterBuffer->bytesPerLine();
1057  func(rasterBuffer->buffer() + x * dstSize + y * dstBPL, dstBPL,
1058  srcBits, srcBPL,
1059  iw, ih,
1060  alpha);
1061 }
1062 
1063 
1065 {
1066  deviceRectUnclipped = QRect(0, 0,
1067  qMin(QT_RASTER_COORD_LIMIT, device->width()),
1068  qMin(QT_RASTER_COORD_LIMIT, device->height()));
1069 
1070  if (!systemClip.isEmpty()) {
1071  QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
1072  deviceRect = clippedDeviceRgn.boundingRect();
1073  baseClip->setClipRegion(clippedDeviceRgn);
1074  } else {
1075  deviceRect = deviceRectUnclipped;
1076  baseClip->setClipRect(deviceRect);
1077  }
1078 #ifdef QT_DEBUG_DRAW
1079  qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << deviceRectUnclipped << systemClip;
1080 #endif
1081 
1082  exDeviceRect = deviceRect;
1083 
1085  q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
1086  q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
1087  q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
1088 }
1089 
1091 {
1092  if (b.d->style == Qt::NoBrush || b.d->style == Qt::SolidPattern)
1093  return;
1094 
1096  bool bilinear = q->state()->flags.bilinear;
1097 
1098  if (b.d->transform.type() > QTransform::TxNone) { // FALCON: optimize
1099  spanData->setupMatrix(b.transform() * m, bilinear);
1100  } else {
1101  if (m.type() <= QTransform::TxTranslate) {
1102  // specialize setupMatrix for translation matrices
1103  // to avoid needless matrix inversion
1104  spanData->m11 = 1;
1105  spanData->m12 = 0;
1106  spanData->m13 = 0;
1107  spanData->m21 = 0;
1108  spanData->m22 = 1;
1109  spanData->m23 = 0;
1110  spanData->m33 = 1;
1111  spanData->dx = -m.dx();
1112  spanData->dy = -m.dy();
1113  spanData->txop = m.type();
1114  spanData->bilinear = bilinear;
1115  spanData->fast_matrix = qAbs(m.dx()) < 1e4 && qAbs(m.dy()) < 1e4;
1116  spanData->adjustSpanMethods();
1117  } else {
1118  spanData->setupMatrix(m, bilinear);
1119  }
1120  }
1121 }
1122 
1123 // #define QT_CLIPPING_RATIOS
1124 
1125 #ifdef QT_CLIPPING_RATIOS
1126 int rectClips;
1127 int regionClips;
1128 int totalClips;
1129 
1130 static void checkClipRatios(QRasterPaintEnginePrivate *d)
1131 {
1132  if (d->clip()->hasRectClip)
1133  rectClips++;
1134  if (d->clip()->hasRegionClip)
1135  regionClips++;
1136  totalClips++;
1137 
1138  if ((totalClips % 5000) == 0) {
1139  printf("Clipping ratio: rectangular=%f%%, region=%f%%, complex=%f%%\n",
1140  rectClips * 100.0 / (qreal) totalClips,
1141  regionClips * 100.0 / (qreal) totalClips,
1142  (totalClips - rectClips - regionClips) * 100.0 / (qreal) totalClips);
1143  totalClips = 0;
1144  rectClips = 0;
1145  regionClips = 0;
1146  }
1147 
1148 }
1149 #endif
1150 
1152 {
1153  if (s->flags.has_clip_ownership)
1154  delete s->clip;
1155  s->clip = 0;
1156  s->flags.has_clip_ownership = false;
1157 }
1158 
1160 {
1164 
1165  d->solid_color_filler.clip = d->clip();
1167 
1168 #ifdef QT_DEBUG_DRAW
1169  dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->clip());
1170 #endif
1171 
1172 }
1173 
1174 
1179 {
1180 #ifdef QT_DEBUG_DRAW
1181  qDebug() << "QRasterPaintEngine::clip(): " << path << op;
1182 
1183  if (path.elements()) {
1184  for (int i=0; i<path.elementCount(); ++i) {
1185  qDebug() << " - " << path.elements()[i]
1186  << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
1187  }
1188  } else {
1189  for (int i=0; i<path.elementCount(); ++i) {
1190  qDebug() << " ---- "
1191  << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
1192  }
1193  }
1194 #endif
1195 
1198 
1199  const qreal *points = path.points();
1200  const QPainterPath::ElementType *types = path.elements();
1201 
1202  // There are some cases that are not supported by clip(QRect)
1203  if (op != Qt::UniteClip && (op != Qt::IntersectClip || !s->clip
1204  || s->clip->hasRectClip || s->clip->hasRegionClip)) {
1205  if (s->matrix.type() <= QTransform::TxScale
1206  && ((path.shape() == QVectorPath::RectangleHint)
1207  || (isRect(points, path.elementCount())
1208  && (!types || (types[0] == QPainterPath::MoveToElement
1209  && types[1] == QPainterPath::LineToElement
1210  && types[2] == QPainterPath::LineToElement
1211  && types[3] == QPainterPath::LineToElement))))) {
1212 #ifdef QT_DEBUG_DRAW
1213  qDebug() << " --- optimizing vector clip to rect clip...";
1214 #endif
1215 
1216  QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
1217  if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op))
1218  return;
1219  }
1220  }
1221 
1222  if (op == Qt::NoClip) {
1224 
1225  } else {
1226  QClipData *base = d->baseClip.data();
1227 
1228  // Intersect with current clip when available...
1229  if (op == Qt::IntersectClip && s->clip)
1230  base = s->clip;
1231 
1232  // We always intersect, except when there is nothing to
1233  // intersect with, in which case we simplify the operation to
1234  // a replace...
1236  if (base == 0)
1237  isectOp = Qt::ReplaceClip;
1238 
1239  QClipData *newClip = new QClipData(d->rasterBuffer->height());
1240  newClip->initialize();
1241  ClipData clipData = { base, newClip, isectOp };
1242  ensureOutlineMapper();
1243  d->rasterize(d->outlineMapper->convertPath(path), qt_span_clip, &clipData, 0);
1244 
1245  newClip->fixup();
1246 
1247  if (op == Qt::UniteClip) {
1248  // merge clips
1249  QClipData *result = new QClipData(d->rasterBuffer->height());
1250  QClipData *current = s->clip ? s->clip : new QClipData(d->rasterBuffer->height());
1251  qt_merge_clip(current, newClip, result);
1252  result->fixup();
1253  delete newClip;
1254  if (!s->clip)
1255  delete current;
1256  newClip = result;
1257  }
1258 
1259  if (s->flags.has_clip_ownership)
1260  delete s->clip;
1261 
1262  s->clip = newClip;
1263  s->flags.has_clip_ownership = true;
1264  }
1266 }
1267 
1268 
1269 
1274 {
1275 #ifdef QT_DEBUG_DRAW
1276  qDebug() << "QRasterPaintEngine::clip(): " << rect << op;
1277 #endif
1278 
1280 
1281  if (op == Qt::NoClip) {
1283 
1284  } else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
1285  QPaintEngineEx::clip(rect, op);
1286  return;
1287 
1288  } else if (!setClipRectInDeviceCoords(s->matrix.mapRect(rect), op)) {
1289  QPaintEngineEx::clip(rect, op);
1290  return;
1291  }
1292 }
1293 
1294 
1296 {
1298  QRect clipRect = r & d->deviceRect;
1300 
1301  if (op == Qt::ReplaceClip || s->clip == 0) {
1302 
1303  // No current clip, hence we intersect with sysclip and be
1304  // done with it...
1305  QRegion clipRegion = systemClip();
1306  QClipData *clip = new QClipData(d->rasterBuffer->height());
1307 
1308  if (clipRegion.isEmpty())
1309  clip->setClipRect(clipRect);
1310  else
1311  clip->setClipRegion(clipRegion & clipRect);
1312 
1313  if (s->flags.has_clip_ownership)
1314  delete s->clip;
1315 
1316  s->clip = clip;
1317  s->clip->enabled = true;
1318  s->flags.has_clip_ownership = true;
1319 
1320  } else if (op == Qt::IntersectClip){ // intersect clip with current clip
1321  QClipData *base = s->clip;
1322 
1323  Q_ASSERT(base);
1324  if (base->hasRectClip || base->hasRegionClip) {
1325  if (!s->flags.has_clip_ownership) {
1326  s->clip = new QClipData(d->rasterBuffer->height());
1327  s->flags.has_clip_ownership = true;
1328  }
1329  if (base->hasRectClip)
1330  s->clip->setClipRect(base->clipRect & clipRect);
1331  else
1332  s->clip->setClipRegion(base->clipRegion & clipRect);
1333  s->clip->enabled = true;
1334  } else {
1335  return false;
1336  }
1337  } else {
1338  return false;
1339  }
1340 
1342  return true;
1343 }
1344 
1345 
1350 {
1351 #ifdef QT_DEBUG_DRAW
1352  qDebug() << "QRasterPaintEngine::clip(): " << region << op;
1353 #endif
1354 
1356 
1357  if (region.rectCount() == 1) {
1358  clip(region.boundingRect(), op);
1359  return;
1360  }
1361 
1363  const QClipData *clip = d->clip();
1364  const QClipData *baseClip = d->baseClip.data();
1365 
1366  if (op == Qt::NoClip) {
1368  } else if (s->matrix.type() > QTransform::TxScale
1369  || op == Qt::UniteClip
1370  || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
1371  || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
1372  QPaintEngineEx::clip(region, op);
1373  } else {
1374  const QClipData *curClip;
1375  QClipData *newClip;
1376 
1377  if (op == Qt::IntersectClip)
1378  curClip = clip;
1379  else
1380  curClip = baseClip;
1381 
1382  if (s->flags.has_clip_ownership) {
1383  newClip = s->clip;
1384  Q_ASSERT(newClip);
1385  } else {
1386  newClip = new QClipData(d->rasterBuffer->height());
1387  s->clip = newClip;
1388  s->flags.has_clip_ownership = true;
1389  }
1390 
1391  QRegion r = s->matrix.map(region);
1392  if (curClip->hasRectClip)
1393  newClip->setClipRegion(r & curClip->clipRect);
1394  else if (curClip->hasRegionClip)
1395  newClip->setClipRegion(r & curClip->clipRegion);
1396 
1398  }
1399 }
1400 
1405 {
1406 #ifdef QT_DEBUG_DRAW
1407  qDebug() << " --- fillPath, bounds=" << path.boundingRect();
1408 #endif
1409 
1410  if (!fillData->blend)
1411  return;
1412 
1414 
1415  const QRectF controlPointRect = path.controlPointRect();
1416 
1418  const QRect deviceRect = s->matrix.mapRect(controlPointRect).toRect();
1419  ProcessSpans blend = d->getBrushFunc(deviceRect, fillData);
1420  const bool do_clip = (deviceRect.left() < -QT_RASTER_COORD_LIMIT
1421  || deviceRect.right() > QT_RASTER_COORD_LIMIT
1422  || deviceRect.top() < -QT_RASTER_COORD_LIMIT
1423  || deviceRect.bottom() > QT_RASTER_COORD_LIMIT);
1424 
1425  if (!s->flags.antialiased && !do_clip) {
1426  d->initializeRasterizer(fillData);
1427  d->rasterizer->rasterize(path * s->matrix, path.fillRule());
1428  return;
1429  }
1430 
1431  ensureOutlineMapper();
1432  d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer.data());
1433 }
1434 
1435 static void fillRect_normalized(const QRect &r, QSpanData *data,
1437 {
1438  int x1, x2, y1, y2;
1439 
1440  bool rectClipped = true;
1441 
1442  if (data->clip) {
1443  x1 = qMax(r.x(), data->clip->xmin);
1444  x2 = qMin(r.x() + r.width(), data->clip->xmax);
1445  y1 = qMax(r.y(), data->clip->ymin);
1446  y2 = qMin(r.y() + r.height(), data->clip->ymax);
1447  rectClipped = data->clip->hasRectClip;
1448 
1449  } else if (pe) {
1450  x1 = qMax(r.x(), pe->deviceRect.x());
1451  x2 = qMin(r.x() + r.width(), pe->deviceRect.x() + pe->deviceRect.width());
1452  y1 = qMax(r.y(), pe->deviceRect.y());
1453  y2 = qMin(r.y() + r.height(), pe->deviceRect.y() + pe->deviceRect.height());
1454  } else {
1455  x1 = qMax(r.x(), 0);
1456  x2 = qMin(r.x() + r.width(), data->rasterBuffer->width());
1457  y1 = qMax(r.y(), 0);
1458  y2 = qMin(r.y() + r.height(), data->rasterBuffer->height());
1459  }
1460 
1461  if (x2 <= x1 || y2 <= y1)
1462  return;
1463 
1464  const int width = x2 - x1;
1465  const int height = y2 - y1;
1466 
1467  bool isUnclipped = rectClipped
1468  || (pe && pe->isUnclipped_normalized(QRect(x1, y1, width, height)));
1469 
1470  if (pe && isUnclipped) {
1472 
1473  if (data->fillRect && (mode == QPainter::CompositionMode_Source
1475  && qAlpha(data->solid.color) == 255)))
1476  {
1477  data->fillRect(data->rasterBuffer, x1, y1, width, height,
1478  data->solid.color);
1479  return;
1480  }
1481  }
1482 
1483  ProcessSpans blend = isUnclipped ? data->unclipped_blend : data->blend;
1484 
1485  const int nspans = 256;
1486  QT_FT_Span spans[nspans];
1487 
1488  Q_ASSERT(data->blend);
1489  int y = y1;
1490  while (y < y2) {
1491  int n = qMin(nspans, y2 - y);
1492  int i = 0;
1493  while (i < n) {
1494  spans[i].x = x1;
1495  spans[i].len = width;
1496  spans[i].y = y + i;
1497  spans[i].coverage = 255;
1498  ++i;
1499  }
1500 
1501  blend(n, spans, data);
1502  y += n;
1503  }
1504 }
1505 
1509 void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
1510 {
1511 #ifdef QT_DEBUG_DRAW
1512  qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount);
1513 #endif
1515  ensureState();
1517 
1518  // Fill
1519  ensureBrush();
1520  if (s->brushData.blend) {
1521  if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxTranslate) {
1522  const QRect *r = rects;
1523  const QRect *lastRect = rects + rectCount;
1524 
1525  int offset_x = int(s->matrix.dx());
1526  int offset_y = int(s->matrix.dy());
1527  while (r < lastRect) {
1528  QRect rect = r->normalized();
1529  QRect rr = rect.translated(offset_x, offset_y);
1530  fillRect_normalized(rr, &s->brushData, d);
1531  ++r;
1532  }
1533  } else {
1534  QRectVectorPath path;
1535  for (int i=0; i<rectCount; ++i) {
1536  path.set(rects[i]);
1537  fill(path, s->brush);
1538  }
1539  }
1540  }
1541 
1542  ensurePen();
1543  if (s->penData.blend) {
1544  QRectVectorPath path;
1545  if (s->flags.fast_pen) {
1547  for (int i = 0; i < rectCount; ++i) {
1548  path.set(rects[i]);
1549  stroker.drawPath(path);
1550  }
1551  } else {
1552  for (int i = 0; i < rectCount; ++i) {
1553  path.set(rects[i]);
1554  stroke(path, s->pen);
1555  }
1556  }
1557  }
1558 }
1559 
1563 void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount)
1564 {
1565 #ifdef QT_DEBUG_DRAW
1566  qDebug(" - QRasterPaintEngine::drawRect(QRectF*), rectCount=%d", rectCount);
1567 #endif
1568 #ifdef QT_FAST_SPANS
1570  ensureState();
1572 
1573 
1574  if (s->flags.tx_noshear) {
1575  ensureBrush();
1576  if (s->brushData.blend) {
1578  for (int i = 0; i < rectCount; ++i) {
1579  const QRectF &rect = rects[i].normalized();
1580  if (rect.isEmpty())
1581  continue;
1582  const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
1583  const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
1584  d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
1585  }
1586  }
1587 
1588  ensurePen();
1589  if (s->penData.blend) {
1590  QRectVectorPath path;
1591  if (s->flags.fast_pen) {
1593  for (int i = 0; i < rectCount; ++i) {
1594  path.set(rects[i]);
1595  stroker.drawPath(path);
1596  }
1597  } else {
1598  for (int i = 0; i < rectCount; ++i) {
1599  path.set(rects[i]);
1600  QPaintEngineEx::stroke(path, s->lastPen);
1601  }
1602  }
1603  }
1604 
1605  return;
1606  }
1607 #endif // QT_FAST_SPANS
1608  QPaintEngineEx::drawRects(rects, rectCount);
1609 }
1610 
1611 
1616 {
1619 
1620  ensurePen(pen);
1621  if (!s->penData.blend)
1622  return;
1623 
1624  if (s->flags.fast_pen) {
1626  stroker.drawPath(path);
1627  } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) {
1628  qreal width = s->lastPen.isCosmetic()
1629  ? (qpen_widthf(s->lastPen) == 0 ? 1 : qpen_widthf(s->lastPen))
1630  : qpen_widthf(s->lastPen) * s->txscale;
1631  int dashIndex = 0;
1632  qreal dashOffset = s->lastPen.dashOffset();
1633  bool inDash = true;
1634  qreal patternLength = 0;
1635  const QVector<qreal> pattern = s->lastPen.dashPattern();
1636  for (int i = 0; i < pattern.size(); ++i)
1637  patternLength += pattern.at(i);
1638 
1639  if (patternLength > 0) {
1640  int n = qFloor(dashOffset / patternLength);
1641  dashOffset -= n * patternLength;
1642  while (dashOffset >= pattern.at(dashIndex)) {
1643  dashOffset -= pattern.at(dashIndex);
1644  if (++dashIndex >= pattern.size())
1645  dashIndex = 0;
1646  inDash = !inDash;
1647  }
1648  }
1649 
1651  d->initializeRasterizer(&s->penData);
1652  int lineCount = path.elementCount() / 2;
1653  const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
1654 
1655  for (int i = 0; i < lineCount; ++i) {
1656  if (lines[i].p1() == lines[i].p2()) {
1657  if (s->lastPen.capStyle() != Qt::FlatCap) {
1658  QPointF p = lines[i].p1();
1659  QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*qreal(0.5), p.y()),
1660  QPointF(p.x() + width*qreal(0.5), p.y())));
1661  d->rasterizer->rasterizeLine(line.p1(), line.p2(), 1);
1662  }
1663  continue;
1664  }
1665 
1666  const QLineF line = s->matrix.map(lines[i]);
1667  if (qpen_style(s->lastPen) == Qt::SolidLine) {
1668  d->rasterizer->rasterizeLine(line.p1(), line.p2(),
1669  width / line.length(),
1670  s->lastPen.capStyle() == Qt::SquareCap);
1671  } else {
1672  d->rasterizeLine_dashed(line, width,
1673  &dashIndex, &dashOffset, &inDash);
1674  }
1675  }
1676  }
1677  else
1678  QPaintEngineEx::stroke(path, pen);
1679 }
1680 
1681 static inline QRect toNormalizedFillRect(const QRectF &rect)
1682 {
1683  int x1 = qRound(rect.x() + aliasedCoordinateDelta);
1684  int y1 = qRound(rect.y() + aliasedCoordinateDelta);
1685  int x2 = qRound(rect.right() + aliasedCoordinateDelta);
1686  int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
1687 
1688  if (x2 < x1)
1689  qSwap(x1, x2);
1690  if (y2 < y1)
1691  qSwap(y1, y2);
1692 
1693  return QRect(x1, y1, x2 - x1, y2 - y1);
1694 }
1695 
1700 {
1701  if (path.isEmpty())
1702  return;
1703 #ifdef QT_DEBUG_DRAW
1704  QRectF rf = path.controlPointRect();
1705  qDebug() << "QRasterPaintEngine::fill(): "
1706  << "size=" << path.elementCount()
1707  << ", hints=" << hex << path.hints()
1708  << rf << brush;
1709 #endif
1710 
1713 
1714  ensureBrush(brush);
1715  if (!s->brushData.blend)
1716  return;
1717 
1718  if (path.shape() == QVectorPath::RectangleHint) {
1719  if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxScale) {
1720  const qreal *p = path.points();
1721  QPointF tl = QPointF(p[0], p[1]) * s->matrix;
1722  QPointF br = QPointF(p[4], p[5]) * s->matrix;
1724  return;
1725  }
1726  ensureState();
1727  if (s->flags.tx_noshear) {
1729  // ### Is normalizing really necessary here?
1730  const qreal *p = path.points();
1731  QRectF r = QRectF(p[0], p[1], p[2] - p[0], p[7] - p[1]).normalized();
1732  if (!r.isEmpty()) {
1733  const QPointF a = s->matrix.map((r.topLeft() + r.bottomLeft()) * 0.5f);
1734  const QPointF b = s->matrix.map((r.topRight() + r.bottomRight()) * 0.5f);
1735  d->rasterizer->rasterizeLine(a, b, r.height() / r.width());
1736  }
1737  return;
1738  }
1739  }
1740 
1741  // ### Optimize for non transformed ellipses and rectangles...
1742  QRectF cpRect = path.controlPointRect();
1743  const QRect deviceRect = s->matrix.mapRect(cpRect).toRect();
1744  ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData);
1745 
1746  // ### Falcon
1747 // const bool do_clip = (deviceRect.left() < -QT_RASTER_COORD_LIMIT
1748 // || deviceRect.right() > QT_RASTER_COORD_LIMIT
1749 // || deviceRect.top() < -QT_RASTER_COORD_LIMIT
1750 // || deviceRect.bottom() > QT_RASTER_COORD_LIMIT);
1751 
1752  // ### Falonc: implement....
1753 // if (!s->flags.antialiased && !do_clip) {
1754 // d->initializeRasterizer(&s->brushData);
1755 // d->rasterizer->rasterize(path * d->matrix, path.fillRule());
1756 // return;
1757 // }
1758 
1759  ensureOutlineMapper();
1760  d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer.data());
1761 }
1762 
1764 {
1767 
1768  if (!s->flags.antialiased) {
1769  uint txop = s->matrix.type();
1770  if (txop == QTransform::TxNone) {
1772  return;
1773  } else if (txop == QTransform::TxTranslate) {
1774  const QRect rr = toNormalizedFillRect(r.translated(s->matrix.dx(), s->matrix.dy()));
1775  fillRect_normalized(rr, data, d);
1776  return;
1777  } else if (txop == QTransform::TxScale) {
1778  const QRect rr = toNormalizedFillRect(s->matrix.mapRect(r));
1779  fillRect_normalized(rr, data, d);
1780  return;
1781  }
1782  }
1783  ensureState();
1784  if (s->flags.tx_noshear) {
1785  d->initializeRasterizer(data);
1786  QRectF nr = r.normalized();
1787  if (!nr.isEmpty()) {
1788  const QPointF a = s->matrix.map((nr.topLeft() + nr.bottomLeft()) * 0.5f);
1789  const QPointF b = s->matrix.map((nr.topRight() + nr.bottomRight()) * 0.5f);
1790  d->rasterizer->rasterizeLine(a, b, nr.height() / nr.width());
1791  }
1792  return;
1793  }
1794 
1795  QPainterPath path;
1796  path.addRect(r);
1797  ensureOutlineMapper();
1798  fillPath(path, data);
1799 }
1800 
1805 {
1806 #ifdef QT_DEBUG_DRAW
1807  qDebug() << "QRasterPaintEngine::fillRecct(): " << r << brush;
1808 #endif
1810 
1811  ensureBrush(brush);
1812  if (!s->brushData.blend)
1813  return;
1814 
1815  fillRect(r, &s->brushData);
1816 }
1817 
1821 void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
1822 {
1823 #ifdef QT_DEBUG_DRAW
1824  qDebug() << "QRasterPaintEngine::fillRect(): " << r << color;
1825 #endif
1828 
1830  if ((d->solid_color_filler.solid.color & 0xff000000) == 0
1832  return;
1833  }
1834  d->solid_color_filler.clip = d->clip();
1836  fillRect(r, &d->solid_color_filler);
1837 }
1838 
1839 static inline bool isAbove(const QPointF *a, const QPointF *b)
1840 {
1841  return a->y() < b->y();
1842 }
1843 
1844 static bool splitPolygon(const QPointF *points, int pointCount, QVector<QPointF> *upper, QVector<QPointF> *lower)
1845 {
1846  Q_ASSERT(upper);
1847  Q_ASSERT(lower);
1848 
1849  Q_ASSERT(pointCount >= 2);
1850 
1851  QVector<const QPointF *> sorted;
1852  sorted.reserve(pointCount);
1853 
1854  upper->reserve(pointCount * 3 / 4);
1855  lower->reserve(pointCount * 3 / 4);
1856 
1857  for (int i = 0; i < pointCount; ++i)
1858  sorted << points + i;
1859 
1860  qSort(sorted.begin(), sorted.end(), isAbove);
1861 
1862  qreal splitY = sorted.at(sorted.size() / 2)->y();
1863 
1864  const QPointF *end = points + pointCount;
1865  const QPointF *last = end - 1;
1866 
1867  QVector<QPointF> *bin[2] = { upper, lower };
1868 
1869  for (const QPointF *p = points; p < end; ++p) {
1870  int side = p->y() < splitY;
1871  int lastSide = last->y() < splitY;
1872 
1873  if (side != lastSide) {
1874  if (qFuzzyCompare(p->y(), splitY)) {
1875  bin[!side]->append(*p);
1876  } else if (qFuzzyCompare(last->y(), splitY)) {
1877  bin[side]->append(*last);
1878  } else {
1879  QPointF delta = *p - *last;
1880  QPointF intersection(p->x() + delta.x() * (splitY - p->y()) / delta.y(), splitY);
1881 
1882  bin[0]->append(intersection);
1883  bin[1]->append(intersection);
1884  }
1885  }
1886 
1887  bin[side]->append(*p);
1888 
1889  last = p;
1890  }
1891 
1892  // give up if we couldn't reduce the point count
1893  return upper->size() < pointCount && lower->size() < pointCount;
1894 }
1895 
1899 void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
1900 {
1903 
1904  const int maxPoints = 0xffff;
1905 
1906  // max amount of points that raster engine can reliably handle
1907  if (pointCount > maxPoints) {
1908  QVector<QPointF> upper, lower;
1909 
1910  if (splitPolygon(points, pointCount, &upper, &lower)) {
1911  fillPolygon(upper.constData(), upper.size(), mode);
1912  fillPolygon(lower.constData(), lower.size(), mode);
1913  } else
1914  qWarning("Polygon too complex for filling.");
1915 
1916  return;
1917  }
1918 
1919  // Compose polygon fill..,
1920  QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
1921  ensureOutlineMapper();
1922  QT_FT_Outline *outline = d->outlineMapper->convertPath(vp);
1923 
1924  // scanconvert.
1926  &s->brushData);
1927  d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer.data());
1928 }
1929 
1933 void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
1934 {
1937 
1938 #ifdef QT_DEBUG_DRAW
1939  qDebug(" - QRasterPaintEngine::drawPolygon(F), pointCount=%d", pointCount);
1940  for (int i=0; i<pointCount; ++i)
1941  qDebug() << " - " << points[i];
1942 #endif
1943  Q_ASSERT(pointCount >= 2);
1944 
1945  if (mode != PolylineMode && isRect((qreal *) points, pointCount)) {
1946  QRectF r(points[0], points[2]);
1947  drawRects(&r, 1);
1948  return;
1949  }
1950 
1951  ensurePen();
1952  if (mode != PolylineMode) {
1953  // Do the fill...
1954  ensureBrush();
1955  if (s->brushData.blend)
1956  fillPolygon(points, pointCount, mode);
1957  }
1958 
1959  // Do the outline...
1960  if (s->penData.blend) {
1961  QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
1962  if (s->flags.fast_pen) {
1964  stroker.drawPath(vp);
1965  } else {
1967  }
1968  }
1969 }
1970 
1974 void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
1975 {
1978 
1979 #ifdef QT_DEBUG_DRAW
1980  qDebug(" - QRasterPaintEngine::drawPolygon(I), pointCount=%d", pointCount);
1981  for (int i=0; i<pointCount; ++i)
1982  qDebug() << " - " << points[i];
1983 #endif
1984  Q_ASSERT(pointCount >= 2);
1985  if (mode != PolylineMode && isRect((int *) points, pointCount)) {
1986  QRect r(points[0].x(),
1987  points[0].y(),
1988  points[2].x() - points[0].x(),
1989  points[2].y() - points[0].y());
1990  drawRects(&r, 1);
1991  return;
1992  }
1993 
1994  ensurePen();
1995 
1996  // Do the fill
1997  if (mode != PolylineMode) {
1998  ensureBrush();
1999  if (s->brushData.blend) {
2000  // Compose polygon fill..,
2001  ensureOutlineMapper();
2002  d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
2003  d->outlineMapper->moveTo(*points);
2004  const QPoint *p = points;
2005  const QPoint *ep = points + pointCount - 1;
2006  do {
2007  d->outlineMapper->lineTo(*(++p));
2008  } while (p < ep);
2009  d->outlineMapper->endOutline();
2010 
2011  // scanconvert.
2013  &s->brushData);
2014  d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
2015  }
2016  }
2017 
2018  // Do the outline...
2019  if (s->penData.blend) {
2020  int count = pointCount * 2;
2021  QVarLengthArray<qreal> fpoints(count);
2022  #ifdef Q_WS_MAC
2023  for (int i=0; i<count; i+=2) {
2024  fpoints[i] = ((int *) points)[i+1];
2025  fpoints[i+1] = ((int *) points)[i];
2026  }
2027  #else
2028  for (int i=0; i<count; ++i)
2029  fpoints[i] = ((int *) points)[i];
2030  #endif
2031  QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
2032 
2033  if (s->flags.fast_pen) {
2035  stroker.drawPath(vp);
2036  } else {
2038  }
2039  }
2040 }
2041 
2045 void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap)
2046 {
2047 #ifdef QT_DEBUG_DRAW
2048  qDebug() << " - QRasterPaintEngine::drawPixmap(), pos=" << pos << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
2049 #endif
2050 
2051  QPixmapData *pd = pixmap.pixmapData();
2052  if (pd->classId() == QPixmapData::RasterClass) {
2053  const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
2054  if (image.depth() == 1) {
2057  if (s->matrix.type() <= QTransform::TxTranslate) {
2058  ensurePen();
2059  drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData);
2060  } else {
2061  drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color()));
2062  }
2063  } else {
2064  QRasterPaintEngine::drawImage(pos, image);
2065  }
2066  } else {
2067  const QImage image = pixmap.toImage();
2068  if (pixmap.depth() == 1) {
2071  if (s->matrix.type() <= QTransform::TxTranslate) {
2072  ensurePen();
2073  drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData);
2074  } else {
2075  drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color()));
2076  }
2077  } else {
2078  QRasterPaintEngine::drawImage(pos, image);
2079  }
2080  }
2081 }
2082 
2086 void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &sr)
2087 {
2088 #ifdef QT_DEBUG_DRAW
2089  qDebug() << " - QRasterPaintEngine::drawPixmap(), r=" << r << " sr=" << sr << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
2090 #endif
2091 
2092  QPixmapData* pd = pixmap.pixmapData();
2093  if (pd->classId() == QPixmapData::RasterClass) {
2094  const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
2095  if (image.depth() == 1) {
2098  if (s->matrix.type() <= QTransform::TxTranslate
2099  && r.size() == sr.size()
2100  && r.size() == pixmap.size()) {
2101  ensurePen();
2102  drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData);
2103  return;
2104  } else {
2105  drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr);
2106  }
2107  } else {
2108  drawImage(r, image, sr);
2109  }
2110  } else {
2111  QRect clippedSource = sr.toAlignedRect().intersected(pixmap.rect());
2112  const QImage image = pd->toImage(clippedSource);
2113  QRectF translatedSource = sr.translated(-clippedSource.topLeft());
2114  if (image.depth() == 1) {
2117  if (s->matrix.type() <= QTransform::TxTranslate
2118  && r.size() == sr.size()
2119  && r.size() == pixmap.size()) {
2120  ensurePen();
2121  drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData);
2122  return;
2123  } else {
2124  drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), translatedSource);
2125  }
2126  } else {
2127  drawImage(r, image, translatedSource);
2128  }
2129  }
2130 }
2131 
2132 // assumes that rect has positive width and height
2133 static inline const QRect toRect_normalized(const QRectF &rect)
2134 {
2135  const int x = qRound(rect.x());
2136  const int y = qRound(rect.y());
2137  const int w = int(rect.width() + qreal(0.5));
2138  const int h = int(rect.height() + qreal(0.5));
2139 
2140  return QRect(x, y, w, h);
2141 }
2142 
2143 static inline int fast_ceil_positive(const qreal &v)
2144 {
2145  const int iv = int(v);
2146  if (v - iv == 0)
2147  return iv;
2148  else
2149  return iv + 1;
2150 }
2151 
2152 static inline const QRect toAlignedRect_positive(const QRectF &rect)
2153 {
2154  const int xmin = int(rect.x());
2155  const int xmax = int(fast_ceil_positive(rect.right()));
2156  const int ymin = int(rect.y());
2157  const int ymax = int(fast_ceil_positive(rect.bottom()));
2158  return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
2159 }
2160 
2165 {
2166 #ifdef QT_DEBUG_DRAW
2167  qDebug() << " - QRasterPaintEngine::drawImage(), p=" << p << " image=" << img.size() << "depth=" << img.depth();
2168 #endif
2169 
2172 
2173  if (s->matrix.type() > QTransform::TxTranslate) {
2174  drawImage(QRectF(p.x(), p.y(), img.width(), img.height()),
2175  img,
2176  QRectF(0, 0, img.width(), img.height()));
2177  } else {
2178 
2179  const QClipData *clip = d->clip();
2180  QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy());
2181 
2184  if (func) {
2185  if (!clip) {
2186  d->drawImage(pt, img, func, d->deviceRect, s->intOpacity);
2187  return;
2188  } else if (clip->hasRectClip) {
2189  d->drawImage(pt, img, func, clip->clipRect, s->intOpacity);
2190  return;
2191  }
2192  }
2193  }
2194 
2195 
2196 
2197  d->image_filler.clip = clip;
2199  if (!d->image_filler.blend)
2200  return;
2201  d->image_filler.dx = -pt.x();
2202  d->image_filler.dy = -pt.y();
2203  QRect rr = img.rect().translated(qRound(pt.x()), qRound(pt.y()));
2204 
2205  fillRect_normalized(rr, &d->image_filler, d);
2206  }
2207 
2208 }
2209 
2211 {
2212  return QRectF(r.topLeft() * t, r.bottomRight() * t);
2213 }
2214 
2215 namespace {
2217  Rotation90,
2218  Rotation180,
2219  Rotation270,
2220  NoRotation
2221  };
2222 
2223  inline RotationType qRotationType(const QTransform &transform)
2224  {
2226 
2227  if (type > QTransform::TxRotate)
2228  return NoRotation;
2229 
2230  if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1))
2231  && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22()))
2232  return Rotation90;
2233 
2234  if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12())
2235  && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1)))
2236  return Rotation180;
2237 
2238  if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1))
2239  && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22()))
2240  return Rotation270;
2241 
2242  return NoRotation;
2243  }
2244 
2245  inline bool isPixelAligned(const QRectF &rect) {
2246  return QRectF(rect.toRect()) == rect;
2247  }
2248 }
2249 
2253 void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
2254  Qt::ImageConversionFlags)
2255 {
2256 #ifdef QT_DEBUG_DRAW
2257  qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << sr << " image=" << img.size() << "depth=" << img.depth();
2258 #endif
2259 
2260  if (r.isEmpty())
2261  return;
2262 
2265  int sr_l = qFloor(sr.left());
2266  int sr_r = qCeil(sr.right()) - 1;
2267  int sr_t = qFloor(sr.top());
2268  int sr_b = qCeil(sr.bottom()) - 1;
2269 
2270  if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
2271  // as fillRect will apply the aliased coordinate delta we need to
2272  // subtract it here as we don't use it for image drawing
2273  QTransform old = s->matrix;
2275 
2276  // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied.
2277  QRgb color = img.pixel(sr_l, sr_t);
2278  switch (img.format()) {
2284  // Combine premultiplied color with the opacity set on the painter.
2286  ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff)
2287  | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00);
2288  break;
2289  default:
2291  break;
2292  }
2293 
2294  if ((d->solid_color_filler.solid.color & 0xff000000) == 0
2296  return;
2297  }
2298 
2299  d->solid_color_filler.clip = d->clip();
2301  fillRect(r, &d->solid_color_filler);
2302 
2303  s->matrix = old;
2304  return;
2305  }
2306 
2307  bool stretch_sr = r.width() != sr.width() || r.height() != sr.height();
2308 
2309  const QClipData *clip = d->clip();
2310 
2312  && !stretch_sr
2313  && (!clip || clip->hasRectClip)
2314  && s->intOpacity == 256
2317  && d->rasterBuffer->format == img.format()
2322  {
2323  RotationType rotationType = qRotationType(s->matrix);
2324 
2325  if (rotationType != NoRotation && qMemRotateFunctions[d->rasterBuffer->format][rotationType] && img.rect().contains(sr.toAlignedRect())) {
2326  QRectF transformedTargetRect = s->matrix.mapRect(r);
2327 
2329  || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr)))
2330  {
2331  QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect);
2332  if (clippedTransformedTargetRect.isNull())
2333  return;
2334 
2335  QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect));
2336 
2337  QRect clippedSourceRect
2338  = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(),
2339  clippedTargetRect.width(), clippedTargetRect.height()).toRect();
2340 
2341  uint dbpl = d->rasterBuffer->bytesPerLine();
2342  uint sbpl = img.bytesPerLine();
2343 
2344  uchar *dst = d->rasterBuffer->buffer();
2345  uint bpp = img.depth() >> 3;
2346 
2347  const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp;
2348  uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp;
2349 
2350  uint cw = clippedSourceRect.width();
2351  uint ch = clippedSourceRect.height();
2352 
2353  qMemRotateFunctions[d->rasterBuffer->format][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl);
2354 
2355  return;
2356  }
2357  }
2358  }
2359 
2360  if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) {
2361 
2362  QRectF targetBounds = s->matrix.mapRect(r);
2363  bool exceedsPrecision = targetBounds.width() > 0xffff
2364  || targetBounds.height() > 0xffff;
2365 
2366  if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
2367  if (s->matrix.type() > QTransform::TxScale) {
2369  if (func && (!clip || clip->hasRectClip)) {
2370  func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(),
2371  img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect,
2372  s->matrix, s->intOpacity);
2373  return;
2374  }
2375  } else {
2377  if (func && (!clip || clip->hasRectClip)) {
2378  func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
2379  img.bits(), img.bytesPerLine(), img.height(),
2381  !clip ? d->deviceRect : clip->clipRect,
2382  s->intOpacity);
2383  return;
2384  }
2385  }
2386  }
2387 
2388  QTransform copy = s->matrix;
2389  copy.translate(r.x(), r.y());
2390  if (stretch_sr)
2391  copy.scale(r.width() / sr.width(), r.height() / sr.height());
2392  copy.translate(-sr.x(), -sr.y());
2393 
2396  if (!d->image_filler_xform.blend)
2397  return;
2399 
2400  if (!s->flags.antialiased && s->matrix.type() == QTransform::TxScale) {
2401  QPointF rr_tl = s->matrix.map(r.topLeft());
2402  QPointF rr_br = s->matrix.map(r.bottomRight());
2403 
2404  int x1 = qRound(rr_tl.x());
2405  int y1 = qRound(rr_tl.y());
2406  int x2 = qRound(rr_br.x());
2407  int y2 = qRound(rr_br.y());
2408 
2409  if (x1 > x2)
2410  qSwap(x1, x2);
2411  if (y1 > y2)
2412  qSwap(y1, y2);
2413 
2414  fillRect_normalized(QRect(x1, y1, x2-x1, y2-y1), &d->image_filler_xform, d);
2415  return;
2416  }
2417 
2418 #ifdef QT_FAST_SPANS
2419  ensureState();
2420  if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) {
2423 
2425 
2426  const QRectF &rect = r.normalized();
2427  const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs;
2428  const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs;
2429 
2430  if (s->flags.tx_noshear)
2431  d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
2432  else
2433  d->rasterizer->rasterizeLine(a, b, qAbs((s->matrix.m22() * rect.height()) / (s->matrix.m11() * rect.width())));
2434  return;
2435  }
2436 #endif
2437  const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta;
2438  QPainterPath path;
2439  path.addRect(r);
2440  QTransform m = s->matrix;
2441  s->matrix = QTransform(m.m11(), m.m12(), m.m13(),
2442  m.m21(), m.m22(), m.m23(),
2443  m.m31() - offs, m.m32() - offs, m.m33());
2444  fillPath(path, &d->image_filler_xform);
2445  s->matrix = m;
2446  } else {
2449  if (func) {
2450  QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy());
2451  if (!clip) {
2452  d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect());
2453  return;
2454  } else if (clip->hasRectClip) {
2455  d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect());
2456  return;
2457  }
2458  }
2459  }
2460 
2461  d->image_filler.clip = clip;
2463  if (!d->image_filler.blend)
2464  return;
2465  d->image_filler.dx = -(r.x() + s->matrix.dx()) + sr.x();
2466  d->image_filler.dy = -(r.y() + s->matrix.dy()) + sr.y();
2467 
2468  QRectF rr = r;
2469  rr.translate(s->matrix.dx(), s->matrix.dy());
2470 
2471  const int x1 = qRound(rr.x());
2472  const int y1 = qRound(rr.y());
2473  const int x2 = qRound(rr.right());
2474  const int y2 = qRound(rr.bottom());
2475 
2476  fillRect_normalized(QRect(x1, y1, x2-x1, y2-y1), &d->image_filler, d);
2477  }
2478 }
2479 
2483 void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sr)
2484 {
2485 #ifdef QT_DEBUG_DRAW
2486  qDebug() << " - QRasterPaintEngine::drawTiledPixmap(), r=" << r << "pixmap=" << pixmap.size();
2487 #endif
2490 
2491  QImage image;
2492 
2493  QPixmapData *pd = pixmap.pixmapData();
2494  if (pd->classId() == QPixmapData::RasterClass) {
2495  image = static_cast<QRasterPixmapData *>(pd)->image;
2496  } else {
2497  image = pixmap.toImage();
2498  }
2499 
2500  if (image.depth() == 1)
2501  image = d->rasterBuffer->colorizeBitmap(image, s->pen.color());
2502 
2503  if (s->matrix.type() > QTransform::TxTranslate) {
2504  QTransform copy = s->matrix;
2505  copy.translate(r.x(), r.y());
2506  copy.translate(-sr.x(), -sr.y());
2507  d->image_filler_xform.clip = d->clip();
2509  if (!d->image_filler_xform.blend)
2510  return;
2512 
2513 #ifdef QT_FAST_SPANS
2514  ensureState();
2515  if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) {
2518 
2519  const QRectF &rect = r.normalized();
2520  const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
2521  const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
2522  if (s->flags.tx_noshear)
2523  d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
2524  else
2525  d->rasterizer->rasterizeLine(a, b, qAbs((s->matrix.m22() * rect.height()) / (s->matrix.m11() * rect.width())));
2526  return;
2527  }
2528 #endif
2529  QPainterPath path;
2530  path.addRect(r);
2531  fillPath(path, &d->image_filler_xform);
2532  } else {
2533  d->image_filler.clip = d->clip();
2534 
2536  if (!d->image_filler.blend)
2537  return;
2538  d->image_filler.dx = -(r.x() + s->matrix.dx()) + sr.x();
2539  d->image_filler.dy = -(r.y() + s->matrix.dy()) + sr.y();
2540 
2541  QRectF rr = r;
2542  rr.translate(s->matrix.dx(), s->matrix.dy());
2544  }
2545 }
2546 
2547 
2548 //QWS hack
2549 static inline bool monoVal(const uchar* s, int x)
2550 {
2551  return (s[x>>3] << (x&7)) & 0x80;
2552 }
2553 
2557 void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h)
2558 {
2561 
2562  if (!s->penData.blend)
2563  return;
2564 
2565  QRasterBuffer *rb = d->rasterBuffer.data();
2566 
2567  const QRect rect(rx, ry, w, h);
2568  const QClipData *clip = d->clip();
2569  bool unclipped = false;
2570  if (clip) {
2571  // inlined QRect::intersects
2572  const bool intersects = qMax(clip->xmin, rect.left()) <= qMin(clip->xmax - 1, rect.right())
2573  && qMax(clip->ymin, rect.top()) <= qMin(clip->ymax - 1, rect.bottom());
2574 
2575  if (clip->hasRectClip) {
2576  unclipped = rx > clip->xmin
2577  && rx + w < clip->xmax
2578  && ry > clip->ymin
2579  && ry + h < clip->ymax;
2580  }
2581 
2582  if (!intersects)
2583  return;
2584  } else {
2585  // inlined QRect::intersects
2586  const bool intersects = qMax(0, rect.left()) <= qMin(rb->width() - 1, rect.right())
2587  && qMax(0, rect.top()) <= qMin(rb->height() - 1, rect.bottom());
2588  if (!intersects)
2589  return;
2590 
2591  // inlined QRect::contains
2592  const bool contains = rect.left() >= 0 && rect.right() < rb->width()
2593  && rect.top() >= 0 && rect.bottom() < rb->height();
2594 
2595  unclipped = contains && d->isUnclipped_normalized(rect);
2596  }
2597 
2598  ProcessSpans blend = unclipped ? s->penData.unclipped_blend : s->penData.blend;
2599  const uchar * scanline = static_cast<const uchar *>(src);
2600 
2601  if (s->flags.fast_text) {
2602  if (unclipped) {
2603  if (depth == 1) {
2604  if (s->penData.bitmapBlit) {
2605  s->penData.bitmapBlit(rb, rx, ry, s->penData.solid.color,
2606  scanline, w, h, bpl);
2607  return;
2608  }
2609  } else if (depth == 8) {
2610  if (s->penData.alphamapBlit) {
2611  s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
2612  scanline, w, h, bpl, 0);
2613  return;
2614  }
2615  } else if (depth == 32) {
2616  // (A)RGB Alpha mask where the alpha component is not used.
2617  if (s->penData.alphaRGBBlit) {
2618  s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
2619  (const uint *) scanline, w, h, bpl / 4, 0);
2620  return;
2621  }
2622  }
2623  } else if (d->deviceDepth == 32 && (depth == 8 || depth == 32)) {
2624  // (A)RGB Alpha mask where the alpha component is not used.
2625  if (!clip) {
2626  int nx = qMax(0, rx);
2627  int ny = qMax(0, ry);
2628 
2629  // Move scanline pointer to compensate for moved x and y
2630  int xdiff = nx - rx;
2631  int ydiff = ny - ry;
2632  scanline += ydiff * bpl;
2633  scanline += xdiff * (depth == 32 ? 4 : 1);
2634 
2635  w -= xdiff;
2636  h -= ydiff;
2637 
2638  if (nx + w > d->rasterBuffer->width())
2639  w = d->rasterBuffer->width() - nx;
2640  if (ny + h > d->rasterBuffer->height())
2641  h = d->rasterBuffer->height() - ny;
2642 
2643  rx = nx;
2644  ry = ny;
2645  }
2646  if (depth == 8 && s->penData.alphamapBlit) {
2647  s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
2648  scanline, w, h, bpl, clip);
2649  } else if (depth == 32 && s->penData.alphaRGBBlit) {
2650  s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
2651  (const uint *) scanline, w, h, bpl / 4, clip);
2652  }
2653  return;
2654  }
2655  }
2656 
2657  int x0 = 0;
2658  if (rx < 0) {
2659  x0 = -rx;
2660  w -= x0;
2661  }
2662 
2663  int y0 = 0;
2664  if (ry < 0) {
2665  y0 = -ry;
2666  scanline += bpl * y0;
2667  h -= y0;
2668  }
2669 
2670  w = qMin(w, rb->width() - qMax(0, rx));
2671  h = qMin(h, rb->height() - qMax(0, ry));
2672 
2673  if (w <= 0 || h <= 0)
2674  return;
2675 
2676  const int NSPANS = 256;
2677  QSpan spans[NSPANS];
2678  int current = 0;
2679 
2680  const int x1 = x0 + w;
2681  const int y1 = y0 + h;
2682 
2683  if (depth == 1) {
2684  for (int y = y0; y < y1; ++y) {
2685  for (int x = x0; x < x1; ) {
2686  if (!monoVal(scanline, x)) {
2687  ++x;
2688  continue;
2689  }
2690 
2691  if (current == NSPANS) {
2692  blend(current, spans, &s->penData);
2693  current = 0;
2694  }
2695  spans[current].x = x + rx;
2696  spans[current].y = y + ry;
2697  spans[current].coverage = 255;
2698  int len = 1;
2699  ++x;
2700  // extend span until we find a different one.
2701  while (x < x1 && monoVal(scanline, x)) {
2702  ++x;
2703  ++len;
2704  }
2705  spans[current].len = len;
2706  ++current;
2707  }
2708  scanline += bpl;
2709  }
2710  } else if (depth == 8) {
2711  for (int y = y0; y < y1; ++y) {
2712  for (int x = x0; x < x1; ) {
2713  // Skip those with 0 coverage
2714  if (scanline[x] == 0) {
2715  ++x;
2716  continue;
2717  }
2718 
2719  if (current == NSPANS) {
2720  blend(current, spans, &s->penData);
2721  current = 0;
2722  }
2723  int coverage = scanline[x];
2724  spans[current].x = x + rx;
2725  spans[current].y = y + ry;
2726  spans[current].coverage = coverage;
2727  int len = 1;
2728  ++x;
2729 
2730  // extend span until we find a different one.
2731  while (x < x1 && scanline[x] == coverage) {
2732  ++x;
2733  ++len;
2734  }
2735  spans[current].len = len;
2736  ++current;
2737  }
2738  scanline += bpl;
2739  }
2740  } else { // 32-bit alpha...
2741  uint *sl = (uint *) src;
2742  for (int y = y0; y < y1; ++y) {
2743  for (int x = x0; x < x1; ) {
2744  // Skip those with 0 coverage
2745  if ((sl[x] & 0x00ffffff) == 0) {
2746  ++x;
2747  continue;
2748  }
2749 
2750  if (current == NSPANS) {
2751  blend(current, spans, &s->penData);
2752  current = 0;
2753  }
2754  uint rgbCoverage = sl[x];
2755  int coverage = qGreen(rgbCoverage);
2756  spans[current].x = x + rx;
2757  spans[current].y = y + ry;
2758  spans[current].coverage = coverage;
2759  int len = 1;
2760  ++x;
2761 
2762  // extend span until we find a different one.
2763  while (x < x1 && sl[x] == rgbCoverage) {
2764  ++x;
2765  ++len;
2766  }
2767  spans[current].len = len;
2768  ++current;
2769  }
2770  sl += bpl / sizeof(uint);
2771  }
2772  }
2773 // qDebug() << "alphaPenBlt: num spans=" << current
2774 // << "span:" << spans->x << spans->y << spans->len << spans->coverage;
2775  // Call span func for current set of spans.
2776  if (current != 0)
2777  blend(current, spans, &s->penData);
2778 }
2779 
2780 bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
2781  const QFixedPoint *positions, QFontEngine *fontEngine)
2782 {
2786 
2787 #if !defined(QT_NO_FREETYPE)
2788  if (fontEngine->type() == QFontEngine::Freetype) {
2789  QFontEngineFT *fe = static_cast<QFontEngineFT *>(fontEngine);
2790  const QFixed xOffs = fe->supportsSubPixelPositions() ? 0 : offs;
2791  QFontEngineFT::GlyphFormat neededFormat =
2793  ? fe->defaultGlyphFormat()
2795 
2796  if (d_func()->mono_surface
2797  || fe->isBitmapFont() // alphaPenBlt can handle mono, too
2798  )
2799  neededFormat = QFontEngineFT::Format_Mono;
2800 
2801  if (neededFormat == QFontEngineFT::Format_None)
2802  neededFormat = QFontEngineFT::Format_A8;
2803 
2805  if (s->matrix.type() >= QTransform::TxScale) {
2806  if (s->matrix.isAffine())
2807  gset = fe->loadTransformedGlyphSet(s->matrix);
2808  else
2809  gset = 0;
2810  }
2811 
2812  if (!gset || gset->outline_drawing
2813  || !fe->loadGlyphs(gset, glyphs, numGlyphs, positions, neededFormat))
2814  return false;
2815 
2816  FT_Face lockedFace = 0;
2817 
2818  int depth;
2819  switch (neededFormat) {
2821  depth = 1;
2822  break;
2824  depth = 8;
2825  break;
2827  depth = 32;
2828  break;
2829  default:
2830  Q_ASSERT(false);
2831  depth = 0;
2832  };
2833 
2834  for (int i = 0; i < numGlyphs; i++) {
2835  QFixed spp = fe->subPixelPositionForX(positions[i].x);
2836  QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i], spp);
2837 
2838  if (!glyph || glyph->format != neededFormat) {
2839  if (!lockedFace)
2840  lockedFace = fe->lockFace();
2841  glyph = fe->loadGlyph(gset, glyphs[i], spp, neededFormat);
2842  }
2843 
2844  if (!glyph || !glyph->data)
2845  continue;
2846 
2847  int pitch;
2848  switch (neededFormat) {
2850  pitch = ((glyph->width + 31) & ~31) >> 3;
2851  break;
2853  pitch = (glyph->width + 3) & ~3;
2854  break;
2856  pitch = glyph->width * 4;
2857  break;
2858  default:
2859  Q_ASSERT(false);
2860  pitch = 0;
2861  };
2862 
2863  alphaPenBlt(glyph->data, pitch, depth,
2864  qFloor(positions[i].x + xOffs) + glyph->x,
2865  qFloor(positions[i].y + offs) - glyph->y,
2866  glyph->width, glyph->height);
2867  }
2868  if (lockedFace)
2869  fe->unlockFace();
2870  } else
2871 #endif
2872  {
2873  QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0
2875  : d->glyphCacheType;
2876 
2877  QImageTextureGlyphCache *cache =
2878  static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix));
2879  if (!cache) {
2880  cache = new QImageTextureGlyphCache(glyphType, s->matrix);
2881  fontEngine->setGlyphCache(0, cache);
2882  }
2883 
2884  cache->populate(fontEngine, numGlyphs, glyphs, positions);
2885  cache->fillInPendingGlyphs();
2886 
2887  const QImage &image = cache->image();
2888  int bpl = image.bytesPerLine();
2889 
2890  int depth = image.depth();
2891  int rightShift = 0;
2892  int leftShift = 0;
2893  if (depth == 32)
2894  leftShift = 2; // multiply by 4
2895  else if (depth == 1)
2896  rightShift = 3; // divide by 8
2897 
2898  int margin = cache->glyphMargin();
2899  const uchar *bits = image.bits();
2900  for (int i=0; i<numGlyphs; ++i) {
2901 
2902  QFixed subPixelPosition = cache->subPixelPositionForX(positions[i].x);
2903  QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
2904  const QTextureGlyphCache::Coord &c = cache->coords[glyph];
2905  if (c.isNull())
2906  continue;
2907 
2908  int x = qFloor(positions[i].x) + c.baseLineX - margin;
2909  int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
2910 
2911  // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
2912  // c.x, c.y,
2913  // c.w, c.h,
2914  // c.baseLineX, c.baseLineY,
2915  // glyphs[i],
2916  // x, y,
2917  // positions[i].x.toInt(), positions[i].y.toInt());
2918 
2919  alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h);
2920  }
2921  }
2922  return true;
2923 }
2924 
2925 #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
2926 void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti)
2927 {
2930 
2931  QFontEngine *fontEngine = ti.fontEngine;
2932  if (fontEngine->type() != QFontEngine::S60FontEngine) {
2934  return;
2935  }
2936 
2937  QFontEngineS60 *fe = static_cast<QFontEngineS60 *>(fontEngine);
2938 
2940  QVarLengthArray<glyph_t> glyphs;
2941  QTransform matrix = s->matrix;
2942  matrix.translate(p.x(), p.y());
2943  if (matrix.type() == QTransform::TxScale)
2944  fe->setFontScale(matrix.m11());
2945  ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
2946 
2947  const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta);
2948 
2949  for (int i=0; i<glyphs.size(); ++i) {
2950  TOpenFontCharMetrics tmetrics;
2951  const TUint8 *glyphBitmapBytes;
2952  TSize glyphBitmapSize;
2953  fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize);
2954  const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta);
2955  const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta);
2956  alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight);
2957  }
2958 
2959  if (matrix.type() == QTransform::TxScale)
2960  fe->setFontScale(1.0);
2961 
2962  return;
2963 }
2964 #endif // Q_OS_SYMBIAN && QT_NO_FREETYPE
2965 
2971 {
2972  const QClipData *cl = clip();
2973  if (!cl) {
2974  // inline contains() for performance (we know the rects are normalized)
2975  const QRect &r1 = deviceRect;
2976  return (r.left() >= r1.left() && r.right() <= r1.right()
2977  && r.top() >= r1.top() && r.bottom() <= r1.bottom());
2978  }
2979 
2980 
2981  if (cl->hasRectClip) {
2982  // currently all painting functions clips to deviceRect internally
2983  if (cl->clipRect == deviceRect)
2984  return true;
2985 
2986  // inline contains() for performance (we know the rects are normalized)
2987  const QRect &r1 = cl->clipRect;
2988  return (r.left() >= r1.left() && r.right() <= r1.right()
2989  && r.top() >= r1.top() && r.bottom() <= r1.bottom());
2990  } else {
2991  return qt_region_strictContains(cl->clipRegion, r);
2992  }
2993 }
2994 
2996  int penWidth) const
2997 {
2998  Q_Q(const QRasterPaintEngine);
2999  const QRasterPaintEngineState *s = q->state();
3000  const QClipData *cl = clip();
3001  if (!cl) {
3002  QRect r = rect.normalized();
3003  // inline contains() for performance (we know the rects are normalized)
3004  const QRect &r1 = deviceRect;
3005  return (r.left() >= r1.left() && r.right() <= r1.right()
3006  && r.top() >= r1.top() && r.bottom() <= r1.bottom());
3007  }
3008 
3009 
3010  // currently all painting functions that call this function clip to deviceRect internally
3011  if (cl->hasRectClip && cl->clipRect == deviceRect)
3012  return true;
3013 
3014  if (s->flags.antialiased)
3015  ++penWidth;
3016 
3017  QRect r = rect.normalized();
3018  if (penWidth > 0) {
3019  r.setX(r.x() - penWidth);
3020  r.setY(r.y() - penWidth);
3021  r.setWidth(r.width() + 2 * penWidth);
3022  r.setHeight(r.height() + 2 * penWidth);
3023  }
3024 
3025  if (cl->hasRectClip) {
3026  // inline contains() for performance (we know the rects are normalized)
3027  const QRect &r1 = cl->clipRect;
3028  return (r.left() >= r1.left() && r.right() <= r1.right()
3029  && r.top() >= r1.top() && r.bottom() <= r1.bottom());
3030  } else {
3031  return qt_region_strictContains(cl->clipRegion, r);
3032  }
3033 }
3034 
3036  int penWidth) const
3037 {
3038  return isUnclipped(rect.normalized().toAlignedRect(), penWidth);
3039 }
3040 
3041 inline ProcessSpans
3043  const QSpanData *data) const
3044 {
3045  return isUnclipped(rect, 0) ? data->unclipped_blend : data->blend;
3046 }
3047 
3048 inline ProcessSpans
3050  const QSpanData *data) const
3051 {
3052  return isUnclipped(rect, 0) ? data->unclipped_blend : data->blend;
3053 }
3054 
3055 inline ProcessSpans
3057  const QSpanData *data) const
3058 {
3059  Q_Q(const QRasterPaintEngine);
3060  const QRasterPaintEngineState *s = q->state();
3061 
3062  if (!s->flags.fast_pen && s->matrix.type() > QTransform::TxTranslate)
3063  return data->blend;
3064  const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF());
3065  return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
3066 }
3067 
3072 {
3073  ensurePen();
3074  ensureState();
3075 
3076  QFontEngine *fontEngine = textItem->fontEngine();
3077  if (!supportsTransformations(fontEngine)) {
3078  drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
3079  fontEngine);
3080  } else {
3082  }
3083 }
3084 
3088 void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
3089 {
3090  const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
3092 
3093 #ifdef QT_DEBUG_DRAW
3095  fprintf(stderr," - QRasterPaintEngine::drawTextItem(), (%.2f,%.2f), string=%s ct=%d\n",
3096  p.x(), p.y(), QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data(),
3097  d->glyphCacheType);
3098 #endif
3099 
3100  ensurePen();
3101  ensureState();
3102 
3103 #if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_MAC) && defined(Q_WS_QPA))
3104 
3105  if (!supportsTransformations(ti.fontEngine)) {
3107  QVarLengthArray<glyph_t> glyphs;
3108 
3109  QTransform matrix = s->matrix;
3110  matrix.translate(p.x(), p.y());
3111 
3112  ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
3113 
3114  drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine);
3115  return;
3116  }
3117 
3118 #elif defined (Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // Q_WS_WIN || Q_WS_MAC
3119  if (s->matrix.type() <= QTransform::TxTranslate
3120  || (s->matrix.type() == QTransform::TxScale
3121  && (qFuzzyCompare(s->matrix.m11(), s->matrix.m22())))) {
3122  drawGlyphsS60(p, ti);
3123  return;
3124  }
3125 #else // Q_WS_WIN || Q_WS_MAC
3126 
3127  QFontEngine *fontEngine = ti.fontEngine;
3128 
3129 #if defined(Q_WS_QWS)
3130  if (fontEngine->type() == QFontEngine::Box) {
3131  fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti);
3132  return;
3133  }
3134 
3135  if (s->matrix.type() < QTransform::TxScale
3136  && (fontEngine->type() == QFontEngine::QPF1 || fontEngine->type() == QFontEngine::QPF2
3137  || (fontEngine->type() == QFontEngine::Proxy
3138  && !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline()))
3139  )) {
3140  fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti);
3141  return;
3142  }
3143 #endif // Q_WS_QWS
3144 
3145 #ifdef Q_WS_QPA
3146  if (s->matrix.type() < QTransform::TxScale) {
3147 
3149  QVarLengthArray<glyph_t> glyphs;
3150  QTransform matrix = state()->transform();
3151 
3152  qreal _x = qFloor(p.x());
3153  qreal _y = qFloor(p.y());
3154  matrix.translate(_x, _y);
3155 
3156  fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
3157  if (glyphs.size() == 0)
3158  return;
3159 
3160  for(int i = 0; i < glyphs.size(); i++) {
3161  QImage img = fontEngine->alphaMapForGlyph(glyphs[i]);
3162  glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
3163  // ### hm, perhaps an QFixed offs = QFixed::fromReal(aliasedCoordinateDelta) is needed here?
3164  alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(),
3165  qRound(positions[i].x + metrics.x),
3166  qRound(positions[i].y + metrics.y),
3167  img.width(), img.height());
3168  }
3169  return;
3170  }
3171 #endif //Q_WS_QPA
3172 
3173 #if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
3174 
3175 #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
3176  if (fontEngine->type() == QFontEngine::QPF2) {
3177  QFontEngine *renderingEngine = static_cast<QFontEngineQPF *>(fontEngine)->renderingEngine();
3178  if (renderingEngine)
3179  fontEngine = renderingEngine;
3180  }
3181 #endif
3182 
3183  if (fontEngine->type() != QFontEngine::Freetype) {
3185  return;
3186  }
3187 
3188  QFontEngineFT *fe = static_cast<QFontEngineFT *>(fontEngine);
3189 
3190  QTransform matrix = s->matrix;
3191  matrix.translate(p.x(), p.y());
3192 
3194  QVarLengthArray<glyph_t> glyphs;
3195  fe->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
3196  if (glyphs.size() == 0)
3197  return;
3198 
3199  if (!drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), fontEngine))
3201 
3202  return;
3203 #endif
3204 #endif
3205 
3207 }
3208 
3212 void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount)
3213 {
3216 
3217  ensurePen();
3218  if (!s->penData.blend)
3219  return;
3220 
3221  if (!s->flags.fast_pen) {
3222  QPaintEngineEx::drawPoints(points, pointCount);
3223  return;
3224  }
3225 
3227  stroker.drawPoints(points, pointCount);
3228 }
3229 
3230 
3231 void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
3232 {
3235 
3236  ensurePen();
3237  if (!s->penData.blend)
3238  return;
3239 
3240  if (!s->flags.fast_pen) {
3241  QPaintEngineEx::drawPoints(points, pointCount);
3242  return;
3243  }
3244 
3246  stroker.drawPoints(points, pointCount);
3247 }
3248 
3252 void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
3253 {
3254 #ifdef QT_DEBUG_DRAW
3255  qDebug() << " - QRasterPaintEngine::drawLines(QLine*)" << lineCount;
3256 #endif
3259 
3260  ensurePen();
3261  if (!s->penData.blend)
3262  return;
3263 
3264  if (s->flags.fast_pen) {
3266  for (int i=0; i<lineCount; ++i) {
3267  const QLine &l = lines[i];
3268  stroker.drawLine(l.p1(), l.p2());
3269  }
3270  } else {
3271  QPaintEngineEx::drawLines(lines, lineCount);
3272  }
3273 }
3274 
3276  qreal width,
3277  int *dashIndex,
3278  qreal *dashOffset,
3279  bool *inDash)
3280 {
3282  QRasterPaintEngineState *s = q->state();
3283 
3284  const QPen &pen = s->lastPen;
3285  const bool squareCap = (pen.capStyle() == Qt::SquareCap);
3286  const QVector<qreal> pattern = pen.dashPattern();
3287 
3288  qreal patternLength = 0;
3289  for (int i = 0; i < pattern.size(); ++i)
3290  patternLength += pattern.at(i);
3291 
3292  if (patternLength <= 0)
3293  return;
3294 
3295  qreal length = line.length();
3296  Q_ASSERT(length > 0);
3297  while (length > 0) {
3298  const bool rasterize = *inDash;
3299  qreal dash = (pattern.at(*dashIndex) - *dashOffset) * width;
3300  QLineF l = line;
3301 
3302  if (dash >= length) {
3303  dash = length;
3304  *dashOffset += dash / width;
3305  length = 0;
3306  } else {
3307  *dashOffset = 0;
3308  *inDash = !(*inDash);
3309  if (++*dashIndex >= pattern.size())
3310  *dashIndex = 0;
3311  length -= dash;
3312  l.setLength(dash);
3313  line.setP1(l.p2());
3314  }
3315 
3316  if (rasterize && dash > 0)
3317  rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap);
3318  }
3319 }
3320 
3324 void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
3325 {
3326 #ifdef QT_DEBUG_DRAW
3327  qDebug() << " - QRasterPaintEngine::drawLines(QLineF *)" << lineCount;
3328 #endif
3331 
3332  ensurePen();
3333  if (!s->penData.blend)
3334  return;
3335  if (s->flags.fast_pen) {
3337  for (int i=0; i<lineCount; ++i) {
3338  QLineF line = lines[i];
3339  stroker.drawLine(line.p1(), line.p2());
3340  }
3341  } else {
3342  QPaintEngineEx::drawLines(lines, lineCount);
3343  }
3344 }
3345 
3346 
3351 {
3354 
3355  ensurePen();
3356  if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen)
3357  || (qpen_style(s->lastPen) == Qt::NoPen))
3358  && !s->flags.antialiased
3359  && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT
3360  && !rect.isEmpty()
3361  && s->matrix.type() <= QTransform::TxScale) // no shear
3362  {
3363  ensureBrush();
3364  const QRectF r = s->matrix.mapRect(rect);
3365  ProcessSpans penBlend = d->getPenFunc(r, &s->penData);
3366  ProcessSpans brushBlend = d->getBrushFunc(r, &s->brushData);
3367  const QRect brect = QRect(int(r.x()), int(r.y()),
3368  int_dim(r.x(), r.width()),
3369  int_dim(r.y(), r.height()));
3370  if (brect == r) {
3371  drawEllipse_midpoint_i(brect, d->deviceRect, penBlend, brushBlend,
3372  &s->penData, &s->brushData);
3373  return;
3374  }
3375  }
3377 }
3378 
3382 #ifdef Q_WS_MAC
3384 {
3386  d->cgContext = ctx;
3387 }
3388 
3393 {
3394  Q_D(const QRasterPaintEngine);
3395  return d->cgContext;
3396 }
3397 #endif
3398 
3399 #ifdef Q_WS_WIN
3400 
3405  d->hdc = hdc;
3406 }
3407 
3412 {
3413  Q_D(const QRasterPaintEngine);
3414  return d->hdc;
3415 }
3416 
3421 {
3422 }
3423 
3424 #endif
3425 
3427 {
3428  const QTransform &m = state()->matrix;
3429 #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
3430  QFontEngine::Type fontEngineType = fontEngine->type();
3431  if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) fontEngine)->ttf && m.type() > QTransform::TxTranslate)
3432  || (m.type() <= QTransform::TxTranslate
3433  && (fontEngineType == QFontEngine::TestFontEngine
3434  || fontEngineType == QFontEngine::Box))) {
3435  return true;
3436  }
3437 #endif
3438  return supportsTransformations(fontEngine->fontDef.pixelSize, m);
3439 }
3440 
3442 {
3443 #if defined(Q_WS_MAC) || (defined(Q_OS_MAC) && defined(Q_WS_QPA))
3444  // Mac font engines don't support scaling and rotation
3445  if (m.type() > QTransform::TxTranslate)
3446 #else
3447  if (m.type() >= QTransform::TxProject)
3448 #endif
3449  return true;
3450 
3451  if (pixelSize * pixelSize * qAbs(m.determinant()) >= 64 * 64)
3452  return true;
3453 
3454  return false;
3455 }
3456 
3461 {
3462  return QPoint(0, 0);
3463 }
3464 
3476 #if defined(Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS)
3477 void QRasterPaintEngine::drawColorSpans(const QSpan *spans, int count, uint color)
3478 {
3479  Q_UNUSED(spans);
3480  Q_UNUSED(count);
3481  Q_UNUSED(color);
3482  qFatal("QRasterPaintEngine::drawColorSpans must be reimplemented on "
3483  "a non memory-mapped device");
3484 }
3485 
3504 void QRasterPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
3505  int x, int y, int length, uint const_alpha)
3506 {
3507  Q_UNUSED(buffer);
3508  Q_UNUSED(bufsize);
3509  Q_UNUSED(x);
3510  Q_UNUSED(y);
3511  Q_UNUSED(length);
3512  Q_UNUSED(const_alpha);
3513  qFatal("QRasterPaintEngine::drawBufferSpan must be reimplemented on "
3514  "a non memory-mapped device");
3515 }
3516 #endif // Q_WS_QWS
3517 
3518 void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fg)
3519 {
3520  Q_ASSERT(fg);
3521  if (!fg->blend)
3522  return;
3524 
3525  Q_ASSERT(image.depth() == 1);
3526 
3527  const int spanCount = 256;
3528  QT_FT_Span spans[spanCount];
3529  int n = 0;
3530 
3531  // Boundaries
3532  int w = image.width();
3533  int h = image.height();
3534  int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height());
3535  int ymin = qMax(qRound(pos.y()), 0);
3536  int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width());
3537  int xmin = qMax(qRound(pos.x()), 0);
3538 
3539  int x_offset = xmin - qRound(pos.x());
3540 
3541  QImage::Format format = image.format();
3542  for (int y = ymin; y < ymax; ++y) {
3543  const uchar *src = image.scanLine(y - qRound(pos.y()));
3544  if (format == QImage::Format_MonoLSB) {
3545  for (int x = 0; x < xmax - xmin; ++x) {
3546  int src_x = x + x_offset;
3547  uchar pixel = src[src_x >> 3];
3548  if (!pixel) {
3549  x += 7 - (src_x%8);
3550  continue;
3551  }
3552  if (pixel & (0x1 << (src_x & 7))) {
3553  spans[n].x = xmin + x;
3554  spans[n].y = y;
3555  spans[n].coverage = 255;
3556  int len = 1;
3557  while (src_x+1 < w && src[(src_x+1) >> 3] & (0x1 << ((src_x+1) & 7))) {
3558  ++src_x;
3559  ++len;
3560  }
3561  spans[n].len = ((len + spans[n].x) > xmax) ? (xmax - spans[n].x) : len;
3562  x += len;
3563  ++n;
3564  if (n == spanCount) {
3565  fg->blend(n, spans, fg);
3566  n = 0;
3567  }
3568  }
3569  }
3570  } else {
3571  for (int x = 0; x < xmax - xmin; ++x) {
3572  int src_x = x + x_offset;
3573  uchar pixel = src[src_x >> 3];
3574  if (!pixel) {
3575  x += 7 - (src_x%8);
3576  continue;
3577  }
3578  if (pixel & (0x80 >> (x & 7))) {
3579  spans[n].x = xmin + x;
3580  spans[n].y = y;
3581  spans[n].coverage = 255;
3582  int len = 1;
3583  while (src_x+1 < w && src[(src_x+1) >> 3] & (0x80 >> ((src_x+1) & 7))) {
3584  ++src_x;
3585  ++len;
3586  }
3587  spans[n].len = ((len + spans[n].x) > xmax) ? (xmax - spans[n].x) : len;
3588  x += len;
3589  ++n;
3590  if (n == spanCount) {
3591  fg->blend(n, spans, fg);
3592  n = 0;
3593  }
3594  }
3595  }
3596  }
3597  }
3598  if (n) {
3599  fg->blend(n, spans, fg);
3600  n = 0;
3601  }
3602 }
3603 
3620 {
3621  Q_D(const QRasterPaintEngine);
3622 
3623  const QClipData *clip = d->clip();
3624  if (!clip || clip->hasRectClip)
3625  return RectClip;
3626  else
3627  return ComplexClip;
3628 }
3629 
3638 {
3639  Q_D(const QRasterPaintEngine);
3640 
3641  const QClipData *clip = d->clip();
3642 
3643  if (!clip)
3644  return d->deviceRect;
3645 
3646  if (clip->hasRectClip)
3647  return clip->clipRect;
3648 
3649  return QRect(clip->xmin, clip->ymin, clip->xmax - clip->xmin, clip->ymax - clip->ymin);
3650 }
3651 
3652 static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result)
3653 {
3654  Q_ASSERT(c1->clipSpanHeight == c2->clipSpanHeight && c1->clipSpanHeight == result->clipSpanHeight);
3655 
3657 
3658  QClipData::ClipLine *c1ClipLines = const_cast<QClipData *>(c1)->clipLines();
3659  QClipData::ClipLine *c2ClipLines = const_cast<QClipData *>(c2)->clipLines();
3660  result->initialize();
3661 
3662  for (int y = 0; y < c1->clipSpanHeight; ++y) {
3663  const QSpan *c1_spans = c1ClipLines[y].spans;
3664  int c1_count = c1ClipLines[y].count;
3665  const QSpan *c2_spans = c2ClipLines[y].spans;
3666  int c2_count = c2ClipLines[y].count;
3667 
3668  if (c1_count == 0 && c2_count == 0)
3669  continue;
3670  if (c1_count == 0) {
3671  result->appendSpans(c2_spans, c2_count);
3672  continue;
3673  } else if (c2_count == 0) {
3674  result->appendSpans(c1_spans, c1_count);
3675  continue;
3676  }
3677 
3678  // we need to merge the two
3679 
3680  // find required length
3681  int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len,
3682  c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
3683  buffer.resize(max);
3684  memset(buffer.data(), 0, buffer.size() * sizeof(short));
3685 
3686  // Fill with old spans.
3687  for (int i = 0; i < c1_count; ++i) {
3688  const QSpan *cs = c1_spans + i;
3689  for (int j=cs->x; j<cs->x + cs->len; ++j)
3690  buffer[j] = cs->coverage;
3691  }
3692 
3693  // Fill with new spans
3694  for (int i = 0; i < c2_count; ++i) {
3695  const QSpan *cs = c2_spans + i;
3696  for (int j = cs->x; j < cs->x + cs->len; ++j) {
3697  buffer[j] += cs->coverage;
3698  if (buffer[j] > 255)
3699  buffer[j] = 255;
3700  }
3701  }
3702 
3703  int x = 0;
3704  while (x<max) {
3705 
3706  // Skip to next span
3707  while (x < max && buffer[x] == 0) ++x;
3708  if (x >= max) break;
3709 
3710  int sx = x;
3711  int coverage = buffer[x];
3712 
3713  // Find length of span
3714  while (x < max && buffer[x] == coverage)
3715  ++x;
3716 
3717  result->appendSpan(sx, x - sx, y, coverage);
3718  }
3719  }
3720 }
3721 
3723 {
3725  QRasterPaintEngineState *s = q->state();
3726 
3727  rasterizer->setAntialiased(s->flags.antialiased);
3728 
3729  QRect clipRect(deviceRect);
3730  ProcessSpans blend;
3731  // ### get from optimized rectbased QClipData
3732 
3733  const QClipData *c = clip();
3734  if (c) {
3735  const QRect r(QPoint(c->xmin, c->ymin),
3736  QSize(c->xmax - c->xmin, c->ymax - c->ymin));
3737  clipRect = clipRect.intersected(r);
3738  blend = data->blend;
3739  } else {
3740  blend = data->unclipped_blend;
3741  }
3742 
3743  rasterizer->setClipRect(clipRect);
3744  rasterizer->initialize(blend, data);
3745 }
3746 
3749  QSpanData *spanData, QRasterBuffer *rasterBuffer)
3750 {
3751  if (!callback || !outline)
3752  return;
3753 
3755  QRasterPaintEngineState *s = q->state();
3756 
3757  if (!s->flags.antialiased) {
3758  initializeRasterizer(spanData);
3759 
3760  const Qt::FillRule fillRule = outline->flags == QT_FT_OUTLINE_NONE
3761  ? Qt::WindingFill
3762  : Qt::OddEvenFill;
3763 
3764  rasterizer->rasterize(outline, fillRule);
3765  return;
3766  }
3767 
3768  rasterize(outline, callback, (void *)spanData, rasterBuffer);
3769 }
3770 
3771 extern "C" {
3772  int q_gray_rendered_spans(QT_FT_Raster raster);
3773 }
3774 
3775 static inline uchar *alignAddress(uchar *address, quintptr alignmentMask)
3776 {
3777  return (uchar *)(((quintptr)address + alignmentMask) & ~alignmentMask);
3778 }
3779 
3782  void *userData, QRasterBuffer *)
3783 {
3784  if (!callback || !outline)
3785  return;
3786 
3788  QRasterPaintEngineState *s = q->state();
3789 
3790  if (!s->flags.antialiased) {
3791  rasterizer->setAntialiased(s->flags.antialiased);
3792  rasterizer->setClipRect(deviceRect);
3793  rasterizer->initialize(callback, userData);
3794 
3795  const Qt::FillRule fillRule = outline->flags == QT_FT_OUTLINE_NONE
3796  ? Qt::WindingFill
3797  : Qt::OddEvenFill;
3798 
3799  rasterizer->rasterize(outline, fillRule);
3800  return;
3801  }
3802 
3803  // Initial size for raster pool is MINIMUM_POOL_SIZE so as to
3804  // minimize memory reallocations. However if initial size for
3805  // raster pool is changed for lower value, reallocations will
3806  // occur normally.
3807  int rasterPoolSize = MINIMUM_POOL_SIZE;
3808  uchar rasterPoolOnStack[MINIMUM_POOL_SIZE + 0xf];
3809  uchar *rasterPoolBase = alignAddress(rasterPoolOnStack, 0xf);
3810  uchar *rasterPoolOnHeap = 0;
3811 
3812  qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
3813 
3814  void *data = userData;
3815 
3816  QT_FT_BBox clip_box = { deviceRect.x(),
3817  deviceRect.y(),
3818  deviceRect.x() + deviceRect.width(),
3819  deviceRect.y() + deviceRect.height() };
3820 
3821  QT_FT_Raster_Params rasterParams;
3822  rasterParams.target = 0;
3823  rasterParams.source = outline;
3824  rasterParams.flags = QT_FT_RASTER_FLAG_CLIP;
3825  rasterParams.gray_spans = 0;
3826  rasterParams.black_spans = 0;
3827  rasterParams.bit_test = 0;
3828  rasterParams.bit_set = 0;
3829  rasterParams.user = data;
3830  rasterParams.clip_box = clip_box;
3831 
3832  bool done = false;
3833  int error;
3834 
3835  int rendered_spans = 0;
3836 
3837  while (!done) {
3838 
3840  rasterParams.gray_spans = callback;
3841  rasterParams.skip_spans = rendered_spans;
3842  error = qt_ft_grays_raster.raster_render(*grayRaster.data(), &rasterParams);
3843 
3844  // Out of memory, reallocate some more and try again...
3845  if (error == -6) { // ErrRaster_OutOfMemory from qgrayraster.c
3846  rasterPoolSize *= 2;
3847  if (rasterPoolSize > 1024 * 1024) {
3848  qWarning("QPainter: Rasterization of primitive failed");
3849  break;
3850  }
3851 
3852  rendered_spans += q_gray_rendered_spans(*grayRaster.data());
3853 
3854  free(rasterPoolOnHeap);
3855  rasterPoolOnHeap = (uchar *)malloc(rasterPoolSize + 0xf);
3856 
3857  Q_CHECK_PTR(rasterPoolOnHeap); // note: we just freed the old rasterPoolBase. I hope it's not fatal.
3858 
3859  rasterPoolBase = alignAddress(rasterPoolOnHeap, 0xf);
3860 
3861  qt_ft_grays_raster.raster_done(*grayRaster.data());
3862  qt_ft_grays_raster.raster_new(grayRaster.data());
3863  qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
3864  } else {
3865  done = true;
3866  }
3867  }
3868 
3869  free(rasterPoolOnHeap);
3870 }
3871 
3873 {
3875  QRasterPaintEngineState *s = q->state();
3876 
3878  && s->matrix.type() <= QTransform::TxShear;
3879 }
3880 
3882 {
3883  Q_Q(const QRasterPaintEngine);
3884  const QRasterPaintEngineState *s = q->state();
3885 
3886  return s->flags.fast_images
3889  && !image.hasAlphaChannel()));
3890 }
3891 
3893 {
3894  Q_ASSERT(image.depth() == 1);
3895 
3896  QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB);
3897  QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied);
3898 
3899  QRgb fg = PREMUL(color.rgba());
3900  QRgb bg = 0;
3901 
3902  int height = sourceImage.height();
3903  int width = sourceImage.width();
3904  for (int y=0; y<height; ++y) {
3905  uchar *source = sourceImage.scanLine(y);
3906  QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
3907  if (!source || !target)
3908  QT_THROW(std::bad_alloc()); // we must have run out of memory
3909  for (int x=0; x < width; ++x)
3910  target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
3911  }
3912  return dest;
3913 }
3914 
3916 {
3917 }
3918 
3920 {
3922  monoDestinationWithClut = false;
3923  destColor0 = 0;
3924  destColor1 = 0;
3925 }
3926 
3928 {
3929  m_buffer = (uchar *)image->bits();
3930  m_width = qMin(QT_RASTER_COORD_LIMIT, image->width());
3931  m_height = qMin(QT_RASTER_COORD_LIMIT, image->height());
3932  bytes_per_pixel = image->depth()/8;
3933  bytes_per_line = image->bytesPerLine();
3934 
3935  format = image->format();
3936  drawHelper = qDrawHelper + format;
3937  if (image->depth() == 1 && image->colorTable().size() == 2) {
3938  monoDestinationWithClut = true;
3939  destColor0 = PREMUL(image->colorTable()[0]);
3940  destColor1 = PREMUL(image->colorTable()[1]);
3941  }
3942 
3943  return format;
3944 }
3945 
3947 {
3948  memset(m_buffer, val, m_height*bytes_per_line);
3949 }
3950 
3951 
3952 #if defined(Q_WS_QWS)
3954 {
3955  m_buffer = reinterpret_cast<uchar*>(device->memory());
3956  m_width = qMin(QT_RASTER_COORD_LIMIT, device->width());
3957  m_height = qMin(QT_RASTER_COORD_LIMIT, device->height());
3958  bytes_per_pixel = device->depth() / 8;
3959  bytes_per_line = device->bytesPerLine();
3960  format = device->format();
3961 #ifndef QT_NO_RASTERCALLBACKS
3962  if (!m_buffer)
3963  drawHelper = qDrawHelperCallback + format;
3964  else
3965 #endif
3966  drawHelper = qDrawHelper + format;
3967 }
3968 
3970 {
3971  switch (m) {
3972  case PdmWidth:
3973  return widget->frameGeometry().width();
3974  case PdmHeight:
3975  return widget->frameGeometry().height();
3976  default:
3977  break;
3978  }
3979 
3980  return qt_paint_device_metric(widget, m);
3981 }
3982 
3984 {
3985  return (width() * depth() + 7) / 8;
3986 }
3987 
3988 #elif defined(Q_OS_SYMBIAN)
3989 
3990 void QRasterBuffer::prepareBuffer(int /* width */, int /* height */)
3991 {
3992 }
3993 
3994 #endif // Q_OS_SYMBIAN
3995 
4081 {
4082  clipSpanHeight = height;
4083  m_clipLines = 0;
4084 
4085  allocated = 0;
4086  m_spans = 0;
4087  xmin = xmax = ymin = ymax = 0;
4088  count = 0;
4089 
4090  enabled = true;
4091  hasRectClip = hasRegionClip = false;
4092 }
4093 
4095 {
4096  if (m_clipLines)
4097  free(m_clipLines);
4098  if (m_spans)
4099  free(m_spans);
4100 }
4101 
4103 {
4104  if (m_spans)
4105  return;
4106 
4107  if (!m_clipLines)
4108  m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
4109 
4110  Q_CHECK_PTR(m_clipLines);
4111  QT_TRY {
4112  m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
4113  allocated = clipSpanHeight;
4114  Q_CHECK_PTR(m_spans);
4115 
4116  QT_TRY {
4117  if (hasRectClip) {
4118  int y = 0;
4119  while (y < ymin) {
4120  m_clipLines[y].spans = 0;
4121  m_clipLines[y].count = 0;
4122  ++y;
4123  }
4124 
4125  const int len = clipRect.width();
4126  count = 0;
4127  while (y < ymax) {
4128  QSpan *span = m_spans + count;
4129  span->x = xmin;
4130  span->len = len;
4131  span->y = y;
4132  span->coverage = 255;
4133  ++count;
4134 
4135  m_clipLines[y].spans = span;
4136  m_clipLines[y].count = 1;
4137  ++y;
4138  }
4139 
4140  while (y < clipSpanHeight) {
4141  m_clipLines[y].spans = 0;
4142  m_clipLines[y].count = 0;
4143  ++y;
4144  }
4145  } else if (hasRegionClip) {
4146 
4147  const QVector<QRect> rects = clipRegion.rects();
4148  const int numRects = rects.size();
4149 
4150  { // resize
4151  const int maxSpans = (ymax - ymin) * numRects;
4152  if (maxSpans > allocated) {
4153  m_spans = q_check_ptr((QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan)));
4154  allocated = maxSpans;
4155  }
4156  }
4157 
4158  int y = 0;
4159  int firstInBand = 0;
4160  count = 0;
4161  while (firstInBand < numRects) {
4162  const int currMinY = rects.at(firstInBand).y();
4163  const int currMaxY = currMinY + rects.at(firstInBand).height();
4164 
4165  while (y < currMinY) {
4166  m_clipLines[y].spans = 0;
4167  m_clipLines[y].count = 0;
4168  ++y;
4169  }
4170 
4171  int lastInBand = firstInBand;
4172  while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y)
4173  ++lastInBand;
4174 
4175  while (y < currMaxY) {
4176 
4177  m_clipLines[y].spans = m_spans + count;
4178  m_clipLines[y].count = lastInBand - firstInBand + 1;
4179 
4180  for (int r = firstInBand; r <= lastInBand; ++r) {
4181  const QRect &currRect = rects.at(r);
4182  QSpan *span = m_spans + count;
4183  span->x = currRect.x();
4184  span->len = currRect.width();
4185  span->y = y;
4186  span->coverage = 255;
4187  ++count;
4188  }
4189  ++y;
4190  }
4191 
4192  firstInBand = lastInBand + 1;
4193  }
4194 
4195  Q_ASSERT(count <= allocated);
4196 
4197  while (y < clipSpanHeight) {
4198  m_clipLines[y].spans = 0;
4199  m_clipLines[y].count = 0;
4200  ++y;
4201  }
4202 
4203  }
4204  } QT_CATCH(...) {
4205  free(m_spans); // have to free m_spans again or someone might think that we were successfully initialized.
4206  m_spans = 0;
4207  QT_RETHROW;
4208  }
4209  } QT_CATCH(...) {
4210  free(m_clipLines); // same for clipLines
4211  m_clipLines = 0;
4212  QT_RETHROW;
4213  }
4214 }
4215 
4217 {
4218  Q_ASSERT(m_spans);
4219 
4220  if (count == 0) {
4221  ymin = ymax = xmin = xmax = 0;
4222  return;
4223  }
4224 
4225  int y = -1;
4226  ymin = m_spans[0].y;
4227  ymax = m_spans[count-1].y + 1;
4228  xmin = INT_MAX;
4229  xmax = 0;
4230 
4231  const int firstLeft = m_spans[0].x;
4232  const int firstRight = m_spans[0].x + m_spans[0].len;
4233  bool isRect = true;
4234 
4235  for (int i = 0; i < count; ++i) {
4236  QT_FT_Span_& span = m_spans[i];
4237 
4238  if (span.y != y) {
4239  if (span.y != y + 1 && y != -1)
4240  isRect = false;
4241  y = span.y;
4242  m_clipLines[y].spans = &span;
4243  m_clipLines[y].count = 1;
4244  } else
4245  ++m_clipLines[y].count;
4246 
4247  const int spanLeft = span.x;
4248  const int spanRight = spanLeft + span.len;
4249 
4250  if (spanLeft < xmin)
4251  xmin = spanLeft;
4252 
4253  if (spanRight > xmax)
4254  xmax = spanRight;
4255 
4256  if (spanLeft != firstLeft || spanRight != firstRight)
4257  isRect = false;
4258  }
4259 
4260  if (isRect) {
4261  hasRectClip = true;
4262  clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
4263  }
4264 }
4265 
4266 /*
4267  Convert \a rect to clip spans.
4268  */
4270 {
4271  if (hasRectClip && rect == clipRect)
4272  return;
4273 
4274 // qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect;
4275  hasRectClip = true;
4276  hasRegionClip = false;
4277  clipRect = rect;
4278 
4279  xmin = rect.x();
4280  xmax = rect.x() + rect.width();
4281  ymin = qMin(rect.y(), clipSpanHeight);
4282  ymax = qMin(rect.y() + rect.height(), clipSpanHeight);
4283 
4284  if (m_spans) {
4285  free(m_spans);
4286  m_spans = 0;
4287  }
4288 
4289 // qDebug() << xmin << xmax << ymin << ymax;
4290 }
4291 
4292 /*
4293  Convert \a region to clip spans.
4294  */
4296 {
4297  if (region.rectCount() == 1) {
4298  setClipRect(region.rects().at(0));
4299  return;
4300  }
4301 
4302  hasRegionClip = true;
4303  hasRectClip = false;
4304  clipRegion = region;
4305 
4306  { // set bounding rect
4307  const QRect rect = region.boundingRect();
4308  xmin = rect.x();
4309  xmax = rect.x() + rect.width();
4310  ymin = rect.y();
4311  ymax = rect.y() + rect.height();
4312  }
4313 
4314  if (m_spans) {
4315  free(m_spans);
4316  m_spans = 0;
4317  }
4318 
4319 }
4320 
4325 static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip,
4326  const QSpan *spans, const QSpan *end,
4327  QSpan **outSpans, int available)
4328 {
4329  const_cast<QClipData *>(clip)->initialize();
4330 
4331  QSpan *out = *outSpans;
4332 
4333  const QSpan *clipSpans = clip->m_spans + *currentClip;
4334  const QSpan *clipEnd = clip->m_spans + clip->count;
4335 
4336  while (available && spans < end ) {
4337  if (clipSpans >= clipEnd) {
4338  spans = end;
4339  break;
4340  }
4341  if (clipSpans->y > spans->y) {
4342  ++spans;
4343  continue;
4344  }
4345  if (spans->y != clipSpans->y) {
4346  if (spans->y < clip->count && clip->m_clipLines[spans->y].spans)
4347  clipSpans = clip->m_clipLines[spans->y].spans;
4348  else
4349  ++clipSpans;
4350  continue;
4351  }
4352  Q_ASSERT(spans->y == clipSpans->y);
4353 
4354  int sx1 = spans->x;
4355  int sx2 = sx1 + spans->len;
4356  int cx1 = clipSpans->x;
4357  int cx2 = cx1 + clipSpans->len;
4358 
4359  if (cx1 < sx1 && cx2 < sx1) {
4360  ++clipSpans;
4361  continue;
4362  } else if (sx1 < cx1 && sx2 < cx1) {
4363  ++spans;
4364  continue;
4365  }
4366  int x = qMax(sx1, cx1);
4367  int len = qMin(sx2, cx2) - x;
4368  if (len) {
4369  out->x = qMax(sx1, cx1);
4370  out->len = qMin(sx2, cx2) - out->x;
4371  out->y = spans->y;
4372  out->coverage = qt_div_255(spans->coverage * clipSpans->coverage);
4373  ++out;
4374  --available;
4375  }
4376  if (sx2 < cx2) {
4377  ++spans;
4378  } else {
4379  ++clipSpans;
4380  }
4381  }
4382 
4383  *outSpans = out;
4384  *currentClip = clipSpans - clip->m_spans;
4385  return spans;
4386 }
4387 
4388 static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userData)
4389 {
4390 // qDebug() << "qt_span_fill_clipped" << spanCount;
4391  QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
4392 
4393  Q_ASSERT(fillData->blend && fillData->unclipped_blend);
4394 
4395  const int NSPANS = 256;
4396  QSpan cspans[NSPANS];
4397  int currentClip = 0;
4398  const QSpan *end = spans + spanCount;
4399  while (spans < end) {
4400  QSpan *clipped = cspans;
4401  spans = qt_intersect_spans(fillData->clip, &currentClip, spans, end, &clipped, NSPANS);
4402 // qDebug() << "processed " << spanCount - (end - spans) << "clipped" << clipped-cspans
4403 // << "span:" << cspans->x << cspans->y << cspans->len << spans->coverage;
4404 
4405  if (clipped - cspans)
4406  fillData->unclipped_blend(clipped - cspans, cspans, fillData);
4407  }
4408 }
4409 
4410 /*
4411  \internal
4412  Clip spans to \a{clip}-rectangle.
4413  Returns number of unclipped spans
4414 */
4415 static int qt_intersect_spans(QT_FT_Span *spans, int numSpans,
4416  const QRect &clip)
4417 {
4418  const short minx = clip.left();
4419  const short miny = clip.top();
4420  const short maxx = clip.right();
4421  const short maxy = clip.bottom();
4422 
4423  int n = 0;
4424  for (int i = 0; i < numSpans; ++i) {
4425  if (spans[i].y > maxy)
4426  break;
4427  if (spans[i].y < miny
4428  || spans[i].x > maxx
4429  || spans[i].x + spans[i].len <= minx) {
4430  continue;
4431  }
4432  if (spans[i].x < minx) {
4433  spans[n].len = qMin(spans[i].len - (minx - spans[i].x), maxx - minx + 1);
4434  spans[n].x = minx;
4435  } else {
4436  spans[n].x = spans[i].x;
4437  spans[n].len = qMin(spans[i].len, ushort(maxx - spans[n].x + 1));
4438  }
4439  if (spans[n].len == 0)
4440  continue;
4441  spans[n].y = spans[i].y;
4442  spans[n].coverage = spans[i].coverage;
4443  ++n;
4444  }
4445  return n;
4446 }
4447 
4448 
4449 static void qt_span_fill_clipRect(int count, const QSpan *spans,
4450  void *userData)
4451 {
4452  QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
4453  Q_ASSERT(fillData->blend && fillData->unclipped_blend);
4454 
4455  Q_ASSERT(fillData->clip);
4456  Q_ASSERT(!fillData->clip->clipRect.isEmpty());
4457 
4458  // hw: check if this const_cast<> is safe!!!
4459  count = qt_intersect_spans(const_cast<QSpan*>(spans), count,
4460  fillData->clip->clipRect);
4461  if (count > 0)
4462  fillData->unclipped_blend(count, spans, fillData);
4463 }
4464 
4465 static void qt_span_clip(int count, const QSpan *spans, void *userData)
4466 {
4467  ClipData *clipData = reinterpret_cast<ClipData *>(userData);
4468 
4469 // qDebug() << " qt_span_clip: " << count << clipData->operation;
4470 // for (int i = 0; i < qMin(count, 10); ++i) {
4471 // qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage;
4472 // }
4473 
4474  switch (clipData->operation) {
4475 
4476  case Qt::IntersectClip:
4477  {
4478  QClipData *newClip = clipData->newClip;
4479  newClip->initialize();
4480 
4481  int currentClip = 0;
4482  const QSpan *end = spans + count;
4483  while (spans < end) {
4484  QSpan *newspans = newClip->m_spans + newClip->count;
4485  spans = qt_intersect_spans(clipData->oldClip, &currentClip, spans, end,
4486  &newspans, newClip->allocated - newClip->count);
4487  newClip->count = newspans - newClip->m_spans;
4488  if (spans < end) {
4489  newClip->m_spans = q_check_ptr((QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan)));
4490  newClip->allocated *= 2;
4491  }
4492  }
4493  }
4494  break;
4495 
4496  case Qt::UniteClip:
4497  case Qt::ReplaceClip:
4498  clipData->newClip->appendSpans(spans, count);
4499  break;
4500  case Qt::NoClip:
4501  break;
4502  }
4503 }
4504 
4505 #ifndef QT_NO_DEBUG
4507 {
4508  QImage image(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
4509 
4510  for (int y = 0; y < m_height; ++y) {
4511  uint *span = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y);
4512 
4513  for (int x=0; x<m_width; ++x) {
4514  uint argb = span[x];
4515  image.setPixel(x, y, argb);
4516  }
4517  }
4518  return image;
4519 }
4520 #endif
4521 
4522 
4524 {
4525  int w = qMin(m_width, target->width());
4526  int h = qMin(m_height, target->height());
4527 
4528  for (int y=0; y<h; ++y) {
4529  uint *sourceLine = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y);
4530  QRgb *dest = (QRgb *) target->scanLine(y);
4531  for (int x=0; x<w; ++x) {
4532  QRgb pixel = sourceLine[x];
4533  int alpha = qAlpha(pixel);
4534  if (!alpha) {
4535  dest[x] = 0;
4536  } else {
4537  dest[x] = (alpha << 24)
4538  | ((255*qRed(pixel)/alpha) << 16)
4539  | ((255*qGreen(pixel)/alpha) << 8)
4540  | ((255*qBlue(pixel)/alpha) << 0);
4541  }
4542  }
4543  }
4544 }
4545 
4546 
4548 {
4549  struct CacheInfo
4550  {
4552  stops(s), opacity(op), interpolationMode(mode) {}
4555  int opacity;
4557  };
4558 
4560 
4561 public:
4562  inline const uint *getBuffer(const QGradient &gradient, int opacity) {
4563  quint64 hash_val = 0;
4564 
4565  QGradientStops stops = gradient.stops();
4566  for (int i = 0; i < stops.size() && i <= 2; i++)
4567  hash_val += stops[i].second.rgba();
4568 
4569  QMutexLocker lock(&mutex);
4570  QGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
4571 
4572  if (it == cache.constEnd())
4573  return addCacheElement(hash_val, gradient, opacity);
4574  else {
4575  do {
4576  const CacheInfo &cache_info = it.value();
4577  if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode())
4578  return cache_info.buffer;
4579  ++it;
4580  } while (it != cache.constEnd() && it.key() == hash_val);
4581  // an exact match for these stops and opacity was not found, create new cache
4582  return addCacheElement(hash_val, gradient, opacity);
4583  }
4584  }
4585 
4586  inline int paletteSize() const { return GRADIENT_STOPTABLE_SIZE; }
4587 protected:
4588  inline int maxCacheSize() const { return 60; }
4589  inline void generateGradientColorTable(const QGradient& g,
4590  uint *colorTable,
4591  int size, int opacity) const;
4592  uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) {
4593  if (cache.size() == maxCacheSize()) {
4594  // may remove more than 1, but OK
4595  cache.erase(cache.begin() + (qrand() % maxCacheSize()));
4596  }
4597  CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
4598  generateGradientColorTable(gradient, cache_entry.buffer, paletteSize(), opacity);
4599  return cache.insert(hash_val, cache_entry).value().buffer;
4600  }
4601 
4602  QGradientColorTableHash cache;
4604 };
4605 
4606 void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const
4607 {
4608  QGradientStops stops = gradient.stops();
4609  int stopCount = stops.count();
4610  Q_ASSERT(stopCount > 0);
4611 
4612  bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
4613 
4614  if (stopCount == 2) {
4615  uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
4616  uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity);
4617 
4618  qreal first_stop = stops[0].first;
4619  qreal second_stop = stops[1].first;
4620 
4621  if (second_stop < first_stop) {
4622  qSwap(first_color, second_color);
4623  qSwap(first_stop, second_stop);
4624  }
4625 
4626  if (colorInterpolation) {
4627  first_color = PREMUL(first_color);
4628  second_color = PREMUL(second_color);
4629  }
4630 
4631  int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1));
4632  int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1));
4633 
4634  uint red_first = qRed(first_color) << 16;
4635  uint green_first = qGreen(first_color) << 16;
4636  uint blue_first = qBlue(first_color) << 16;
4637  uint alpha_first = qAlpha(first_color) << 16;
4638 
4639  uint red_second = qRed(second_color) << 16;
4640  uint green_second = qGreen(second_color) << 16;
4641  uint blue_second = qBlue(second_color) << 16;
4642  uint alpha_second = qAlpha(second_color) << 16;
4643 
4644  int i = 0;
4645  for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) {
4646  if (colorInterpolation)
4647  colorTable[i] = first_color;
4648  else
4649  colorTable[i] = PREMUL(first_color);
4650  }
4651 
4652  if (i < second_index) {
4653  qreal reciprocal = qreal(1) / (second_index - first_index);
4654 
4655  int red_delta = qRound(int(red_second - red_first) * reciprocal);
4656  int green_delta = qRound(int(green_second - green_first) * reciprocal);
4657  int blue_delta = qRound(int(blue_second - blue_first) * reciprocal);
4658  int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal);
4659 
4660  // rounding
4661  red_first += 1 << 15;
4662  green_first += 1 << 15;
4663  blue_first += 1 << 15;
4664  alpha_first += 1 << 15;
4665 
4666  for (; i < qMin(GRADIENT_STOPTABLE_SIZE, second_index); ++i) {
4667  red_first += red_delta;
4668  green_first += green_delta;
4669  blue_first += blue_delta;
4670  alpha_first += alpha_delta;
4671 
4672  const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000)
4673  | ((green_first >> 8) & 0xff00) | (blue_first >> 16);
4674 
4675  if (colorInterpolation)
4676  colorTable[i] = color;
4677  else
4678  colorTable[i] = PREMUL(color);
4679  }
4680  }
4681 
4682  for (; i < GRADIENT_STOPTABLE_SIZE; ++i) {
4683  if (colorInterpolation)
4684  colorTable[i] = second_color;
4685  else
4686  colorTable[i] = PREMUL(second_color);
4687  }
4688 
4689  return;
4690  }
4691 
4692  uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
4693  if (stopCount == 1) {
4694  current_color = PREMUL(current_color);
4695  for (int i = 0; i < size; ++i)
4696  colorTable[i] = current_color;
4697  return;
4698  }
4699 
4700  // The position where the gradient begins and ends
4701  qreal begin_pos = stops[0].first;
4702  qreal end_pos = stops[stopCount-1].first;
4703 
4704  int pos = 0; // The position in the color table.
4705  uint next_color;
4706 
4707  qreal incr = 1 / qreal(size); // the double increment.
4708  qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1)
4709 
4710  // Up to first point
4711  colorTable[pos++] = PREMUL(current_color);
4712  while (dpos <= begin_pos) {
4713  colorTable[pos] = colorTable[pos - 1];
4714  ++pos;
4715  dpos += incr;
4716  }
4717 
4718  int current_stop = 0; // We always interpolate between current and current + 1.
4719 
4720  qreal t; // position between current left and right stops
4721  qreal t_delta; // the t increment per entry in the color table
4722 
4723  if (dpos < end_pos) {
4724  // Gradient area
4725  while (dpos > stops[current_stop+1].first)
4726  ++current_stop;
4727 
4728  if (current_stop != 0)
4729  current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity);
4730  next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity);
4731 
4732  if (colorInterpolation) {
4733  current_color = PREMUL(current_color);
4734  next_color = PREMUL(next_color);
4735  }
4736 
4737  qreal diff = stops[current_stop+1].first - stops[current_stop].first;
4738  qreal c = (diff == 0) ? qreal(0) : 256 / diff;
4739  t = (dpos - stops[current_stop].first) * c;
4740  t_delta = incr * c;
4741 
4742  while (true) {
4743  Q_ASSERT(current_stop < stopCount);
4744 
4745  int dist = qRound(t);
4746  int idist = 256 - dist;
4747 
4748  if (colorInterpolation)
4749  colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
4750  else
4751  colorTable[pos] = PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
4752 
4753  ++pos;
4754  dpos += incr;
4755 
4756  if (dpos >= end_pos)
4757  break;
4758 
4759  t += t_delta;
4760 
4761  int skip = 0;
4762  while (dpos > stops[current_stop+skip+1].first)
4763  ++skip;
4764 
4765  if (skip != 0) {
4766  current_stop += skip;
4767  if (skip == 1)
4768  current_color = next_color;
4769  else
4770  current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity);
4771  next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity);
4772 
4773  if (colorInterpolation) {
4774  if (skip != 1)
4775  current_color = PREMUL(current_color);
4776  next_color = PREMUL(next_color);
4777  }
4778 
4779  qreal diff = stops[current_stop+1].first - stops[current_stop].first;
4780  qreal c = (diff == 0) ? qreal(0) : 256 / diff;
4781  t = (dpos - stops[current_stop].first) * c;
4782  t_delta = incr * c;
4783  }
4784  }
4785  }
4786 
4787  // After last point
4788  current_color = PREMUL(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity));
4789  while (pos < size - 1) {
4790  colorTable[pos] = current_color;
4791  ++pos;
4792  }
4793 
4794  // Make sure the last color stop is represented at the end of the table
4795  colorTable[size - 1] = current_color;
4796 }
4797 
4798 Q_GLOBAL_STATIC(QGradientCache, qt_gradient_cache)
4799 
4800 
4802 {
4803  rasterBuffer = rb;
4804 #ifdef Q_WS_QWS
4805  rasterEngine = const_cast<QRasterPaintEngine *>(pe);
4806 #endif
4807  type = None;
4808  txop = 0;
4809  bilinear = false;
4810  m11 = m22 = m33 = 1.;
4811  m12 = m13 = m21 = m23 = dx = dy = 0.0;
4812  clip = pe ? pe->d_func()->clip() : 0;
4813 }
4814 
4815 Q_GUI_EXPORT extern QImage qt_imageForBrush(int brushStyle, bool invert);
4816 
4818 {
4819  Qt::BrushStyle brushStyle = qbrush_style(brush);
4820  switch (brushStyle) {
4821  case Qt::SolidPattern: {
4822  type = Solid;
4823  QColor c = qbrush_color(brush);
4824  QRgb rgba = c.rgba();
4825  solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha));
4826  if ((solid.color & 0xff000000) == 0
4827  && compositionMode == QPainter::CompositionMode_SourceOver) {
4828  type = None;
4829  }
4830  break;
4831  }
4832 
4834  {
4835  type = LinearGradient;
4836  const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient());
4837  gradient.alphaColor = !brush.isOpaque() || alpha != 256;
4838  gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha));
4839  gradient.spread = g->spread();
4840 
4841  QLinearGradientData &linearData = gradient.linear;
4842 
4843  linearData.origin.x = g->start().x();
4844  linearData.origin.y = g->start().y();
4845  linearData.end.x = g->finalStop().x();
4846  linearData.end.y = g->finalStop().y();
4847  break;
4848  }
4849 
4851  {
4852  type = RadialGradient;
4853  const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient());
4854  gradient.alphaColor = !brush.isOpaque() || alpha != 256;
4855  gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha));
4856  gradient.spread = g->spread();
4857 
4858  QRadialGradientData &radialData = gradient.radial;
4859 
4860  QPointF center = g->center();
4861  radialData.center.x = center.x();
4862  radialData.center.y = center.y();
4863  radialData.center.radius = g->centerRadius();
4864  QPointF focal = g->focalPoint();
4865  radialData.focal.x = focal.x();
4866  radialData.focal.y = focal.y();
4867  radialData.focal.radius = g->focalRadius();
4868  }
4869  break;
4870 
4872  {
4873  type = ConicalGradient;
4874  const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient());
4875  gradient.alphaColor = !brush.isOpaque() || alpha != 256;
4876  gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha));
4877  gradient.spread = QGradient::RepeatSpread;
4878 
4879  QConicalGradientData &conicalData = gradient.conical;
4880 
4881  QPointF center = g->center();
4882  conicalData.center.x = center.x();
4883  conicalData.center.y = center.y();
4884  conicalData.angle = g->angle() * 2 * Q_PI / 360.0;
4885  }
4886  break;
4887 
4888  case Qt::Dense1Pattern:
4889  case Qt::Dense2Pattern:
4890  case Qt::Dense3Pattern:
4891  case Qt::Dense4Pattern:
4892  case Qt::Dense5Pattern:
4893  case Qt::Dense6Pattern:
4894  case Qt::Dense7Pattern:
4895  case Qt::HorPattern:
4896  case Qt::VerPattern:
4897  case Qt::CrossPattern:
4898  case Qt::BDiagPattern:
4899  case Qt::FDiagPattern:
4900  case Qt::DiagCrossPattern:
4901  type = Texture;
4902  if (!tempImage)
4903  tempImage = new QImage();
4904  *tempImage = rasterBuffer->colorizeBitmap(qt_imageForBrush(brushStyle, true), brush.color());
4905  initTexture(tempImage, alpha, QTextureData::Tiled);
4906  break;
4907  case Qt::TexturePattern:
4908  type = Texture;
4909  if (!tempImage)
4910  tempImage = new QImage();
4911 
4912  if (qHasPixmapTexture(brush) && brush.texture().isQBitmap())
4913  *tempImage = rasterBuffer->colorizeBitmap(brush.textureImage(), brush.color());
4914  else
4915  *tempImage = brush.textureImage();
4916  initTexture(tempImage, alpha, QTextureData::Tiled, tempImage->rect());
4917  break;
4918 
4919  case Qt::NoBrush:
4920  default:
4921  type = None;
4922  break;
4923  }
4924  adjustSpanMethods();
4925 }
4926 
4928 {
4929  bitmapBlit = 0;
4930  alphamapBlit = 0;
4931  alphaRGBBlit = 0;
4932 
4933  fillRect = 0;
4934 
4935  switch(type) {
4936  case None:
4937  unclipped_blend = 0;
4938  break;
4939  case Solid:
4940  unclipped_blend = rasterBuffer->drawHelper->blendColor;
4941  bitmapBlit = rasterBuffer->drawHelper->bitmapBlit;
4942  alphamapBlit = rasterBuffer->drawHelper->alphamapBlit;
4943  alphaRGBBlit = rasterBuffer->drawHelper->alphaRGBBlit;
4944  fillRect = rasterBuffer->drawHelper->fillRect;
4945  break;
4946  case LinearGradient:
4947  case RadialGradient:
4948  case ConicalGradient:
4949  unclipped_blend = rasterBuffer->drawHelper->blendGradient;
4950  break;
4951  case Texture:
4952 #ifdef Q_WS_QWS
4953 #ifndef QT_NO_RASTERCALLBACKS
4954  if (!rasterBuffer->buffer())
4955  unclipped_blend = qBlendTextureCallback;
4956  else
4957 #endif
4958  unclipped_blend = qBlendTexture;
4959 #else
4960  unclipped_blend = qBlendTexture;
4961 #endif
4962  if (!texture.imageData)
4963  unclipped_blend = 0;
4964 
4965  break;
4966  }
4967  // setup clipping
4968  if (!unclipped_blend) {
4969  blend = 0;
4970  } else if (!clip) {
4971  blend = unclipped_blend;
4972  } else if (clip->hasRectClip) {
4973  blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect;
4974  } else {
4975  blend = qt_span_fill_clipped;
4976  }
4977 }
4978 
4980 {
4981  QTransform delta;
4982  // make sure we round off correctly in qdrawhelper.cpp
4983  delta.translate(1.0 / 65536, 1.0 / 65536);
4984 
4985  QTransform inv = (delta * matrix).inverted();
4986  m11 = inv.m11();
4987  m12 = inv.m12();
4988  m13 = inv.m13();
4989  m21 = inv.m21();
4990  m22 = inv.m22();
4991  m23 = inv.m23();
4992  m33 = inv.m33();
4993  dx = inv.dx();
4994  dy = inv.dy();
4995  txop = inv.type();
4996  bilinear = bilin;
4997 
4998  const bool affine = !m13 && !m23;
4999  fast_matrix = affine
5000  && m11 * m11 + m21 * m21 < 1e4
5001  && m12 * m12 + m22 * m22 < 1e4
5002  && qAbs(dx) < 1e4
5003  && qAbs(dy) < 1e4;
5004 
5005  adjustSpanMethods();
5006 }
5007 
5008 extern const QVector<QRgb> *qt_image_colortable(const QImage &image);
5009 
5010 void QSpanData::initTexture(const QImage *image, int alpha, QTextureData::Type _type, const QRect &sourceRect)
5011 {
5012  const QImageData *d = const_cast<QImage *>(image)->data_ptr();
5013  if (!d || d->height == 0) {
5014  texture.imageData = 0;
5015  texture.width = 0;
5016  texture.height = 0;
5017  texture.x1 = 0;
5018  texture.y1 = 0;
5019  texture.x2 = 0;
5020  texture.y2 = 0;
5021  texture.bytesPerLine = 0;
5022  texture.format = QImage::Format_Invalid;
5023  texture.colorTable = 0;
5024  texture.hasAlpha = alpha != 256;
5025  } else {
5026  texture.imageData = d->data;
5027  texture.width = d->width;
5028  texture.height = d->height;
5029 
5030  if (sourceRect.isNull()) {
5031  texture.x1 = 0;
5032  texture.y1 = 0;
5033  texture.x2 = texture.width;
5034  texture.y2 = texture.height;
5035  } else {
5036  texture.x1 = sourceRect.x();
5037  texture.y1 = sourceRect.y();
5038  texture.x2 = qMin(texture.x1 + sourceRect.width(), d->width);
5039  texture.y2 = qMin(texture.y1 + sourceRect.height(), d->height);
5040  }
5041 
5042  texture.bytesPerLine = d->bytes_per_line;
5043 
5044  texture.format = d->format;
5045  texture.colorTable = (d->format <= QImage::Format_Indexed8 && !d->colortable.isEmpty()) ? &d->colortable : 0;
5046  texture.hasAlpha = image->hasAlphaChannel() || alpha != 256;
5047  }
5048  texture.const_alpha = alpha;
5049  texture.type = _type;
5050 
5051  adjustSpanMethods();
5052 }
5053 
5058 static inline void drawEllipsePoints(int x, int y, int length,
5059  const QRect &rect,
5060  const QRect &clip,
5061  ProcessSpans pen_func, ProcessSpans brush_func,
5062  QSpanData *pen_data, QSpanData *brush_data)
5063 {
5064  if (length == 0)
5065  return;
5066 
5067  QT_FT_Span outline[4];
5068  const int midx = rect.x() + (rect.width() + 1) / 2;
5069  const int midy = rect.y() + (rect.height() + 1) / 2;
5070 
5071  x = x + midx;
5072  y = midy - y;
5073 
5074  // topleft
5075  outline[0].x = midx + (midx - x) - (length - 1) - (rect.width() & 0x1);
5076  outline[0].len = qMin(length, x - outline[0].x);
5077  outline[0].y = y;
5078  outline[0].coverage = 255;
5079 
5080  // topright
5081  outline[1].x = x;
5082  outline[1].len = length;
5083  outline[1].y = y;
5084  outline[1].coverage = 255;
5085 
5086  // bottomleft
5087  outline[2].x = outline[0].x;
5088  outline[2].len = outline[0].len;
5089  outline[2].y = midy + (midy - y) - (rect.height() & 0x1);
5090  outline[2].coverage = 255;
5091 
5092  // bottomright
5093  outline[3].x = x;
5094  outline[3].len = length;
5095  outline[3].y = outline[2].y;
5096  outline[3].coverage = 255;
5097 
5098  if (brush_func && outline[0].x + outline[0].len < outline[1].x) {
5099  QT_FT_Span fill[2];
5100 
5101  // top fill
5102  fill[0].x = outline[0].x + outline[0].len - 1;
5103  fill[0].len = qMax(0, outline[1].x - fill[0].x);
5104  fill[0].y = outline[1].y;
5105  fill[0].coverage = 255;
5106 
5107  // bottom fill
5108  fill[1].x = outline[2].x + outline[2].len - 1;
5109  fill[1].len = qMax(0, outline[3].x - fill[1].x);
5110  fill[1].y = outline[3].y;
5111  fill[1].coverage = 255;
5112 
5113  int n = (fill[0].y >= fill[1].y ? 1 : 2);
5114  n = qt_intersect_spans(fill, n, clip);
5115  if (n > 0)
5116  brush_func(n, fill, brush_data);
5117  }
5118  if (pen_func) {
5119  int n = (outline[1].y >= outline[2].y ? 2 : 4);
5120  n = qt_intersect_spans(outline, n, clip);
5121  if (n > 0)
5122  pen_func(n, outline, pen_data);
5123  }
5124 }
5125 
5133 static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
5134  ProcessSpans pen_func, ProcessSpans brush_func,
5135  QSpanData *pen_data, QSpanData *brush_data)
5136 {
5137  const qreal a = qreal(rect.width()) / 2;
5138  const qreal b = qreal(rect.height()) / 2;
5139  qreal d = b*b - (a*a*b) + qreal(0.25)*a*a;
5140 
5141  int x = 0;
5142  int y = (rect.height() + 1) / 2;
5143  int startx = x;
5144 
5145  // region 1
5146  while (a*a*(2*y - 1) > 2*b*b*(x + 1)) {
5147  if (d < 0) { // select E
5148  d += b*b*(2*x + 3);
5149  ++x;
5150  } else { // select SE
5151  d += b*b*(2*x + 3) + a*a*(-2*y + 2);
5152  drawEllipsePoints(startx, y, x - startx + 1, rect, clip,
5153  pen_func, brush_func, pen_data, brush_data);
5154  startx = ++x;
5155  --y;
5156  }
5157  }
5158  drawEllipsePoints(startx, y, x - startx + 1, rect, clip,
5159  pen_func, brush_func, pen_data, brush_data);
5160 
5161  // region 2
5162  d = b*b*(x + qreal(0.5))*(x + qreal(0.5)) + a*a*((y - 1)*(y - 1) - b*b);
5163  const int miny = rect.height() & 0x1;
5164  while (y > miny) {
5165  if (d < 0) { // select SE
5166  d += b*b*(2*x + 2) + a*a*(-2*y + 3);
5167  ++x;
5168  } else { // select S
5169  d += a*a*(-2*y + 3);
5170  }
5171  --y;
5172  drawEllipsePoints(x, y, 1, rect, clip,
5173  pen_func, brush_func, pen_data, brush_data);
5174  }
5175 }
5176 
5198 #ifdef QT_DEBUG_DRAW
5199 void dumpClip(int width, int height, const QClipData *clip)
5200 {
5201  QImage clipImg(width, height, QImage::Format_ARGB32_Premultiplied);
5202  clipImg.fill(0xffff0000);
5203 
5204  int x0 = width;
5205  int x1 = 0;
5206  int y0 = height;
5207  int y1 = 0;
5208 
5209  ((QClipData *) clip)->spans(); // Force allocation of the spans structure...
5210 
5211  for (int i = 0; i < clip->count; ++i) {
5212  const QSpan *span = ((QClipData *) clip)->spans() + i;
5213  for (int j = 0; j < span->len; ++j)
5214  clipImg.setPixel(span->x + j, span->y, 0xffffff00);
5215  x0 = qMin(x0, int(span->x));
5216  x1 = qMax(x1, int(span->x + span->len - 1));
5217 
5218  y0 = qMin(y0, int(span->y));
5219  y1 = qMax(y1, int(span->y));
5220  }
5221 
5222  static int counter = 0;
5223 
5224  Q_ASSERT(y0 >= 0);
5225  Q_ASSERT(x0 >= 0);
5226  Q_ASSERT(y1 >= 0);
5227  Q_ASSERT(x1 >= 0);
5228 
5229  fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1);
5230  clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++));
5231 }
5232 #endif
5233 
5234 
ElementType type
the type of element
Definition: qpainterpath.h:81
qreal focalRadius() const
Returns the focal radius of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2211
virtual void drawPoints(const QPointF *points, int pointCount)
Draws the first pointCount points in the buffer points.
QClipData * oldClip
void resize(int size)
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
static const qreal aliasedCoordinateDelta
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
QPointF bottomRight() const
Returns the position of the rectangle&#39;s bottom-right corner.
Definition: qrect.h:540
T * q_check_ptr(T *p)
Definition: qglobal.h:1857
int width
Definition: qimage_p.h:76
static const QSpan * qt_intersect_spans(const QClipData *clip, int *currentClip, const QSpan *spans, const QSpan *end, QSpan **outSpans, int available)
void qBlendTextureCallback(int count, const QSpan *spans, void *userData)
QPointF focalPoint() const
Returns the focal point of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2251
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
const QT_FT_Raster_Funcs qt_ft_grays_raster
Definition: qgrayraster.c:1931
static void qt_span_clip(int count, const QSpan *spans, void *userData)
QFontEngine * fontEngine
const T * constData() const
QImage toImage() const
Converts the pixmap to a QImage.
Definition: qpixmap.cpp:542
ElementType
This enum describes the types of elements used to connect vertices in subpaths.
Definition: qpainterpath.h:70
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
void setClipRegion(const QRegion &region)
QScopedPointer< QClipData > baseClip
Format
The following image formats are available in Qt.
Definition: qimage.h:91
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
static void callback(AuServer *, AuEventHandlerRec *, AuEvent *e, AuPointer p)
Definition: qsound_x11.cpp:170
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
void saveBuffer(const QString &s) const
void setP1(const QPointF &p1)
Sets the starting point of this line to p1.
Definition: qline.h:381
void lineTo(const QPointF &pt)
QImage::Format format
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
unsigned int QRgb
Definition: qrgb.h:53
BrushStyle
Definition: qnamespace.h:1162
QT_FT_Raster_DoneFunc raster_done
virtual bool supportsSubPixelPositions() const
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
void setHeight(int h)
Sets the height of the rectangle to the given height.
Definition: qrect.h:445
void(* SrcOverScaleFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, int srch, const QRectF &targetRect, const QRectF &sourceRect, const QRect &clipRect, int const_alpha)
int type
Definition: qmetatype.cpp:239
double qreal
Definition: qglobal.h:1193
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
virtual QImage alphaMapForGlyph(glyph_t)
qreal determinant() const
Returns the matrix&#39;s determinant.
Definition: qtransform.h:228
unsigned char c[8]
Definition: qnumeric_p.h:62
qreal opacity() const
Returns the opacity in the current paint engine state.
Definition: qpainter.cpp:9529
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
int q_gray_rendered_spans(QT_FT_Raster raster)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const QColor & color() const
Returns the brush color.
Definition: qbrush.h:183
QHash< GlyphAndSubPixelPosition, Coord > coords
static void qt_ft_outline_move_to(qfixed x, qfixed y, void *data)
unsigned char coverage
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
#define GRADIENT_STOPTABLE_SIZE
QFontEngine * fontEngine() const
QPointer< QWidget > widget
static uchar * alignAddress(uchar *address, quintptr alignmentMask)
QSize size() const
Returns the size of the pixmap.
Definition: qpixmap.cpp:661
qreal length() const
Returns the length of the line.
Definition: qline.cpp:698
int elementCount() const
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
The QCustomRasterPaintDevice class is provided to activate hardware accelerated paint engines in Qt f...
QRasterPaintEngineState * state()
bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
qreal m32() const
Returns the vertical translation factor.
Definition: qtransform.h:265
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
QPainter::RenderHints renderHints
Definition: qpainter_p.h:158
bool isEmpty() const
int qCeil(qreal v)
Definition: qmath.h:63
T * data() const
Returns the value of the pointer referenced by this object.
const QGradient * gradient() const
Returns the gradient describing this brush.
Definition: qbrush.cpp:871
QPainter::CompositionMode composition_mode
Definition: qpainter_p.h:174
#define it(className, varName)
Qt::BrushStyle qbrush_style(const QBrush &b)
Definition: qpainter_p.h:96
const QChar * chars
PaintEngineFeatures gccaps
Definition: qpaintengine.h:240
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
QFixedPoint * glyphPositions
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
QFixed subPixelPositionForX(QFixed x) const
static void qt_ft_outline_line_to(qfixed x, qfixed y, void *data)
QPoint p1() const
Returns the line&#39;s start point.
Definition: qline.h:132
void drawLine(const QPointF &p1, const QPointF &p2)
unsigned short len
GlyphFormat defaultGlyphFormat() const
const QImage & image() const
ClipType clipType() const
Returns the type of the clip currently set.
void rasterize(const QT_FT_Outline *outline, Qt::FillRule fillRule)
int qFloor(qreal v)
Definition: qmath.h:73
void moveTo(const QPointF &pt)
void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix)
static const uchar inv
Definition: qisciicodec.cpp:91
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
QPointF p1() const
Returns the line&#39;s start point.
Definition: qline.h:314
#define error(msg)
QScopedPointer< QBrushData, QBrushDataPointerDeleter > d
Definition: qbrush.h:146
QPoint p2() const
Returns the line&#39;s end point.
Definition: qline.h:137
T & first()
Returns a reference to the first item in the vector.
Definition: qvector.h:260
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
~QRasterPaintEngine()
Destroys this paint engine.
int height() const
Definition: qpaintdevice.h:92
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
RenderFlags flags
The QConicalGradient class is used in combination with QBrush to specify a conical gradient brush...
Definition: qbrush.h:329
void drawLines(const QLine *line, int lineCount)
Reimplemented Function
QTransform transform() const
Returns the matrix in the current paint engine state.
Definition: qpainter.cpp:9377
AlphaRGBBlitFunc alphaRGBBlit
QGradientColorTableHash cache
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QT_FT_SpanFunc gray_spans
FillRule
Definition: qnamespace.h:1485
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
void resetBuffer(int val=0)
static bool isRect(const T *pts, int elementCount)
void drawEllipse(const QRectF &rect)
Reimplemented Function
QRect clipBoundingRect() const
Returns the bounding rect of the currently set clip.
static void drawEllipsePoints(int x, int y, int length, const QRect &rect, const QRect &clip, ProcessSpans pen_func, ProcessSpans brush_func, QSpanData *pen_data, QSpanData *brush_data)
QRect normalized() const
Returns a normalized rectangle; i.e., a rectangle that has a non-negative width and height...
Definition: qrect.cpp:322
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
QT_FT_SpanFunc ProcessSpans
CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode)
QRect frameGeometry
geometry of the widget relative to its parent including any window frame
Definition: qwidget.h:159
bool begin(QPaintDevice *device)
Reimplemented Function
QPointF topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:539
bool save(const QString &fileName, const char *format=0, int quality=-1) const
Saves the image to the file with the given fileName, using the given image file format and quality fa...
Definition: qimage.cpp:5346
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
QRect translated(int dx, int dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:328
void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill)
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr)
Reimplemented Function
virtual uint flags() const
ProcessSpans getBrushFunc(const QRect &rect, const QSpanData *data) const
void updateBrush(const QBrush &brush)
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
Definition: qglobal.h:2030
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
Definition: qimage.cpp:6495
QPoint coordinateOffset() const
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
long ASN1_INTEGER_get ASN1_INTEGER * a
QRect intersected(const QRect &other) const
Returns the intersection of this rectangle and the given rectangle.
Definition: qrect.h:481
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
Qt::PenJoinStyle qpen_joinStyle(const QPen &p)
Definition: qpainter_p.h:91
void fillPath(const QPainterPath &path, QSpanData *fillData)
QPointF bottomLeft() const
Returns the position of the rectangle&#39;s bottom-left corner.
Definition: qrect.h:542
SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats]
void setClipRect(const QRect &rect)
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
virtual QImage::Format format() const
Returns the format of the device&#39;s memory buffet.
int depth() const
Returns the depth of the pixmap.
Definition: qpixmap.cpp:695
MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3]
Definition: qmemrotate.cpp:627
QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t)
QScopedPointer< QRasterBuffer > rasterBuffer
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QRadialGradient class is used in combination with QBrush to specify a radial gradient brush...
Definition: qbrush.h:297
void setY(int y)
Sets the top edge of the rectangle to the given y coordinate.
Definition: qrect.h:285
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
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
Q_CORE_EXPORT int qrand()
Qt::PenCapStyle qpen_capStyle(const QPen &p)
Definition: qpainter_p.h:90
static bool monoVal(const uchar *s, int x)
int bytesPerLine() const
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
const QVector< QRgb > * qt_image_colortable(const QImage &image)
Definition: qimage.cpp:122
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QClipData(int height)
#define QT_FT_RASTER_FLAG_CLIP
QVector< QRgb > colortable
Definition: qimage_p.h:80
TransformationType type() const
Returns the transformation type of this matrix.
void set(const QRect &r)
QSolidData solid
#define Q_D(Class)
Definition: qglobal.h:2482
bool isUnclipped_normalized(const QRect &rect) const
Returns true if the rectangle is completely within the current clip state of the paint engine...
QTransform transform() const
Returns the current transformation matrix for the brush.
Definition: qbrush.h:185
QImage * tempImage
qreal angle() const
Returns the start angle of the conical gradient in logical coordinates.
Definition: qbrush.cpp:2433
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
QRgb pixel(int x, int y) const
Returns the color of the pixel at coordinates (x, y).
Definition: qimage.cpp:4240
static const uint base
Definition: qurl.cpp:268
virtual Type type() const =0
virtual int devType() const
Definition: qpaintdevice.h:167
const QPainterPath::ElementType * elements() const
void init(QPainter *p)
Definition: qpainter.cpp:8770
static QString fromRawData(const QChar *, int size)
Constructs a QString that uses the first size Unicode characters in the array unicode.
Definition: qstring.cpp:7673
bool end()
Reimplemented Function
QPainter::CompositionMode compositionMode
QVector< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition: qpen.cpp:466
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
int rectCount() const
Returns the number of rectangles that will be returned in rects().
Definition: qregion.cpp:4461
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
void updateMatrix(const QTransform &matrix)
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
PenStyle
Definition: qnamespace.h:1134
virtual int bytesPerLine() const
Returns the number of bytes per line in the framebuffer.
Glyph * getGlyph(glyph_t index, QFixed subPixelPosition=0) const
InterpolationMode interpolationMode() const
Returns the interpolation mode of this gradient.
Definition: qbrush.cpp:1607
QT_FT_Raster_BitSet_Func bit_set
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
void drawRects(const QRect *rects, int rectCount)
Reimplemented Function
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QPointF center() const
Returns the center of the conical gradient in logical coordinates.
Definition: qbrush.cpp:2391
QT_FT_Outline * outline()
BitmapBlitFunc bitmapBlit
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:250
void setAntialiased(bool antialiased)
#define Q_Q(Class)
Definition: qglobal.h:2483
struct QConicalGradientData::@233 center
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision...
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
ProcessSpans blend
bool qt_applefontsmoothing_enabled
static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData)
static const QRectF boundingRect(const QPointF *points, int pointCount)
QRectF controlPointRect() const
Q_CORE_EXPORT void qDebug(const char *,...)
QGradientStops stops() const
Returns the stop points for this gradient.
Definition: qbrush.cpp:1520
void drawImage(const QPointF &p, const QImage &img)
void initializeRasterizer(QSpanData *data)
void qBlendTexture(int count, const QSpan *spans, void *userData)
virtual void stroke(const QVectorPath &path, const QPen &pen)
static bool splitPolygon(const QPointF *points, int pointCount, QVector< QPointF > *upper, QVector< QPointF > *lower)
QGlyphLayout glyphs
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
#define QT_RETHROW
Definition: qglobal.h:1539
unsigned char uchar
Definition: qglobal.h:994
virtual QImage toImage() const =0
virtual int metric(PaintDeviceMetric m) const
Reimplemented Function
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
TransformationType
Definition: qtransform.h:68
RectFillFunc fillRect
#define ARGB_COMBINE_ALPHA(argb, alpha)
QMultiHash< quint64, CacheInfo > QGradientColorTableHash
#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
int width() const
Definition: qpaintdevice.h:91
SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats]
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s)
int height
Definition: qimage_p.h:77
struct FT_FaceRec_ * FT_Face
Definition: qfont.h:50
void setupMatrix(const QTransform &matrix, int bilinear)
QTransform transform
Definition: qbrush.h:179
bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush &brush)
Definition: qbrush.cpp:223
const int QT_RASTER_COORD_LIMIT
static float pixelSize(const QFontDef &request, int dpi)
Definition: qfont_win.cpp:80
unsigned __int64 quint64
Definition: qglobal.h:943
#define QT_THROW(A)
Definition: qglobal.h:1538
QImage bufferImage() const
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition: qpen.cpp:840
static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip, ProcessSpans pen_func, ProcessSpans brush_func, QSpanData *pen_data, QSpanData *brush_data)
Draws an ellipse using the integer point midpoint algorithm.
void drawPoints(const QPointF *points, int pointCount)
Reimplemented Function
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
Definition: qregion.cpp:4098
void setCGContext(CGContextRef ref)
static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result)
Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
Definition: qcssparser.cpp:329
#define calloc(a, b)
static QRect toNormalizedFillRect(const QRectF &rect)
uint buffer[GRADIENT_STOPTABLE_SIZE]
struct QClipData::ClipLine * m_clipLines
void unlockFace() const
void setActive(bool newState)
Sets the active state of the paint engine to state.
Definition: qpaintengine.h:155
Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
static void drawRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface)
#define QT_FT_RASTER_FLAG_DIRECT
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
qreal qpen_widthf(const QPen &p)
Definition: qpainter_p.h:88
void drawStaticTextItem(QStaticTextItem *textItem)
Reimplemented Function
void rasterizeLine(const QPointF &a, const QPointF &b, qreal width, bool squareCap=false)
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
static uint polygonFlags(QPaintEngine::PolygonDrawMode mode)
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
virtual void drawColorSpans(const QSpan *spans, int count, uint color)
Draws the given color spans with the specified color.
Q_CORE_EXPORT void qWarning(const char *,...)
QGlyphSet * defaultGlyphs()
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...
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert)
Definition: qbrush.cpp:167
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 isBitmapFont() const
static const char * data(const QByteArray &arr)
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 Bigint * diff(Bigint *a, Bigint *b)
void releaseDC(HDC hdc) const
Q_CORE_EXPORT QTextStream & bin(QTextStream &s)
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
void rasterize(QT_FT_Outline *outline, ProcessSpans callback, QSpanData *spanData, QRasterBuffer *rasterBuffer)
void setLength(qreal len)
Sets the length of the line to the given length.
Definition: qline.h:360
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
void setDirty(DirtyFlags df)
Definition: qpaintengine.h:349
void clip(const QVectorPath &path, Qt::ClipOperation op)
virtual void setState(QPainterState *s)
ClassId classId() const
static void qt_ft_outline_cubic_to(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey, void *data)
QImage colorizeBitmap(const QImage &image, const QColor &color)
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
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
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs)=0
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
void initTexture(const QImage *image, int alpha, QTextureData::Type=QTextureData::Plain, const QRect &sourceRect=QRect())
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
DrawHelper qDrawHelper[QImage::NImageFormats]
void(* SrcOverBlendFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, int w, int h, int const_alpha)
QImage::Format prepare(QImage *image)
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs, const QFixedPoint *positions, GlyphFormat format=Format_Render)
#define QT_CATCH(A)
Definition: qglobal.h:1537
bool isUnclipped(const QRect &rect, int penWidth) const
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
void appendSpan(int x, int length, int y, int coverage)
void translate(qreal dx, qreal dy)
Moves the rectangle dx along the x-axis and dy along the y-axis, relative to the current position...
Definition: qrect.h:716
QPointF start() const
Returns the start point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1796
void setX(int x)
Sets the left edge of the rectangle to the given x coordinate.
Definition: qrect.h:282
static bool isAbove(const QPointF *a, const QPointF *b)
QRect toRect() const
Returns a QRect based on the values of this rectangle.
Definition: qrect.h:845
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
bool contains(const QPoint &p, bool proper=false) const
Returns true if the given point is inside or on the edge of the rectangle, otherwise returns false...
Definition: qrect.cpp:1101
bool supportsTransformations(const QFontEngine *fontEngine) const
uint hints() const
QT_FT_SpanFunc black_spans
void fill(const QVectorPath &path, const QBrush &brush)
qreal pixelSize
Definition: qfont_p.h:90
#define None
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
void drawPixmap(const QPointF &p, const QPixmap &pm)
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
QT_FT_Bitmap * target
qreal m31() const
Returns the horizontal translation factor.
Definition: qtransform.h:261
DrawHelper qDrawHelperCallback[QImage::NImageFormats]
QPainter * painter() const
Returns a pointer to the painter currently updating the paint engine.
Definition: qpainter.cpp:9514
CGContextRef getCGContext() const
void setState(QPainterState *s)
#define qt_fixed_to_real(fixed)
Definition: qstroker_p.h:102
Q_CORE_EXPORT QTextStream & center(QTextStream &s)
void drawPoints(const QPoint *points, int num)
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
virtual void drawLines(const QLine *lines, int lineCount)
The default implementation converts the first lineCount lines in lines to a QLineF and calls the floa...
int bytes_per_line
Definition: qimage_p.h:86
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
void updatePen(const QPen &pen)
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
const uint * getBuffer(const QGradient &gradient, int opacity)
void appendSpans(const QSpan *s, int num)
void setPixel(int x, int y, uint index_or_rgb)
Sets the pixel index or color at (x, y) to index_or_rgb.
Definition: qimage.cpp:4311
Q_CORE_EXPORT void qFatal(const char *,...)
#define Q_CHECK_PTR(p)
Definition: qglobal.h:1853
bool isAffine() const
Returns true if the matrix represent an affine transformation, otherwise returns false.
Definition: qtransform.h:200
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
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
void prepare(QCustomRasterPaintDevice *)
const QClipData * clip
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
Qt::BrushStyle style
Definition: qbrush.h:177
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode)
virtual int glyphMargin() const
void rasterizeLine_dashed(QLineF line, qreal width, int *dashIndex, qreal *dashOffset, bool *inDash)
void setGlyphCache(void *key, QFontEngineGlyphCache *data)
void init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
virtual void drawBufferSpan(const uint *buffer, int bufsize, int x, int y, int length, uint const_alpha)
Draws the given buffer.
QRectF controlPointRect() const
Returns the rectangle containing all the points and control points in this path.
static const struct @32 types[]
iterator begin()
Returns an STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:247
The QLinearGradient class is used in combination with QBrush to specify a linear gradient brush...
Definition: qbrush.h:280
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
QRasterBuffer * rasterBuffer
The QGradient class is used in combination with QBrush to specify gradient fills. ...
Definition: qbrush.h:201
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
QFixed subPixelPositionForX(QFixed x)
struct QLinearGradientData::@229 origin
void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
QImage::Format format
Definition: qimage_p.h:85
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
uint clipEnabled
Definition: qpainter_p.h:169
void * data_ptr(const QTransform &t)
Definition: qpainter_p.h:81
qreal miterLimit() const
Returns the miter limit of the pen.
Definition: qpen.cpp:589
#define QT_FT_OUTLINE_NONE
void beginOutline(Qt::FillRule fillRule)
InterpolationMode
Definition: qbrush.h:225
bool populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
void alphaPenBlt(const void *src, int bpl, int depth, int rx, int ry, int w, int h)
#define ctx
Definition: qgl.cpp:6094
Q_GUI_EXPORT bool qt_region_strictContains(const QRegion &region, const QRect &rect)
Returns true if rect is guaranteed to be fully contained in region.
Definition: qregion.cpp:4380
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
virtual void drawStaticTextItem(QStaticTextItem *)
struct QRadialGradientData::@232 focal
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
void fillRect(const QRectF &rect, const QBrush &brush)
Reimplemented Function
const qreal * points() const
FT_Face lockFace(Scaling scale=Scaled) const
qreal m23() const
Returns the vertical projection factor.
Definition: qtransform.h:257
QPainterState * createState(QPainterState *orig) const
void setWidth(int w)
Sets the width of the rectangle to the given width.
Definition: qrect.h:442
QPointF p2() const
Returns the line&#39;s end point.
Definition: qline.h:319
static QReadWriteLock lock
Definition: proxyconf.cpp:399
QPointF brushOrigin
Definition: qpainter_p.h:149
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QFactoryLoader * l
const QClipData * clip() const
const QColor & qbrush_color(const QBrush &b)
Definition: qpainter_p.h:97
Spread spread() const
Returns the spread method use by this gradient.
Definition: qbrush.h:235
uchar * data
Definition: qimage_p.h:81
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
void flushToARGBImage(QImage *image) const
QSizeF size() const
Returns the size of the rectangle.
Definition: qrect.h:713
QGradient::InterpolationMode interpolationMode
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func, const QRect &clip, int alpha, const QRect &sr=QRect())
QRect rect() const
Returns the pixmap&#39;s enclosing rectangle.
Definition: qpixmap.cpp:676
#define MINIMUM_POOL_SIZE
Definition: qgrayraster_p.h:94
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
ProcessSpans getPenFunc(const QRectF &rect, const QSpanData *data) const
QPointF center() const
Returns the center of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2102
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
virtual void * memory() const
Returns a pointer to the paint device&#39;s memory buffer, or 0 if no such buffer exists.
int depth() const
Definition: qpaintdevice.h:103
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
uint * addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity)
static int fast_ceil_positive(const qreal &v)
QT_FT_Raster_BitTest_Func bit_test
virtual QImage * buffer()
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
Definition: qpainter.cpp:9443
QClipData * newClip
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
Q_STATIC_INLINE_FUNCTION int qt_div_255(int x)
qreal dashOffset() const
Returns the dash offset for the pen.
Definition: qpen.cpp:547
QGlyphSet * loadTransformedGlyphSet(const QTransform &matrix)
struct QLinearGradientData::@230 end
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
Reimplemented Function
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
QT_FT_Raster_RenderFunc raster_render
static const QRect toRect_normalized(const QRectF &rect)
bool qt_cleartype_enabled
void prepareBuffer(int w, int h)
uchar * buffer() const
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
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
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
Definition: qtransform.cpp:485
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
void drawTextItem(const QPointF &p, const QTextItem &textItem)
Reimplemented Function
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
void reserve(int size)
Attempts to allocate memory for at least size elements.
Definition: qvector.h:339
QFontEngineGlyphCache * glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const
QPen pen() const
Returns the pen in the current paint engine state.
Definition: qpainter.cpp:9259
virtual void drawRects(const QRect *rects, int rectCount)
The default implementation converts the first rectCount rectangles in the buffer rects to a QRectF an...
struct CGContext * CGContextRef
void(* SrcOverTransformFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, const QRectF &targetRect, const QRectF &sourceRect, const QRect &clipRect, const QTransform &targetRectTransform, int const_alpha)
The QRasterPaintEngine class enables hardware acceleration of painting operations in Qt for Embedded ...
QFontEngineGlyphCache::Type glyphCacheType
qreal m13() const
Returns the horizontal projection factor.
Definition: qtransform.h:245
QRgb rgba() const
Returns the RGB value of the color, including its alpha.
Definition: qcolor.cpp:1019
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
QFontDef fontDef
ProcessSpans unclipped_blend
void stroke(const QVectorPath &path, const QPen &pen)
QScopedPointer< QOutlineMapper > outlineMapper
QT_FT_Raster_ResetFunc raster_reset
The QTextItem class provides all the information required to draw text in a custom paint engine...
Definition: qpaintengine.h:68
QRectF translated(qreal dx, qreal dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:740
bool isValid() const
Returns true if the rectangle is valid, otherwise returns false.
Definition: qrect.h:237
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:658
qreal centerRadius() const
Returns the center radius of this radial gradient in logical coordinates.
Definition: qbrush.cpp:2182
QPointF topRight() const
Returns the position of the rectangle&#39;s top-right corner.
Definition: qrect.h:541
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
static const KeyPair *const end
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
void drawPath(const QVectorPath &path)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
Glyph * loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format=Format_None, bool fetchMetricsOnly=false) const
enum QSpanData::Type type
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QT_FT_Raster_NewFunc raster_new
#define QT_TRY
Definition: qglobal.h:1536
struct QRadialGradientData::@231 center
static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s)
qreal qfixed
Definition: qstroker_p.h:100
QScopedPointer< QRasterizer > rasterizer
#define INT_MAX
QVector< QRgb > colorTable() const
Returns a list of the colors contained in the image&#39;s color table, or an empty list if the image does...
Definition: qimage.cpp:1770
SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats]
QRasterPaintEngine(QPaintDevice *device)
Creates a raster based paint engine for operating on the given device, with the complete set of QPain...
unsigned int glyph_t
void generateGradientColorTable(const QGradient &g, uint *colorTable, int size, int opacity) const
#define enabled
Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric)
static void fillRect_normalized(const QRect &r, QSpanData *data, QRasterPaintEnginePrivate *pe)
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const
virtual void drawEllipse(const QRectF &r)
Reimplement this function to draw the largest ellipse that can be contained within rectangle rect...
QT_FT_Outline * convertPath(const QPainterPath &path)
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
qreal m33() const
Returns the division factor.
Definition: qtransform.h:269
static const QRect toAlignedRect_positive(const QRectF &rect)
#define int_dim(pos, dim)
AlphamapBlitFunc alphamapBlit
int size() const
Qt::ClipOperation operation
QPointF finalStop() const
Returns the final stop point of this linear gradient in logical coordinates.
Definition: qbrush.cpp:1856
void setStyle(Qt::PenStyle)
Sets the pen style to the given style.
Definition: qpen.cpp:450
static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData)
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
#define QT_FT_RASTER_FLAG_AA
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
ClipOperation
Definition: qnamespace.h:1495
virtual void clip(const QVectorPath &path, Qt::ClipOperation op)=0
glyph_t * glyphs
Hint shape() const
QPixmapData * pixmapData() const
Definition: qpixmap.cpp:2277
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
static const qreal Q_PI
Definition: qmath_p.h:61