From 89cc6c1b49e3e33fc7787f1dd9cfaadb43ad4bac Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Tue, 18 Aug 2009 15:46:00 +0200 Subject: Fixed QRasterPaintEngine::drawImage() for 1x1 source rectangles. QRasterPaintEngine::drawImage() used an optimized code path when the source rectangle was 1x1. It would sample the source image at the source rectangle's top-left corner and use the sampled color to fill the entire target rectangle. There were two bugs, however: 1) The sampled color was assumed to be non-premultiplied, so you could end up with premultiplying the color twice. This was fixed by avoiding premultiplying a second time if the source image has a premultiplied format. 2) Since the source rectangle is a QRectF, it could easily cross pixel boundaries even if it's 1x1. In this case, it is not correct to fill the target rectangle with a single color. This was fixed by checking if the entire source rectangle is contained in a single pixel before taking the optimized code path. Task-number: 256950 Reviewed-by: Trond --- src/gui/painting/qpaintengine_raster.cpp | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 547818c..63c4e32 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2544,12 +2544,44 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); const bool aa = s->flags.antialiased || s->flags.bilinear; - if (!aa && sr.size() == QSize(1, 1)) { + int sr_l = qFloor(sr.left()); + int sr_r = qCeil(sr.right()) - 1; + int sr_t = qFloor(sr.top()); + int sr_b = qCeil(sr.bottom()) - 1; + + if (!aa && sr_l == sr_r && sr_t == sr_b) { // as fillRect will apply the aliased coordinate delta we need to // subtract it here as we don't use it for image drawing QTransform old = s->matrix; s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); - fillRect(r, QColor::fromRgba(img.pixel(sr.x(), sr.y()))); + + // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. + QRgb color = img.pixel(sr_l, sr_t); + switch (img.format()) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + // Combine premultiplied color with the opacity set on the painter. + d->solid_color_filler.solid.color = + ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) + | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + break; + default: + d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + break; + } + + if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + return; + } + + d->solid_color_filler.clip = d->clip(); + d->solid_color_filler.adjustSpanMethods(); + fillRect(r, &d->solid_color_filler); + s->matrix = old; return; } -- cgit v0.12