diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index a27386c2ad..25f6c4aa21 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1594,6 +1594,100 @@ static const char *kr_tryFonts[] = { static const char **tryFonts = 0; +LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request) +{ + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + + lf.lfHeight = -qRound(request.pixelSize); + lf.lfWidth = 0; + lf.lfEscapement = 0; + lf.lfOrientation = 0; + if (request.weight == 50) + lf.lfWeight = FW_DONTCARE; + else + lf.lfWeight = (request.weight*900)/99; + lf.lfItalic = request.style != QFont::StyleNormal; + lf.lfCharSet = DEFAULT_CHARSET; + + int strat = OUT_DEFAULT_PRECIS; + if (request.styleStrategy & QFont::PreferBitmap) { + strat = OUT_RASTER_PRECIS; +#ifndef Q_OS_WINCE + } else if (request.styleStrategy & QFont::PreferDevice) { + strat = OUT_DEVICE_PRECIS; + } else if (request.styleStrategy & QFont::PreferOutline) { + strat = OUT_OUTLINE_PRECIS; + } else if (request.styleStrategy & QFont::ForceOutline) { + strat = OUT_TT_ONLY_PRECIS; +#endif + } + + lf.lfOutPrecision = strat; + + int qual = DEFAULT_QUALITY; + + if (request.styleStrategy & QFont::PreferMatch) + qual = DRAFT_QUALITY; +#ifndef Q_OS_WINCE + else if (request.styleStrategy & QFont::PreferQuality) + qual = PROOF_QUALITY; +#endif + + if (request.styleStrategy & QFont::PreferAntialias) { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) { + qual = CLEARTYPE_QUALITY; + } else { + qual = ANTIALIASED_QUALITY; + } + } else if (request.styleStrategy & QFont::NoAntialias) { + qual = NONANTIALIASED_QUALITY; + } + + lf.lfQuality = qual; + + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + + int hint = FF_DONTCARE; + switch (request.styleHint) { + case QFont::Helvetica: + hint = FF_SWISS; + break; + case QFont::Times: + hint = FF_ROMAN; + break; + case QFont::Courier: + hint = FF_MODERN; + break; + case QFont::OldEnglish: + hint = FF_DECORATIVE; + break; + case QFont::System: + hint = FF_MODERN; + break; + default: + break; + } + + lf.lfPitchAndFamily = DEFAULT_PITCH | hint; + + QString fam = request.family; + + if (fam.isEmpty()) + fam = QStringLiteral("MS Sans Serif"); + + if ((fam == QStringLiteral("MS Sans Serif")) + && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { + fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale + } + if (fam == QStringLiteral("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 + + return lf; +} + QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &request, HDC fontHdc, int dpi, bool rawMode, const QStringList &family_list, @@ -1645,91 +1739,8 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ } stockFont = true; } else { - int hint = FF_DONTCARE; - switch (request.styleHint) { - case QFont::Helvetica: - hint = FF_SWISS; - break; - case QFont::Times: - hint = FF_ROMAN; - break; - case QFont::Courier: - hint = FF_MODERN; - break; - case QFont::OldEnglish: - hint = FF_DECORATIVE; - break; - case QFont::System: - hint = FF_MODERN; - break; - default: - break; - } - - lf.lfHeight = -qRound(request.pixelSize); - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - if (request.weight == 50) - lf.lfWeight = FW_DONTCARE; - else - lf.lfWeight = (request.weight*900)/99; - lf.lfItalic = request.style != QFont::StyleNormal; - lf.lfCharSet = DEFAULT_CHARSET; - - int strat = OUT_DEFAULT_PRECIS; - if (request.styleStrategy & QFont::PreferBitmap) { - strat = OUT_RASTER_PRECIS; -#ifndef Q_OS_WINCE - } else if (request.styleStrategy & QFont::PreferDevice) { - strat = OUT_DEVICE_PRECIS; - } else if (request.styleStrategy & QFont::PreferOutline) { - strat = OUT_OUTLINE_PRECIS; - } else if (request.styleStrategy & QFont::ForceOutline) { - strat = OUT_TT_ONLY_PRECIS; -#endif - } - - lf.lfOutPrecision = strat; - - int qual = DEFAULT_QUALITY; - - if (request.styleStrategy & QFont::PreferMatch) - qual = DRAFT_QUALITY; -#ifndef Q_OS_WINCE - else if (request.styleStrategy & QFont::PreferQuality) - qual = PROOF_QUALITY; -#endif - - if (request.styleStrategy & QFont::PreferAntialias) { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) { - qual = CLEARTYPE_QUALITY; - preferClearTypeAA = true; - } else { - qual = ANTIALIASED_QUALITY; - } - } else if (request.styleStrategy & QFont::NoAntialias) { - qual = NONANTIALIASED_QUALITY; - } - - lf.lfQuality = qual; - - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfPitchAndFamily = DEFAULT_PITCH | hint; - - QString fam = request.family; - - if(fam.isEmpty()) - fam = QStringLiteral("MS Sans Serif"); - - if ((fam == QStringLiteral("MS Sans Serif")) - && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { - fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale - } - if (fam == QStringLiteral("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 + lf = fontDefToLOGFONT(request); + preferClearTypeAA = lf.lfQuality == CLEARTYPE_QUALITY; hfont = CreateFontIndirect(&lf); if (!hfont) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index 6441e79177..a6b96e3818 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -101,6 +101,7 @@ public: static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); static qreal fontSmoothingGamma(); + static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef); private: void populate(const QString &family = QString()); diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index d7f48e59c5..a78b6f1620 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -50,6 +50,7 @@ #include "qwindowscontext.h" #include "qwindowsfontdatabase.h" #include "qtwindows_additional.h" +#include "qwindowsfontenginedirectwrite.h" #include // glyph_metrics_t #include @@ -74,6 +75,10 @@ # include "qplatformfunctions_wince.h" #endif +#if !defined(QT_NO_DIRECTWRITE) +# include +#endif + QT_BEGIN_NAMESPACE //### mingw needed define @@ -1318,10 +1323,65 @@ void QWindowsMultiFontEngine::loadEngine(int at) Q_ASSERT(at < engines.size()); Q_ASSERT(engines.at(at) == 0); + QFontEngine *fontEngine = engines.at(0); + QSharedPointer data; + LOGFONT lf; + +#ifndef QT_NO_DIRECTWRITE + if (fontEngine->type() == QFontEngine::DirectWrite) { + QWindowsFontEngineDirectWrite *fe = static_cast(fontEngine); + lf = QWindowsFontDatabase::fontDefToLOGFONT(fe->fontDef); + + data = fe->fontEngineData(); + } else +#endif + { + QWindowsFontEngine *fe = static_cast(fontEngine); + lf = fe->logFont(); + + data = fe->fontEngineData(); + } + const QString fam = fallbacks.at(at-1); - QWindowsFontEngine *fe = static_cast(engines.at(0)); - LOGFONT lf = fe->logFont(); memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + +#ifndef QT_NO_DIRECTWRITE + if (fontEngine->type() == QFontEngine::DirectWrite) { + const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), + sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); + + IDWriteFont *directWriteFont = 0; + HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); + if (FAILED(hr)) { + qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); + } else { + IDWriteFontFace *directWriteFontFace = NULL; + HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace); + if (SUCCEEDED(hr)) { + QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, + fontEngine->fontDef.pixelSize, + data); + fedw->setObjectName(QStringLiteral("QWindowsFontEngineDirectWrite_") + fontEngine->fontDef.family); + + fedw->fontDef = fontDef; + fedw->ref.ref(); + engines[at] = fedw; + + if (QWindowsContext::verboseFonts) + qDebug("%s %d %s", __FUNCTION__, at, qPrintable(fam)); + + return; + } else { + qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); + } + + } + } +#endif + + // Get here if original font is not DirectWrite or DirectWrite creation failed for some + // reason HFONT hfont = CreateFontIndirect(&lf); bool stockFont = false; @@ -1329,7 +1389,7 @@ void QWindowsMultiFontEngine::loadEngine(int at) hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); stockFont = true; } - engines[at] = new QWindowsFontEngine(fam, hfont, stockFont, lf, fe->fontEngineData()); + engines[at] = new QWindowsFontEngine(fam, hfont, stockFont, lf, data); engines[at]->ref.ref(); engines[at]->fontDef = fontDef; if (QWindowsContext::verboseFonts) diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index f5f20d57ce..32444c7cb0 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -99,6 +99,8 @@ public: bool canRender(const QChar *string, int len); Type type() const; + const QSharedPointer &fontEngineData() const { return m_fontEngineData; } + static QString fontNameSubstitute(const QString &familyName); private: