summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qpaintengine_raster.cpp
diff options
context:
space:
mode:
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);