mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
patch 9.1.2125: MS-Windows: DirectX rendering can be improved
Problem: MS-Windows: DirectX rendering can be improved
Solution: Use lpDx advance, fix vertical text shift and correct
font-size calculations (Yasuhiro Matsumoto).
This changes DirectWrite rendering to:
- Respect lpDx-provided advance widths instead of always adjusting to
cell width.
- Use a fixed baseline derived from cell geometry to prevent vertical
shifts when font fallback occurs (e.g. with CJK characters).
- Correctly convert LOGFONT lfHeight to DirectWrite font size using font
metrics for closer GDI compatibility.
closes: #19254
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
01956225bc
commit
b39b065d6f
+57
-22
@@ -307,6 +307,8 @@ struct DWriteContext {
|
||||
IDWriteTextFormat *mTextFormat;
|
||||
DWRITE_FONT_WEIGHT mFontWeight;
|
||||
DWRITE_FONT_STYLE mFontStyle;
|
||||
FLOAT mFontSize; // Font size in pixels (em height)
|
||||
FLOAT mFontAscent; // Font ascent in pixels
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE mTextAntialiasMode;
|
||||
|
||||
@@ -367,7 +369,10 @@ public:
|
||||
AdjustedGlyphRun(
|
||||
const DWRITE_GLYPH_RUN *glyphRun,
|
||||
FLOAT cellWidth,
|
||||
FLOAT &accum) :
|
||||
FLOAT &accum,
|
||||
const INT *lpDx,
|
||||
int *glyphIndex,
|
||||
int cchText) :
|
||||
DWRITE_GLYPH_RUN(*glyphRun),
|
||||
mAccum(accum),
|
||||
mDelta(0.0f),
|
||||
@@ -377,7 +382,18 @@ public:
|
||||
for (UINT32 i = 0; i < glyphRun->glyphCount; ++i)
|
||||
{
|
||||
FLOAT orig = glyphRun->glyphAdvances[i];
|
||||
FLOAT adjusted = adjustToCell(orig, cellWidth);
|
||||
FLOAT adjusted;
|
||||
|
||||
if (*glyphIndex < cchText)
|
||||
{
|
||||
adjusted = FLOAT(lpDx[*glyphIndex]);
|
||||
(*glyphIndex)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
adjusted = adjustToCell(orig, cellWidth);
|
||||
}
|
||||
|
||||
mAdjustedAdvances[i] = adjusted;
|
||||
mDelta += adjusted - orig;
|
||||
}
|
||||
@@ -403,9 +419,13 @@ struct TextRendererContext {
|
||||
// const fields.
|
||||
COLORREF color;
|
||||
FLOAT cellWidth;
|
||||
const INT *lpDx;
|
||||
int cchText;
|
||||
FLOAT baselineY; // Fixed baseline Y coordinate
|
||||
|
||||
// working fields.
|
||||
FLOAT offsetX;
|
||||
int glyphIndex;
|
||||
};
|
||||
|
||||
class TextRenderer FINAL : public IDWriteTextRenderer
|
||||
@@ -496,8 +516,14 @@ public:
|
||||
TextRendererContext *context =
|
||||
reinterpret_cast<TextRendererContext*>(clientDrawingContext);
|
||||
|
||||
// Use fixed baseline Y from context instead of DirectWrite's
|
||||
// baselineOriginY to prevent vertical shifts when font fallback
|
||||
// occurs (e.g., for CJK characters).
|
||||
FLOAT fixedBaselineY = context->baselineY;
|
||||
|
||||
AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth,
|
||||
context->offsetX);
|
||||
context->offsetX, context->lpDx, &context->glyphIndex,
|
||||
context->cchText);
|
||||
|
||||
#ifdef FEAT_DIRECTX_COLOR_EMOJI
|
||||
if (pDWC_->mDWriteFactory2 != NULL)
|
||||
@@ -526,7 +552,7 @@ public:
|
||||
pDWC_->mRT->DrawGlyphRun(
|
||||
D2D1::Point2F(
|
||||
colorGlyphRun->baselineOriginX,
|
||||
colorGlyphRun->baselineOriginY),
|
||||
fixedBaselineY),
|
||||
&colorGlyphRun->glyphRun,
|
||||
pDWC_->mBrush,
|
||||
DWRITE_MEASURING_MODE_NATURAL);
|
||||
@@ -542,7 +568,7 @@ public:
|
||||
pDWC_->mRT->DrawGlyphRun(
|
||||
D2D1::Point2F(
|
||||
baselineOriginX + context->offsetX,
|
||||
baselineOriginY),
|
||||
fixedBaselineY),
|
||||
&adjustedGlyphRun,
|
||||
pDWC_->SolidBrush(context->color),
|
||||
DWRITE_MEASURING_MODE_NATURAL);
|
||||
@@ -619,6 +645,8 @@ DWriteContext::DWriteContext() :
|
||||
mTextFormat(NULL),
|
||||
mFontWeight(DWRITE_FONT_WEIGHT_NORMAL),
|
||||
mFontStyle(DWRITE_FONT_STYLE_NORMAL),
|
||||
mFontSize(0.0f),
|
||||
mFontAscent(0.0f),
|
||||
mTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
|
||||
{
|
||||
HRESULT hr;
|
||||
@@ -776,28 +804,25 @@ DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
|
||||
// Use lfHeight of the LOGFONT as font size.
|
||||
fontSize = float(logFont.lfHeight);
|
||||
|
||||
DWRITE_FONT_METRICS fontMetrics;
|
||||
font->GetMetrics(&fontMetrics);
|
||||
|
||||
// Convert lfHeight to DirectWrite font size
|
||||
if (fontSize < 0)
|
||||
{
|
||||
// Negative lfHeight represents the size of the em unit.
|
||||
// Negative lfHeight represents the font's em height in pixels
|
||||
fontSize = -fontSize;
|
||||
}
|
||||
else
|
||||
else if (fontSize > 0)
|
||||
{
|
||||
// Positive lfHeight represents the cell height (ascent +
|
||||
// descent).
|
||||
DWRITE_FONT_METRICS fontMetrics;
|
||||
font->GetMetrics(&fontMetrics);
|
||||
|
||||
// Convert the cell height (ascent + descent) from design units
|
||||
// to ems.
|
||||
float cellHeight = static_cast<float>(
|
||||
fontMetrics.ascent + fontMetrics.descent)
|
||||
/ fontMetrics.designUnitsPerEm;
|
||||
|
||||
// Divide the font size by the cell height to get the font em
|
||||
// size.
|
||||
fontSize /= cellHeight;
|
||||
// Positive lfHeight represents the font's cell height (ascent + descent)
|
||||
// Convert to em height
|
||||
fontSize = fontSize * float(fontMetrics.designUnitsPerEm)
|
||||
/ float(fontMetrics.ascent + fontMetrics.descent);
|
||||
}
|
||||
|
||||
// Scale by ascent ratio to match GDI rendering size
|
||||
fontSize = ceil(fontSize * float(fontMetrics.ascent) / float(fontMetrics.designUnitsPerEm));
|
||||
}
|
||||
|
||||
// The text format includes a locale name. Ideally, this would be the
|
||||
@@ -1039,8 +1064,18 @@ DWriteContext::DrawText(const WCHAR *text, int len,
|
||||
textLayout->SetFontWeight(mFontWeight, textRange);
|
||||
textLayout->SetFontStyle(mFontStyle, textRange);
|
||||
|
||||
// Calculate baseline using a fixed formula based on cell geometry.
|
||||
// Do NOT use GetLineMetrics() because it returns different values
|
||||
// depending on text content (e.g., when CJK characters trigger
|
||||
// font fallback, the metrics change).
|
||||
// Use the same baseline calculation for all text to prevent
|
||||
// vertical shifts during redraw.
|
||||
FLOAT baselineY = floorf(FLOAT(y) + FLOAT(h) * 0.83f + 0.5f);
|
||||
|
||||
TextRenderer renderer(this);
|
||||
TextRendererContext context = { color, FLOAT(cellWidth), 0.0f };
|
||||
TextRendererContext context = { color, FLOAT(cellWidth), lpDx, len,
|
||||
baselineY, 0.0f, 0 };
|
||||
|
||||
textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y));
|
||||
}
|
||||
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2125,
|
||||
/**/
|
||||
2124,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user