Implement aliased text rendering with DirectWrite
This creates aliased glyphs using the DirectWrite engine when requested. Note: There was previously a fallback to GDI to support aliased text, which ignored the hinting settings. This patch also removes that fallback. [ChangeLog][Windows] Support QFont::NoAntialias with the DirectWrite font engine. Pick-to: 6.5 6.6 6.7 Fixes: QTBUG-97645 Change-Id: I587f56ace468cfdd57debe7bc8492a96587a4e05 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>bb10
parent
0d91cc866f
commit
421e7621fa
|
|
@ -350,7 +350,7 @@ QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef
|
|||
{
|
||||
const FontHandle *fontHandle = static_cast<const FontHandle *>(handle);
|
||||
IDWriteFontFace *face = fontHandle->fontFace;
|
||||
if (face == nullptr || fontDef.styleStrategy & QFont::NoAntialias) {
|
||||
if (face == nullptr) {
|
||||
qCDebug(lcQpaFonts) << "Falling back to GDI";
|
||||
return QWindowsFontDatabase::fontEngine(fontDef, handle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,8 +162,11 @@ 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 (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
|
||||
// Microsoft documentation recommends using asymmetric rendering for small fonts
|
||||
|
|
@ -486,7 +489,8 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
|
|||
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
|
||||
bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
|
||||
if (!needsDesignMetrics && (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC
|
||||
|| renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL)) {
|
||||
|| renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL
|
||||
|| renderMode == DWRITE_RENDERING_MODE_ALIASED)) {
|
||||
hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
|
||||
1.0f,
|
||||
NULL,
|
||||
|
|
@ -676,7 +680,9 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
|
|||
bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
|
||||
{
|
||||
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
|
||||
return (renderMode != DWRITE_RENDERING_MODE_GDI_CLASSIC && renderMode != DWRITE_RENDERING_MODE_GDI_NATURAL);
|
||||
return (renderMode != DWRITE_RENDERING_MODE_GDI_CLASSIC
|
||||
&& renderMode != DWRITE_RENDERING_MODE_GDI_NATURAL
|
||||
&& renderMode != DWRITE_RENDERING_MODE_ALIASED);
|
||||
}
|
||||
|
||||
QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
|
||||
|
|
@ -779,7 +785,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();
|
||||
|
|
@ -860,7 +869,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
b,
|
||||
a,
|
||||
colorGlyphsAnalysis,
|
||||
boundingRect);
|
||||
boundingRect,
|
||||
renderMode);
|
||||
}
|
||||
colorGlyphsAnalysis->Release();
|
||||
|
||||
|
|
@ -887,7 +897,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
b,
|
||||
a,
|
||||
glyphAnalysis,
|
||||
boundingRect);
|
||||
boundingRect,
|
||||
renderMode);
|
||||
}
|
||||
|
||||
glyphAnalysis->Release();
|
||||
|
|
@ -905,7 +916,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();
|
||||
|
|
@ -926,12 +938,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;
|
||||
|
|
@ -949,7 +963,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));
|
||||
|
|
@ -1124,7 +1147,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);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ QT_REQUIRE_CONFIG(directwrite);
|
|||
|
||||
#include <QtGui/private/qfontengine_p.h>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <dwrite.h>
|
||||
|
||||
struct IDWriteFont;
|
||||
struct IDWriteFontFace;
|
||||
|
|
@ -108,8 +109,16 @@ private:
|
|||
const QTransform &xform,
|
||||
const QColor &color = QColor());
|
||||
void collectMetrics();
|
||||
void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect);
|
||||
void renderGlyphRun(QImage *destination,
|
||||
float r,
|
||||
float g,
|
||||
float b,
|
||||
float a,
|
||||
IDWriteGlyphRunAnalysis *glyphAnalysis,
|
||||
const QRect &boundingRect,
|
||||
DWRITE_RENDERING_MODE renderMode);
|
||||
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
|
||||
DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef) const;
|
||||
|
||||
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue