PAYATHON 2026

为什么 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 像素;具体尺寸还取决于字体度量和文本内容。

备注:内容仅供参考。