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.6 6.5 Fixes: QTBUG-97645 Change-Id: I587f56ace468cfdd57debe7bc8492a96587a4e05 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit 421e7621faa50bf9007076d6be4e0da9514edc59)
This commit is contained in:
parent
a225fb5d89
commit
b62b6094dd
@ -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);
|
QFont::HintingPreference hintingPreference = QFont::HintingPreference(fontDef.hintingPreference);
|
||||||
if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
|
if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
|
||||||
// Microsoft documentation recommends using asymmetric rendering for small fonts
|
// Microsoft documentation recommends using asymmetric rendering for small fonts
|
||||||
@ -484,7 +487,8 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
|
|||||||
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
|
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
|
||||||
bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
|
bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
|
||||||
if (!needsDesignMetrics && (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC
|
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),
|
hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
|
||||||
1.0f,
|
1.0f,
|
||||||
NULL,
|
NULL,
|
||||||
@ -673,7 +677,8 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
|
|||||||
|
|
||||||
bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
|
bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
|
||||||
{
|
{
|
||||||
return true;
|
DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
|
||||||
|
return renderMode != DWRITE_RENDERING_MODE_ALIASED;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
|
QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
|
||||||
@ -776,7 +781,10 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
RECT rect;
|
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)
|
if (rect.top == rect.bottom || rect.left == rect.right)
|
||||||
return QImage();
|
return QImage();
|
||||||
@ -857,7 +865,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||||||
b,
|
b,
|
||||||
a,
|
a,
|
||||||
colorGlyphsAnalysis,
|
colorGlyphsAnalysis,
|
||||||
boundingRect);
|
boundingRect,
|
||||||
|
renderMode);
|
||||||
}
|
}
|
||||||
colorGlyphsAnalysis->Release();
|
colorGlyphsAnalysis->Release();
|
||||||
|
|
||||||
@ -884,7 +893,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||||||
b,
|
b,
|
||||||
a,
|
a,
|
||||||
glyphAnalysis,
|
glyphAnalysis,
|
||||||
boundingRect);
|
boundingRect,
|
||||||
|
renderMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
glyphAnalysis->Release();
|
glyphAnalysis->Release();
|
||||||
@ -902,7 +912,8 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
|
|||||||
float b,
|
float b,
|
||||||
float a,
|
float a,
|
||||||
IDWriteGlyphRunAnalysis *glyphAnalysis,
|
IDWriteGlyphRunAnalysis *glyphAnalysis,
|
||||||
const QRect &boundingRect)
|
const QRect &boundingRect,
|
||||||
|
DWRITE_RENDERING_MODE renderMode)
|
||||||
{
|
{
|
||||||
const int width = destination->width();
|
const int width = destination->width();
|
||||||
const int height = destination->height();
|
const int height = destination->height();
|
||||||
@ -923,12 +934,14 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
|
|||||||
BYTE *alphaValues = alphaValueArray.data();
|
BYTE *alphaValues = alphaValueArray.data();
|
||||||
memset(alphaValues, 0, size);
|
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,
|
&rect,
|
||||||
alphaValues,
|
alphaValues,
|
||||||
size);
|
size);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
if (destination->hasAlphaChannel()) {
|
if (destination->hasAlphaChannel()) { // Color glyphs
|
||||||
for (int y = 0; y < height; ++y) {
|
for (int y = 0; y < height; ++y) {
|
||||||
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
|
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
|
||||||
BYTE *src = alphaValues + width * 3 * y;
|
BYTE *src = alphaValues + width * 3 * y;
|
||||||
@ -946,7 +959,16 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
|
|||||||
qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
|
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 {
|
} else {
|
||||||
for (int y = 0; y < height; ++y) {
|
for (int y = 0; y < height; ++y) {
|
||||||
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
|
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
|
||||||
@ -1121,7 +1143,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
|
|||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
RECT rect;
|
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();
|
glyphAnalysis->Release();
|
||||||
|
|
||||||
int margin = glyphMargin(format);
|
int margin = glyphMargin(format);
|
||||||
|
@ -22,6 +22,7 @@ QT_REQUIRE_CONFIG(directwrite);
|
|||||||
|
|
||||||
#include <QtGui/private/qfontengine_p.h>
|
#include <QtGui/private/qfontengine_p.h>
|
||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
|
#include <dwrite.h>
|
||||||
|
|
||||||
struct IDWriteFont;
|
struct IDWriteFont;
|
||||||
struct IDWriteFontFace;
|
struct IDWriteFontFace;
|
||||||
@ -108,8 +109,16 @@ private:
|
|||||||
const QTransform &xform,
|
const QTransform &xform,
|
||||||
const QColor &color = QColor());
|
const QColor &color = QColor());
|
||||||
void collectMetrics();
|
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);
|
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
|
||||||
|
DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef) const;
|
||||||
|
|
||||||
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
|
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user