Fix colorization of native rendered text...
authorGunnar Sletta <gunnar.sletta@digia.com>
Fri, 27 Sep 2013 13:31:12 +0000 (15:31 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sun, 29 Sep 2013 05:37:14 +0000 (07:37 +0200)
Task-number: QTBUG-33633

Change-Id: Ic7fabe36887fc19e28286ae6f4eb2f22b4211b4f
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
src/quick/scenegraph/qsgdefaultglyphnode_p.cpp

index c62bee0..31b9ae1 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+#ifndef GL_FRAMEBUFFER_SRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+
 class QSGTextMaskMaterialData : public QSGMaterialShader
 {
 public:
@@ -75,6 +79,8 @@ protected:
     int m_color_id;
     int m_textureScale_id;
 
+    uint m_useSRGB : 1;
+
     QFontEngineGlyphCache::Type m_cacheType;
 };
 
@@ -109,52 +115,61 @@ char const *const *QSGTextMaskMaterialData::attributeNames() const
 }
 
 QSGTextMaskMaterialData::QSGTextMaskMaterialData(QFontEngineGlyphCache::Type cacheType)
-    : m_cacheType(cacheType)
+    : m_useSRGB(false)
+    , m_cacheType(cacheType)
 {
 }
 
+static inline qreal fontSmoothingGamma()
+{
+    static qreal fontSmoothingGamma = QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
+    return fontSmoothingGamma;
+}
+
 void QSGTextMaskMaterialData::initialize()
 {
     m_matrix_id = program()->uniformLocation("matrix");
     m_color_id = program()->uniformLocation("color");
     m_textureScale_id = program()->uniformLocation("textureScale");
-}
 
-static inline qreal fontSmoothingGamma()
-{
-    static qreal fontSmoothingGamma = QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
-    return fontSmoothingGamma;
+    // 0.25 was found to be acceptable error margin by experimentation. On Mac, the gamma is 2.0,
+    // but using sRGB looks okay.
+    if (strstr((const char *) glGetString(GL_EXTENSIONS), "GL_ARB_framebuffer_sRGB")
+            && m_cacheType == QFontEngineGlyphCache::Raster_RGBMask
+            && qAbs(fontSmoothingGamma() - 2.2) < 0.25) {
+        m_useSRGB = true;
+    }
 }
 
 void QSGTextMaskMaterialData::activate()
 {
-    QSGMaterialShader::activate();
-
     if (m_cacheType == QFontEngineGlyphCache::Raster_RGBMask)
         glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
 
-#if !defined(QT_OPENGL_ES_2) && defined(GL_ARB_framebuffer_sRGB)
-    // 0.25 was found to be acceptable error margin by experimentation. On Mac, the gamma is 2.0,
-    // but using sRGB looks okay.
-    if (m_cacheType == QFontEngineGlyphCache::Raster_RGBMask
-            && qAbs(fontSmoothingGamma() - 2.2) < 0.25) {
+    if (m_useSRGB)
         glEnable(GL_FRAMEBUFFER_SRGB);
-    }
-#endif
 }
 
 void QSGTextMaskMaterialData::deactivate()
 {
-    QSGMaterialShader::deactivate();
     if (m_cacheType == QFontEngineGlyphCache::Raster_RGBMask)
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
-#if !defined(QT_OPENGL_ES_2) && defined(GL_ARB_framebuffer_sRGB)
-    if (m_cacheType == QFontEngineGlyphCache::Raster_RGBMask
-            && qAbs(fontSmoothingGamma() - 2.2) < 0.25) {
+    if (m_useSRGB)
         glDisable(GL_FRAMEBUFFER_SRGB);
-    }
-#endif
+}
+
+static inline qreal qt_sRGB_to_linear_RGB(qreal f)
+{
+    return f > 0.04045 ? qPow((f + 0.055) / 1.055, 2.4) : f / 12.92;
+}
+
+static inline QVector4D qt_sRGB_to_linear_RGB(const QColor &color)
+{
+    return QVector4D(qt_sRGB_to_linear_RGB(color.redF()),
+                     qt_sRGB_to_linear_RGB(color.greenF()),
+                     qt_sRGB_to_linear_RGB(color.blueF()),
+                     color.alphaF());
 }
 
 void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
@@ -165,15 +180,17 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial
 
     if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
         QColor c = material->color();
-        QVector4D color(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+        QVector4D color = m_useSRGB
+                ? qt_sRGB_to_linear_RGB(c)
+                : QVector4D(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(),
-                                                       c.alphaF());
+            state.context()->functions()->glBlendColor(color.x(),
+                                                       color.y(),
+                                                       color.z(),
+                                                       color.w());
         }
     }