Add option to use native rasterizer for SceneGraph text
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Wed, 4 Jul 2012 12:56:38 +0000 (14:56 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 10 Jul 2012 12:22:34 +0000 (14:22 +0200)
For old-style (desktop components) apps using QML 2 on regular density
displays, distance field text will look out of place. We introduce
an option to use the native rasterizer instead if you would rather
have native look and feel than scalable text items.

Change-Id: Idb38e3c89f2deab9ae1963357c6c5fb235ddeab8
Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com>
14 files changed:
src/quick/items/qquicktext.cpp
src/quick/items/qquicktext_p.h
src/quick/items/qquicktext_p_p.h
src/quick/items/qquicktextedit.cpp
src/quick/items/qquicktextedit_p.h
src/quick/items/qquicktextedit_p_p.h
src/quick/items/qquicktextinput.cpp
src/quick/items/qquicktextinput_p.h
src/quick/items/qquicktextinput_p_p.h
src/quick/items/qquicktextnode.cpp
src/quick/items/qquicktextnode_p.h
src/quick/scenegraph/qsgcontext.cpp
src/quick/scenegraph/qsgcontext_p.h
src/quick/scenegraph/qsgdefaultglyphnode_p.cpp

index c48ea0f..3d29ade 100644 (file)
@@ -84,6 +84,7 @@ QQuickTextPrivate::QQuickTextPrivate()
     , elideMode(QQuickText::ElideNone), hAlign(QQuickText::AlignLeft), vAlign(QQuickText::AlignTop)
     , format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap)
     , style(QQuickText::Normal)
+    , renderType(QQuickText::QtRendering)
     , updateType(UpdatePaintNode)
     , maximumLineCountValid(false), updateOnComponentComplete(true), richText(false)
     , styledText(false), widthExceeded(false), heightExceeded(false), internalWidthUpdate(false)
@@ -300,6 +301,41 @@ qreal QQuickTextPrivate::getImplicitHeight() const
     return implicitHeight;
 }
 
+/*!
+    \qmlproperty enumeration QtQuick2::Text::renderType
+
+    Override the default rendering type for this component.
+
+    Supported render types are:
+    \list
+    \li Text.QtRendering - the default
+    \li Text.NativeRendering
+    \endlist
+
+    Select Text.NativeRendering if you prefer text to look native on the target platform and do
+    not require advanced features such as transformation of the text. Using such features in
+    combination with the NativeRendering render type will lend poor and sometimes pixelated
+    results.
+*/
+QQuickText::RenderType QQuickText::renderType() const
+{
+    Q_D(const QQuickText);
+    return d->renderType;
+}
+
+void QQuickText::setRenderType(QQuickText::RenderType renderType)
+{
+    Q_D(QQuickText);
+    if (d->renderType == renderType)
+        return;
+
+    d->renderType = renderType;
+    emit renderTypeChanged();
+
+    if (isComponentComplete())
+        d->updateLayout();
+}
+
 void QQuickText::q_imagesLoaded()
 {
     Q_D(QQuickText);
@@ -482,7 +518,7 @@ void QQuickTextPrivate::updateSize()
         QTextOption option;
         option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
         option.setWrapMode(QTextOption::WrapMode(wrapMode));
-        option.setUseDesignMetrics(true);
+        option.setUseDesignMetrics(renderType != QQuickText::NativeRendering);
         extra->doc->setDefaultTextOption(option);
         qreal naturalWidth = 0;
         if (requireImplicitSize && q->widthValid()) {
@@ -734,14 +770,16 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
         return QRectF(0, 0, 0, height);
     }
 
+    bool shouldUseDesignMetrics = renderType != QQuickText::NativeRendering;
+
     layout.setCacheEnabled(true);
     QTextOption textOption = layout.textOption();
     if (textOption.alignment() != q->effectiveHAlign()
             || textOption.wrapMode() != QTextOption::WrapMode(wrapMode)
-            || !textOption.useDesignMetrics()) {
+            || textOption.useDesignMetrics() != shouldUseDesignMetrics) {
         textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
         textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
-        textOption.setUseDesignMetrics(true);
+        textOption.setUseDesignMetrics(shouldUseDesignMetrics);
         layout.setTextOption(textOption);
     }
     if (layout.font() != font)
@@ -2219,6 +2257,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
         node = static_cast<QQuickTextNode *>(oldNode);
     }
 
+    node->setUseNativeRenderer(d->renderType == NativeRendering);
     node->deleteContent();
     node->setMatrix(QMatrix4x4());
 
