如何在gtk中从文件载入字体

⌚Time: 2024-06-28 10:26:00

👨‍💻Author: Jack Ge

使用pango库的PangoFontDescription来获取字体

使用gtk_widget_modify_font函数来改变控件使用的字体

GtkWidget* label;
...

PangoFontDescription *font_desc = pango_font_description_from_string("Fixedsys Excelsior");  
pango_font_description_set_size (font_desc, 15 * PANGO_SCALE);

gtk_widget_modify_font (GTK_WIDGET(label),  font_desc);
pango_font_description_free (font_desc);

但是这种办法只能使用在系统中注册的字体,如果要从文件中载入字体,在windows系统里,可以使用windows API的 AddFontResource函数来注册字体,之后再使用这个办法来改变字体


// 载入字体文件
const char* fontFile = "fonts/FSEX302.ttf";
if (AddFontResource(fontFile)) {
    // 更新字体资源
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
        
    // 在这里可以使用已载入的字体进行操作
}

对于linux系统,可以使用freetype库或者fontconfig库来加载字体,下面是AI写的例子

#include <gtk/gtk.h>
#include <fontconfig/fontconfig.h>

int main(int argc, char *argv[]) {
    GtkWidget *window;
    GtkWidget *label;
    PangoFontDescription *font_desc;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);

    // 从文件中加载字体
    FcConfigAppFontAddFile(FcConfigGetCurrent(), "/path/to/font.ttf");

    // 创建一个Pango字体描述符
    font_desc = pango_font_description_new();

    // 设置字体描述符的家族和大小
    pango_font_description_set_family(font_desc, "Custom Font");
    pango_font_description_set_absolute_size(font_desc, 12 * PANGO_SCALE);

    // 创建一个带有自定义字体的标签
    label = gtk_label_new("Custom Font");
    gtk_widget_override_font(label, font_desc);

    gtk_container_add(GTK_CONTAINER(window), label);
    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

另外,对于 AddFontResource的微软解释

AddFontResource 函数将指定文件中的字体资源添加到系统字体表中。 字体随后可用于任何应用程序的文本输出。

若要将字体标记为专用或不可枚举,请使用 AddFontResourceEx 函数。

语法

int AddFontResourceW(
  [in] LPCWSTR unnamedParam1
);

参数 [in] unnamedParam1

指向包含有效字体文件名的以 null 结尾的字符串的指针。 此参数可以指定以下任何文件。


File Extension  Meaning
.fon
Font resource file.
.fnt
Raw bitmap font file.
.ttf
Raw TrueType file.
.ttc
East Asian Windows: TrueType font collection.
.fot
TrueType resource file.
.otf
PostScript OpenType font.
.mmm
Multiple master Type1 font resource file. It must be used with .pfm and .pfb files.
.pfb
Type 1 font bits file. It is used with a .pfm file.
.pfm
Type 1 font metrics file. It is used with a .pfb file.
 

关于windows系统字体的安装和删除

仅当该字体驻留在指定的设备上或安装在系统字体表中时,应用程序才能使用该字体来绘制文本。 字体表是一个内部数组,用于标识应用程序可用的所有非设备字体。 应用程序可以通过调用 EnumFontFamilies 或 ChooseFont 函数来检索当前安装在设备上或存储在内部字体表中的字体的名称。

若要临时安装字体,请调用 AddFontResource 或 AddFontResourceEx。 这些函数加载存储在字体资源文件中的字体。 但是,这是一个临时安装,因为在重新启动后,字体将不存在。

若要安装将在系统重新启动后保留的字体,请使用以下方法之一:

在任何活动会话(包括会话 0)中加载时,无法修改从 %windir%\fonts 文件夹以外的位置安装的字体。 因此,将阻止任何更改、替换或删除的尝试。 如果需要修改字体:

每当应用程序调用添加和删除字体资源的函数时,它还应调用 SendMessage 函数,并将 WM_FONTCHANGE 消息发送到系统中的所有顶级窗口。 此消息通知其他应用程序,已由添加或删除字体的应用程序更改了内部字体表。


问AI如果多次调用AddFontResource会怎样:

在Windows上,如果你多次使用AddFontResource函数来加载同一字体,它只会在第一次调用时将字体添加到系统字体资源中。重复调用AddFontResource函数不会导致重复加载字体。

以下是一个示例代码,演示了多次使用AddFontResource函数加载同一字体的情况:

#include <Windows.h>

int main() {
    const wchar_t* fontFile = L"path/to/font.ttf";
    
    // 第一次加载字体文件
    if (AddFontResource(fontFile)) {
        // 更新字体资源
        SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
        
        // 在这里可以使用已加载的字体进行操作
    }
    
    // 再次加载同一字体文件
    if (AddFontResource(fontFile)) {
        // 更新字体资源
        SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
        
        // 在这里可以继续使用已加载的字体进行操作
    }
    
    // ...
    
    return 0;
}

无论调用AddFontResource函数多少次,字体只会被添加到字体资源中一次。这意味着你可以在程序中多次使用AddFontResource来加载同一字体,而无需担心重复加载的问题。