Introduce FontSmoothingGamma as a platform style hint.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Tue, 27 Mar 2012 06:30:47 +0000 (08:30 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 27 Mar 2012 10:33:42 +0000 (12:33 +0200)
- Allocate gamma tables on the heap in a thread-safe way, use
  font smoothing returned by the style hints of the platform to
  calculate them.
- Improve font rendering on Windows.

Change-Id: I8cd39b51cf03cbd642474c02b9076814baecd597
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
14 files changed:
src/gui/image/qimage.cpp
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qguiapplication_p.h
src/gui/kernel/qplatformintegration_qpa.cpp
src/gui/kernel/qplatformintegration_qpa.h
src/gui/kernel/qstylehints.cpp
src/gui/kernel/qstylehints.h
src/gui/painting/painting.pri
src/gui/painting/qdrawhelper.cpp
src/gui/painting/qdrawhelper_p.h
src/gui/painting/qgammatables.cpp [new file with mode: 0644]
src/plugins/platforms/windows/qwindowsfontdatabase.cpp
src/plugins/platforms/windows/qwindowsfontdatabase.h
src/plugins/platforms/windows/qwindowsintegration.cpp

index 61a3895..9770aca 100644 (file)
@@ -51,6 +51,7 @@
 #include "qvariant.h"
 #include "qimagepixmapcleanuphooks_p.h"
 #include "qplatformintegration_qpa.h"
+#include <private/qguiapplication_p.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <limits.h>
@@ -3303,10 +3304,10 @@ extern const uchar *qt_pow_rgb_gamma();
 
 void qGamma_correct_back_to_linear_cs(QImage *image)
 {
-    const uchar *gamma = qt_pow_rgb_gamma();
-    if (!gamma)
+    const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
+    if (!tables)
         return;
-
+    const uchar *gamma = tables->qt_pow_rgb_gamma;
     // gamma correct the pixels back to linear color space...
     int h = image->height();
     int w = image->width();
index 5a95ebe..4cd02c3 100644 (file)
@@ -61,6 +61,7 @@
 #include <qpalette.h>
 #include <qscreen.h>
 #include <private/qscreen_p.h>
+#include <private/qdrawhelper_p.h>
 
 #include <QtGui/QPlatformIntegration>
 #include <QtGui/QGenericPluginFactory>
@@ -764,6 +765,7 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
     delete  platform_theme;
     delete platform_integration;
     platform_integration = 0;
+    delete m_gammaTables.load();
 }
 
 #if 0
@@ -2170,4 +2172,17 @@ void QGuiApplicationPrivate::notifyThemeChanged()
     }
 }
 
+const QDrawHelperGammaTables *QGuiApplicationPrivate::gammaTables()
+{
+    QDrawHelperGammaTables *result = m_gammaTables.load();
+    if (!result){
+        const qreal smoothing = qApp->styleHints()->fontSmoothingGamma();
+        QDrawHelperGammaTables *tables = new QDrawHelperGammaTables(smoothing);
+        if (!m_gammaTables.testAndSetRelease(0, tables))
+            delete tables;
+        result = m_gammaTables.load();
+    }
+    return result;
+}
+
 QT_END_NAMESPACE
index f30a2bb..4d8ef6f 100644 (file)
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
 
 class QPlatformIntegration;
 class QPlatformTheme;
+struct QDrawHelperGammaTables;
 
 class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate
 {
@@ -203,6 +204,8 @@ public:
     };
     QHash<QWindow *, SynthesizedMouseData> synthesizedMousePoints;
 
+    const QDrawHelperGammaTables *gammaTables();
+
 protected:
     virtual void notifyThemeChanged();
 
@@ -212,6 +215,7 @@ private:
     static QGuiApplicationPrivate *self;
     static QTouchDevice *m_fakeTouchDevice;
     static int m_fakeMouseSourcePointId;
+    QAtomicPointer<QDrawHelperGammaTables> m_gammaTables;
 };
 
 Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k);
