painting/qpaintengine_raster.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/****************************************************************************-
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/****************************************************************************
2** -
3** Copyright (C) 2013 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 <qbitmap.h> -
55#include <qmath.h> -
56 -
57// #include <private/qdatabuffer_p.h> -
58// #include <private/qpainter_p.h> -
59#include <private/qmath_p.h> -
60#include <private/qtextengine_p.h> -
61#include <private/qfontengine_p.h> -
62#include <private/qpixmap_raster_p.h> -
63// #include <private/qpolygonclipper_p.h> -
64// #include <private/qrasterizer_p.h> -
65#include <private/qimage_p.h> -
66#include <private/qstatictext_p.h> -
67#include <private/qcosmeticstroker_p.h> -
68#include "qmemrotate_p.h" -
69 -
70#include "qpaintengine_raster_p.h" -
71// #include "qbezier_p.h" -
72#include "qoutlinemapper_p.h" -
73 -
74#include <limits.h> -
75 -
76#ifdef Q_OS_WIN -
77# include <qvarlengtharray.h> -
78# include <private/qfontengine_p.h> -
79# include <qt_windows.h> -
80#ifdef Q_OS_WIN64 -
81# include <malloc.h> -
82# endif -
83#endif -
84 -
85QT_BEGIN_NAMESPACE -
86 -
87class QRectVectorPath : public QVectorPath { -
88public: -
89 inline void set(const QRect &r) { -
90 qreal left = r.x(); -
91 qreal right = r.x() + r.width(); -
92 qreal top = r.y(); -
93 qreal bottom = r.y() + r.height(); -
94 pts[0] = left; -
95 pts[1] = top; -
96 pts[2] = right; -
97 pts[3] = top; -
98 pts[4] = right; -
99 pts[5] = bottom; -
100 pts[6] = left; -
101 pts[7] = bottom; -
102 } -
103 -
104 inline void set(const QRectF &r) { -
105 qreal left = r.x(); -
106 qreal right = r.x() + r.width(); -
107 qreal top = r.y(); -
108 qreal bottom = r.y() + r.height(); -
109 pts[0] = left; -
110 pts[1] = top; -
111 pts[2] = right; -
112 pts[3] = top; -
113 pts[4] = right; -
114 pts[5] = bottom; -
115 pts[6] = left; -
116 pts[7] = bottom; -
117 } -
118 inline QRectVectorPath(const QRect &r) -
119 : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose) -
120 { -
121 set(r); -
122 } -
123 inline QRectVectorPath(const QRectF &r) -
124 : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose) -
125 { -
126 set(r); -
127 } -
128 inline QRectVectorPath() -
129 : QVectorPath(pts, 4, 0, QVectorPath::RectangleHint | QVectorPath::ImplicitClose) -
130 { } -
131 -
132 qreal pts[8]; -
133}; -
134 -
135Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp -
136 -
137#define qreal_to_fixed_26_6(f) (int(f * 64)) -
138#define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; } -
139#define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; } -
140 -
141// #define QT_DEBUG_DRAW -
142#ifdef QT_DEBUG_DRAW -
143void dumpClip(int width, int height, const QClipData *clip); -
144#endif -
145 -
146#define QT_FAST_SPANS -
147 -
148 -
149// A little helper macro to get a better approximation of dimensions. -
150// If we have a rect that starting at 0.5 of width 3.5 it should span -
151// 4 pixels. -
152#define int_dim(pos, dim) (int(pos+dim) - int(pos)) -
153 -
154static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; -
155 -
156#ifdef Q_OS_WIN -
157 -
158static inline bool winClearTypeFontsEnabled() -
159{ -
160 UINT result = 0; -
161#if !defined(SPI_GETFONTSMOOTHINGTYPE) // MinGW -
162# define SPI_GETFONTSMOOTHINGTYPE 0x200A -
163# define FE_FONTSMOOTHINGCLEARTYPE 0x002 -
164#endif -
165 SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); -
166 return result == FE_FONTSMOOTHINGCLEARTYPE; -
167} -
168 -
169/*! -
170 \internal -
171 */ -
172bool QRasterPaintEngine::clearTypeFontsEnabled() -
173{ -
174 static const bool result = winClearTypeFontsEnabled(); -
175 return result; -
176} -
177 -
178#endif // Q_OS_WIN -
179 -
180 -
181 -
182/******************************************************************************** -
183 * Span functions -
184 */ -
185static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData); -
186static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData); -
187static void qt_span_clip(int count, const QSpan *spans, void *userData); -
188 -
189struct ClipData -
190{ -
191 QClipData *oldClip; -
192 QClipData *newClip; -
193 Qt::ClipOperation operation; -
194}; -
195 -
196enum LineDrawMode { -
197 LineDrawClipped, -
198 LineDrawNormal, -
199 LineDrawIncludeLastPixel -
200}; -
201 -
202static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip, -
203 ProcessSpans pen_func, ProcessSpans brush_func, -
204 QSpanData *pen_data, QSpanData *brush_data); -
205 -
206struct QRasterFloatPoint { -
207 qreal x; -
208 qreal y; -
209}; -
210 -
211#ifdef QT_DEBUG_DRAW -
212static const QRectF boundingRect(const QPointF *points, int pointCount) -
213{ -
214 const QPointF *e = points; -
215 const QPointF *last = points + pointCount; -
216 qreal minx, maxx, miny, maxy; -
217 minx = maxx = e->x(); -
218 miny = maxy = e->y(); -
219 while (++e < last) { -
220 if (e->x() < minx) -
221 minx = e->x(); -
222 else if (e->x() > maxx) -
223 maxx = e->x(); -
224 if (e->y() < miny) -
225 miny = e->y(); -
226 else if (e->y() > maxy) -
227 maxy = e->y(); -
228 } -
229 return QRectF(QPointF(minx, miny), QPointF(maxx, maxy)); -
230} -
231#endif -
232 -
233template <typename T> static inline bool isRect(const T *pts, int elementCount) { -
234 return (elementCount == 5 // 5-point polygon, check for closed rect -
235 && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point -
236 && pts[0] == pts[6] && pts[2] == pts[4] // x values equal -
237 && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... -
238 && pts[0] < pts[4] && pts[1] < pts[5] -
239 ) || -
240 (elementCount == 4 // 4-point polygon, check for unclosed rect -
241 && pts[0] == pts[6] && pts[2] == pts[4] // x values equal -
242 && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... -
243 && pts[0] < pts[4] && pts[1] < pts[5] -
244 ); -
245} -
246 -
247 -
248static void qt_ft_outline_move_to(qfixed x, qfixed y, void *data) -
249{ -
250 ((QOutlineMapper *) data)->moveTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y))); -
251} -
252 -
253static void qt_ft_outline_line_to(qfixed x, qfixed y, void *data) -
254{ -
255 ((QOutlineMapper *) data)->lineTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y))); -
256} -
257 -
258static void qt_ft_outline_cubic_to(qfixed c1x, qfixed c1y, -
259 qfixed c2x, qfixed c2y, -
260 qfixed ex, qfixed ey, -
261 void *data) -
262{ -
263 ((QOutlineMapper *) data)->curveTo(QPointF(qt_fixed_to_real(c1x), qt_fixed_to_real(c1y)), -
264 QPointF(qt_fixed_to_real(c2x), qt_fixed_to_real(c2y)), -
265 QPointF(qt_fixed_to_real(ex), qt_fixed_to_real(ey))); -
266} -
267 -
268 -
269#if !defined(QT_NO_DEBUG) && 0 -
270static void qt_debug_path(const QPainterPath &path) -
271{ -
272 const char *names[] = { -
273 "MoveTo ", -
274 "LineTo ", -
275 "CurveTo ", -
276 "CurveToData" -
277 }; -
278 -
279 fprintf(stderr,"\nQPainterPath: elementCount=%d\n", path.elementCount()); -
280 for (int i=0; i<path.elementCount(); ++i) { -
281 const QPainterPath::Element &e = path.elementAt(i); -
282 Q_ASSERT(e.type >= 0 && e.type <= QPainterPath::CurveToDataElement); -
283 fprintf(stderr," - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); -
284 } -
285} -
286#endif -
287 -
288QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : -
289 QPaintEngineExPrivate(), -
290 cachedLines(0) -
291{ -
292} -
293 -
294 -
295/*!-
\class QRasterPaintEngine
\preliminary
\ingroup qws
\since 4.2
\brief The QRasterPaintEngine class enables hardware acceleration
of painting operations in Qt for Embedded Linux.
Note that this functionality is only available in
\l{Qt for Embedded Linux}.
In \l{Qt for Embedded Linux}, painting is a pure software
implementation. But starting with Qt 4.2, it is
possible to add an accelerated graphics driver to take advantage
of available hardware resources.
Hardware acceleration is accomplished by creating a custom screen
driver, accelerating the copying from memory to the screen, and
implementing a custom paint engine accelerating the various
painting operations. Then a custom paint device (derived from the
QCustomRasterPaintDevice class) and a custom window surface
(derived from QWSWindowSurface) must be implemented to make
\l{Qt for Embedded Linux} aware of the accelerated driver.
\note The QRasterPaintEngine class does not support 8-bit images.
Instead, they need to be converted to a supported format, such as
QImage::Format_ARGB32_Premultiplied.
See the \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
documentation for details.
\sa QCustomRasterPaintDevice, QPaintEngine
*/*!
296 \class QRasterPaintEngine -
297 \preliminary -
298 \ingroup qws -
299 \inmodule QtGui -
300 \since 4.2 -
301 -
302 \brief The QRasterPaintEngine class enables hardware acceleration -
303 of painting operations in Qt for Embedded Linux. -
304 -
305 Note that this functionality is only available in -
306 \l{Qt for Embedded Linux}. -
307 -
308 In \l{Qt for Embedded Linux}, painting is a pure software -
309 implementation. But starting with Qt 4.2, it is -
310 possible to add an accelerated graphics driver to take advantage -
311 of available hardware resources. -
312 -
313 Hardware acceleration is accomplished by creating a custom screen -
314 driver, accelerating the copying from memory to the screen, and -
315 implementing a custom paint engine accelerating the various -
316 painting operations. Then a custom paint device (derived from the -
317 QCustomRasterPaintDevice class) and a custom window surface -
318 (derived from QWSWindowSurface) must be implemented to make -
319 \l{Qt for Embedded Linux} aware of the accelerated driver. -
320 -
321 \note The QRasterPaintEngine class does not support 8-bit images. -
322 Instead, they need to be converted to a supported format, such as -
323 QImage::Format_ARGB32_Premultiplied. -
324 -
325 See the \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux} -
326 documentation for details. -
327 -
328 \sa QCustomRasterPaintDevice, QPaintEngine -
329*/ -
330 -
331/*! -
332 \fn Type QRasterPaintEngine::type() const -
333 \reimp -
334*/ -
335 -
336/*! -
337 \typedef QSpan -
338 \relates QRasterPaintEngine -
339 -
340 A struct equivalent to QT_FT_Span, containing a position (x, -
341 y), the span's length in pixels and its color/coverage (a value -
342 ranging from 0 to 255). -
343*/ -
344 -
345/*! -
346 \since 4.5 -
347 -
348 Creates a raster based paint engine for operating on the given -
349 \a device, with the complete set of \l -
350 {QPaintEngine::PaintEngineFeature}{paint engine features and -
351 capabilities}. -
352*/ -
353QRasterPaintEngine::QRasterPaintEngine(QPaintDevice *device) -
354 : QPaintEngineEx(*(new QRasterPaintEnginePrivate)) -
355{ -
356 d_func()->device = device; -
357 init(); -
358} -
359 -
360/*! -
361 \internal -
362*/ -
363QRasterPaintEngine::QRasterPaintEngine(QRasterPaintEnginePrivate &dd, QPaintDevice *device) -
364 : QPaintEngineEx(dd) -
365{ -
366 d_func()->device = device; -
367 init(); -
368} -
369 -
370void QRasterPaintEngine::init() -
371{ -
372 Q_D(QRasterPaintEngine); -
373 -
374 -
375#ifdef Q_OS_WIN -
376 d->hdc = 0; -
377#endif -
378 -
379 // The antialiasing raster. -
380 d->grayRaster.reset(new QT_FT_Raster); -
381 Q_CHECK_PTR(d->grayRaster.data()); -
382 if (qt_ft_grays_raster.raster_new(d->grayRaster.data())) -
383 QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc -
384 -
385 -
386 d->rasterizer.reset(new QRasterizer); -
387 d->rasterBuffer.reset(new QRasterBuffer()); -
388 d->outlineMapper.reset(new QOutlineMapper); -
389 d->outlinemapper_xform_dirty = true; -
390 -
391 d->basicStroker.setMoveToHook(qt_ft_outline_move_to); -
392 d->basicStroker.setLineToHook(qt_ft_outline_line_to); -
393 d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to); -
394 -
395 d->baseClip.reset(new QClipData(d->device->height())); -
396 d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height())); -
397 -
398 d->image_filler.init(d->rasterBuffer.data(), this); -
399 d->image_filler.type = QSpanData::Texture; -
400 -
401 d->image_filler_xform.init(d->rasterBuffer.data(), this); -
402 d->image_filler_xform.type = QSpanData::Texture; -
403 -
404 d->solid_color_filler.init(d->rasterBuffer.data(), this); -
405 d->solid_color_filler.type = QSpanData::Solid; -
406 -
407 d->deviceDepth = d->device->depth(); -
408 -
409 d->mono_surface = false; -
410 gccaps &= ~PorterDuff; -
411 -
412 QImage::Format format = QImage::Format_Invalid; -
413 -
414 switch (d->device->devType()) { -
415 case QInternal::Pixmap: -
416 qWarning("QRasterPaintEngine: unsupported for pixmaps..."); -
417 break; -
418 case QInternal::Image: -
419 format = d->rasterBuffer->prepare(static_cast<QImage *>(d->device)); -
420 break; -
421 default: -
422 qWarning("QRasterPaintEngine: unsupported target device %d\n", d->device->devType()); -
423 d->device = 0; -
424 return; -
425 } -
426 -
427 switch (format) { -
428 case QImage::Format_MonoLSB: -
429 case QImage::Format_Mono: -
430 d->mono_surface = true; -
431 break; -
432 case QImage::Format_ARGB8565_Premultiplied: -
433 case QImage::Format_ARGB8555_Premultiplied: -
434 case QImage::Format_ARGB6666_Premultiplied: -
435 case QImage::Format_ARGB4444_Premultiplied: -
436 case QImage::Format_ARGB32_Premultiplied: -
437 case QImage::Format_ARGB32: -
438 gccaps |= PorterDuff; -
439 break; -
440 case QImage::Format_RGB32: -
441 case QImage::Format_RGB444: -
442 case QImage::Format_RGB555: -
443 case QImage::Format_RGB666: -
444 case QImage::Format_RGB888: -
445 case QImage::Format_RGB16: -
446 break; -
447 default: -
448 break; -
449 } -
450} -
451 -
452 -
453 -
454 -
455/*! -
456 Destroys this paint engine. -
457*/ -
458QRasterPaintEngine::~QRasterPaintEngine() -
459{ -
460 Q_D(QRasterPaintEngine); -
461 -
462 qt_ft_grays_raster.raster_done(*d->grayRaster.data()); -
463} -
464 -
465/*! -
466 \reimp -
467*/ -
468bool QRasterPaintEngine::begin(QPaintDevice *device) -
469{ -
470 Q_D(QRasterPaintEngine); -
471 -
472 if (device->devType() == QInternal::Pixmap) { -
473 QPixmap *pixmap = static_cast<QPixmap *>(device); -
474 QPlatformPixmap *pd = pixmap->handle(); -
475 if (pd->classId() == QPlatformPixmap::RasterClass || pd->classId() == QPlatformPixmap::BlitterClass) -
476 d->device = pd->buffer(); -
477 } else { -
478 d->device = device; -
479 } -
480 -
481 // Make sure QPaintEngine::paintDevice() returns the proper device. -
482 d->pdev = d->device; -
483 -
484 Q_ASSERT(d->device->devType() == QInternal::Image -
485 || d->device->devType() == QInternal::CustomRaster); -
486 -
487 d->systemStateChanged(); -
488 -
489 QRasterPaintEngineState *s = state(); -
490 ensureOutlineMapper(); -
491 d->outlineMapper->m_clip_rect = d->deviceRect; -
492 -
493 if (d->outlineMapper->m_clip_rect.width() > QT_RASTER_COORD_LIMIT) -
494 d->outlineMapper->m_clip_rect.setWidth(QT_RASTER_COORD_LIMIT); -
495 if (d->outlineMapper->m_clip_rect.height() > QT_RASTER_COORD_LIMIT) -
496 d->outlineMapper->m_clip_rect.setHeight(QT_RASTER_COORD_LIMIT); -
497 -
498 d->rasterizer->setClipRect(d->deviceRect); -
499 -
500 s->penData.init(d->rasterBuffer.data(), this); -
501 s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode); -
502 s->stroker = &d->basicStroker; -
503 d->basicStroker.setClipRect(d->deviceRect); -
504 -
505 s->brushData.init(d->rasterBuffer.data(), this); -
506 s->brushData.setup(s->brush, s->intOpacity, s->composition_mode); -
507 -
508 d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver; -
509 -
510 setDirty(DirtyBrushOrigin); -
511 -
512#ifdef QT_DEBUG_DRAW -
513 qDebug() << "QRasterPaintEngine::begin(" << (void *) device -
514 << ") devType:" << device->devType() -
515 << "devRect:" << d->deviceRect; -
516 if (d->baseClip) { -
517 dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip); -
518 } -
519#endif -
520 -
521 if (d->mono_surface) -
522 d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono; -
523#if defined(Q_OS_WIN) -
524 else if (clearTypeFontsEnabled()) -
525#else -
526 else if (false) -
527#endif -
528 { -
529 QImage::Format format = static_cast<QImage *>(d->device)->format(); -
530 if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32) -
531 d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; -
532 else -
533 d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; -
534 } else -
535 d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; -
536 -
537 setActive(true); -
538 return true; -
539} -
540 -
541/*! -
542 \reimp -
543*/ -
544bool QRasterPaintEngine::end() -
545{ -
546#ifdef QT_DEBUG_DRAW -
547 Q_D(QRasterPaintEngine); -
548 qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect; -
549 if (d->baseClip) { -
550 dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip); -
551 } -
552#endif -
553 -
554 return true; -
555} -
556 -
557/*! -
558 \internal -
559*/ -
560void QRasterPaintEngine::releaseBuffer() -
561{ -
562 Q_D(QRasterPaintEngine); -
563 d->rasterBuffer.reset(new QRasterBuffer); -
564} -
565 -
566/*! -
567 \internal -
568*/ -
569QSize QRasterPaintEngine::size() const -
570{ -
571 Q_D(const QRasterPaintEngine); -
572 return QSize(d->rasterBuffer->width(), d->rasterBuffer->height()); -
573} -
574 -
575/*! -
576 \internal -
577*/ -
578#ifndef QT_NO_DEBUG -
579void QRasterPaintEngine::saveBuffer(const QString &s) const -
580{ -
581 Q_D(const QRasterPaintEngine); -
582 d->rasterBuffer->bufferImage().save(s, "PNG"); -
583} -
584#endif -
585 -
586/*! -
587 \internal -
588*/ -
589void QRasterPaintEngine::updateMatrix(const QTransform &matrix) -
590{ -
591 QRasterPaintEngineState *s = state(); -
592 // FALCON: get rid of this line, see drawImage call below. -
593 s->matrix = matrix; -
594 QTransform::TransformationType txop = s->matrix.type(); -
595 -
596 switch (txop) { -
597 -
598 case QTransform::TxNone: -
599 s->flags.int_xform = true; -
600 break; -
601 -
602 case QTransform::TxTranslate: -
603 s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx() -
604 && qreal(int(s->matrix.dy())) == s->matrix.dy(); -
605 break; -
606 -
607 case QTransform::TxScale: -
608 s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx() -
609 && qreal(int(s->matrix.dy())) == s->matrix.dy() -
610 && qreal(int(s->matrix.m11())) == s->matrix.m11() -
611 && qreal(int(s->matrix.m22())) == s->matrix.m22(); -
612 break; -
613 -
614 default: // shear / perspective... -
615 s->flags.int_xform = false; -
616 break; -
617 } -
618 -
619 s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale); -
620 -
621 ensureOutlineMapper(); -
622} -
623 -
624 -
625 -
626QRasterPaintEngineState::~QRasterPaintEngineState() -
627{ -
628 if (flags.has_clip_ownership) -
629 delete clip; -
630} -
631 -
632 -
633QRasterPaintEngineState::QRasterPaintEngineState() -
634{ -
635 stroker = 0; -
636 -
637 fillFlags = 0; -
638 strokeFlags = 0; -
639 pixmapFlags = 0; -
640 -
641 intOpacity = 256; -
642 -
643 txscale = 1.; -
644 -
645 flags.fast_pen = true; -
646 flags.antialiased = false; -
647 flags.bilinear = false; -
648 flags.legacy_rounding = false; -
649 flags.fast_text = true; -
650 flags.int_xform = true; -
651 flags.tx_noshear = true; -
652 flags.fast_images = true; -
653 -
654 clip = 0; -
655 flags.has_clip_ownership = false; -
656 -
657 dirty = 0; -
658} -
659 -
660QRasterPaintEngineState::QRasterPaintEngineState(QRasterPaintEngineState &s) -
661 : QPainterState(s) -
662 , lastPen(s.lastPen) -
663 , penData(s.penData) -
664 , stroker(s.stroker) -
665 , strokeFlags(s.strokeFlags) -
666 , lastBrush(s.lastBrush) -
667 , brushData(s.brushData) -
668 , fillFlags(s.fillFlags) -
669 , pixmapFlags(s.pixmapFlags) -
670 , intOpacity(s.intOpacity) -
671 , txscale(s.txscale) -
672 , clip(s.clip) -
673 , dirty(s.dirty) -
674 , flag_bits(s.flag_bits) -
675{ -
676 brushData.tempImage = 0; -
677 penData.tempImage = 0; -
678 flags.has_clip_ownership = false; -
679} -
680 -
681/*! -
682 \internal -
683*/ -
684QPainterState *QRasterPaintEngine::createState(QPainterState *orig) const -
685{ -
686 QRasterPaintEngineState *s; -
687 if (!orig) -
688 s = new QRasterPaintEngineState(); -
689 else -
690 s = new QRasterPaintEngineState(*static_cast<QRasterPaintEngineState *>(orig)); -
691 -
692 return s; -
693} -
694 -
695/*! -
696 \internal -
697*/ -
698void QRasterPaintEngine::setState(QPainterState *s) -
699{ -
700 Q_D(QRasterPaintEngine); -
701 QPaintEngineEx::setState(s); -
702 d->rasterBuffer->compositionMode = s->composition_mode; -
703} -
704 -
705/*! -
706 \fn QRasterPaintEngineState *QRasterPaintEngine::state() -
707 \internal -
708*/ -
709 -
710/*! -
711 \fn const QRasterPaintEngineState *QRasterPaintEngine::state() const -
712 \internal -
713*/ -
714 -
715/*! -
716 \internal -
717*/ -
718void QRasterPaintEngine::penChanged() -
719{ -
720#ifdef QT_DEBUG_DRAW -
721 qDebug() << "QRasterPaintEngine::penChanged():" << state()->pen; -
722#endif -
723 QRasterPaintEngineState *s = state(); -
724 s->strokeFlags |= DirtyPen; -
725 s->dirty |= DirtyPen; -
726} -
727 -
728/*! -
729 \internal -
730*/ -
731void QRasterPaintEngine::updatePen(const QPen &pen) -
732{ -
733 Q_D(QRasterPaintEngine); -
734 QRasterPaintEngineState *s = state(); -
735#ifdef QT_DEBUG_DRAW -
736 qDebug() << "QRasterPaintEngine::updatePen():" << s->pen; -
737#endif -
738 -
739 Qt::PenStyle pen_style = qpen_style(pen); -
740 -
741 s->lastPen = pen; -
742 s->strokeFlags = 0; -
743 -
744 s->penData.clip = d->clip(); -
745 s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode); -
746 -
747 if (s->strokeFlags & QRasterPaintEngine::DirtyTransform -
748 || pen.brush().transform().type() >= QTransform::TxNone) { -
749 d->updateMatrixData(&s->penData, pen.brush(), s->matrix); -
750 } -
751 -
752 // Slightly ugly handling of an uncommon case... We need to change -
753 // the pen because it is reused in draw_midpoint to decide dashed -
754 // or non-dashed. -
755 if (pen_style == Qt::CustomDashLine && pen.dashPattern().size() == 0) { -
756 pen_style = Qt::SolidLine; -
757 s->lastPen.setStyle(Qt::SolidLine); -
758 } -
759 -
760 d->basicStroker.setJoinStyle(qpen_joinStyle(pen)); -
761 d->basicStroker.setCapStyle(qpen_capStyle(pen)); -
762 d->basicStroker.setMiterLimit(pen.miterLimit()); -
763 -
764 qreal penWidth = qpen_widthf(pen); -
765 if (penWidth == 0) -
766 d->basicStroker.setStrokeWidth(1); -
767 else -
768 d->basicStroker.setStrokeWidth(penWidth); -
769 -
770 if(pen_style == Qt::SolidLine) { -
771 s->stroker = &d->basicStroker; -
772 } else if (pen_style != Qt::NoPen) { -
773 if (!d->dashStroker) -
774 d->dashStroker.reset(new QDashStroker(&d->basicStroker)); -
775 if (qt_pen_is_cosmetic(pen, s->renderHints)) { -
776 d->dashStroker->setClipRect(d->deviceRect); -
777 } else { -
778 // ### I've seen this inverted devrect multiple places now... -
779 QRectF clipRect = s->matrix.inverted().mapRect(QRectF(d->deviceRect)); -
780 d->dashStroker->setClipRect(clipRect); -
781 } -
782 d->dashStroker->setDashPattern(pen.dashPattern()); -
783 d->dashStroker->setDashOffset(pen.dashOffset()); -
784 s->stroker = d->dashStroker.data(); -
785 } else { -
786 s->stroker = 0; -
787 } -
788 -
789 ensureRasterState(); // needed because of tx_noshear... -
790 bool cosmetic = qt_pen_is_cosmetic(pen, s->renderHints); -
791 s->flags.fast_pen = pen_style > Qt::NoPen -
792 && s->penData.blend -
793 && ((cosmetic && penWidth <= 1) -
794 || (!cosmetic && s->flags.tx_noshear && penWidth * s->txscale <= 1)); -
795 -
796 s->flags.non_complex_pen = qpen_capStyle(s->lastPen) <= Qt::SquareCap && s->flags.tx_noshear; -
797 -
798 s->strokeFlags = 0; -
799} -
800 -
801 -
802 -
803/*! -
804 \internal -
805*/ -
806void QRasterPaintEngine::brushOriginChanged() -
807{ -
808 QRasterPaintEngineState *s = state(); -
809#ifdef QT_DEBUG_DRAW -
810 qDebug() << "QRasterPaintEngine::brushOriginChanged()" << s->brushOrigin; -
811#endif -
812 -
813 s->fillFlags |= DirtyBrushOrigin; -
814} -
815 -
816 -
817/*! -
818 \internal -
819*/ -
820void QRasterPaintEngine::brushChanged() -
821{ -
822 QRasterPaintEngineState *s = state(); -
823#ifdef QT_DEBUG_DRAW -
824 qDebug() << "QRasterPaintEngine::brushChanged():" << s->brush; -
825#endif -
826 s->fillFlags |= DirtyBrush; -
827} -
828 -
829 -
830 -
831 -
832/*! -
833 \internal -
834*/ -
835void QRasterPaintEngine::updateBrush(const QBrush &brush) -
836{ -
837#ifdef QT_DEBUG_DRAW -
838 qDebug() << "QRasterPaintEngine::updateBrush()" << brush; -
839#endif -
840 Q_D(QRasterPaintEngine); -
841 QRasterPaintEngineState *s = state(); -
842 // must set clip prior to setup, as setup uses it... -
843 s->brushData.clip = d->clip(); -
844 s->brushData.setup(brush, s->intOpacity, s->composition_mode); -
845 if (s->fillFlags & DirtyTransform -
846 || brush.transform().type() >= QTransform::TxNone) -
847 d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix()); -
848 s->lastBrush = brush; -
849 s->fillFlags = 0; -
850} -
851 -
852void QRasterPaintEngine::updateOutlineMapper() -
853{ -
854 Q_D(QRasterPaintEngine); -
855 d->outlineMapper->setMatrix(state()->matrix); -
856} -
857 -
858void QRasterPaintEngine::updateRasterState() -
859{ -
860 QRasterPaintEngineState *s = state(); -
861 -
862 if (s->dirty & DirtyTransform) -
863 updateMatrix(s->matrix); -
864 -
865 if (s->dirty & (DirtyPen|DirtyCompositionMode|DirtyOpacity)) { -
866 const QPainter::CompositionMode mode = s->composition_mode; -
867 s->flags.fast_text = (s->penData.type == QSpanData::Solid) -
868 && s->intOpacity == 256 -
869 && (mode == QPainter::CompositionMode_Source -
870 || (mode == QPainter::CompositionMode_SourceOver -
871 && qAlpha(s->penData.solid.color) == 255)); -
872 } -
873 -
874 s->dirty = 0; -
875} -
876 -
877 -
878/*! -
879 \internal -
880*/ -
881void QRasterPaintEngine::opacityChanged() -
882{ -
883 QRasterPaintEngineState *s = state(); -
884 -
885#ifdef QT_DEBUG_DRAW -
886 qDebug() << "QRasterPaintEngine::opacityChanged()" << s->opacity; -
887#endif -
888 -
889 s->fillFlags |= DirtyOpacity; -
890 s->strokeFlags |= DirtyOpacity; -
891 s->pixmapFlags |= DirtyOpacity; -
892 s->dirty |= DirtyOpacity; -
893 s->intOpacity = (int) (s->opacity * 256); -
894} -
895 -
896/*! -
897 \internal -
898*/ -
899void QRasterPaintEngine::compositionModeChanged() -
900{ -
901 Q_D(QRasterPaintEngine); -
902 QRasterPaintEngineState *s = state(); -
903 -
904#ifdef QT_DEBUG_DRAW -
905 qDebug() << "QRasterPaintEngine::compositionModeChanged()" << s->composition_mode; -
906#endif -
907 -
908 s->fillFlags |= DirtyCompositionMode; -
909 s->dirty |= DirtyCompositionMode; -
910 -
911 s->strokeFlags |= DirtyCompositionMode; -
912 d->rasterBuffer->compositionMode = s->composition_mode; -
913 -
914 d->recalculateFastImages(); -
915} -
916 -
917/*! -
918 \internal -
919*/ -
920void QRasterPaintEngine::renderHintsChanged() -
921{ -
922 QRasterPaintEngineState *s = state(); -
923 -
924#ifdef QT_DEBUG_DRAW -
925 qDebug() << "QRasterPaintEngine::renderHintsChanged()" << hex << s->renderHints; -
926#endif -
927 -
928 bool was_aa = s->flags.antialiased; -
929 bool was_bilinear = s->flags.bilinear; -
930 -
931 s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing); -
932 s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform); -
933 s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting); -
934 -
935 if (was_aa != s->flags.antialiased) -
936 s->strokeFlags |= DirtyHints; -
937 -
938 if (was_bilinear != s->flags.bilinear) { -
939 s->strokeFlags |= DirtyPen; -
940 s->fillFlags |= DirtyBrush; -
941 } -
942 -
943 Q_D(QRasterPaintEngine); -
944 d->recalculateFastImages(); -
945} -
946 -
947/*! -
948 \internal -
949*/ -
950void QRasterPaintEngine::transformChanged() -
951{ -
952 QRasterPaintEngineState *s = state(); -
953 -
954#ifdef QT_DEBUG_DRAW -
955 qDebug() << "QRasterPaintEngine::transformChanged()" << s->matrix; -
956#endif -
957 -
958 s->fillFlags |= DirtyTransform; -
959 s->strokeFlags |= DirtyTransform; -
960 -
961 s->dirty |= DirtyTransform; -
962 -
963 Q_D(QRasterPaintEngine); -
964 d->recalculateFastImages(); -
965} -
966 -
967/*! -
968 \internal -
969*/ -
970void QRasterPaintEngine::clipEnabledChanged() -
971{ -
972 QRasterPaintEngineState *s = state(); -
973 -
974#ifdef QT_DEBUG_DRAW -
975 qDebug() << "QRasterPaintEngine::clipEnabledChanged()" << s->clipEnabled; -
976#endif -
977 -
978 if (s->clip) { -
979 s->clip->enabled = s->clipEnabled; -
980 s->fillFlags |= DirtyClipEnabled; -
981 s->strokeFlags |= DirtyClipEnabled; -
982 s->pixmapFlags |= DirtyClipEnabled; -
983 } -
984} -
985 -
986void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, -
987 const QImage &img, -
988 SrcOverBlendFunc func, -
989 const QRect &clip, -
990 int alpha, -
991 const QRect &sr) -
992{ -
993 if (alpha == 0 || !clip.isValid()) -
994 return; -
995 -
996 Q_ASSERT(img.depth() >= 8); -
997 -
998 int srcBPL = img.bytesPerLine(); -
999 const uchar *srcBits = img.bits(); -
1000 int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit.. -
1001 int iw = img.width(); -
1002 int ih = img.height(); -
1003 -
1004 if (!sr.isEmpty()) { -
1005 iw = sr.width(); -
1006 ih = sr.height(); -
1007 // Adjust the image according to the source offset... -
1008 srcBits += ((sr.y() * srcBPL) + sr.x() * srcSize); -
1009 } -
1010 -
1011 // adapt the x parameters -
1012 int x = qRound(pt.x()); -
1013 int cx1 = clip.x(); -
1014 int cx2 = clip.x() + clip.width(); -
1015 if (x < cx1) { -
1016 int d = cx1 - x; -
1017 srcBits += srcSize * d; -
1018 iw -= d; -
1019 x = cx1; -
1020 } -
1021 if (x + iw > cx2) { -
1022 int d = x + iw - cx2; -
1023 iw -= d; -
1024 } -
1025 if (iw <= 0) -
1026 return; -
1027 -
1028 // adapt the y paremeters... -
1029 int cy1 = clip.y(); -
1030 int cy2 = clip.y() + clip.height(); -
1031 int y = qRound(pt.y()); -
1032 if (y < cy1) { -
1033 int d = cy1 - y; -
1034 srcBits += srcBPL * d; -
1035 ih -= d; -
1036 y = cy1; -
1037 } -
1038 if (y + ih > cy2) { -
1039 int d = y + ih - cy2; -
1040 ih -= d; -
1041 } -
1042 if (ih <= 0) -
1043 return; -
1044 -
1045 // call the blend function... -
1046 int dstSize = rasterBuffer->bytesPerPixel(); -
1047 int dstBPL = rasterBuffer->bytesPerLine(); -
1048 func(rasterBuffer->buffer() + x * dstSize + y * dstBPL, dstBPL, -
1049 srcBits, srcBPL, -
1050 iw, ih, -
1051 alpha); -
1052} -
1053 -
1054 -
1055void QRasterPaintEnginePrivate::systemStateChanged() -
1056{ -
1057 deviceRectUnclipped = QRectclipRect(0, 0,
executed (the execution status of this line is deduced): deviceRectUnclipped = QRect(0, 0,
-
1058 qMin(QT_RASTER_COORD_LIMIT, device->width()),
executed (the execution status of this line is deduced): qMin(QT_RASTER_COORD_LIMIT, device->width()),
-
1059 qMin(QT_RASTER_COORD_LIMIT, device->height()));
executed (the execution status of this line is deduced): qMin(QT_RASTER_COORD_LIMIT, device->height()));
-
1060 -
1061 if (!systemClip.isEmpty()) {
evaluated: !systemClip.isEmpty()
TRUEFALSE
yes
Evaluation Count:14829
yes
Evaluation Count:13971
13971-14829
1062 QRegion clippedDeviceRgn = systemClip & clipRectdeviceRectUnclipped;
executed (the execution status of this line is deduced): QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
-
1063 deviceRect = clippedDeviceRgn.boundingRect();
executed (the execution status of this line is deduced): deviceRect = clippedDeviceRgn.boundingRect();
-
1064 baseClip->setClipRegion(clippedDeviceRgn);
executed (the execution status of this line is deduced): baseClip->setClipRegion(clippedDeviceRgn);
-
1065 } else {
executed: }
Execution Count:14829
14829
1066 deviceRect = clipRectdeviceRectUnclipped;
executed (the execution status of this line is deduced): deviceRect = deviceRectUnclipped;
-
1067 baseClip->setClipRect(deviceRect);
executed (the execution status of this line is deduced): baseClip->setClipRect(deviceRect);
-
1068 }
executed: }
Execution Count:13971
13971
1069#ifdef QT_DEBUG_DRAW -
1070 qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRectdeviceRectUnclipped << systemClip; -
1071#endif -
1072 -
1073 exDeviceRect = deviceRect;
executed (the execution status of this line is deduced): exDeviceRect = deviceRect;
-
1074 -
1075 Q_Q(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEngine * const q = q_func();
-
1076 if (q->state()) {
partially evaluated: q->state()
TRUEFALSE
yes
Evaluation Count:28800
no
Evaluation Count:0
0-28800
1077 q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
executed (the execution status of this line is deduced): q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
-
1078 q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
executed (the execution status of this line is deduced): q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
-
1079 q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
executed (the execution status of this line is deduced): q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
-
1080 }
executed: }
Execution Count:28800
28800
1081}
executed: }
Execution Count:28800
28800
1082 -
1083void QRasterPaintEnginePrivate::updateMatrixData(QSpanData *spanData, const QBrush &b, const QTransform &m) -
1084{ -
1085 if (b.d->style == Qt::NoBrush || b.d->style == Qt::SolidPattern) -
1086 return; -
1087 -
1088 Q_Q(QRasterPaintEngine); -
1089 bool bilinear = q->state()->flags.bilinear; -
1090 -
1091 if (b.d->transform.type() > QTransform::TxNone) { // FALCON: optimize -
1092 spanData->setupMatrix(b.transform() * m, bilinear); -
1093 } else { -
1094 if (m.type() <= QTransform::TxTranslate) { -
1095 // specialize setupMatrix for translation matrices -
1096 // to avoid needless matrix inversion -
1097 spanData->m11 = 1; -
1098 spanData->m12 = 0; -
1099 spanData->m13 = 0; -
1100 spanData->m21 = 0; -
1101 spanData->m22 = 1; -
1102 spanData->m23 = 0; -
1103 spanData->m33 = 1; -
1104 spanData->dx = -m.dx(); -
1105 spanData->dy = -m.dy(); -
1106 spanData->txop = m.type(); -
1107 spanData->bilinear = bilinear; -
1108 spanData->fast_matrix = qAbs(m.dx()) < 1e4 && qAbs(m.dy()) < 1e4; -
1109 spanData->adjustSpanMethods(); -
1110 } else { -
1111 spanData->setupMatrix(m, bilinear); -
1112 } -
1113 } -
1114} -
1115 -
1116// #define QT_CLIPPING_RATIOS -
1117 -
1118#ifdef QT_CLIPPING_RATIOS -
1119int rectClips; -
1120int regionClips; -
1121int totalClips; -
1122 -
1123static void checkClipRatios(QRasterPaintEnginePrivate *d) -
1124{ -
1125 if (d->clip()->hasRectClip) -
1126 rectClips++; -
1127 if (d->clip()->hasRegionClip) -
1128 regionClips++; -
1129 totalClips++; -
1130 -
1131 if ((totalClips % 5000) == 0) { -
1132 printf("Clipping ratio: rectangular=%f%%, region=%f%%, complex=%f%%\n", -
1133 rectClips * 100.0 / (qreal) totalClips, -
1134 regionClips * 100.0 / (qreal) totalClips, -
1135 (totalClips - rectClips - regionClips) * 100.0 / (qreal) totalClips); -
1136 totalClips = 0; -
1137 rectClips = 0; -
1138 regionClips = 0; -
1139 } -
1140 -
1141} -
1142#endif -
1143 -
1144static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s) -
1145{ -
1146 if (s->flags.has_clip_ownership) -
1147 delete s->clip; -
1148 s->clip = 0; -
1149 s->flags.has_clip_ownership = false; -
1150} -
1151 -
1152static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s) -
1153{ -
1154 s->fillFlags |= QPaintEngine::DirtyClipPath; -
1155 s->strokeFlags |= QPaintEngine::DirtyClipPath; -
1156 s->pixmapFlags |= QPaintEngine::DirtyClipPath; -
1157 -
1158 d->solid_color_filler.clip = d->clip(); -
1159 d->solid_color_filler.adjustSpanMethods(); -
1160 -
1161#ifdef QT_DEBUG_DRAW -
1162 dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->clip()); -
1163#endif -
1164 -
1165} -
1166 -
1167 -
1168/*! -
1169 \internal -
1170*/ -
1171void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) -
1172{ -
1173#ifdef QT_DEBUG_DRAW -
1174 qDebug() << "QRasterPaintEngine::clip(): " << path << op; -
1175 -
1176 if (path.elements()) { -
1177 for (int i=0; i<path.elementCount(); ++i) { -
1178 qDebug() << " - " << path.elements()[i] -
1179 << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; -
1180 } -
1181 } else { -
1182 for (int i=0; i<path.elementCount(); ++i) { -
1183 qDebug() << " ---- " -
1184 << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; -
1185 } -
1186 } -
1187#endif -
1188 -
1189 Q_D(QRasterPaintEngine); -
1190 QRasterPaintEngineState *s = state(); -
1191 -
1192 const qreal *points = path.points(); -
1193 const QPainterPath::ElementType *types = path.elements(); -
1194 -
1195 // There are some cases that are not supported by clip(QRect) -
1196 if (op != Qt::IntersectClip || !s->clip || s->clip->hasRectClip || s->clip->hasRegionClip) { -
1197 if (s->matrix.type() <= QTransform::TxScale -
1198 && ((path.shape() == QVectorPath::RectangleHint) -
1199 || (isRect(points, path.elementCount()) -
1200 && (!types || (types[0] == QPainterPath::MoveToElement -
1201 && types[1] == QPainterPath::LineToElement -
1202 && types[2] == QPainterPath::LineToElement -
1203 && types[3] == QPainterPath::LineToElement))))) { -
1204#ifdef QT_DEBUG_DRAW -
1205 qDebug() << " --- optimizing vector clip to rect clip..."; -
1206#endif -
1207 -
1208 QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]); -
1209 if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op)) -
1210 return; -
1211 } -
1212 } -
1213 -
1214 if (op == Qt::NoClip) { -
1215 qrasterpaintengine_state_setNoClip(s); -
1216 -
1217 } else { -
1218 QClipData *base = d->baseClip.data(); -
1219 -
1220 // Intersect with current clip when available... -
1221 if (op == Qt::IntersectClip && s->clip) -
1222 base = s->clip; -
1223 -
1224 // We always intersect, except when there is nothing to -
1225 // intersect with, in which case we simplify the operation to -
1226 // a replace... -
1227 Qt::ClipOperation isectOp = Qt::IntersectClip; -
1228 if (base == 0) -
1229 isectOp = Qt::ReplaceClip; -
1230 -
1231 QClipData *newClip = new QClipData(d->rasterBuffer->height()); -
1232 newClip->initialize(); -
1233 ClipData clipData = { base, newClip, isectOp }; -
1234 ensureOutlineMapper(); -
1235 d->rasterize(d->outlineMapper->convertPath(path), qt_span_clip, &clipData, 0); -
1236 -
1237 newClip->fixup(); -
1238 -
1239 if (s->flags.has_clip_ownership) -
1240 delete s->clip; -
1241 -
1242 s->clip = newClip; -
1243 s->flags.has_clip_ownership = true; -
1244 } -
1245 qrasterpaintengine_dirty_clip(d, s); -
1246} -
1247 -
1248 -
1249 -
1250/*! -
1251 \internal -
1252*/ -
1253void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) -
1254{ -
1255#ifdef QT_DEBUG_DRAW -
1256 qDebug() << "QRasterPaintEngine::clip(): " << rect << op; -
1257#endif -
1258 -
1259 QRasterPaintEngineState *s = state(); -
1260 -
1261 if (op == Qt::NoClip) { -
1262 qrasterpaintengine_state_setNoClip(s); -
1263 -
1264 } else if (s->matrix.type() > QTransform::TxScale) { -
1265 QPaintEngineEx::clip(rect, op); -
1266 return; -
1267 -
1268 } else if (!setClipRectInDeviceCoords(s->matrix.mapRect(rect), op)) { -
1269 QPaintEngineEx::clip(rect, op); -
1270 return; -
1271 } -
1272} -
1273 -
1274 -
1275bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op) -
1276{ -
1277 Q_D(QRasterPaintEngine); -
1278 QRect clipRect = r & d->deviceRect; -
1279 QRasterPaintEngineState *s = state(); -
1280 -
1281 if (op == Qt::ReplaceClip || s->clip == 0) { -
1282 -
1283 // No current clip, hence we intersect with sysclip and be -
1284 // done with it... -
1285 QRegion clipRegion = systemClip(); -
1286 QClipData *clip = new QClipData(d->rasterBuffer->height()); -
1287 -
1288 if (clipRegion.isEmpty()) -
1289 clip->setClipRect(clipRect); -
1290 else -
1291 clip->setClipRegion(clipRegion & clipRect); -
1292 -
1293 if (s->flags.has_clip_ownership) -
1294 delete s->clip; -
1295 -
1296 s->clip = clip; -
1297 s->clip->enabled = true; -
1298 s->flags.has_clip_ownership = true; -
1299 -
1300 } else if (op == Qt::IntersectClip){ // intersect clip with current clip -
1301 QClipData *base = s->clip; -
1302 -
1303 Q_ASSERT(base); -
1304 if (base->hasRectClip || base->hasRegionClip) { -
1305 if (!s->flags.has_clip_ownership) { -
1306 s->clip = new QClipData(d->rasterBuffer->height()); -
1307 s->flags.has_clip_ownership = true; -
1308 } -
1309 if (base->hasRectClip) -
1310 s->clip->setClipRect(base->clipRect & clipRect); -
1311 else -
1312 s->clip->setClipRegion(base->clipRegion & clipRect); -
1313 s->clip->enabled = true; -
1314 } else { -
1315 return false; -
1316 } -
1317 } else { -
1318 return false; -
1319 } -
1320 -
1321 qrasterpaintengine_dirty_clip(d, s); -
1322 return true; -
1323} -
1324 -
1325 -
1326/*! -
1327 \internal -
1328*/ -
1329void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op) -
1330{ -
1331#ifdef QT_DEBUG_DRAW -
1332 qDebug() << "QRasterPaintEngine::clip(): " << region << op; -
1333#endif -
1334 -
1335 Q_D(QRasterPaintEngine); -
1336 -
1337 if (region.rectCount() == 1) { -
1338 clip(region.boundingRect(), op); -
1339 return; -
1340 } -
1341 -
1342 QRasterPaintEngineState *s = state(); -
1343 const QClipData *clip = d->clip(); -
1344 const QClipData *baseClip = d->baseClip.data(); -
1345 -
1346 if (op == Qt::NoClip) { -
1347 qrasterpaintengine_state_setNoClip(s); -
1348 } else if (s->matrix.type() > QTransform::TxScale -
1349 || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip) -
1350 || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) { -
1351 QPaintEngineEx::clip(region, op); -
1352 } else { -
1353 const QClipData *curClip; -
1354 QClipData *newClip; -
1355 -
1356 if (op == Qt::IntersectClip) -
1357 curClip = clip; -
1358 else -
1359 curClip = baseClip; -
1360 -
1361 if (s->flags.has_clip_ownership) { -
1362 newClip = s->clip; -
1363 Q_ASSERT(newClip); -
1364 } else { -
1365 newClip = new QClipData(d->rasterBuffer->height()); -
1366 s->clip = newClip; -
1367 s->flags.has_clip_ownership = true; -
1368 } -
1369 -
1370 QRegion r = s->matrix.map(region); -
1371 if (curClip->hasRectClip) -
1372 newClip->setClipRegion(r & curClip->clipRect); -
1373 else if (curClip->hasRegionClip) -
1374 newClip->setClipRegion(r & curClip->clipRegion); -
1375 -
1376 qrasterpaintengine_dirty_clip(d, s); -
1377 } -
1378} -
1379 -
1380/*! -
1381 \fn const QClipData *QRasterPaintEngine::clipData() const -
1382 -
1383 \internal -
1384*/ -
1385 -
1386 -
1387/*! -
1388 \internal -
1389*/ -
1390void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData) -
1391{ -
1392#ifdef QT_DEBUG_DRAW -
1393 qDebug() << " --- fillPath, bounds=" << path.boundingRect(); -
1394#endif -
1395 -
1396 if (!fillData->blend) -
1397 return; -
1398 -
1399 Q_D(QRasterPaintEngine); -
1400 -
1401 const QRectF controlPointRect = path.controlPointRect(); -
1402 -
1403 QRasterPaintEngineState *s = state(); -
1404 const QRect deviceRect = s->matrix.mapRect(controlPointRect).toRect(); -
1405 ProcessSpans blend = d->getBrushFunc(deviceRect, fillData); -
1406 const bool do_clip = (deviceRect.left() < -QT_RASTER_COORD_LIMIT -
1407 || deviceRect.right() > QT_RASTER_COORD_LIMIT -
1408 || deviceRect.top() < -QT_RASTER_COORD_LIMIT -
1409 || deviceRect.bottom() > QT_RASTER_COORD_LIMIT); -
1410 -
1411 if (!s->flags.antialiased && !do_clip) { -
1412 d->initializeRasterizer(fillData); -
1413 d->rasterizer->rasterize(path * s->matrix, path.fillRule()); -
1414 return; -
1415 } -
1416 -
1417 ensureOutlineMapper(); -
1418 d->rasterize(d->outlineMapper->convertPath(path), blend, fillData, d->rasterBuffer.data()); -
1419} -
1420 -
1421static void fillRect_normalized(const QRect &r, QSpanData *data, -
1422 QRasterPaintEnginePrivate *pe) -
1423{ -
1424 int x1, x2, y1, y2; -
1425 -
1426 bool rectClipped = true; -
1427 -
1428 if (data->clip) { -
1429 x1 = qMax(r.x(), data->clip->xmin); -
1430 x2 = qMin(r.x() + r.width(), data->clip->xmax); -
1431 y1 = qMax(r.y(), data->clip->ymin); -
1432 y2 = qMin(r.y() + r.height(), data->clip->ymax); -
1433 rectClipped = data->clip->hasRectClip; -
1434 -
1435 } else if (pe) { -
1436 x1 = qMax(r.x(), pe->deviceRect.x()); -
1437 x2 = qMin(r.x() + r.width(), pe->deviceRect.x() + pe->deviceRect.width()); -
1438 y1 = qMax(r.y(), pe->deviceRect.y()); -
1439 y2 = qMin(r.y() + r.height(), pe->deviceRect.y() + pe->deviceRect.height()); -
1440 } else { -
1441 x1 = qMax(r.x(), 0); -
1442 x2 = qMin(r.x() + r.width(), data->rasterBuffer->width()); -
1443 y1 = qMax(r.y(), 0); -
1444 y2 = qMin(r.y() + r.height(), data->rasterBuffer->height()); -
1445 } -
1446 -
1447 if (x2 <= x1 || y2 <= y1) -
1448 return; -
1449 -
1450 const int width = x2 - x1; -
1451 const int height = y2 - y1; -
1452 -
1453 bool isUnclipped = rectClipped -
1454 || (pe && pe->isUnclipped_normalized(QRect(x1, y1, width, height))); -
1455 -
1456 if (pe && isUnclipped) { -
1457 const QPainter::CompositionMode mode = pe->rasterBuffer->compositionMode; -
1458 -
1459 if (data->fillRect && (mode == QPainter::CompositionMode_Source -
1460 || (mode == QPainter::CompositionMode_SourceOver -
1461 && qAlpha(data->solid.color) == 255))) -
1462 { -
1463 data->fillRect(data->rasterBuffer, x1, y1, width, height, -
1464 data->solid.color); -
1465 return; -
1466 } -
1467 } -
1468 -
1469 ProcessSpans blend = isUnclipped ? data->unclipped_blend : data->blend; -
1470 -
1471 const int nspans = 256; -
1472 QT_FT_Span spans[nspans]; -
1473 -
1474 Q_ASSERT(data->blend); -
1475 int y = y1; -
1476 while (y < y2) { -
1477 int n = qMin(nspans, y2 - y); -
1478 int i = 0; -
1479 while (i < n) { -
1480 spans[i].x = x1; -
1481 spans[i].len = width; -
1482 spans[i].y = y + i; -
1483 spans[i].coverage = 255; -
1484 ++i; -
1485 } -
1486 -
1487 blend(n, spans, data); -
1488 y += n; -
1489 } -
1490} -
1491 -
1492/*! -
1493 \reimp -
1494*/ -
1495void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount) -
1496{ -
1497#ifdef QT_DEBUG_DRAW -
1498 qDebug(" - QRasterPaintEngine::drawRect(), rectCount=%d", rectCount); -
1499#endif -
1500 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1501 ensureRasterState();
executed (the execution status of this line is deduced): ensureRasterState();
-
1502 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
1503 -
1504 // Fill -
1505 ensureBrush();
executed (the execution status of this line is deduced): ensureBrush();
-
1506 if (s->brushData.blend) {
evaluated: s->brushData.blend
TRUEFALSE
yes
Evaluation Count:6418
yes
Evaluation Count:2013
2013-6418
1507 if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxTranslate) {
evaluated: !s->flags.antialiased
TRUEFALSE
yes
Evaluation Count:6408
yes
Evaluation Count:10
evaluated: s->matrix.type() <= QTransform::TxTranslate
TRUEFALSE
yes
Evaluation Count:6405
yes
Evaluation Count:3
3-6408
1508 const QRect *r = rects;
executed (the execution status of this line is deduced): const QRect *r = rects;
-
1509 const QRect *lastRect = rects + rectCount;
executed (the execution status of this line is deduced): const QRect *lastRect = rects + rectCount;
-
1510 -
1511 int offset_x = int(s->matrix.dx());
executed (the execution status of this line is deduced): int offset_x = int(s->matrix.dx());
-
1512 int offset_y = int(s->matrix.dy());
executed (the execution status of this line is deduced): int offset_y = int(s->matrix.dy());
-
1513 while (r < lastRect) {
evaluated: r < lastRect
TRUEFALSE
yes
Evaluation Count:6405
yes
Evaluation Count:6405
6405
1514 QRect rect = r->normalized();
executed (the execution status of this line is deduced): QRect rect = r->normalized();
-
1515 QRect rr = rect.translated(offset_x, offset_y);
executed (the execution status of this line is deduced): QRect rr = rect.translated(offset_x, offset_y);
-
1516 fillRect_normalized(rr, &s->brushData, d);
executed (the execution status of this line is deduced): fillRect_normalized(rr, &s->brushData, d);
-
1517 ++r;
executed (the execution status of this line is deduced): ++r;
-
1518 }
executed: }
Execution Count:6405
6405
1519 } else {
executed: }
Execution Count:6405
6405
1520 QRectVectorPath path;
executed (the execution status of this line is deduced): QRectVectorPath path;
-
1521 for (int i=0; i<rectCount; ++i) {
evaluated: i<rectCount
TRUEFALSE
yes
Evaluation Count:13
yes
Evaluation Count:13
13
1522 path.set(rects[i]);
executed (the execution status of this line is deduced): path.set(rects[i]);
-
1523 fill(path, s->brush);
executed (the execution status of this line is deduced): fill(path, s->brush);
-
1524 }
executed: }
Execution Count:13
13
1525 }
executed: }
Execution Count:13
13
1526 } -
1527 -
1528 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
1529 if (s->penData.blend) {
evaluated: s->penData.blend
TRUEFALSE
yes
Evaluation Count:2384
yes
Evaluation Count:6047
2384-6047
1530 QRectVectorPath path;
executed (the execution status of this line is deduced): QRectVectorPath path;
-
1531 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:2378
yes
Evaluation Count:6
6-2378
1532 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
1533 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
1534 for (int i = 0; i < rectCount; ++i) {
evaluated: i < rectCount
TRUEFALSE
yes
Evaluation Count:2378
yes
Evaluation Count:2378
2378
1535 path.set(rects[i]);
executed (the execution status of this line is deduced): path.set(rects[i]);
-
1536 stroker.drawPath(path);
executed (the execution status of this line is deduced): stroker.drawPath(path);
-
1537 }
executed: }
Execution Count:2378
2378
1538 } else {
executed: }
Execution Count:2378
2378
1539 for (int i = 0; i < rectCount; ++i) {
evaluated: i < rectCount
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:6
6
1540 path.set(rects[i]);
executed (the execution status of this line is deduced): path.set(rects[i]);
-
1541 stroke(path, s->pen);
executed (the execution status of this line is deduced): stroke(path, s->pen);
-
1542 }
executed: }
Execution Count:6
6
1543 }
executed: }
Execution Count:6
6
1544 } -
1545}
executed: }
Execution Count:8431
8431
1546 -
1547/*! -
1548 \reimp -
1549*/ -
1550void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) -
1551{ -
1552#ifdef QT_DEBUG_DRAW -
1553 qDebug(" - QRasterPaintEngine::drawRect(QRectF*), rectCount=%d", rectCount); -
1554#endif -
1555#ifdef QT_FAST_SPANS -
1556 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1557 ensureRasterState();
executed (the execution status of this line is deduced): ensureRasterState();
-
1558 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
1559 -
1560 -
1561 if (s->flags.tx_noshear) {
evaluated: s->flags.tx_noshear
TRUEFALSE
yes
Evaluation Count:616
yes
Evaluation Count:8
8-616
1562 ensureBrush();
executed (the execution status of this line is deduced): ensureBrush();
-
1563 if (s->brushData.blend) {
evaluated: s->brushData.blend
TRUEFALSE
yes
Evaluation Count:313
yes
Evaluation Count:303
303-313
1564 d->initializeRasterizer(&s->brushData);
executed (the execution status of this line is deduced): d->initializeRasterizer(&s->brushData);
-
1565 for (int i = 0; i < rectCount; ++i) {
evaluated: i < rectCount
TRUEFALSE
yes
Evaluation Count:313
yes
Evaluation Count:313
313
1566 const QRectF &rect = rects[i].normalized();
executed (the execution status of this line is deduced): const QRectF &rect = rects[i].normalized();
-
1567 if (rect.isEmpty())
evaluated: rect.isEmpty()
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:311
2-311
1568 continue;
executed: continue;
Execution Count:2
2
1569 const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
executed (the execution status of this line is deduced): const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
-
1570 const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
executed (the execution status of this line is deduced): const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
-
1571 d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
executed (the execution status of this line is deduced): d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
-
1572 }
executed: }
Execution Count:311
311
1573 }
executed: }
Execution Count:313
313
1574 -
1575 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
1576 if (s->penData.blend) {
evaluated: s->penData.blend
TRUEFALSE
yes
Evaluation Count:361
yes
Evaluation Count:255
255-361
1577 QRectVectorPath path;
executed (the execution status of this line is deduced): QRectVectorPath path;
-
1578 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:337
yes
Evaluation Count:24
24-337
1579 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
1580 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
1581 for (int i = 0; i < rectCount; ++i) {
evaluated: i < rectCount
TRUEFALSE
yes
Evaluation Count:337
yes
Evaluation Count:337
337
1582 path.set(rects[i]);
executed (the execution status of this line is deduced): path.set(rects[i]);
-
1583 stroker.drawPath(path);
executed (the execution status of this line is deduced): stroker.drawPath(path);
-
1584 }
executed: }
Execution Count:337
337
1585 } else {
executed: }
Execution Count:337
337
1586 for (int i = 0; i < rectCount; ++i) {
evaluated: i < rectCount
TRUEFALSE
yes
Evaluation Count:24
yes
Evaluation Count:24
24
1587 path.set(rects[i]);
executed (the execution status of this line is deduced): path.set(rects[i]);
-
1588 QPaintEngineEx::stroke(path, s->lastPen);
executed (the execution status of this line is deduced): QPaintEngineEx::stroke(path, s->lastPen);
-
1589 }
executed: }
Execution Count:24
24
1590 }
executed: }
Execution Count:24
24
1591 } -
1592 -
1593 return;
executed: return;
Execution Count:616
616
1594 } -
1595#endif // QT_FAST_SPANS -
1596 QPaintEngineEx::drawRects(rects, rectCount);
executed (the execution status of this line is deduced): QPaintEngineEx::drawRects(rects, rectCount);
-
1597}
executed: }
Execution Count:8
8
1598 -
1599 -
1600/*! -
1601 \internal -
1602*/ -
1603void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) -
1604{ -
1605 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1606 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
1607 -
1608 ensurePen(pen);
executed (the execution status of this line is deduced): ensurePen(pen);
-
1609 if (!s->penData.blend)
evaluated: !s->penData.blend
TRUEFALSE
yes
Evaluation Count:13
yes
Evaluation Count:13272
13-13272
1610 return;
executed: return;
Execution Count:13
13
1611 -
1612 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:11507
yes
Evaluation Count:1765
1765-11507
1613 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
1614 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
1615 stroker.drawPath(path);
executed (the execution status of this line is deduced): stroker.drawPath(path);
-
1616 } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) {
executed: }
Execution Count:11507
evaluated: s->flags.non_complex_pen
TRUEFALSE
yes
Evaluation Count:1545
yes
Evaluation Count:220
evaluated: path.shape() == QVectorPath::LinesHint
TRUEFALSE
yes
Evaluation Count:875
yes
Evaluation Count:670
220-11507
1617 qreal width = qt_pen_is_cosmetic(s->lastPen, s->renderHints)
partially evaluated: qt_pen_is_cosmetic(s->lastPen, s->renderHints)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:875
0-875
1618 ? (qpen_widthf(s->lastPen) == 0 ? 1 : qpen_widthf(s->lastPen))
executed (the execution status of this line is deduced): ? (qpen_widthf(s->lastPen) == 0 ? 1 : qpen_widthf(s->lastPen))
-
1619 : qpen_widthf(s->lastPen) * s->txscale;
executed (the execution status of this line is deduced): : qpen_widthf(s->lastPen) * s->txscale;
-
1620 int dashIndex = 0;
executed (the execution status of this line is deduced): int dashIndex = 0;
-
1621 qreal dashOffset = s->lastPen.dashOffset();
executed (the execution status of this line is deduced): qreal dashOffset = s->lastPen.dashOffset();
-
1622 bool inDash = true;
executed (the execution status of this line is deduced): bool inDash = true;
-
1623 qreal patternLength = 0;
executed (the execution status of this line is deduced): qreal patternLength = 0;
-
1624 const QVector<qreal> pattern = s->lastPen.dashPattern();
executed (the execution status of this line is deduced): const QVector<qreal> pattern = s->lastPen.dashPattern();
-
1625 for (int i = 0; i < pattern.size(); ++i)
evaluated: i < pattern.size()
TRUEFALSE
yes
Evaluation Count:6
yes
Evaluation Count:875
6-875
1626 patternLength += pattern.at(i);
executed: patternLength += pattern.at(i);
Execution Count:6
6
1627 -
1628 if (patternLength > 0) {
evaluated: patternLength > 0
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:874
1-874
1629 int n = qFloor(dashOffset / patternLength);
executed (the execution status of this line is deduced): int n = qFloor(dashOffset / patternLength);
-
1630 dashOffset -= n * patternLength;
executed (the execution status of this line is deduced): dashOffset -= n * patternLength;
-
1631 while (dashOffset >= pattern.at(dashIndex)) {
partially evaluated: dashOffset >= pattern.at(dashIndex)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:1
0-1
1632 dashOffset -= pattern.at(dashIndex);
never executed (the execution status of this line is deduced): dashOffset -= pattern.at(dashIndex);
-
1633 if (++dashIndex >= pattern.size())
never evaluated: ++dashIndex >= pattern.size()
0
1634 dashIndex = 0;
never executed: dashIndex = 0;
0
1635 inDash = !inDash;
never executed (the execution status of this line is deduced): inDash = !inDash;
-
1636 }
never executed: }
0
1637 }
executed: }
Execution Count:1
1
1638 -
1639 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1640 d->initializeRasterizer(&s->penData);
executed (the execution status of this line is deduced): d->initializeRasterizer(&s->penData);
-
1641 int lineCount = path.elementCount() / 2;
executed (the execution status of this line is deduced): int lineCount = path.elementCount() / 2;
-
1642 const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
executed (the execution status of this line is deduced): const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
-
1643 -
1644 for (int i = 0; i < lineCount; ++i) {
evaluated: i < lineCount
TRUEFALSE
yes
Evaluation Count:876
yes
Evaluation Count:875
875-876
1645 if (lines[i].p1() == lines[i].p2()) {
evaluated: lines[i].p1() == lines[i].p2()
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:875
1-875
1646 if (s->lastPen.capStyle() != Qt::FlatCap) {
partially evaluated: s->lastPen.capStyle() != Qt::FlatCap
TRUEFALSE
yes
Evaluation Count:1
no
Evaluation Count:0
0-1
1647 QPointF p = lines[i].p1();
executed (the execution status of this line is deduced): QPointF p = lines[i].p1();
-
1648 QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()),
executed (the execution status of this line is deduced): QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()),
-
1649 QPointF(p.x() + width*0.5, p.y())));
executed (the execution status of this line is deduced): QPointF(p.x() + width*0.5, p.y())));
-
1650 d->rasterizer->rasterizeLine(line.p1(), line.p2(), 1);
executed (the execution status of this line is deduced): d->rasterizer->rasterizeLine(line.p1(), line.p2(), 1);
-
1651 }
executed: }
Execution Count:1
1
1652 continue;
executed: continue;
Execution Count:1
1
1653 } -
1654 -
1655 const QLineF line = s->matrix.map(lines[i]);
executed (the execution status of this line is deduced): const QLineF line = s->matrix.map(lines[i]);
-
1656 if (qpen_style(s->lastPen) == Qt::SolidLine) {
evaluated: qpen_style(s->lastPen) == Qt::SolidLine
TRUEFALSE
yes
Evaluation Count:872
yes
Evaluation Count:3
3-872
1657 d->rasterizer->rasterizeLine(line.p1(), line.p2(),
executed (the execution status of this line is deduced): d->rasterizer->rasterizeLine(line.p1(), line.p2(),
-
1658 width / line.length(),
executed (the execution status of this line is deduced): width / line.length(),
-
1659 s->lastPen.capStyle() == Qt::SquareCap);
executed (the execution status of this line is deduced): s->lastPen.capStyle() == Qt::SquareCap);
-
1660 } else {
executed: }
Execution Count:872
872
1661 d->rasterizeLine_dashed(line, width,
executed (the execution status of this line is deduced): d->rasterizeLine_dashed(line, width,
-
1662 &dashIndex, &dashOffset, &inDash);
executed (the execution status of this line is deduced): &dashIndex, &dashOffset, &inDash);
-
1663 }
executed: }
Execution Count:3
3
1664 } -
1665 }
executed: }
Execution Count:875
875
1666 else -
1667 QPaintEngineEx::stroke(path, pen);
executed: QPaintEngineEx::stroke(path, pen);
Execution Count:890
890
1668} -
1669 -
1670QRect QRasterPaintEngine::toNormalizedFillRect(const QRectF &rect) -
1671{ -
1672 QRasterPaintEngineState *s = state(); -
1673 -
1674 qreal delta = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0); -
1675 -
1676 int x1 = qRound(rect.x() + delta); -
1677 int y1 = qRound(rect.y() + delta); -
1678 int x2 = qRound(rect.right() + delta); -
1679 int y2 = qRound(rect.bottom() + delta); -
1680 -
1681 if (x2 < x1) -
1682 qSwap(x1, x2); -
1683 if (y2 < y1) -
1684 qSwap(y1, y2); -
1685 -
1686 return QRect(x1, y1, x2 - x1, y2 - y1); -
1687} -
1688 -
1689/*! -
1690 \internal -
1691*/ -
1692void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) -
1693{ -
1694 if (path.isEmpty()) -
1695 return; -
1696#ifdef QT_DEBUG_DRAW -
1697 QRectF rf = path.controlPointRect(); -
1698 qDebug() << "QRasterPaintEngine::fill(): " -
1699 << "size=" << path.elementCount() -
1700 << ", hints=" << hex << path.hints() -
1701 << rf << brush; -
1702#endif -
1703 -
1704 Q_D(QRasterPaintEngine); -
1705 QRasterPaintEngineState *s = state(); -
1706 -
1707 ensureBrush(brush); -
1708 if (!s->brushData.blend) -
1709 return; -
1710 -
1711 if (path.shape() == QVectorPath::RectangleHint) { -
1712 if (!s->flags.antialiased && s->matrix.type() <= QTransform::TxScale) { -
1713 const qreal *p = path.points(); -
1714 QPointF tl = QPointF(p[0], p[1]) * s->matrix; -
1715 QPointF br = QPointF(p[4], p[5]) * s->matrix; -
1716 fillRect_normalized(toNormalizedFillRect(QRectF(tl, br)), &s->brushData, d); -
1717 return; -
1718 } -
1719 ensureRasterState(); -
1720 if (s->flags.tx_noshear) { -
1721 d->initializeRasterizer(&s->brushData); -
1722 // ### Is normalizing really necessary here? -
1723 const qreal *p = path.points(); -
1724 QRectF r = QRectF(p[0], p[1], p[2] - p[0], p[7] - p[1]).normalized(); -
1725 if (!r.isEmpty()) { -
1726 const QPointF a = s->matrix.map((r.topLeft() + r.bottomLeft()) * 0.5f); -
1727 const QPointF b = s->matrix.map((r.topRight() + r.bottomRight()) * 0.5f); -
1728 d->rasterizer->rasterizeLine(a, b, r.height() / r.width()); -
1729 } -
1730 return; -
1731 } -
1732 } -
1733 -
1734 // ### Optimize for non transformed ellipses and rectangles... -
1735 QRectF cpRect = path.controlPointRect(); -
1736 const QRect deviceRect = s->matrix.mapRect(cpRect).toRect(); -
1737 ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData); -
1738 -
1739 // ### Falcon -
1740// const bool do_clip = (deviceRect.left() < -QT_RASTER_COORD_LIMIT -
1741// || deviceRect.right() > QT_RASTER_COORD_LIMIT -
1742// || deviceRect.top() < -QT_RASTER_COORD_LIMIT -
1743// || deviceRect.bottom() > QT_RASTER_COORD_LIMIT); -
1744 -
1745 // ### Falonc: implement.... -
1746// if (!s->flags.antialiased && !do_clip) { -
1747// d->initializeRasterizer(&s->brushData); -
1748// d->rasterizer->rasterize(path * d->matrix, path.fillRule()); -
1749// return; -
1750// } -
1751 -
1752 ensureOutlineMapper(); -
1753 d->rasterize(d->outlineMapper->convertPath(path), blend, &s->brushData, d->rasterBuffer.data()); -
1754} -
1755 -
1756void QRasterPaintEngine::fillRect(const QRectF &r, QSpanData *data) -
1757{ -
1758 Q_D(QRasterPaintEngine); -
1759 QRasterPaintEngineState *s = state(); -
1760 -
1761 if (!s->flags.antialiased) { -
1762 uint txop = s->matrix.type(); -
1763 if (txop == QTransform::TxNone) { -
1764 fillRect_normalized(toNormalizedFillRect(r), data, d); -
1765 return; -
1766 } else if (txop == QTransform::TxTranslate) { -
1767 const QRect rr = toNormalizedFillRect(r.translated(s->matrix.dx(), s->matrix.dy())); -
1768 fillRect_normalized(rr, data, d); -
1769 return; -
1770 } else if (txop == QTransform::TxScale) { -
1771 const QRect rr = toNormalizedFillRect(s->matrix.mapRect(r)); -
1772 fillRect_normalized(rr, data, d); -
1773 return; -
1774 } -
1775 } -
1776 ensureRasterState(); -
1777 if (s->flags.tx_noshear) { -
1778 d->initializeRasterizer(data); -
1779 QRectF nr = r.normalized(); -
1780 if (!nr.isEmpty()) { -
1781 const QPointF a = s->matrix.map((nr.topLeft() + nr.bottomLeft()) * 0.5f); -
1782 const QPointF b = s->matrix.map((nr.topRight() + nr.bottomRight()) * 0.5f); -
1783 d->rasterizer->rasterizeLine(a, b, nr.height() / nr.width()); -
1784 } -
1785 return; -
1786 } -
1787 -
1788 QPainterPath path; -
1789 path.addRect(r); -
1790 ensureOutlineMapper(); -
1791 fillPath(path, data); -
1792} -
1793 -
1794/*! -
1795 \reimp -
1796*/ -
1797void QRasterPaintEngine::fillRect(const QRectF &r, const QBrush &brush) -
1798{ -
1799#ifdef QT_DEBUG_DRAW -
1800 qDebug() << "QRasterPaintEngine::fillRecct(): " << r << brush; -
1801#endif -
1802 QRasterPaintEngineState *s = state(); -
1803 -
1804 ensureBrush(brush); -
1805 if (!s->brushData.blend) -
1806 return; -
1807 -
1808 fillRect(r, &s->brushData); -
1809} -
1810 -
1811/*! -
1812 \reimp -
1813*/ -
1814void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) -
1815{ -
1816#ifdef QT_DEBUG_DRAW -
1817 qDebug() << "QRasterPaintEngine::fillRect(): " << r << color; -
1818#endif -
1819 Q_D(QRasterPaintEngine); -
1820 QRasterPaintEngineState *s = state(); -
1821 -
1822 d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); -
1823 if ((d->solid_color_filler.solid.color & 0xff000000) == 0 -
1824 && s->composition_mode == QPainter::CompositionMode_SourceOver) { -
1825 return; -
1826 } -
1827 d->solid_color_filler.clip = d->clip(); -
1828 d->solid_color_filler.adjustSpanMethods(); -
1829 fillRect(r, &d->solid_color_filler); -
1830} -
1831 -
1832static inline bool isAbove(const QPointF *a, const QPointF *b) -
1833{ -
1834 return a->y() < b->y(); -
1835} -
1836 -
1837static bool splitPolygon(const QPointF *points, int pointCount, QVector<QPointF> *upper, QVector<QPointF> *lower) -
1838{ -
1839 Q_ASSERT(upper); -
1840 Q_ASSERT(lower); -
1841 -
1842 Q_ASSERT(pointCount >= 2); -
1843 -
1844 QVector<const QPointF *> sorted; -
1845 sorted.reserve(pointCount); -
1846 -
1847 upper->reserve(pointCount * 3 / 4); -
1848 lower->reserve(pointCount * 3 / 4); -
1849 -
1850 for (int i = 0; i < pointCount; ++i) -
1851 sorted << points + i; -
1852 -
1853 qSort(sorted.begin(), sorted.end(), isAbove); -
1854 -
1855 qreal splitY = sorted.at(sorted.size() / 2)->y(); -
1856 -
1857 const QPointF *end = points + pointCount; -
1858 const QPointF *last = end - 1; -
1859 -
1860 QVector<QPointF> *bin[2] = { upper, lower }; -
1861 -
1862 for (const QPointF *p = points; p < end; ++p) { -
1863 int side = p->y() < splitY; -
1864 int lastSide = last->y() < splitY; -
1865 -
1866 if (side != lastSide) { -
1867 if (qFuzzyCompare(p->y(), splitY)) { -
1868 bin[!side]->append(*p); -
1869 } else if (qFuzzyCompare(last->y(), splitY)) { -
1870 bin[side]->append(*last); -
1871 } else { -
1872 QPointF delta = *p - *last; -
1873 QPointF intersection(p->x() + delta.x() * (splitY - p->y()) / delta.y(), splitY); -
1874 -
1875 bin[0]->append(intersection); -
1876 bin[1]->append(intersection); -
1877 } -
1878 } -
1879 -
1880 bin[side]->append(*p); -
1881 -
1882 last = p; -
1883 } -
1884 -
1885 // give up if we couldn't reduce the point count -
1886 return upper->size() < pointCount && lower->size() < pointCount; -
1887} -
1888 -
1889/*! -
1890 \internal -
1891 */ -
1892void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -
1893{ -
1894 Q_D(QRasterPaintEngine); -
1895 QRasterPaintEngineState *s = state(); -
1896 -
1897 const int maxPoints = 0xffff; -
1898 -
1899 // max amount of points that raster engine can reliably handle -
1900 if (pointCount > maxPoints) { -
1901 QVector<QPointF> upper, lower; -
1902 -
1903 if (splitPolygon(points, pointCount, &upper, &lower)) { -
1904 fillPolygon(upper.constData(), upper.size(), mode); -
1905 fillPolygon(lower.constData(), lower.size(), mode); -
1906 } else -
1907 qWarning("Polygon too complex for filling."); -
1908 -
1909 return; -
1910 } -
1911 -
1912 // Compose polygon fill.., -
1913 QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode)); -
1914 ensureOutlineMapper(); -
1915 QT_FT_Outline *outline = d->outlineMapper->convertPath(vp); -
1916 -
1917 // scanconvert. -
1918 ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, -
1919 &s->brushData); -
1920 d->rasterize(outline, brushBlend, &s->brushData, d->rasterBuffer.data()); -
1921} -
1922 -
1923/*! -
1924 \reimp -
1925*/ -
1926void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) -
1927{ -
1928 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1929 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
1930 -
1931#ifdef QT_DEBUG_DRAW -
1932 qDebug(" - QRasterPaintEngine::drawPolygon(F), pointCount=%d", pointCount); -
1933 for (int i=0; i<pointCount; ++i) -
1934 qDebug() << " - " << points[i]; -
1935#endif -
1936 Q_ASSERT(pointCount >= 2);
executed (the execution status of this line is deduced): qt_noop();
-
1937 -
1938 if (mode != PolylineMode && isRect((qreal *) points, pointCount)) {
partially evaluated: mode != PolylineMode
TRUEFALSE
yes
Evaluation Count:447
no
Evaluation Count:0
evaluated: isRect((qreal *) points, pointCount)
TRUEFALSE
yes
Evaluation Count:20
yes
Evaluation Count:427
0-447
1939 QRectF r(points[0], points[2]);
executed (the execution status of this line is deduced): QRectF r(points[0], points[2]);
-
1940 drawRects(&r, 1);
executed (the execution status of this line is deduced): drawRects(&r, 1);
-
1941 return;
executed: return;
Execution Count:20
20
1942 } -
1943 -
1944 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
1945 if (mode != PolylineMode) {
partially evaluated: mode != PolylineMode
TRUEFALSE
yes
Evaluation Count:427
no
Evaluation Count:0
0-427
1946 // Do the fill... -
1947 ensureBrush();
executed (the execution status of this line is deduced): ensureBrush();
-
1948 if (s->brushData.blend)
evaluated: s->brushData.blend
TRUEFALSE
yes
Evaluation Count:391
yes
Evaluation Count:36
36-391
1949 fillPolygon(points, pointCount, mode);
executed: fillPolygon(points, pointCount, mode);
Execution Count:391
391
1950 }
executed: }
Execution Count:427
427
1951 -
1952 // Do the outline... -
1953 if (s->penData.blend) {
evaluated: s->penData.blend
TRUEFALSE
yes
Evaluation Count:408
yes
Evaluation Count:19
19-408
1954 QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
executed (the execution status of this line is deduced): QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode));
-
1955 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:396
yes
Evaluation Count:12
12-396
1956 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
1957 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
1958 stroker.drawPath(vp);
executed (the execution status of this line is deduced): stroker.drawPath(vp);
-
1959 } else {
executed: }
Execution Count:396
396
1960 QPaintEngineEx::stroke(vp, s->lastPen);
executed (the execution status of this line is deduced): QPaintEngineEx::stroke(vp, s->lastPen);
-
1961 }
executed: }
Execution Count:12
12
1962 } -
1963}
executed: }
Execution Count:427
427
1964 -
1965/*! -
1966 \reimp -
1967*/ -
1968void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) -
1969{ -
1970 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
1971 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
1972 -
1973#ifdef QT_DEBUG_DRAW -
1974 qDebug(" - QRasterPaintEngine::drawPolygon(I), pointCount=%d", pointCount); -
1975 for (int i=0; i<pointCount; ++i) -
1976 qDebug() << " - " << points[i]; -
1977#endif -
1978 Q_ASSERT(pointCount >= 2);
executed (the execution status of this line is deduced): qt_noop();
-
1979 if (mode != PolylineMode && isRect((int *) points, pointCount)) {
evaluated: mode != PolylineMode
TRUEFALSE
yes
Evaluation Count:906
yes
Evaluation Count:50052
evaluated: isRect((int *) points, pointCount)
TRUEFALSE
yes
Evaluation Count:20
yes
Evaluation Count:886
20-50052
1980 QRect r(points[0].x(),
executed (the execution status of this line is deduced): QRect r(points[0].x(),
-
1981 points[0].y(),
executed (the execution status of this line is deduced): points[0].y(),
-
1982 points[2].x() - points[0].x(),
executed (the execution status of this line is deduced): points[2].x() - points[0].x(),
-
1983 points[2].y() - points[0].y());
executed (the execution status of this line is deduced): points[2].y() - points[0].y());
-
1984 drawRects(&r, 1);
executed (the execution status of this line is deduced): drawRects(&r, 1);
-
1985 return;
executed: return;
Execution Count:20
20
1986 } -
1987 -
1988 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
1989 -
1990 // Do the fill -
1991 if (mode != PolylineMode) {
evaluated: mode != PolylineMode
TRUEFALSE
yes
Evaluation Count:886
yes
Evaluation Count:50052
886-50052
1992 ensureBrush();
executed (the execution status of this line is deduced): ensureBrush();
-
1993 if (s->brushData.blend) {
evaluated: s->brushData.blend
TRUEFALSE
yes
Evaluation Count:850
yes
Evaluation Count:36
36-850
1994 // Compose polygon fill.., -
1995 ensureOutlineMapper();
executed (the execution status of this line is deduced): ensureOutlineMapper();
-
1996 d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
executed (the execution status of this line is deduced): d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
-
1997 d->outlineMapper->moveTo(*points);
executed (the execution status of this line is deduced): d->outlineMapper->moveTo(*points);
-
1998 const QPoint *p = points;
executed (the execution status of this line is deduced): const QPoint *p = points;
-
1999 const QPoint *ep = points + pointCount - 1;
executed (the execution status of this line is deduced): const QPoint *ep = points + pointCount - 1;
-
2000 do { -
2001 d->outlineMapper->lineTo(*(++p));
executed (the execution status of this line is deduced): d->outlineMapper->lineTo(*(++p));
-
2002 } while (p < ep);
executed: }
Execution Count:2317
evaluated: p < ep
TRUEFALSE
yes
Evaluation Count:1467
yes
Evaluation Count:850
850-2317
2003 d->outlineMapper->endOutline();
executed (the execution status of this line is deduced): d->outlineMapper->endOutline();
-
2004 -
2005 // scanconvert. -
2006 ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
executed (the execution status of this line is deduced): ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
-
2007 &s->brushData);
executed (the execution status of this line is deduced): &s->brushData);
-
2008 d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
executed (the execution status of this line is deduced): d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
-
2009 }
executed: }
Execution Count:850
850
2010 }
executed: }
Execution Count:886
886
2011 -
2012 // Do the outline... -
2013 if (s->penData.blend) {
evaluated: s->penData.blend
TRUEFALSE
yes
Evaluation Count:50920
yes
Evaluation Count:18
18-50920
2014 int count = pointCount * 2;
executed (the execution status of this line is deduced): int count = pointCount * 2;
-
2015 QVarLengthArray<qreal> fpoints(count);
executed (the execution status of this line is deduced): QVarLengthArray<qreal> fpoints(count);
-
2016 for (int i=0; i<count; ++i)
evaluated: i<count
TRUEFALSE
yes
Evaluation Count:309350
yes
Evaluation Count:50920
50920-309350
2017 fpoints[i] = ((int *) points)[i];
executed: fpoints[i] = ((int *) points)[i];
Execution Count:309350
309350
2018 QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
executed (the execution status of this line is deduced): QVectorPath vp((qreal *) fpoints.data(), pointCount, 0, QVectorPath::polygonFlags(mode));
-
2019 -
2020 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:50908
yes
Evaluation Count:12
12-50908
2021 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
2022 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
2023 stroker.drawPath(vp);
executed (the execution status of this line is deduced): stroker.drawPath(vp);
-
2024 } else {
executed: }
Execution Count:50908
50908
2025 QPaintEngineEx::stroke(vp, s->lastPen);
executed (the execution status of this line is deduced): QPaintEngineEx::stroke(vp, s->lastPen);
-
2026 }
executed: }
Execution Count:12
12
2027 } -
2028}
executed: }
Execution Count:50938
50938
2029 -
2030/*! -
2031 \internal -
2032*/ -
2033void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap) -
2034{ -
2035#ifdef QT_DEBUG_DRAW -
2036 qDebug() << " - QRasterPaintEngine::drawPixmap(), pos=" << pos << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth(); -
2037#endif -
2038 -
2039 QPlatformPixmap *pd = pixmap.handle(); -
2040 if (pd->classId() == QPlatformPixmap::RasterClass) { -
2041 const QImage &image = static_cast<QRasterPlatformPixmap *>(pd)->image; -
2042 if (image.depth() == 1) { -
2043 Q_D(QRasterPaintEngine); -
2044 QRasterPaintEngineState *s = state(); -
2045 if (s->matrix.type() <= QTransform::TxTranslate) { -
2046 ensurePen(); -
2047 drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); -
2048 } else { -
2049 drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color())); -
2050 } -
2051 } else { -
2052 QRasterPaintEngine::drawImage(pos, image); -
2053 } -
2054 } else { -
2055 const QImage image = pixmap.toImage(); -
2056 if (pixmap.depth() == 1) { -
2057 Q_D(QRasterPaintEngine); -
2058 QRasterPaintEngineState *s = state(); -
2059 if (s->matrix.type() <= QTransform::TxTranslate) { -
2060 ensurePen(); -
2061 drawBitmap(pos + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); -
2062 } else { -
2063 drawImage(pos, d->rasterBuffer->colorizeBitmap(image, s->pen.color())); -
2064 } -
2065 } else { -
2066 QRasterPaintEngine::drawImage(pos, image); -
2067 } -
2068 } -
2069} -
2070 -
2071/*! -
2072 \reimp -
2073*/ -
2074void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &sr) -
2075{ -
2076#ifdef QT_DEBUG_DRAW -
2077 qDebug() << " - QRasterPaintEngine::drawPixmap(), r=" << r << " sr=" << sr << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth(); -
2078#endif -
2079 -
2080 QPlatformPixmap* pd = pixmap.handle(); -
2081 if (pd->classId() == QPlatformPixmap::RasterClass) { -
2082 const QImage &image = static_cast<QRasterPlatformPixmap *>(pd)->image; -
2083 if (image.depth() == 1) { -
2084 Q_D(QRasterPaintEngine); -
2085 QRasterPaintEngineState *s = state(); -
2086 if (s->matrix.type() <= QTransform::TxTranslate -
2087 && r.size() == sr.size() -
2088 && r.size() == pixmap.size()) { -
2089 ensurePen(); -
2090 drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); -
2091 return; -
2092 } else { -
2093 drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), sr); -
2094 } -
2095 } else { -
2096 drawImage(r, image, sr); -
2097 } -
2098 } else { -
2099 QRect clippedSource = sr.toAlignedRect().intersected(pixmap.rect()); -
2100 const QImage image = pd->toImage(clippedSource); -
2101 QRectF translatedSource = sr.translated(-clippedSource.topLeft()); -
2102 if (image.depth() == 1) { -
2103 Q_D(QRasterPaintEngine); -
2104 QRasterPaintEngineState *s = state(); -
2105 if (s->matrix.type() <= QTransform::TxTranslate -
2106 && r.size() == sr.size() -
2107 && r.size() == pixmap.size()) { -
2108 ensurePen(); -
2109 drawBitmap(r.topLeft() + QPointF(s->matrix.dx(), s->matrix.dy()), image, &s->penData); -
2110 return; -
2111 } else { -
2112 drawImage(r, d->rasterBuffer->colorizeBitmap(image, s->pen.color()), translatedSource); -
2113 } -
2114 } else { -
2115 drawImage(r, image, translatedSource); -
2116 } -
2117 } -
2118} -
2119 -
2120static inline int fast_ceil_positive(const qreal &v) -
2121{ -
2122 const int iv = int(v); -
2123 if (v - iv == 0) -
2124 return iv; -
2125 else -
2126 return iv + 1; -
2127} -
2128 -
2129static inline const QRect toAlignedRect_positive(const QRectF &rect) -
2130{ -
2131 const int xmin = int(rect.x()); -
2132 const int xmax = int(fast_ceil_positive(rect.right())); -
2133 const int ymin = int(rect.y()); -
2134 const int ymax = int(fast_ceil_positive(rect.bottom())); -
2135 return QRect(xmin, ymin, xmax - xmin, ymax - ymin); -
2136} -
2137 -
2138/*! -
2139 \internal -
2140*/ -
2141void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) -
2142{ -
2143#ifdef QT_DEBUG_DRAW -
2144 qDebug() << " - QRasterPaintEngine::drawImage(), p=" << p << " image=" << img.size() << "depth=" << img.depth(); -
2145#endif -
2146 -
2147 Q_D(QRasterPaintEngine); -
2148 QRasterPaintEngineState *s = state(); -
2149 qreal scale = img.devicePixelRatio(); -
2150 -
2151 if (scale > 1.0 || s->matrix.type() > QTransform::TxTranslate) { -
2152 drawImage(QRectF(p.x(), p.y(), img.width() / scale, img.height() / scale), -
2153 img, -
2154 QRectF(0, 0, img.width(), img.height())); -
2155 } else { -
2156 -
2157 const QClipData *clip = d->clip(); -
2158 QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); -
2159 -
2160 if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { -
2161 SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; -
2162 if (func) { -
2163 if (!clip) { -
2164 d->drawImage(pt, img, func, d->deviceRect, s->intOpacity); -
2165 return; -
2166 } else if (clip->hasRectClip) { -
2167 d->drawImage(pt, img, func, clip->clipRect, s->intOpacity); -
2168 return; -
2169 } -
2170 } -
2171 } -
2172 -
2173 -
2174 -
2175 d->image_filler.clip = clip; -
2176 d->image_filler.initTexture(&img, s->intOpacity, QTextureData::Plain, img.rect()); -
2177 if (!d->image_filler.blend) -
2178 return; -
2179 d->image_filler.dx = -pt.x(); -
2180 d->image_filler.dy = -pt.y(); -
2181 QRect rr = img.rect().translated(qRound(pt.x()), qRound(pt.y())); -
2182 -
2183 fillRect_normalized(rr, &d->image_filler, d); -
2184 } -
2185 -
2186} -
2187 -
2188QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t) -
2189{ -
2190 return QRectF(r.topLeft() * t, r.bottomRight() * t); -
2191} -
2192 -
2193namespace { -
2194 enum RotationType { -
2195 Rotation90, -
2196 Rotation180, -
2197 Rotation270, -
2198 NoRotation -
2199 }; -
2200 -
2201 inline RotationType qRotationType(const QTransform &transform) -
2202 { -
2203 QTransform::TransformationType type = transform.type(); -
2204 -
2205 if (type > QTransform::TxRotate) -
2206 return NoRotation; -
2207 -
2208 if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1)) -
2209 && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22())) -
2210 return Rotation90; -
2211 -
2212 if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12()) -
2213 && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1))) -
2214 return Rotation180; -
2215 -
2216 if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1)) -
2217 && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22())) -
2218 return Rotation270; -
2219 -
2220 return NoRotation; -
2221 } -
2222 -
2223 inline bool isPixelAligned(const QRectF &rect) { -
2224 return QRectF(rect.toRect()) == rect; -
2225 } -
2226} -
2227 -
2228/*! -
2229 \reimp -
2230*/ -
2231void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr, -
2232 Qt::ImageConversionFlags) -
2233{ -
2234#ifdef QT_DEBUG_DRAW -
2235 qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << sr << " image=" << img.size() << "depth=" << img.depth(); -
2236#endif -
2237 -
2238 if (r.isEmpty()) -
2239 return; -
2240 -
2241 Q_D(QRasterPaintEngine); -
2242 QRasterPaintEngineState *s = state(); -
2243 int sr_l = qFloor(sr.left()); -
2244 int sr_r = qCeil(sr.right()) - 1; -
2245 int sr_t = qFloor(sr.top()); -
2246 int sr_b = qCeil(sr.bottom()) - 1; -
2247 -
2248 if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { -
2249 // as fillRect will apply the aliased coordinate delta we need to -
2250 // subtract it here as we don't use it for image drawing -
2251 QTransform old = s->matrix; -
2252 -
2253 if (s->flags.legacy_rounding) -
2254 s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); -
2255 -
2256 // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. -
2257 QRgb color = img.pixel(sr_l, sr_t); -
2258 switch (img.format()) { -
2259 case QImage::Format_ARGB32_Premultiplied: -
2260 case QImage::Format_ARGB8565_Premultiplied: -
2261 case QImage::Format_ARGB6666_Premultiplied: -
2262 case QImage::Format_ARGB8555_Premultiplied: -
2263 case QImage::Format_ARGB4444_Premultiplied: -
2264 // Combine premultiplied color with the opacity set on the painter. -
2265 d->solid_color_filler.solid.color = -
2266 ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) -
2267 | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); -
2268 break; -
2269 default: -
2270 d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity)); -
2271 break; -
2272 } -
2273 -
2274 if ((d->solid_color_filler.solid.color & 0xff000000) == 0 -
2275 && s->composition_mode == QPainter::CompositionMode_SourceOver) { -
2276 return; -
2277 } -
2278 -
2279 d->solid_color_filler.clip = d->clip(); -
2280 d->solid_color_filler.adjustSpanMethods(); -
2281 fillRect(r, &d->solid_color_filler); -
2282 -
2283 s->matrix = old; -
2284 return; -
2285 } -
2286 -
2287 bool stretch_sr = r.width() != sr.width() || r.height() != sr.height(); -
2288 -
2289 const QClipData *clip = d->clip(); -
2290 -
2291 if (s->matrix.type() > QTransform::TxTranslate -
2292 && !stretch_sr -
2293 && (!clip || clip->hasRectClip) -
2294 && s->intOpacity == 256 -
2295 && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver -
2296 || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source) -
2297 && d->rasterBuffer->format == img.format() -
2298 && (d->rasterBuffer->format == QImage::Format_RGB16 -
2299 || d->rasterBuffer->format == QImage::Format_RGB32 -
2300 || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied -
2301 && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))) -
2302 { -
2303 RotationType rotationType = qRotationType(s->matrix); -
2304 -
2305 if (rotationType != NoRotation && qMemRotateFunctions[d->rasterBuffer->format][rotationType] && img.rect().contains(sr.toAlignedRect())) { -
2306 QRectF transformedTargetRect = s->matrix.mapRect(r); -
2307 -
2308 if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) -
2309 || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr))) -
2310 { -
2311 QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect); -
2312 if (clippedTransformedTargetRect.isNull()) -
2313 return; -
2314 -
2315 QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect)); -
2316 -
2317 QRect clippedSourceRect -
2318 = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(), -
2319 clippedTargetRect.width(), clippedTargetRect.height()).toRect(); -
2320 -
2321 uint dbpl = d->rasterBuffer->bytesPerLine(); -
2322 uint sbpl = img.bytesPerLine(); -
2323 -
2324 uchar *dst = d->rasterBuffer->buffer(); -
2325 uint bpp = img.depth() >> 3; -
2326 -
2327 const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp; -
2328 uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp; -
2329 -
2330 uint cw = clippedSourceRect.width(); -
2331 uint ch = clippedSourceRect.height(); -
2332 -
2333 qMemRotateFunctions[d->rasterBuffer->format][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl); -
2334 -
2335 return; -
2336 } -
2337 } -
2338 } -
2339 -
2340 if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { -
2341 -
2342 QRectF targetBounds = s->matrix.mapRect(r); -
2343 bool exceedsPrecision = targetBounds.width() > 0xffff -
2344 || targetBounds.height() > 0xffff; -
2345 -
2346 if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { -
2347 if (s->matrix.type() > QTransform::TxScale) { -
2348 SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; -
2349 if (func && (!clip || clip->hasRectClip)) { -
2350 func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(), -
2351 img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect, -
2352 s->matrix, s->intOpacity); -
2353 return; -
2354 } -
2355 } else { -
2356 // Test for optimized high-dpi case: 2x source on 2x target. (Could be generalized to nX.) -
2357 bool sourceRect2x = r.width() * 2 == sr.width() && r.height() * 2 == sr.height(); -
2358 bool scale2x = (s->matrix.m11() == qreal(2)) && (s->matrix.m22() == qreal(2)); -
2359 if (s->matrix.type() == QTransform::TxScale && sourceRect2x && scale2x) { -
2360 SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; -
2361 if (func) { -
2362 QPointF pt(r.x() * 2 + s->matrix.dx(), r.y() * 2 + s->matrix.dy()); -
2363 if (!clip) { -
2364 d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect()); -
2365 return; -
2366 } else if (clip->hasRectClip) { -
2367 d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect()); -
2368 return; -
2369 } -
2370 } -
2371 } -
2372 SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()]; -
2373 if (func && (!clip || clip->hasRectClip)) { -
2374 func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), -
2375 img.bits(), img.bytesPerLine(), -
2376 qt_mapRect_non_normalizing(r, s->matrix), sr, -
2377 !clip ? d->deviceRect : clip->clipRect, -
2378 s->intOpacity); -
2379 return; -
2380 } -
2381 } -
2382 } -
2383 -
2384 QTransform copy = s->matrix; -
2385 copy.translate(r.x(), r.y()); -
2386 if (stretch_sr) -
2387 copy.scale(r.width() / sr.width(), r.height() / sr.height()); -
2388 copy.translate(-sr.x(), -sr.y()); -
2389 -
2390 d->image_filler_xform.clip = clip; -
2391 d->image_filler_xform.initTexture(&img, s->intOpacity, QTextureData::Plain, toAlignedRect_positive(sr)); -
2392 if (!d->image_filler_xform.blend) -
2393 return; -
2394 d->image_filler_xform.setupMatrix(copy, s->flags.bilinear); -
2395 -
2396 if (!s->flags.antialiased && s->matrix.type() == QTransform::TxScale) { -
2397 QRectF rr = s->matrix.mapRect(r); -
2398 -
2399 const int x1 = qRound(rr.x()); -
2400 const int y1 = qRound(rr.y()); -
2401 const int x2 = qRound(rr.right()); -
2402 const int y2 = qRound(rr.bottom()); -
2403 -
2404 fillRect_normalized(QRect(x1, y1, x2-x1, y2-y1), &d->image_filler_xform, d); -
2405 return; -
2406 } -
2407 -
2408#ifdef QT_FAST_SPANS -
2409 ensureRasterState(); -
2410 if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) { -
2411 d->initializeRasterizer(&d->image_filler_xform); -
2412 d->rasterizer->setAntialiased(s->flags.antialiased); -
2413 d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); -
2414 -
2415 const QPointF offs = s->flags.legacy_rounding ? QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta) : QPointF(); -
2416 -
2417 const QRectF &rect = r.normalized(); -
2418 const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs; -
2419 const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs; -
2420 -
2421 if (s->flags.tx_noshear) -
2422 d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width()); -
2423 else -
2424 d->rasterizer->rasterizeLine(a, b, qAbs((s->matrix.m22() * rect.height()) / (s->matrix.m11() * rect.width()))); -
2425 return; -
2426 } -
2427#endif -
2428 const qreal offs = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0); -
2429 QPainterPath path; -
2430 path.addRect(r); -
2431 QTransform m = s->matrix; -
2432 s->matrix = QTransform(m.m11(), m.m12(), m.m13(), -
2433 m.m21(), m.m22(), m.m23(), -
2434 m.m31() - offs, m.m32() - offs, m.m33()); -
2435 fillPath(path, &d->image_filler_xform); -
2436 s->matrix = m; -
2437 } else { -
2438 if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { -
2439 SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; -
2440 if (func) { -
2441 QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); -
2442 if (!clip) { -
2443 d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect()); -
2444 return; -
2445 } else if (clip->hasRectClip) { -
2446 d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect()); -
2447 return; -
2448 } -
2449 } -
2450 } -
2451 -
2452 d->image_filler.clip = clip; -
2453 d->image_filler.initTexture(&img, s->intOpacity, QTextureData::Plain, toAlignedRect_positive(sr)); -
2454 if (!d->image_filler.blend) -
2455 return; -
2456 d->image_filler.dx = -(r.x() + s->matrix.dx()) + sr.x(); -
2457 d->image_filler.dy = -(r.y() + s->matrix.dy()) + sr.y(); -
2458 -
2459 QRectF rr = r; -
2460 rr.translate(s->matrix.dx(), s->matrix.dy()); -
2461 -
2462 const int x1 = qRound(rr.x()); -
2463 const int y1 = qRound(rr.y()); -
2464 const int x2 = qRound(rr.right()); -
2465 const int y2 = qRound(rr.bottom()); -
2466 -
2467 fillRect_normalized(QRect(x1, y1, x2-x1, y2-y1), &d->image_filler, d); -
2468 } -
2469} -
2470 -
2471/*! -
2472 \reimp -
2473*/ -
2474void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sr) -
2475{ -
2476#ifdef QT_DEBUG_DRAW -
2477 qDebug() << " - QRasterPaintEngine::drawTiledPixmap(), r=" << r << "pixmap=" << pixmap.size(); -
2478#endif -
2479 Q_D(QRasterPaintEngine); -
2480 QRasterPaintEngineState *s = state(); -
2481 -
2482 QImage image; -
2483 -
2484 QPlatformPixmap *pd = pixmap.handle(); -
2485 if (pd->classId() == QPlatformPixmap::RasterClass) { -
2486 image = static_cast<QRasterPlatformPixmap *>(pd)->image; -
2487 } else { -
2488 image = pixmap.toImage(); -
2489 } -
2490 -
2491 if (image.depth() == 1) -
2492 image = d->rasterBuffer->colorizeBitmap(image, s->pen.color()); -
2493 -
2494 if (s->matrix.type() > QTransform::TxTranslate) { -
2495 QTransform copy = s->matrix; -
2496 copy.translate(r.x(), r.y()); -
2497 copy.translate(-sr.x(), -sr.y()); -
2498 d->image_filler_xform.clip = d->clip(); -
2499 d->image_filler_xform.initTexture(&image, s->intOpacity, QTextureData::Tiled); -
2500 if (!d->image_filler_xform.blend) -
2501 return; -
2502 d->image_filler_xform.setupMatrix(copy, s->flags.bilinear); -
2503 -
2504#ifdef QT_FAST_SPANS -
2505 ensureRasterState(); -
2506 if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) { -
2507 d->initializeRasterizer(&d->image_filler_xform); -
2508 d->rasterizer->setAntialiased(s->flags.antialiased); -
2509 d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); -
2510 -
2511 const QRectF &rect = r.normalized(); -
2512 const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); -
2513 const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f); -
2514 if (s->flags.tx_noshear) -
2515 d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width()); -
2516 else -
2517 d->rasterizer->rasterizeLine(a, b, qAbs((s->matrix.m22() * rect.height()) / (s->matrix.m11() * rect.width()))); -
2518 return; -
2519 } -
2520#endif -
2521 QPainterPath path; -
2522 path.addRect(r); -
2523 fillPath(path, &d->image_filler_xform); -
2524 } else { -
2525 d->image_filler.clip = d->clip(); -
2526 -
2527 d->image_filler.initTexture(&image, s->intOpacity, QTextureData::Tiled); -
2528 if (!d->image_filler.blend) -
2529 return; -
2530 d->image_filler.dx = -(r.x() + s->matrix.dx()) + sr.x(); -
2531 d->image_filler.dy = -(r.y() + s->matrix.dy()) + sr.y(); -
2532 -
2533 QRectF rr = r; -
2534 rr.translate(s->matrix.dx(), s->matrix.dy()); -
2535 fillRect_normalized(rr.toRect().normalized(), &d->image_filler, d); -
2536 } -
2537} -
2538 -
2539 -
2540//QWS hack -
2541static inline bool monoVal(const uchar* s, int x) -
2542{ -
2543 return (s[x>>3] << (x&7)) & 0x80; -
2544} -
2545 -
2546/*! -
2547 \internal -
2548 */ -
2549QRasterBuffer *QRasterPaintEngine::rasterBuffer() -
2550{ -
2551 Q_D(QRasterPaintEngine); -
2552 return d->rasterBuffer.data(); -
2553} -
2554 -
2555/*! -
2556 \internal -
2557*/ -
2558void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h) -
2559{ -
2560 Q_D(QRasterPaintEngine); -
2561 QRasterPaintEngineState *s = state(); -
2562 -
2563 if (!s->penData.blend) -
2564 return; -
2565 -
2566 QRasterBuffer *rb = d->rasterBuffer.data(); -
2567 -
2568 const QRect rect(rx, ry, w, h); -
2569 const QClipData *clip = d->clip(); -
2570 bool unclipped = false; -
2571 if (clip) { -
2572 // inlined QRect::intersects -
2573 const bool intersects = qMax(clip->xmin, rect.left()) <= qMin(clip->xmax - 1, rect.right()) -
2574 && qMax(clip->ymin, rect.top()) <= qMin(clip->ymax - 1, rect.bottom()); -
2575 -
2576 if (clip->hasRectClip) { -
2577 unclipped = rx > clip->xmin -
2578 && rx + w < clip->xmax -
2579 && ry > clip->ymin -
2580 && ry + h < clip->ymax; -
2581 } -
2582 -
2583 if (!intersects) -
2584 return; -
2585 } else { -
2586 // inlined QRect::intersects -
2587 const bool intersects = qMax(0, rect.left()) <= qMin(rb->width() - 1, rect.right()) -
2588 && qMax(0, rect.top()) <= qMin(rb->height() - 1, rect.bottom()); -
2589 if (!intersects) -
2590 return; -
2591 -
2592 // inlined QRect::contains -
2593 const bool contains = rect.left() >= 0 && rect.right() < rb->width() -
2594 && rect.top() >= 0 && rect.bottom() < rb->height(); -
2595 -
2596 unclipped = contains && d->isUnclipped_normalized(rect); -
2597 } -
2598 -
2599 ProcessSpans blend = unclipped ? s->penData.unclipped_blend : s->penData.blend; -
2600 const uchar * scanline = static_cast<const uchar *>(src); -
2601 -
2602 if (s->flags.fast_text) { -
2603 if (unclipped) { -
2604 if (depth == 1) { -
2605 if (s->penData.bitmapBlit) { -
2606 s->penData.bitmapBlit(rb, rx, ry, s->penData.solid.color, -
2607 scanline, w, h, bpl); -
2608 return; -
2609 } -
2610 } else if (depth == 8) { -
2611 if (s->penData.alphamapBlit) { -
2612 s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color, -
2613 scanline, w, h, bpl, 0); -
2614 return; -
2615 } -
2616 } else if (depth == 32) { -
2617 // (A)RGB Alpha mask where the alpha component is not used. -
2618 if (s->penData.alphaRGBBlit) { -
2619 s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color, -
2620 (const uint *) scanline, w, h, bpl / 4, 0); -
2621 return; -
2622 } -
2623 } -
2624 } else if (d->deviceDepth == 32 && (depth == 8 || depth == 32)) { -
2625 // (A)RGB Alpha mask where the alpha component is not used. -
2626 if (!clip) { -
2627 int nx = qMax(0, rx); -
2628 int ny = qMax(0, ry); -
2629 -
2630 // Move scanline pointer to compensate for moved x and y -
2631 int xdiff = nx - rx; -
2632 int ydiff = ny - ry; -
2633 scanline += ydiff * bpl; -
2634 scanline += xdiff * (depth == 32 ? 4 : 1); -
2635 -
2636 w -= xdiff; -
2637 h -= ydiff; -
2638 -
2639 if (nx + w > d->rasterBuffer->width()) -
2640 w = d->rasterBuffer->width() - nx; -
2641 if (ny + h > d->rasterBuffer->height()) -
2642 h = d->rasterBuffer->height() - ny; -
2643 -
2644 rx = nx; -
2645 ry = ny; -
2646 } -
2647 if (depth == 8 && s->penData.alphamapBlit) { -
2648 s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color, -
2649 scanline, w, h, bpl, clip); -
2650 } else if (depth == 32 && s->penData.alphaRGBBlit) { -
2651 s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color, -
2652 (const uint *) scanline, w, h, bpl / 4, clip); -
2653 } -
2654 return; -
2655 } -
2656 } -
2657 -
2658 int x0 = 0; -
2659 if (rx < 0) { -
2660 x0 = -rx; -
2661 w -= x0; -
2662 } -
2663 -
2664 int y0 = 0; -
2665 if (ry < 0) { -
2666 y0 = -ry; -
2667 scanline += bpl * y0; -
2668 h -= y0; -
2669 } -
2670 -
2671 w = qMin(w, rb->width() - qMax(0, rx)); -
2672 h = qMin(h, rb->height() - qMax(0, ry)); -
2673 -
2674 if (w <= 0 || h <= 0) -
2675 return; -
2676 -
2677 const int NSPANS = 256; -
2678 QSpan spans[NSPANS]; -
2679 int current = 0; -
2680 -
2681 const int x1 = x0 + w; -
2682 const int y1 = y0 + h; -
2683 -
2684 if (depth == 1) { -
2685 for (int y = y0; y < y1; ++y) { -
2686 for (int x = x0; x < x1; ) { -
2687 if (!monoVal(scanline, x)) { -
2688 ++x; -
2689 continue; -
2690 } -
2691 -
2692 if (current == NSPANS) { -
2693 blend(current, spans, &s->penData); -
2694 current = 0; -
2695 } -
2696 spans[current].x = x + rx; -
2697 spans[current].y = y + ry; -
2698 spans[current].coverage = 255; -
2699 int len = 1; -
2700 ++x; -
2701 // extend span until we find a different one. -
2702 while (x < x1 && monoVal(scanline, x)) { -
2703 ++x; -
2704 ++len; -
2705 } -
2706 spans[current].len = len; -
2707 ++current; -
2708 } -
2709 scanline += bpl; -
2710 } -
2711 } else if (depth == 8) { -
2712 for (int y = y0; y < y1; ++y) { -
2713 for (int x = x0; x < x1; ) { -
2714 // Skip those with 0 coverage -
2715 if (scanline[x] == 0) { -
2716 ++x; -
2717 continue; -
2718 } -
2719 -
2720 if (current == NSPANS) { -
2721 blend(current, spans, &s->penData); -
2722 current = 0; -
2723 } -
2724 int coverage = scanline[x]; -
2725 spans[current].x = x + rx; -
2726 spans[current].y = y + ry; -
2727 spans[current].coverage = coverage; -
2728 int len = 1; -
2729 ++x; -
2730 -
2731 // extend span until we find a different one. -
2732 while (x < x1 && scanline[x] == coverage) { -
2733 ++x; -
2734 ++len; -
2735 } -
2736 spans[current].len = len; -
2737 ++current; -
2738 } -
2739 scanline += bpl; -
2740 } -
2741 } else { // 32-bit alpha... -
2742 uint *sl = (uint *) src; -
2743 for (int y = y0; y < y1; ++y) { -
2744 for (int x = x0; x < x1; ) { -
2745 // Skip those with 0 coverage -
2746 if ((sl[x] & 0x00ffffff) == 0) { -
2747 ++x; -
2748 continue; -
2749 } -
2750 -
2751 if (current == NSPANS) { -
2752 blend(current, spans, &s->penData); -
2753 current = 0; -
2754 } -
2755 uint rgbCoverage = sl[x]; -
2756 int coverage = qGreen(rgbCoverage); -
2757 spans[current].x = x + rx; -
2758 spans[current].y = y + ry; -
2759 spans[current].coverage = coverage; -
2760 int len = 1; -
2761 ++x; -
2762 -
2763 // extend span until we find a different one. -
2764 while (x < x1 && sl[x] == rgbCoverage) { -
2765 ++x; -
2766 ++len; -
2767 } -
2768 spans[current].len = len; -
2769 ++current; -
2770 } -
2771 sl += bpl / sizeof(uint); -
2772 } -
2773 } -
2774// qDebug() << "alphaPenBlt: num spans=" << current -
2775// << "span:" << spans->x << spans->y << spans->len << spans->coverage; -
2776 // Call span func for current set of spans. -
2777 if (current != 0) -
2778 blend(current, spans, &s->penData); -
2779} -
2780 -
2781/*! -
2782 \internal -
2783*/ -
2784bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, -
2785 const QFixedPoint *positions, QFontEngine *fontEngine) -
2786{ -
2787 Q_D(QRasterPaintEngine); -
2788 QRasterPaintEngineState *s = state(); -
2789 -
2790 if (fontEngine->hasInternalCaching()) { -
2791 QFontEngine::GlyphFormat neededFormat = -
2792 painter()->device()->devType() == QInternal::Widget -
2793 ? QFontEngine::Format_None -
2794 : QFontEngine::Format_A8; -
2795 -
2796 if (d_func()->mono_surface) // alphaPenBlt can handle mono, too -
2797 neededFormat = QFontEngine::Format_Mono; -
2798 -
2799 for (int i = 0; i < numGlyphs; i++) { -
2800 QFixed spp = fontEngine->subPixelPositionForX(positions[i].x); -
2801 -
2802 QPoint offset; -
2803 QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, -
2804 &offset); -
2805 if (alphaMap == 0 || alphaMap->isNull()) -
2806 continue; -
2807 -
2808 alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(), -
2809 qFloor(positions[i].x) + offset.x(), -
2810 qRound(positions[i].y) + offset.y(), -
2811 alphaMap->width(), alphaMap->height()); -
2812 -
2813 fontEngine->unlockAlphaMapForGlyph(); -
2814 } -
2815 -
2816 } else { -
2817 QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType; -
2818 -
2819 QImageTextureGlyphCache *cache = -
2820 static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix)); -
2821 if (!cache) { -
2822 cache = new QImageTextureGlyphCache(glyphType, s->matrix); -
2823 fontEngine->setGlyphCache(0, cache); -
2824 } -
2825 -
2826 cache->populate(fontEngine, numGlyphs, glyphs, positions); -
2827 cache->fillInPendingGlyphs(); -
2828 -
2829 const QImage &image = cache->image(); -
2830 int bpl = image.bytesPerLine(); -
2831 -
2832 int depth = image.depth(); -
2833 int rightShift = 0; -
2834 int leftShift = 0; -
2835 if (depth == 32) -
2836 leftShift = 2; // multiply by 4 -
2837 else if (depth == 1) -
2838 rightShift = 3; // divide by 8 -
2839 -
2840 int margin = fontEngine->glyphMargin(glyphType); -
2841 const uchar *bits = image.bits(); -
2842 for (int i=0; i<numGlyphs; ++i) { -
2843 -
2844 QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x); -
2845 QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition); -
2846 const QTextureGlyphCache::Coord &c = cache->coords[glyph]; -
2847 if (c.isNull()) -
2848 continue; -
2849 -
2850 int x = qFloor(positions[i].x) + c.baseLineX - margin; -
2851 int y = qRound(positions[i].y) - c.baseLineY - margin; -
2852 -
2853 // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", -
2854 // c.x, c.y, -
2855 // c.w, c.h, -
2856 // c.baseLineX, c.baseLineY, -
2857 // glyphs[i], -
2858 // x, y, -
2859 // positions[i].x.toInt(), positions[i].y.toInt()); -
2860 -
2861 alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h); -
2862 } -
2863 } -
2864 return true; -
2865} -
2866 -
2867 -
2868/*! -
2869 * Returns true if the rectangle is completely within the current clip -
2870 * state of the paint engine. -
2871 */ -
2872bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const -
2873{ -
2874 const QClipData *cl = clip(); -
2875 if (!cl) { -
2876 // inline contains() for performance (we know the rects are normalized) -
2877 const QRect &r1 = deviceRect; -
2878 return (r.left() >= r1.left() && r.right() <= r1.right() -
2879 && r.top() >= r1.top() && r.bottom() <= r1.bottom()); -
2880 } -
2881 -
2882 -
2883 if (cl->hasRectClip) { -
2884 // currently all painting functions clips to deviceRect internally -
2885 if (cl->clipRect == deviceRect) -
2886 return true; -
2887 -
2888 // inline contains() for performance (we know the rects are normalized) -
2889 const QRect &r1 = cl->clipRect; -
2890 return (r.left() >= r1.left() && r.right() <= r1.right() -
2891 && r.top() >= r1.top() && r.bottom() <= r1.bottom()); -
2892 } else { -
2893 return qt_region_strictContains(cl->clipRegion, r); -
2894 } -
2895} -
2896 -
2897bool QRasterPaintEnginePrivate::isUnclipped(const QRect &rect, -
2898 int penWidth) const -
2899{ -
2900 Q_Q(const QRasterPaintEngine); -
2901 const QRasterPaintEngineState *s = q->state(); -
2902 const QClipData *cl = clip(); -
2903 if (!cl) { -
2904 QRect r = rect.normalized(); -
2905 // inline contains() for performance (we know the rects are normalized) -
2906 const QRect &r1 = deviceRect; -
2907 return (r.left() >= r1.left() && r.right() <= r1.right() -
2908 && r.top() >= r1.top() && r.bottom() <= r1.bottom()); -
2909 } -
2910 -
2911 -
2912 // currently all painting functions that call this function clip to deviceRect internally -
2913 if (cl->hasRectClip && cl->clipRect == deviceRect) -
2914 return true; -
2915 -
2916 if (s->flags.antialiased) -
2917 ++penWidth; -
2918 -
2919 QRect r = rect.normalized(); -
2920 if (penWidth > 0) { -
2921 r.setX(r.x() - penWidth); -
2922 r.setY(r.y() - penWidth); -
2923 r.setWidth(r.width() + 2 * penWidth); -
2924 r.setHeight(r.height() + 2 * penWidth); -
2925 } -
2926 -
2927 if (cl->hasRectClip) { -
2928 // inline contains() for performance (we know the rects are normalized) -
2929 const QRect &r1 = cl->clipRect; -
2930 return (r.left() >= r1.left() && r.right() <= r1.right() -
2931 && r.top() >= r1.top() && r.bottom() <= r1.bottom()); -
2932 } else { -
2933 return qt_region_strictContains(cl->clipRegion, r); -
2934 } -
2935} -
2936 -
2937inline bool QRasterPaintEnginePrivate::isUnclipped(const QRectF &rect, -
2938 int penWidth) const -
2939{ -
2940 return isUnclipped(rect.normalized().toAlignedRect(), penWidth); -
2941} -
2942 -
2943inline ProcessSpans -
2944QRasterPaintEnginePrivate::getBrushFunc(const QRect &rect, -
2945 const QSpanData *data) const -
2946{ -
2947 return isUnclipped(rect, 0) ? data->unclipped_blend : data->blend; -
2948} -
2949 -
2950inline ProcessSpans -
2951QRasterPaintEnginePrivate::getBrushFunc(const QRectF &rect, -
2952 const QSpanData *data) const -
2953{ -
2954 return isUnclipped(rect, 0) ? data->unclipped_blend : data->blend; -
2955} -
2956 -
2957inline ProcessSpans -
2958QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect, -
2959 const QSpanData *data) const -
2960{ -
2961 Q_Q(const QRasterPaintEngine); -
2962 const QRasterPaintEngineState *s = q->state(); -
2963 -
2964 if (!s->flags.fast_pen && s->matrix.type() > QTransform::TxTranslate) -
2965 return data->blend; -
2966 const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF()); -
2967 return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend; -
2968} -
2969 -
2970static QPair<int, int> visibleGlyphRange(const QRectF &clip, QFontEngine *fontEngine, -
2971 glyph_t *glyphs, QFixedPoint *positions, int numGlyphs) -
2972{ -
2973 QFixed clipLeft = QFixed::fromReal(clip.left()); -
2974 QFixed clipRight = QFixed::fromReal(clip.right()); -
2975 QFixed clipTop = QFixed::fromReal(clip.top()); -
2976 QFixed clipBottom = QFixed::fromReal(clip.bottom()); -
2977 -
2978 int first = 0; -
2979 while (first < numGlyphs) { -
2980 glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[first]); -
2981 QFixed left = metrics.x + positions[first].x; -
2982 QFixed top = metrics.y + positions[first].y; -
2983 QFixed right = left + metrics.width; -
2984 QFixed bottom = top + metrics.height; -
2985 if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop) -
2986 break; -
2987 ++first; -
2988 } -
2989 int last = numGlyphs - 1; -
2990 while (last > first) { -
2991 glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[last]); -
2992 QFixed left = metrics.x + positions[last].x; -
2993 QFixed top = metrics.y + positions[last].y; -
2994 QFixed right = left + metrics.width; -
2995 QFixed bottom = top + metrics.height; -
2996 if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop) -
2997 break; -
2998 --last; -
2999 } -
3000 return QPair<int, int>(first, last + 1); -
3001} -
3002 -
3003/*! -
3004 \reimp -
3005*/ -
3006void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) -
3007{ -
3008 if (textItem->numGlyphs == 0) -
3009 return; -
3010 -
3011 ensurePen(); -
3012 ensureRasterState(); -
3013 -
3014 QFontEngine *fontEngine = textItem->fontEngine(); -
3015 if (!supportsTransformations(fontEngine)) { -
3016 drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions, -
3017 fontEngine); -
3018 } else if (state()->matrix.type() < QTransform::TxProject) { -
3019 bool invertible; -
3020 QTransform invMat = state()->matrix.inverted(&invertible); -
3021 if (!invertible) -
3022 return; -
3023 -
3024 QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()), -
3025 textItem->fontEngine(), textItem->glyphs, -
3026 textItem->glyphPositions, textItem->numGlyphs); -
3027 QStaticTextItem copy = *textItem; -
3028 copy.glyphs += range.first; -
3029 copy.glyphPositions += range.first; -
3030 copy.numGlyphs = range.second - range.first; -
3031 QPaintEngineEx::drawStaticTextItem(&copy); -
3032 } else { -
3033 QPaintEngineEx::drawStaticTextItem(textItem); -
3034 } -
3035} -
3036 -
3037/*! -
3038 \reimp -
3039*/ -
3040void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) -
3041{ -
3042 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); -
3043 -
3044#ifdef QT_DEBUG_DRAW -
3045 Q_D(QRasterPaintEngine); -
3046 fprintf(stderr," - QRasterPaintEngine::drawTextItem(), (%.2f,%.2f), string=%s ct=%d\n", -
3047 p.x(), p.y(), QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data(), -
3048 d->glyphCacheType); -
3049#endif -
3050 -
3051 if (ti.glyphs.numGlyphs == 0) -
3052 return; -
3053 ensurePen(); -
3054 ensureRasterState(); -
3055 -
3056 QRasterPaintEngineState *s = state(); -
3057 QTransform matrix = s->matrix; -
3058 -
3059 if (!supportsTransformations(ti.fontEngine)) { -
3060 QVarLengthArray<QFixedPoint> positions; -
3061 QVarLengthArray<glyph_t> glyphs; -
3062 -
3063 matrix.translate(p.x(), p.y()); -
3064 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); -
3065 -
3066 drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine); -
3067 } else if (matrix.type() < QTransform::TxProject) { -
3068 bool invertible; -
3069 QTransform invMat = matrix.inverted(&invertible); -
3070 if (!invertible) -
3071 return; -
3072 -
3073 QVarLengthArray<QFixedPoint> positions; -
3074 QVarLengthArray<glyph_t> glyphs; -
3075 -
3076 ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform::fromTranslate(p.x(), p.y()), -
3077 ti.flags, glyphs, positions); -
3078 QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()), -
3079 ti.fontEngine, glyphs.data(), positions.data(), -
3080 glyphs.size()); -
3081 -
3082 if (range.first >= range.second) -
3083 return; -
3084 -
3085 QStaticTextItem staticTextItem; -
3086 staticTextItem.color = s->pen.color(); -
3087 staticTextItem.font = s->font; -
3088 staticTextItem.setFontEngine(ti.fontEngine); -
3089 staticTextItem.numGlyphs = range.second - range.first; -
3090 staticTextItem.glyphs = glyphs.data() + range.first; -
3091 staticTextItem.glyphPositions = positions.data() + range.first; -
3092 QPaintEngineEx::drawStaticTextItem(&staticTextItem); -
3093 } else { -
3094 QPaintEngineEx::drawTextItem(p, ti); -
3095 } -
3096} -
3097 -
3098/*! -
3099 \reimp -
3100*/ -
3101void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount) -
3102{ -
3103 Q_D(QRasterPaintEngine);
never executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
3104 QRasterPaintEngineState *s = state();
never executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
3105 -
3106 ensurePen();
never executed (the execution status of this line is deduced): ensurePen();
-
3107 if (!s->penData.blend)
never evaluated: !s->penData.blend
0
3108 return;
never executed: return;
0
3109 -
3110 if (!s->flags.fast_pen) {
never evaluated: !s->flags.fast_pen
0
3111 QPaintEngineEx::drawPoints(points, pointCount);
never executed (the execution status of this line is deduced): QPaintEngineEx::drawPoints(points, pointCount);
-
3112 return;
never executed: return;
0
3113 } -
3114 -
3115 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
never executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
3116 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
never executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
3117 stroker.drawPoints(points, pointCount);
never executed (the execution status of this line is deduced): stroker.drawPoints(points, pointCount);
-
3118}
never executed: }
0
3119 -
3120 -
3121void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount) -
3122{ -
3123 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
3124 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
3125 -
3126 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
3127 if (!s->penData.blend)
partially evaluated: !s->penData.blend
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:136
0-136
3128 return;
never executed: return;
0
3129 -
3130 if (!s->flags.fast_pen) {
evaluated: !s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:135
1-135
3131 QPaintEngineEx::drawPoints(points, pointCount);
executed (the execution status of this line is deduced): QPaintEngineEx::drawPoints(points, pointCount);
-
3132 return;
executed: return;
Execution Count:1
1
3133 } -
3134 -
3135 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
3136 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
3137 stroker.drawPoints(points, pointCount);
executed (the execution status of this line is deduced): stroker.drawPoints(points, pointCount);
-
3138}
executed: }
Execution Count:135
135
3139 -
3140/*! -
3141 \reimp -
3142*/ -
3143void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) -
3144{ -
3145#ifdef QT_DEBUG_DRAW -
3146 qDebug() << " - QRasterPaintEngine::drawLines(QLine*)" << lineCount; -
3147#endif -
3148 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
3149 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
3150 -
3151 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
3152 if (!s->penData.blend)
evaluated: !s->penData.blend
TRUEFALSE
yes
Evaluation Count:48
yes
Evaluation Count:4988
48-4988
3153 return;
executed: return;
Execution Count:48
48
3154 -
3155 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:4933
yes
Evaluation Count:55
55-4933
3156 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
3157 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
3158 for (int i=0; i<lineCount; ++i) {
evaluated: i<lineCount
TRUEFALSE
yes
Evaluation Count:4933
yes
Evaluation Count:4933
4933
3159 const QLine &l = lines[i];
executed (the execution status of this line is deduced): const QLine &l = lines[i];
-
3160 stroker.drawLine(l.p1(), l.p2());
executed (the execution status of this line is deduced): stroker.drawLine(l.p1(), l.p2());
-
3161 }
executed: }
Execution Count:4933
4933
3162 } else {
executed: }
Execution Count:4933
4933
3163 QPaintEngineEx::drawLines(lines, lineCount);
executed (the execution status of this line is deduced): QPaintEngineEx::drawLines(lines, lineCount);
-
3164 }
executed: }
Execution Count:55
55
3165} -
3166 -
3167void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line, -
3168 qreal width, -
3169 int *dashIndex, -
3170 qreal *dashOffset, -
3171 bool *inDash) -
3172{ -
3173 Q_Q(QRasterPaintEngine); -
3174 QRasterPaintEngineState *s = q->state(); -
3175 -
3176 const QPen &pen = s->lastPen; -
3177 const bool squareCap = (pen.capStyle() == Qt::SquareCap); -
3178 const QVector<qreal> pattern = pen.dashPattern(); -
3179 -
3180 qreal patternLength = 0; -
3181 for (int i = 0; i < pattern.size(); ++i) -
3182 patternLength += pattern.at(i); -
3183 -
3184 if (patternLength <= 0) -
3185 return; -
3186 -
3187 qreal length = line.length(); -
3188 Q_ASSERT(length > 0); -
3189 while (length > 0) { -
3190 const bool rasterize = *inDash; -
3191 qreal dash = (pattern.at(*dashIndex) - *dashOffset) * width; -
3192 QLineF l = line; -
3193 -
3194 if (dash >= length) { -
3195 dash = length; -
3196 *dashOffset += dash / width; -
3197 length = 0; -
3198 } else { -
3199 *dashOffset = 0; -
3200 *inDash = !(*inDash); -
3201 if (++*dashIndex >= pattern.size()) -
3202 *dashIndex = 0; -
3203 length -= dash; -
3204 l.setLength(dash); -
3205 line.setP1(l.p2()); -
3206 } -
3207 -
3208 if (rasterize && dash > 0) -
3209 rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap); -
3210 } -
3211} -
3212 -
3213/*! -
3214 \reimp -
3215*/ -
3216void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) -
3217{ -
3218#ifdef QT_DEBUG_DRAW -
3219 qDebug() << " - QRasterPaintEngine::drawLines(QLineF *)" << lineCount; -
3220#endif -
3221 Q_D(QRasterPaintEngine);
executed (the execution status of this line is deduced): QRasterPaintEnginePrivate * const d = d_func();
-
3222 QRasterPaintEngineState *s = state();
executed (the execution status of this line is deduced): QRasterPaintEngineState *s = state();
-
3223 -
3224 ensurePen();
executed (the execution status of this line is deduced): ensurePen();
-
3225 if (!s->penData.blend)
evaluated: !s->penData.blend
TRUEFALSE
yes
Evaluation Count:48
yes
Evaluation Count:1925
48-1925
3226 return;
executed: return;
Execution Count:48
48
3227 if (s->flags.fast_pen) {
evaluated: s->flags.fast_pen
TRUEFALSE
yes
Evaluation Count:1106
yes
Evaluation Count:819
819-1106
3228 QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
executed (the execution status of this line is deduced): QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
-
3229 stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
executed (the execution status of this line is deduced): stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
-
3230 for (int i=0; i<lineCount; ++i) {
evaluated: i<lineCount
TRUEFALSE
yes
Evaluation Count:1595
yes
Evaluation Count:1106
1106-1595
3231 QLineF line = lines[i];
executed (the execution status of this line is deduced): QLineF line = lines[i];
-
3232 stroker.drawLine(line.p1(), line.p2());
executed (the execution status of this line is deduced): stroker.drawLine(line.p1(), line.p2());
-
3233 }
executed: }
Execution Count:1595
1595
3234 } else {
executed: }
Execution Count:1106
1106
3235 QPaintEngineEx::drawLines(lines, lineCount);
executed (the execution status of this line is deduced): QPaintEngineEx::drawLines(lines, lineCount);
-
3236 }
executed: }
Execution Count:819
819
3237} -
3238 -
3239 -
3240/*! -
3241 \reimp -
3242*/ -
3243void QRasterPaintEngine::drawEllipse(const QRectF &rect) -
3244{ -
3245 Q_D(QRasterPaintEngine); -
3246 QRasterPaintEngineState *s = state(); -
3247 -
3248 ensurePen(); -
3249 if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen) -
3250 || (qpen_style(s->lastPen) == Qt::NoPen)) -
3251 && !s->flags.antialiased -
3252 && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT -
3253 && !rect.isEmpty() -
3254 && s->matrix.type() <= QTransform::TxScale) // no shear -
3255 { -
3256 ensureBrush(); -
3257 const QRectF r = s->matrix.mapRect(rect); -
3258 ProcessSpans penBlend = d->getPenFunc(r, &s->penData); -
3259 ProcessSpans brushBlend = d->getBrushFunc(r, &s->brushData); -
3260 const QRect brect = QRect(int(r.x()), int(r.y()), -
3261 int_dim(r.x(), r.width()), -
3262 int_dim(r.y(), r.height())); -
3263 if (brect == r) { -
3264 drawEllipse_midpoint_i(brect, d->deviceRect, penBlend, brushBlend, -
3265 &s->penData, &s->brushData); -
3266 return; -
3267 } -
3268 } -
3269 QPaintEngineEx::drawEllipse(rect); -
3270} -
3271 -
3272 -
3273#ifdef Q_OS_WIN -
3274/*! -
3275 \internal -
3276*/ -
3277void QRasterPaintEngine::setDC(HDC hdc) { -
3278 Q_D(QRasterPaintEngine); -
3279 d->hdc = hdc; -
3280} -
3281 -
3282/*! -
3283 \internal -
3284*/ -
3285HDC QRasterPaintEngine::getDC() const -
3286{ -
3287 Q_D(const QRasterPaintEngine); -
3288 return d->hdc; -
3289} -
3290 -
3291/*! -
3292 \internal -
3293*/ -
3294void QRasterPaintEngine::releaseDC(HDC) const -
3295{ -
3296} -
3297 -
3298#endif -
3299 -
3300/*! -
3301 \internal -
3302*/ -
3303bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine) const -
3304{ -
3305 const QTransform &m = state()->matrix; -
3306 return supportsTransformations(fontEngine, m); -
3307} -
3308 -
3309/*! -
3310 \internal -
3311*/ -
3312bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const -
3313{ -
3314 if (fontEngine->supportsTransformations(m)) -
3315 return true; -
3316 -
3317 return !shouldDrawCachedGlyphs(fontEngine, m); -
3318} -
3319 -
3320/*! -
3321 \internal -
3322*/ -
3323QPoint QRasterPaintEngine::coordinateOffset() const -
3324{ -
3325 return QPoint(0, 0); -
3326} -
3327 -
3328void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fg) -
3329{ -
3330 Q_ASSERT(fg); -
3331 if (!fg->blend) -
3332 return; -
3333 Q_D(QRasterPaintEngine); -
3334 -
3335 Q_ASSERT(image.depth() == 1); -
3336 -
3337 const int spanCount = 256; -
3338 QT_FT_Span spans[spanCount]; -
3339 int n = 0; -
3340 -
3341 // Boundaries -
3342 int w = image.width(); -
3343 int h = image.height(); -
3344 int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height()); -
3345 int ymin = qMax(qRound(pos.y()), 0); -
3346 int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width()); -
3347 int xmin = qMax(qRound(pos.x()), 0); -
3348 -
3349 int x_offset = xmin - qRound(pos.x()); -
3350 -
3351 QImage::Format format = image.format(); -
3352 for (int y = ymin; y < ymax; ++y) { -
3353 const uchar *src = image.scanLine(y - qRound(pos.y())); -
3354 if (format == QImage::Format_MonoLSB) { -
3355 for (int x = 0; x < xmax - xmin; ++x) { -
3356 int src_x = x + x_offset; -
3357 uchar pixel = src[src_x >> 3]; -
3358 if (!pixel) { -
3359 x += 7 - (src_x%8); -
3360 continue; -
3361 } -
3362 if (pixel & (0x1 << (src_x & 7))) { -
3363 spans[n].x = xmin + x; -
3364 spans[n].y = y; -
3365 spans[n].coverage = 255; -
3366 int len = 1; -
3367 while (src_x+1 < w && src[(src_x+1) >> 3] & (0x1 << ((src_x+1) & 7))) { -
3368 ++src_x; -
3369 ++len; -
3370 } -
3371 spans[n].len = ((len + spans[n].x) > xmax) ? (xmax - spans[n].x) : len; -
3372 x += len; -
3373 ++n; -
3374 if (n == spanCount) { -
3375 fg->blend(n, spans, fg); -
3376 n = 0; -
3377 } -
3378 } -
3379 } -
3380 } else { -
3381 for (int x = 0; x < xmax - xmin; ++x) { -
3382 int src_x = x + x_offset; -
3383 uchar pixel = src[src_x >> 3]; -
3384 if (!pixel) { -
3385 x += 7 - (src_x%8); -
3386 continue; -
3387 } -
3388 if (pixel & (0x80 >> (x & 7))) { -
3389 spans[n].x = xmin + x; -
3390 spans[n].y = y; -
3391 spans[n].coverage = 255; -
3392 int len = 1; -
3393 while (src_x+1 < w && src[(src_x+1) >> 3] & (0x80 >> ((src_x+1) & 7))) { -
3394 ++src_x; -
3395 ++len; -
3396 } -
3397 spans[n].len = ((len + spans[n].x) > xmax) ? (xmax - spans[n].x) : len; -
3398 x += len; -
3399 ++n; -
3400 if (n == spanCount) { -
3401 fg->blend(n, spans, fg); -
3402 n = 0; -
3403 } -
3404 } -
3405 } -
3406 } -
3407 } -
3408 if (n) { -
3409 fg->blend(n, spans, fg); -
3410 n = 0; -
3411 } -
3412} -
3413 -
3414/*! -
3415 \enum QRasterPaintEngine::ClipType -
3416 \internal -
3417 -
3418 \value RectClip Indicates that the currently set clip is a single rectangle. -
3419 \value ComplexClip Indicates that the currently set clip is a combination of several shapes. -
3420*/ -
3421 -
3422/*! -
3423 \internal -
3424 Returns the type of the clip currently set. -
3425*/ -
3426QRasterPaintEngine::ClipType QRasterPaintEngine::clipType() const -
3427{ -
3428 Q_D(const QRasterPaintEngine); -
3429 -
3430 const QClipData *clip = d->clip(); -
3431 if (!clip || clip->hasRectClip) -
3432 return RectClip; -
3433 else -
3434 return ComplexClip; -
3435} -
3436 -
3437/*! -
3438 \internal -
3439 Returns the bounding rect of the currently set clip. -
3440*/ -
3441QRect QRasterPaintEngine::clipBoundingRect() const -
3442{ -
3443 Q_D(const QRasterPaintEngine); -
3444 -
3445 const QClipData *clip = d->clip(); -
3446 -
3447 if (!clip) -
3448 return d->deviceRect; -
3449 -
3450 if (clip->hasRectClip) -
3451 return clip->clipRect; -
3452 -
3453 return QRect(clip->xmin, clip->ymin, clip->xmax - clip->xmin, clip->ymax - clip->ymin); -
3454} -
3455 -
3456void QRasterPaintEnginePrivate::initializeRasterizer(QSpanData *data) -
3457{ -
3458 Q_Q(QRasterPaintEngine); -
3459 QRasterPaintEngineState *s = q->state(); -
3460 -
3461 rasterizer->setAntialiased(s->flags.antialiased); -
3462 rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); -
3463 -
3464 QRect clipRect(deviceRect); -
3465 ProcessSpans blend; -
3466 // ### get from optimized rectbased QClipData -
3467 -
3468 const QClipData *c = clip(); -
3469 if (c) { -
3470 const QRect r(QPoint(c->xmin, c->ymin), -
3471 QSize(c->xmax - c->xmin, c->ymax - c->ymin)); -
3472 clipRect = clipRect.intersected(r); -
3473 blend = data->blend; -
3474 } else { -
3475 blend = data->unclipped_blend; -
3476 } -
3477 -
3478 rasterizer->setClipRect(clipRect); -
3479 rasterizer->initialize(blend, data); -
3480} -
3481 -
3482void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, -
3483 ProcessSpans callback, -
3484 QSpanData *spanData, QRasterBuffer *rasterBuffer) -
3485{ -
3486 if (!callback || !outline) -
3487 return; -
3488 -
3489 Q_Q(QRasterPaintEngine); -
3490 QRasterPaintEngineState *s = q->state(); -
3491 -
3492 if (!s->flags.antialiased) { -
3493 initializeRasterizer(spanData); -
3494 -
3495 const Qt::FillRule fillRule = outline->flags == QT_FT_OUTLINE_NONE -
3496 ? Qt::WindingFill -
3497 : Qt::OddEvenFill; -
3498 -
3499 rasterizer->rasterize(outline, fillRule); -
3500 return; -
3501 } -
3502 -
3503 rasterize(outline, callback, (void *)spanData, rasterBuffer); -
3504} -
3505 -
3506extern "C" { -
3507 int q_gray_rendered_spans(QT_FT_Raster raster); -
3508} -
3509 -
3510static inline uchar *alignAddress(uchar *address, quintptr alignmentMask) -
3511{ -
3512 return (uchar *)(((quintptr)address + alignmentMask) & ~alignmentMask); -
3513} -
3514 -
3515void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, -
3516 ProcessSpans callback, -
3517 void *userData, QRasterBuffer *) -
3518{ -
3519 if (!callback || !outline) -
3520 return; -
3521 -
3522 Q_Q(QRasterPaintEngine); -
3523 QRasterPaintEngineState *s = q->state(); -
3524 -
3525 if (!s->flags.antialiased) { -
3526 rasterizer->setAntialiased(s->flags.antialiased); -
3527 rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); -
3528 rasterizer->setClipRect(deviceRect); -
3529 rasterizer->initialize(callback, userData); -
3530 -
3531 const Qt::FillRule fillRule = outline->flags == QT_FT_OUTLINE_NONE -
3532 ? Qt::WindingFill -
3533 : Qt::OddEvenFill; -
3534 -
3535 rasterizer->rasterize(outline, fillRule); -
3536 return; -
3537 } -
3538 -
3539 // Initial size for raster pool is MINIMUM_POOL_SIZE so as to -
3540 // minimize memory reallocations. However if initial size for -
3541 // raster pool is changed for lower value, reallocations will -
3542 // occur normally. -
3543 int rasterPoolSize = MINIMUM_POOL_SIZE; -
3544 uchar rasterPoolOnStack[MINIMUM_POOL_SIZE + 0xf]; -
3545 uchar *rasterPoolBase = alignAddress(rasterPoolOnStack, 0xf); -
3546 uchar *rasterPoolOnHeap = 0; -
3547 -
3548 qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); -
3549 -
3550 void *data = userData; -
3551 -
3552 QT_FT_BBox clip_box = { deviceRect.x(), -
3553 deviceRect.y(), -
3554 deviceRect.x() + deviceRect.width(), -
3555 deviceRect.y() + deviceRect.height() }; -
3556 -
3557 QT_FT_Raster_Params rasterParams; -
3558 rasterParams.target = 0; -
3559 rasterParams.source = outline; -
3560 rasterParams.flags = QT_FT_RASTER_FLAG_CLIP; -
3561 rasterParams.gray_spans = 0; -
3562 rasterParams.black_spans = 0; -
3563 rasterParams.bit_test = 0; -
3564 rasterParams.bit_set = 0; -
3565 rasterParams.user = data; -
3566 rasterParams.clip_box = clip_box; -
3567 -
3568 bool done = false; -
3569 int error; -
3570 -
3571 int rendered_spans = 0; -
3572 -
3573 while (!done) { -
3574 -
3575 rasterParams.flags |= (QT_FT_RASTER_FLAG_AA | QT_FT_RASTER_FLAG_DIRECT); -
3576 rasterParams.gray_spans = callback; -
3577 rasterParams.skip_spans = rendered_spans; -
3578 error = qt_ft_grays_raster.raster_render(*grayRaster.data(), &rasterParams); -
3579 -
3580 // Out of memory, reallocate some more and try again... -
3581 if (error == -6) { // ErrRaster_OutOfMemory from qgrayraster.c -
3582 rasterPoolSize *= 2; -
3583 if (rasterPoolSize > 1024 * 1024) { -
3584 qWarning("QPainter: Rasterization of primitive failed"); -
3585 break; -
3586 } -
3587 -
3588 rendered_spans += q_gray_rendered_spans(*grayRaster.data()); -
3589 -
3590 free(rasterPoolOnHeap); -
3591 rasterPoolOnHeap = (uchar *)malloc(rasterPoolSize + 0xf); -
3592 -
3593 Q_CHECK_PTR(rasterPoolOnHeap); // note: we just freed the old rasterPoolBase. I hope it's not fatal. -
3594 -
3595 rasterPoolBase = alignAddress(rasterPoolOnHeap, 0xf); -
3596 -
3597 qt_ft_grays_raster.raster_done(*grayRaster.data()); -
3598 qt_ft_grays_raster.raster_new(grayRaster.data()); -
3599 qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); -
3600 } else { -
3601 done = true; -
3602 } -
3603 } -
3604 -
3605 free(rasterPoolOnHeap); -
3606} -
3607 -
3608void QRasterPaintEnginePrivate::recalculateFastImages() -
3609{ -
3610 Q_Q(QRasterPaintEngine); -
3611 QRasterPaintEngineState *s = q->state(); -
3612 -
3613 s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform) -
3614 && s->matrix.type() <= QTransform::TxShear; -
3615} -
3616 -
3617bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const -
3618{ -
3619 Q_Q(const QRasterPaintEngine); -
3620 const QRasterPaintEngineState *s = q->state(); -
3621 -
3622 return s->flags.fast_images -
3623 && (mode == QPainter::CompositionMode_SourceOver -
3624 || (mode == QPainter::CompositionMode_Source -
3625 && !image.hasAlphaChannel())); -
3626} -
3627 -
3628QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) -
3629{ -
3630 Q_ASSERT(image.depth() == 1); -
3631 -
3632 QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB); -
3633 QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied); -
3634 -
3635 QRgb fg = PREMUL(color.rgba()); -
3636 QRgb bg = 0; -
3637 -
3638 int height = sourceImage.height(); -
3639 int width = sourceImage.width(); -
3640 for (int y=0; y<height; ++y) { -
3641 uchar *source = sourceImage.scanLine(y); -
3642 QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y)); -
3643 if (!source || !target) -
3644 QT_THROW(std::bad_alloc()); // we must have run out of memory -
3645 for (int x=0; x < width; ++x) -
3646 target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg; -
3647 } -
3648 return dest; -
3649} -
3650 -
3651QRasterBuffer::~QRasterBuffer() -
3652{ -
3653} -
3654 -
3655void QRasterBuffer::init() -
3656{ -
3657 compositionMode = QPainter::CompositionMode_SourceOver; -
3658 monoDestinationWithClut = false; -
3659 destColor0 = 0; -
3660 destColor1 = 0; -
3661} -
3662 -
3663QImage::Format QRasterBuffer::prepare(QImage *image) -
3664{ -
3665 m_buffer = (uchar *)image->bits(); -
3666 m_width = qMin(QT_RASTER_COORD_LIMIT, image->width()); -
3667 m_height = qMin(QT_RASTER_COORD_LIMIT, image->height()); -
3668 bytes_per_pixel = image->depth()/8; -
3669 bytes_per_line = image->bytesPerLine(); -
3670 -
3671 format = image->format(); -
3672 drawHelper = qDrawHelper + format; -
3673 if (image->depth() == 1 && image->colorTable().size() == 2) { -
3674 monoDestinationWithClut = true; -
3675 destColor0 = PREMUL(image->colorTable()[0]); -
3676 destColor1 = PREMUL(image->colorTable()[1]); -
3677 } -
3678 -
3679 return format; -
3680} -
3681 -
3682void QRasterBuffer::resetBuffer(int val) -
3683{ -
3684 memset(m_buffer, val, m_height*bytes_per_line); -
3685} -
3686 -
3687QClipData::QClipData(int height) -
3688{ -
3689 clipSpanHeight = height; -
3690 m_clipLines = 0; -
3691 -
3692 allocated = 0; -
3693 m_spans = 0; -
3694 xmin = xmax = ymin = ymax = 0; -
3695 count = 0; -
3696 -
3697 enabled = true; -
3698 hasRectClip = hasRegionClip = false; -
3699} -
3700 -
3701QClipData::~QClipData() -
3702{ -
3703 if (m_clipLines) -
3704 free(m_clipLines); -
3705 if (m_spans) -
3706 free(m_spans); -
3707} -
3708 -
3709void QClipData::initialize() -
3710{ -
3711 if (m_spans) -
3712 return; -
3713 -
3714 if (!m_clipLines) -
3715 m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); -
3716 -
3717 Q_CHECK_PTR(m_clipLines); -
3718 QT_TRY { -
3719 m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); -
3720 allocated = clipSpanHeight; -
3721 Q_CHECK_PTR(m_spans); -
3722 -
3723 QT_TRY { -
3724 if (hasRectClip) { -
3725 int y = 0; -
3726 while (y < ymin) { -
3727 m_clipLines[y].spans = 0; -
3728 m_clipLines[y].count = 0; -
3729 ++y; -
3730 } -
3731 -
3732 const int len = clipRect.width(); -
3733 count = 0; -
3734 while (y < ymax) { -
3735 QSpan *span = m_spans + count; -
3736 span->x = xmin; -
3737 span->len = len; -
3738 span->y = y; -
3739 span->coverage = 255; -
3740 ++count; -
3741 -
3742 m_clipLines[y].spans = span; -
3743 m_clipLines[y].count = 1; -
3744 ++y; -
3745 } -
3746 -
3747 while (y < clipSpanHeight) { -
3748 m_clipLines[y].spans = 0; -
3749 m_clipLines[y].count = 0; -
3750 ++y; -
3751 } -
3752 } else if (hasRegionClip) { -
3753 -
3754 const QVector<QRect> rects = clipRegion.rects(); -
3755 const int numRects = rects.size(); -
3756 -
3757 { // resize -
3758 const int maxSpans = (ymax - ymin) * numRects; -
3759 if (maxSpans > allocated) { -
3760 m_spans = q_check_ptr((QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan))); -
3761 allocated = maxSpans; -
3762 } -
3763 } -
3764 -
3765 int y = 0; -
3766 int firstInBand = 0; -
3767 count = 0; -
3768 while (firstInBand < numRects) { -
3769 const int currMinY = rects.at(firstInBand).y(); -
3770 const int currMaxY = currMinY + rects.at(firstInBand).height(); -
3771 -
3772 while (y < currMinY) { -
3773 m_clipLines[y].spans = 0; -
3774 m_clipLines[y].count = 0; -
3775 ++y; -
3776 } -
3777 -
3778 int lastInBand = firstInBand; -
3779 while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y) -
3780 ++lastInBand; -
3781 -
3782 while (y < currMaxY) { -
3783 -
3784 m_clipLines[y].spans = m_spans + count; -
3785 m_clipLines[y].count = lastInBand - firstInBand + 1; -
3786 -
3787 for (int r = firstInBand; r <= lastInBand; ++r) { -
3788 const QRect &currRect = rects.at(r); -
3789 QSpan *span = m_spans + count; -
3790 span->x = currRect.x(); -
3791 span->len = currRect.width(); -
3792 span->y = y; -
3793 span->coverage = 255; -
3794 ++count; -
3795 } -
3796 ++y; -
3797 } -
3798 -
3799 firstInBand = lastInBand + 1; -
3800 } -
3801 -
3802 Q_ASSERT(count <= allocated); -
3803 -
3804 while (y < clipSpanHeight) { -
3805 m_clipLines[y].spans = 0; -
3806 m_clipLines[y].count = 0; -
3807 ++y; -
3808 } -
3809 -
3810 } -
3811 } QT_CATCH(...) { -
3812 free(m_spans); // have to free m_spans again or someone might think that we were successfully initialized. -
3813 m_spans = 0; -
3814 QT_RETHROW; -
3815 } -
3816 } QT_CATCH(...) { -
3817 free(m_clipLines); // same for clipLines -
3818 m_clipLines = 0; -
3819 QT_RETHROW; -
3820 } -
3821} -
3822 -
3823void QClipData::fixup() -
3824{ -
3825 Q_ASSERT(m_spans); -
3826 -
3827 if (count == 0) { -
3828 ymin = ymax = xmin = xmax = 0; -
3829 return; -
3830 } -
3831 -
3832 int y = -1; -
3833 ymin = m_spans[0].y; -
3834 ymax = m_spans[count-1].y + 1; -
3835 xmin = INT_MAX; -
3836 xmax = 0; -
3837 -
3838 const int firstLeft = m_spans[0].x; -
3839 const int firstRight = m_spans[0].x + m_spans[0].len; -
3840 bool isRect = true; -
3841 -
3842 for (int i = 0; i < count; ++i) { -
3843 QT_FT_Span_& span = m_spans[i]; -
3844 -
3845 if (span.y != y) { -
3846 if (span.y != y + 1 && y != -1) -
3847 isRect = false; -
3848 y = span.y; -
3849 m_clipLines[y].spans = &span; -
3850 m_clipLines[y].count = 1; -
3851 } else -
3852 ++m_clipLines[y].count; -
3853 -
3854 const int spanLeft = span.x; -
3855 const int spanRight = spanLeft + span.len; -
3856 -
3857 if (spanLeft < xmin) -
3858 xmin = spanLeft; -
3859 -
3860 if (spanRight > xmax) -
3861 xmax = spanRight; -
3862 -
3863 if (spanLeft != firstLeft || spanRight != firstRight) -
3864 isRect = false; -
3865 } -
3866 -
3867 if (isRect) { -
3868 hasRectClip = true; -
3869 clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin); -
3870 } -
3871} -
3872 -
3873/* -
3874 Convert \a rect to clip spans. -
3875 */ -
3876void QClipData::setClipRect(const QRect &rect) -
3877{ -
3878 if (hasRectClip && rect == clipRect) -
3879 return; -
3880 -
3881// qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect; -
3882 hasRectClip = true; -
3883 hasRegionClip = false; -
3884 clipRect = rect; -
3885 -
3886 xmin = rect.x(); -
3887 xmax = rect.x() + rect.width(); -
3888 ymin = qMin(rect.y(), clipSpanHeight); -
3889 ymax = qMin(rect.y() + rect.height(), clipSpanHeight); -
3890 -
3891 if (m_spans) { -
3892 free(m_spans); -
3893 m_spans = 0; -
3894 } -
3895 -
3896// qDebug() << xmin << xmax << ymin << ymax; -
3897} -
3898 -
3899/* -
3900 Convert \a region to clip spans. -
3901 */ -
3902void QClipData::setClipRegion(const QRegion &region) -
3903{ -
3904 if (region.rectCount() == 1) { -
3905 setClipRect(region.rects().at(0)); -
3906 return; -
3907 } -
3908 -
3909 hasRegionClip = true; -
3910 hasRectClip = false; -
3911 clipRegion = region; -
3912 -
3913 { // set bounding rect -
3914 const QRect rect = region.boundingRect(); -
3915 xmin = rect.x(); -
3916 xmax = rect.x() + rect.width(); -
3917 ymin = rect.y(); -
3918 ymax = rect.y() + rect.height(); -
3919 } -
3920 -
3921 if (m_spans) { -
3922 free(m_spans); -
3923 m_spans = 0; -
3924 } -
3925 -
3926} -
3927 -
3928/*! -
3929 \internal -
3930 spans must be sorted on y -
3931*/ -
3932static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip, -
3933 const QSpan *spans, const QSpan *end, -
3934 QSpan **outSpans, int available) -
3935{ -
3936 const_cast<QClipData *>(clip)->initialize(); -
3937 -
3938 QSpan *out = *outSpans; -
3939 -
3940 const QSpan *clipSpans = clip->m_spans + *currentClip; -
3941 const QSpan *clipEnd = clip->m_spans + clip->count; -
3942 -
3943 while (available && spans < end ) { -
3944 if (clipSpans >= clipEnd) { -
3945 spans = end; -
3946 break; -
3947 } -
3948 if (clipSpans->y > spans->y) { -
3949 ++spans; -
3950 continue; -
3951 } -
3952 if (spans->y != clipSpans->y) { -
3953 if (spans->y < clip->count && clip->m_clipLines[spans->y].spans) -
3954 clipSpans = clip->m_clipLines[spans->y].spans; -
3955 else -
3956 ++clipSpans; -
3957 continue; -
3958 } -
3959 Q_ASSERT(spans->y == clipSpans->y); -
3960 -
3961 int sx1 = spans->x; -
3962 int sx2 = sx1 + spans->len; -
3963 int cx1 = clipSpans->x; -
3964 int cx2 = cx1 + clipSpans->len; -
3965 -
3966 if (cx1 < sx1 && cx2 < sx1) { -
3967 ++clipSpans; -
3968 continue; -
3969 } else if (sx1 < cx1 && sx2 < cx1) { -
3970 ++spans; -
3971 continue; -
3972 } -
3973 int x = qMax(sx1, cx1); -
3974 int len = qMin(sx2, cx2) - x; -
3975 if (len) { -
3976 out->x = qMax(sx1, cx1); -
3977 out->len = qMin(sx2, cx2) - out->x; -
3978 out->y = spans->y; -
3979 out->coverage = qt_div_255(spans->coverage * clipSpans->coverage); -
3980 ++out; -
3981 --available; -
3982 } -
3983 if (sx2 < cx2) { -
3984 ++spans; -
3985 } else { -
3986 ++clipSpans; -
3987 } -
3988 } -
3989 -
3990 *outSpans = out; -
3991 *currentClip = clipSpans - clip->m_spans; -
3992 return spans; -
3993} -
3994 -
3995static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userData) -
3996{ -
3997// qDebug() << "qt_span_fill_clipped" << spanCount; -
3998 QSpanData *fillData = reinterpret_cast<QSpanData *>(userData); -
3999 -
4000 Q_ASSERT(fillData->blend && fillData->unclipped_blend); -
4001 -
4002 const int NSPANS = 256; -
4003 QSpan cspans[NSPANS]; -
4004 int currentClip = 0; -
4005 const QSpan *end = spans + spanCount; -
4006 while (spans < end) { -
4007 QSpan *clipped = cspans; -
4008 spans = qt_intersect_spans(fillData->clip, &currentClip, spans, end, &clipped, NSPANS); -
4009// qDebug() << "processed " << spanCount - (end - spans) << "clipped" << clipped-cspans -
4010// << "span:" << cspans->x << cspans->y << cspans->len << spans->coverage; -
4011 -
4012 if (clipped - cspans) -
4013 fillData->unclipped_blend(clipped - cspans, cspans, fillData); -
4014 } -
4015} -
4016 -
4017/* -
4018 \internal -
4019 Clip spans to \a{clip}-rectangle. -
4020 Returns number of unclipped spans -
4021*/ -
4022static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, -
4023 const QRect &clip) -
4024{ -
4025 const short minx = clip.left(); -
4026 const short miny = clip.top(); -
4027 const short maxx = clip.right(); -
4028 const short maxy = clip.bottom(); -
4029 -
4030 int n = 0; -
4031 for (int i = 0; i < numSpans; ++i) { -
4032 if (spans[i].y > maxy) -
4033 break; -
4034 if (spans[i].y < miny -
4035 || spans[i].x > maxx -
4036 || spans[i].x + spans[i].len <= minx) { -
4037 continue; -
4038 } -
4039 if (spans[i].x < minx) { -
4040 spans[n].len = qMin(spans[i].len - (minx - spans[i].x), maxx - minx + 1); -
4041 spans[n].x = minx; -
4042 } else { -
4043 spans[n].x = spans[i].x; -
4044 spans[n].len = qMin(spans[i].len, ushort(maxx - spans[n].x + 1)); -
4045 } -
4046 if (spans[n].len == 0) -
4047 continue; -
4048 spans[n].y = spans[i].y; -
4049 spans[n].coverage = spans[i].coverage; -
4050 ++n; -
4051 } -
4052 return n; -
4053} -
4054 -
4055 -
4056static void qt_span_fill_clipRect(int count, const QSpan *spans, -
4057 void *userData) -
4058{ -
4059 QSpanData *fillData = reinterpret_cast<QSpanData *>(userData); -
4060 Q_ASSERT(fillData->blend && fillData->unclipped_blend); -
4061 -
4062 Q_ASSERT(fillData->clip); -
4063 Q_ASSERT(!fillData->clip->clipRect.isEmpty()); -
4064 -
4065 // hw: check if this const_cast<> is safe!!! -
4066 count = qt_intersect_spans(const_cast<QSpan*>(spans), count, -
4067 fillData->clip->clipRect); -
4068 if (count > 0) -
4069 fillData->unclipped_blend(count, spans, fillData); -
4070} -
4071 -
4072static void qt_span_clip(int count, const QSpan *spans, void *userData) -
4073{ -
4074 ClipData *clipData = reinterpret_cast<ClipData *>(userData); -
4075 -
4076// qDebug() << " qt_span_clip: " << count << clipData->operation; -
4077// for (int i = 0; i < qMin(count, 10); ++i) { -
4078// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage; -
4079// } -
4080 -
4081 switch (clipData->operation) { -
4082 -
4083 case Qt::IntersectClip: -
4084 { -
4085 QClipData *newClip = clipData->newClip; -
4086 newClip->initialize(); -
4087 -
4088 int currentClip = 0; -
4089 const QSpan *end = spans + count; -
4090 while (spans < end) { -
4091 QSpan *newspans = newClip->m_spans + newClip->count; -
4092 spans = qt_intersect_spans(clipData->oldClip, &currentClip, spans, end, -
4093 &newspans, newClip->allocated - newClip->count); -
4094 newClip->count = newspans - newClip->m_spans; -
4095 if (spans < end) { -
4096 newClip->m_spans = q_check_ptr((QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan))); -
4097 newClip->allocated *= 2; -
4098 } -
4099 } -
4100 } -
4101 break; -
4102 -
4103 case Qt::ReplaceClip: -
4104 clipData->newClip->appendSpans(spans, count); -
4105 break; -
4106 case Qt::NoClip: -
4107 break; -
4108 } -
4109} -
4110 -
4111#ifndef QT_NO_DEBUG -
4112QImage QRasterBuffer::bufferImage() const -
4113{ -
4114 QImage image(m_width, m_height, QImage::Format_ARGB32_Premultiplied); -
4115 -
4116 for (int y = 0; y < m_height; ++y) { -
4117 uint *span = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y); -
4118 -
4119 for (int x=0; x<m_width; ++x) { -
4120 uint argb = span[x]; -
4121 image.setPixel(x, y, argb); -
4122 } -
4123 } -
4124 return image; -
4125} -
4126#endif -
4127 -
4128 -
4129void QRasterBuffer::flushToARGBImage(QImage *target) const -
4130{ -
4131 int w = qMin(m_width, target->width()); -
4132 int h = qMin(m_height, target->height()); -
4133 -
4134 for (int y=0; y<h; ++y) { -
4135 uint *sourceLine = (uint *)const_cast<QRasterBuffer *>(this)->scanLine(y); -
4136 QRgb *dest = (QRgb *) target->scanLine(y); -
4137 for (int x=0; x<w; ++x) { -
4138 QRgb pixel = sourceLine[x]; -
4139 int alpha = qAlpha(pixel); -
4140 if (!alpha) { -
4141 dest[x] = 0; -
4142 } else { -
4143 dest[x] = (alpha << 24) -
4144 | ((255*qRed(pixel)/alpha) << 16) -
4145 | ((255*qGreen(pixel)/alpha) << 8) -
4146 | ((255*qBlue(pixel)/alpha) << 0); -
4147 } -
4148 } -
4149 } -
4150} -
4151 -
4152 -
4153class QGradientCache -
4154{ -
4155 struct CacheInfo -
4156 { -
4157 inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : -
4158 stops(s), opacity(op), interpolationMode(mode) {} -
4159 uint buffer[GRADIENT_STOPTABLE_SIZE]; -
4160 QGradientStops stops; -
4161 int opacity; -
4162 QGradient::InterpolationMode interpolationMode; -
4163 }; -
4164 -
4165 typedef QMultiHash<quint64, CacheInfo> QGradientColorTableHash; -
4166 -
4167public: -
4168 inline const uint *getBuffer(const QGradient &gradient, int opacity) { -
4169 quint64 hash_val = 0; -
4170 -
4171 QGradientStops stops = gradient.stops(); -
4172 for (int i = 0; i < stops.size() && i <= 2; i++) -
4173 hash_val += stops[i].second.rgba(); -
4174 -
4175 QMutexLocker lock(&mutex); -
4176 QGradientColorTableHash::const_iterator it = cache.constFind(hash_val); -
4177 -
4178 if (it == cache.constEnd()) -
4179 return addCacheElement(hash_val, gradient, opacity); -
4180 else { -
4181 do { -
4182 const CacheInfo &cache_info = it.value(); -
4183 if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) -
4184 return cache_info.buffer; -
4185 ++it; -
4186 } while (it != cache.constEnd() && it.key() == hash_val); -
4187 // an exact match for these stops and opacity was not found, create new cache -
4188 return addCacheElement(hash_val, gradient, opacity); -
4189 } -
4190 } -
4191 -
4192 inline int paletteSize() const { return GRADIENT_STOPTABLE_SIZE; } -
4193protected: -
4194 inline int maxCacheSize() const { return 60; } -
4195 inline void generateGradientColorTable(const QGradient& g, -
4196 uint *colorTable, -
4197 int size, int opacity) const; -
4198 uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { -
4199 if (cache.size() == maxCacheSize()) { -
4200 // may remove more than 1, but OK -
4201 cache.erase(cache.begin() + (qrand() % maxCacheSize())); -
4202 } -
4203 CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); -
4204 generateGradientColorTable(gradient, cache_entry.buffer, paletteSize(), opacity); -
4205 return cache.insert(hash_val, cache_entry).value().buffer; -
4206 } -
4207 -
4208 QGradientColorTableHash cache; -
4209 QMutex mutex; -
4210}; -
4211 -
4212void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const -
4213{ -
4214 QGradientStops stops = gradient.stops(); -
4215 int stopCount = stops.count(); -
4216 Q_ASSERT(stopCount > 0); -
4217 -
4218 bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); -
4219 -
4220 if (stopCount == 2) { -
4221 uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); -
4222 uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity); -
4223 -
4224 qreal first_stop = stops[0].first; -
4225 qreal second_stop = stops[1].first; -
4226 -
4227 if (second_stop < first_stop) { -
4228 qSwap(first_color, second_color); -
4229 qSwap(first_stop, second_stop); -
4230 } -
4231 -
4232 if (colorInterpolation) { -
4233 first_color = PREMUL(first_color); -
4234 second_color = PREMUL(second_color); -
4235 } -
4236 -
4237 int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); -
4238 int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1)); -
4239 -
4240 uint red_first = qRed(first_color) << 16; -
4241 uint green_first = qGreen(first_color) << 16; -
4242 uint blue_first = qBlue(first_color) << 16; -
4243 uint alpha_first = qAlpha(first_color) << 16; -
4244 -
4245 uint red_second = qRed(second_color) << 16; -
4246 uint green_second = qGreen(second_color) << 16; -
4247 uint blue_second = qBlue(second_color) << 16; -
4248 uint alpha_second = qAlpha(second_color) << 16; -
4249 -
4250 int i = 0; -
4251 for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) { -
4252 if (colorInterpolation) -
4253 colorTable[i] = first_color; -
4254 else -
4255 colorTable[i] = PREMUL(first_color); -
4256 } -
4257 -
4258 if (i < second_index) { -
4259 qreal reciprocal = qreal(1) / (second_index - first_index); -
4260 -
4261 int red_delta = qRound(int(red_second - red_first) * reciprocal); -
4262 int green_delta = qRound(int(green_second - green_first) * reciprocal); -
4263 int blue_delta = qRound(int(blue_second - blue_first) * reciprocal); -
4264 int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal); -
4265 -
4266 // rounding -
4267 red_first += 1 << 15; -
4268 green_first += 1 << 15; -
4269 blue_first += 1 << 15; -
4270 alpha_first += 1 << 15; -
4271 -
4272 for (; i < qMin(GRADIENT_STOPTABLE_SIZE, second_index); ++i) { -
4273 red_first += red_delta; -
4274 green_first += green_delta; -
4275 blue_first += blue_delta; -
4276 alpha_first += alpha_delta; -
4277 -
4278 const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000) -
4279 | ((green_first >> 8) & 0xff00) | (blue_first >> 16); -
4280 -
4281 if (colorInterpolation) -
4282 colorTable[i] = color; -
4283 else -
4284 colorTable[i] = PREMUL(color); -
4285 } -
4286 } -
4287 -
4288 for (; i < GRADIENT_STOPTABLE_SIZE; ++i) { -
4289 if (colorInterpolation) -
4290 colorTable[i] = second_color; -
4291 else -
4292 colorTable[i] = PREMUL(second_color); -
4293 } -
4294 -
4295 return; -
4296 } -
4297 -
4298 uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); -
4299 if (stopCount == 1) { -
4300 current_color = PREMUL(current_color); -
4301 for (int i = 0; i < size; ++i) -
4302 colorTable[i] = current_color; -
4303 return; -
4304 } -
4305 -
4306 // The position where the gradient begins and ends -
4307 qreal begin_pos = stops[0].first; -
4308 qreal end_pos = stops[stopCount-1].first; -
4309 -
4310 int pos = 0; // The position in the color table. -
4311 uint next_color; -
4312 -
4313 qreal incr = 1 / qreal(size); // the double increment. -
4314 qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) -
4315 -
4316 // Up to first point -
4317 colorTable[pos++] = PREMUL(current_color); -
4318 while (dpos <= begin_pos) { -
4319 colorTable[pos] = colorTable[pos - 1]; -
4320 ++pos; -
4321 dpos += incr; -
4322 } -
4323 -
4324 int current_stop = 0; // We always interpolate between current and current + 1. -
4325 -
4326 qreal t; // position between current left and right stops -
4327 qreal t_delta; // the t increment per entry in the color table -
4328 -
4329 if (dpos < end_pos) { -
4330 // Gradient area -
4331 while (dpos > stops[current_stop+1].first) -
4332 ++current_stop; -
4333 -
4334 if (current_stop != 0) -
4335 current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); -
4336 next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); -
4337 -
4338 if (colorInterpolation) { -
4339 current_color = PREMUL(current_color); -
4340 next_color = PREMUL(next_color); -
4341 } -
4342 -
4343 qreal diff = stops[current_stop+1].first - stops[current_stop].first; -
4344 qreal c = (diff == 0) ? qreal(0) : 256 / diff; -
4345 t = (dpos - stops[current_stop].first) * c; -
4346 t_delta = incr * c; -
4347 -
4348 while (true) { -
4349 Q_ASSERT(current_stop < stopCount); -
4350 -
4351 int dist = qRound(t); -
4352 int idist = 256 - dist; -
4353 -
4354 if (colorInterpolation) -
4355 colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); -
4356 else -
4357 colorTable[pos] = PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); -
4358 -
4359 ++pos; -
4360 dpos += incr; -
4361 -
4362 if (dpos >= end_pos) -
4363 break; -
4364 -
4365 t += t_delta; -
4366 -
4367 int skip = 0; -
4368 while (dpos > stops[current_stop+skip+1].first) -
4369 ++skip; -
4370 -
4371 if (skip != 0) { -
4372 current_stop += skip; -
4373 if (skip == 1) -
4374 current_color = next_color; -
4375 else -
4376 current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); -
4377 next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); -
4378 -
4379 if (colorInterpolation) { -
4380 if (skip != 1) -
4381 current_color = PREMUL(current_color); -
4382 next_color = PREMUL(next_color); -
4383 } -
4384 -
4385 qreal diff = stops[current_stop+1].first - stops[current_stop].first; -
4386 qreal c = (diff == 0) ? qreal(0) : 256 / diff; -
4387 t = (dpos - stops[current_stop].first) * c; -
4388 t_delta = incr * c; -
4389 } -
4390 } -
4391 } -
4392 -
4393 // After last point -
4394 current_color = PREMUL(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); -
4395 while (pos < size - 1) { -
4396 colorTable[pos] = current_color; -
4397 ++pos; -
4398 } -
4399 -
4400 // Make sure the last color stop is represented at the end of the table -
4401 colorTable[size - 1] = current_color; -
4402} -
4403 -
4404Q_GLOBAL_STATIC(QGradientCache, qt_gradient_cache) -
4405 -
4406 -
4407void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) -
4408{ -
4409 rasterBuffer = rb; -
4410 type = None; -
4411 txop = 0; -
4412 bilinear = false; -
4413 m11 = m22 = m33 = 1.; -
4414 m12 = m13 = m21 = m23 = dx = dy = 0.0; -
4415 clip = pe ? pe->d_func()->clip() : 0; -
4416} -
4417 -
4418Q_GUI_EXPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); -
4419 -
4420void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode) -
4421{ -
4422 Qt::BrushStyle brushStyle = qbrush_style(brush); -
4423 switch (brushStyle) { -
4424 case Qt::SolidPattern: { -
4425 type = Solid; -
4426 QColor c = qbrush_color(brush); -
4427 QRgb rgba = c.rgba(); -
4428 solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha)); -
4429 if ((solid.color & 0xff000000) == 0 -
4430 && compositionMode == QPainter::CompositionMode_SourceOver) { -
4431 type = None; -
4432 } -
4433 break; -
4434 } -
4435 -
4436 case Qt::LinearGradientPattern: -
4437 { -
4438 type = LinearGradient; -
4439 const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); -
4440 gradient.alphaColor = !brush.isOpaque() || alpha != 256; -
4441 gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); -
4442 gradient.spread = g->spread(); -
4443 -
4444 QLinearGradientData &linearData = gradient.linear; -
4445 -
4446 linearData.origin.x = g->start().x(); -
4447 linearData.origin.y = g->start().y(); -
4448 linearData.end.x = g->finalStop().x(); -
4449 linearData.end.y = g->finalStop().y(); -
4450 break; -
4451 } -
4452 -
4453 case Qt::RadialGradientPattern: -
4454 { -
4455 type = RadialGradient; -
4456 const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); -
4457 gradient.alphaColor = !brush.isOpaque() || alpha != 256; -
4458 gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); -
4459 gradient.spread = g->spread(); -
4460 -
4461 QRadialGradientData &radialData = gradient.radial; -
4462 -
4463 QPointF center = g->center(); -
4464 radialData.center.x = center.x(); -
4465 radialData.center.y = center.y(); -
4466 radialData.center.radius = g->centerRadius(); -
4467 QPointF focal = g->focalPoint(); -
4468 radialData.focal.x = focal.x(); -
4469 radialData.focal.y = focal.y(); -
4470 radialData.focal.radius = g->focalRadius(); -
4471 } -
4472 break; -
4473 -
4474 case Qt::ConicalGradientPattern: -
4475 { -
4476 type = ConicalGradient; -
4477 const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); -
4478 gradient.alphaColor = !brush.isOpaque() || alpha != 256; -
4479 gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); -
4480 gradient.spread = QGradient::RepeatSpread; -
4481 -
4482 QConicalGradientData &conicalData = gradient.conical; -
4483 -
4484 QPointF center = g->center(); -
4485 conicalData.center.x = center.x(); -
4486 conicalData.center.y = center.y(); -
4487 conicalData.angle = g->angle() * 2 * Q_PI / 360.0; -
4488 } -
4489 break; -
4490 -
4491 case Qt::Dense1Pattern: -
4492 case Qt::Dense2Pattern: -
4493 case Qt::Dense3Pattern: -
4494 case Qt::Dense4Pattern: -
4495 case Qt::Dense5Pattern: -
4496 case Qt::Dense6Pattern: -
4497 case Qt::Dense7Pattern: -
4498 case Qt::HorPattern: -
4499 case Qt::VerPattern: -
4500 case Qt::CrossPattern: -
4501 case Qt::BDiagPattern: -
4502 case Qt::FDiagPattern: -
4503 case Qt::DiagCrossPattern: -
4504 type = Texture; -
4505 if (!tempImage) -
4506 tempImage = new QImage(); -
4507 *tempImage = rasterBuffer->colorizeBitmap(qt_imageForBrush(brushStyle, true), brush.color()); -
4508 initTexture(tempImage, alpha, QTextureData::Tiled); -
4509 break; -
4510 case Qt::TexturePattern: -
4511 type = Texture; -
4512 if (!tempImage) -
4513 tempImage = new QImage(); -
4514 -
4515 if (qHasPixmapTexture(brush) && brush.texture().isQBitmap()) -
4516 *tempImage = rasterBuffer->colorizeBitmap(brush.textureImage(), brush.color()); -
4517 else -
4518 *tempImage = brush.textureImage(); -
4519 initTexture(tempImage, alpha, QTextureData::Tiled, tempImage->rect()); -
4520 break; -
4521 -
4522 case Qt::NoBrush: -
4523 default: -
4524 type = None; -
4525 break; -
4526 } -
4527 adjustSpanMethods(); -
4528} -
4529 -
4530void QSpanData::adjustSpanMethods() -
4531{ -
4532 bitmapBlit = 0; -
4533 alphamapBlit = 0; -
4534 alphaRGBBlit = 0; -
4535 -
4536 fillRect = 0; -
4537 -
4538 switch(type) { -
4539 case None: -
4540 unclipped_blend = 0; -
4541 break; -
4542 case Solid: -
4543 unclipped_blend = rasterBuffer->drawHelper->blendColor; -
4544 bitmapBlit = rasterBuffer->drawHelper->bitmapBlit; -
4545 alphamapBlit = rasterBuffer->drawHelper->alphamapBlit; -
4546 alphaRGBBlit = rasterBuffer->drawHelper->alphaRGBBlit; -
4547 fillRect = rasterBuffer->drawHelper->fillRect; -
4548 break; -
4549 case LinearGradient: -
4550 case RadialGradient: -
4551 case ConicalGradient: -
4552 unclipped_blend = rasterBuffer->drawHelper->blendGradient; -
4553 break; -
4554 case Texture: -
4555 unclipped_blend = qBlendTexture; -
4556 if (!texture.imageData) -
4557 unclipped_blend = 0; -
4558 -
4559 break; -
4560 } -
4561 // setup clipping -
4562 if (!unclipped_blend) { -
4563 blend = 0; -
4564 } else if (!clip) { -
4565 blend = unclipped_blend; -
4566 } else if (clip->hasRectClip) { -
4567 blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect; -
4568 } else { -
4569 blend = qt_span_fill_clipped; -
4570 } -
4571} -
4572 -
4573void QSpanData::setupMatrix(const QTransform &matrix, int bilin) -
4574{ -
4575 QTransform delta; -
4576 // make sure we round off correctly in qdrawhelper.cpp -
4577 delta.translate(1.0 / 65536, 1.0 / 65536); -
4578 -
4579 QTransform inv = (delta * matrix).inverted(); -
4580 m11 = inv.m11(); -
4581 m12 = inv.m12(); -
4582 m13 = inv.m13(); -
4583 m21 = inv.m21(); -
4584 m22 = inv.m22(); -
4585 m23 = inv.m23(); -
4586 m33 = inv.m33(); -
4587 dx = inv.dx(); -
4588 dy = inv.dy(); -
4589 txop = inv.type(); -
4590 bilinear = bilin; -
4591 -
4592 const bool affine = inv.isAffine(); -
4593 fast_matrix = affine -
4594 && m11 * m11 + m21 * m21 < 1e4 -
4595 && m12 * m12 + m22 * m22 < 1e4 -
4596 && qAbs(dx) < 1e4 -
4597 && qAbs(dy) < 1e4; -
4598 -
4599 adjustSpanMethods(); -
4600} -
4601 -
4602void QSpanData::initTexture(const QImage *image, int alpha, QTextureData::Type _type, const QRect &sourceRect) -
4603{ -
4604 const QImageData *d = const_cast<QImage *>(image)->data_ptr(); -
4605 if (!d || d->height == 0) { -
4606 texture.imageData = 0; -
4607 texture.width = 0; -
4608 texture.height = 0; -
4609 texture.x1 = 0; -
4610 texture.y1 = 0; -
4611 texture.x2 = 0; -
4612 texture.y2 = 0; -
4613 texture.bytesPerLine = 0; -
4614 texture.format = QImage::Format_Invalid; -
4615 texture.colorTable = 0; -
4616 texture.hasAlpha = alpha != 256; -
4617 } else { -
4618 texture.imageData = d->data; -
4619 texture.width = d->width; -
4620 texture.height = d->height; -
4621 -
4622 if (sourceRect.isNull()) { -
4623 texture.x1 = 0; -
4624 texture.y1 = 0; -
4625 texture.x2 = texture.width; -
4626 texture.y2 = texture.height; -
4627 } else { -
4628 texture.x1 = sourceRect.x(); -
4629 texture.y1 = sourceRect.y(); -
4630 texture.x2 = qMin(texture.x1 + sourceRect.width(), d->width); -
4631 texture.y2 = qMin(texture.y1 + sourceRect.height(), d->height); -
4632 } -
4633 -
4634 texture.bytesPerLine = d->bytes_per_line; -
4635 -
4636 texture.format = d->format; -
4637 texture.colorTable = (d->format <= QImage::Format_Indexed8 && !d->colortable.isEmpty()) ? &d->colortable : 0; -
4638 texture.hasAlpha = image->hasAlphaChannel() || alpha != 256; -
4639 } -
4640 texture.const_alpha = alpha; -
4641 texture.type = _type; -
4642 -
4643 adjustSpanMethods(); -
4644} -
4645 -
4646/*! -
4647 \internal -
4648 \a x and \a y is relative to the midpoint of \a rect. -
4649*/ -
4650static inline void drawEllipsePoints(int x, int y, int length, -
4651 const QRect &rect, -
4652 const QRect &clip, -
4653 ProcessSpans pen_func, ProcessSpans brush_func, -
4654 QSpanData *pen_data, QSpanData *brush_data) -
4655{ -
4656 if (length == 0) -
4657 return; -
4658 -
4659 QT_FT_Span outline[4]; -
4660 const int midx = rect.x() + (rect.width() + 1) / 2; -
4661 const int midy = rect.y() + (rect.height() + 1) / 2; -
4662 -
4663 x = x + midx; -
4664 y = midy - y; -
4665 -
4666 // topleft -
4667 outline[0].x = midx + (midx - x) - (length - 1) - (rect.width() & 0x1); -
4668 outline[0].len = qMin(length, x - outline[0].x); -
4669 outline[0].y = y; -
4670 outline[0].coverage = 255; -
4671 -
4672 // topright -
4673 outline[1].x = x; -
4674 outline[1].len = length; -
4675 outline[1].y = y; -
4676 outline[1].coverage = 255; -
4677 -
4678 // bottomleft -
4679 outline[2].x = outline[0].x; -
4680 outline[2].len = outline[0].len; -
4681 outline[2].y = midy + (midy - y) - (rect.height() & 0x1); -
4682 outline[2].coverage = 255; -
4683 -
4684 // bottomright -
4685 outline[3].x = x; -
4686 outline[3].len = length; -
4687 outline[3].y = outline[2].y; -
4688 outline[3].coverage = 255; -
4689 -
4690 if (brush_func && outline[0].x + outline[0].len < outline[1].x) { -
4691 QT_FT_Span fill[2]; -
4692 -
4693 // top fill -
4694 fill[0].x = outline[0].x + outline[0].len - 1; -
4695 fill[0].len = qMax(0, outline[1].x - fill[0].x); -
4696 fill[0].y = outline[1].y; -
4697 fill[0].coverage = 255; -
4698 -
4699 // bottom fill -
4700 fill[1].x = outline[2].x + outline[2].len - 1; -
4701 fill[1].len = qMax(0, outline[3].x - fill[1].x); -
4702 fill[1].y = outline[3].y; -
4703 fill[1].coverage = 255; -
4704 -
4705 int n = (fill[0].y >= fill[1].y ? 1 : 2); -
4706 n = qt_intersect_spans(fill, n, clip); -
4707 if (n > 0) -
4708 brush_func(n, fill, brush_data); -
4709 } -
4710 if (pen_func) { -
4711 int n = (outline[1].y >= outline[2].y ? 2 : 4); -
4712 n = qt_intersect_spans(outline, n, clip); -
4713 if (n > 0) -
4714 pen_func(n, outline, pen_data); -
4715 } -
4716} -
4717 -
4718/*! -
4719 \internal -
4720 Draws an ellipse using the integer point midpoint algorithm. -
4721*/ -
4722static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip, -
4723 ProcessSpans pen_func, ProcessSpans brush_func, -
4724 QSpanData *pen_data, QSpanData *brush_data) -
4725{ -
4726 const qreal a = qreal(rect.width()) / 2; -
4727 const qreal b = qreal(rect.height()) / 2; -
4728 qreal d = b*b - (a*a*b) + 0.25*a*a; -
4729 -
4730 int x = 0; -
4731 int y = (rect.height() + 1) / 2; -
4732 int startx = x; -
4733 -
4734 // region 1 -
4735 while (a*a*(2*y - 1) > 2*b*b*(x + 1)) { -
4736 if (d < 0) { // select E -
4737 d += b*b*(2*x + 3); -
4738 ++x; -
4739 } else { // select SE -
4740 d += b*b*(2*x + 3) + a*a*(-2*y + 2); -
4741 drawEllipsePoints(startx, y, x - startx + 1, rect, clip, -
4742 pen_func, brush_func, pen_data, brush_data); -
4743 startx = ++x; -
4744 --y; -
4745 } -
4746 } -
4747 drawEllipsePoints(startx, y, x - startx + 1, rect, clip, -
4748 pen_func, brush_func, pen_data, brush_data); -
4749 -
4750 // region 2 -
4751 d = b*b*(x + 0.5)*(x + 0.5) + a*a*((y - 1)*(y - 1) - b*b); -
4752 const int miny = rect.height() & 0x1; -
4753 while (y > miny) { -
4754 if (d < 0) { // select SE -
4755 d += b*b*(2*x + 2) + a*a*(-2*y + 3); -
4756 ++x; -
4757 } else { // select S -
4758 d += a*a*(-2*y + 3); -
4759 } -
4760 --y; -
4761 drawEllipsePoints(x, y, 1, rect, clip, -
4762 pen_func, brush_func, pen_data, brush_data); -
4763 } -
4764} -
4765 -
4766/*! -
4767 \fn void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount) -
4768 \overload -
4769 \reimp -
4770*/ -
4771 -
4772 -
4773#ifdef QT_DEBUG_DRAW -
4774void dumpClip(int width, int height, const QClipData *clip) -
4775{ -
4776 QImage clipImg(width, height, QImage::Format_ARGB32_Premultiplied); -
4777 clipImg.fill(0xffff0000); -
4778 -
4779 int x0 = width; -
4780 int x1 = 0; -
4781 int y0 = height; -
4782 int y1 = 0; -
4783 -
4784 ((QClipData *) clip)->spans(); // Force allocation of the spans structure... -
4785 -
4786 for (int i = 0; i < clip->count; ++i) { -
4787 const QSpan *span = ((QClipData *) clip)->spans() + i; -
4788 for (int j = 0; j < span->len; ++j) -
4789 clipImg.setPixel(span->x + j, span->y, 0xffffff00); -
4790 x0 = qMin(x0, int(span->x)); -
4791 x1 = qMax(x1, int(span->x + span->len - 1)); -
4792 -
4793 y0 = qMin(y0, int(span->y)); -
4794 y1 = qMax(y1, int(span->y)); -
4795 } -
4796 -
4797 static int counter = 0; -
4798 -
4799 Q_ASSERT(y0 >= 0); -
4800 Q_ASSERT(x0 >= 0); -
4801 Q_ASSERT(y1 >= 0); -
4802 Q_ASSERT(x1 >= 0); -
4803 -
4804 fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1); -
4805 clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++)); -
4806} -
4807#endif -
4808 -
4809 -
4810QT_END_NAMESPACE -
4811 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial