透明 GDI 上的 DirectWrite 文本渲染直流

发布于 2024-12-19 07:23:34 字数 2290 浏览 1 评论 0原文

我有一个重要的预先存在的 GDI+ 代码体,用本机 C++ 编写,其中包括在其上绘制文本和位图的透明层。这些层(使用具有自己的 GDI+ 图形的内存 DC 实现)随后在呈现到屏幕上之前进行组合。

我对文本元素不太满意,因为 GDI+ 不允许单次文本运行具有多种画笔颜色,因此我必须将不同的颜色绘制为单独的文本运行,彼此相邻。连接单独的文本运行很麻烦,因为相邻运行之间的字距调整等与不同颜色的连续单个运行不同。

切入正题,探索 DirectWrite 所提供的功能似乎是个好主意,因此我尝试复制 DirectWrite 中的一些现有功能。最具体地说,将文本渲染为透明位图。

这就是困难所在:我无法让 DirectWrite 文本在包含 alpha 的背景上渲染,而不会出现抗锯齿问题(因为前景文本像素应该淡出为透明,但它们会淡出为黑色)。我的文本看起来像这篇文章中的示例

MS 的文档和示例有点薄弱,到目前为止,谷歌/stackoverflow 的搜索也没有给出任何重要的信息。

我的代码包含以下 DirectWrite 内容:

// create a Text Layout object
IDWriteTextLayout *textLayout = NULL;
DWFactory->CreateTextLayout(wcstring,length,textFormat,width,height,&textLayout);
// create the render target using the label DC
HDC hdc = NULL;
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
                                                                    D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_PREMULTIPLIED),
                                                                    0,0,D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,D2D1_FEATURE_LEVEL_DEFAULT);
D2DFactory->CreateDCRenderTarget(&props, &D2DRT);
hdc = myGraphics->GetHDC();
RECT dwrect = {0,0,size.w,size.h};
D2DRT->BindDC(hdc,&dwrect);
D2DRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
// set rendering parameters
IDWriteRenderingParams *oldparams = NULL;
IDWriteRenderingParams *params = NULL;
DWFactory->CreateRenderingParams(&oldparams);
DWFactory->CreateCustomRenderingParams(oldparams->GetGamma(),oldparams->GetEnhancedContrast(),0.0f,oldparams->GetPixelGeometry(),DWRITE_RENDERING_MODE_DEFAULT,&params);
D2DRT->SetTextRenderingParams(params);
// create the brush colors
ID2D1SolidColorBrush *color = NULL;
D2DRT->CreateSolidColorBrush(<some ColorF>,&color);
// render the text
D2DRT->BeginDraw();
D2DRT->DrawTextLayout(origin,textLayout,color);
D2DRT->EndDraw();
myGraphics->ReleaseHDC(hdc);
hdc = NULL;

看起来我需要回退到灰度抗锯齿,但我正在努力。请有人:

  • 解释一下灰度抗锯齿应该做什么,以及它是否适用于透明位图渲染目标;并
  • 给我一些关于如何使灰度抗锯齿发挥作用的指示?

I have a significant pre-existing body of GDI+ code, written in native C++, which includes transparent layers upon which text and bitmaps are drawn. The layers (implemented using memory DCs with their own GDI+ Graphics) are subsequently combined before being presented to the screen.

I'm not that happy with the text elements, as GDI+ doesn't allow single runs of text to have multiple brush colors and hence I have to draw different colors as separate runs of text, next to each other. Concatenating separate text runs is mucky, because the kerning etc between adjacent runs isn't the same as if it were a continuous single run in different colors.

Cutting to the chase, it seemed like a good idea to explore what DirectWrite has to offer, so I'm trying to replicate some of the existing functionality in DirectWrite. Most specifically, rendering text to transparent bitmaps.

This is where it got tough: I can't get the DirectWrite text to render on an alpha-including background without the antialiasing going wrong (as foreground text pixels should fade to transparent, they instead fade to black). My text looks like the example in this post.

The MS documentation and examples on this are a bit thin, and no amount of googling/stackoverflow searching has shone any significant light thus far.

My code includes the following bits of DirectWrite stuff:

// create a Text Layout object
IDWriteTextLayout *textLayout = NULL;
DWFactory->CreateTextLayout(wcstring,length,textFormat,width,height,&textLayout);
// create the render target using the label DC
HDC hdc = NULL;
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
                                                                    D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_PREMULTIPLIED),
                                                                    0,0,D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,D2D1_FEATURE_LEVEL_DEFAULT);
D2DFactory->CreateDCRenderTarget(&props, &D2DRT);
hdc = myGraphics->GetHDC();
RECT dwrect = {0,0,size.w,size.h};
D2DRT->BindDC(hdc,&dwrect);
D2DRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
// set rendering parameters
IDWriteRenderingParams *oldparams = NULL;
IDWriteRenderingParams *params = NULL;
DWFactory->CreateRenderingParams(&oldparams);
DWFactory->CreateCustomRenderingParams(oldparams->GetGamma(),oldparams->GetEnhancedContrast(),0.0f,oldparams->GetPixelGeometry(),DWRITE_RENDERING_MODE_DEFAULT,¶ms);
D2DRT->SetTextRenderingParams(params);
// create the brush colors
ID2D1SolidColorBrush *color = NULL;
D2DRT->CreateSolidColorBrush(<some ColorF>,&color);
// render the text
D2DRT->BeginDraw();
D2DRT->DrawTextLayout(origin,textLayout,color);
D2DRT->EndDraw();
myGraphics->ReleaseHDC(hdc);
hdc = NULL;

It looks like I need to fall back to grayscale antialiasing, but I'm struggling. Please would someone:

  • Explain what grayscale anti-aliasing is supposed to do, and whether it works with transparent bitmap render targets; and
  • Give me some pointers on how to get grayscale anti-alias to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文