使用 Opentype.js 生成字体子集的实例代码详解


Posted in Javascript onMay 25, 2020

字体子集是将字体文件中部分多余的字符删除,来减小文件大小,从而在 Web 端使用或嵌入到其他应用或系统中,在网上可以找到不少这方面的工具。

Opentype.js是一套可以支持浏览器环境和 Node.js 环境的开源 OpenType 字体读写库,利用这个库可以很轻松实现浏览器环境和 Node.js 环境的字体子集功能。

在浏览器环境创建字体子集工具

首先创建一个简单的 HTML界面,包括一个选取字体文件按钮,一个输入框用于输入保留的字符,和一个保存下载按钮。

HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Font Subset</title>
</head>
<body>
 <div>
  <p><label for="text">Choose a font file:</label></p>
  <input type="file" id="file">
 </div>
 <div>
  <p><label for="text">Text:</label></p>
  <textarea id="text"></textarea>
 </div>
 <div>
  <input type="button" id="save" value="save">
 </div>
</body>
</html>

在 HTML 的</body>前引入 opentype.js,并加入 Javascript。

<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>
<script>
 var save = document.getElementById("save");
 save.onclick = function() {
  var file = document.getElementById("file");
  var text = document.getElementById("text");
  if (file.files.length === 0) {
   alert("Choose a font file.")
   return;
  }
  if (text.value === "") {
   alert("Type some text.")
   return;
  }

  var glyphsArray = text.value.split("");
  var glyphs = glyphsArray.filter(function(item) {
    return item !== " ";
   }).filter(function(item, index) {
    return glyphsArray.indexOf(item) === index;
   }).join("");

  var reader = new FileReader();
  reader.onload = function(error) {
   try {
    var font = opentype.parse(reader.result);
    var postScriptName = font.getEnglishName("postScriptName");
    var [familyName, styleName] = postScriptName.split("-");
    
    var notdefGlyph = font.glyphs.get(0);
    notdefGlyph.name = ".notdef";
    var subGlyphs = [notdefGlyph].concat(font.stringToGlyphs(glyphs));

    var subsetFont = new opentype.Font({
     familyName: familyName,
     styleName: styleName,
     unitsPerEm: font.unitsPerEm,
     ascender: font.ascender,
     descender: font.descender,
     designer: font.getEnglishName("designer"),
     designerURL: font.getEnglishName("designerURL"),
     manufacturer: font.getEnglishName("manufacturer"),
     manufacturerURL: font.getEnglishName("manufacturerURL"),
     license: font.getEnglishName("license"),
     licenseURL: font.getEnglishName("licenseURL"),
     version: font.getEnglishName("version"),
     description: font.getEnglishName("description"),
     copyright: "This is a subset font of " + postScriptName + ". " + font.getEnglishName("copyright"),
     trademark: font.getEnglishName("trademark"),
     glyphs: subGlyphs
    });
    subsetFont.download();
   } catch (error) {
    alert(error.message);
    throw(error);
   }
  };
  reader.onerror = function(error) {
   alert(error.message);
   throw(error);
  };
  reader.readAsArrayBuffer(file.files[0]);
 };
</script>

在 Node.js 环境创建字体子集工具

创建项目文件

在 Node.js 版的项目中,可以考虑通过配置文件来实现批量处理多个字体文件功能。

mkdir font_subset
cd font_subset
npm init

项目结构如下,把所有原始的字体保存在 src 目录下,子集化之后的字体保存在 dist 目录下,main.js 为主脚本。

font_subset
├── config.json
├── dist
├── main.js
├── node_modules
├── package-lock.json
├── package.json
└── src
 └── NotoSerifSC-Bold.otf

字体配置

修改 “config.json” 文件。fonts数组类型,可配置多个字体文件;texts字符串类型,输入需要保留的字符,字符可以重复,可包含空格,不可换行,英文双引号使用\"表示。

{
 "fonts": ["./src/NotoSerifSC-Bold.otf"],
 "texts": " 0123456789:"
}

生成字体

main.js 内容如下。

const config = require('./config.json');
const fonts = config.fonts;
const texts = config.texts;

const path = require('path');
const opentype = require('opentype.js');

const glyphs = [...new Set(texts.split(''))].join('');

fonts.forEach(item => {
 const font = opentype.loadSync(item);
 const postScriptName = font.getEnglishName('postScriptName');
 const dist = path.join(
  'dist',
  postScriptName.replace(/-/g, '_').toLowerCase() + '_subset.otf'
 );
 const [familyName, styleName] = postScriptName.split('-');
 
 const notdefGlyph = font.glyphs.get(0);
 notdefGlyph.name = '.notdef';
 const subGlyphs = [notdefGlyph].concat(font.stringToGlyphs(glyphs));
 
 const subsetFont = new opentype.Font({
  familyName: familyName,
  styleName: styleName,
  unitsPerEm: font.unitsPerEm,
  ascender: font.ascender,
  descender: font.descender,
  designer: font.getEnglishName('designer'),
  designerURL: font.getEnglishName('designerURL'),
  manufacturer: font.getEnglishName('manufacturer'),
  manufacturerURL: font.getEnglishName('manufacturerURL'),
  license: font.getEnglishName('license'),
  licenseURL: font.getEnglishName('licenseURL'),
  version: font.getEnglishName('version'),
  description: font.getEnglishName('description'),
  copyright: 'This is a subset font of ' + postScriptName + '. ' + font.getEnglishName('copyright'),
  trademark: font.getEnglishName('trademark'),
  glyphs: subGlyphs
 });

 subsetFont.download(dist);
});