index 6879f05..4efd2d8 100644 (file)
@@ -293,6 +293,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
         return false;
     case PasswordMaskDelay:
         return 0;
+    case FontSmoothingGamma:
+        return qreal(1.7);
     }
 
     return 0;
index 68dfc21..fe40fd3 100644 (file)
@@ -122,7 +122,8 @@ public:
         StartDragTime,
         KeyboardAutoRepeatRate,
         ShowIsFullScreen,
-        PasswordMaskDelay
+        PasswordMaskDelay,
+        FontSmoothingGamma
     };
 
     virtual QVariant styleHint(StyleHint hint) const;
index 4970f6a..9384d34 100644 (file)
@@ -101,4 +101,9 @@ int QStyleHints::passwordMaskDelay() const
     return hint(QPlatformIntegration::PasswordMaskDelay).toInt();
 }
 
+qreal QStyleHints::fontSmoothingGamma() const
+{
+    return hint(QPlatformIntegration::FontSmoothingGamma).toReal();
+}
+
 QT_END_NAMESPACE
index ae51ebc..301b518 100644 (file)
@@ -63,6 +63,7 @@ public:
     int cursorFlashTime() const;
     bool showIsFullScreen() const;
     int passwordMaskDelay() const;
+    qreal fontSmoothingGamma() const;
 
 private:
     friend class QGuiApplication;
index 3ce2e5b..977aea2 100644 (file)
@@ -75,6 +75,7 @@ SOURCES += \
         SOURCES +=                                      \
                 painting/qpaintengine_raster.cpp        \
                 painting/qdrawhelper.cpp                \
+                painting/qgammatables.cpp               \
                 painting/qimagescale.cpp                \
                 painting/qgrayraster.c                  \
                 painting/qpaintengine_blitter.cpp       \
index 7571d81..774678c 100644 (file)
@@ -39,6 +39,9 @@
 **
 ****************************************************************************/
 
+#include <qstylehints.h>
+#include <qguiapplication.h>
+#include <qatomic.h>
 #include <private/qdrawhelper_p.h>
 #include <private/qpaintengine_raster_p.h>
 #include <private/qpainter_p.h>
@@ -51,6 +54,7 @@
 #include <private/qdrawhelper_mips_dsp_p.h>
 #endif
 #include <private/qmath_p.h>
+#include <private/qguiapplication_p.h>
 #include <qmath.h>
 
 QT_BEGIN_NAMESPACE
@@ -5313,54 +5317,6 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer,
                                     map, mapWidth, mapHeight, mapStride);
 }
 
-
-struct QDrawHelperGammaTables
-{
-    QDrawHelperGammaTables();
-
-    uchar qt_pow_rgb_gamma[256];
-    uchar qt_pow_rgb_invgamma[256];
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
-    uint qt_pow_gamma[256];
-    uchar qt_pow_invgamma[2048];
-#endif
-};
-
-QDrawHelperGammaTables::QDrawHelperGammaTables()
-{
-    qreal smoothing = qreal(1.7);
-
-    for (int i=0; i<256; ++i) {
-        qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255));
-        qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255));
-    }
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
-    const qreal gray_gamma = 2.31;
-    for (int i=0; i<256; ++i)
-        qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
-    for (int i=0; i<2048; ++i)
-        qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255));
-#endif
-}
-
-Q_GLOBAL_STATIC(QDrawHelperGammaTables, qt_gamma_tables);
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
-const uint *qt_pow_gamma()
-{
-    QDrawHelperGammaTables *tables = qt_gamma_tables();
-    return tables ? tables->qt_pow_gamma : 0;
-}
-#endif
-
-const uchar *qt_pow_rgb_gamma()
-{
-    QDrawHelperGammaTables *tables = qt_gamma_tables();
-    return tables ? tables->qt_pow_rgb_gamma : 0;
-}
-
 static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
                                     int x, int y, quint32 color,
                                     const uchar *map,
@@ -5473,7 +5429,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer,
     const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
 
 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
-    QDrawHelperGammaTables *tables = qt_gamma_tables();
+    const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
     if (!tables)
         return;
 
