QFontDataBase为Qt提供了当前系统所有可用的字体及其信息

Linux平台

Linux平台下,Qt解析字体相关的库使用的是FontConfig。
Fontconfig是用于配置和自定义字体访问的库。

Fontconfig可以:
自动安装时发现新字体,从而消除了常见的配置问题。
执行字体名称替换,以便在缺少字体时可以选择适当的替代字体。
确定完全覆盖一组语言所需的一组字体。
因为使用基于XML的配置文件而构建了GUI配置工具(尽管具有自动发现功能,但我们认为这种需求已最小化)。
即使已安装了数千种字体,也可以在减少内存使用的同时,高效,快速地在已安装的字体集中找到所需的字体。
与X Render Extension和FreeType配合使用,可在显示器上实现高质量,抗锯齿和亚像素渲染的文本。

Fontconfig不会:
自己渲染字体(留给FreeType或其他渲染机制)
以任何方式依赖于X Window系统,因此仅打印机应用程序不具有此类依赖关系

Qt的流程

所以Qt解析字体的一个流程即

使用FontConfig提取字体相关的信息(比如字体名称,风格)。组织成Qt自己的数据结构。然后再提供给QFont,QFontInfo等类来使用。

先上Qt中使用FontConfig解析字体相关信息的代码

//qt-everywhere-src-5.15.0/qtbase/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
void QFontconfigDatabase::populateFontDatabase()
    FcInit();
    FcFontSet  *fonts;
        FcObjectSet *os = FcObjectSetCreate();
        FcPattern *pattern = FcPatternCreate();
        const char *properties [] = {
            FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT,
            FC_SPACING, FC_FILE, FC_INDEX,
            FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE,
            FC_WIDTH, FC_FAMILYLANG,
#if FC_VERSION >= 20297
            FC_CAPABILITY,
#endif
            (const char *)nullptr
        const char **p = properties;
        while (*p) {
            FcObjectSetAdd(os, *p);
            ++p;
        fonts = FcFontList(nullptr, pattern, os);
        FcObjectSetDestroy(os);
        FcPatternDestroy(pattern);

上面代码首先将 字体中需要解析的信息(比如字体名称FC_FAMILY,字体风格FC_STYLEden 等等) 塞到FcObjectSet中,等待解析。然后通过函数FcFontList获取系统中所有的字体信息(上面我们添加的)FcFontSet *fonts

然后开始通过循环解析我们系统中的字体

    for (int i = 0; i < fonts->nfont; i++)
        populateFromPattern(fonts->fonts[i]);

下面开始讲解 populateFromPattern

    if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch)
        return;
    familyName = QString::fromUtf8((const char *)value);
    if (FcPatternGetString(pattern, FC_FAMILYLANG, 0, &value) == FcResultMatch)
        familyNameLang = QString::fromUtf8((const char *)value);

通过上面的函数我们得到了字体的名称,跟名称对应的语言。即 FC_FAMILY FC_FAMILYLANG。这里只上了部分代码,其它的函数也是如此获取的字体相关的信息

//xxxxxxxxxxxxxxxxxxxxxxxxxxx
    if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch)
        slant_value = FC_SLANT_ROMAN;
    if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch)
        weight_value = FC_WEIGHT_REGULAR;
    if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch)
        width_value = FC_WIDTH_NORMAL;
    if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch)
        spacing_value = FC_PROPORTIONAL;
    if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch)
        file_value = nullptr;
    if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch)
        indexValue = 0;
    if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch)
        scalable = FcTrue;
    if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch)
        foundry_value = nullptr;
    if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch)
        style_value = nullptr;
    if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch)
        antialias = true;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

这样,我们就得到了所有的字体信息,然后最后通过函数放入到Qt中

