C++ 在Cairo曲面之前创建Pango布局

C++ 在Cairo曲面之前创建Pango布局,c++,text,cairo,pango,pangocairo,C++,Text,Cairo,Pango,Pangocairo,在我的应用程序中,我使用Pango和Cairo创建文本纹理。这些纹理的宽度固定,但应缩放其高度以适合文本内容。这种情况下涉及的父对象将缩放其高度以匹配文本 问题是,我初始化Pango和Cairo的方式不允许这样。目前,该系统由以下人员设置: cairo_surface_t* cairoSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, sizeX, sizeY ); cairo_t* cairoContext = cairo_cr

在我的应用程序中,我使用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\u layout\u get\u size()
找到高度。我想先创建布局,然后使用此函数的输出创建曲面

但是,
pango\u cairo\u create\u layout()
要求已经创建曲面,我无法找到通过cairo从
pango\u layout\u new()
渲染布局的方法。API记录了其中一个渲染函数,
pango\u cairo\u update\u layout()
,指定创建布局时必须使用
pango\u cairo\u create\u layout()
;然而,更重要的函数,
pango\u cairo\u show\u layout()
,注意到没有这样的要求,我不确定这是否意味着任何pango布局都是允许的。虽然我可以测试它是否有效,但我担心反复试验可能会导致我出现未定义的行为


我觉得我陷入了一种鸡和蛋的境地,Pango的文档主要是一个API参考,几乎没有解释如何使用该库。有什么方法可以正确地做到这一点吗?

我已经想出了这个过程。希望这些信息是有帮助的——尽管我不认为这是做任何事情的“正确”方式,但这是可行的

首先,设置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\u cairo\u create\u 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_markup( pangoLayout, text.c_str( ), -1 );
之后,您可以通过
pango\u layout\u get\u pixel\u size()
获取布局高度,并使用该高度创建Cairo的对象。然后可以通过以下方式渲染:

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