如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?

Posted

技术标签:

【中文标题】如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?【英文标题】:How to draw TrueType fonts into an array of pixels in WinAPI? 【发布时间】:2019-01-16 03:24:23 【问题描述】:

有一些 WinAPI 函数可以将 TrueType 字体绘制到 Windows GDI 上下文中。

我想将这个 TrueType 文本写入我自己的二维像素数组中(我只是用这段代码将它粘贴到一个窗口中:)

int blit_mode =  STRETCH_DELETESCANS; 

void BlitFrame() 
 
  BITMAPINFO bmi =   sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0, 0,0,0,0 ;
  SetStretchBltMode(hdc, blit_mode); 
  int result = StretchDIBits(hdc, 
             0, 0, client_x, client_y, 
             0, 0, frame_size_x, frame_size_y, 
             frame_bitmap, 
             &bmi, 
             DIB_RGB_COLORS, 
             SRCCOPY); 
 

这段代码在 WinAPI 中非常混乱,我不知道(至少到现在)该怎么做。

我该怎么做?

【问题讨论】:

搜索“内存设备上下文”和“设备无关位图”。 Petzold 的“Programming Windows”解释了位图、设备上下文以及它们之间的关系。了解您正在使用的概念是一种有效且高效的前进策略。 奇怪的是:即使我不会将这个字形渲染到我的位图中(我不知道该怎么做,这很受欢迎,因为我可以用我的 cpu 等对其进行后处理),我只是将我的像素表blit到窗口然后将这些文本也渲染到窗口 - 然后它也不起作用,它闪烁......我不明白为什么......这一切都是在一个绘画程序中完成的,在我看来它不应该是被视为两个单独的重绘,即使这两个绘图之间的时间间隔很小.. 奇怪的结论可能是窗口在绘图例程结束之前不会缓冲它,而是实时显示它 如果那真的很奇怪..那么我需要将那些将其渲染到我的数组中的例程...但是为什么这一切都如此混乱和如此混乱 这对您来说似乎是一团糟,因为您拒绝做基础工作,并拒绝了解您正在使用的系统的解剖结构。阅读WM_PAINT message 文档以了解您的解决方案为何会出现闪烁。更好的是,获取 Petzold 的Programming Windows®。这是学习 Windows 编程的最有效方式。 【参考方案1】:

tnx 巴马克谢米拉尼

我得到了你的代码并产生了类似的东西

void BlitFrame2()


 BITMAPINFO bmi =   sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0, 0,0,0,0 ;


HDC  memdc = CreateCompatibleDC(hdc);
HBITMAP  hbitmap = CreateBitmap(frame_size_x, frame_size_y, 1, 32, frame_bitmap);
HGDIOBJ  oldbmp = SelectObject(memdc, hbitmap);

SetBkMode(memdc, TRANSPARENT);
SetTextColor(memdc, 0xffffff);
TextOut(memdc, 0, 0, "123", 3);

SelectObject(memdc, oldbmp);
GetDIBits(memdc, hbitmap, 0, frame_size_y, frame_bitmap, &bmi, 0);
DeleteObject(hbitmap);
DeleteDC(memdc);

//  ReleaseDC(0, hdc);

SetStretchBltMode(hdc, blit_mode);

int result = StretchDIBits(hdc,
             0, 0, client_x, client_y,
             0, 0, frame_size_x, frame_size_y,
             frame_bitmap,
             &bmi,
             DIB_RGB_COLORS,
             SRCCOPY);

它为我的 blitted 帧添加了稳定的文本,tnx

悬停我会得到一些问题,因为我不明白它

1) 也许有人可以告诉我更多它是如何工作的以及内存传输在哪里?我对这个用绘制文本更新的像素表有简单的字节访问吗? (例如后处理)

2) 它可以工作,但速度会明显变慢,例如,当我的原始帧为 2 毫秒(绘制一些位图精灵然后 blit)时,使用这个驯服会增长到 8 毫秒

3) 我可以将其中一些调用移到帧循环之外吗?

PS 在考虑这个问题时,我认为它是这样工作的 1)它会在某个时候(在哪里?)将我的像素表复制到 memdc 中 2)它将那些字体吸引到这个memdc 3)GetDIBits 用改变的像素更新我的原始像素表(我不确定这个悬停,但几乎可以肯定) 4)我像以前一样blit它

如果是这样,我得到三个而不是一个 blit(co 它应该慢 3 倍, 测量显示它更像是 4 次,但可能是测量误差(例如 2 和 8 可能是 2.7 和 8.1)

如果这是三个就可以了,但是我认为我并不总是需要从 memdc 重新更新那些表格像素,有没有办法 从 memdc 直接删除它? (那么它只会慢两倍而不是 3 倍,但遗憾的是那些 fount 例程不能直接渲染到我自己的 ram 表中 - 那么它根本不会慢)(真的可能吗?)

【讨论】:

你的目标是什么?您可以使用 memory dc 在位图上绘图。您还可以使用内存 dc 作为绘图缓冲区。 BitBlitStretchBlt 跳过 BITMAPINFO 函数。 hdc 的用法似乎是错误的。 hdc 是一个临时句柄,它可以传递,但不应该保留 - 顺便说一句,您可以更新问题,或者删除答案和问题,而是提出一个新问题。 GDI 字体渲染例程可以直接渲染到设备上下文中,由内存中的位图支持。要看到这一点,需要了解device contexts。

以上是关于如何在 WinAPI 中将 TrueType 字体绘制到像素数组中?的主要内容,如果未能解决你的问题,请参考以下文章

libGDX 中的 TrueType 字体

如何在Linux系统上安装字体

如何更改静态文本控件(winapi)的字体?

PHP:读取字体文件的 TrueType/OpenType 元数据

计算字体 truetype hhea 值(上升、下降)

Office PPT保持提示无法保存Gill Sans 等非TrueType字体