aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCharles Yin <charles.yin@nokia.com>2011-09-13 13:53:25 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-16 03:51:22 +0200
commita2e8238045820cb3d74aae9564e2efdba205a3eb (patch)
tree110979fa38ac2c9bf7eba3b06b199c7f490e7056 /src
parentef5f27339f34bc8d09077c1039d8e567e7fa69bd (diff)
fix broken canvas blur after merging refactor branch
Change-Id: If145f1d02566f839abeb50df167db2b237499290 Reviewed-on: http://codereview.qt-project.org/4857 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Charles Yin <charles.yin@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/declarative/items/context2d/qsgcontext2d.cpp194
-rw-r--r--src/declarative/items/context2d/qsgcontext2dcommandbuffer.cpp20
-rw-r--r--src/declarative/items/context2d/qsgcontext2dcommandbuffer_p.h5
3 files changed, 82 insertions, 137 deletions
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp
index af2676f0e3..6762c9160e 100644
--- a/src/declarative/items/context2d/qsgcontext2d.cpp
+++ b/src/declarative/items/context2d/qsgcontext2d.cpp
@@ -338,45 +338,52 @@ public:
QImage image;
};
-static QImage qt_texture_to_image(QSGTexture* texture)
-{
- if (!texture || !texture->textureId())
- return QImage();
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(GL_RGBA);
- format.setMipmap(false);
- QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(texture->textureSize(), format);
-#if 0
- // ### refactor
- fbo->drawTexture(QPointF(0,0), texture->textureId(), GL_TEXTURE_2D);
-#endif
- return fbo->toImage();
-}
-
-static QSGTexture* qt_item_to_texture(QSGItem* item)
-{
- if (!item)
- return 0;
- QSGShaderEffectTexture* texture = new QSGShaderEffectTexture(item);
- texture->setItem(QSGItemPrivate::get(item)->itemNode());
- texture->setLive(true);
-
- QRectF sourceRect = QRectF(0, 0, item->width(), item->height());
-
- texture->setRect(sourceRect);
- QSize textureSize = QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())));
- texture->setSize(textureSize);
- texture->setRecursive(false);
- texture->setFormat(GL_RGBA);
- texture->setHasMipmaps(false);
- texture->markDirtyTexture();
- texture->updateTexture();
- return texture;
-}
-
-static QImage qt_item_to_image(QSGItem* item) {
- return qt_texture_to_image(qt_item_to_texture(item));
+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);
+
+ 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 < w && scx >= 0 && scx < h) {
+ 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;
+ }
+ }
+ 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);
+ }
}
static QPainter::CompositionMode qt_composite_mode_from_string(const QString &compositeOperator)
@@ -1010,24 +1017,24 @@ static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
QV8Engine *engine = V8ENGINE();
- if (args.Length() == 2) {
- QSGContext2DEngineData *ed = engineData(engine);
- v8::Local<v8::Object> pattern = ed->constructorPattern->NewInstance();
- QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
+// if (args.Length() == 2) {
+// QSGContext2DEngineData *ed = engineData(engine);
+// v8::Local<v8::Object> pattern = ed->constructorPattern->NewInstance();
+// QV8Context2DStyleResource *r = new QV8Context2DStyleResource(engine);
- QImage img;
+// QImage img;
- QSGItem* item = qobject_cast<QSGItem*>(engine->toQObject(args[0]));
- if (item) {
- img = qt_item_to_image(item);
+// QSGItem* item = qobject_cast<QSGItem*>(engine->toQObject(args[0]));
+// if (item) {
+// img = qt_item_to_image(item);
// if (img.isNull()) {
// //exception: INVALID_STATE_ERR
// }
- } /*else {
- //exception: TYPE_MISMATCH_ERR
- }*/
+// } /*else {
+// //exception: TYPE_MISMATCH_ERR
+// }*/
- QString repetition = engine->toString(args[1]);
+// QString repetition = engine->toString(args[1]);
// if (repetition == "repeat" || repetition.isEmpty()) {
// //TODO
@@ -1040,10 +1047,10 @@ static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
// } else {
// //TODO: exception: SYNTAX_ERR
// }
- r->brush = img;
- pattern->SetExternalResource(r);
- return pattern;
- }
+// r->brush = img;
+// pattern->SetExternalResource(r);
+ // return pattern;
+// }
return v8::Null();
}
@@ -1558,7 +1565,7 @@ static v8::Handle<v8::Value> ctx2d_closePath(const v8::Arguments &args)
static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
- CHECK_CONTEXT(r)
+ CHECK_CONTEXT(r);
r->context->buffer()->fill(r->context->m_path);
@@ -1687,7 +1694,7 @@ static v8::Handle<v8::Value> ctx2d_ellipse(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 6) {
+ if (args.Length() == 4) {
r->context->ellipse(args[0]->NumberValue(),
args[1]->NumberValue(),
args[2]->NumberValue(),
@@ -2170,19 +2177,6 @@ static v8::Handle<v8::Value> ctx2d_imageData_mirror(const v8::Arguments &args)
horizontal = args[0]->BooleanValue();
vertical = args[1]->BooleanValue();
}
-#if 0
- // ### refactor
- // blur the alpha channel
- if (state.shadowBlur > 0) {
- QImage blurred(shadowImg.size(), QImage::Format_ARGB32);
- blurred.fill(0);
- QPainter blurPainter(&blurred);
- qt_blurImage(&blurPainter, shadowImg, state.shadowBlur, false, true);
- blurPainter.end();
- shadowImg = blurred;
- }
-#endif
-
r->image = r->image.mirrored(horizontal, vertical);
return args.This();
}
@@ -2250,18 +2244,15 @@ static v8::Handle<v8::Value> ctx2d_imageData_filter(const v8::Arguments &args)
break;
case QSGCanvasItem::Blur :
{
- QImage blurred(r->image.size(), QImage::Format_ARGB32);
- qreal blur = 10;
+ int radius = 3;
+ bool quality = false;
+
if (args.Length() > 1)
- blur = args[1]->NumberValue();
-
- blurred.fill(Qt::transparent);
- QPainter blurPainter(&blurred);
-#if 0
- qt_blurImage(&blurPainter, r->image, blur, true, false);
-#endif
- blurPainter.end();
- r->image = blurred;
+ radius = args[1]->IntegerValue() / 2;
+ if (args.Length() > 2)
+ quality = args[2]->BooleanValue();
+
+ qt_image_boxblur(r->image, radius, quality);
}
break;
case QSGCanvasItem::Opaque :
@@ -2278,45 +2269,10 @@ static v8::Handle<v8::Value> ctx2d_imageData_filter(const v8::Arguments &args)
{
if (args.Length() > 1 && args[1]->IsArray()) {
v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]);
- QVector<int> weights;
+ QVector<qreal> weights;
for (uint32_t i = 0; i < array->Length(); ++i)
weights.append(array->Get(i)->NumberValue());
- int sides = qRound(qSqrt(weights.size()));
- int half = qFloor(sides/2);
-
- QImage image = QImage(r->image.size(), QImage::Format_ARGB32);
- int w = r->image.width();
- int h = r->image.height();
- for (int y = 0; y < image.height(); ++y) {
- QRgb *dRow = (QRgb*)image.scanLine(y);
- for (int x = 0; x < image.width(); ++x) {
- unsigned char* dRgb = ((unsigned char*)&dRow[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 < w && scx >= 0 && scx < h) {
- QRgb *sRow = (QRgb*)(r->image.scanLine(scy));
- unsigned char* sRgb = ((unsigned char*)&sRow[scx]);
- int wt = 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;
- }
- }
- r->image = image;
+ r->image = qt_image_convolute_filter(r->image, weights);
} else {
//error
}
@@ -2932,7 +2888,7 @@ QSGContext2DEngineData::QSGContext2DEngineData(QV8Engine *engine)
ft->PrototypeTemplate()->Set(v8::String::New("moveTo"), V8FUNCTION(ctx2d_moveTo, engine));
ft->PrototypeTemplate()->Set(v8::String::New("quadraticCurveTo"), V8FUNCTION(ctx2d_quadraticCurveTo, engine));
ft->PrototypeTemplate()->Set(v8::String::New("rect"), V8FUNCTION(ctx2d_rect, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("roundedRect "), V8FUNCTION(ctx2d_roundedRect, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("roundedRect"), V8FUNCTION(ctx2d_roundedRect, engine));
ft->PrototypeTemplate()->Set(v8::String::New("text"), V8FUNCTION(ctx2d_text, engine));
ft->PrototypeTemplate()->Set(v8::String::New("ellipse"), V8FUNCTION(ctx2d_ellipse, engine));
ft->PrototypeTemplate()->Set(v8::String::New("stroke"), V8FUNCTION(ctx2d_stroke, engine));
diff --git a/src/declarative/items/context2d/qsgcontext2dcommandbuffer.cpp b/src/declarative/items/context2d/qsgcontext2dcommandbuffer.cpp
index 0448fa01c7..224f640abc 100644
--- a/src/declarative/items/context2d/qsgcontext2dcommandbuffer.cpp
+++ b/src/declarative/items/context2d/qsgcontext2dcommandbuffer.cpp
@@ -45,10 +45,13 @@
#include <QtCore/QMutex>
#define HAS_SHADOW(offsetX, offsetY, blur, color) (color.isValid() && color.alpha() && (blur || offsetX || offsetY))
+
+void qt_image_boxblur(QImage& image, int radius, bool quality);
+
static QImage makeShadowImage(const QImage& image, qreal offsetX, qreal offsetY, qreal blur, const QColor& color)
{
- QImage shadowImg(image.width() + blur * 2 + qAbs(offsetX),
- image.height() + blur *2 + qAbs(offsetY),
+ QImage shadowImg(image.width() + blur + qAbs(offsetX),
+ image.height() + blur + qAbs(offsetY),
QImage::Format_ARGB32);
shadowImg.fill(0);
QPainter tmpPainter(&shadowImg);
@@ -59,17 +62,8 @@ static QImage makeShadowImage(const QImage& image, qreal offsetX, qreal offsetY,
tmpPainter.drawImage(shadowX, shadowY, image);
tmpPainter.end();
- // blur the alpha channel
- if (blur > 0) {
- QImage blurred(shadowImg.size(), QImage::Format_ARGB32);
- blurred.fill(0);
- QPainter blurPainter(&blurred);
-#if 0
- qt_blurImage(&blurPainter, shadowImg, blur, true, false);
-#endif
- blurPainter.end();
- shadowImg = blurred;
- }
+ if (blur > 0)
+ qt_image_boxblur(shadowImg, blur/2, true);
// blacken the image with shadow color...
tmpPainter.begin(&shadowImg);
diff --git a/src/declarative/items/context2d/qsgcontext2dcommandbuffer_p.h b/src/declarative/items/context2d/qsgcontext2dcommandbuffer_p.h
index d238027c05..d95adeeafd 100644
--- a/src/declarative/items/context2d/qsgcontext2dcommandbuffer_p.h
+++ b/src/declarative/items/context2d/qsgcontext2dcommandbuffer_p.h
@@ -45,11 +45,6 @@
#include "qsgcontext2d_p.h"
#include "qdeclarativepixmapcache_p.h"
-// Note, this is exported but in a private header as qtopengl depends on it.
-// But it really should be considered private API
-void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
-void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
-
QT_BEGIN_HEADER