打开终端项目所在目录,输入以下命令,字体保存到 “dist” 文件夹下。

node main.js

总结

到此这篇关于使用 Opentype.js 生成字体子集的实例代码详解的文章就介绍到这了,更多相关Opentype.js 字体子集内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于JQUERY的两个ListBox子项互相调整的实现代码
May 07 Javascript
给应用部分的js代码设定一个统一的入口
Jun 15 Javascript
PHP实现的各种中文编码转换类分享
Jan 23 Javascript
Linux下编译安装php libevent扩展实例
Feb 14 Javascript
jquery插件uploadify实现带进度条的文件批量上传
Dec 13 Javascript
jQuery基于ajax操作json数据简单示例
Jan 05 Javascript
浅谈JS封闭函数、闭包、内置对象
Jul 18 Javascript
vue页面使用阿里oss上传功能的实例(一)
Aug 09 Javascript
一次记住JavaScript的6个正则表达式方法
Feb 22 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(下)
Apr 18 Javascript
浅谈vue生命周期共有几个阶段?分别是什么?
Aug 07 Javascript
jQuery实现回到顶部效果
Oct 19 jQuery
Node.js API详解之 repl模块用法实例分析
May 25 #Javascript
微信小程序仿抖音视频之整屏上下切换功能的实现代码
May 24 #Javascript
如何使用vue slot创建一个模态框的实例代码
May 24 #Javascript
使用React代码动态生成栅格布局的方法
May 24 #Javascript
ES6对象操作实例详解
May 23 #Javascript
ES6函数和数组用法实例分析
May 23 #Javascript
ES6箭头函数和扩展实例分析
May 23 #Javascript
You might like
php中禁止单个IP与ip段访问的代码小结
2012/07/04 PHP
Php中使用Select 查询语句的实例
2014/02/19 PHP
PHP+jquery实时显示网站在线人数的方法
2015/01/04 PHP
js去除重复字符串两种实现方法
2013/01/09 Javascript
jquery在Chrome下获取图片的长宽问题解决
2013/03/20 Javascript
使用javascript实现页面定时跳转总结篇
2013/09/21 Javascript
javascript中数组的多种定义方法和常用函数简介
2014/05/09 Javascript
使用js dom和jquery分别实现简单增删改
2014/09/11 Javascript
JS实现自动固定顶部的悬浮菜单栏效果
2015/09/16 Javascript
浅谈json取值(对象和数组)
2016/06/24 Javascript
通过BootStrap实现轮播图的实际应用
2016/09/26 Javascript
Javascript实现汉字和拼音互转的终极方案
2016/10/19 Javascript
AngularJS中$http使用的简单介绍
2017/03/17 Javascript
Angular排序实例详解
2017/06/28 Javascript
JS简单数组排序操作示例【sort方法】
2019/05/17 Javascript
小程序如何自主实现拦截器的示例代码
2019/11/04 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
ant design的table组件实现全选功能以及自定义分页
2020/11/17 Javascript
vue-cli4.0多环境配置变量与模式详解
2020/12/30 Vue.js
[02:47]DOTA2亚洲邀请赛 HR战队出场宣传片
2015/02/07 DOTA
[44:40]KG vs LGD 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python中List.count()方法的使用教程
2015/05/20 Python
详解js文件通过python访问数据库方法
2019/03/03 Python
django 使用 PIL 压缩图片的例子
2019/08/16 Python
Tensorflow 自定义loss的情况下初始化部分变量方式
2020/01/06 Python
django queryset 去重 .distinct()说明
2020/05/19 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
css3 图片圆形显示 如何CSS将正方形图片显示为圆形图片布局
2014/10/10 HTML / CSS
HTML5的语法变化介绍
2013/08/13 HTML / CSS
Marc O’Polo俄罗斯官方在线商店:德国高端时尚品牌
2019/12/26 全球购物
搬家公司的创业计划书
2014/01/01 职场文书
社区端午节活动方案
2014/01/28 职场文书
会计专业毕业生求职信
2014/07/04 职场文书
上班时间打瞌睡检讨书
2014/09/26 职场文书
领导干部群众路线对照检查材料
2014/11/05 职场文书
新手,如何业余时间安排好写作、提高写作能力?
2019/10/21 职场文书