深入了解 GTK 字体选择器

我之前写过关于 GTK 中字体处理的文章。这篇文章将重点介绍如何在应用程序中使用更高级的字体(和字体选择器)功能。

查找字体

文件选择器最突出的最终用户功能当然是,您可以使用搜索条目按名称搜索字体

一个更隐蔽的功能是,您可以按各种条件过滤列表。一个条件是仅显示等宽字体,另一个条件是仅显示覆盖特定语言的字体

这里需要注意的一个小细节是,GTK 会自动更改预览文本以匹配您正在筛选的语言。

少即是多

字体选择器返回一个PangoFontDescription,其中包含所选字体的完整详细信息:字体系列、样式、大小等。如果您的应用程序只需要字体系列,那么让用户选择样式和大小,结果却被忽略,这会让人感到困惑。

如果您的应用程序是这种情况,您可以使用 gtk_font_chooser_set_level() 和 GtkFontChooserLevel 标志来指示 GTK 您需要的字体详细信息

typedef enum {
  GTK_FONT_CHOOSER_LEVEL_FAMILY     = 0,
  GTK_FONT_CHOOSER_LEVEL_STYLE      = 1 << 0, 
  GTK_FONT_CHOOSER_LEVEL_SIZE       = 1 << 1,
  GTK_FONT_CHOOSER_LEVEL_VARIATIONS = 1 << 2,
  GTK_FONT_CHOOSER_LEVEL_FEATURES   = 1 << 3
} GtkFontChooserLevel;

例如,在

gtk_font_chooser_set_level (chooser, 
                            GTK_FONT_CHOOSER_LEVEL_FAMILY);

之后,字体选择器看起来像这样

简单多了!

深入深渊

现代字体是复杂的野兽,并且表面之下隐藏着许多东西。如果您告诉 GTK 字体选择器,它可以提供许多字体功能。

首先,有字体变体。这些使您可以连续更改字体的特性(只要这些特性作为变体轴公开)。

 

典型的变体轴是字体的粗细、宽度和倾斜度,但也可以有其他的(例如本示例中的光学尺寸)。

选定的变体是字体选择器返回的 PangoFontDescription 的一部分,应用程序无需进行任何额外的工作来应用它们。只需像往常一样使用字体描述即可。

要在 GTK 文件选择器中启用字体变体支持,请使用 GTK_FONT_CHOOSER_LEVEL_VARIATIONS 标志

level = level | GTK_FONT_CHOOSER_LEVEL_VARIATIONS;
gtk_font_chooser_set_level (chooser, level);

更多功能

字体不仅包含字形轮廓,还包含许多其他数据,可以在渲染这些字形时以各种方式应用。这包括传统的字距调整和连字等数据,还包括可选的字形形状或定位变体,甚至是调色板。用户可以通过OpenType 功能启用其中的许多功能。

这是一个用于字形形状变体的 OpenType 功能示例


从左到右切换时在此处启用的功能称为 *ss12*。值得庆幸的是,该字体还提供了更有意义的名称“单层 g”。

此示例显示了 *frac* 功能对分数显示的影响。

在 GTK 字体选择器中,OpenType 功能与变体显示在同一页面上。如您所见,它们可能有很多

请注意,Pango 将 OpenType 功能视为与字体本身分开。它们不是字体描述的一部分,但必须使用 PangoAttributes 或通过 Pango 标记将它们应用于文本。

要应用来自 GTK 字体选择器的选定字体功能,请调用 gtk_font_chooser_get_font_features() 并将返回的字符串传递给 pango_attr_font_features_new()。

要在 GTK 文件选择器中启用 OpenType 功能支持,请使用 GTK_FONT_CHOOSER_LEVEL_FEATURES 标志

level = level | GTK_FONT_CHOOSER_LEVEL_FEATURES;
gtk_font_chooser_set_level (chooser, level);

总结

总之,您可以使用 GtkFontChooser 的级别属性来影响您向应用程序用户提供的字体选择粒度。如果您在其中包含字体功能,请不要忘记使用 PangoAttributes 或标记来应用选定的功能。

所有这一切都得益于 harfbuzz 为我们提供了跨平台的字体及其所有功能的 API。否则是不可能实现的。值得指出的是,这是通过直接访问 harfbuzz 对象来完成的,而不是将所有 harfbuzz API 包装在 Pango 中。