@@ -5570,7 +5526,7 @@ static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer,
     int sb = qBlue(color);
     int sa = qAlpha(color);
 
-    QDrawHelperGammaTables *tables = qt_gamma_tables();
+    const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
     if (!tables)
         return;
 
index 442fd8b..2e9f064 100644 (file)
@@ -328,6 +328,18 @@ struct QSpanData
     void adjustSpanMethods();
 };
 
+struct QDrawHelperGammaTables
+{
+    explicit QDrawHelperGammaTables(qreal smoothing);
+
+    void refresh(qreal smoothing);
+
+    uchar qt_pow_rgb_gamma[256];
+    uchar qt_pow_rgb_invgamma[256];
+    uint qt_pow_gamma[256];
+    uchar qt_pow_invgamma[2048];
+};
+
 static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
 {
     if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
diff --git a/src/gui/painting/qgammatables.cpp b/src/gui/painting/qgammatables.cpp
new file mode 100644 (file)
index 0000000..06dc95a
--- /dev/null
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qdrawhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QDrawHelperGammaTables::QDrawHelperGammaTables(qreal smoothing)
+{
+    const qreal gray_gamma = 2.31;
+    for (int i=0; i<256; ++i)
+        qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
+    for (int i=0; i<2048; ++i)
+        qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255));
+
+    refresh(smoothing);
+}
+
+void QDrawHelperGammaTables::refresh(qreal smoothing)
+{
+    for (int i=0; i<256; ++i) {
+        qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255));
+        qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255));
+    }
+}
+
+QT_END_NAMESPACE
index e0be731..7d0bd53 100644 (file)
@@ -68,8 +68,10 @@ QT_BEGIN_NAMESPACE
 */
 
 QWindowsFontEngineData::QWindowsFontEngineData()
+    : clearTypeEnabled(false)
+    , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
 #if !defined(QT_NO_DIRECTWRITE)
-    : directWriteFactory(0)
+    , directWriteFactory(0)
     , directWriteGdiInterop(0)
 #endif
 {
@@ -78,17 +80,6 @@ QWindowsFontEngineData::QWindowsFontEngineData()
     if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
         clearTypeEnabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
 
-    int winSmooth;
-    if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) {
-        fontSmoothingGamma = winSmooth / qreal(1000.0);
-    } else {
-        fontSmoothingGamma = 1.0;
-    }
-
-    // Safeguard ourselves against corrupt registry values...
-    if (fontSmoothingGamma > 5 || fontSmoothingGamma < 1)
-        fontSmoothingGamma = qreal(1.4);
-
     const qreal gray_gamma = 2.31;
     for (int i=0; i<256; ++i)
         pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
@@ -110,6 +101,19 @@ QWindowsFontEngineData::~QWindowsFontEngineData()
 #endif
 }
 
+qreal QWindowsFontDatabase::fontSmoothingGamma()
+{
+    int winSmooth;
+    qreal result = 1;
+    if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
+        result = qreal(winSmooth) / qreal(1000.0);
+
+    // Safeguard ourselves against corrupt registry values...
+    if (result > 5 || result < 1)
+        result = qreal(1.4);
+    return result;
+}
+
 #if !defined(QT_NO_DIRECTWRITE)
 static inline bool initDirectWrite(QWindowsFontEngineData *d)
 {
index f8f2a1e..774a203 100644 (file)
@@ -96,6 +96,8 @@ public:
     static HFONT systemFont();
     static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0);
 
+    static qreal fontSmoothingGamma();
+
 private:
     void populate(const QString &family = QString());
     QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
index ee58a19..fa63d77 100644 (file)
@@ -317,6 +317,8 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
     case QPlatformIntegration::KeyboardInputInterval:
     case QPlatformIntegration::ShowIsFullScreen:
         break; // Not implemented
+    case QPlatformIntegration::FontSmoothingGamma:
+        return QVariant(QWindowsFontDatabase::fontSmoothingGamma());
     }
     return QPlatformIntegration::styleHint(hint);
 }