使用 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 相关文章推荐
直接在JS里创建JSON数据然后遍历使用
Jul 25 Javascript
javascript日期验证之输入日期大于等于当前日期
Dec 13 Javascript
表单元素值获取方式js及java方式的简单实例
Oct 15 Javascript
JavaScript简单验证表单空值及邮箱格式的方法
Jan 20 Javascript
jquery插件canvaspercent.js实现百分比圆饼效果
Jul 18 jQuery
webpack学习笔记之代码分割和按需加载的实例详解
Jul 20 Javascript
浅谈React高阶组件
Mar 28 Javascript
vue自定义filters过滤器
Apr 26 Javascript
vue-cli V3.0版本的使用详解
Oct 24 Javascript
图文讲解vue的v-if使用方法
Feb 11 Javascript
JavaScript实现多张图片放大镜效果示例【不限定图片尺寸,rem单位】
May 14 Javascript
ES6实现图片切换特效代码
Jan 14 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
PHP-redis中文文档介绍
2013/02/07 PHP
最新制作ThinkPHP3.2.3完全开发手册
2015/11/23 PHP
php+laravel依赖注入知识点总结
2019/11/04 PHP
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
2010/04/18 Javascript
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
jquery幻灯片插件bxslider样式改进实例
2014/10/15 Javascript
JQuery.Ajax()的data参数类型实例详解
2015/11/20 Javascript
jquery中键盘事件小结
2016/02/24 Javascript
JavaScript仿flash遮罩动画效果
2016/06/15 Javascript
JavaScript调试之console.log调试的一个小技巧分享
2017/08/07 Javascript
说说AngularJS中的$parse和$eval的用法
2017/09/14 Javascript
react-router v4如何使用history控制路由跳转详解
2018/01/09 Javascript
jQuery与vue实现拖动验证码功能
2018/01/30 jQuery
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
详解JavaScript中的数组合并方法和对象合并方法
2018/05/11 Javascript
javascript、php关键字搜索函数的使用方法
2018/05/29 Javascript
微信小程序实现收藏与取消收藏切换图片功能
2018/08/03 Javascript
angular ng-model 无法获取值的处理方法
2018/10/02 Javascript
python定时采集摄像头图像上传ftp服务器功能实现
2013/12/23 Python
python中二维阵列的变换实例
2014/10/09 Python
Python实现监控程序执行时间并将其写入日志的方法
2015/06/30 Python
pytorch 在网络中添加可训练参数,修改预训练权重文件的方法
2019/08/17 Python
利用pandas将非数值数据转换成数值的方式
2019/12/18 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
python安装第三方库如xlrd的方法
2020/10/31 Python
阿根廷首家户外用品制造商和经销商:Montagne
2018/02/12 全球购物
英国最好的包装供应商:Priory Direct
2019/12/17 全球购物
综合内勤岗位职责
2014/04/14 职场文书
标准毕业生自荐信
2014/06/24 职场文书
班子四风对照检查材料
2014/08/21 职场文书
四风批评与自我批评发言稿
2014/10/14 职场文书
上课睡觉万能检讨书
2015/02/17 职场文书
工程质量保证书
2015/05/09 职场文书
运动会入场词
2015/07/18 职场文书
青年联谊会致辞
2015/07/31 职场文书
导游带团欢迎词
2015/09/30 职场文书