字体的 build 配置有三个基本层:
背景
将一系列字体添加到 Fuchsia build 的设置 非常困难。这是因为
- Fuchsia 的开发者指南倾向于将预构建的二进制文件保留在 CIPD 中, 不在 Git 代码库中
- Fuchsia 的字体文件来自各种来源。
- 在运行的 Fuchsia 系统上,仅仅为客户提供
目录中包含
.ttf
个文件。 - 字体元数据冗长、经常重复,并且容易维护。它 最好为每个常用字体仅定义一次此元数据 而非询问产品定位和 单独的组件来管理自己的副本。
通用基础架构和元数据
第一层为资产和元数据建立目录, 可用于 Fuchsia 产品 build。
字体数据存储区
字体文件的元数据和外部源列表保存在
字体数据代码库。对于 Fuchsia 的开源字体,您可以在以下位置找到该字体:
//fontdata
。
每当字体数据代码库的内容发生变化时,Furchsia 的 自动化基础架构会自动对其进行检查, 代码库描述的字体文件,并将它们捆绑到 CIPD 软件包中 并上传到 Fuchsia 的 CIPD 服务器。
字体数据存储区包含以下文件:
manifest.xml
这是一个 Jiri 清单文件。 在本示例中,它由 Git 代码库和修订版本 ID 列表组成,其中包含 所需的字体文件
每个导入的代码库都列在 <project>
元素中。
示例条目:
<project
name="github.com/googlefonts/noto-cjk"
path="github.com/googlefonts/noto-cjk"
remote="https://fuchsia.googlesource.com/third_party/github.com/googlefonts/noto-cjk"
remotebranch="upstream/master"
revision="be6c059ac1587e556e2412b27f5155c8eb3ddbe6"/>
name
:任意名称(不会影响任何内容)path
:确定代码库相对于根的检出位置 checkout 目录。remote
:远程代码库的 Git 网址remotebranch
:远程代码库中的分支名称revision
:用于固定检出的 Git 提交哈希值
contents.json
这些是供 Fuchsia 的基础架构从
checkout 目录进入暂存目录 (staging directory)。{destination,
files}
的每个条目都定义了暂存目录中的顶级文件夹,并且
文件。
示例条目:
{
"destination": "material",
"files": [
"github.com/google/material-design-icons/iconfont/MaterialIcons-Regular.ttf",
"github.com/google/material-design-icons/LICENSE"
]
}
${catalog_name}.font_catalog.json
字体目录文件是人工编写的,包含所有字体的元数据, 系列、资源和字体。
为便于修改,我们提供了 .font_catalog.json
文件的 JSON 架构
在
/src/fonts/tools/schemas/font_catalog.schema.json.
规范架构为
在 Rust 中定义。
packing_script.py
Fuchsia 的基础架构会在填充预演条件后调用此脚本 目录。
脚本:
- 将暂存目录中的所有字体和许可文件复制到输出中 目录。
- 在以下文件中生成
${catalog_name}.font_pkgs.json
文件: 输出目录中。
此脚本通常不需要修改。
基础架构配方
如上所述,无论何时,只要
fontdata
的修改。这个食谱:
- 使用
jiri init
和jiri update
检出引用的代码库。 - 根据
contents.json
暂存已签出的文件。 - 调用打包脚本以将文件写入输出 目录。
- 将输出目录的内容上传到 CIPD。
CIPD 软件包
系统会将开放源代码字体包上传到
fuchsia/third_party/fonts
CIPD 软件包。
Jiri 预构建
CIPD 软件包的内容通过
prebuilts
jiri 清单:
<!-- Fonts -->
<package name="fuchsia/third_party/fonts"
version="git_revision:a10ce51e308f48c5e6d70ab5777434af46a5ddb8"
path="prebuilt/third_party/fonts"/>
可以获取 fuchsia/third_party/fonts
软件包的 version
ID
通过“代码”菜单集群上的最新实例
“CIPD 软件包”页面。
全局 GN 参数
//src/fonts/build/font_args.gni
进行声明
几个与字体相关的构建参数。其中最重要的两个选项是
font_catalog_paths
:所有选定项目的位置.font_catalog.json
文件。font_pkgs_paths
:所有.font_pkgs.json
的位置 文件。
*.font_pkgs.json
个文件
按照设计,这些文件可以通过 GN 的简单 JSON 解析器解析,
read_file
。
它们包含以下形式的条目列表:
{
"file_name": "AlphaSans-Regular.ttf",
"safe_name": "alphasans-regular-ttf",
"path_prefix": "alpha"
},
file_name
:字体文件资源文件的名称。这是规范的 的标识符,从而获取此对照表中的键。safe_name
:文件名的转换版本:转换为小写形式。 并将所有特殊字符替换为连字符。它可用于命名 Fuchsia 软件包。path_prefix
:素材资源父级目录的位置(相对于该目录)//prebuilt/third_party/fonts
。
在 //src/fonts/build/fonts.gni
中,
.font_pkgs.json
文件合并为单个 GN 作用域,
用作对照表
字体包
除了直接向字体提供程序的命名空间提供字体资源之外,
还可以选择创建单字体的 Fuchsia 软件包。这是
顾名思义,就是一个 package
,它只包含一种字体,
仅 resources
,不执行任何其他操作。
这可用于结合临时字体传递
fuchsia.pkg.FontResolver
。(待办事项:链接到更多文档。)
所有可能的字体包都已在
//src/fonts/packages/BUILD.gn
。
- 每个软件包名称均采用
font-package-<font-safe-name>
格式(请参阅safe_name
),例如font-package-roboto-regular-ttf
。 - 因此,软件包的 GN 目标为
//src/fonts/packages:<package-name>
,例如//src/fonts/packages:font-package-roboto-regular.ttf
。 - 每个包的网址都采用以下格式
fuchsia-pkg://fuchsia.com/<package-name>
,例如fuchsia-pkg://fuchsia.com/font-package-roboto-regular-ttf
。
local_font_bundle
在 fonts.gni 中定义
本地字体包是一组直接放置在
使用
config_data()
。
大多数本地字体包都是在
//src/fonts/collections/BUILD.gn
。
示例:
```gn
local_font_bundle("small-open-fonts-local") {
asset_names = [
"MaterialIcons-Regular.ttf",
"Roboto-Regular.ttf",
"Roboto-Light.ttf",
"Roboto-Medium.ttf",
"RobotoMono-Regular.ttf",
"RobotoSlab-Regular.ttf",
]
}
产品特定的字体配置
最后,每个 主推产品组 需要配置特定的字体资源, 元数据。
字体产品配置文件
.fontcfg.json
(或 .fontcfg.json5
)文件包含一组人工编写的
产品特定的字体设置。这里有
JSON 架构适用于
更好的编辑器体验
目前,此文件的主要用途是定义一种 链,即在与 客户端的字体请求不可用。
以下是一个后备广告链的基本示例,
//src/fonts/collections/open-fonts-collection.fontcfg.json5
:
fallback_chain: [
///
///
/// SANS SERIF LATIN
"Roboto-Regular.ttf",
"Roboto-Black.ttf",
"Roboto-BlackItalic.ttf",
"Roboto-Bold.ttf",
"Roboto-BoldItalic.ttf",
"Roboto-Italic.ttf",
"Roboto-Light.ttf",
"Roboto-LightItalic.ttf",
"Roboto-Medium.ttf",
"Roboto-MediumItalic.ttf",
"Roboto-Thin.ttf",
"Roboto-ThinItalic.ttf",
"RobotoCondensed-Regular.ttf",
"RobotoCondensed-Bold.ttf",
"RobotoCondensed-BoldItalic.ttf",
"RobotoCondensed-Italic.ttf",
"RobotoCondensed-Light.ttf",
"RobotoCondensed-LightItalic.ttf",
"DroidSans-Regular.ttf",
"DroidSans-Bold.ttf",
///
///
/// SANS-SERIF NON-LATIN
"NotoNaskhArabicUI-Regular.ttf",
"NotoSansArmenian-Regular.ttf",
"NotoSansEthiopic-Regular.ttf",
"NotoSansGeorgian-Regular.ttf",
"NotoSansHebrew-Regular.ttf",
"NotoSansThaiUI-Regular.ttf",
// All Indian scripts should come after Devanagari, due to shared danda characters.
"NotoSansDevanagariUI-Regular.ttf",
"NotoSansBengaliUI-Regular.ttf",
"NotoSansGujaratiUI-Regular.ttf",
"NotoSansKannada-Regular.ttf",
"NotoSansMalayalamUI-Regular.ttf",
"NotoSansTamilUI-Regular.ttf",
"NotoSansTelugu-Regular.ttf",
///
///
/// SANS SERIF CJK
{
full_name: "Noto Sans CJK SC",
},
{
full_name: "Noto Sans CJK TC",
},
{
full_name: "Noto Sans CJK HK",
},
{
full_name: "Noto Sans CJK KR",
},
{
full_name: "Noto Sans CJK JP",
},
{
full_name: "Noto Sans CJK SC Bold",
},
{
full_name: "Noto Sans CJK TC Bold",
},
{
full_name: "Noto Sans CJK HK Bold",
},
{
full_name: "Noto Sans CJK KR Bold",
},
{
full_name: "Noto Sans CJK JP Bold",
},
{
full_name: "Noto Sans CJK SC Black",
},
{
full_name: "Noto Sans CJK TC Black",
},
{
full_name: "Noto Sans CJK HK Black",
},
{
full_name: "Noto Sans CJK KR Black",
},
{
full_name: "Noto Sans CJK JP Black",
},
{
full_name: "Noto Sans CJK SC DemiLight",
},
{
full_name: "Noto Sans CJK TC DemiLight",
},
{
full_name: "Noto Sans CJK HK DemiLight",
},
{
full_name: "Noto Sans CJK KR DemiLight",
},
{
full_name: "Noto Sans CJK JP DemiLight",
},
{
full_name: "Noto Sans CJK SC Light",
},
{
full_name: "Noto Sans CJK TC Light",
},
{
full_name: "Noto Sans CJK HK Light",
},
{
full_name: "Noto Sans CJK KR Light",
},
{
full_name: "Noto Sans CJK JP Light",
},
{
full_name: "Noto Sans CJK SC Medium",
},
{
full_name: "Noto Sans CJK TC Medium",
},
{
full_name: "Noto Sans CJK HK Medium",
},
{
full_name: "Noto Sans CJK KR Medium",
},
{
full_name: "Noto Sans CJK JP Medium",
},
{
full_name: "Noto Sans CJK SC Thin",
},
{
full_name: "Noto Sans CJK TC Thin",
},
{
full_name: "Noto Sans CJK HK Thin",
},
{
full_name: "Noto Sans CJK KR Thin",
},
{
full_name: "Noto Sans CJK JP Thin",
},
///
///
/// SERIF LATIN
"RobotoSlab-Regular.ttf",
"RobotoSlab-Bold.ttf",
"RobotoSlab-Light.ttf",
"RobotoSlab-Thin.ttf",
"DroidSerif-Regular.ttf",
"DroidSerif-Bold.ttf",
"DroidSerif-BoldItalic.ttf",
"DroidSerif-Italic.ttf",
///
///
/// SERIF CJK
{
full_name: "Noto Serif CJK SC",
},
{
full_name: "Noto Serif CJK TC",
},
{
full_name: "Noto Serif CJK KR",
},
{
full_name: "Noto Serif CJK JP",
},
{
full_name: "Noto Serif CJK SC Bold",
},
{
full_name: "Noto Serif CJK TC Bold",
},
{
full_name: "Noto Serif CJK KR Bold",
},
{
full_name: "Noto Serif CJK JP Bold",
},
{
full_name: "Noto Serif CJK SC Black",
},
{
full_name: "Noto Serif CJK TC Black",
},
{
full_name: "Noto Serif CJK KR Black",
},
{
full_name: "Noto Serif CJK JP Black",
},
{
full_name: "Noto Serif CJK SC ExtraLight",
},
{
full_name: "Noto Serif CJK TC ExtraLight",
},
{
full_name: "Noto Serif CJK KR ExtraLight",
},
{
full_name: "Noto Serif CJK JP ExtraLight",
},
{
full_name: "Noto Serif CJK SC Light",
},
{
full_name: "Noto Serif CJK TC Light",
},
{
full_name: "Noto Serif CJK KR Light",
},
{
full_name: "Noto Serif CJK JP Light",
},
{
full_name: "Noto Serif CJK SC Medium",
},
{
full_name: "Noto Serif CJK TC Medium",
},
{
full_name: "Noto Serif CJK KR Medium",
},
{
full_name: "Noto Serif CJK JP Medium",
},
{
full_name: "Noto Serif CJK SC SemiBold",
},
{
full_name: "Noto Serif CJK TC SemiBold",
},
{
full_name: "Noto Serif CJK KR SemiBold",
},
{
full_name: "Noto Serif CJK JP SemiBold",
},
///
///
/// MONOSPACE LATIN
"RobotoMono-Bold.ttf",
"RobotoMono-BoldItalic.ttf",
"RobotoMono-Italic.ttf",
"RobotoMono-Light.ttf",
"RobotoMono-LightItalic.ttf",
"RobotoMono-Regular.ttf",
"RobotoMono-Medium.ttf",
"RobotoMono-MediumItalic.ttf",
"RobotoMono-Thin.ttf",
"RobotoMono-ThinItalic.ttf",
"DroidSansMono-Regular.ttf",
///
///
/// MONOSPACE CJK
{
full_name: "Noto Sans Mono CJK SC",
},
{
full_name: "Noto Sans Mono CJK TC",
},
{
full_name: "Noto Sans Mono CJK HK",
},
{
full_name: "Noto Sans Mono CJK KR",
},
{
full_name: "Noto Sans Mono CJK JP",
},
{
full_name: "Noto Sans Mono CJK SC Bold",
},
{
full_name: "Noto Sans Mono CJK TC Bold",
},
{
full_name: "Noto Sans Mono CJK HK Bold",
},
{
full_name: "Noto Sans Mono CJK KR Bold",
},
{
full_name: "Noto Sans Mono CJK JP Bold",
},
///
///
/// CURSIVE LATIN
"Quintessential-Regular.ttf",
///
///
/// EMOJI
"NotoColorEmoji.ttf",
///
///
/// SYMBOLS
"NotoSansSymbols-Regular.ttf",
"NotoSansSymbols2-Regular.ttf",
]
如果资源文件包含多个字型,则同一种字型 使用 JSON 对象(而不仅仅是文件名)进行引用:
fallback_chain: [
"SomeCompleteFont-Bold.ttf",
{ file_name: "NotoSansCJK-Regular.ttc", index: 1},
]
后备链是由手动定义的。请遵循以下准则:
- 为每种受支持的脚本添加至少一种字体。(支持的 脚本因产品而异)。
- 尽量至少覆盖
sans-serif
、serif
和monospace
字体 。 - 当覆盖范围重叠时,将更具体的素材资源放在 列表。例如,所有 Noto Sans 脚本专用字体都有字形 ,但应首先显示 Noto Sans Latin 变体。
- 当有重叠的覆盖区域时,将较小的字体文件放在 列表。这可以减少加载后备字体时的界面卡顿。
font_collection
在 fonts.gni 中定义
在完成任何所需的 local_font_bundle
和/或字体 packages
之后
它们会汇编到 font_collection
中。
输入
(如需查看完整文档,请参阅 fonts.gni。)
font_packages
:字体为package
的 GN 标签 位于目标商品的universe_package_labels
中。local_font_bundles
:目标的local_font_bundle
的 GN 标签 产品。这些内容将包含在字体提供程序的配置数据中。local_asset_names
:本地字体素材资源名称列表(用于创建临时local_font_bundle
)。product_config_path
:包含以下内容的 JSON 文件的路径 产品专用的字体配置,包括后备字体 。manifest_prefix
:生成的字体清单文件名称的前缀。 默认设置为"all"
。
内部原理
font_collection
会遍历所有字体资源和传递闭包,
其中包含的所有软件包它会收集其 GN
元数据
构建映射到本地文件中字体包的字体列表。
模板会将此信息传递给字体清单生成器 (GN 模板、 Rust 源代码)以及 字体目录和所有字体资产。
清单生成器从字体目录中选择预定义的元数据
。font_collection
它还读了
从每个包含的字体文件中提取
码位(字符集)。
所有这些数据都会汇聚到一个 .font_manifest.json
文件中,
使用 config_data
规则提供给字体提供程序服务。
输出
font_collection
会生成以下工件:
<manifest-prefix>.font_manifest.json
:这是元数据的集合 。它通过使用config_data
规则。font_packages.json
。此文件列出了包含的所有单字体 Fuchsia 软件包,并使用config_data
规则提供给pkg-resolver
。这个 用于确定通过fuchsia.pkg.FontResolver
公开的字体包。
由 font_collection
创建的 GN 目标包含config_data
上述两个 JSON 文件,以及本地字体资源的 config_data 目标。
如果商品仅使用本地字体,则添加本地字体就足够了。
font_collection
定位到产品的依赖项标签(通常
base_package_labels
)。
如果产品还使用字体 package
,则必须明确添加这些目标
更改为
base_package_labels
或
universe_package_labels
,
具体取决于软件包是否为临时资源