28bool QAlphaPaintEngine::begin(QPaintDevice *pdev)
30 Q_D(QAlphaPaintEngine);
32 d->m_continueCall =
true;
37 d->m_savedcaps = gccaps;
40 d->m_alphaPen =
false;
41 d->m_alphaBrush =
false;
42 d->m_alphaOpacity =
false;
43 d->m_hasalpha =
false;
44 d->m_advancedPen =
false;
45 d->m_advancedBrush =
false;
46 d->m_complexTransform =
false;
47 d->m_emulateProjectiveTransforms =
false;
50 d->m_alphargn = QRegion();
51 d->m_cliprgn = QRegion();
53 d->m_transform = QTransform();
73void QAlphaPaintEngine::updateState(
const QPaintEngineState &state)
75 Q_D(QAlphaPaintEngine);
77 DirtyFlags flags = state.state();
78 if (flags & QPaintEngine::DirtyTransform) {
79 d->m_transform = state.transform();
80 d->m_complexTransform = (d->m_transform.type() > QTransform::TxScale);
81 d->m_emulateProjectiveTransforms = !(d->m_savedcaps & QPaintEngine::PerspectiveTransform)
82 && !(d->m_savedcaps & QPaintEngine::AlphaBlend)
83 && (d->m_transform.type() >= QTransform::TxProject);
85 if (flags & QPaintEngine::DirtyPen) {
86 d->m_pen = state.pen();
87 if (d->m_pen.style() == Qt::NoPen) {
88 d->m_advancedPen =
false;
89 d->m_alphaPen =
false;
91 d->m_advancedPen = (d->m_pen.brush().style() != Qt::SolidPattern);
92 d->m_alphaPen = !d->m_pen.brush().isOpaque();
97 d->m_continueCall =
true;
100 d->m_continueCall =
false;
102 if (flags & QPaintEngine::DirtyOpacity) {
103 d->m_alphaOpacity = (state.opacity() != 1.0f);
106 if (flags & QPaintEngine::DirtyBrush) {
107 if (state.brush().style() == Qt::NoBrush) {
108 d->m_advancedBrush =
false;
109 d->m_alphaBrush =
false;
111 d->m_advancedBrush = (state.brush().style() != Qt::SolidPattern);
112 d->m_alphaBrush = !state.brush().isOpaque();
117 d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen;
119 if (d->m_picengine) {
120 const QPainter *p = painter();
121 d->m_picpainter->setPen(p->pen());
122 d->m_picpainter->setBrush(p->brush());
123 d->m_picpainter->setBrushOrigin(p->brushOrigin());
124 d->m_picpainter->setFont(p->font());
125 d->m_picpainter->setOpacity(p->opacity());
126 d->m_picpainter->setTransform(p->combinedTransform());
127 d->m_picengine->updateState(state);
131void QAlphaPaintEngine::drawPath(
const QPainterPath &path)
133 Q_D(QAlphaPaintEngine);
135 QRectF tr = d->addPenWidth(path);
137 if (d->m_pass == 0) {
138 d->m_continueCall =
false;
139 if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
140 || d->m_emulateProjectiveTransforms)
148 d->m_picengine->drawPath(path);
150 d->m_continueCall = !d->fullyContained(tr);
154void QAlphaPaintEngine::drawPolygon(
const QPointF *points,
int pointCount, PolygonDrawMode mode)
156 Q_D(QAlphaPaintEngine);
159 poly.reserve(pointCount);
160 for (
int i = 0; i < pointCount; ++i)
161 poly.append(points[i]);
164 path.addPolygon(poly);
165 QRectF tr = d->addPenWidth(path);
167 if (d->m_pass == 0) {
168 d->m_continueCall =
false;
169 if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
170 || d->m_emulateProjectiveTransforms)
178 d->m_picengine->drawPolygon(points, pointCount, mode);
180 d->m_continueCall = !d->fullyContained(tr);
184void QAlphaPaintEngine::drawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
186 Q_D(QAlphaPaintEngine);
188 QRectF tr = d->m_transform.mapRect(r);
189 if (d->m_pass == 0) {
190 d->m_continueCall =
false;
191 if (d->canSeeTroughBackground(pm.hasAlpha() || d->m_alphaOpacity, tr) || d->m_complexTransform || pm.isQBitmap()) {
198 d->m_picengine->drawPixmap(r, pm, sr);
201 d->m_continueCall = !d->fullyContained(tr);
205void QAlphaPaintEngine::drawTextItem(
const QPointF &p,
const QTextItem &textItem)
207 Q_D(QAlphaPaintEngine);
209 QRectF tr(p.x(), p.y() - textItem.ascent(), textItem.width() + 5, textItem.ascent() + textItem.descent() + 5);
210 tr = d->m_transform.mapRect(tr);
212 if (d->m_pass == 0) {
213 d->m_continueCall =
false;
214 if (d->canSeeTroughBackground(d->m_alphaPen || d->m_alphaOpacity, tr) || d->m_advancedPen) {
220 if (d->m_picengine) {
221 d->m_picengine->drawTextItem(p, textItem);
224 d->m_continueCall = !d->fullyContained(tr);
228void QAlphaPaintEngine::drawTiledPixmap(
const QRectF &r,
const QPixmap &pixmap,
const QPointF &s)
230 Q_D(QAlphaPaintEngine);
232 QRectF brect = d->m_transform.mapRect(r);
234 if (d->m_pass == 0) {
235 d->m_continueCall =
false;
236 if (d->canSeeTroughBackground(pixmap.hasAlpha() || d->m_alphaOpacity, brect) || d->m_complexTransform || pixmap.isQBitmap()) {
237 d->addAlphaRect(brect);
240 d->addDirtyRect(brect);
243 d->m_picengine->drawTiledPixmap(r, pixmap, s);
245 d->m_continueCall = !d->fullyContained(brect);
261void QAlphaPaintEngine::flushAndInit(
bool init)
263 Q_D(QAlphaPaintEngine);
264 Q_ASSERT(d->m_pass == 0);
267 d->m_picpainter->end();
270 d->m_alphargn = d->m_alphargn.intersected(QRect(0, 0, d->m_pdev->width(), d->m_pdev->height()));
273 if (d->m_alphargn.rectCount() > 10) {
274 QRect br = d->m_alphargn.boundingRect();
275 d->m_alphargn = QRegion(br);
278 const auto oldAlphaRegion = d->m_cliprgn = d->m_alphargn;
284 gccaps = d->m_savedcaps;
287 d->resetState(painter());
291 mtx.scale(1.0f / (qreal(d->m_pdev->logicalDpiX()) / qreal(qt_defaultDpiX())),
292 1.0f / (qreal(d->m_pdev->logicalDpiY()) / qreal(qt_defaultDpiY())));
293 painter()->setTransform(mtx);
294 painter()->drawPicture(0, 0, *d->m_pic);
296 d->m_cliprgn = QRegion();
297 d->resetState(painter());
300 for (
const auto &rect : oldAlphaRegion)
301 d->drawAlphaImage(rect);
303 d->m_alphargn = QRegion();
305 painter()->restore();
313 gccaps = PaintEngineFeatures(AllFeatures & ~QPaintEngine::ObjectBoundingModeGradients);
315 d->m_pic =
new QPicture();
316 d->m_pic->d_ptr->in_memory_only =
true;
317 d->m_picpainter =
new QPainter(d->m_pic);
318 d->m_picengine = d->m_picpainter->paintEngine();
323 d->m_picpainter->setPen(painter()->pen());
324 d->m_picpainter->setBrush(painter()->brush());
325 d->m_picpainter->setBrushOrigin(painter()->brushOrigin());
326 d->m_picpainter->setFont(painter()->font());
327 d->m_picpainter->setOpacity(painter()->opacity());
328 d->m_picpainter->setTransform(painter()->combinedTransform());
329 d->m_picengine->syncState();
330 QPainterState &state = *d->m_picpainter->d_func()->state;
331 QPainter *oldPainter = state.painter;
332 state = *painter()->d_func()->state;
333 state.painter = oldPainter;
372QRectF QAlphaPaintEnginePrivate::addPenWidth(
const QPainterPath &path)
374 QPainterPath tmp = path;
376 if (m_pen.style() == Qt::NoPen)
377 return (path.controlPointRect() * m_transform).boundingRect();
378 bool cosmetic = m_pen.isCosmetic();
380 tmp = path * m_transform;
382 QPainterPathStroker stroker;
383 if (m_pen.widthF() == 0.0f)
384 stroker.setWidth(1.0);
386 stroker.setWidth(m_pen.widthF());
387 stroker.setJoinStyle(m_pen.joinStyle());
388 stroker.setCapStyle(m_pen.capStyle());
389 tmp = stroker.createStroke(tmp);
391 return tmp.controlPointRect();
393 return (tmp.controlPointRect() * m_transform).boundingRect();
401bool QAlphaPaintEnginePrivate::canSeeTroughBackground(
bool somethingInRectHasAlpha,
const QRectF &rect)
const
403 if (somethingInRectHasAlpha) {
404 if (m_dirtyRects.size() != m_numberOfCachedRects) {
405 m_cachedDirtyRgn.setRects(m_dirtyRects.constData(), m_dirtyRects.size());
406 m_numberOfCachedRects = m_dirtyRects.size();
408 return m_cachedDirtyRgn.intersects(rect.toAlignedRect());
413void QAlphaPaintEnginePrivate::drawAlphaImage(
const QRectF &rect)
415 Q_Q(QAlphaPaintEngine);
417 qreal dpiX = qMax(m_pdev->logicalDpiX(), 300);
418 qreal dpiY = qMax(m_pdev->logicalDpiY(), 300);
419 qreal xscale = (dpiX / m_pdev->logicalDpiX());
420 qreal yscale = (dpiY / m_pdev->logicalDpiY());
423 picscale.scale(xscale, yscale);
425 const int tileSize = 2048;
426 QSize size((
int(rect.width() * xscale)),
int(rect.height() * yscale));
427 int divw = (size.width() / tileSize);
428 int divh = (size.height() / tileSize);
432 int incx =
int(rect.width() / divw);
433 int incy =
int(rect.height() / divh);
435 for (
int y=0; y<divh; ++y) {
436 int ypos =
int((incy * y) + rect.y());
437 int height =
int((y == (divh - 1)) ? (rect.height() - (incy * y)) : incy) + 1;
439 for (
int x=0; x<divw; ++x) {
440 int xpos =
int((incx * x) + rect.x());
441 int width =
int((x == (divw - 1)) ? (rect.width() - (incx * x)) : incx) + 1;
443 QSize imgsize((
int)(width * xscale), (
int)(height * yscale));
444 QImage img(imgsize, QImage::Format_RGB32);
445 img.fill(0xffffffff);
447 QPainter imgpainter(&img);
448 imgpainter.setTransform(picscale);
449 QPointF picpos(qreal(-xpos), qreal(-ypos));
450 imgpainter.drawPicture(picpos, *m_pic);
453 q->painter()->setTransform(QTransform());
454 QRect r(xpos, ypos, width, height);
455 q->painter()->drawImage(r, img);
466void QAlphaPaintEnginePrivate::resetState(QPainter *p)
469 p->setBrush(QBrush());
470 p->setBrushOrigin(0,0);
471 p->setBackground(QBrush());
473 p->setTransform(QTransform());
477 p->setViewTransformEnabled(
false);
478 p->setClipRegion(QRegion(), Qt::NoClip);
479 p->setClipPath(QPainterPath(), Qt::NoClip);
480 p->setClipping(
false);