# 字体加载与替代

接入应用字体或外部字体库，区分逻辑字体、实际渲染字体和导出资源。

工具栏中有字体名称，不代表浏览器已经有这份字体。字体缺失会改变字宽、换行和分页。应用需要明确选择字体来源，并区分正文保存的字体意图与当前设备能够绘制的字体。

## 方案一：应用已经加载的字体

适合统一品牌字体或离线部署。先在应用样式中声明实际可访问的 `@font-face`，再等待加载完成，使用 `mountedFamilies` 告诉 Classic 精确 CSS family。下面的 `Application Serif` 是示例名称，必须换成你实际声明的 family；它不是内置字体。

### classic/fonts/application.ts

```ts
import type { ClassicEditorWebFontOptions } from "@quirekit/classic-editor";

/**
 * Waits for an application-owned @font-face before creating Classic.
 * @param owner - Browser document whose stylesheet already declares the face.
 * @returns Explicit mounted-family configuration without an external catalog.
 */
export async function prepareApplicationFonts(owner: Document): Promise<ClassicEditorWebFontOptions> {
  const faces = await owner.fonts.load('16px "Application Serif"');
  if (faces.length === 0) throw new Error("Application Serif has no registered @font-face.");
  return { families: [], catalogs: [], mountedFamilies: [{ family: "Application Serif", displayName: "应用正文字体" }] };
}

```

```ts [在创建 Classic 前调用]
const webFonts = await prepareApplicationFonts(host.ownerDocument)
const instance = createClassicEditor({ element: host, preset, document, webFonts })
```

这里的 `host`、`preset`、`document` 沿用[快速接入](/classic/quick-start)的宿主、Word 预设和正文。只声明 mountedFamilies 不会替你加载 CSS；`webFonts: false` 也不会加载缺失字体或自动消除字体差异。

`displayName` 是显示文案，不能代替精确 `family`。配置字体来源不等于修改正文的字体选择；改变当前选区字体使用已安装的 `setFontFamily(family)` 命令，整份文档的字体主题则属于规范文档配置。

## 方案二：按需安装外部字体

`webFonts` 可提供 `families`、`catalogs` 与可搜索的 `sources`。`families` 公开可供安装的元数据；catalog 根据精确 family 返回完整 manifest；source 提供搜索、分页和 manifest 解析。manifest 包含版本、字面、资产和许可告知，不能只给一个显示名称或 CSS URL 冒充完整合同。

挂载后读取 `instance.fontLibrary`。先 `subscribe(listener)` 观察加载状态，再根据明确用户操作调用 `install(family)`；它返回浏览器注册与布局失效完成的 Promise。`previewFamily()` 允许预览而不把记录加入已导入字体，`importFamily()` 管理显式导入。页面退出或更换 library 时解除订阅，异步返回后也要复核当前实例。

默认字体库可以被配置替换；自己提供的 `families` / `catalogs` 是完整配置，不应假定默认来源仍然自动存在。实际预算由 `maxAssetBytes`、`maxConcurrentAssets`、`fetch` 和 `cache` 控制。

## 读懂字体状态

`instance.documentFontStatus` 描述文档正文字体：

| 字段或状态 | 含义 |
| --- | --- |
| `requestedFamily` | 正文保留的逻辑字体 |
| `renderedFamily` | 当前选择的具体渲染字体，不代表每个字符都来自它 |
| `pending` | 正在解析或加载 |
| `available` | 请求字体可用 |
| `substituted` | 使用明确替代候选，逻辑字体仍保留 |
| `unresolved` | 尚无可确认的具体字体 |

不要在替代发生时悄悄重写正文的字体名称。不同脚本和单个缺字还可能走 glyph fallback；一个正文字体状态不能证明全文每个字形都相同。

## 布局与导出的验证

内置字体安装流程会刷新字体度量与布局；应用自行在挂载后加载 CSS 字体时，需要在就绪后调用当前 `instance.editor?.view.refreshFontMetrics()`。保持当前编辑器有效，避免对已经卸载的 Core 刷新。

字体缓存、浏览器注册与可导出的字体字节是不同资源。`fontLibrary.getInstallations()` 可读取已完成的安装结果；仅本地可用的记录不含可嵌入字节，不能因此声称导出必然携带该字体。导出还需按所用服务确认资源与授权范围。

验证首次打开、缓存命中、离线、下载失败和中英混排。等待字体就绪后检查换行、页数与选区位置；不要只确认下拉列表里出现了名称。配置类型在[实例参考](/classic/reference)查询。
