summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qpaintengine_raster.cpp
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-08-03 01:00:16 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2018-08-07 17:44:51 +0200
commit053e7cce79d4bef99ec85101b0d22bbb171072c5 (patch)
treec2059e82cccdea1fd0024c5942d1a834c28d39da /src/gui/painting/qpaintengine_raster.cpp
parenta420d02538d28854914a6978c9637a0ddd652146 (diff)
parentf271dd8f960ad9f61697dfa57b26c4071441cadc (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.cpp119
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);