使用Harfbuzz正确组合字符位置

3

我正在尝试使用Harfbuzz和带有签名距离场的图集来渲染文本。

代码基本上是这样的:

void drawText(const std::wstring &str, Vec2 pos)
{
    // Init harfbuzz
    hb_buffer_t *hbBuf = hb_buffer_create();
    hb_buffer_set_direction(hbBuf, HB_DIRECTION_LTR);
    hb_buffer_set_script(hbBuf, HB_SCRIPT_LATIN);
    hb_buffer_set_language(hbBuf, hb_language_from_string("en", 2));

    // Process string
    hb_buffer_add_utf32(hbBuf, reinterpret_cast<const uint32_t*>(str.c_str()), -1, 0, -1);
    hb_shape(font.hb, hbBuf, nullptr, 0);

    // Display string
    unsigned int nbGlyphs;
    hb_glyph_info_t *glyphInfos = hb_buffer_get_glyph_infos(hbBuf, &nbGlyphs);
    hb_glyph_position_t *glyphPos = hb_buffer_get_glyph_positions(hbBuf, &nbGlyphs);

    for(unsigned int i = 0; i < nbGlyphs; i++)
    {
        Vec2 drawPos = pos + Vec2(glyphPos[i].x_offset, glyphPos[i].y_offset) / 64.f;
        drawGlyph(glyphInfos[i].codepoint, drawPos);
        pos.x += glyphPos[i].x_advance / 64.f;
        pos.y += glyphPos[i].y_advance / 64.f;
    }
}

这段文本在英语短语中看起来形状正确,但是当我用变音符号进行测试时,它们看起来错位了。 我正在使用aâa aâ̈a bb̂b bb̂̈b bb̧b bb͜b bb︠︡b 进行测试。Unicode字符串不包含预组合字符。Harfbuzz 使用预组合字符â,使其看起来很好。大多数其他变音符号都偏离了。

变音符号在应该出现的左侧的文本

当我将x_offset乘以0.5时,组合字符的位置更好。重音符和塞迪利亚位于正确的x位置。重音符不堆叠,并且在b上太低。 BBB(U+035C)下的弧线应连接最后两个字母,而不是居中于第二个b

我也尝试了在先前的 b 组中使用 U+FE20 和 U+FE21。在我的测试中,U+FE21 在第二个 b 上,但看起来应该在第三个上。

使用glyphPos [i] .x_offset * 0.5f 测试,效果更好但仍不正确

我尝试了几种字体,但这些字体中只有NotoSansDisplay-Regular.ttf拥有组合字符。在我的Debian系统(测试版,带有HarfBuzz 2.6.4-1)上,我无法使程序按预期显示该字符串。

在Windows上,我获得了更好的结果。以下是我的期望结果:重音符号叠加,组合双短音符放置在正确位置,而塞迪利亚则被移除。

文本渲染更接近我的期望结果

我是否在使用 HarfBuzz 方面出了问题,或者我正在测试 HarfBuzz 尚未支持的地域特例?

编辑:

实际问题未在上述中描述。我使用FreeType加载字体FT_New_Face,然后使用hb_ft_font_create创建了一个hb_font_t。对于每个绘制的字符串,我调用了FT_Set_Pixel_Sizes,但保持了hb_font_t
2个回答

3
你应该尝试使用 hb-view / hb-shape 对相同的文本和字体进行处理。这将有助于你缩小问题范围。我猜测问题可能是出在你是否正确考虑了字形原点在图集中的位置。

1
每次使用FT_Set_Pixel_Sizes更改字体大小时,使用hb_ft_font_create创建一个新的hb_font_t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接