为什么 pango_layout_get_pixel_extents 返回 0×2 矩形?
问题出在字号单位。pango_font_description_set_size(desc, 16) 设置的字号是 16 / PANGO_SCALE pt。要设置 16 pt,应使用 pango_font_description_set_size(desc, 16 * PANGO_SCALE)。把设置字号的操作放在单独的函数中没有问题。Pango 字号参数说明
为什么会得到 0×2?
pango_font_description_set_size() 接收的是经过 PANGO_SCALE 缩放的点数。按文档当前的 PANGO_SCALE = 1024 计算,原代码设置的字号实际上是:
16 / 1024 pt = 0.015625 pt
这个字号远小于正常显示文字的字号。代码中应使用 PANGO_SCALE 宏,不要写死数值。PANGO_SCALE 定义
两个测量函数返回的单位也不同:
pango_layout_get_extents()返回 Pango 单位下的矩形。pango_layout_get_pixel_extents()返回设备单位下的整数矩形;在题目中的图像 surface 场景下,通常就是像素。
像素矩形会向外取整,以完整包含原始矩形。在极小字号下,字形度量、行高和取整可能产生看起来异常的结果。仅凭这段代码,不能断定所有字体后端都会得到相同的 0×2,也不能把宽度为 0 简单解释为“非零宽度向下取整”。可以确定的是,传入字号时少乘了 PANGO_SCALE。布局尺寸单位、像素矩形取整规则
如何设置为 16 pt?
替换设置字号的那一行,保留其余调用顺序即可:
pango_layout_set_text(layout, "Hello, world!", 13);
pango_font_description_set_size(desc, 16 * PANGO_SCALE);
pango_layout_set_font_description(layout, desc);
如果需要把整数 pt 字号作为参数传入,可以封装成:
static void set_layout_font_size(PangoLayout *layout,
PangoFontDescription *desc,
int size_pt)
{
pango_font_description_set_size(desc, size_pt * PANGO_SCALE);
pango_layout_set_font_description(layout, desc);
}
调用时传入实际的 pt 值:
set_layout_font_size(layout, desc, 16);
如果想设置为 16 像素呢?
使用 pango_font_description_set_absolute_size()。这个函数按设备单位设置字号,参数同样需要乘以 PANGO_SCALE:
pango_font_description_set_absolute_size(desc, 16.0 * PANGO_SCALE);
pango_layout_set_font_description(layout, desc);
在设备单位为像素的后端中,这表示 16 像素字号。pt 字号到像素的换算依赖分辨率设置,因此 16 pt 和 16 像素不能混用。绝对字号参数说明
测量结果还需要注意什么?
原代码将矩形传给第三个参数 logical_rect,获取的是逻辑布局范围。若要测量实际绘制字形的范围,应使用第二个参数 ink_rect:
PangoRectangle ink_rect, logical_rect;
pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect);
字号描述字体的大小,布局矩形描述整段文本的范围。即使设置了 16 像素字号,返回的文本高度也不一定恰好是 16 像素;具体尺寸还取决于字体度量和文本内容。
备注:内容仅供参考。
