【问题标题】:Create Pango Layout Before Cairo Surface在 Cairo 曲面之前创建 Pango 布局
【发布时间】:2015-08-03 13:26:01
【问题描述】:

在我的应用程序中,我使用 Pango 和 Cairo 创建文本纹理。这些纹理的宽度是固定的,但应该缩放它们的高度以适应文本内容。在这种情况下,父对象会缩放它们的高度以匹配文本。

问题是,我一直在初始化 Pango 和 Cairo 的方式不允许这样做。目前,系统由:

cairo_surface_t* cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, sizeX, sizeY );
cairo_t* cairoContext = cairo_create( cairoSurface );
PangoLayout* pangoLayout = pango_cairo_create_layout( cairoContext );

它固定了高度,至少是表面的高度——这是我不想做的事情,至少不是一直都不想做。

我的理解是,如果没有指定布局高度,它会自动缩放高度,然后可以通过pango_layout_get_size()找到。我想先创建布局,然后使用此函数的输出创建表面。

但是,pango_cairo_create_layout() 要求已创建表面,我一直无法找到通过 Cairo 从 pango_layout_new() 渲染布局的方法。 API 文档中的渲染函数之一 pango_cairo_update_layout() 指定必须使用 pango_cairo_create_layout() 来创建布局;然而,更重要的功能pango_cairo_show_layout() 没有指出这样的要求,我不确定这是否意味着允许任何 Pango 布局。虽然我可以测试它是否有效,但我担心反复试验可能会导致我出现未定义的行为。

我觉得自己陷入了先有鸡还是先有蛋的困境,Pango 的文档主要是 API 参考,几乎没有解释该库的用途。有没有办法正确地做到这一点?

【问题讨论】:

    标签: c++ text cairo pango pangocairo


    【解决方案1】:

    我已经弄清楚了这个过程。希望这些信息对您有所帮助 - 尽管我没有声称这是执行任何这些操作的“正确”方式,但它确实有效。

    首先,设置 FontConfig。在某些系统上这可能不是必需的——在 Linux 上让它自动运行可能是可以的。但是,在 Windows 上,FontConfig 是有问题的。处理它的最简单方法是在内存中创建一个配置并将其指向您希望它查找字体的位置。我将它指向我的程序的资源目录。您可以使用“C:\Windows\Fonts”,但请注意这需要永远加载。加载正确的 font.conf 文件可能是最好的方法,但我自己运气不佳。

    gchar* workingDir = g_get_current_dir();
    gchar* resourceDir = g_strjoin( NULL, workingDir, "/Resources", (char*)0 );
    FcConfigAppFontAddDir( fontConfig, (const FcChar8*)resourceDir );
    g_free(workingDir);
    g_free(resourceDir);
    FcConfigBuildFonts( fontConfig );
    FcConfigSetCurrent( fontConfig );
    

    然后,您必须创建字体映射、Pango 上下文和 Pango 布局:

    PangoFontMap* fontMap = pango_cairo_font_map_new();
    PangoContext* pangoContext = pango_font_map_create_context( fontMap );
    PangoLayout* pangoLayout = pango_layout_new( pangoContext );
    

    现在,使用手动创建(不是来自 pango_cairo_create_layout())的布局似乎不会自动加载字体。尝试使用在字体映射中但未加载的字体会导致 Pango-Cairo 崩溃(使用未列出的完全没有列出的字体只是进入默认值)。因此,加载字体映射中列出的所有字体:

    FcPattern *p = FcPatternCreate();
    FcObjectSet *os = FcObjectSetBuild(FC_FAMILY,NULL);
    FcFontSet *fs = FcFontList(fontConfig, p, os);
    FcPatternDestroy( p );
    FcObjectSetDestroy( os );
    for( int i = 0; i < fs->nfont; ++i )
    {
        guchar* fontName = FcNameUnparse( fs->fonts[i] );
        PangoFontDescription* fontDesc = pango_font_description_from_string( (gchar*)fontName );
        pango_font_map_load_font( fontMap, pangoContext, fontDesc );
        pango_font_description_free( fontDesc );
        g_free(fontName);
    }
    

    指定宽度:

    pango_layout_set_width( pangoLayout, sizeX * PANGO_SCALE );
    

    这也是您应该设置对齐/对齐/等的点。

    然后你可以插入你的文字:

    pango_layout_set_markup( pangoLayout, text.c_str( ), -1 );
    

    在此之后,您可以通过pango_layout_get_pixel_size() 获取布局高度并使用它来创建 Cairo 的对象。然后你可以通过以下方式渲染它:

    cairo_move_to(cairoContext, 0, 0);
    pango_cairo_update_layout( cairoContext, pangoLayout );
    pango_cairo_show_layout( cairoContext, pangoLayout );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多