void QSGPainterNode::paint() { QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect; QPainter painter; if (m_actualRenderTarget == QQuickPaintedItem::Image) { if (m_image.isNull()) return; painter.begin(&m_image); } else { if (!m_gl_device) { m_gl_device = new QOpenGLPaintDevice(m_fboSize); m_gl_device->setPaintFlipped(true); } if (m_multisampledFbo) m_multisampledFbo->bind(); else m_fbo->bind(); painter.begin(m_gl_device); } if (m_smoothPainting) { painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); } painter.scale(m_contentsScale, m_contentsScale); QRect sclip(qFloor(dirtyRect.x()/m_contentsScale), qFloor(dirtyRect.y()/m_contentsScale), qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)), qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale))); if (!m_dirtyRect.isNull()) painter.setClipRect(sclip); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(sclip, m_fillColor); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); m_item->paint(&painter); painter.end(); if (m_actualRenderTarget == QQuickPaintedItem::Image) { m_texture->setImage(m_image); m_texture->setDirtyRect(dirtyRect); } else if (m_multisampledFbo) { QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect); } if (m_multisampledFbo) m_multisampledFbo->release(); else if (m_fbo) m_fbo->release(); m_dirtyRect = QRect(); }
/*! \internal */ void QDeclarativePaintedItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QDeclarativePaintedItem); const QRect content = boundingRect().toRect(); if (content.width() <= 0 || content.height() <= 0) return; ++inpaint; const QTransform &x = p->deviceTransform(); QTransform xinv = x.inverted(); QRegion effectiveClip; QRegion sysClip = p->paintEngine()->systemClip(); if (xinv.type() <= QTransform::TxScale && sysClip.numRects() < 5) { // simple transform, region gets no more complicated... effectiveClip = xinv.map(sysClip); } else { // do not make complicated regions... effectiveClip = xinv.mapRect(sysClip.boundingRect()); } QRegion topaint = p->clipRegion(); if (topaint.isEmpty()) { if (effectiveClip.isEmpty()) topaint = QRect(0,0,p->device()->width(),p->device()->height()); else topaint = effectiveClip; } else if (!effectiveClip.isEmpty()) { topaint &= effectiveClip; } topaint &= content; QRegion uncached(content); p->setRenderHints(QPainter::SmoothPixmapTransform, d->smooth); int cachesize=0; for (int i=0; i<d->imagecache.count(); ++i) { QRect area = d->imagecache[i]->area; if (topaint.contains(area)) { QRectF target(area.x(), area.y(), area.width(), area.height()); if (!d->cachefrozen) { if (!d->imagecache[i]->dirty.isNull() && topaint.contains(d->imagecache[i]->dirty)) { #ifdef Q_WS_MAC bool oldSmooth = qt_applefontsmoothing_enabled; qt_applefontsmoothing_enabled = false; #endif QPainter qp(&d->imagecache[i]->image); #ifdef Q_WS_MAC qt_applefontsmoothing_enabled = oldSmooth; #endif qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); qp.translate(-area.x(), -area.y()); qp.scale(d->contentsScale,d->contentsScale); QRect clip = d->imagecache[i]->dirty; QRect sclip(qFloor(clip.x()/d->contentsScale), qFloor(clip.y()/d->contentsScale), qCeil(clip.width()/d->contentsScale+clip.x()/d->contentsScale-qFloor(clip.x()/d->contentsScale)), qCeil(clip.height()/d->contentsScale+clip.y()/d->contentsScale-qFloor(clip.y()/d->contentsScale))); qp.setClipRect(sclip); if (d->fillColor.isValid()){ if(d->fillColor.alpha() < 255){ // ### Might not work outside of raster paintengine QPainter::CompositionMode prev = qp.compositionMode(); qp.setCompositionMode(QPainter::CompositionMode_Source); qp.fillRect(sclip,d->fillColor); qp.setCompositionMode(prev); }else{ qp.fillRect(sclip,d->fillColor); } } drawContents(&qp, sclip); d->imagecache[i]->dirty = QRect(); } } p->drawPixmap(target.toRect(), d->imagecache[i]->image); topaint -= area; d->imagecache[i]->age=0; } else { d->imagecache[i]->age++; } cachesize += area.width()*area.height(); uncached -= area; } if (!topaint.isEmpty()) { if (!d->cachefrozen) { // Find a sensible larger area, otherwise will paint lots of tiny images. QRect biggerrect = topaint.boundingRect().adjusted(-64,-64,128,128); cachesize += biggerrect.width() * biggerrect.height(); while (d->imagecache.count() && cachesize > d->max_imagecache_size) { int oldest=-1; int age=-1; for (int i=0; i<d->imagecache.count(); ++i) { int a = d->imagecache[i]->age; if (a > age) { oldest = i; age = a; } } cachesize -= d->imagecache[oldest]->area.width()*d->imagecache[oldest]->area.height(); uncached += d->imagecache[oldest]->area; delete d->imagecache.takeAt(oldest); } const QRegion bigger = QRegion(biggerrect) & uncached; const QVector<QRect> rects = bigger.rects(); for (int i = 0; i < rects.count(); ++i) { const QRect &r = rects.at(i); QPixmap img(r.size()); if (d->fillColor.isValid()) img.fill(d->fillColor); { #ifdef Q_WS_MAC bool oldSmooth = qt_applefontsmoothing_enabled; qt_applefontsmoothing_enabled = false; #endif QPainter qp(&img); #ifdef Q_WS_MAC qt_applefontsmoothing_enabled = oldSmooth; #endif qp.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, d->smoothCache); qp.translate(-r.x(),-r.y()); qp.scale(d->contentsScale,d->contentsScale); QRect sclip(qFloor(r.x()/d->contentsScale), qFloor(r.y()/d->contentsScale), qCeil(r.width()/d->contentsScale+r.x()/d->contentsScale-qFloor(r.x()/d->contentsScale)), qCeil(r.height()/d->contentsScale+r.y()/d->contentsScale-qFloor(r.y()/d->contentsScale))); drawContents(&qp, sclip); } QDeclarativePaintedItemPrivate::ImageCacheItem *newitem = new QDeclarativePaintedItemPrivate::ImageCacheItem; newitem->area = r; newitem->image = img; d->imagecache.append(newitem); p->drawPixmap(r, newitem->image); } } else { const QVector<QRect> rects = uncached.rects(); for (int i = 0; i < rects.count(); ++i) p->fillRect(rects.at(i), Qt::lightGray); } } if (inpaint_clearcache) { clearCache(); inpaint_clearcache = 0; } --inpaint; }