You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取单行Pango字形范围——Rust中Pango+Cairo沿路径绘文本问询

在Rust中使用Pango+Cairo获取字形中心坐标与宽度

你的实现思路是正确的:通过Pango Layout生成文本布局,提取单行、遍历同字体样式的Run,再逐个处理字形信息,是获取带字距/字体间距的字形位置的标准方式。以下是补全的实现步骤和代码示例:

关键步骤说明

  • Pango单位转换:Pango默认使用1/64像素的单位,所有坐标、宽度值需要除以64.0才能转换为Cairo的用户坐标。
  • Run起始位置:每个Run(同字体样式的文本段)在单行中有自己的起始x偏移,需要结合字形的相对偏移计算绝对位置。
  • 字形几何信息:GlyphGeometry的x_offset是字形相对于Run起始点的偏移,width是字形的实际宽度(已包含字距调整)。

完整Rust代码示例

use cairo::{Context, Format, ImageSurface};
use pangocairo::functions::create_layout;
use pango::{FontDescription, LayoutLine};

fn get_glyph_centers(text: &str) -> Vec<(f64, f64)> {
    // 创建Cairo上下文(示例用图片表面,实际可替换为你的绘图上下文)
    let surface = ImageSurface::create(Format::Argb32, 800, 600).unwrap();
    let context = Context::new(&surface);

    // 创建Pango Layout并配置文本和字体
    let layout = create_layout(&context);
    layout.set_text(text);
    let font_desc = FontDescription::from_string("Sans Bold 12");
    layout.set_font_description(Some(&font_desc));

    // 触发布局计算(确保Pango生成完整的字形信息)
    let _ = layout.get_pixel_size();

    // 获取单行(假设输入是单行文本)
    let line = layout.line_readonly(0).unwrap();
    let mut glyph_centers = Vec::new();

    for run in line.runs() {
        let glyph_string = run.glyph_string();
        // 获取Run在单行中的起始x偏移(Pango单位)
        let run_extents = run.extents();
        let run_start_x = run_extents.logical.x;

        for glyph_info in glyph_string.glyph_info() {
            let geom = glyph_info.geometry();
            // 计算字形的绝对起始x(Pango单位)
            let glyph_start_x = run_start_x + geom.x_offset;
            // 计算字形中心x,转换为Cairo坐标(除以64)
            let center_x = (glyph_start_x + geom.width / 2) as f64 / 64.0;
            // 字形宽度(Cairo坐标)
            let glyph_width = geom.width as f64 / 64.0;

            glyph_centers.push((center_x, glyph_width));
        }
    }

    glyph_centers
}

fn main() {
    let centers = get_glyph_centers("Hello World");
    for (i, (center_x, width)) in centers.iter().enumerate() {
        println!("字形{}: 中心x={:.2}, 宽度={:.2}", i, center_x, width);
    }
}

额外提示

  • 如果需要沿自定义路径绘制文本,可将每个字形的中心x坐标映射到路径上的对应点,再结合Cairo的坐标变换和show_glyphs方法实现。
  • 若处理多行文本,只需遍历layout.lines()而非仅取第0行。
  • 如需更精确的字形像素边界,可使用glyph_info.extents()获取字形的墨水范围(实际像素覆盖区域)。

内容的提问来源于stack exchange,提问作者Martin Ždila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:37