diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 38bbc6689662e4e8153cd1f5b9e92a3701a6a04f..50a0a762670484fa85540806c90183d94e685af1 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 6a2469adc2609f7d4b82189d91abbeebd1abb5fe..1d0898115ddbef91cfd5174152ee204fe4e1c361 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 d5b959fd9f4dba90463edea787e77cfeac021f1d..bda2867696fb1a8fae0ee2f82554dfa7e65af08a 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 c96d0a99e3c0aa6099e3a5fbdc66766bb2f3be87..71033bd6d0f08abddc859a78293867202c372822 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 7f85c31ccbf3151b1b9084c65ac54649c4713e6a..69df506d2aa02e99f71b476d2063d28bba9b8be6 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 26b087284b1f6fbffd3801d97446d7bd2e1ff153..558e4d8ba49a88038ecc77e843228b8ff7981d80 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 0000000000000000000000000000000000000000..804567cf19f3f5a46a7ace11374a2b828a497806 --- /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 0000000000000000000000000000000000000000..b10554ad660161bf3ed7f4be4a982ffd871d7ba7 --- /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 0000000000000000000000000000000000000000..73cc53ed2be9eba992c6e13a0ed668f559efcd5f --- /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 0000000000000000000000000000000000000000..8356f02614ca5e9c8bf3d30d47ceca276cf2a3c2 --- /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 0000000000000000000000000000000000000000..9213589648a77c86734cc55378cfd5f3a325fe40 --- /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 0000000000000000000000000000000000000000..615abdee20bfabbd1f1b7966daef789d726b1103 --- /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 0000000000000000000000000000000000000000..58ed4d44dc5c91db84b97f2469485505e6124687 --- /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 0000000000000000000000000000000000000000..7e0045bf24a2c496753e002bb52e92e470fb91ed --- /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 0000000000000000000000000000000000000000..04c2d021f0359fbe0e80187e6f5945445c07b9a4 --- /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 0000000000000000000000000000000000000000..5210bab321ec2cd2488f320df66d1ce33e402320 --- /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 0000000000000000000000000000000000000000..2e89496c921fe3a9fe03166a63f068328d3479e5 --- /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 0000000000000000000000000000000000000000..4388601f13dbfb6b486d5bf8e15fbb3160011943 --- /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 0000000000000000000000000000000000000000..af240b09c3e0dcf48480f340e832c2a5231f67c7 Binary files /dev/null and b/tests/manual/scenegraph_lancelot/data/shared/uniquepixels.png differ