DirectWrite文本位置因字体大小而异

时间:2013-08-07 13:27:57

标签: c++ winapi directwrite

我正在使用DirectWrite将一些文本渲染到窗口。除了使用不同字体大小的定位外,一切似乎都有效:我希望有两个字体大小为v1和v2的文本以及两个带有(x,y)=(0,0)的文本位于左上角,但正如您所见:

enter image description here

“测试”和“X”都不在左上角。

有没有办法让这项工作?

3 个答案:

答案 0 :(得分:7)

欢迎来到字体世界。字体可能是最难使用的东西,因为字体本身有惊喜(有很多新标准应该解决所有问题而且只是混淆更多,因为几乎没有字体支持它100%,甚至一些'经典'字体有其中的部分/不良信息)GDI,GDI +,DirectDraw不会因为数学,坐标舍入,抗锯齿而在像素中的相同位置绘制字体...(如果你用数学计算,你可以再获得一个奖励freetype)。

当您尝试打印字体时,还有其他pb。所以解决这个问题的唯一方法就是对我而言。甚至不尝试在某些像素坐标处绘制字体。你的工作是在绘制字体,图片,在屏幕上渲染得很好的线条,尽力将它们转换为出口的打印坐标,但从不期望控制字体中的像素,一切都是近似的。

PS:不要相信字体中的内部字段。在Arial上,它们对所有其他字体都很好,有些缺失或初始化为零,但“有趣”部分并不总是相同的字段,它不存在取决于字体。如果您之前按字体尝试,则只能使用这些字段。是的字体太棒了!

答案 1 :(得分:2)

@evilruff所指的术语被称为“内部领导”。您可以使用IDWriteFontFace::GetMetricsIDWriteFontFace::GetDesignGlyphMetrics来获取此值(对于GetMetrics,您要查找的值很可能是metrics.ascent - metrics.capHeight)。

这里的值是字体设计单位,而不是像素(任何种类)。您可以通过除以metrics.designUnitsPerEm将这些值转换为em高度;通常,DirectWrite中的字体大小由(小写)m的像素大小指定;因此,如果将ems中的值乘以字体大小,则应获得以像素为单位的值。

答案 2 :(得分:0)

我假设您正在将IDWriteTextLayout与DrawTextLayout结合使用(而不是创建自己的DWRITE_GLYPH_RUN)。 IDWriteTextLayout将字形对齐到它们的布局单元格(包括完整的上升和线条间隙),而不是字形墨水,几乎所有文本布局都是如此,无论是Web浏览器还是文字处理器还是简单的编辑控件。如果他们没有(而是与字母的顶部对齐),那么像Ť这样的词语中的变音符会被剪掉。

如果您始终想要与墨水对齐,请创建IDWriteTextLayout,调用IDWriteTextLayout :: GetOverhangMetrics,然后调用DrawTextLayout,其原点等于负DWRITE_OVERHANG_METRICS :: left& top。如果你想总是与帽子高度对齐(那样“hello”和“Hello”都会在同一个垂直坐标上绘制),那么Eric的方法就可以了。