opentype.js使用 JavaScript 读写 OpenType 字体
opentype.js 是 TrueType 和 OpenType 字体的 JavaScript 解析器和编写器。
它使您可以从浏览器或 Node.js 访问文本的字母形式。
特征
- 从一段文本中创建一条贝塞尔曲线路径。
- 支持复合字形(重音字母)。
- 支持 WOFF、OTF、TTF(均具有 TrueType
glyf
和 PostScriptcff
轮廓) - 支持字距调整(使用 GPOS 或 kern 表)。
- 支持连字。
- 支持 TrueType 字体提示。
- 支持阿拉伯文本渲染(参见问题 #364 和 PR #359 #361)
- 可以选择低内存模式(参见#329)
- 在浏览器和 Node.js 中运行。
安装
通过 CDN
在下一个示例中选择以下来源之一:
- https://opentype.js.org/dist/opentype.js
- https://cdn.jsdelivr.net/npm/opentype.js
- https://unpkg.com/opentype.js
<!-- using global declaration --> <script src="https://your.favorite.cdn/opentype.js"></script> <script>opentype.parse(...)</script> <!-- using module declaration (need full path) --> <script type=module> import { parse } from "https://unpkg.com/opentype.js/dist/opentype.module.js"; parse(...); </script>
通过npm包管理器
npm install opentype.js
const opentype = require('opentype.js'); import opentype from 'opentype.js' import { load } from 'opentype.js'
用法
加载 WOFF/OTF/TTF 字体
// case 1: from an URL const buffer = fetch('/fonts/my.woff').then(res => res.arrayBuffer()); // case 2: from filesystem (node) const buffer = require('fs').promises.readFile('./my.woff'); // case 3: from an <input type=file id=myfile> const buffer = document.getElementById('myfile').files[0].arrayBuffer(); // if running in async context: const font = opentype.parse(await buffer); console.log(font); // if not running in async context: buffer.then(data => { const font = opentype.parse(data); console.log(font); })
加载 WOFF2 字体
WOFF2 Brotli 压缩性能比 WOFF 前身好 29% 。但是这种压缩也更复杂,并且会导致 opentype.js 库更重(~120KB => ~1400KB)。
要解决这个问题:预先解压缩字体(例如使用fontello/wawoff2)。
// promise-based utility to load libraries using the good old <script> tag const loadScript = (src) => new Promise((onload) => document.documentElement.append( Object.assign(document.createElement('script'), {src, onload}) )); const buffer = //...same as previous example... // load wawoff2 if needed and wait (!) for it to be ready if (!window.Module) { const path = 'https://unpkg.com/wawoff2@2.0.1/build/decompress_binding.js' const init = new Promise((done) => window.Module = { onRuntimeInitialized: done}); await loadScript(path).then(() => init); } // decompress before parsing const font = opentype.parse(Module.decompress(await buffer));
加载字体(1.x 样式)
此示例依赖于已弃用的.load()
方法
// case 1: from an URL const font = opentype.load('./fonts/my.woff', {}, {isUrl: true}); // case 2: from filesystem const font = opentype.load('./fonts/my.woff', {}, {isUrl: false}); // ... play with `font` ... console.log(font.supported);
写字体
一旦你有了一个Font
对象(通过使用opentype.load
或从头开始创建一个新对象),你就可以将它作为二进制文件写回。
在浏览器中,您可以使用Font.download()
指示浏览器下载二进制 .OTF 文件。该名称基于字体名称。
// Create the bézier paths for each of the glyphs. // Note that the .notdef glyph is required. const notdefGlyph = new opentype.Glyph({ name: '.notdef', advanceWidth: 650, path: new opentype.Path() }); const aPath = new opentype.Path(); aPath.moveTo(100, 0); aPath.lineTo(100, 700); // more drawing instructions... const aGlyph = new opentype.Glyph({ name: 'A', unicode: 65, advanceWidth: 650, path: aPath }); const glyphs = [notdefGlyph, aGlyph]; const font = new opentype.Font({ familyName: 'OpenTypeSans', styleName: 'Medium', unitsPerEm: 1000, ascender: 800, descender: -200, glyphs: glyphs}); font.download();
如果要检查字体,请使用font.toTables()
生成一个显示直接映射到二进制值的数据结构的对象。如果你想得到一个ArrayBuffer
,使用font.toArrayBuffer()
。
字体对象
Font 表示加载的 OpenType 字体文件。它包含一组字形和方法,用于在绘图上下文中绘制文本,或获取表示文本的路径。
-
glyphs
:字形对象的索引列表。 -
unitsPerEm
: 字体中的 X/Y 坐标存储为整数。该值决定了网格的大小。常用值为 2048 和 4096。 -
ascender
:距最高上升者基线的距离。以字体为单位,而不是像素。 -
descender
:距最低下降基线的距离。以字体为单位,而不是像素。
Font.getPath(text, x, y, fontSize, options)
创建表示给定文本的路径。
-
x
: 文本开头的水平位置。(默认值:0) -
y
:文本基线的垂直位置。(默认值:0) -
fontSize
: 以像素为单位的文本大小(默认值:72)。
选项是一个可选对象,包含:
-
kerning
: 如果为 true 则考虑字距调整信息(默认值:true) -
features
:一个以OpenType 功能标签作为键的对象,以及一个用于启用每个功能的布尔值。目前仅支持连字功能“liga”和“rlig”(默认值:true)。 -
hinting
: 如果 true 使用 TrueType 字体提示(如果可用)(默认值:false)。
注意:还有Font.getPaths
相同的参数返回路径列表。
Font.draw(ctx, text, x, y, fontSize, options)
创建表示给定文本的路径。
-
ctx
:二维绘图上下文,如 Canvas。 -
x
: 文本开头的水平位置。(默认值:0) -
y
:文本基线的垂直位置。(默认值:0) -
fontSize
: 以像素为单位的文本大小(默认值:72)。
选项是一个可选对象,包含:
-
kerning
: 如果为 true 则考虑字距调整信息(默认值:true) -
features
:一个以OpenType 功能标签作为键的对象,以及一个用于启用每个功能的布尔值。目前仅支持连字功能“liga”和“rlig”(默认值:true)。 -
hinting
: 如果 true 使用 TrueType 字体提示(如果可用)(默认值:false)。
Font.drawPoints(ctx, text, x, y, fontSize, options)
绘制文本中所有字形的点。曲线上的点将以蓝色绘制,曲线外的点将以红色绘制。参数与Font.draw
.
Font.drawMetrics(ctx, text, x, y, fontSize, options)
画线指示文本中所有字形的重要字体尺寸。黑线表示坐标系的原点(点 0,0)。蓝线表示字形边界框。绿线表示字形的前进宽度。
Font.stringToGlyphs(string)
将字符串转换为字形对象列表。请注意,由于可能的替换(例如连字),字符串和字形列表之间没有严格的一对一对应关系。返回的字形列表可以大于或小于给定字符串的长度。
Font.charToGlyph(char)
将字符转换为Glyph
对象。如果找不到字形,则返回 null。请注意,此函数假定给定字符和字形之间存在一对一映射;对于复杂的脚本,情况可能并非如此。
Font.getKerningValue(leftGlyph, rightGlyph)
检索左字形(或其索引)和右字形(或其索引)之间的字距对的值。如果未找到字距对,则返回 0。在计算字形之间的间距时,字距值会添加到提前宽度中。
Font.getAdvanceWidth(text, fontSize, options)
返回文本的前进宽度。
这与 Path.getBoundingBox() 有所不同,例如,带后缀的空格会增加 advancewidth 但不会增加边界框,或者像书法 'f' 这样的悬垂字母可能具有比其 advance 宽度大得多的边界框。
这对应于 canvas2dContext.measureText(text).width
-
fontSize
: 以像素为单位的文本大小(默认值:72)。 -
options
: 请参见 Font.getPath
字形对象
一个字形是一个单独的标记,通常对应于一个字符。一些字形,例如连字,是许多字符的组合。字形是字体的基本构建块。
-
font
: 对象的引用Font
。 -
name
:字形名称(例如“Aring”、“five”) -
unicode
: 这个字形的主要 unicode 值(可以是undefined
)。 -
unicodes
: 此字形的 unicode 值列表(大多数情况下为 1,也可以为空)。 -
index
: 字形的索引号。 -
advanceWidth
: 绘制此字形时笔前进的宽度。 -
leftSideBearing
:前一个字符到原点的水平距离(0, 0
);负值表示悬垂 -
xMin
,yMin
,xMax
,yMax
:字形的边界框。 -
path
:字形的原始、未缩放路径。
Glyph.getPath(x, y, fontSize)
获取一个缩放的字形 Path 对象,我们可以在绘图上下文中绘制。
-
x
: 字形的水平位置。(默认值:0) -
y
:字形基线的垂直位置。(默认值:0) -
fontSize
:以像素为单位的字体大小(默认值:72)。
Glyph.getBoundingBox()
计算给定字形的未缩放路径的最小边界框。返回opentype.BoundingBox
包含 x1/y1/x2/y2 的对象。如果字形没有点(例如空格字符),则所有坐标都将为零。
Glyph.draw(ctx, x, y, fontSize)
在给定的上下文中绘制字形。
-
ctx
:绘图上下文。 -
x
: 字形的水平位置。(默认值:0) -
y
:字形基线的垂直位置。(默认值:0) -
fontSize
:字体大小,以像素为单位(默认值:72)。
Glyph.drawPoints(ctx, x, y, fontSize)
在给定的上下文中绘制字形的点。曲线上的点将以蓝色绘制,曲线外的点将以红色绘制。参数与Glyph.draw
.
Glyph.drawMetrics(ctx, x, y, fontSize)
画线指示文本中所有字形的重要字体尺寸。黑线表示坐标系的原点(点 0,0)。蓝线表示字形边界框。绿线表示字形的前进宽度。参数与Glyph.draw
.
Glyph.toPathData(options)
, Glyph.toDOMElement(options)
, Glyph.toSVG(options)
, Glyph.fromSVG(pathData, options)
,
这些目前只是 Path 对象上对应对象的包装函数(请参阅那里的文档),但将来可能会扩展以传递 Glyph 数据以进行自动计算。
路径对象
一旦有了通过Font.getPath
或 的路径Glyph.getPath
,就可以使用它。
-
commands
: 路径命令。每个命令都是一个包含类型和坐标的字典。有关示例,请参见下文。 -
fill
: 的填充颜色Path
。Color 是一个代表CSS color 的字符串。(默认值:'黑色') -
stroke
: 的描边颜色Path
。Color 是一个代表CSS color 的字符串。(默认::null
路径不会被描边) -
strokeWidth
: 的线条粗细Path
。(默认值:1,但由于为stroke
null,因此不会绘制笔划)
Path.draw(ctx)
在给定的 2D 上下文中绘制路径。这使用对象的fill
,stroke
和strokeWidth
属性Path
。
-
ctx
:绘图上下文。
Path.getBoundingBox()
计算给定路径的最小边界框。返回opentype.BoundingBox
包含 x1/y1/x2/y2 的对象。如果路径为空(例如空格字符),则所有坐标都将为零。
Path.toPathData(options)
将 Path 转换为一串路径数据指令。请参阅https://www.w3.org/TR/SVG/paths.html#PathData
-
options
:-
decimalPlaces
:浮点值的小数位数。(默认值:2) -
optimize
:对路径数据应用一些优化,例如删除不必要/重复的命令(true/false,默认值:true) -
flipY
:是否翻转路径数据的Y轴,因为SVG和字体路径使用倒置的Y轴。(true:从边界框计算,false:禁用;默认值:true) -
flipYBase
:基础翻转计算的基础值。您可能希望根据字体的升序值和降序值来计算它。(默认:从路径数据的边界框自动计算)
-
Path.toSVG(options)
将路径转换为 SVG <path> 元素,作为字符串。
-
options
: 见 Path.toPathData
Path.fromSVG(pathData, options)
从 SVG 路径数据中检索路径。覆盖现有路径的路径数据
const path = new Path(); path.fromSVG('M0 0');
或直接创建新路径:
const path = Path.fromSVG('M0 0');
-
pathData
:一串 SVG 路径命令,或者(仅在浏览器上下文中)一个SVGPathElement
-
options
:-
decimalPlaces
,optimize
,flipY
,flipYBase
: 见 Path.toPathData -
scale
:应用于所有命令坐标的缩放值(默认值:1) -
x
/y
:应用于 x 或 y 轴上所有命令坐标的偏移量(默认值:0)
-
路径命令
- 移动到:移动到新位置。这创建了一个新的轮廓。例子:
{type: 'M', x: 100, y: 200}
- Line To:从前一个位置到给定坐标画一条线。例子:
{type: 'L', x: 100, y: 200}
- Curve To : 绘制一条从当前位置到给定坐标的贝塞尔曲线。例子:
{type: 'C', x1: 0, y1: 50, x2: 100, y2: 200, x: 100, y: 200}
- Quad To:绘制从当前位置到给定坐标的二次贝塞尔曲线。例子:
{type: 'Q', x1: 0, y1: 50, x: 100, y: 200}
- 关闭:关闭路径。如果描边,这将从轮廓的第一个点到最后一个点画一条线。例子:
{type: 'Z'}