index b6aefd7..733cba8 100644 (file)
@@ -63,6 +63,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
     Q_ENUMS(WrapMode)
     Q_ENUMS(LineHeightMode)
     Q_ENUMS(FontSizeMode)
+    Q_ENUMS(RenderType)
 
     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
     Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
@@ -90,6 +91,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickText : public QQuickImplicitSizeItem
     Q_PROPERTY(int minimumPixelSize READ minimumPixelSize WRITE setMinimumPixelSize NOTIFY minimumPixelSizeChanged)
     Q_PROPERTY(int minimumPointSize READ minimumPointSize WRITE setMinimumPointSize NOTIFY minimumPointSizeChanged)
     Q_PROPERTY(FontSizeMode fontSizeMode READ fontSizeMode WRITE setFontSizeMode NOTIFY fontSizeModeChanged)
+    Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
 
 public:
     QQuickText(QQuickItem *parent=0);
@@ -122,6 +124,10 @@ public:
                     Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere
                   };
 
+    enum RenderType { QtRendering,
+                      NativeRendering
+                    };
+
     enum LineHeightMode { ProportionalHeight, FixedHeight };
 
     enum FontSizeMode { FixedSize = 0x0, HorizontalFit = 0x01, VerticalFit = 0x02,
@@ -200,6 +206,9 @@ public:
     QRectF clipRect() const;
     Q_INVOKABLE void doLayout();
 
+    RenderType renderType() const;
+    void setRenderType(RenderType renderType);
+
 Q_SIGNALS:
     void textChanged(const QString &text);
     void linkActivated(const QString &link);
@@ -225,6 +234,7 @@ Q_SIGNALS:
     void effectiveHorizontalAlignmentChanged();
     void lineLaidOut(QQuickTextLine *line);
     void baseUrlChanged();
+    void renderTypeChanged();
 
 protected:
     void mousePressEvent(QMouseEvent *event);
index 49d3580..b6f68c4 100644 (file)
@@ -142,6 +142,7 @@ public:
     QQuickText::TextFormat format;
     QQuickText::WrapMode wrapMode;
     QQuickText::TextStyle style;
+    QQuickText::RenderType renderType;
     UpdateType updateType;
 
     bool maximumLineCountValid:1;
index 41b6e94..71e5dfb 100644 (file)
@@ -344,6 +344,42 @@ void QQuickTextEdit::setTextFormat(TextFormat format)
     emit textFormatChanged(d->format);
 }
 
+/*!
+    \qmlproperty enumeration QtQuick2::TextEdit::renderType
+
+    Override the default rendering type for this component.
+
+    Supported render types are:
+    \list
+    \li Text.QtRendering - the default
+    \li Text.NativeRendering
+    \endlist
+
+    Select Text.NativeRendering if you prefer text to look native on the target platform and do
+    not require advanced features such as transformation of the text. Using such features in
+    combination with the NativeRendering render type will lend poor and sometimes pixelated
+    results.
+*/
+QQuickTextEdit::RenderType QQuickTextEdit::renderType() const
+{
+    Q_D(const QQuickTextEdit);
+    return d->renderType;
+}
+
+void QQuickTextEdit::setRenderType(QQuickTextEdit::RenderType renderType)
+{
+    Q_D(QQuickTextEdit);
+    if (d->renderType == renderType)
+        return;
+
+    d->renderType = renderType;
+    emit renderTypeChanged();
+    d->updateDefaultTextOption();
+
+    if (isComponentComplete())
+        updateSize();
+}
+
 QFont QQuickTextEdit::font() const
 {
     Q_D(const QQuickTextEdit);
@@ -1631,6 +1667,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
             node = static_cast<QQuickTextNode *>(oldNode);
         }
 
+        node->setUseNativeRenderer(d->renderType == NativeRendering);
         node->deleteContent();
         node->setMatrix(QMatrix4x4());
 
@@ -2040,10 +2077,13 @@ void QQuickTextEditPrivate::updateDefaultTextOption()
 
     QTextOption::WrapMode oldWrapMode = opt.wrapMode();
     opt.setWrapMode(QTextOption::WrapMode(wrapMode));
-    opt.setUseDesignMetrics(true);
+
+    bool oldUseDesignMetrics = opt.useDesignMetrics();
+    opt.setUseDesignMetrics(renderType != QQuickTextEdit::NativeRendering);
 
     if (oldWrapMode != opt.wrapMode() || oldAlignment != opt.alignment()
-        || oldTextDirection != opt.textDirection()) {
+        || oldTextDirection != opt.textDirection()
+        || oldUseDesignMetrics != opt.useDesignMetrics()) {
         document->setDefaultTextOption(opt);
     }
 }
