/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: http://www.qt-project.org/
**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qquickcontext2dcommandbuffer_p.h"
#include "qquickcanvasitem_p.h"
-#include <qdeclarative.h>
+#include <qqml.h>
#include <QtCore/QMutex>
+#include <QtQuick/qsgtexture.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QPaintEngine>
+#include <QtGui/private/qopenglpaintengine_p.h>
#define HAS_SHADOW(offsetX, offsetY, blur, color) (color.isValid() && color.alpha() && (blur || offsetX || offsetY))
p->setCompositionMode(state.globalCompositeOperation);
}
+static void qt_drawImage(QPainter *p, QQuickContext2D::State& state, QImage image, const QRectF& sr, const QRectF& dr, bool shadow = false)
+{
+ Q_ASSERT(p);
+
+ if (image.isNull())
+ return;
+
+ qreal sx = sr.x();
+ qreal sy = sr.y();
+ qreal sw = sr.width();
+ qreal sh = sr.height();
+ qreal dx = dr.x();
+ qreal dy = dr.y();
+ qreal dw = dr.width();
+ qreal dh = dr.height();
+
+ if (sw == -1 || sh == -1) {
+ sw = image.width();
+ sh = image.height();
+ }
+ if (sx != 0 || sy != 0 || sw != image.width() || sh != image.height())
+ image = image.copy(sx, sy, sw, sh);
+
+ if (sw != dw || sh != dh)
+ image = image.scaled(dw, dh);
+
+ if (shadow) {
+ QImage shadow = makeShadowImage(image, state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
+ qreal shadow_dx = dx + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
+ qreal shadow_dy = dy + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
+ p->drawImage(shadow_dx, shadow_dy, shadow);
+ }
+ //Strange OpenGL painting behavior here, without beginNativePainting/endNativePainting, only the first image is painted.
+ p->beginNativePainting();
+ p->drawImage(dx, dy, image);
+ p->endNativePainting();
+}
+
void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& state)
{
if (!p)
reset();
- QTransform originMatrix = p->transform();
+ QTransform originMatrix = p->worldTransform();
QPen pen = makePen(state);
setPainterState(p, state, pen);
case QQuickContext2D::UpdateMatrix:
{
state.matrix = takeMatrix();
- p->setTransform(state.matrix * originMatrix);
+ p->setWorldTransform(state.matrix * originMatrix);
break;
}
case QQuickContext2D::ClearRect:
state.strokeStyle = takeStrokeStyle();
state.strokePatternRepeatX = takeBool();
state.strokePatternRepeatY = takeBool();
- pen.setBrush(state.strokeStyle);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setBrush(state.strokeStyle);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineWidth:
{
state.lineWidth = takeLineWidth();
- pen.setWidth(state.lineWidth);
- p->setPen(pen);
+ QPen nPen = p->pen();
+
+ nPen.setWidthF(state.lineWidth);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineCap:
{
state.lineCap = takeLineCap();
- pen.setCapStyle(state.lineCap);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setCapStyle(state.lineCap);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineJoin:
{
state.lineJoin = takeLineJoin();
- pen.setJoinStyle(state.lineJoin);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setJoinStyle(state.lineJoin);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::MiterLimit:
{
state.miterLimit = takeMiterLimit();
- pen.setMiterLimit(state.miterLimit);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setMiterLimit(state.miterLimit);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::TextAlign:
}
case QQuickContext2D::DrawImage:
{
- qreal sx = takeReal();
- qreal sy = takeReal();
- qreal sw = takeReal();
- qreal sh = takeReal();
- qreal dx = takeReal();
- qreal dy = takeReal();
- qreal dw = takeReal();
- qreal dh = takeReal();
- QImage image = takeImage();
-
- if (!image.isNull()) {
- if (sw == -1 || sh == -1) {
- sw = image.width();
- sh = image.height();
- }
- if (sx != 0 || sy != 0 || sw != image.width() || sh != image.height())
- image = image.copy(sx, sy, sw, sh);
-
- image = image.scaled(dw, dh);
-
- if (HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor)) {
- QImage shadow = makeShadowImage(image, state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
- qreal shadow_dx = dx + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
- qreal shadow_dy = dy + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
- p->drawImage(shadow_dx, shadow_dy, shadow);
+ QRectF sr = takeRect();
+ QRectF dr = takeRect();
+ qt_drawImage(p, state, takeImage(), sr, dr, HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor));
+ break;
+ }
+ case QQuickContext2D::DrawPixmap:
+ {
+ QRectF sr = takeRect();
+ QRectF dr = takeRect();
+
+ QQmlRefPointer<QQuickCanvasPixmap> pix = takePixmap();
+ Q_ASSERT(!pix.isNull());
+
+ const bool hasShadow = HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
+ if (p->paintEngine()->type() != QPaintEngine::OpenGL2 || hasShadow){
+ //TODO: generate shadow blur with shaders
+ qt_drawImage(p, state, pix->image(), sr, dr, hasShadow);
+ } else if (pix->texture()){
+ QSGTexture *tex = pix->texture();
+ QSGDynamicTexture *dynamicTexture = qobject_cast<QSGDynamicTexture *>(tex);
+ if (dynamicTexture)
+ dynamicTexture->updateTexture();
+
+ if (tex->textureId()) {
+
+ if (sr.width() < 0)
+ sr.setWidth(tex->textureSize().width());
+ if (sr.height() < 0)
+ sr.setHeight(tex->textureSize().height());
+
+ if (dr.width() < 0)
+ dr.setWidth(sr.width());
+ if (dr.height() < 0)
+ dr.setHeight(sr.height());
+
+ qreal srBottom = sr.bottom();
+ sr.setBottom(sr.top());
+ sr.setTop(srBottom);
+
+ tex->bind();
+ if (p->paintEngine()->type() == QPaintEngine::OpenGL2) {
+ QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx *>(p->paintEngine());
+ engine->drawTexture(dr, tex->textureId(), tex->textureSize(), sr);
+ }
}
- p->drawImage(dx, dy, image);
}
break;
}
, intIdx(0)
, boolIdx(0)
, realIdx(0)
+ , rectIdx(0)
, colorIdx(0)
, matrixIdx(0)
, brushIdx(0)
, pathIdx(0)
, imageIdx(0)
+ , pixmapIdx(0)
{
+ static bool registered = false;
+ if (!registered) {
+ qRegisterMetaType<QQuickContext2DCommandBuffer*>("QQuickContext2DCommandBuffer*");
+ registered = true;
+ }
}
ints.clear();
bools.clear();
reals.clear();
+ rects.clear();
colors.clear();
matrixes.clear();
brushes.clear();
pathes.clear();
images.clear();
+ pixmaps.clear();
reset();
}
intIdx = 0;
boolIdx = 0;
realIdx = 0;
+ rectIdx = 0;
colorIdx = 0;
matrixIdx = 0;
brushIdx = 0;
pathIdx = 0;
imageIdx = 0;
+ pixmapIdx = 0;
}
QT_END_NAMESPACE
-