From: Yann Bodson Date: Tue, 5 Jul 2011 03:06:54 +0000 (+1000) Subject: Improvements to Image element X-Git-Tag: qt-v5.0.0-alpha1~2133 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a8925e668aca0e1d2b90308c8286e5bb68f9ee42;p=profile%2Fivi%2Fqtdeclarative.git 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 --- 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 0000000..14ddf2a Binary files /dev/null and b/tests/systemtests/declarative/qsgimage/qt-logo.png differ