summaryrefslogtreecommitdiffstats
path: root/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/windows/qwindowsfontenginedirectwrite.cpp')
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp107
1 files changed, 83 insertions, 24 deletions
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
index 14dd064c33..47b8a7ee3c 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
@@ -12,10 +12,14 @@
#include <QtCore/private/qwinregistry_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpainterpath.h>
-#include <dwrite_2.h>
+#if QT_CONFIG(directwrite3)
+# include "qwindowsdirectwritefontdatabase_p.h"
+# include <dwrite_3.h>
+#else
+# include <dwrite_2.h>
+#endif
#include <d2d1.h>
@@ -158,10 +162,13 @@ static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE rende
}
}
-static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef)
+DWRITE_RENDERING_MODE QWindowsFontEngineDirectWrite::hintingPreferenceToRenderingMode(const QFontDef &fontDef) const
{
+ if ((fontDef.styleStrategy & QFont::NoAntialias) && glyphFormat != QFontEngine::Format_ARGB)
+ return DWRITE_RENDERING_MODE_ALIASED;
+
QFont::HintingPreference hintingPreference = QFont::HintingPreference(fontDef.hintingPreference);
- if (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting) {
+ if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
// Microsoft documentation recommends using asymmetric rendering for small fonts
// at pixel size 16 and less, and symmetric for larger fonts.
hintingPreference = fontDef.pixelSize > 16.0
@@ -212,7 +219,7 @@ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *di
fontDef.pixelSize = pixelSize;
collectMetrics();
- cache_cost = (m_ascent.toInt() + m_descent.toInt()) * m_xHeight.toInt() * 2000;
+ cache_cost = m_xHeight.toInt() * m_xHeight.toInt() * 2000;
}
QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite()
@@ -354,12 +361,14 @@ void QWindowsFontEngineDirectWrite::collectMetrics()
fontFile->Release();
}
- QByteArray table = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ QByteArray table = getSfntTable(QFont::Tag("hhea").value());
const int advanceWidthMaxLocation = 10;
if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) {
quint16 advanceWidthMax = qFromBigEndian<quint16>(table.constData() + advanceWidthMaxLocation);
m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax);
}
+
+ loadKerningPairs(emSquareSize() / QFixed::fromReal(fontDef.pixelSize));
}
QFixed QWindowsFontEngineDirectWrite::underlinePosition() const
@@ -426,13 +435,13 @@ glyph_t QWindowsFontEngineDirectWrite::glyphIndex(uint ucs4) const
return glyphIndex;
}
-bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
- int *nglyphs, QFontEngine::ShaperFlags flags) const
+int QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
- return false;
+ return -1;
}
QVarLengthArray<UINT32> codePoints(len);
@@ -446,11 +455,15 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly
glyphIndices.data());
if (FAILED(hr)) {
qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
- return false;
+ return -1;
}
- for (int i = 0; i < actualLength; ++i)
+ int mappedGlyphs = 0;
+ for (int i = 0; i < actualLength; ++i) {
glyphs->glyphs[i] = glyphIndices.at(i);
+ if (glyphs->glyphs[i] != 0 || isIgnorableChar(codePoints.at(i)))
+ mappedGlyphs++;
+ }
*nglyphs = actualLength;
glyphs->numGlyphs = actualLength;
@@ -458,7 +471,7 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, {});
- return true;
+ return mappedGlyphs;
}
QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const
@@ -466,7 +479,7 @@ QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const
return m_faceId;
}
-void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
+void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags shaperFlags) const
{
QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
@@ -478,11 +491,14 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
HRESULT hr;
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
- if (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL) {
+ bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
+ if (!needsDesignMetrics && (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC
+ || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL
+ || renderMode == DWRITE_RENDERING_MODE_ALIASED)) {
hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
1.0f,
NULL,
- TRUE,
+ renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL,
glyphIndices.data(),
glyphIndices.size(),
glyphMetrics.data());
@@ -586,7 +602,9 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &g
for (int i = 0; i < glyphs.numGlyphs; ++i)
w += glyphs.effectiveAdvance(i);
- return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent() + descent(), w, 0);
+ const QFixed leftBearing = firstLeftBearing(glyphs);
+ return glyph_metrics_t(leftBearing, -ascent(), w - leftBearing - lastRightBearing(glyphs),
+ ascent() + descent(), w, 0);
}
glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g)
@@ -665,7 +683,10 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
{
- return true;
+ DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
+ return (renderMode != DWRITE_RENDERING_MODE_GDI_CLASSIC
+ && renderMode != DWRITE_RENDERING_MODE_GDI_NATURAL
+ && renderMode != DWRITE_RENDERING_MODE_ALIASED);
}
QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
@@ -768,7 +789,10 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
if (SUCCEEDED(hr)) {
RECT rect;
- glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED
+ ? DWRITE_TEXTURE_ALIASED_1x1
+ : DWRITE_TEXTURE_CLEARTYPE_3x1,
+ &rect);
if (rect.top == rect.bottom || rect.left == rect.right)
return QImage();
@@ -849,7 +873,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
b,
a,
colorGlyphsAnalysis,
- boundingRect);
+ boundingRect,
+ renderMode);
}
colorGlyphsAnalysis->Release();
@@ -876,7 +901,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
b,
a,
glyphAnalysis,
- boundingRect);
+ boundingRect,
+ renderMode);
}
glyphAnalysis->Release();
@@ -894,7 +920,8 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
float b,
float a,
IDWriteGlyphRunAnalysis *glyphAnalysis,
- const QRect &boundingRect)
+ const QRect &boundingRect,
+ DWRITE_RENDERING_MODE renderMode)
{
const int width = destination->width();
const int height = destination->height();
@@ -915,12 +942,14 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
BYTE *alphaValues = alphaValueArray.data();
memset(alphaValues, 0, size);
- HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
+ HRESULT hr = glyphAnalysis->CreateAlphaTexture(renderMode == DWRITE_RENDERING_MODE_ALIASED
+ ? DWRITE_TEXTURE_ALIASED_1x1
+ : DWRITE_TEXTURE_CLEARTYPE_3x1,
&rect,
alphaValues,
size);
if (SUCCEEDED(hr)) {
- if (destination->hasAlphaChannel()) {
+ if (destination->hasAlphaChannel()) { // Color glyphs
for (int y = 0; y < height; ++y) {
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
BYTE *src = alphaValues + width * 3 * y;
@@ -938,7 +967,16 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
}
}
+ } else if (renderMode == DWRITE_RENDERING_MODE_ALIASED) {
+ for (int y = 0; y < height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
+ BYTE *src = alphaValues + width * y;
+ for (int x = 0; x < width; ++x) {
+ int alpha = *(src++);
+ dest[x] = (alpha << 16) + (alpha << 8) + alpha;
+ }
+ }
} else {
for (int y = 0; y < height; ++y) {
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
@@ -1007,6 +1045,27 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request,
fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
else if (fontDef.pixelSize == -1)
fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.);
+
+ m_faceId.variableAxes = request.variableAxisValues;
+
+#if QT_CONFIG(directwrite3)
+ IDWriteFontFace3 *face3 = nullptr;
+ if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace3),
+ reinterpret_cast<void **>(&face3)))) {
+ IDWriteLocalizedStrings *names;
+ if (SUCCEEDED(face3->GetFaceNames(&names))) {
+ wchar_t englishLocale[] = L"en-us";
+ fontDef.styleName = QWindowsDirectWriteFontDatabase::localeString(names, englishLocale);
+ names->Release();
+ }
+
+ // Color font
+ if (face3->GetPaletteEntryCount() > 0)
+ glyphFormat = QFontEngine::Format_ARGB;
+
+ face3->Release();
+ }
+#endif
}
QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyName)
@@ -1092,7 +1151,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
if (SUCCEEDED(hr)) {
RECT rect;
- glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED ? DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
glyphAnalysis->Release();
int margin = glyphMargin(format);