You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Linux Fontconfig匹配字体规格提取字体列表遇问题求助

问题

我希望通过Fontconfig匹配指定字体规格来提取字体列表。编写的测试代码可以选出单个“最佳匹配”字体,但尝试列出备选字体时结果为空;若传入空模式则会列出系统所有字体,说明列表逻辑本身正常。

测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <fontconfig/fontconfig.h>

int main(){
    FcConfig* config=NULL;
    FcPattern* pat=NULL;
    FcPattern* font=NULL;
    FcObjectSet* os=NULL;
    FcFontSet* fs=NULL;
    FcChar8* file=NULL;
    char* fontFile=NULL;
    FcResult result;

    int i;

    FcInit();
    config = FcInitLoadConfigAndFonts();

    pat = FcNameParse((const FcChar8*)"Mono");
    //pat=FcPatternCreate();

    FcConfigSubstitute(config, pat, FcMatchPattern);
    FcDefaultSubstitute(pat);

    //os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, (char *) 0);
    os = FcObjectSetBuild (FC_FAMILY, (char *) 0);

    fs = FcFontList(config, pat, os);

    printf("nfonts %d\n", fs->nfont);
    for (i=0; i<fs->nfont; i++){
        font=fs->fonts[i];
        FcPatternGetString(font, FC_FILE, 0, &file);
        printf("font# %d  %s\n", i, (char*)file);
    };

    //  font = FcFontMatch(config, pat, &result);
    //
    //  if (font){
    //      file = NULL;
    //
    //      if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch){
    //          fontFile = (char*)file;
    //          printf("%s\n",fontFile);
    //      };
    //  
    };


    FcFontSetDestroy(fs);
    FcObjectSetDestroy(os);
    //FcPatternDestroy(font);
    FcPatternDestroy(pat);
    FcConfigDestroy(config);
    FcFini();
    return 0;
}
原因与解决方法

核心问题

  1. 替换模式错误:FcConfigSubstitute使用了FcMatchPattern参数,该参数是为单一最佳字体匹配设计的,会对模式进行严格调整,过滤掉所有非最优匹配的字体,导致FcFontList返回空列表。
  2. 属性请求缺失:FcObjectSetBuild只请求了FC_FAMILY属性,但后续代码尝试获取FC_FILE,由于未请求该属性,FcPatternGetString会失败,即使有匹配字体也无法正确输出路径。

修复步骤

  1. 将FcConfigSubstitute的第三个参数改为FcMatchFonts,该参数用于批量字体匹配,保留所有符合规格的备选字体。
  2. 在FcObjectSetBuild中加入FC_FILE属性,确保能获取到字体文件路径。

修改后的关键代码片段

// 改用FcMatchFonts适配批量列表匹配
FcConfigSubstitute(config, pat, FcMatchFonts);
FcDefaultSubstitute(pat);

// 加入FC_FILE属性,保证能获取字体文件路径
os = FcObjectSetBuild(FC_FAMILY, FC_FILE, (char *) 0);

完整修复代码

#include <stdio.h>
#include <stdlib.h>
#include <fontconfig/fontconfig.h>

int main(){
    FcConfig* config=NULL;
    FcPattern* pat=NULL;
    FcPattern* font=NULL;
    FcObjectSet* os=NULL;
    FcFontSet* fs=NULL;
    FcChar8* file=NULL;
    char* fontFile=NULL;
    FcResult result;

    int i;

    FcInit();
    config = FcInitLoadConfigAndFonts();

    pat = FcNameParse((const FcChar8*)"Mono");
    //pat=FcPatternCreate();

    // 替换为FcMatchFonts,用于列表匹配
    FcConfigSubstitute(config, pat, FcMatchFonts);
    FcDefaultSubstitute(pat);

    // 加入FC_FILE属性,确保能获取字体文件路径
    os = FcObjectSetBuild(FC_FAMILY, FC_FILE, (char *) 0);

    fs = FcFontList(config, pat, os);

    printf("nfonts %d\n", fs->nfont);
    for (i=0; i<fs->nfont; i++){
        font=fs->fonts[i];
        if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) {
            printf("font# %d  %s\n", i, (char*)file);
        }
    };

    FcFontSetDestroy(fs);
    FcObjectSetDestroy(os);
    FcPatternDestroy(pat);
    FcConfigDestroy(config);
    FcFini();
    return 0;
}

内容的提问来源于stack exchange,提问作者Marta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:20:31