diff options
Diffstat (limited to 'src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp')
-rw-r--r-- | src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp | 218 |
1 files changed, 95 insertions, 123 deletions
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index 4c39560cbe..f131419140 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -48,11 +48,11 @@ #include "qwindowsdirect2ddevicecontext.h" #include "qwindowsfontengine.h" -#include "qwindowsfontenginedirectwrite.h" #include "qwindowsfontdatabase.h" #include "qwindowsintegration.h" #include <QtCore/QStack> +#include <QtCore/QSettings> #include <QtGui/private/qpaintengine_p.h> #include <QtGui/private/qtextengine_p.h> #include <QtGui/private/qfontengine_p.h> @@ -109,6 +109,13 @@ static inline ID2D1Factory1 *factory() return QWindowsDirect2DContext::instance()->d2dFactory(); } +inline static FLOAT pixelSizeToDIP(int pixelSize) +{ + FLOAT dpiX, dpiY; + QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY); + return FLOAT(pixelSize) * 96.0f / dpiY; +} + class Direct2DPathGeometryWriter { public: @@ -243,7 +250,7 @@ public: QPointF currentBrushOrigin; - QHash< QFont, ComPtr<IDWriteFontFace> > fontCache; + QHash< QFontDef, ComPtr<IDWriteFontFace> > fontCache; struct { bool emulate; @@ -836,6 +843,74 @@ public: { dc()->SetAntialiasMode(antialiasMode()); } + + void drawGlyphRun(const D2D1_POINT_2F &pos, + IDWriteFontFace *fontFace, + const QFontDef &fontDef, + int numGlyphs, + const UINT16 *glyphIndices, + const FLOAT *glyphAdvances, + const DWRITE_GLYPH_OFFSET *glyphOffsets, + bool rtl) + { + Q_Q(QWindowsDirect2DPaintEngine); + + DWRITE_GLYPH_RUN glyphRun = { + fontFace, // IDWriteFontFace *fontFace; + pixelSizeToDIP(fontDef.pixelSize), // FLOAT fontEmSize; + numGlyphs, // UINT32 glyphCount; + glyphIndices, // const UINT16 *glyphIndices; + glyphAdvances, // const FLOAT *glyphAdvances; + glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets; + FALSE, // BOOL isSideways; + rtl ? 1 : 0 // UINT32 bidiLevel; + }; + + const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing) + && !(fontDef.styleStrategy & QFont::NoAntialias)); + dc()->SetTextAntialiasMode(antiAlias ? D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE + : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + + dc()->DrawGlyphRun(pos, + &glyphRun, + NULL, + pen.brush.Get(), + DWRITE_MEASURING_MODE_GDI_CLASSIC); + } + + ComPtr<IDWriteFontFace> fontFaceFromFontEngine(QFontEngine *fe) + { + const QFontDef fontDef = fe->fontDef; + ComPtr<IDWriteFontFace> fontFace = fontCache.value(fontDef); + if (fontFace) + return fontFace; + + LOGFONT lf = QWindowsFontDatabase::fontDefToLOGFONT(fontDef); + + // Get substitute name + static const char keyC[] = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"; + const QString familyName = QString::fromWCharArray(lf.lfFaceName); + const QString nameSubstitute = QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString(); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); + + ComPtr<IDWriteFont> dwriteFont; + HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFromLOGFONT(&lf, &dwriteFont); + if (FAILED(hr)) { + qDebug("%s: CreateFontFromLOGFONT failed: %#x", __FUNCTION__, hr); + return fontFace; + } + + hr = dwriteFont->CreateFontFace(&fontFace); + if (FAILED(hr)) { + qDebug("%s: CreateFontFace failed: %#x", __FUNCTION__, hr); + return fontFace; + } + + if (fontFace) + fontCache.insert(fontDef, fontFace); + + return fontFace; + } }; QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap) @@ -1411,7 +1486,7 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText return; } - ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->font, staticTextItem->fontEngine()); + ComPtr<IDWriteFontFace> fontFace = d->fontFaceFromFontEngine(staticTextItem->fontEngine()); if (!fontFace) { qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__); QPaintEngineEx::drawStaticTextItem(staticTextItem); @@ -1432,14 +1507,14 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText glyphOffsets[i].ascenderOffset = staticTextItem->glyphPositions[i].y.toReal() * -1; } - drawGlyphRun(D2D1::Point2F(0, 0), - fontFace.Get(), - staticTextItem->font, - staticTextItem->numGlyphs, - glyphIndices.constData(), - glyphAdvances.constData(), - glyphOffsets.constData(), - false); + d->drawGlyphRun(D2D1::Point2F(0, 0), + fontFace.Get(), + staticTextItem->fontEngine()->fontDef, + staticTextItem->numGlyphs, + glyphIndices.constData(), + glyphAdvances.constData(), + glyphOffsets.constData(), + false); } void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) @@ -1459,7 +1534,7 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem return; } - ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(*ti.f, ti.fontEngine); + ComPtr<IDWriteFontFace> fontFace = d->fontFaceFromFontEngine(ti.fontEngine); if (!fontFace) { qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__); QPaintEngine::drawTextItem(p, textItem); @@ -1482,72 +1557,14 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem const bool rtl = (ti.flags & QTextItem::RightToLeft); const QPointF offset(rtl ? ti.width.toReal() : 0, 0); - drawGlyphRun(to_d2d_point_2f(p + offset), - fontFace.Get(), - ti.font(), - ti.glyphs.numGlyphs, - glyphIndices.constData(), - glyphAdvances.constData(), - glyphOffsets.constData(), - rtl); -} - -inline static FLOAT pointSizeToDIP(qreal pointSize, FLOAT dpiY) -{ - return (pointSize + (pointSize / qreal(3.0))) * (dpiY / 96.0f); -} - -inline static FLOAT pixelSizeToDIP(int pixelSize, FLOAT dpiY) -{ - return FLOAT(pixelSize) * 96.0f / dpiY; -} - -inline static FLOAT fontSizeInDIP(const QFont &font) -{ - FLOAT dpiX, dpiY; - QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&dpiX, &dpiY); - - if (font.pixelSize() == -1) { - // font size was set as points - return pointSizeToDIP(font.pointSizeF(), dpiY); - } else { - // font size was set as pixels - return pixelSizeToDIP(font.pixelSize(), dpiY); - } -} - -void QWindowsDirect2DPaintEngine::drawGlyphRun(const D2D1_POINT_2F &pos, - IDWriteFontFace *fontFace, - const QFont &font, - int numGlyphs, - const UINT16 *glyphIndices, - const FLOAT *glyphAdvances, - const DWRITE_GLYPH_OFFSET *glyphOffsets, - bool rtl) -{ - Q_D(QWindowsDirect2DPaintEngine); - - DWRITE_GLYPH_RUN glyphRun = { - fontFace, // IDWriteFontFace *fontFace; - fontSizeInDIP(font), // FLOAT fontEmSize; - numGlyphs, // UINT32 glyphCount; - glyphIndices, // const UINT16 *glyphIndices; - glyphAdvances, // const FLOAT *glyphAdvances; - glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets; - FALSE, // BOOL isSideways; - rtl ? 1 : 0 // UINT32 bidiLevel; - }; - - const bool antiAlias = bool((state()->renderHints & QPainter::TextAntialiasing) - && !(font.styleStrategy() & QFont::NoAntialias)); - d->dc()->SetTextAntialiasMode(antiAlias ? D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE - : D2D1_TEXT_ANTIALIAS_MODE_ALIASED); - - d->dc()->DrawGlyphRun(pos, - &glyphRun, - NULL, - d->pen.brush.Get(), - DWRITE_MEASURING_MODE_GDI_CLASSIC); + d->drawGlyphRun(to_d2d_point_2f(p + offset), + fontFace.Get(), + ti.fontEngine->fontDef, + ti.glyphs.numGlyphs, + glyphIndices.constData(), + glyphAdvances.constData(), + glyphOffsets.constData(), + rtl); } void QWindowsDirect2DPaintEngine::ensureBrush() @@ -1678,49 +1695,4 @@ void QWindowsDirect2DPaintEngine::adjustForAliasing(QPointF *point) (*point) += adjustment; } -Microsoft::WRL::ComPtr<IDWriteFontFace> QWindowsDirect2DPaintEngine::fontFaceFromFontEngine(const QFont &font, QFontEngine *fe) -{ - Q_D(QWindowsDirect2DPaintEngine); - - ComPtr<IDWriteFontFace> fontFace = d->fontCache.value(font); - if (fontFace) - return fontFace; - - switch (fe->type()) { - case QFontEngine::Win: - { - QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe); - QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData(); - - HGDIOBJ oldfont = wfe->selectDesignFont(); - HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace); - DeleteObject(SelectObject(wfed->hdc, oldfont)); - if (FAILED(hr)) - qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr); - - } - break; - -#ifndef QT_NO_DIRECTWRITE - - case QFontEngine::DirectWrite: - { - QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe); - fontFace = wfedw->directWriteFontFace(); - } - break; - -#endif // QT_NO_DIRECTWRITE - - default: - qWarning("%s: Unknown font engine!", __FUNCTION__); - break; - } - - if (fontFace) - d->fontCache.insert(font, fontFace); - - return fontFace; -} - QT_END_NAMESPACE |