index 2b02a4a..b5180e7 100644 (file)
@@ -59,6 +59,7 @@ class Q_AUTOTEST_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
     Q_ENUMS(TextFormat)
     Q_ENUMS(WrapMode)
     Q_ENUMS(SelectionMode)
+    Q_ENUMS(RenderType)
 
     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
     Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
@@ -95,6 +96,7 @@ class Q_AUTOTEST_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
     Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged)
     Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
     Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged)
+    Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
 
 public:
     QQuickTextEdit(QQuickItem *parent=0);
@@ -130,6 +132,10 @@ public:
         SelectWords
     };
 
+    enum RenderType { QtRendering,
+                      NativeRendering
+                    };
+
     QString text() const;
     void setText(const QString &);
 
@@ -230,6 +236,9 @@ public:
 
     bool isInputMethodComposing() const;
 
+    RenderType renderType() const;
+    void setRenderType(RenderType renderType);
+
     Q_INVOKABLE QString getText(int start, int end) const;
     Q_INVOKABLE QString getFormattedText(int start, int end) const;
 
@@ -266,6 +275,7 @@ Q_SIGNALS:
     void effectiveHorizontalAlignmentChanged();
     void baseUrlChanged();
     void inputMethodHintsChanged();
+    void renderTypeChanged();
 
 public Q_SLOTS:
     void selectAll();
index 6e15736..f412aac 100644 (file)
@@ -76,6 +76,7 @@ public:
         , lastSelectionStart(0), lastSelectionEnd(0), lineCount(0)
         , hAlign(QQuickTextEdit::AlignLeft), vAlign(QQuickTextEdit::AlignTop)
         , format(QQuickTextEdit::PlainText), wrapMode(QQuickTextEdit::NoWrap)
+        , renderType(QQuickTextEdit::QtRendering)
         , contentDirection(Qt::LayoutDirectionAuto)
         , mouseSelectionMode(QQuickTextEdit::SelectCharacters), inputMethodHints(Qt::ImhNone)
         , updateType(UpdatePaintNode)
@@ -134,6 +135,7 @@ public:
     QQuickTextEdit::VAlignment vAlign;
     QQuickTextEdit::TextFormat format;
     QQuickTextEdit::WrapMode wrapMode;
+    QQuickTextEdit::RenderType renderType;
     Qt::LayoutDirection contentDirection;
     QQuickTextEdit::SelectionMode mouseSelectionMode;
     Qt::InputMethodHints inputMethodHints;
index af7349e..bbcdc30 100644 (file)
@@ -133,6 +133,42 @@ void QQuickTextInput::setText(const QString &s)
     d->internalSetText(s, -1, false);
 }
 
