Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpaintengine_blitter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "private/qpaintengine_blitter_p.h"
6
7#include "private/qblittable_p.h"
8#include "private/qpaintengine_raster_p.h"
9#include "private/qpainter_p.h"
10#include "private/qpixmap_blitter_p.h"
11
12#ifndef QT_NO_BLITTABLE
13QT_BEGIN_NAMESPACE
14
15#define STATE_XFORM_SCALE 0x00000001
16#define STATE_XFORM_COMPLEX 0x00000002
17
18#define STATE_BRUSH_PATTERN 0x00000010
19#define STATE_BRUSH_ALPHA 0x00000020
20
21#define STATE_PEN_ENABLED 0x00000100
22
23#define STATE_ANTIALIASING 0x00001000
24#define STATE_ALPHA 0x00002000
25#define STATE_BLENDING_COMPLEX 0x00004000
26
27#define STATE_CLIPSYS_COMPLEX 0x00010000
28#define STATE_CLIP_COMPLEX 0x00020000
29
30
31class CapabilitiesToStateMask
32{
33public:
34 CapabilitiesToStateMask(QBlittable::Capabilities capabilities)
35 : m_capabilities(capabilities)
36 , fillRectMask(0)
37 , drawRectMask(0)
38 , drawPixmapMask(0)
39 , alphaFillRectMask(0)
40 , opacityPixmapMask(0)
41 , capabillitiesState(0)
42 {
43 if (capabilities & QBlittable::SolidRectCapability)
44 setFillRectMask();
45 if (capabilities & QBlittable::SourcePixmapCapability)
46 setSourcePixmapMask();
47 if (capabilities & QBlittable::SourceOverPixmapCapability)
48 setSourceOverPixmapMask();
49 if (capabilities & QBlittable::SourceOverScaledPixmapCapability)
50 setSourceOverScaledPixmapMask();
51 if (capabilities & QBlittable::AlphaFillRectCapability)
52 setAlphaFillRectMask();
53 if (capabilities & QBlittable::OpacityPixmapCapability)
54 setOpacityPixmapMask();
55 }
56
57 inline bool canBlitterFillRect() const
58 {
59 return checkStateAgainstMask(capabillitiesState, fillRectMask);
60 }
61
62 inline bool canBlitterAlphaFillRect() const
63 {
64 return checkStateAgainstMask(capabillitiesState, alphaFillRectMask);
65 }
66
67 inline bool canBlitterDrawRectMask() const
68 {
69 return checkStateAgainstMask(capabillitiesState, drawRectMask);
70 }
71
72 bool canBlitterDrawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) const
73 {
74 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
75 return false;
76 if (checkStateAgainstMask(capabillitiesState, drawPixmapMask)) {
77 if (m_capabilities & (QBlittable::SourceOverPixmapCapability
78 | QBlittable::SourceOverScaledPixmapCapability)) {
79 if (r.size() != sr.size())
80 return m_capabilities & QBlittable::SourceOverScaledPixmapCapability;
81 else
82 return m_capabilities & QBlittable::SourceOverPixmapCapability;
83 }
84 if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel())
85 return m_capabilities & QBlittable::SourcePixmapCapability;
86 }
87 return false;
88 }
89
90 bool canBlitterDrawPixmapOpacity(const QPixmap &pm) const
91 {
92 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
93 return false;
94
95 return checkStateAgainstMask(capabillitiesState, opacityPixmapMask);
96 }
97
98 bool canBlitterDrawCachedGlyphs(const QTransform &transform, QFontEngine::GlyphFormat requestedGlyphFormat, bool complexClip) const
99 {
100 if (transform.type() > QTransform::TxScale)
101 return false;
102 if (!(m_capabilities & QBlittable::DrawScaledCachedGlyphsCapability))
103 return false;
104 if (requestedGlyphFormat == QFontEngine::Format_ARGB && !(m_capabilities & QBlittable::SubPixelGlyphsCapability))
105 return false;
106 if (complexClip && !(m_capabilities & QBlittable::ComplexClipCapability))
107 return false;
108 return true;
109 }
110
111 inline void updateState(uint mask, bool on) {
112 updateStateBits(&capabillitiesState, mask, on);
113 }
114
115private:
116
117 static inline void updateStateBits(uint *state, uint mask, bool on)
118 {
119 *state = on ? (*state | mask) : (*state & ~mask);
120 }
121
122 static inline bool checkStateAgainstMask(uint state, uint mask)
123 {
124 return !state || (state & mask && !(state & ~mask));
125 }
126
127 void setFillRectMask() {
128 updateStateBits(&fillRectMask, STATE_XFORM_SCALE, false);
129 updateStateBits(&fillRectMask, STATE_XFORM_COMPLEX, false);
130
131 updateStateBits(&fillRectMask, STATE_BRUSH_PATTERN, false);
132 updateStateBits(&fillRectMask, STATE_BRUSH_ALPHA, false);
133
134 updateStateBits(&fillRectMask, STATE_PEN_ENABLED, true);
135
136 //Sub-pixel aliasing should not be sent to the blitter
137 updateStateBits(&fillRectMask, STATE_ANTIALIASING, true);
138 updateStateBits(&fillRectMask, STATE_ALPHA, false);
139 updateStateBits(&fillRectMask, STATE_BLENDING_COMPLEX, false);
140
141 updateStateBits(&fillRectMask, STATE_CLIPSYS_COMPLEX, false);
142 updateStateBits(&fillRectMask, STATE_CLIP_COMPLEX, false);
143 }
144
145 void setAlphaFillRectMask() {
146 updateStateBits(&alphaFillRectMask, STATE_XFORM_SCALE, false);
147 updateStateBits(&alphaFillRectMask, STATE_XFORM_COMPLEX, false);
148
149 updateStateBits(&alphaFillRectMask, STATE_BRUSH_PATTERN, false);
150 updateStateBits(&alphaFillRectMask, STATE_BRUSH_ALPHA, true);
151
152 updateStateBits(&alphaFillRectMask, STATE_PEN_ENABLED, true);
153
154 //Sub-pixel aliasing should not be sent to the blitter
155 updateStateBits(&alphaFillRectMask, STATE_ANTIALIASING, true);
156 updateStateBits(&alphaFillRectMask, STATE_ALPHA, false);
157 updateStateBits(&alphaFillRectMask, STATE_BLENDING_COMPLEX, false);
158
159 updateStateBits(&alphaFillRectMask, STATE_CLIPSYS_COMPLEX, false);
160 updateStateBits(&alphaFillRectMask, STATE_CLIP_COMPLEX, false);
161 }
162
163 void setSourcePixmapMask() {
164 updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, false);
165 updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false);
166
167 updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true);
168 updateStateBits(&drawPixmapMask, STATE_BRUSH_ALPHA, false);
169
170 updateStateBits(&drawPixmapMask, STATE_PEN_ENABLED, true);
171
172 updateStateBits(&drawPixmapMask, STATE_ANTIALIASING, true);
173 updateStateBits(&drawPixmapMask, STATE_ALPHA, false);
174 updateStateBits(&drawPixmapMask, STATE_BLENDING_COMPLEX, false);
175
176 updateStateBits(&drawPixmapMask, STATE_CLIPSYS_COMPLEX, false);
177 updateStateBits(&drawPixmapMask, STATE_CLIP_COMPLEX, false);
178 }
179
180 void setSourceOverPixmapMask() {
181 setSourcePixmapMask();
182 }
183
184 void setSourceOverScaledPixmapMask() {
185 setSourceOverPixmapMask();
186 updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true);
187 }
188
189 void setOpacityPixmapMask() {
190 updateStateBits(&opacityPixmapMask, STATE_XFORM_SCALE, true);
191 updateStateBits(&opacityPixmapMask, STATE_XFORM_COMPLEX, false);
192
193 updateStateBits(&opacityPixmapMask, STATE_BRUSH_PATTERN, true);
194 updateStateBits(&opacityPixmapMask, STATE_BRUSH_ALPHA, true);
195
196 updateStateBits(&opacityPixmapMask, STATE_PEN_ENABLED, true);
197
198 updateStateBits(&opacityPixmapMask, STATE_ANTIALIASING, true);
199 updateStateBits(&opacityPixmapMask, STATE_ALPHA, true);
200 updateStateBits(&opacityPixmapMask, STATE_BLENDING_COMPLEX, false);
201
202 updateStateBits(&opacityPixmapMask, STATE_CLIPSYS_COMPLEX, false);
203 updateStateBits(&opacityPixmapMask, STATE_CLIP_COMPLEX, false);
204 }
205
206 QBlittable::Capabilities m_capabilities;
207 uint fillRectMask;
208 uint drawRectMask;
209 uint drawPixmapMask;
210 uint alphaFillRectMask;
211 uint opacityPixmapMask;
212 uint capabillitiesState;
213};
214
216{
217 Q_DECLARE_PUBLIC(QBlitterPaintEngine)
218public:
226
227 void lock();
228 void unlock();
229 void fillRect(const QRectF &rect, const QColor &color, bool alpha);
230 void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr, bool opacity);
231
232
233 void updateCompleteState(QPainterState *s);
234 void updatePenState(QPainterState *s);
235 void updateBrushState(QPainterState *s);
236 void updateOpacityState(QPainterState *s);
237 void updateCompositionModeState(QPainterState *s);
238 void updateRenderHintsState(QPainterState *s);
239 void updateTransformState(QPainterState *s);
240 void updateClipState(QPainterState *s);
241
243 CapabilitiesToStateMask caps;
245};
246
247
248inline void QBlitterPaintEnginePrivate::lock()
249{
250 if (!pmData->blittable()->isLocked())
251 rasterBuffer->prepare(pmData->buffer());
252}
253
255{
256 pmData->blittable()->unlock();
257}
258
259// State tracking to make decisions
261{
262 updatePenState(s);
263 updateBrushState(s);
264 updateOpacityState(s);
265 updateCompositionModeState(s);
266 updateRenderHintsState(s);
267 updateTransformState(s);
268 updateClipState(s);
269}
270
272{
273 caps.updateState(STATE_PEN_ENABLED, qpen_style(s->pen) != Qt::NoPen);
274}
275
277{
278 Qt::BrushStyle style = qbrush_style(s->brush);
279
280 caps.updateState(STATE_BRUSH_PATTERN, style != Qt::SolidPattern);
281 caps.updateState(STATE_BRUSH_ALPHA,
282 qbrush_color(s->brush).alpha() < 255);
283}
284
286{
287 bool translucent = s->opacity < 1;
288 caps.updateState(STATE_ALPHA, translucent);
289}
290
292{
293 bool nonTrivial = s->composition_mode != QPainter::CompositionMode_SourceOver
294 && s->composition_mode != QPainter::CompositionMode_Source;
295
296 caps.updateState(STATE_BLENDING_COMPLEX, nonTrivial);
297}
298
300{
301 bool aa = s->renderHints & QPainter::Antialiasing;
302 caps.updateState(STATE_ANTIALIASING, aa);
303}
304
306{
307 QTransform::TransformationType type = s->matrix.type();
308
309 // consider scaling operations with a negative factor as "complex" for now.
310 // as some blitters could handle axisymmetrical operations, we should improve blitter
311 // paint engine to handle them as a capability
312 caps.updateState(STATE_XFORM_COMPLEX, (type > QTransform::TxScale) ||
313 ((type == QTransform::TxScale) && ((s->matrix.m11() < 0.0) || (s->matrix.m22() < 0.0))));
314 caps.updateState(STATE_XFORM_SCALE, type > QTransform::TxTranslate);
315
316 hasXForm = type >= QTransform::TxTranslate;
317}
318
320{
321 const QClipData *clipData = clip();
322 bool complexClip = clipData && !(clipData->hasRectClip || clipData->hasRegionClip);
323 caps.updateState(STATE_CLIP_COMPLEX, complexClip);
324}
325
326void QBlitterPaintEnginePrivate::fillRect(const QRectF &rect, const QColor &color, bool alpha)
327{
328 Q_Q(QBlitterPaintEngine);
329 pmData->unmarkRasterOverlay(rect);
330 QRectF targetRect = rect;
331 if (hasXForm)
332 targetRect = q->state()->matrix.mapRect(rect);
333 const QClipData *clipData = clip();
334 if (clipData) {
335 if (clipData->hasRectClip) {
336 unlock();
337 if (alpha)
338 pmData->blittable()->alphaFillRect(targetRect & clipData->clipRect, color, q->state()->compositionMode());
339 else
340 pmData->blittable()->fillRect(targetRect & clipData->clipRect, color);
341 } else if (clipData->hasRegionClip) {
342 for (const QRect &rect : clipData->clipRegion) {
343 QRect intersectRect = rect.intersected(targetRect.toRect());
344 if (!intersectRect.isEmpty()) {
345 unlock();
346 if (alpha)
347 pmData->blittable()->alphaFillRect(intersectRect, color, q->state()->compositionMode());
348 else
349 pmData->blittable()->fillRect(intersectRect, color);
350 }
351 }
352 }
353 } else {
354 if (targetRect.x() >= 0 && targetRect.y() >= 0
355 && targetRect.width() <= q->paintDevice()->width()
356 && targetRect.height() <= q->paintDevice()->height()) {
357 unlock();
358 if (alpha)
359 pmData->blittable()->alphaFillRect(targetRect, color, q->state()->compositionMode());
360 else
361 pmData->blittable()->fillRect(targetRect, color);
362 } else {
363 QRectF deviceRect(0, 0, q->paintDevice()->width(), q->paintDevice()->height());
364 unlock();
365 if (alpha)
366 pmData->blittable()->alphaFillRect(deviceRect & targetRect, color, q->state()->compositionMode());
367 else
368 pmData->blittable()->fillRect(deviceRect & targetRect, color);
369 }
370 }
371}
372
374 const QRectF &target,
375 const QPixmap &pm,
376 const QRectF &sr,
377 bool opacity)
378{
379 Q_Q(QBlitterPaintEngine);
380 QRectF intersectedRect = clip.intersected(target);
381 if (intersectedRect.isEmpty())
382 return;
383 QRectF source = sr;
384 if (intersectedRect.size() != target.size()) {
385 if (sr.size() == target.size()) {
386 // no resize
387 qreal deltaTop = target.top() - intersectedRect.top();
388 qreal deltaLeft = target.left() - intersectedRect.left();
389 qreal deltaBottom = target.bottom() - intersectedRect.bottom();
390 qreal deltaRight = target.right() - intersectedRect.right();
391 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
392 } else {
393 // resize case
394 qreal hFactor = sr.size().width() / target.size().width();
395 qreal vFactor = sr.size().height() / target.size().height();
396 qreal deltaTop = (target.top() - intersectedRect.top()) * vFactor;
397 qreal deltaLeft = (target.left() - intersectedRect.left()) * hFactor;
398 qreal deltaBottom = (target.bottom() - intersectedRect.bottom()) * vFactor;
399 qreal deltaRight = (target.right() - intersectedRect.right()) * hFactor;
400 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
401 }
402 }
403 pmData->unmarkRasterOverlay(intersectedRect);
404 if (opacity)
405 pmData->blittable()->drawPixmapOpacity(intersectedRect, pm, source, q->state()->compositionMode(), q->state()->opacity);
406 else
407 pmData->blittable()->drawPixmap(intersectedRect, pm, source);
408}
409
410QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePlatformPixmap *p)
411 : QRasterPaintEngine(*(new QBlitterPaintEnginePrivate(p)), p->buffer())
412{}
413
414// State tracking
415void QBlitterPaintEngine::penChanged()
416{
417 Q_D(QBlitterPaintEngine);
418
419 QRasterPaintEngine::penChanged();
420 d->updatePenState(state());
421}
422
423void QBlitterPaintEngine::brushChanged()
424{
425 Q_D(QBlitterPaintEngine);
426
427 QRasterPaintEngine::brushChanged();
428 d->updateBrushState(state());
429}
430
431void QBlitterPaintEngine::opacityChanged()
432{
433 Q_D(QBlitterPaintEngine);
434
435 QRasterPaintEngine::opacityChanged();
436 d->updateOpacityState(state());
437}
438
439void QBlitterPaintEngine::compositionModeChanged()
440{
441 Q_D(QBlitterPaintEngine);
442
443 QRasterPaintEngine::compositionModeChanged();
444 d->updateCompositionModeState(state());
445}
446
447void QBlitterPaintEngine::renderHintsChanged()
448{
449 Q_D(QBlitterPaintEngine);
450
451 QRasterPaintEngine::renderHintsChanged();
452 d->updateRenderHintsState(state());
453}
454
455void QBlitterPaintEngine::transformChanged()
456{
457 Q_D(QBlitterPaintEngine);
458
459 QRasterPaintEngine::transformChanged();
460 d->updateTransformState(state());
461}
462
463void QBlitterPaintEngine::clipEnabledChanged()
464{
465 Q_D(QBlitterPaintEngine);
466 QRasterPaintEngine::clipEnabledChanged();
467 d->updateClipState(state());
468}
469
470bool QBlitterPaintEngine::begin(QPaintDevice *pdev)
471{
472 Q_D(QBlitterPaintEngine);
473 bool ok = QRasterPaintEngine::begin(pdev);
474#ifdef QT_BLITTER_RASTEROVERLAY
475 d->pmData->unmergeOverlay();
476#endif
477 d->pdev = pdev;
478 return ok;
479}
480
481bool QBlitterPaintEngine::end()
482{
483#ifdef QT_BLITTER_RASTEROVERLAY
484 Q_D(QBlitterPaintEngine);
485 d->pmData->mergeOverlay();
486#endif
487
488 return QRasterPaintEngine::end();
489}
490
491void QBlitterPaintEngine::setState(QPainterState *s)
492{
493 Q_D(QBlitterPaintEngine);
494
495 QRasterPaintEngine::setState(s);
496 d->updateCompleteState(s);
497}
498
499// Accelerated paths
500void QBlitterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
501{
502 Q_D(QBlitterPaintEngine);
503 if (path.shape() == QVectorPath::RectangleHint) {
504 QRectF rect(((const QPointF *) path.points())[0], ((const QPointF *) path.points())[2]);
505 fillRect(rect, brush);
506 } else {
507 d->lock();
508 d->pmData->markRasterOverlay(path);
509 QRasterPaintEngine::fill(path, brush);
510 }
511}
512
513void QBlitterPaintEngine::fillRect(const QRectF &rect, const QColor &color)
514{
515 Q_D(QBlitterPaintEngine);
516 if (d->caps.canBlitterAlphaFillRect()) {
517 d->fillRect(rect, color, true);
518 } else if (d->caps.canBlitterFillRect() && color.alpha() == 0xff) {
519 d->fillRect(rect, color, false);
520 } else {
521 d->lock();
522 d->pmData->markRasterOverlay(rect);
523 QRasterPaintEngine::fillRect(rect, color);
524 }
525}
526
527void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
528{
529 if (rect.size().isEmpty())
530 return;
531
532 Q_D(QBlitterPaintEngine);
533
534 if (qbrush_style(brush) == Qt::SolidPattern
535 && d->caps.canBlitterAlphaFillRect()) {
536 d->fillRect(rect, qbrush_color(brush), true);
537 } else if (qbrush_style(brush) == Qt::SolidPattern
538 && qbrush_color(brush).alpha() == 0xff
539 && d->caps.canBlitterFillRect()) {
540 d->fillRect(rect, qbrush_color(brush), false);
541 } else if ((brush.style() == Qt::TexturePattern) &&
542 (brush.transform().type() <= QTransform::TxTranslate) &&
543 ((d->caps.canBlitterDrawPixmapOpacity(brush.texture())) ||
544 (d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)))) {
545 bool rectIsFilled = false;
546 QRectF transformedRect = state()->matrix.mapRect(rect);
547 qreal x = transformedRect.x();
548 qreal y = transformedRect.y();
549 QPixmap pm = brush.texture();
550 d->unlock();
551 int srcX = int(rect.x() - state()->brushOrigin.x() - brush.transform().dx()) % pm.width();
552 if (srcX < 0)
553 srcX = pm.width() + srcX;
554 const int startX = srcX;
555 int srcY = int(rect.y() - state()->brushOrigin.y() - brush.transform().dy()) % pm.height();
556 if (srcY < 0)
557 srcY = pm.height() + srcY;
558 while (!rectIsFilled) {
559 qreal blitWidth = (pm.width() ) - srcX;
560 qreal blitHeight = (pm.height() ) - srcY;
561 if (x + blitWidth > transformedRect.right())
562 blitWidth = transformedRect.right() -x;
563 if (y + blitHeight > transformedRect.bottom())
564 blitHeight = transformedRect.bottom() - y;
565 const QClipData *clipData = d->clip();
566 if (clipData->hasRectClip) {
567 QRect targetRect = QRect(x, y, blitWidth, blitHeight).intersected(clipData->clipRect);
568 if (targetRect.isValid()) {
569 int tmpSrcX = srcX + (targetRect.x() - x);
570 int tmpSrcY = srcY + (targetRect.y() - y);
571 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
572 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
573 }
574 } else if (clipData->hasRegionClip) {
575 QRect unclippedTargetRect(x, y, blitWidth, blitHeight);
576 const QRegion targetRegion = clipData->clipRegion.intersected(unclippedTargetRect);
577 for (const QRect &targetRect : targetRegion) {
578 if (!targetRect.isValid() || targetRect.isEmpty())
579 continue;
580 int tmpSrcX = srcX + (targetRect.x() - x);
581 int tmpSrcY = srcY + (targetRect.y() - y);
582 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
583 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
584 }
585 }
586 x+=blitWidth;
587 if (qFuzzyCompare(x, transformedRect.right())) {
588 x = transformedRect.x();
589 srcX = startX;
590 srcY = 0;
591 y += blitHeight;
592 if (qFuzzyCompare(y, transformedRect.bottom()))
593 rectIsFilled = true;
594 } else
595 srcX = 0;
596 }
597 } else {
598 d->lock();
599 d->pmData->markRasterOverlay(rect);
600 QRasterPaintEngine::fillRect(rect, brush);
601 }
602
603}
604
605void QBlitterPaintEngine::drawRects(const QRect *rects, int rectCount)
606{
607 Q_D(QBlitterPaintEngine);
608 if (d->caps.canBlitterDrawRectMask()) {
609 for (int i=0; i<rectCount; ++i)
610 d->fillRect(rects[i], qbrush_color(state()->brush), false);
611 } else {
612 d->pmData->markRasterOverlay(rects, rectCount);
613 QRasterPaintEngine::drawRects(rects, rectCount);
614 }
615}
616
617void QBlitterPaintEngine::drawRects(const QRectF *rects, int rectCount)
618{
619 Q_D(QBlitterPaintEngine);
620 if (d->caps.canBlitterDrawRectMask()) {
621 for (int i = 0; i < rectCount; ++i)
622 d->fillRect(rects[i], qbrush_color(state()->brush), false);
623 } else {
624 d->pmData->markRasterOverlay(rects, rectCount);
625 QRasterPaintEngine::drawRects(rects, rectCount);
626 }
627}
628
629void QBlitterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
630{
631 drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
632}
633
634void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
635{
636 Q_D(QBlitterPaintEngine);
637 bool canDrawOpacity;
638
639 canDrawOpacity = d->caps.canBlitterDrawPixmapOpacity(pm);
640 if (canDrawOpacity || (d->caps.canBlitterDrawPixmap(r, pm, sr))) {
641
642 d->unlock();
643 QRectF targetRect = r;
644 if (d->hasXForm)
645 targetRect = state()->matrix.mapRect(r);
646 const QClipData *clipData = d->clip();
647 if (clipData) {
648 if (clipData->hasRectClip) {
649 d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity);
650 } else if (clipData->hasRegionClip) {
651 for (const QRect &rect : clipData->clipRegion)
652 d->clipAndDrawPixmap(rect, targetRect, pm, sr, canDrawOpacity);
653 }
654 } else {
655 QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height());
656 d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr, canDrawOpacity);
657 }
658 }else {
659 d->lock();
660 d->pmData->markRasterOverlay(r);
661 QRasterPaintEngine::drawPixmap(r, pm, sr);
662 }
663}
664
665// Overridden methods to lock the graphics memory
666void QBlitterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
667{
668 Q_D(QBlitterPaintEngine);
669 d->lock();
670 d->pmData->markRasterOverlay(points, pointCount);
671 QRasterPaintEngine::drawPolygon(points, pointCount, mode);
672}
673
674void QBlitterPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
675{
676 Q_D(QBlitterPaintEngine);
677 d->lock();
678 d->pmData->markRasterOverlay(points, pointCount);
679 QRasterPaintEngine::drawPolygon(points, pointCount, mode);
680}
681
682void QBlitterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
683{
684 Q_D(QBlitterPaintEngine);
685 d->lock();
686 d->pmData->markRasterOverlay(path);
687 QRasterPaintEngine::fillPath(path, fillData);
688}
689
690void QBlitterPaintEngine::fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
691{
692 Q_D(QBlitterPaintEngine);
693 d->lock();
694 d->pmData->markRasterOverlay(points, pointCount);
695 QRasterPaintEngine::fillPolygon(points, pointCount, mode);
696}
697
698void QBlitterPaintEngine::drawEllipse(const QRectF &r)
699{
700 Q_D(QBlitterPaintEngine);
701 d->lock();
702 d->pmData->markRasterOverlay(r);
703 QRasterPaintEngine::drawEllipse(r);
704}
705
706void QBlitterPaintEngine::drawImage(const QPointF &pos, const QImage &image)
707{
708 drawImage(QRectF(pos, image.size()), image, image.rect());
709}
710
711void QBlitterPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
712 Qt::ImageConversionFlags flags)
713{
714 Q_D(QBlitterPaintEngine);
715 d->lock();
716 d->pmData->markRasterOverlay(r);
717 QRasterPaintEngine::drawImage(r, pm, sr, flags);
718}
719
720void QBlitterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr)
721{
722 Q_D(QBlitterPaintEngine);
723 d->lock();
724 d->pmData->markRasterOverlay(r);
725 QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
726}
727
728void QBlitterPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
729{
730 Q_D(QBlitterPaintEngine);
731 d->lock();
732 d->pmData->markRasterOverlay(pos, ti);
733 QRasterPaintEngine::drawTextItem(pos, ti);
734}
735
736void QBlitterPaintEngine::drawPoints(const QPointF *points, int pointCount)
737{
738 Q_D(QBlitterPaintEngine);
739 d->lock();
740 d->pmData->markRasterOverlay(points, pointCount);
741 QRasterPaintEngine::drawPoints(points, pointCount);
742}
743
744void QBlitterPaintEngine::drawPoints(const QPoint *points, int pointCount)
745{
746 Q_D(QBlitterPaintEngine);
747 d->lock();
748 d->pmData->markRasterOverlay(points, pointCount);
749 QRasterPaintEngine::drawPoints(points, pointCount);
750}
751
752void QBlitterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
753{
754 Q_D(QBlitterPaintEngine);
755 d->lock();
756 d->pmData->markRasterOverlay(path);
757 QRasterPaintEngine::stroke(path, pen);
758}
759
760void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti)
761{
762 Q_D(QBlitterPaintEngine);
763 d->lock();
764 QRasterPaintEngine::drawStaticTextItem(sti);
765
766#ifdef QT_BLITTER_RASTEROVERLAY
767//#### d->pmData->markRasterOverlay(sti);
768 qWarning("not implemented: markRasterOverlay for QStaticTextItem");
769#endif
770}
771
772bool QBlitterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
773{
774 Q_D(QBlitterPaintEngine);
775 QFontEngine::GlyphFormat glyphFormat = d->glyphCacheFormat;
776 if (fontEngine->glyphFormat != QFontEngine::Format_None)
777 glyphFormat = fontEngine->glyphFormat;
778
779 const QClipData *clipData = d->clip();
780 const bool complexClip = clipData && !clipData->hasRectClip;
781
782 const QPainterState *s = state();
783 if (d->caps.canBlitterDrawCachedGlyphs(s->transform(), glyphFormat, complexClip)) {
784 d->unlock();
785 const bool result = d->pmData->blittable()->drawCachedGlyphs(s, glyphFormat, numGlyphs, glyphs, positions, fontEngine);
786 // Lock again as the raster paint engine might draw decorations now.
787 d->lock();
788 return result;
789 } else {
790 return QRasterPaintEngine::drawCachedGlyphs(numGlyphs, glyphs, positions, fontEngine);
791 }
792}
793
794QT_END_NAMESPACE
795#endif //QT_NO_BLITTABLE
void updateOpacityState(QPainterState *s)
void updateBrushState(QPainterState *s)
void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr, bool opacity)
void fillRect(const QRectF &rect, const QColor &color, bool alpha)
void updateCompositionModeState(QPainterState *s)
void updateTransformState(QPainterState *s)
void updatePenState(QPainterState *s)
void updateRenderHintsState(QPainterState *s)
void updateClipState(QPainterState *s)
QBlittablePlatformPixmap * pmData
void updateCompleteState(QPainterState *s)
#define STATE_BRUSH_ALPHA
#define STATE_ANTIALIASING
#define STATE_ALPHA
#define STATE_BLENDING_COMPLEX
#define STATE_XFORM_SCALE
#define STATE_BRUSH_PATTERN
#define STATE_CLIP_COMPLEX
#define STATE_XFORM_COMPLEX
#define STATE_CLIPSYS_COMPLEX
#define STATE_PEN_ENABLED