From 3a9b01127054901293b177e538eb8cfa3937e9fe Mon Sep 17 00:00:00 2001 From: Michael Brasser <michael.brasser@live.com> Date: Fri, 8 Nov 2013 20:17:00 -0600 Subject: [PATCH] Support toggling antialiasing for Text and Rectangle. Task-number: QTBUG-27968 Task-number: QTBUG-34366 Change-Id: Ic446ff4470abf21696e1764f902bd71e79762697 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com> --- .../items/context2d/qquickcanvasitem.cpp | 6 +- src/quick/items/qquickitem.cpp | 59 +++++++++++++++---- src/quick/items/qquickitem.h | 6 +- src/quick/items/qquickitem_p.h | 4 ++ src/quick/items/qquickrectangle.cpp | 14 ++++- src/quick/items/qquicktext.cpp | 28 +++++++++ src/quick/items/qquicktext_p.h | 1 + .../qquickrectangle/tst_qquickrectangle.cpp | 57 ++++++++++++++++++ .../auto/quick/qquicktext/tst_qquicktext.cpp | 25 ++++++++ 9 files changed, 181 insertions(+), 19 deletions(-) diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index ba3592986c..ee1b5f316c 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -196,7 +196,7 @@ QQuickCanvasItemPrivate::QQuickCanvasItemPrivate() , renderTarget(QQuickCanvasItem::Image) , renderStrategy(QQuickCanvasItem::Cooperative) { - antialiasing = true; + implicitAntialiasing = true; } QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() @@ -654,7 +654,7 @@ void QQuickCanvasItem::updatePolish() Q_D(QQuickCanvasItem); if (d->context && d->renderStrategy != QQuickCanvasItem::Cooperative) - d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing); + d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing()); if (d->animationCallbacks.size() > 0 && isVisible()) { QMap<int, QV4::PersistentValue> animationCallbacks = d->animationCallbacks; @@ -708,7 +708,7 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData node->setFiltering(QSGTexture::Nearest); if (d->renderStrategy == QQuickCanvasItem::Cooperative) { - d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, d->antialiasing); + d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing()); d->context->flush(); } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 65322f6de4..96797a7588 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2703,6 +2703,8 @@ QQuickItemPrivate::QQuickItemPrivate() , culled(false) , hasCursor(false) , activeFocusOnTab(false) + , implicitAntialiasing(false) + , antialiasingValid(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -5477,6 +5479,9 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } } break; + case QQuickItem::ItemAntialiasingHasChanged: + q->itemChange(change, data); + break; } } @@ -5570,37 +5575,65 @@ void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab) /*! \qmlproperty bool QtQuick::Item::antialiasing - Primarily used in Rectangle and image based elements to decide if the item should - use antialiasing or not. Items with antialiasing enabled require more memory and - are potentially slower to render. + Used by visual elements to decide if the item should use antialiasing or not. + In some cases items with antialiasing require more memory and are potentially + slower to render (see \l {Antialiasing} for more details). - The default is false. + The default is false, but may be overridden by derived elements. */ /*! \property QQuickItem::antialiasing \brief Specifies whether the item is antialiased or not - Primarily used in Rectangle and image based elements to decide if the item should - use antialiasing or not. Items with antialiasing enabled require more memory and - are potentially slower to render. + Used by visual elements to decide if the item should use antialiasing or not. + In some cases items with antialiasing require more memory and are potentially + slower to render (see \l {Antialiasing} for more details). - The default is false. + The default is false, but may be overridden by derived elements. */ bool QQuickItem::antialiasing() const { Q_D(const QQuickItem); - return d->antialiasing; + return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing; } -void QQuickItem::setAntialiasing(bool antialiasing) + +void QQuickItem::setAntialiasing(bool aa) { Q_D(QQuickItem); - if (d->antialiasing == antialiasing) + + bool changed = (aa != antialiasing()); + d->antialiasingValid = true; + + if (!changed) return; - d->antialiasing = antialiasing; + d->antialiasing = aa; d->dirty(QQuickItemPrivate::Antialiasing); - emit antialiasingChanged(antialiasing); + d->itemChange(ItemAntialiasingHasChanged, d->antialiasing); + + emit antialiasingChanged(antialiasing()); +} + +void QQuickItem::resetAntialiasing() +{ + Q_D(QQuickItem); + if (!d->antialiasingValid) + return; + + d->antialiasingValid = false; + + if (d->implicitAntialiasing != d->antialiasing) + emit antialiasingChanged(antialiasing()); +} + +void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing) +{ + Q_Q(QQuickItem); + bool prev = q->antialiasing(); + implicitAntialiasing = antialiasing; + if (componentComplete && (q->antialiasing() != prev)) + emit q->antialiasingChanged(q->antialiasing()); } /*! diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 2500a2d33a..c666af2729 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -141,7 +141,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(QQmlListProperty<QQuickTransform> transform READ transform DESIGNABLE false FINAL) Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged) - Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged) + Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing) Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged) Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged) @@ -172,7 +172,8 @@ public: ItemParentHasChanged, // value.item ItemOpacityHasChanged, // value.realValue ItemActiveFocusHasChanged, // value.boolValue - ItemRotationHasChanged // value.realValue + ItemRotationHasChanged, // value.realValue + ItemAntialiasingHasChanged // value.boolValue }; union ItemChangeData { @@ -267,6 +268,7 @@ public: bool antialiasing() const; void setAntialiasing(bool); + void resetAntialiasing(); Flags flags() const; void setFlag(Flag flag, bool enabled = true); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index ccf949ee8b..3987ff0cfb 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -422,6 +422,8 @@ public: bool hasCursor:1; // Bit 32 bool activeFocusOnTab:1; + bool implicitAntialiasing:1; + bool antialiasingValid:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -521,6 +523,8 @@ public: virtual void implicitWidthChanged(); virtual void implicitHeightChanged(); + void setImplicitAntialiasing(bool antialiasing); + void resolveLayoutMirror(); void setImplicitLayoutMirror(bool mirror, bool inherit); void setLayoutMirror(bool mirror); diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp index dd482eddb7..d6323026e7 100644 --- a/src/quick/items/qquickrectangle.cpp +++ b/src/quick/items/qquickrectangle.cpp @@ -320,6 +320,16 @@ void QQuickRectangle::doUpdate() update(); } +/*! + \qmlproperty bool QtQuick::Rectangle::antialiasing + + Used to decide if the Rectangle should use antialiasing or not. + \l {Antialiasing} provides information on the performance implications + of this property. + + The default is true for Rectangles with a radius, and false otherwise. +*/ + /*! \qmlproperty int QtQuick::Rectangle::border.width \qmlproperty color QtQuick::Rectangle::border.color @@ -408,6 +418,8 @@ void QQuickRectangle::setRadius(qreal radius) return; d->radius = radius; + d->setImplicitAntialiasing(radius != 0.0); + update(); emit radiusChanged(); } @@ -475,7 +487,7 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData } rectangle->setRadius(d->radius); - rectangle->setAntialiasing(d->antialiasing || d->radius > 0); + rectangle->setAntialiasing(antialiasing()); QGradientStops stops; if (d->gradient) { diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 1d2e70d519..9d11bfb4ea 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -88,6 +88,7 @@ QQuickTextPrivate::QQuickTextPrivate() , truncated(false), hAlignImplicit(true), rightToLeftText(false) , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false) { + implicitAntialiasing = true; } QQuickTextPrivate::ExtraData::ExtraData() @@ -297,6 +298,15 @@ qreal QQuickTextPrivate::getImplicitHeight() const return implicitHeight; } +/*! + \qmlproperty bool QtQuick::Text::antialiasing + + Used to decide if the Text should use antialiasing or not. Only Text + with renderType of Text.NativeRendering can disable antialiasing. + + The default is true. +*/ + /*! \qmlproperty enumeration QtQuick::Text::renderType @@ -1465,6 +1475,9 @@ void QQuickText::setFont(const QFont &font) QFont oldFont = d->font; d->font = font; + if (!antialiasing()) + d->font.setStyleStrategy(QFont::NoAntialias); + if (d->font.pointSizeF() != -1) { // 0.5pt resolution qreal size = qRound(d->font.pointSizeF()*2.0); @@ -1484,6 +1497,21 @@ void QQuickText::setFont(const QFont &font) emit fontChanged(d->sourceFont); } +void QQuickText::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickText); + Q_UNUSED(value); + if (change == ItemAntialiasingHasChanged) { + if (!antialiasing()) + d->font.setStyleStrategy(QFont::NoAntialias); + else + d->font.setStyleStrategy(QFont::PreferAntialias); + d->implicitWidthValid = false; + d->implicitHeightValid = false; + d->updateLayout(); + } +} + /*! \qmlproperty string QtQuick::Text::text diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index 489ef58344..d55dc7e287 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -241,6 +241,7 @@ Q_SIGNALS: protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); + virtual void itemChange(ItemChange change, const ItemChangeData &value); virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp index 204a3ff019..1fed2ecda8 100644 --- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp +++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ #include <qtest.h> +#include <QtTest/QSignalSpy> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -54,6 +55,7 @@ public: private slots: void gradient(); + void antialiasing(); private: QQmlEngine engine; @@ -87,6 +89,61 @@ void tst_qquickrectangle::gradient() delete rect; } +void tst_qquickrectangle::antialiasing() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n Rectangle {}", QUrl()); + QScopedPointer<QObject> object(component.create()); + QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(object.data()); + QVERIFY(rect); + + QSignalSpy spy(rect, SIGNAL(antialiasingChanged(bool))); + + QCOMPARE(rect->antialiasing(), false); + + rect->setAntialiasing(true); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 1); + + rect->setAntialiasing(true); + QCOMPARE(spy.count(), 1); + + rect->resetAntialiasing(); + QCOMPARE(rect->antialiasing(), false); + QCOMPARE(spy.count(), 2); + + rect->setRadius(5); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 3); + + rect->resetAntialiasing(); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 3); + + rect->setRadius(0); + QCOMPARE(rect->antialiasing(), false); + QCOMPARE(spy.count(), 4); + + rect->resetAntialiasing(); + QCOMPARE(rect->antialiasing(), false); + QCOMPARE(spy.count(), 4); + + rect->setRadius(5); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 5); + + rect->resetAntialiasing(); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 5); + + rect->setAntialiasing(false); + QCOMPARE(rect->antialiasing(), false); + QCOMPARE(spy.count(), 6); + + rect->resetAntialiasing(); + QCOMPARE(rect->antialiasing(), true); + QCOMPARE(spy.count(), 7); +} QTEST_MAIN(tst_qquickrectangle) diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 82a1e21764..d241ac2d70 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -101,6 +101,7 @@ private slots: void color(); void smooth(); void renderType(); + void antialiasing(); // QQuickFontValueType void weight(); @@ -1311,6 +1312,30 @@ void tst_qquicktext::renderType() QCOMPARE(spy.count(), 2); } +void tst_qquicktext::antialiasing() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n Text {}", QUrl()); + QScopedPointer<QObject> object(component.create()); + QQuickText *text = qobject_cast<QQuickText *>(object.data()); + QVERIFY(text); + + QSignalSpy spy(text, SIGNAL(antialiasingChanged(bool))); + + QCOMPARE(text->antialiasing(), true); + + text->setAntialiasing(false); + QCOMPARE(text->antialiasing(), false); + QCOMPARE(spy.count(), 1); + + text->setAntialiasing(false); + QCOMPARE(spy.count(), 1); + + text->resetAntialiasing(); + QCOMPARE(text->antialiasing(), true); + QCOMPARE(spy.count(), 2); +} + void tst_qquicktext::weight() { { -- GitLab