From 50482f69af0b9392424dfdad5376fcb09be36d46 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 9 May 2012 11:25:31 +1000 Subject: Make unaligned centered alignment optional. Centered alignment was recently made unaligned by e99c5a3f113bbc1b8f8db996b4b0d5715eea2d89. This has the side-effect of sometimes making items appear fuzzy due to sub-pixel alignment. Since we have two conflicting goals, make this behavior configuarable. Change-Id: I5ed0e9532a64f4a986d148044f5871a7ec970f5f Reviewed-by: Bea Lam --- src/quick/items/qquickanchors.cpp | 45 +++++++++++++++++++++- src/quick/items/qquickanchors_p.h | 5 +++ src/quick/items/qquickanchors_p_p.h | 3 +- src/quick/items/qquickitem.cpp | 8 ++++ tests/auto/quick/qquickanchors/data/centerin.qml | 7 ++++ .../quick/qquickanchors/data/centerinRotation.qml | 1 + .../auto/quick/qquickanchors/tst_qquickanchors.cpp | 11 ++++-- 7 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index b7071b9598..cc4239cc2e 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -53,12 +53,30 @@ QT_BEGIN_NAMESPACE static inline qreal hcenter(QQuickItem *item) { - return item->width() / 2; + qreal width = item->width(); + if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { + if (!QQuickAnchorsPrivate::get(anchors)->centerAligned) + return width / 2; + } + int iw = width; + if (iw % 2) + return (width + 1) / 2; + else + return width / 2; } static inline qreal vcenter(QQuickItem *item) { - return item->height() / 2; + qreal height = item->height(); + if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { + if (!QQuickAnchorsPrivate::get(anchors)->centerAligned) + return height / 2; + } + int ih = height; + if (ih % 2) + return (height + 1) / 2; + else + return height / 2; } //### const item? @@ -309,6 +327,29 @@ bool QQuickAnchors::mirrored() return QQuickItemPrivate::get(d->item)->effectiveLayoutMirror; } +bool QQuickAnchors::alignWhenCentered() const +{ + Q_D(const QQuickAnchors); + return d->centerAligned; +} + +void QQuickAnchors::setAlignWhenCentered(bool aligned) +{ + Q_D(QQuickAnchors); + if (aligned == d->centerAligned) + return; + d->centerAligned = aligned; + emit centerAlignedChanged(); + if (d->centerIn) { + d->centerInChanged(); + } else { + if (d->usedAnchors & QQuickAnchors::VCenterAnchor) + d->updateVerticalAnchors(); + else if (d->usedAnchors & QQuickAnchors::HCenterAnchor) + d->updateHorizontalAnchors(); + } +} + bool QQuickAnchorsPrivate::isItemComplete() const { return componentComplete; diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index 9076fbe697..7167857104 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -77,6 +77,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnchors : public QObject Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged) Q_PROPERTY(QQuickItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged) Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged) + Q_PROPERTY(bool alignWhenCentered READ alignWhenCentered WRITE setAlignWhenCentered NOTIFY centerAlignedChanged) public: QQuickAnchors(QQuickItem *item, QObject *parent=0); @@ -159,6 +160,9 @@ public: bool mirrored(); + bool alignWhenCentered() const; + void setAlignWhenCentered(bool); + void classBegin(); void componentComplete(); @@ -181,6 +185,7 @@ Q_SIGNALS: void horizontalCenterOffsetChanged(); void baselineOffsetChanged(); void mirroredChanged(); + void centerAlignedChanged(); private: friend class QQuickItemPrivate; diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 1814185980..0fdcd1540c 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -92,7 +92,7 @@ class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListe Q_DECLARE_PUBLIC(QQuickAnchors) public: QQuickAnchorsPrivate(QQuickItem *i) - : componentComplete(true), updatingMe(false), inDestructor(false), updatingHorizontalAnchor(0), + : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true), updatingHorizontalAnchor(0), updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0), centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0) @@ -109,6 +109,7 @@ public: bool componentComplete:1; bool updatingMe:1; bool inDestructor:1; + bool centerAligned:1; uint updatingHorizontalAnchor:2; uint updatingVerticalAnchor:2; uint updatingFill:2; diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a38b8bd514..fd81328d29 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2893,6 +2893,7 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) \qmlproperty real QtQuick2::Item::anchors.baselineOffset \qmlproperty bool QtQuick2::Item::anchors.mirrored + \qmlproperty bool QtQuick2::Item::anchors.alignWhenCentered Anchors provide a way to position an item by specifying its relationship with other items. @@ -2953,6 +2954,13 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}. + \c anchors.alignWhenCentered (default true) forces centered anchors to align to a + whole pixel, i.e. if the item being centered has an odd width/height the item + will be positioned on a whole pixel rather than being placed on a half-pixel. + This ensures the item is painted crisply. There are cases where this is not + desirable, for example when rotating the item jitters may be apparent as the + center is rounded. + \note You can only anchor an item to siblings or a parent. For more information see \l {anchor-layout}{Anchor Layouts}. diff --git a/tests/auto/quick/qquickanchors/data/centerin.qml b/tests/auto/quick/qquickanchors/data/centerin.qml index e6c9179116..b880219f0f 100644 --- a/tests/auto/quick/qquickanchors/data/centerin.qml +++ b/tests/auto/quick/qquickanchors/data/centerin.qml @@ -15,4 +15,11 @@ Rectangle { width: 11; height: 11; color: "green" anchors.centerIn: parent; } + + Rectangle { + objectName: "centered3" + width: 11; height: 11; color: "green" + anchors.centerIn: parent; + anchors.alignWhenCentered: false + } } diff --git a/tests/auto/quick/qquickanchors/data/centerinRotation.qml b/tests/auto/quick/qquickanchors/data/centerinRotation.qml index 933a25c100..86d696bca2 100644 --- a/tests/auto/quick/qquickanchors/data/centerinRotation.qml +++ b/tests/auto/quick/qquickanchors/data/centerinRotation.qml @@ -7,6 +7,7 @@ Rectangle { rotation: 90 width: 101; height: 101; color: "blue" anchors.centerIn: parent; + anchors.alignWhenCentered: false Rectangle { objectName: "inner" diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp index 7b748f6191..544fb4ba12 100644 --- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp +++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp @@ -545,10 +545,15 @@ void tst_qquickanchors::centerIn() QCOMPARE(rect->x(), 75.0 - 20.0); QCOMPARE(rect->y(), 75.0 - 10.0); - //QTBUG-21730 (use actual center to prevent animation jitter) + // By default center aligned to pixel QQuickRectangle* rect2 = findItem(view->rootObject(), QLatin1String("centered2")); - QCOMPARE(rect2->x(), 94.5); - QCOMPARE(rect2->y(), 94.5); + QCOMPARE(rect2->x(), 94.0); + QCOMPARE(rect2->y(), 94.0); + + //QTBUG-21730 (use actual center to prevent animation jitter) + QQuickRectangle* rect3 = findItem(view->rootObject(), QLatin1String("centered3")); + QCOMPARE(rect3->x(), 94.5); + QCOMPARE(rect3->y(), 94.5); delete view; } -- cgit v1.2.3