void qt_registerFont(const QString &familyName, const QString &stylename,
                     const QString &foundryname, int weight,
                     QFont::Style style, int stretch, bool antialiased,
                     bool scalable, int pixelSize, bool fixedPitch,
                     const QSupportedWritingSystems &writingSystems, void *handle)
    QFontDatabasePrivate *d = privateDb();
    qCDebug(lcFontDb) << "Adding font: familyName" << familyName << "stylename" << stylename << "weight" << weight
        << "style" << style << "pixelSize" << pixelSize << "antialiased" << antialiased << "fixed" << fixedPitch;
    QtFontStyle::Key styleKey;
    styleKey.style = style;
    styleKey.weight = weight;
    styleKey.stretch = stretch;
    QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::EnsureCreated);
    f->fixedPitch = fixedPitch;
    for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
        if (writingSystems.supported(QFontDatabase::WritingSystem(i)))
            f->writingSystems[i] = QtFontFamily::Supported;
    QtFontFoundry *foundry = f->foundry(foundryname, true);
    QtFontStyle *fontStyle = foundry->style(styleKey, stylename, true);
    fontStyle->smoothScalable = scalable;
    fontStyle->antialiased = antialiased;
    QtFontSize *size = fontStyle->pixelSize(pixelSize ? pixelSize : SMOOTH_SCALABLE, true);
    if (size->handle) {
        QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
        if (integration)
            integration->fontDatabase()->releaseHandle(size->handle);
    size->handle = handle;
    f->populated = true;

最后总结下:实际上,Qt在不同的平台,分别调用的当前系统的库函数,来封装成统一的接口提供给开发者,我们不需要自己再引用对应的库了。这才是Qt的理念。
Code Less

公众号:Qt那些事儿

公众号:Qt那些事儿简介Qt中对于字体处理最常用的三个类QFontDataBaseQFontQFontInfo今天主要讲的是Qt在Linux下字体的基础-QFontDataBase类。QFontDataBaseQFontDataBase为Qt提供了当前系统所有可用的字体及其信息Linux平台Linux平台下,Qt解析字体相关的库使用的是FontConfig。Fontconfig是用于配置和自定义字体访问的库。Fontconfig可以:自动安装时发现新字体,从而消除了常见的配 cmake: find_package(Qt6 COMPONENTS Gui REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Gui) qmake: QT += gui 注意:此类中的所有函数都是线程安全的。 此类的最常见用法是在数据库中查询字体系列(families)的列表以及每个系列可用的p QFontDatabase fontbase; //遍历本地字库 foreach (const QString &fontfamily, fontbase.families()) { qDebug()<<fontfamily; QString log; int fontId = QFontDatabase::addApplicationFont("ukai.ttc"); QString QFontDatabase: Cannot find font directory /home/tgm/qt/qt_sdk/lib/fonts. Note that Qt no longer ships fonts. Deploy some (from http://dejavu-fonts.org for example) or switch to fontconfig. QFontDatabase: Cannot find fon
QFontDatabase类提供了关于底层窗口系统中可用字体的信息。 这个类最常见的用途是查询数据库中每个字体族families()的列表和pointSizes()和styles()。pointSizes()的另一个替代方法是smoothSizes(),它返回指定字体和风格的sizes。 如果字体族可以从两个或更多的制造商,制造商名称包括在字体族名称中;例如:“Helvetica [Adobe]”和“Helvetica [Cronyx]”。当你指定一个字体族,你可以使用旧的连接字符“foundry-..
sudo apt-get install libfontconfig1-dev ./configure -qt-freetype -fontconfig -nomake examples -nomake docs -nomake demo make && make install cp xxx.ttf/...
linux上装完qt之后,跑了一个简单的小程序,发现不支持中文,经过上网找资料研究发现,编译QT的时候没有编译字体库,于是重新编译QT, . 首先配置一些编译Qt要用到的程序,使用以下命令: sudo apt-get  install build-essential  libpcap0.8-dev  libx11-dev  libfreetype6-dev  libavahi-go
int fontId = QFontDatabase::addApplicationFont(qApp->applicationDirPath() + "/Styles/fontawesome-webfont.ttf"); QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);                                        Qt应用程序中设置字体          应用程序中常常须要设置字体。比如office软件或者是其它的编辑器软件等等。这里主要涉及到例如以下几个概念:字体,字号以及风格(比如:粗体,斜体。下划线等等)。Qt里面也有相应的类。接下来我们主要对这几个类进行具体的说明。最后举例说明它们的应用。 1、Qt中相关的类:...
Qt中,可以通过添加自己的字体库来使用自定义字体。具体步骤如下: 1. 将字体文件(.ttf或.otf格式)添加到你的应用程序文件夹中,或者将它们放在系统字体库目录之一中,比如在Linux系统中是/usr/share/fonts目录。 2. 在Qt应用程序中,使用QFontDatabase类加载字体。例如,以下代码演示如何加载名为“myfont.ttf”的字体文件: QFontDatabase::addApplicationFont(":/fonts/myfont.ttf"); 其中,addApplicationFont()函数接受字体文件路径作为参数,路径可以是相对路径或绝对路径。冒号后面的“/fonts”表示字体文件在Qt资源文件中的路径。 3. 加载字体后,可以使用QFont类来设置自定义字体。例如,以下代码使用“myfont字体来设置标签的字体QFont font("myfont"); font.setPointSize(12); ui->label->setFont(font); 这些步骤可以帮助你在Qt应用程序中添加自己的字体库。