Subscripts and superscripts rendering is not implemented in DirectWrite(at least I couldn't find it), so I've made my own render following this. Though it seems to be very illegal, I modified fontEmSize
and glyphAdvances
member of DWRITE_GLYPH_RUN
in order to imitate the result of superscripts and subscripts. However, this only move glyphs leftside but the width of the region remains unchanged. Modified glyphAdvances
doesn't fix this. How can these empty gaps be removed? Or is there a more proper way to render subscripts or superscripts?
Here's the result of below code, and please ignore the underline and strikethrough.

(The superscripts was rendered with modified font size and glyph advances, while the subscripts was rendered with modified font size only.)
Here's my code:
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;
}