aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickborderimage.cpp381
-rw-r--r--src/quick/items/qquickborderimage_p.h2
-rw-r--r--src/quick/items/qquickborderimage_p_p.h10
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h12
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp57
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode_p.h3
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_smoothed.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_border_overlap.qml31
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_negative_borders.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_borders.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_bottom.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_center.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_left.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right_left.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top_bottom.qml34
-rw-r--r--tests/manual/scenegraph_lancelot/data/shared/uniquepixels.pngbin0 -> 210 bytes
19 files changed, 798 insertions, 72 deletions
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 38bbc66896..50a0a76267 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -540,90 +540,347 @@ void QQuickBorderImage::doUpdate()
update();
}
+QImage QQuickBorderImage::shallowCopy(const QImage &image, const QRect &rect)
+{
+ if (image.depth() == 1) {
+ return image.copy(rect);
+ } else {
+ const uchar *bits = image.constBits() + image.bytesPerLine() * rect.y() + (image.depth() / 8) * rect.x();
+ return QImage(bits, rect.width(), rect.height(), image.bytesPerLine(), image.format());
+ }
+}
+
QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickBorderImage);
- QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
-
- if (!texture || width() <= 0 || height() <= 0) {
+ if (!d->pix.isReady() || width() <= 0 || height() <= 0) {
delete oldNode;
return 0;
}
- QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
-
- bool updatePixmap = d->pixmapChanged;
- d->pixmapChanged = false;
- if (!node) {
- node = d->sceneGraphContext()->createImageNode();
- updatePixmap = true;
- }
-
- if (updatePixmap)
- node->setTexture(texture);
-
// Don't implicitly create the scalegrid in the rendering thread...
QRectF innerSourceRect(0, 0, 1, 1);
- QRectF targetRect(0, 0, width(), height());
- QRectF innerTargetRect = targetRect;
+ QRectF innerTargetRect(0, 0, width(), height());
+ int borderLeft, borderTop, borderRight, borderBottom;
if (d->border) {
const QQuickScaleGrid *border = d->getScaleGrid();
- innerSourceRect = QRectF(border->left() / qreal(d->pix.width()),
- border->top() / qreal(d->pix.height()),
- qMax<qreal>(0, d->pix.width() - border->right() - border->left()) / d->pix.width(),
- qMax<qreal>(0, d->pix.height() - border->bottom() - border->top()) / d->pix.height());
- innerTargetRect = QRectF(border->left(),
- border->top(),
+
+ borderLeft = qBound(0, border->left(), d->pix.width());
+ borderTop = qBound(0, border->top(), d->pix.height());
+ borderRight = d->pix.rect().width() - qBound(0, border->right(), d->pix.rect().width() - borderLeft);
+ borderBottom = d->pix.rect().height() - qBound(0, border->bottom(), d->pix.rect().height() - borderTop);
+
+ innerSourceRect = QRectF(borderLeft / qreal(d->pix.width()),
+ borderTop / qreal(d->pix.height()),
+ qMax<qreal>(0, borderRight - borderLeft) / d->pix.width(),
+ qMax<qreal>(0, borderBottom - borderTop) / d->pix.height());
+ innerTargetRect = QRectF(borderLeft,
+ borderTop,
qMax<qreal>(0, width() - border->right() - border->left()),
qMax<qreal>(0, height() - border->bottom() - border->top()));
}
- qreal hTiles = 1;
- qreal vTiles = 1;
- if (innerSourceRect.width() != 0) {
- switch (d->horizontalTileMode) {
- case QQuickBorderImage::Repeat:
- hTiles = innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width());
- break;
- case QQuickBorderImage::Round:
- hTiles = qCeil(innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width()));
- break;
- default:
- break;
+
+ bool updatePixmap = d->pixmapChanged;
+ d->pixmapChanged = false;
+ if (!oldNode) {
+ oldNode = new QSGNode;
+ updatePixmap = true;
+
+ for (int i=0; i<9; ++i)
+ d->regions[i].node = 0;
+
+ if (innerSourceRect.left() > 0) {
+ if (innerSourceRect.top() > 0)
+ d->regions[0].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.bottom() < 1)
+ d->regions[6].node = d->sceneGraphContext()->createImageNode();
+
+ if (innerSourceRect.top() < innerSourceRect.bottom())
+ d->regions[3].node = d->sceneGraphContext()->createImageNode();
+ }
+
+ if (innerSourceRect.right() < 1) {
+ if (innerSourceRect.top() > 0)
+ d->regions[2].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.bottom() < 1)
+ d->regions[8].node = d->sceneGraphContext()->createImageNode();
+
+ if (innerSourceRect.top() < innerSourceRect.bottom())
+ d->regions[5].node = d->sceneGraphContext()->createImageNode();
+ }
+
+ if (innerSourceRect.top() > 0 && innerSourceRect.left() < innerSourceRect.right())
+ d->regions[1].node = d->sceneGraphContext()->createImageNode();
+
+ if (innerSourceRect.bottom() < 1 && innerSourceRect.left() < innerSourceRect.right())
+ d->regions[7].node = d->sceneGraphContext()->createImageNode();
+
+ if (innerSourceRect.left() < innerSourceRect.right() && innerSourceRect.top() < innerSourceRect.bottom())
+ d->regions[4].node = d->sceneGraphContext()->createImageNode();
+
+ for (int i=0; i<9; ++i) {
+ if (d->regions[i].node != 0)
+ oldNode->appendChildNode(d->regions[i].node);
}
}
- if (innerSourceRect.height() != 0) {
- switch (d->verticalTileMode) {
- case QQuickBorderImage::Repeat:
- vTiles = innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height());
- break;
- case QQuickBorderImage::Round:
- vTiles = qCeil(innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height()));
- break;
- default:
- break;
+
+
+ QImage image = d->pix.image();
+
+ if (d->regions[0].node != 0) {
+ if (updatePixmap)
+ d->regions[0].image = shallowCopy(image, QRect(QPoint(0, 0), QSize(borderLeft, borderTop)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingLeft | QSGImageNode::AntialiasingTop);
+ if (d->regions[1].node == 0 && d->regions[2].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[3].node == 0 && d->regions[6].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ d->regions[0].node->setAntialiasing(antialiasing);
+
+ QRectF rect(0,
+ 0,
+ innerTargetRect.left(),
+ innerTargetRect.top());
+ d->regions[0].node->setTargetRect(rect);
+ d->regions[0].node->setInnerTargetRect(rect);
+ d->regions[0].targetRect = rect;
+ }
+
+ if (d->regions[1].node != 0) {
+ if (updatePixmap)
+ d->regions[1].image = shallowCopy(image, QRect(QPoint(borderLeft, 0), QSize(borderRight - borderLeft, borderTop)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingTop;
+ if (d->regions[0].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[2].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[4].node == 0 && d->regions[7].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ d->regions[1].node->setAntialiasing(antialiasing);
+
+ QRectF rect(innerTargetRect.left(),
+ 0,
+ innerTargetRect.width(),
+ innerTargetRect.top());
+ d->regions[1].node->setTargetRect(rect);
+ d->regions[1].node->setInnerTargetRect(rect);
+ d->regions[1].targetRect = rect;
+ }
+
+ if (d->regions[2].node != 0) {
+ if (updatePixmap)
+ d->regions[2].image = shallowCopy(image, QRect(QPoint(borderRight, 0), QSize(d->pix.rect().width() - borderRight, borderTop)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingTop | QSGImageNode::AntialiasingRight);
+ if (d->regions[0].node == 0 && d->regions[1].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[5].node == 0 && d->regions[8].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ d->regions[2].node->setAntialiasing(antialiasing);
+
+ QRectF rect(innerTargetRect.right(),
+ 0,
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ innerTargetRect.top());
+ d->regions[2].node->setTargetRect(rect);
+ d->regions[2].node->setInnerTargetRect(rect);
+ d->regions[2].targetRect = rect;
+ }
+
+ if (d->regions[3].node != 0) {
+ if (updatePixmap)
+ d->regions[3].image = shallowCopy(image, QRect(QPoint(0, borderTop), QSize(borderLeft, borderBottom - borderTop)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingLeft;
+ if (d->regions[4].node == 0 && d->regions[5].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[6].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ if (d->regions[0].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ d->regions[3].node->setAntialiasing(antialiasing);
+
+ QRectF rect(0,
+ innerTargetRect.top(),
+ innerTargetRect.left(),
+ innerTargetRect.height());
+ d->regions[3].node->setTargetRect(rect);
+ d->regions[3].node->setInnerTargetRect(rect);
+ d->regions[3].targetRect = rect;
+ }
+
+ if (d->regions[4].node != 0) {
+ if (updatePixmap) {
+ if (innerSourceRect == QRectF(0, 0, 1, 1)) {
+ d->regions[4].image = image;
+ } else {
+ d->regions[4].image = shallowCopy(image, QRect(QPoint(borderLeft, borderTop), QSize(borderRight - borderLeft, borderBottom - borderTop)));
+ }
}
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingNone;
+ if (d->regions[3].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[5].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[1].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ if (d->regions[7].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ d->regions[4].node->setAntialiasing(antialiasing);
+
+ d->regions[4].node->setInnerTargetRect(innerTargetRect);
+ d->regions[4].node->setTargetRect(innerTargetRect);
+ d->regions[4].targetRect = innerTargetRect;
}
- node->setTargetRect(targetRect);
- node->setInnerSourceRect(innerSourceRect);
- node->setInnerTargetRect(innerTargetRect);
- node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
- node->setMirror(d->mirror);
-
- node->setMipmapFiltering(QSGTexture::None);
- node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
- if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) {
- node->setHorizontalWrapMode(QSGTexture::Repeat);
- node->setVerticalWrapMode(QSGTexture::Repeat);
- } else {
- node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- node->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ if (d->regions[5].node != 0) {
+ if (updatePixmap)
+ d->regions[5].image = shallowCopy(image, QRect(QPoint(borderRight, borderTop), QSize(d->pix.rect().width() - borderRight, borderBottom - borderTop)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingRight;
+ if (d->regions[4].node == 0 && d->regions[3].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[2].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ if (d->regions[8].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingBottom;
+ d->regions[5].node->setAntialiasing(antialiasing);
+
+ QRectF rect(innerTargetRect.right(),
+ innerTargetRect.top(),
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ innerTargetRect.height());
+ d->regions[5].node->setTargetRect(rect);
+ d->regions[5].node->setInnerTargetRect(rect);
+ d->regions[5].targetRect = rect;
+ }
+
+ if (d->regions[6].node != 0) {
+ if (updatePixmap)
+ d->regions[6].image = shallowCopy(image, QRect(QPoint(0, borderBottom), QSize(borderLeft, d->pix.rect().height() - borderBottom)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingLeft);
+ if (d->regions[7].node == 0 && d->regions[8].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[3].node == 0 && d->regions[0].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ d->regions[6].node->setAntialiasing(antialiasing);
+
+ QRectF rect(0,
+ innerTargetRect.bottom(),
+ innerTargetRect.left(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+ d->regions[6].node->setTargetRect(rect);
+ d->regions[6].node->setInnerTargetRect(rect);
+ d->regions[6].targetRect = rect;
+ }
+
+ if (d->regions[7].node != 0) {
+ if (updatePixmap)
+ d->regions[7].image = shallowCopy(image, QRect(QPoint(borderLeft, borderBottom), QSize(borderRight - borderLeft, d->pix.rect().height() - borderBottom)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingBottom;
+ if (d->regions[6].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[8].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingRight;
+ if (d->regions[4].node == 0 && d->regions[1].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ d->regions[7].node->setAntialiasing(antialiasing);
+
+ QRectF rect(innerTargetRect.left(),
+ innerTargetRect.bottom(),
+ innerTargetRect.width(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+ d->regions[7].node->setTargetRect(rect);
+ d->regions[7].node->setInnerTargetRect(rect);
+ d->regions[7].targetRect = rect;
+ }
+
+ if (d->regions[8].node != 0) {
+ if (updatePixmap)
+ d->regions[8].image = shallowCopy(image, QRect(QPoint(borderRight, borderBottom), QSize(d->pix.rect().width() - borderRight, d->pix.rect().height() - borderBottom)));
+
+ QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingRight);
+ if (d->regions[7].node == 0 && d->regions[6].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingLeft;
+ if (d->regions[5].node == 0 && d->regions[2].node == 0)
+ antialiasing |= QSGImageNode::AntialiasingTop;
+ d->regions[8].node->setAntialiasing(antialiasing);
+
+ QRectF rect(innerTargetRect.right(),
+ innerTargetRect.bottom(),
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+ d->regions[8].node->setTargetRect(rect);
+ d->regions[8].node->setInnerTargetRect(rect);
+ d->regions[8].targetRect = rect;
+ }
+
+ for (int i=0; i<9; ++i) {
+ if (d->regions[i].node != 0) {
+ if (updatePixmap) {
+ QQuickTextureFactory *textureFactory = QSGContext::createTextureFactoryFromImage(d->regions[i].image);
+ if (textureFactory == 0)
+ textureFactory = new QQuickDefaultTextureFactory(d->regions[i].image);
+ d->regions[i].textureFactory.reset(textureFactory);
+ d->regions[i].node->setTexture(d->sceneGraphRenderContext()->textureForFactory(d->regions[i].textureFactory.data(),
+ window()));
+ }
+
+ d->regions[i].node->setInnerSourceRect(QRectF(0, 0, 1, 1));
+ d->regions[i].node->setMipmapFiltering(QSGTexture::None);
+ d->regions[i].node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
+ d->regions[i].node->setMirror(d->mirror);
+
+
+ qreal hTiles = 1;
+ qreal vTiles = 1;
+
+ if (innerSourceRect.width() != 0) {
+ switch (d->horizontalTileMode) {
+ case QQuickBorderImage::Repeat:
+ hTiles = d->regions[i].targetRect.width() / qreal(d->regions[i].image.width());
+ break;
+ case QQuickBorderImage::Round:
+ hTiles = qCeil(d->regions[i].targetRect.width() / qreal(d->regions[i].image.width()));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (innerSourceRect.height() != 0) {
+ switch (d->verticalTileMode) {
+ case QQuickBorderImage::Repeat:
+ vTiles = d->regions[i].targetRect.height() / qreal(d->regions[i].image.height());
+ break;
+ case QQuickBorderImage::Round:
+ vTiles = qCeil(d->regions[i].targetRect.height() / qreal(d->regions[i].image.height()));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (vTiles > 1 || hTiles > 1) {
+ d->regions[i].node->setHorizontalWrapMode(QSGTexture::Repeat);
+ d->regions[i].node->setVerticalWrapMode(QSGTexture::Repeat);
+ } else {
+ d->regions[i].node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ d->regions[i].node->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ }
+
+ d->regions[i].node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
+ d->regions[i].node->update();
+ }
}
- node->setAntialiasing(d->antialiasing);
- node->update();
- return node;
+ return oldNode;
}
void QQuickBorderImage::pixmapChange()
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 6a2469adc2..1d0898115d 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -87,6 +87,8 @@ private Q_SLOTS:
void sciRequestFinished();
private:
+ static QImage shallowCopy(const QImage &image, const QRect &rect);
+
Q_DISABLE_COPY(QQuickBorderImage)
Q_DECLARE_PRIVATE(QQuickBorderImage)
};
diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h
index d5b959fd9f..bda2867696 100644
--- a/src/quick/items/qquickborderimage_p_p.h
+++ b/src/quick/items/qquickborderimage_p_p.h
@@ -89,6 +89,16 @@ public:
QQuickBorderImage::TileMode verticalTileMode;
int redirectCount;
+ struct BorderImageRegion
+ {
+ BorderImageRegion() : node(0), textureFactory(0) {}
+ QImage image;
+ QSGImageNode *node;
+ QScopedPointer<QQuickTextureFactory> textureFactory;
+ QRectF targetRect;
+ };
+ BorderImageRegion regions[9];
+
bool pixmapChanged : 1;
};
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index c96d0a99e3..71033bd6d0 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -126,6 +126,17 @@ public:
class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode
{
public:
+ enum AntialiasingFlag
+ {
+ AntialiasingNone = 0,
+ AntialiasingLeft = 1,
+ AntialiasingRight = 2,
+ AntialiasingTop = 4,
+ AntialiasingBottom = 8,
+ AntialiasingAll = AntialiasingLeft | AntialiasingRight | AntialiasingBottom | AntialiasingTop
+ };
+ Q_DECLARE_FLAGS(AntialiasingFlags, AntialiasingFlag)
+
virtual void setTargetRect(const QRectF &rect) = 0;
virtual void setInnerTargetRect(const QRectF &rect) = 0;
virtual void setInnerSourceRect(const QRectF &rect) = 0;
@@ -140,6 +151,7 @@ public:
virtual void setFiltering(QSGTexture::Filtering filtering) = 0;
virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
+ virtual void setAntialiasing(AntialiasingFlags flags) { Q_UNUSED(flags); }
virtual void update() = 0;
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
index 7f85c31ccb..69df506d2a 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -140,10 +140,11 @@ void SmoothTextureMaterialShader::initialize()
QSGDefaultImageNode::QSGDefaultImageNode()
: m_innerSourceRect(0, 0, 1, 1)
, m_subSourceRect(0, 0, 1, 1)
- , m_antialiasing(false)
, m_mirror(false)
, m_dirtyGeometry(false)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+ , m_antialiasing(AntialiasingNone)
+
{
setMaterial(&m_materialO);
setOpaqueMaterial(&m_material);
@@ -249,10 +250,20 @@ void QSGDefaultImageNode::setTexture(QSGTexture *texture)
void QSGDefaultImageNode::setAntialiasing(bool antialiasing)
{
- if (antialiasing == m_antialiasing)
+ AntialiasingFlags antialiasingFlags = antialiasing
+ ? AntialiasingAll
+ : AntialiasingNone;
+
+ setAntialiasing(antialiasingFlags);
+}
+
+void QSGDefaultImageNode::setAntialiasing(AntialiasingFlags antialiasingFlags)
+{
+ if (antialiasingFlags == m_antialiasing)
return;
- m_antialiasing = antialiasing;
- if (m_antialiasing) {
+
+ m_antialiasing = antialiasingFlags;
+ if (m_antialiasing != AntialiasingNone) {
setMaterial(&m_smoothMaterial);
setOpaqueMaterial(0);
setGeometry(new QSGGeometry(smoothAttributeSet(), 0));
@@ -364,11 +375,14 @@ void QSGDefaultImageNode::updateGeometry()
}
// An image can be rendered as a single quad if:
+ // - There is antialiasing on all or no edges
// - There are no margins, and either:
// - the image isn't repeated
// - the source rectangle fills the entire texture so that texture wrapping can be used,
// and NPOT is supported
- if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) {
+ if (!hasMargins
+ && (m_antialiasing == AntialiasingAll || m_antialiasing == AntialiasingNone)
+ && (!hasTiles || (fullTexture && wrapSupported))) {
QRectF sr;
if (!fullTexture) {
sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(),
@@ -547,10 +561,35 @@ void QSGDefaultImageNode::updateGeometry()
topDv = bottomDv *= 0.5f;
}
+ if (!m_antialiasing.testFlag(AntialiasingTop)) {
+ topDy = 0.0f;
+ topDv = 0.0f;
+ }
+
+ if (!m_antialiasing.testFlag(AntialiasingBottom)) {
+ bottomDy = 0.0f;
+ bottomDv = 0.0f;
+ }
+
+ if (!m_antialiasing.testFlag(AntialiasingLeft)) {
+ leftDx = 0.0f;
+ leftDu = 0.0f;
+ }
+
+ if (!m_antialiasing.testFlag(AntialiasingRight)) {
+ rightDx = 0.0f;
+ rightDu = 0.0f;
+ }
+
// This delta is how much the fuzziness can reach out from the image.
float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
? m_targetRect.width() : m_targetRect.height()) * 0.5f;
+ float deltaTop = m_antialiasing.testFlag(AntialiasingTop) ? delta : 0.0f;
+ float deltaBottom = m_antialiasing.testFlag(AntialiasingBottom) ? delta : 0.0f;
+ float deltaLeft = m_antialiasing.testFlag(AntialiasingLeft) ? delta : 0.0f;
+ float deltaRight = m_antialiasing.testFlag(AntialiasingRight) ? delta : 0.0f;
+
quint16 index = 0;
ys = yData.data();
for (int j = 0; j < vCells; ++j, ys += 2) {
@@ -600,28 +639,28 @@ void QSGDefaultImageNode::updateGeometry()
if (isTop) {
vertices[topLeft].dy = vertices[topRight].dy = topDy;
vertices[topLeft].dv = vertices[topRight].dv = topDv;
- vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta;
+ vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -deltaTop;
appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
}
if (isBottom) {
vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv;
- vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta;
+ vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = deltaBottom;
appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
}
if (isLeft) {
vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
vertices[topLeft].du = vertices[bottomLeft].du = leftDu;
- vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta;
+ vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -deltaLeft;
appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
}
if (isRight) {
vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
vertices[topRight].du = vertices[bottomRight].du = -rightDu;
- vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta;
+ vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = deltaRight;
appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
}
}
diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h
index 26b087284b..558e4d8ba4 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode_p.h
+++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h
@@ -62,6 +62,7 @@ public:
virtual void setSubSourceRect(const QRectF &rect);
virtual void setTexture(QSGTexture *t);
virtual void setAntialiasing(bool antialiasing);
+ virtual void setAntialiasing(AntialiasingFlags antialiasing);
virtual void setMirror(bool mirror);
virtual void update();
@@ -84,11 +85,11 @@ private:
QSGTextureMaterial m_materialO;
QSGSmoothTextureMaterial m_smoothMaterial;
- uint m_antialiasing : 1;
uint m_mirror : 1;
uint m_dirtyGeometry : 1;
QSGGeometry m_geometry;
+ AntialiasingFlags m_antialiasing;
};
QT_END_NAMESPACE
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_smoothed.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_smoothed.qml
new file mode 100644
index 0000000000..804567cf19
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_smoothed.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: true
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 1
+ border.right: 1
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed.qml
new file mode 100644
index 0000000000..b10554ad66
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 1
+ border.right: 1
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_border_overlap.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_border_overlap.qml
new file mode 100644
index 0000000000..73cc53ed2b
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_border_overlap.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 0
+ border.left: 3
+ border.right: 3
+ border.top: 0
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_negative_borders.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_negative_borders.qml
new file mode 100644
index 0000000000..8356f02614
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_negative_borders.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: -1
+ border.left: -1
+ border.right: -1
+ border.top: -1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_borders.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_borders.qml
new file mode 100644
index 0000000000..9213589648
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_borders.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 0
+ border.left: 0
+ border.right: 0
+ border.top: 0
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_bottom.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_bottom.qml
new file mode 100644
index 0000000000..615abdee20
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_bottom.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 0
+ border.left: 1
+ border.right: 1
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_center.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_center.qml
new file mode 100644
index 0000000000..58ed4d44dc
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_center.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 4
+ border.left: 4
+ border.right: 4
+ border.top: 4
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_left.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_left.qml
new file mode 100644
index 0000000000..7e0045bf24
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_left.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 0
+ border.right: 1
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right.qml
new file mode 100644
index 0000000000..04c2d021f0
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 1
+ border.right: 0
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right_left.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right_left.qml
new file mode 100644
index 0000000000..5210bab321
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_right_left.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 0
+ border.right: 0
+ border.top: 1
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top.qml
new file mode 100644
index 0000000000..2e89496c92
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 1
+ border.left: 1
+ border.right: 1
+ border.top: 0
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top_bottom.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top_bottom.qml
new file mode 100644
index 0000000000..4388601f13
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_rotated_unsmoothed_no_top_bottom.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/uniquepixels.png"
+
+ width: 8
+ height: 8
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+ rotation: 10
+ scale: 10
+
+ border.bottom: 0
+ border.left: 1
+ border.right: 1
+ border.top: 0
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/shared/uniquepixels.png b/tests/manual/scenegraph_lancelot/data/shared/uniquepixels.png
new file mode 100644
index 0000000000..af240b09c3
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shared/uniquepixels.png
Binary files differ