Make unaligned centered alignment optional.
authorMartin Jones <martin.jones@nokia.com>
Wed, 9 May 2012 01:25:31 +0000 (11:25 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 11 May 2012 05:22:25 +0000 (07:22 +0200)
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 <bea.lam@nokia.com>
src/quick/items/qquickanchors.cpp
src/quick/items/qquickanchors_p.h
src/quick/items/qquickanchors_p_p.h
src/quick/items/qquickitem.cpp
tests/auto/quick/qquickanchors/data/centerin.qml
tests/auto/quick/qquickanchors/data/centerinRotation.qml
tests/auto/quick/qquickanchors/tst_qquickanchors.cpp

index b7071b9..cc4239c 100644 (file)
@@ -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;
index 9076fbe..7167857 100644 (file)
@@ -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;
index 1814185..0fdcd15 100644 (file)
@@ -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;
index a38b8bd..fd81328 100644 (file)
@@ -2893,6 +2893,7 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *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<QQuickTransform> *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}.
index e6c9179..b880219 100644 (file)
@@ -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
+    }
 }
index 933a25c..86d696b 100644 (file)
@@ -7,6 +7,7 @@ Rectangle {
         rotation: 90
         width: 101; height: 101; color: "blue"
         anchors.centerIn: parent;
+        anchors.alignWhenCentered: false
 
         Rectangle {
             objectName: "inner"
index 7b748f6..544fb4b 100644 (file)
@@ -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<QQuickRectangle>(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<QQuickRectangle>(view->rootObject(), QLatin1String("centered3"));
+    QCOMPARE(rect3->x(), 94.5);
+    QCOMPARE(rect3->y(), 94.5);
 
     delete view;
 }