29bool QAlphaPaintEngine::begin(QPaintDevice *pdev)
31 Q_D(QAlphaPaintEngine);
33 d->m_continueCall =
true;
38 d->m_savedcaps = gccaps;
41 d->m_alphaPen =
false;
42 d->m_alphaBrush =
false;
43 d->m_alphaOpacity =
false;
44 d->m_hasalpha =
false;
45 d->m_advancedPen =
false;
46 d->m_advancedBrush =
false;
47 d->m_complexTransform =
false;
48 d->m_emulateProjectiveTransforms =
false;
51 d->m_alphargn = QRegion();
52 d->m_cliprgn = QRegion();
54 d->m_transform = QTransform();
74void QAlphaPaintEngine::updateState(
const QPaintEngineState &state)
76 Q_D(QAlphaPaintEngine);
78 DirtyFlags flags = state.state();
79 if (flags & QPaintEngine::DirtyTransform) {
80 d->m_transform = state.transform();
81 d->m_complexTransform = (d->m_transform.type() > QTransform::TxScale);
82 d->m_emulateProjectiveTransforms = !(d->m_savedcaps & QPaintEngine::PerspectiveTransform)
83 && !(d->m_savedcaps & QPaintEngine::AlphaBlend)
84 && (d->m_transform.type() >= QTransform::TxProject);
86 if (flags & QPaintEngine::DirtyPen) {
87 d->m_pen = state.pen();
88 if (d->m_pen.style() == Qt::NoPen) {
89 d->m_advancedPen =
false;
90 d->m_alphaPen =
false;
92 d->m_advancedPen = (d->m_pen.brush().style() != Qt::SolidPattern);
93 d->m_alphaPen = !d->m_pen.brush().isOpaque();
98 d->m_continueCall =
true;
101 d->m_continueCall =
false;
103 if (flags & QPaintEngine::DirtyOpacity) {
104 d->m_alphaOpacity = (state.opacity() != 1.0f);
107 if (flags & QPaintEngine::DirtyBrush) {
108 if (state.brush().style() == Qt::NoBrush) {
109 d->m_advancedBrush =
false;
110 d->m_alphaBrush =
false;
112 d->m_advancedBrush = (state.brush().style() != Qt::SolidPattern);
113 d->m_alphaBrush = !state.brush().isOpaque();
118 d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen;
120 if (d->m_picengine) {
121 const QPainter *p = painter();
122 d->m_picpainter->setPen(p->pen());
123 d->m_picpainter->setBrush(p->brush());
124 d->m_picpainter->setBrushOrigin(p->brushOriginF());
125 d->m_picpainter->setFont(p->font());
126 d->m_picpainter->setOpacity(p->opacity());
127 d->m_picpainter->setTransform(p->combinedTransform());
128 d->m_picengine->updateState(state);
132void QAlphaPaintEngine::drawPath(
const QPainterPath &path)
134 Q_D(QAlphaPaintEngine);
136 QRectF tr = d->addPenWidth(path);
138 if (d->m_pass == 0) {
139 d->m_continueCall =
false;
140 if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
141 || d->m_emulateProjectiveTransforms)
149 d->m_picengine->drawPath(path);
151 d->m_continueCall = !d->fullyContained(tr);
155void QAlphaPaintEngine::drawPolygon(
const QPointF *points,
int pointCount, PolygonDrawMode mode)
157 Q_D(QAlphaPaintEngine);
160 poly.reserve(pointCount);
161 for (
int i = 0; i < pointCount; ++i)
162 poly.append(points[i]);
165 path.addPolygon(poly);
166 QRectF tr = d->addPenWidth(path);
168 if (d->m_pass == 0) {
169 d->m_continueCall =
false;
170 if (d->canSeeTroughBackground(d->m_hasalpha, tr) || d->m_advancedPen || d->m_advancedBrush
171 || d->m_emulateProjectiveTransforms)
179 d->m_picengine->drawPolygon(points, pointCount, mode);
181 d->m_continueCall = !d->fullyContained(tr);
185void QAlphaPaintEngine::drawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
187 Q_D(QAlphaPaintEngine);
189 QRectF tr = d->m_transform.mapRect(r);
190 if (d->m_pass == 0) {
191 d->m_continueCall =
false;
192 if (d->canSeeTroughBackground(pm.hasAlpha() || d->m_alphaOpacity, tr) || d->m_complexTransform || pm.isQBitmap()) {
199 d->m_picengine->drawPixmap(r, pm, sr);
202 d->m_continueCall = !d->fullyContained(tr);
206void QAlphaPaintEngine::drawTextItem(
const QPointF &p,
const QTextItem &textItem)
208 Q_D(QAlphaPaintEngine);
210 QRectF tr(p.x(), p.y() - textItem.ascent(), textItem.width() + 5, textItem.ascent() + textItem.descent() + 5);
211 tr = d->m_transform.mapRect(tr);
213 if (d->m_pass == 0) {
214 d->m_continueCall =
false;
215 if (d->canSeeTroughBackground(d->m_alphaPen || d->m_alphaOpacity, tr) || d->m_advancedPen) {
221 if (d->m_picengine) {
222 d->m_picengine->drawTextItem(p, textItem);
225 d->m_continueCall = !d->fullyContained(tr);
229void QAlphaPaintEngine::drawTiledPixmap(
const QRectF &r,
const QPixmap &pixmap,
const QPointF &s)
231 Q_D(QAlphaPaintEngine);
233 QRectF brect = d->m_transform.mapRect(r);
235 if (d->m_pass == 0) {
236 d->m_continueCall =
false;
237 if (d->canSeeTroughBackground(pixmap.hasAlpha() || d->m_alphaOpacity, brect) || d->m_complexTransform || pixmap.isQBitmap()) {
238 d->addAlphaRect(brect);
241 d->addDirtyRect(brect);
244 d->m_picengine->drawTiledPixmap(r, pixmap, s);
246 d->m_continueCall = !d->fullyContained(brect);
262void QAlphaPaintEngine::flushAndInit(
bool init)
264 Q_D(QAlphaPaintEngine);
265 Q_ASSERT(d->m_pass == 0);
268 d->m_picpainter->end();
271 d->m_alphargn = d->m_alphargn.intersected(QRect(0, 0, d->m_pdev->width(), d->m_pdev->height()));
274 if (d->m_alphargn.rectCount() > 10) {
275 QRect br = d->m_alphargn.boundingRect();
276 d->m_alphargn = QRegion(br);
279 const auto oldAlphaRegion = d->m_cliprgn = d->m_alphargn;
285 gccaps = d->m_savedcaps;
288 d->resetState(painter());
292 mtx.scale(1.0f / (qreal(d->m_pdev->logicalDpiX()) / qreal(qt_defaultDpiX())),
293 1.0f / (qreal(d->m_pdev->logicalDpiY()) / qreal(qt_defaultDpiY())));
294 painter()->setTransform(mtx);
295 painter()->drawPicture(0, 0, *d->m_pic);
297 d->m_cliprgn = QRegion();
298 d->resetState(painter());
301 for (
const auto &rect : oldAlphaRegion)
302 d->drawAlphaImage(rect);
304 d->m_alphargn = QRegion();
306 painter()->restore();
314 gccaps = PaintEngineFeatures(AllFeatures & ~QPaintEngine::ObjectBoundingModeGradients);
316 d->m_pic =
new QPicture();
317 d->m_pic->d_ptr->in_memory_only =
true;
318 d->m_picpainter =
new QPainter(d->m_pic);
319 d->m_picengine = d->m_picpainter->paintEngine();
324 d->m_picpainter->setPen(painter()->pen());
325 d->m_picpainter->setBrush(painter()->brush());
326 d->m_picpainter->setBrushOrigin(painter()->brushOriginF());
327 d->m_picpainter->setFont(painter()->font());
328 d->m_picpainter->setOpacity(painter()->opacity());
329 d->m_picpainter->setTransform(painter()->combinedTransform());
330 d->m_picengine->syncState();
331 QPainterState &state = *d->m_picpainter->d_func()->state;
332 QPainter *oldPainter = state.painter;
333 state = *painter()->d_func()->state;
334 state.painter = oldPainter;
373QRectF QAlphaPaintEnginePrivate::addPenWidth(
const QPainterPath &path)
375 QPainterPath tmp = path;
377 if (m_pen.style() == Qt::NoPen)
378 return (path.controlPointRect() * m_transform).boundingRect();
379 bool cosmetic = m_pen.isCosmetic();
381 tmp = path * m_transform;
383 QPainterPathStroker stroker;
384 if (m_pen.widthF() == 0.0f)
385 stroker.setWidth(1.0);
387 stroker.setWidth(m_pen.widthF());
388 stroker.setJoinStyle(m_pen.joinStyle());
389 stroker.setCapStyle(m_pen.capStyle());
390 tmp = stroker.createStroke(tmp);
392 return tmp.controlPointRect();
394 return (tmp.controlPointRect() * m_transform).boundingRect();
402bool QAlphaPaintEnginePrivate::canSeeTroughBackground(
bool somethingInRectHasAlpha,
const QRectF &rect)
const
404 if (somethingInRectHasAlpha) {
405 if (m_dirtyRects.size() != m_numberOfCachedRects) {
406 m_cachedDirtyRgn.setRects(m_dirtyRects.constData(), m_dirtyRects.size());
407 m_numberOfCachedRects = m_dirtyRects.size();
409 return m_cachedDirtyRgn.intersects(rect.toAlignedRect());
414void QAlphaPaintEnginePrivate::drawAlphaImage(
const QRectF &rect)
416 Q_Q(QAlphaPaintEngine);
418 qreal dpiX = qMax(m_pdev->logicalDpiX(), 300);
419 qreal dpiY = qMax(m_pdev->logicalDpiY(), 300);
420 qreal xscale = (dpiX / m_pdev->logicalDpiX());
421 qreal yscale = (dpiY / m_pdev->logicalDpiY());
424 picscale.scale(xscale, yscale);
426 const int tileSize = 2048;
427 QSize size((
int(rect.width() * xscale)),
int(rect.height() * yscale));
428 int divw = (size.width() / tileSize);
429 int divh = (size.height() / tileSize);
433 int incx =
int(rect.width() / divw);
434 int incy =
int(rect.height() / divh);
436 for (
int y=0; y<divh; ++y) {
437 int ypos =
int((incy * y) + rect.y());
438 int height =
int((y == (divh - 1)) ? (rect.height() - (incy * y)) : incy) + 1;
440 for (
int x=0; x<divw; ++x) {
441 int xpos =
int((incx * x) + rect.x());
442 int width =
int((x == (divw - 1)) ? (rect.width() - (incx * x)) : incx) + 1;
444 QSize imgsize((
int)(width * xscale), (
int)(height * yscale));
445 QImage img(imgsize, QImage::Format_RGB32);
446 img.fill(0xffffffff);
448 QPainter imgpainter(&img);
449 imgpainter.setTransform(picscale);
450 QPointF picpos(qreal(-xpos), qreal(-ypos));
451 imgpainter.drawPicture(picpos, *m_pic);
454 q->painter()->setTransform(QTransform());
455 QRect r(xpos, ypos, width, height);
456 q->painter()->drawImage(r, img);
467void QAlphaPaintEnginePrivate::resetState(QPainter *p)
470 p->setBrush(QBrush());
471 p->setBrushOrigin(0,0);
472 p->setBackground(QBrush());
474 p->setTransform(QTransform());
478 p->setViewTransformEnabled(
false);
479 p->setClipRegion(QRegion(), Qt::NoClip);
480 p->setClipPath(QPainterPath(), Qt::NoClip);
481 p->setClipping(
false);