+
+/*!
+    \qmlproperty enumeration QtQuick2::TextInput::renderType
+
+    Override the default rendering type for this component.
+
+    Supported render types are:
+    \list
+    \li Text.QtRendering - the default
+    \li Text.NativeRendering
+    \endlist
+
+    Select Text.NativeRendering if you prefer text to look native on the target platform and do
+    not require advanced features such as transformation of the text. Using such features in
+    combination with the NativeRendering render type will lend poor and sometimes pixelated
+    results.
+*/
+QQuickTextInput::RenderType QQuickTextInput::renderType() const
+{
+    Q_D(const QQuickTextInput);
+    return d->renderType;
+}
+
+void QQuickTextInput::setRenderType(QQuickTextInput::RenderType renderType)
+{
+    Q_D(QQuickTextInput);
+    if (d->renderType == renderType)
+        return;
+
+    d->renderType = renderType;
+    emit renderTypeChanged();
+
+    if (isComponentComplete())
+        d->updateLayout();
+}
+
 /*!
     \qmlproperty int QtQuick2::TextInput::length
 
@@ -1749,6 +1785,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
             }
         }
     } else {
+        node->setUseNativeRenderer(d->renderType == QQuickTextInput::NativeRendering);
         node->deleteContent();
         node->setMatrix(QMatrix4x4());
 
@@ -2458,7 +2495,7 @@ void QQuickTextInputPrivate::init()
 
     if (!qmlDisableDistanceField()) {
         QTextOption option = m_textLayout.textOption();
-        option.setUseDesignMetrics(true);
+        option.setUseDesignMetrics(renderType != QQuickTextInput::NativeRendering);
         m_textLayout.setTextOption(option);
     }
 }
index 16faa01..3af2cdc 100644 (file)
@@ -61,6 +61,7 @@ class Q_AUTOTEST_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
     Q_ENUMS(EchoMode)
     Q_ENUMS(SelectionMode)
     Q_ENUMS(CursorPosition)
+    Q_ENUMS(RenderType)
 
     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
     Q_PROPERTY(int length READ length NOTIFY textChanged)
@@ -106,6 +107,7 @@ class Q_AUTOTEST_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
     Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
     Q_PROPERTY(qreal contentWidth READ contentWidth NOTIFY contentSizeChanged)
     Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged)
+    Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
 
 public:
     QQuickTextInput(QQuickItem * parent=0);
@@ -150,6 +152,9 @@ public:
         CursorOnCharacter
     };
 
+    enum RenderType { QtRendering,
+                      NativeRendering
+                    };
 
     //Auxilliary functions needed to control the TextInput from QML
     Q_INVOKABLE void positionAt(QQmlV8Function *args) const;
@@ -157,6 +162,9 @@ public:
     Q_INVOKABLE void moveCursorSelection(int pos);
     Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
 
+    RenderType renderType() const;
+    void setRenderType(RenderType renderType);
+
     QString text() const;
     void setText(const QString &);
 
@@ -298,6 +306,7 @@ Q_SIGNALS:
     void effectiveHorizontalAlignmentChanged();
     void contentSizeChanged();
     void inputMethodHintsChanged();
+    void renderTypeChanged();
 
 protected:
     virtual void geometryChanged(const QRectF &newGeometry,
index 2648af1..0cc0846 100644 (file)
@@ -102,6 +102,7 @@ public:
         , vAlign(QQuickTextInput::AlignTop)
         , wrapMode(QQuickTextInput::NoWrap)
         , m_echoMode(QQuickTextInput::Normal)
+        , renderType(QQuickTextInput::QtRendering)
         , updateType(UpdatePaintNode)
         , mouseSelectionMode(QQuickTextInput::SelectCharacters)
         , m_layoutDirection(Qt::LayoutDirectionAuto)
@@ -230,6 +231,7 @@ public:
     QQuickTextInput::VAlignment vAlign;
     QQuickTextInput::WrapMode wrapMode;
     QQuickTextInput::EchoMode m_echoMode;
+    QQuickTextInput::RenderType renderType;
     UpdateType updateType;
     QQuickTextInput::SelectionMode mouseSelectionMode;
     Qt::LayoutDirection m_layoutDirection;
index ecc522c..cb8c422 100644 (file)
@@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE
   Creates an empty QQuickTextNode
 */
 QQuickTextNode::QQuickTextNode(QSGContext *context, QQuickItem *ownerElement)
-    : m_context(context), m_cursorNode(0), m_ownerElement(ownerElement)
+    : m_context(context), m_cursorNode(0), m_ownerElement(ownerElement), m_useNativeRenderer(false)
 {
 #if defined(QML_RUNTIME_TESTING)
     description = QLatin1String("text");
@@ -131,7 +131,9 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun
                                      QQuickText::TextStyle style, const QColor &styleColor,
                                      QSGNode *parentNode)
 {
-    QSGGlyphNode *node = m_context->createGlyphNode();
+    QSGGlyphNode *node = m_useNativeRenderer
+            ? m_context->createNativeGlyphNode()
+            : m_context->createGlyphNode();
     node->setOwnerElement(m_ownerElement);
     node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
     node->setStyle(style);
index 9e75731..c5b55df 100644 (file)
@@ -100,6 +100,9 @@ public:
                             QSGNode *parentNode = 0);
     void addImage(const QRectF &rect, const QImage &image);
 
+    bool useNativeRenderer() const { return m_useNativeRenderer; }
+    void setUseNativeRenderer(bool on) { m_useNativeRenderer = on; }
+
 private:
     void mergeFormats(QTextLayout *textLayout, QVarLengthArray<QTextLayout::FormatRange> *mergedFormats);
 
@@ -107,6 +110,7 @@ private:
     QSGSimpleRectNode *m_cursorNode;
     QList<QSGTexture *> m_textures;
     QQuickItem *m_ownerElement;
+    bool m_useNativeRenderer;
 };
 
 QT_END_NAMESPACE
