-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
168 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
--- | ||
layout: post | ||
categories: original | ||
title: "中文字库嵌入Web时的分割与裁剪" | ||
author: 立泉 | ||
mention: 霞鹜文楷 CnFontSplit | ||
date: 2024-04-24 +0800 | ||
description: 可能注意到这个博客站点的字体有点奇怪,并不是常见的无衬线黑体,而是一种接近宋体但又像手写楷书的字体。其实是一款兼顾排版和中文美感的霞鹜文楷开源字体,但要将它嵌入博客中,需要解决一些应用中文字库的典型问题。 | ||
cover: | ||
tags: Code Blog Font 霞鹜文楷 CnFontSplit TTF WOFF2 | ||
--- | ||
|
||
可能注意到这个博客站点的字体有点奇怪,并不是常见的无衬线`黑体`,而是一种接近`宋体`但又像手写`楷书`的字体。其实是一款兼顾排版和中文美感的[霞鹜文楷](https://github.com/lxgw/LxgwWenKai){: target="_blank" }开源字体,但要将它嵌入博客中,需要解决一些应用中文字库的典型问题。 | ||
|
||
## 分割 | ||
|
||
其中最大的问题是中文字库的庞大体积,英文字库无非是字母和符号,如[JetBrains Mono](https://www.jetbrains.com/lp/mono/){: target="_blank" }的`WOFF2`文件体积仅为92KB,可以非常方便的在`Web`中无感加载。但中文字库收录的汉字数以千计,而且笔画复杂,以8000字的`霞鹜文楷GB`为例,`Regular`字重的`TTF`文件为18.3MB,如果加上常用的`Bold`字重,体积就已经超过36MB,这么大的单体资源对网页加载是不可接受的。 | ||
|
||
所以中文字库必须分割,按常用字顺序以百KB为单位分割为多个`WOFF2`文件,再由页面按需加载。 | ||
|
||
```css | ||
/* CSS支持为字体文件指定其包含的字符编码范围 */ | ||
@font-face { | ||
font-family: "LXGW WenKai GB"; | ||
src: url("https://hosturl.com/01.woff2") format("woff2"); | ||
font-style: normal; | ||
font-weight: 400; | ||
font-display: swap; | ||
/* 字符编码范围 */ | ||
unicode-range: U+305e3, U+305f6, U+3067d ...; | ||
} | ||
@font-face { | ||
font-family: "LXGW WenKai GB"; | ||
src: url("https://hosturl.com/02.woff2") format("woff2"); | ||
font-style: normal; | ||
font-weight: 400; | ||
font-display: swap; | ||
/* 字符编码范围 */ | ||
unicode-range: U+2ce29-2ce2a, U+2ce31, U+2ce7c ...; | ||
} | ||
``` | ||
|
||
其实用过[Google Fonts](https://fonts.google.com/specimen/Ma+Shan+Zheng?subset=chinese-simplified){: target="_blank" }就会知道它对中文字库也是这么处理的,所以现在问题就变成了如何分割字库。 | ||
|
||
网上冲浪发现[中文网字计划](https://chinese-font.netlify.app){: target="_blank" }的[cn-font-split](https://github.com/KonghaYao/cn-font-split){: target="_blank" }项目很不错,一个简单命令就可以把`TTF`文件分割为数百个60KB的`WOFF2`文件并生成`CSS`代码,而且也支持指定要裁剪的字符编码范围,只生成包含所需字符的字库文件。 | ||
|
||
```sh | ||
# 执行分割,指定输入TTF文件和输出目录 | ||
cn-font-split -i=/Users/apqx/Downloads/Input.ttf -o=/Users/apqx/Downloads/Output | ||
``` | ||
|
||
配合浏览器缓存策略,每个页面加载的字体资源至多也不过几百KB,已属正常范围。这个问题解决后,选择字体就再不用为此纠结,放心使用喜欢的中文字库。 | ||
|
||
## 裁剪 | ||
|
||
我的博文中会经常嵌入代码块,之前一直使用等宽的`JetBrains Mono`字体,但应用`霞鹜文楷`后发现英文`黑体`和中文`楷体`混在一起总感觉怪怪的...所幸`霞鹜文楷`也提供等宽版本,但却是包含完整8000汉字的`TTF`字库,这些汉字与已有字库重叠,而我所需只是其中的英文和符号。 | ||
|
||
借助`cn-font-split`的裁剪功能,可以从`TTF`中提取出指定范围的字符,生成独立的`WOFF2`文件。 | ||
|
||
```ts | ||
import {fontSplit} from 'cn-font-split'; | ||
|
||
await fontSplit({ | ||
// 要分割的字体文件 | ||
FontPath: `/Users/apqx/Downloads/Input.ttf`, | ||
// 输出目录 | ||
destFold: `/Users/apqx/Downloads/Output`, | ||
// 输出格式 woff2 | ||
targetType: 'woff2', | ||
// 分包大小 70KB | ||
chunkSize: 70 * 1024, | ||
// 关闭自动分包,只打包 subsets 中指定的字符 | ||
autoChunk: false, | ||
// 指定要打包的字符 | ||
subsets: [ | ||
// 数字、字母、符号 | ||
'1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~!@#$%^&*()-_=+\\|{}[];:\'"<>,.?/ ' | ||
.split('') | ||
.filter(Boolean) | ||
.map((i) => i.charCodeAt(0)) | ||
], | ||
testHTML: true, | ||
threads: {}, | ||
previewImage: {}, | ||
}); | ||
``` | ||
|
||
同理我的博客中还存在一些使用手写字体的中文片段,没必要为它们引入整个字库,也是裁剪处理。 |