From a8925e668aca0e1d2b90308c8286e5bb68f9ee42 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Tue, 5 Jul 2011 13:06:54 +1000 Subject: [PATCH] Improvements to Image element - add Image.Pad as a fillMode - add horizontal and vertical alignment properties Task-number: QTBUG-18291 Change-Id: Iaaf3b2d02c47ad01d2c8b49d146f1a9401b2558d Reviewed-on: http://codereview.qt.nokia.com/1468 Reviewed-by: Qt Sanity Bot Reviewed-by: Martin Jones Reviewed-by: Yann Bodson --- src/declarative/items/qsgimage.cpp | 91 ++++++++++++++++++-- src/declarative/items/qsgimage_p.h | 22 +++++- src/declarative/items/qsgimage_p_p.h | 2 + tests/systemtests/declarative/qsgimage/ImageNG.qml | 19 ++++ .../systemtests/declarative/qsgimage/img-align.qml | 92 ++++++++++++++++++++ tests/systemtests/declarative/qsgimage/qt-logo.png | Bin 0 -> 5149 bytes 6 files changed, 217 insertions(+), 9 deletions(-) create mode 100644 tests/systemtests/declarative/qsgimage/ImageNG.qml create mode 100644 tests/systemtests/declarative/qsgimage/img-align.qml create mode 100644 tests/systemtests/declarative/qsgimage/qt-logo.png diff --git a/src/declarative/items/qsgimage.cpp b/src/declarative/items/qsgimage.cpp index ee4ea2b..b77a654 100644 --- a/src/declarative/items/qsgimage.cpp +++ b/src/declarative/items/qsgimage.cpp @@ -46,6 +46,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -54,6 +55,8 @@ QSGImagePrivate::QSGImagePrivate() , paintedWidth(0) , paintedHeight(0) , pixmapChanged(false) + , hAlign(QSGImage::AlignHCenter) + , vAlign(QSGImage::AlignVCenter) { } @@ -155,6 +158,9 @@ void QSGImage::updatePaintedGeometry() d->paintedHeight = heightScale * qreal(d->pix.height()); d->paintedWidth = widthScale * qreal(d->pix.width()); + } else if (d->fillMode == Pad) { + d->paintedWidth = d->pix.width(); + d->paintedHeight = d->pix.height(); } else { d->paintedWidth = width(); d->paintedHeight = height(); @@ -218,6 +224,21 @@ QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge; QSGTexture::WrapMode vWrap = QSGTexture::ClampToEdge; + qreal pixWidth = (d->fillMode == PreserveAspectFit) ? d->paintedWidth : d->pix.width(); + qreal pixHeight = (d->fillMode == PreserveAspectFit) ? d->paintedHeight : d->pix.height(); + + int xOffset = 0; + if (d->hAlign == QSGImage::AlignHCenter) + xOffset = qCeil((width() - pixWidth) / 2.); + else if (d->hAlign == QSGImage::AlignRight) + xOffset = qCeil(width() - pixWidth); + + int yOffset = 0; + if (d->vAlign == QSGImage::AlignVCenter) + yOffset = qCeil((height() - pixHeight) / 2.); + else if (d->vAlign == QSGImage::AlignBottom) + yOffset = qCeil(height() - pixHeight); + switch (d->fillMode) { default: case Stretch: @@ -226,8 +247,7 @@ QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) break; case PreserveAspectFit: - targetRect = QRectF((width() - d->paintedWidth) / 2., (height() - d->paintedHeight) / 2., - d->paintedWidth, d->paintedHeight); + targetRect = QRectF(xOffset, yOffset, d->paintedWidth, d->paintedHeight); sourceRect = d->pix.rect(); break; @@ -238,33 +258,52 @@ QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) if (wscale > hscale) { int src = (hscale / wscale) * qreal(d->pix.height()); - sourceRect = QRectF(0, (d->pix.height() - src) / 2, d->pix.width(), src); + int y = 0; + if (d->vAlign == QSGImage::AlignVCenter) + y = qCeil((d->pix.height() - src) / 2.); + else if (d->vAlign == QSGImage::AlignBottom) + y = qCeil(d->pix.height() - src); + sourceRect = QRectF(0, y, d->pix.width(), src); + } else { int src = (wscale / hscale) * qreal(d->pix.width()); - sourceRect = QRectF((d->pix.width() - src) / 2, 0, src, d->pix.height()); + int x = 0; + if (d->hAlign == QSGImage::AlignHCenter) + x = qCeil((d->pix.width() - src) / 2.); + else if (d->hAlign == QSGImage::AlignRight) + x = qCeil(d->pix.width() - src); + sourceRect = QRectF(x, 0, src, d->pix.height()); + } } - } break; case Tile: targetRect = QRectF(0, 0, width(), height()); - sourceRect = QRectF(0, 0, width(), height()); + sourceRect = QRectF(-xOffset, -yOffset, width(), height()); hWrap = QSGTexture::Repeat; vWrap = QSGTexture::Repeat; break; case TileHorizontally: targetRect = QRectF(0, 0, width(), height()); - sourceRect = QRectF(0, 0, width(), d->pix.height()); + sourceRect = QRectF(-xOffset, 0, width(), d->pix.height()); hWrap = QSGTexture::Repeat; break; case TileVertically: targetRect = QRectF(0, 0, width(), height()); - sourceRect = QRectF(0, 0, d->pix.width(), height()); + sourceRect = QRectF(0, -yOffset, d->pix.width(), height()); vWrap = QSGTexture::Repeat; break; + case Pad: + qreal w = qMin(qreal(d->pix.width()), width()); + qreal h = qMin(qreal(d->pix.height()), height()); + qreal x = (d->pix.width() > width()) ? -xOffset : 0; + qreal y = (d->pix.height() > height()) ? -yOffset : 0; + targetRect = QRectF(x + xOffset, y + yOffset, w, h); + sourceRect = QRectF(x, y, w, h); + break; }; QRectF nsrect(sourceRect.x() / d->pix.width(), @@ -302,4 +341,40 @@ void QSGImage::pixmapChange() d->pixmapChanged = true; } +QSGImage::VAlignment QSGImage::verticalAlignment() const +{ + Q_D(const QSGImage); + return d->vAlign; +} + +void QSGImage::setVerticalAlignment(VAlignment align) +{ + Q_D(QSGImage); + if (d->vAlign == align) + return; + + d->vAlign = align; + update(); + updatePaintedGeometry(); + emit verticalAlignmentChanged(align); +} + +QSGImage::HAlignment QSGImage::horizontalAlignment() const +{ + Q_D(const QSGImage); + return d->hAlign; +} + +void QSGImage::setHorizontalAlignment(HAlignment align) +{ + Q_D(QSGImage); + if (d->hAlign == align) + return; + + d->hAlign = align; + update(); + updatePaintedGeometry(); + emit horizontalAlignmentChanged(align); +} + QT_END_NAMESPACE diff --git a/src/declarative/items/qsgimage_p.h b/src/declarative/items/qsgimage_p.h index 7fc2940..4faf96d 100644 --- a/src/declarative/items/qsgimage_p.h +++ b/src/declarative/items/qsgimage_p.h @@ -57,11 +57,15 @@ class Q_AUTOTEST_EXPORT QSGImage : public QSGImageBase, public QSGTextureProvide { Q_OBJECT Q_ENUMS(FillMode) + Q_ENUMS(HAlignment) + Q_ENUMS(VAlignment) Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedGeometryChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedGeometryChanged) Q_PROPERTY(QSGTexture *texture READ texture) + Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged) + Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged) Q_INTERFACES(QSGTextureProvider) @@ -69,7 +73,15 @@ public: QSGImage(QSGItem *parent=0); ~QSGImage(); - enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally }; + enum HAlignment { AlignLeft = Qt::AlignLeft, + AlignRight = Qt::AlignRight, + AlignHCenter = Qt::AlignHCenter }; + enum VAlignment { AlignTop = Qt::AlignTop, + AlignBottom = Qt::AlignBottom, + AlignVCenter = Qt::AlignVCenter }; + + enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally, Pad }; + FillMode fillMode() const; void setFillMode(FillMode); @@ -80,9 +92,17 @@ public: virtual QSGTexture *texture() const; + HAlignment horizontalAlignment() const; + void setHorizontalAlignment(HAlignment align); + + VAlignment verticalAlignment() const; + void setVerticalAlignment(VAlignment align); + Q_SIGNALS: void fillModeChanged(); void paintedGeometryChanged(); + void horizontalAlignmentChanged(HAlignment alignment); + void verticalAlignmentChanged(VAlignment alignment); protected: QSGImage(QSGImagePrivate &dd, QSGItem *parent); diff --git a/src/declarative/items/qsgimage_p_p.h b/src/declarative/items/qsgimage_p_p.h index 0d0f2ee..d0b1099 100644 --- a/src/declarative/items/qsgimage_p_p.h +++ b/src/declarative/items/qsgimage_p_p.h @@ -74,6 +74,8 @@ public: void setPixmap(const QPixmap &pix); bool pixmapChanged : 1; + QSGImage::HAlignment hAlign; + QSGImage::VAlignment vAlign; }; QT_END_NAMESPACE diff --git a/tests/systemtests/declarative/qsgimage/ImageNG.qml b/tests/systemtests/declarative/qsgimage/ImageNG.qml new file mode 100644 index 0000000..4a10910 --- /dev/null +++ b/tests/systemtests/declarative/qsgimage/ImageNG.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Image { + property bool explicitSize: true + property alias label: lb.text + + width: explicitSize ? 200 : undefined; height: explicitSize ? 150 : undefined + smooth: true + + Rectangle { + border.color: "red"; color: "transparent" + anchors.fill: parent + } + + Text { + id: lb + anchors.top: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; anchors.topMargin: 4 + } +} diff --git a/tests/systemtests/declarative/qsgimage/img-align.qml b/tests/systemtests/declarative/qsgimage/img-align.qml new file mode 100644 index 0000000..55ee112 --- /dev/null +++ b/tests/systemtests/declarative/qsgimage/img-align.qml @@ -0,0 +1,92 @@ +import QtQuick 2.0 + +Rectangle { + id: main + width: 800; height: 600 + focus: true + color: "#eeeeee" + + property variant hAlign: Image.AlignHCenter + property variant vAlign: Image.AlignVCenter + property bool mirror: false + property string source: "qt-logo.png" + + Flow { + anchors.fill: parent + anchors { topMargin: 20; leftMargin: 20; rightMargin: 20 } + spacing: 30 + + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + mirror: main.mirror; source: main.source + explicitSize: false + label: "implicit size" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + mirror: main.mirror; source: main.source + label: "explicit size" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.Pad + mirror: main.mirror; source: main.source + label: "padding" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.Tile + mirror: main.mirror; source: main.source + label: "tile" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.TileHorizontally + mirror: main.mirror; source: main.source + label: "tile horizontally" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.TileVertically + mirror: main.mirror; source: main.source + label: "tile vertically" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.PreserveAspectFit + mirror: main.mirror; source: main.source + label: "preserve aspect fit" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.PreserveAspectFit + width: 150; height: 200 + mirror: main.mirror; source: main.source + label: "preserve aspect fit" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.PreserveAspectCrop + mirror: main.mirror; source: main.source + label: "preserve aspect crop" + } + ImageNG { + horizontalAlignment: main.hAlign; verticalAlignment: main.vAlign + fillMode: Image.PreserveAspectCrop + width: 150; height: 200 + mirror: main.mirror; source: main.source + label: "preserve aspect crop" + } + } + + Keys.onUpPressed: vAlign = Image.AlignTop + Keys.onDownPressed: vAlign = Image.AlignBottom + Keys.onLeftPressed: hAlign = Image.AlignLeft + Keys.onRightPressed: hAlign = Image.AlignRight + Keys.onPressed: { + if (event.key == Qt.Key_H) + hAlign = Image.AlignHCenter + else if (event.key == Qt.Key_V) + vAlign = Image.AlignVCenter + } +} diff --git a/tests/systemtests/declarative/qsgimage/qt-logo.png b/tests/systemtests/declarative/qsgimage/qt-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..14ddf2a0289e64c686b34712b8754bc4baac2726 GIT binary patch literal 5149 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 literal 0 HcmV?d00001 -- 1.7.2.5