diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index abbe584d91b0b2320f830d9c7061d2ab6ef3fd8e..4a1765f1297e1c3c51cf61aef152f0de3b1aa28e 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -264,50 +264,86 @@ public: QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0) { - int sides = radius ? radius : qRound(qSqrt(weights.size())); - int half = qFloor(sides/2); + // weights 3x3 => delta 1 + int delta = radius ? radius : qFloor(qSqrt(weights.size()) / qreal(2)); + int filterDim = 2 * delta + 1; QImage dst = QImage(src.size(), src.format()); + int w = src.width(); int h = src.height(); - for (int y = 0; y < dst.height(); ++y) { - QRgb *dr = (QRgb*)dst.scanLine(y); - for (int x = 0; x < dst.width(); ++x) { - unsigned char* dRgb = ((unsigned char*)&dr[x]); - unsigned char red=0, green=0, blue=0, alpha=0; - int sy = y; - int sx = x; - - for (int cy=0; cy<sides; cy++) { - for (int cx=0; cx<sides; cx++) { - int scy = sy + cy - half; - int scx = sx + cx - half; - if (scy >= 0 && scy < h && scx >= 0 && scx < w) { - const QRgb *sr = (const QRgb*)(src.constScanLine(scy)); - const unsigned char* sRgb = ((const unsigned char*)&sr[scx]); - qreal wt = radius ? weights[0] : weights[cy*sides+cx]; - red += sRgb[0] * wt; - green += sRgb[1] * wt; - blue += sRgb[2] * wt; - alpha += sRgb[3] * wt; - } - } - } - dRgb[0] = red; - dRgb[1] = green; - dRgb[2] = blue; - dRgb[3] = alpha; - } + + const QRgb *sr = (const QRgb *)(src.constBits()); + int srcStride = src.bytesPerLine() / 4; + + QRgb *dr = (QRgb*)dst.bits(); + int dstStride = dst.bytesPerLine() / 4; + + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; + + qreal redF = 0; + qreal greenF = 0; + qreal blueF = 0; + qreal alphaF = 0; + + int sy = y; + int sx = x; + + for (int cy = 0; cy < filterDim; ++cy) { + int scy = sy + cy - delta; + + if (scy < 0 || scy >= h) + continue; + + const QRgb *sry = sr + scy * srcStride; + + for (int cx = 0; cx < filterDim; ++cx) { + int scx = sx + cx - delta; + + if (scx < 0 || scx >= w) + continue; + + const QRgb col = sry[scx]; + + if (radius) { + red += qRed(col); + green += qGreen(col); + blue += qBlue(col); + alpha += qAlpha(col); + } else { + qreal wt = weights[cy * filterDim + cx]; + + redF += qRed(col) * wt; + greenF += qGreen(col) * wt; + blueF += qBlue(col) * wt; + alphaF += qAlpha(col) * wt; + } + } + } + + if (radius) + dr[x] = qRgba(qRound(red * weights[0]), qRound(green * weights[0]), qRound(blue * weights[0]), qRound(alpha * weights[0])); + else + dr[x] = qRgba(qRound(redF), qRound(greenF), qRound(blueF), qRound(alphaF)); + } + + dr += dstStride; } + return dst; } void qt_image_boxblur(QImage& image, int radius, bool quality) { int passes = quality? 3: 1; - for (int i=0; i < passes; i++) { - image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0/(radius * radius * 1.0), radius); - } + int filterSize = 2 * radius + 1; + for (int i = 0; i < passes; ++i) + image = qt_image_convolute_filter(image, QVector<qreal>() << 1.0 / (filterSize * filterSize), radius); } static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator) diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp index e917623cb0df42df40582dbd74b5fd3da6ff5d03..237bd61c1bbbb39dbbc04b756689cd045b372606 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp @@ -75,7 +75,7 @@ namespace { shadowPainter.end(); if (blur > 0) - qt_image_boxblur(shadowImage, blur/2, true); + qt_image_boxblur(shadowImage, qMax(1, qRound(blur / 2)), true); // blacken the image with shadow color... shadowPainter.begin(&shadowImage);