下标和上标渲染不是在DirectWrite中实现的(至少我找不到它),所以我按照这个制作了自己的渲染。虽然这似乎是非法的,但我修改了 DWRITE_GLYPH_RUN 的 fontEmSize 和 glyphAdvances 成员,以模仿上标和下标的结果。但是,这只会将字形向左移动,但该区域的宽度保持不变。修改后的 glyphAdvances 无法解决此问题。如何消除这些空洞的缝隙?或者有没有更合适的方法来呈现下标或上标?
这是以下代码的结果,请忽略下划线和删除线。
用户图像
(上标以修改后的字体大小和字形前进呈现,而下标仅以修改后的字体大小呈现。)
这是我的代码:
HRESULT __stdcall TextRenderer::DrawGlyphRun(void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, DWRITE_GLYPH_RUN const* glyphRun, DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, IUnknown* clientDrawingEffect) noexcept
{
auto pDC = reinterpret_cast<ID2D1DeviceContext6*>(clientDrawingContext);
auto effect = reinterpret_cast<ScriptEffect*>(clientDrawingEffect);
auto glyph = (DWRITE_GLYPH_RUN*)(glyphRun); // seems to be illegal but what i can do lol
auto offset = new DWRITE_GLYPH_OFFSET[glyph->glyphCount]; // this only change position of glyph, so not used
for (int i = 0; i < glyph->glyphCount; i++) offset[i] = { 0, 0 };
glyph->glyphOffsets = offset;
IDWriteFontFace3* fontFace;
glyphRun->fontFace->QueryInterface(__uuidof(IDWriteFontFace3), reinterpret_cast<void**>(&fontFace));
DWRITE_FONT_METRICS1 metrics;
fontFace->GetMetrics(&metrics);
switch (effect->GetScriptType())
{
case SCRIPTTYPE_SUBSCRIPT:
baselineOriginY -= metrics.subscriptPositionY / (float)metrics.subscriptSizeY * glyph->fontEmSize;
glyph->fontEmSize = glyph->fontEmSize / 2;
break;
case SCRIPTTYPE_SUPERSCRIPT:
baselineOriginY -= metrics.superscriptPositionY / (float)metrics.superscriptSizeY * glyph->fontEmSize;
glyph->fontEmSize = glyph->fontEmSize / 2;
for (int i = 0; i < glyph->glyphCount; i++)
{
((FLOAT*)(glyph->glyphAdvances))[i] = glyph->glyphAdvances[i] / 2; // seems to be illegal too
}
break;
}
pDC->DrawGlyphRun(D2D1::Point2F(baselineOriginX, baselineOriginY), glyph, effect->GetBrush(), measuringMode);
delete[] offset;
return S_OK;
}
此问题由: Howto render subscripts or superscripts using DirectWrite custom renderer? -Microsoft Q&A 总结而来