PPT 字体嵌入

首发于https://zhuanlan.zhihu.com/p/90706046
上一篇介绍了 PPT 的文档结构,但是当用户下载下来会发现很多字体不能正常显示或者替换成了默认字体,对于最终呈现的效果就会大打折扣,这是因为用户电脑上没有安装对应的字体,所以最好能在下载 PPT 的同时将字体也嵌入进去。

目前 Microsoft PowerPoint 2019 之前的版本只支持 windows 版本的字体嵌入,2019 之后,Mac 也能嵌入,所以并没有进行版本判断,无法正常嵌入的会在打开弹出提示框。

WPS 都支持嵌入字体,但有些字体无法识别,大多是因为大小写的问题,比如之前嵌入“思源黑体”,字体名为英文,Microsoft 可以识别,WPS 不能识别,换成中文,WPS 能识别,Microsoft 有不能。很气。

第一步:下载字体。

因为只能嵌入 EOT 格式的字体,所以要考虑是否需要进行字体格式的转换。

EOT 是微软设计用来在 web 使用的,对字体进行压缩和裁剪使得文件体积更小,同时避免了受版权保护的字体被随意复制。

由于网页在显示模板的时候会下载一次相关 WOFF 格式的相关字体,所以为了节省下载时间,就直接将 WOFF 转成 EOT。

WOFF(Web Open Font Format) 由 Mozilla 联合其他几大组织共同开发,使用了 OpenType 和 TrueType 字体的存储结构和压缩算法,所以加载比较快。

好像不能直接将 WOFF 转成 EOT,所以绕了一步,先将 WOFF 转成 TTF,再进一步转成 EOT。可以直接调用相关库实现转换。

fetch(font.woff).then(res => {
    return res.arrayBuffer();
})
.then(buffer => {
    const eotBuffer = woff2eot(buffer);
    const unit8Array = new Unit8Array(eotBuffer);
    const blob = new Blob([unit8Array], {
        type: 'font/opentype'
    });
    
    return blob;
})
第二步:将字体写入 PPT 中

从 PPT 的文件结构可知,文字是专门放在一个fonts文件夹中,以 fntdata 后缀名保存

zip.file(`ppt/fonts/font1.fntdata`, blob);
第三步:引用字体

在 ppt/presentation.xml 中声明嵌入字体

xml += `
<p:embeddedFontLst>
    <p:embeddedFont>
        <p:font typeface="fontFamily" panose="02010601030101010101" pitchFamily="2" charset="-122" />
        <p:regular r:id="rId1" />
    </p:embeddedFont>
</p:embeddedFontLst>`

在 ppt/_rels/presentation.xml.rels 中声明关系

xml += `
    <Relationship Id="rId1" Target="fonts/font1.fntdata" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/font">`

最重要!一定要在 [Content_Types.xml] 列出所有用到的文件格式

xml += `<Default Extension="fntdata" ContentType="application/x-fontdata" />`

到这里就成功将字体嵌入到了 PPT 中,只要在写入文字的时候直接引用字体名就可以了

点赞