index 20b383a..dec9ea9 100644 (file)
@@ -335,6 +335,15 @@ QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &
 }
 
 /*!
+    Factory function for scene graph backends of the Text elements which supports native
+    text rendering. Used in special cases where native look and feel is a main objective.
+*/
+QSGGlyphNode *QSGContext::createNativeGlyphNode()
+{
+    return new QSGDefaultGlyphNode;
+}
+
+/*!
     Factory function for scene graph backends of the Text elements;
  */
 QSGGlyphNode *QSGContext::createGlyphNode()
@@ -342,7 +351,7 @@ QSGGlyphNode *QSGContext::createGlyphNode()
     Q_D(QSGContext);
 
     if (d->distanceFieldDisabled) {
-        return new QSGDefaultGlyphNode;
+        return createNativeGlyphNode();
     } else {
         QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(this);
         node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
index 30372c3..a2495a8 100644 (file)
@@ -101,6 +101,7 @@ public:
     virtual QSGRectangleNode *createRectangleNode();
     virtual QSGImageNode *createImageNode();
     virtual QSGGlyphNode *createGlyphNode();
+    virtual QSGGlyphNode *createNativeGlyphNode();
     virtual QSGRenderer *createRenderer();
 
     virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
index 4c4f97a..2f1a4ae 100644 (file)
@@ -44,6 +44,8 @@
 #include <qopenglshaderprogram.h>
 
 #include <QtGui/private/qopengltextureglyphcache_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
 #include <private/qfontengine_p.h>
 #include <private/qopenglextensions_p.h>
 
@@ -61,6 +63,10 @@ public:
 
     virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
     virtual char const *const *attributeNames() const;
+
+    virtual void activate();
+    virtual void deactivate();
+
 private:
     virtual void initialize();
     virtual const char *vertexShader() const;
@@ -90,7 +96,7 @@ const char *QSGTextMaskMaterialData::fragmentShader() const {
         "uniform sampler2D texture;                     \n"
         "uniform lowp vec4 color;                       \n"
         "void main() {                                  \n"
-        "    gl_FragColor = color * texture2D(texture, sampleCoord).a; \n"
+        "    gl_FragColor = vec4(texture2D(texture, sampleCoord).rgb, 1.0); \n"
         "}";
 }
 
@@ -111,6 +117,32 @@ void QSGTextMaskMaterialData::initialize()
     m_textureScale_id = program()->uniformLocation("textureScale");
 }
 
+static inline qreal fontSmoothingGamma()
+{
+    static qreal fontSmoothingGamma = QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
+    return fontSmoothingGamma;
+}
+
+void QSGTextMaskMaterialData::activate()
+{
+    QSGMaterialShader::activate();
+    glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
+
+    // 0.25 was found to be acceptable error margin by experimentation. On Mac, the gamma is 2.0,
+    // but using sRGB looks okay.
+    if (qAbs(fontSmoothingGamma() - 2.2) < 0.25)
+        glEnable(GL_FRAMEBUFFER_SRGB);
+}
+
+void QSGTextMaskMaterialData::deactivate()
+{
+    QSGMaterialShader::deactivate();
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+    if (qAbs(fontSmoothingGamma() - 2.2) < 0.25)
+        glDisable(GL_FRAMEBUFFER_SRGB);
+}
+
 void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
 {
     Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
@@ -118,10 +150,17 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial
     QSGTextMaskMaterial *oldMaterial = static_cast<QSGTextMaskMaterial *>(oldEffect);
 
     if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
-        QVector4D color(material->color().redF(), material->color().greenF(),
-                        material->color().blueF(), material->color().alphaF());
+        QColor c = material->color();
+        QVector4D color(c.redF(), c.greenF(), c.blueF(), c.alphaF());
         color *= state.opacity();
         program()->setUniformValue(m_color_id, color);
+
+        if (oldMaterial == 0 || material->color() != oldMaterial->color()) {
+            state.context()->functions()->glBlendColor(c.redF(),
+                                                       c.greenF(),
+                                                       c.blueF(),
+                                                       1.0f);
+        }
     }
 
     bool updated = material->ensureUpToDate();
@@ -138,8 +177,8 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial
         // Set the mag/min filters to be linear. We only need to do this when the texture
         // has been recreated.
         if (updated) {
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         }
     }
 
@@ -161,7 +200,7 @@ void QSGTextMaskMaterial::init()
 {
     Q_ASSERT(m_font.isValid());
 
-    QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_A8;
+    QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_RGBMask;
     setFlag(Blending, true);
 
     QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());