使用 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获得页面元素的坐标值实现思路及代码
Apr 15 Javascript
jQuery文字横向滚动效果的实现代码
May 31 Javascript
jQuery简单动画变换效果实例分析
Jul 04 Javascript
深入浅出讲解ES6的解构
Aug 03 Javascript
JS实现页面跳转参数不丢失的方法
Nov 28 Javascript
JavaScript实现移动端轮播效果
Jun 06 Javascript
基于Vue渲染与插件的加载顺序的问题详解
Mar 05 Javascript
实例介绍JavaScript中多种组合继承
Jan 20 Javascript
Vue 事件处理操作实例详解
Mar 05 Javascript
vue+element 实现商城主题开发的示例代码
Mar 26 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
Aug 31 Javascript
微信小程序中使用vant框架的具体步骤
Feb 18 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
从零开始学YII2框架(六)高级应用程序模板
2014/08/20 PHP
php调整服务器时间的方法
2015/04/03 PHP
详解WordPress中过滤链接与过滤SQL语句的方法
2015/12/18 PHP
php+mysql查询实现无限下级分类树输出示例
2016/10/03 PHP
PHP排序算法之快速排序(Quick Sort)及其优化算法详解
2018/04/21 PHP
ThinkPHP5&amp;5.1框架关联模型分页操作示例
2019/08/03 PHP
分享8个Laravel模型时间戳使用技巧小结
2020/02/12 PHP
javascript nextSibling 与 getNextElement(node) 使用介绍
2011/10/13 Javascript
js事件冒泡实例分享(已测试)
2013/04/23 Javascript
Javascript实现真实字符串剩余字数提示的实例代码
2013/10/22 Javascript
js加入收藏以及使用Jquery更改透明度
2014/01/26 Javascript
JavaScript定时器和优化的取消定时器方法
2015/07/03 Javascript
浅析四种常见的Javascript声明循环变量的书写方式
2015/10/14 Javascript
Vue.js 父子组件通讯开发实例
2016/09/06 Javascript
Angular 常用指令实例总结整理
2016/12/13 Javascript
Bootstrap select多选下拉框实现代码
2016/12/23 Javascript
jquery 正整数数字校验正则表达式
2017/01/10 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
2017/11/17 Javascript
微信小程序 JS动态修改样式的实现方法
2018/12/16 Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
2019/04/17 Javascript
vue 验证码界面实现点击后标灰并设置div按钮不可点击状态
2019/10/28 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
python三元运算符实现方法
2013/12/17 Python
tensorflow训练中出现nan问题的解决
2018/02/10 Python
python读取有密码的zip压缩文件实例
2019/02/08 Python
Pytorch中的variable, tensor与numpy相互转化的方法
2019/10/10 Python
python系统指定文件的查找只输出目录下所有文件及文件夹
2020/01/19 Python
Python urllib.request对象案例解析
2020/05/11 Python
python 实现Harris角点检测算法
2020/12/11 Python
Pycharm 设置默认解释器路径和编码格式的操作
2021/02/05 Python
Can a struct inherit from another struct? (结构体能继承结构体吗)
2016/09/25 面试题
教学大赛获奖感言
2014/01/15 职场文书
公司会计主管岗位责任制
2014/03/01 职场文书
2015年度培训工作总结范文
2015/04/02 职场文书
幼儿园园长六一致辞
2015/07/31 职场文书
python基于机器学习预测股票交易信号
2021/05/25 Python