From 4f92f9b7251addef556b25e8ab88e00acfaf61b0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 27 Mar 2012 08:30:47 +0200 Subject: Introduce FontSmoothingGamma as a platform style hint. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- src/gui/image/qimage.cpp | 7 ++- src/gui/kernel/qguiapplication.cpp | 15 +++++ src/gui/kernel/qguiapplication_p.h | 4 ++ src/gui/kernel/qplatformintegration_qpa.cpp | 2 + src/gui/kernel/qplatformintegration_qpa.h | 3 +- src/gui/kernel/qstylehints.cpp | 5 ++ src/gui/kernel/qstylehints.h | 1 + src/gui/painting/painting.pri | 1 + src/gui/painting/qdrawhelper.cpp | 56 ++---------------- src/gui/painting/qdrawhelper_p.h | 12 ++++ src/gui/painting/qgammatables.cpp | 66 ++++++++++++++++++++++ .../platforms/windows/qwindowsfontdatabase.cpp | 28 +++++---- .../platforms/windows/qwindowsfontdatabase.h | 2 + .../platforms/windows/qwindowsintegration.cpp | 2 + 14 files changed, 138 insertions(+), 66 deletions(-) create mode 100644 src/gui/painting/qgammatables.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 61a3895a6b..9770aca9e5 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -51,6 +51,7 @@ #include "qvariant.h" #include "qimagepixmapcleanuphooks_p.h" #include "qplatformintegration_qpa.h" +#include #include #include #include @@ -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(); diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 5a95ebe848..4cd02c3d5b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index f30a2bb5a0..4d8ef6fadd 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -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 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 m_gammaTables; }; Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k); diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp index 6879f0517e..4efd2d896f 100644 --- a/src/gui/kernel/qplatformintegration_qpa.cpp +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -293,6 +293,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return false; case PasswordMaskDelay: return 0; + case FontSmoothingGamma: + return qreal(1.7); } return 0; diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h index 68dfc21833..fe40fd3dad 100644 --- a/src/gui/kernel/qplatformintegration_qpa.h +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -122,7 +122,8 @@ public: StartDragTime, KeyboardAutoRepeatRate, ShowIsFullScreen, - PasswordMaskDelay + PasswordMaskDelay, + FontSmoothingGamma }; virtual QVariant styleHint(StyleHint hint) const; diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 4970f6a26b..9384d34097 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -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 diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index ae51ebc052..301b51868f 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -63,6 +63,7 @@ public: int cursorFlashTime() const; bool showIsFullScreen() const; int passwordMaskDelay() const; + qreal fontSmoothingGamma() const; private: friend class QGuiApplication; diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 3ce2e5b258..977aea26e3 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -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 \ diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 7571d81a36..774678c67f 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -39,6 +39,9 @@ ** ****************************************************************************/ +#include +#include +#include #include #include #include @@ -51,6 +54,7 @@ #include #endif #include +#include #include 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; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 442fd8bcd7..2e9f064951 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -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 index 0000000000..06dc95a103 --- /dev/null +++ b/src/gui/painting/qgammatables.cpp @@ -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 + +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 diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index e0be731b53..7d0bd53e8b 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -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) { diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index f8f2a1eb85..774a203a55 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -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 m_fontEngineData; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index ee58a19ca9..fa63d77dd7 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -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); } -- cgit v1.2.3