如何使用DirectWrite自定义呈现器呈现下标或上标?

Roy Li - MSFT 32,646 信誉分 Microsoft 供应商
2024-05-15T02:16:46.3433333+00:00

下标和上标渲染不是在DirectWrite中实现的(至少我找不到它),所以我按照这个制作了自己的渲染。虽然这似乎是非法的,但我修改了 DWRITE_GLYPH_RUN 的 fontEmSize 和 glyphAdvances 成员,以模仿上标和下标的结果。但是,这只会将字形向左移动,但该区域的宽度保持不变。修改后的 glyphAdvances 无法解决此问题。如何消除这些空洞的缝隙?或者有没有更合适的方法来呈现下标或上标?

这是以下代码的结果,请忽略下划线和删除线。

用户图像

(上标以修改后的字体大小和字形前进呈现,而下标仅以修改后的字体大小呈现。)

User's image

这是我的代码:


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 总结而来

Windows API - Win32
Windows API - Win32
一组适用于桌面和服务器应用程序的核心 Windows 应用程序编程接口 (API)。 以前称为 Win32 API。
62 个问题
0 个注释 无注释
{count} 票

接受的答案
  1. Tong Xu - MSFT 2,116 信誉分 Microsoft 供应商
    2024-05-15T07:17:49.9333333+00:00

    你好,
    欢迎来到 Microsoft Q&A!

    就我而言,您应该调用 IDWriteTextLayout::SetFontSize 函数来减小通常的字体大小。并调用 IDWriteTextLayout::SetDrawingEffect 方法设置自定义绘图效果的文本范围。

    有关更多详细信息,您可以参考以下主题:https://social.msdn.microsoft.com/Forums/en-US/53c6c9da-74f2-46b0-b08e-84a06bab4547/how-can-i-use-superscripts-with-directwrite?forum=vcgeneral


    如果答案是正确的解决方案,请单击“接受答案”并请投赞成票。如果您对此答案有其他疑问,请点击“评论”。

    注意:如果您想接收此线程的相关电子邮件通知,请按照我们文档中的步骤启用电子邮件通知。

    0 个注释 无注释

0 个其他答案

排序依据: 非常有帮助