使用 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 相关文章推荐
javascript Zifa FormValid 0.1表单验证 代码打包下载
Jun 08 Javascript
基于JavaScript实现 获取鼠标点击位置坐标的方法
Apr 12 Javascript
实现动画效果核心方式的js代码
Sep 27 Javascript
JavaScipt选取文档元素的方法(推荐)
Aug 05 Javascript
JavaScript实现动态添加Form表单元素的方法示例
Aug 14 Javascript
详解react-native WebView 返回处理(非回调方法可解决)
Feb 27 Javascript
json对象及数组键值的深度大小写转换问题详解
Mar 30 Javascript
jQuery实现动态生成年月日级联下拉列表示例
May 11 jQuery
JS把字符串格式的时间转换成几秒前、几分钟前、几小时前、几天前等格式
Jul 10 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
Jul 26 Javascript
layui 富文本图片上传接口与普通按钮 文件上传接口的例子
Sep 23 Javascript
JS操作JSON常用方法(10w阅读)
Dec 06 Javascript
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
《五等分的花嫁》漫画完结!2020年10月第2期TV动画制作组换血!
2020/03/06 日漫
索尼SONY ICF-SW7600GR电路分析与改良
2021/03/02 无线电
php中simplexml_load_file函数用法实例
2014/11/12 PHP
php魔术函数__call()用法实例分析
2015/02/13 PHP
php中header跳转使用include包含解决参数丢失问题
2015/05/08 PHP
PHP下 Mongodb 连接远程数据库的实例代码
2017/08/30 PHP
web 页面分页打印的实现
2009/06/22 Javascript
js预载入和JavaScript Image()对象使用介绍
2011/08/28 Javascript
MyEclipse取消验证Js的两种方法
2013/11/14 Javascript
Javascript中的delete操作符详细介绍
2014/06/06 Javascript
用原生js做个简单的滑动效果的回到顶部
2014/10/15 Javascript
Vue.js中数组变动的检测详解
2016/10/12 Javascript
移动端脚本框架Hammer.js
2016/12/15 Javascript
vue.js实现备忘录功能的方法
2017/07/10 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
2017/09/18 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
2017/12/15 Javascript
JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能
2018/02/06 Javascript
使用Vue.js和Element-UI做一个简单登录页面的实例
2018/02/23 Javascript
关于Vue在ie10下空白页的debug小结
2018/05/02 Javascript
[56:57]LGD vs VP 2019DOTA2国际邀请赛淘汰赛 胜者组赛BO3 第一场 8.20.mp4
2019/08/22 DOTA
Python三元运算实现方法
2015/01/12 Python
python编程开发之日期操作实例分析
2015/11/13 Python
基于python实现的抓取腾讯视频所有电影的爬虫
2016/04/22 Python
matplotlib作图添加表格实例代码
2018/01/23 Python
python web基础之加载静态文件实例
2018/03/20 Python
Selenium自动化测试工具使用方法汇总
2020/06/12 Python
如何利用python之wxpy模块玩转微信
2020/08/17 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
2015/01/27 面试题
师德承诺书
2015/01/20 职场文书
5.12护士节活动总结
2015/02/10 职场文书
2015初中政治教学工作总结
2015/07/21 职场文书
奖学金申请个人主要事迹材料
2015/11/04 职场文书
2019年公司快递收发管理制度模板
2019/11/20 职场文书
详解Python牛顿插值法
2021/05/11 Python
Python实现8种常用抽样方法
2021/06/27 Python