diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsfontdatabase.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsfontdatabase.cpp | 218 |
1 files changed, 81 insertions, 137 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 9c26a227b8..56adae8ffb 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -618,20 +618,6 @@ QDebug operator<<(QDebug d, const QFontDef &def) return d; } -// convert 0 ~ 1000 integer to QFont::Weight -static inline QFont::Weight weightFromInteger(long weight) -{ - if (weight < 400) - return QFont::Light; - if (weight < 600) - return QFont::Normal; - if (weight < 700) - return QFont::DemiBold; - if (weight < 800) - return QFont::Bold; - return QFont::Black; -} - static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) { switch (charSet) { @@ -808,7 +794,7 @@ QString getEnglishName(const QString &familyName) HDC hdc = GetDC( 0 ); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); + memcpy(lf.lfFaceName, familyName.utf16(), qMin(familyName.length(), LF_FACESIZE - 1) * sizeof(wchar_t)); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); @@ -865,7 +851,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT @@ -1078,15 +1064,15 @@ QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, if (script == QChar::Script_Common) return new QWindowsMultiFontEngine(fontEngine, script); // ### as long as fallbacksForFamily() does not take script parameter into account, - // prefer QFontEngineMultiBasicImpl's loadEngine() implementation for complex scripts + // prefer QFontEngineMulti's loadEngine() implementation for complex scripts return QPlatformFontDatabase::fontEngineMulti(fontEngine, script); } QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) { - QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, 0, + QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, QWindowsContext::instance()->defaultDPI(), - false, sharedFontData()); + sharedFontData()); qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << fe << handle; return fe; } @@ -1134,9 +1120,9 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal request.styleStrategy = QFont::PreferMatch; request.hintingPreference = hintingPreference; - fontEngine = QWindowsFontDatabase::createEngine(request, 0, + fontEngine = QWindowsFontDatabase::createEngine(request, QWindowsContext::instance()->defaultDPI(), - false, sharedFontData()); + sharedFontData()); if (fontEngine) { if (request.family != fontEngine->fontDef.family) { @@ -1238,7 +1224,7 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal else fontEngine->fontDef.style = QFont::StyleNormal; - fontEngine->fontDef.weight = weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); + fontEngine->fontDef.weight = QPlatformFontDatabase::weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); } } @@ -1349,7 +1335,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, HDC hdc = GetDC(0); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); + memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size())); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); HGDIOBJ oldobj = SelectObject(hdc, hfont); @@ -1436,7 +1422,7 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont) HFONT QWindowsFontDatabase::systemFont() { - static const HFONT stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); + static const HFONT stock_sysfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); return stock_sysfont; } @@ -1574,6 +1560,10 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request) lf.lfPitchAndFamily = DEFAULT_PITCH | hint; QString fam = request.family; + if (fam.size() >= LF_FACESIZE) { + qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam)); + fam.truncate(LF_FACESIZE - 1); + } if (fam.isEmpty()) fam = QStringLiteral("MS Sans Serif"); @@ -1585,7 +1575,7 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request) if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) fam = QStringLiteral("Courier New"); - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t)); return lf; } @@ -1668,21 +1658,9 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, - HDC fontHdc, int dpi, bool rawMode, + int dpi, const QSharedPointer<QWindowsFontEngineData> &data) { - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - - const bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc; - - const HDC hdc = useDevice ? fontHdc : data->hdc; - - bool stockFont = false; - bool preferClearTypeAA = false; - - HFONT hfont = 0; - #if !defined(QT_NO_DIRECTWRITE) bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) || (request.hintingPreference == QFont::PreferVerticalHinting); @@ -1691,105 +1669,71 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, bool useDirectWrite = false; #endif - if (rawMode) { // will choose a stock font - int f = SYSTEM_FONT; - const QString fam = request.family.toLower(); - if (fam == QLatin1String("default") || fam == QLatin1String("system")) - f = SYSTEM_FONT; -#ifndef Q_OS_WINCE - else if (fam == QLatin1String("system_fixed")) - f = SYSTEM_FIXED_FONT; - else if (fam == QLatin1String("ansi_fixed")) - f = ANSI_FIXED_FONT; - else if (fam == QLatin1String("ansi_var")) - f = ANSI_VAR_FONT; - else if (fam == QLatin1String("device_default")) - f = DEVICE_DEFAULT_FONT; - else if (fam == QLatin1String("oem_fixed")) - f = OEM_FIXED_FONT; -#endif - else if (fam.at(0) == QLatin1Char('#')) - f = fam.right(fam.length()-1).toInt(); - hfont = (HFONT)GetStockObject(f); - if (!hfont) { - qErrnoWarning("%s: GetStockObject failed", __FUNCTION__); - hfont = QWindowsFontDatabase::systemFont(); - } - stockFont = true; - } else { - lf = fontDefToLOGFONT(request); - preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY; - - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); - - stockFont = (hfont == 0); - bool ttf = false; - int avWidth = 0; - BOOL res; - HGDIOBJ oldObj = SelectObject(hdc, hfont); - - TEXTMETRIC tm; - res = GetTextMetrics(hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - SelectObject(hdc, oldObj); - - if (!useDirectWrite) { - if (hfont && (!ttf || request.stretch != 100)) { - DeleteObject(hfont); - if (!res) - qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed"); - lf.lfWidth = avWidth * request.stretch/100; - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("%s: CreateFontIndirect with stretch failed", __FUNCTION__); - } + LOGFONT lf = fontDefToLOGFONT(request); + const bool preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY; -#ifndef Q_OS_WINCE - if (hfont == 0) { - hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); - stockFont = true; - } -#else - if (hfont == 0) { - hfont = (HFONT)GetStockObject(SYSTEM_FONT); - stockFont = true; + HFONT hfont = 0; + hfont = CreateFontIndirect(&lf); + if (!hfont) { + qErrnoWarning("%s: CreateFontIndirect failed", __FUNCTION__); + hfont = QWindowsFontDatabase::systemFont(); + } + + bool ttf = false; + int avWidth = 0; + BOOL res; + HGDIOBJ oldObj = SelectObject(data->hdc, hfont); + + TEXTMETRIC tm; + res = GetTextMetrics(data->hdc, &tm); + avWidth = tm.tmAveCharWidth; + ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; + SelectObject(data->hdc, oldObj); + + if (!useDirectWrite) { + if (!ttf || request.stretch != 100) { + DeleteObject(hfont); + if (!res) + qErrnoWarning("%s: GetTextMetrics failed", __FUNCTION__); + lf.lfWidth = avWidth * request.stretch/100; + hfont = CreateFontIndirect(&lf); + if (!hfont) { + qErrnoWarning("%s: CreateFontIndirect with stretch failed", __FUNCTION__); + hfont = QWindowsFontDatabase::systemFont(); } -#endif } + } #if !defined(QT_NO_DIRECTWRITE) - else { - // Default to false for DirectWrite (and re-enable once/if everything - // turns out okay) - useDirectWrite = false; - if (initDirectWrite(data.data())) { - const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), - sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); - - HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT( - &lf, - &directWriteFont); - if (FAILED(hr)) { - qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); - } else { - DeleteObject(hfont); - useDirectWrite = true; - } - } + else { + // Default to false for DirectWrite (and re-enable once/if everything turns out okay) + useDirectWrite = false; + if (initDirectWrite(data.data())) { + const QString fam = QString::fromWCharArray(lf.lfFaceName); + const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); + if (nameSubstitute != fam) { + const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); + lf.lfFaceName[nameSubstituteLength] = 0; + } + + HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); + if (FAILED(hr)) { + qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); + } else { + DeleteObject(hfont); + useDirectWrite = true; + } } -#endif } +#endif QFontEngine *fe = 0; - if (!useDirectWrite) { - QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, stockFont, lf, data); + if (!useDirectWrite) { + QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, lf, data); if (preferClearTypeAA) few->glyphFormat = QFontEngine::Format_A32; - few->initFontInfo(request, fontHdc, dpi); + few->initFontInfo(request, dpi); fe = few; } @@ -1806,10 +1750,10 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, } else { qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); } - } - if (directWriteFont != 0) directWriteFont->Release(); + } + #endif return fe; @@ -1823,7 +1767,7 @@ static inline int verticalDPI() QFont QWindowsFontDatabase::systemDefaultFont() { LOGFONT lf; - GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); + GetObject(QWindowsFontDatabase::systemFont(), sizeof(lf), &lf); QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf); // "MS Shell Dlg 2" is the correct system font >= Win2k if (systemFont.family() == QLatin1String("MS Shell Dlg")) @@ -1839,7 +1783,7 @@ QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int vertica QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); qFont.setItalic(logFont.lfItalic); if (logFont.lfWeight != FW_DONTCARE) - qFont.setWeight(weightFromInteger(logFont.lfWeight)); + qFont.setWeight(QPlatformFontDatabase::weightFromInteger(logFont.lfWeight)); const qreal logFontHeight = qAbs(logFont.lfHeight); qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); qFont.setUnderline(logFont.lfUnderline); |