Qt源码那些事儿-Linux下Qt的QFontDataBase字体引擎解析

2024-05-12 19:48

本文主要是介绍Qt源码那些事儿-Linux下Qt的QFontDataBase字体引擎解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

公众号:Qt那些事儿

公众号

简介

Qt中对于字体处理最常用的三个类

  • QFontDataBase
  • QFont
  • QFontInfo

今天主要讲的是Qt在Linux下字体的基础-QFontDataBase类。

QFontDataBase

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 >= 20297FC_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。这里只上了部分代码,其它的函数也是如此获取的字体相关的信息

//xxxxxxxxxxxxxxxxxxxxxxxxxxxif (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源码那些事儿-Linux下Qt的QFontDataBase字体引擎解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983574

相关文章

QT移植到RK3568开发板的方法步骤

《QT移植到RK3568开发板的方法步骤》本文主要介绍了QT移植到RK3568开发板的方法步骤,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录前言一、获取SDK1. 安装依赖2. 获取SDK资源包3. SDK工程目录介绍4. 获取补丁包二

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(

Java的volatile和sychronized底层实现原理解析

《Java的volatile和sychronized底层实现原理解析》文章详细介绍了Java中的synchronized和volatile关键字的底层实现原理,包括字节码层面、JVM层面的实现细节,以... 目录1. 概览2. Synchronized2.1 字节码层面2.2 JVM层面2.2.1 ente

Linux下修改hostname的三种实现方式

《Linux下修改hostname的三种实现方式》:本文主要介绍Linux下修改hostname的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下修改ho编程stname三种方式方法1:修改配置文件方法2:hFvEWEostnamectl命

Linux虚拟机不显示IP地址的解决方法(亲测有效)

《Linux虚拟机不显示IP地址的解决方法(亲测有效)》本文主要介绍了通过VMware新装的Linux系统没有IP地址的解决方法,主要步骤包括:关闭虚拟机、打开VM虚拟网络编辑器、还原VMnet8或修... 目录前言步骤0.问题情况1.关闭虚拟机2.China编程打开VM虚拟网络编辑器3.1 方法一:点击还原VM

Linux搭建Mysql主从同步的教程

《Linux搭建Mysql主从同步的教程》:本文主要介绍Linux搭建Mysql主从同步的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux搭建mysql主从同步1.启动mysql服务2.修改Mysql主库配置文件/etc/my.cnf3.重启主库my

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

Linux系统之authconfig命令的使用解读

《Linux系统之authconfig命令的使用解读》authconfig是一个用于配置Linux系统身份验证和账户管理设置的命令行工具,主要用于RedHat系列的Linux发行版,它提供了一系列选项... 目录linux authconfig命令的使用基本语法常用选项示例总结Linux authconfi

Python批量调整Word文档中的字体、段落间距及格式

《Python批量调整Word文档中的字体、段落间距及格式》这篇文章主要为大家详细介绍了如何使用Python的docx库来批量处理Word文档,包括设置首行缩进、字体、字号、行间距、段落对齐方式等,需... 目录关键代码一级标题设置  正文设置完整代码运行结果最近关于批处理格式的问题我查了很多资料,但是都没

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR