diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-08-03 01:00:16 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2018-08-07 17:44:51 +0200 |
commit | 053e7cce79d4bef99ec85101b0d22bbb171072c5 (patch) | |
tree | c2059e82cccdea1fd0024c5942d1a834c28d39da /src/gui/painting/qpaintengine_raster.cpp | |
parent | a420d02538d28854914a6978c9637a0ddd652146 (diff) | |
parent | f271dd8f960ad9f61697dfa57b26c4071441cadc (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts:
.qmake.conf
src/corelib/doc/src/objectmodel/signalsandslots.qdoc
src/plugins/platforms/cocoa/qcocoamenuloader.mm
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection.h
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/plugins/platforms/xcb/qxcbwindow.cpp
tests/auto/gui/image/qimage/tst_qimage.cpp
Done-with: Gatis Paeglis <gatis.paeglis@qt.io>
Change-Id: I9bd24ee9b00d4f26c8f344ce3970aa6e93935ff5
Diffstat (limited to 'src/gui/painting/qpaintengine_raster.cpp')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 119 |
1 files changed, 117 insertions, 2 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index e0dd789dfd..7caaf3a8fa 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1056,6 +1056,77 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, alpha); } +void QRasterPaintEnginePrivate::blitImage(const QPointF &pt, + const QImage &img, + const QRect &clip, + const QRect &sr) +{ + if (!clip.isValid()) + return; + + Q_ASSERT(img.depth() >= 8); + + qsizetype srcBPL = img.bytesPerLine(); + const uchar *srcBits = img.bits(); + int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit.. + int iw = img.width(); + int ih = img.height(); + + if (!sr.isEmpty()) { + iw = sr.width(); + ih = sr.height(); + // Adjust the image according to the source offset... + srcBits += ((sr.y() * srcBPL) + sr.x() * srcSize); + } + + // adapt the x parameters + int x = qRound(pt.x()); + int cx1 = clip.x(); + int cx2 = clip.x() + clip.width(); + if (x < cx1) { + int d = cx1 - x; + srcBits += srcSize * d; + iw -= d; + x = cx1; + } + if (x + iw > cx2) { + int d = x + iw - cx2; + iw -= d; + } + if (iw <= 0) + return; + + // adapt the y paremeters... + int cy1 = clip.y(); + int cy2 = clip.y() + clip.height(); + int y = qRound(pt.y()); + if (y < cy1) { + int d = cy1 - y; + srcBits += srcBPL * d; + ih -= d; + y = cy1; + } + if (y + ih > cy2) { + int d = y + ih - cy2; + ih -= d; + } + if (ih <= 0) + return; + + // blit.. + int dstSize = rasterBuffer->bytesPerPixel(); + qsizetype dstBPL = rasterBuffer->bytesPerLine(); + const uint *src = (const uint *) srcBits; + uint *dst = reinterpret_cast<uint *>(rasterBuffer->buffer() + x * dstSize + y * dstBPL); + + const int len = iw * (qt_depthForFormat(rasterBuffer->format) >> 3); + for (int y = 0; y < ih; ++y) { + memcpy(dst, src, len); + dst = (quint32 *)(((uchar *) dst) + dstBPL); + src = (const quint32 *)(((const uchar *) src) + srcBPL); + } +} + void QRasterPaintEnginePrivate::systemStateChanged() { @@ -2160,7 +2231,15 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { + if (!clip) { + d->blitImage(pt, img, d->deviceRect); + return; + } else if (clip->hasRectClip) { + d->blitImage(pt, img, clip->clipRect); + return; + } + } else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { if (!clip) { @@ -2445,7 +2524,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe fillPath(path, &d->image_filler_xform); s->matrix = m; } else { - if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { + QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); + if (!clip) { + d->blitImage(pt, img, d->deviceRect, sr.toRect()); + return; + } else if (clip->hasRectClip) { + d->blitImage(pt, img, clip->clipRect, sr.toRect()); + return; + } + } else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); @@ -3668,6 +3756,33 @@ bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMod && !image.hasAlphaChannel())); } +bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const +{ + Q_Q(const QRasterPaintEngine); + const QRasterPaintEngineState *s = q->state(); + + if (!s->flags.fast_images || s->intOpacity != 256 || qt_depthForFormat(rasterBuffer->format) < 8) + return false; + + QImage::Format dFormat = rasterBuffer->format; + QImage::Format sFormat = image.format(); + // Formats must match or source format must be a subset of destination format + if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) { + if ((sFormat == QImage::Format_RGB32 && dFormat == QImage::Format_ARGB32) + || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888)) + sFormat = dFormat; + else + sFormat = qt_maybeAlphaVersionWithSameDepth(sFormat); // this returns premul formats + } + if (dFormat != sFormat) + return false; + + return s->matrix.type() <= QTransform::TxTranslate + && (mode == QPainter::CompositionMode_Source + || (mode == QPainter::CompositionMode_SourceOver + && !image.hasAlphaChannel())); +} + QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) { Q_ASSERT(image.depth() == 1); |