pdf.js源码分析-字体加载流程

news/2024/11/15 21:32:39/文章来源:https://www.cnblogs.com/xxss0903/p/18296837

pdf.js中的字体加载流程,下面演示一种Type1的字体的加载流程,会把一些兼容性的内容省去,只记录字体数据的加载过程中涉及到的方法和作用:

  1. evaluator.js -> handleSetFont:操作符列表中加载字体
  2. evaluator.js -> loadFont:加载字体的方法
  3. evaluator.js -> preEvaluateFont:对字体信息进行预处理,对pdf中的字体信息开始整理,类似于将pdf中的字典信息进行整理,拿到pdf中字体的信息
  4. evaluator.js -> translateFont:通过上一步获取的字体信息,开始对字体进行加载和转换,此时假设字体数据包含有descriptor对象
    在translateFont中会创建Font对象,首先是创建字体的properties属性,根据descriptor等获取到fontName等属性值,fontFile拿到字体的数据。
    下面是包含descriptor时创建的字体properties属性对象
const properties = {type,name: fontName.name,subtype,file: fontFile,length1,length2,length3,isInternalFont,loadedName: baseDict.loadedName,composite,fixedPitch: false,fontMatrix: dict.getArray("FontMatrix") || FONT_IDENTITY_MATRIX,firstChar,lastChar,toUnicode,bbox: descriptor.getArray("FontBBox") || dict.getArray("FontBBox"),ascent: descriptor.get("Ascent"),descent: descriptor.get("Descent"),xHeight: descriptor.get("XHeight") || 0,capHeight: descriptor.get("CapHeight") || 0,flags: descriptor.get("Flags"),italicAngle: descriptor.get("ItalicAngle") || 0,isType3Font,cssFontInfo,scaleFactors: glyphScaleFactors,systemFontInfo,};
  1. evaluator.js -> extractDataStructures:有了上面的properties之后,调用extractDataStructures方法来获取字体编码和differences的值,这个方法重要,根据字体数据的编码类型,比如StandardEncoding还是其他等,获取到字体的编码映射等。以及获取toUnicodeMap,这里关于字体的映射和differences限于篇幅,就不做多的赘述,另开文章详写。
  2. evaluator.js -> extractWidths:提取字体中字符的宽度,每个字符都有一个宽度,所以拿到对应字符之后再进行宽度校正
  3. evaluator.js -> new Font(fontName.name, fontFile, newProperties):创建Font字体对象
  4. fonts.js -> fontFile.isEmpty:这个isEmpty会读取字体数据,判断不为空来读取字体的字节数据
  5. fonts.js -> getFontFileType:获取字体的类型,[type, subtype] = getFontFileType(file, properties);
  6. fonts.js -> new Type1Font(name, file, properties):根据字体数据和属性properties来创建Type1Font,这里按照Type1类型的字体进行解析字体数据。
  7. type1_font.js -> new Type1Font(name, file, properties):根据字体数据和属性properties来创建Type1Font,这里按照Type1类型的字体进行解析字体数据。
  8. type1_font.js -> checkEExecFlag,getHeaderBlock,extractFontHeader来获取Type1字体的头数据
  9. type1_parser.js -> extractFontProgram:提取字体数据中的/CharStrings等token数据,这里时字体的规格数据
  10. type1_parser.js -> this.wrap(name,type2Charstrings,this.charstrings,subrs,properties):将字体数据进行包装,按照CFF格式进行组装拼接,这里是对字体格式进行,里面涉及的关于字体的内容比较多,这里不做过多赘述。CFF是紧凑型字体,这里还不会直接使用,通过CFF字体之后会再次convert为OTF字体
  11. type1_parser.js -> adjustWidths(properties):对字体宽度进行重新矫正,使用fontMatrix进行校正
  12. fonts.js -> convert(name, cff, properties):最后是将CFF的字体数据传入之后再进行组装成OTF字体数据,并且转换成unit8array的二进制数组,这个就是最后使用的字体数据了,进行loadFont的数据
  13. evaluator.js -> new TranslatedFont({loadedName: font.loadedName,font: translatedFont,dict: font,evaluatorOptions: this.options}):将OTF的字体再次进行转换,构造一个TranslatedFont对象,主要是包含了OTF的字体数据font值,以及用来发送字体加载完成的消息,也就是send方法,并且对Type3字体做处理,这里具体Type3字体的处理暂不赘述。
  14. evaluator.js -> handleSetFont:这里进入到let translated = await this.loadFont,将上面所生成的translatedFont对象作为字体数据,并且translatedFont调用send方法表示当前字体加载完成,将当前的消息发送到api.js中,此时调用的是commonobj,然后对象是Font类型
  15. api.js -> messageHandler.on("commonobj"):处理加载完字体发送过来的数据,const font = new FontFaceObject(exportedData, ...),这里将translatedFont中的font的data数据进行转换成FontFaceObject对象,这个FontFaceObject是pdf.js封装的用来进行处理FontFace字体对象的类,这样在使用FontFace的时候就是使用pdf.js中包装的FontFaceObject来将OTF中的字体数据和浏览器的FontFace对象之间进行关联
  16. api.js -> this.fontLoader.bind(font):使用fontLoader对上一步中的FontFaceObject字体进行加载,会调用FontFaceObject中的createNativeFontFace,也就是将pdf.js中的字体转换为FontFace这样的对象,这样创建浏览器的本地FontFace对象,这个FontFace加载的名字也就是后面要在设置字体的时候使用的font-family的名字,再通过document.fonts.add(fontFace)即完成字体到本地浏览器的加载
    以上便是pdf.js对于Type1字体加载的整个流程,其中并没有进行详细叙述,但是也大概包含了完整的从数据流到字体的流程,其中还包含几个重要步骤没有详细描述,比如FlateStream的加载和解析,相当于对flate编码的流数据进行解密。以及具体的CFF和OTF字体之间的转换,关键有一个是对于字体中header的一个描述使用。还有toUnicodeMap这样进行字体映射的内容的具体描述。
    下图是一个加载的具体流程,从左到右,从上到下的顺序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/742501.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vmware个人版免费

官方个人免费版本的VMware产品 2024年5月15日,PC虚拟巨头VMware宣布旗下的两款产品VMware Workstation Pro和VMware Fusion Pro即日起对个人用户免费开放。博通官网注册账号 打开地址:https://www.broadcom.com/ 登录 https://support.broadcom.com/web/ecx/home#.下载安装免…

企业微信对接

基本概念corpid 每个企业都拥有唯一的corpid,获取此信息可在管理后台“我的企业”-“企业信息”下查看“企业ID”(需要有管理员权限) userid 每个成员都有唯一的userid,即所谓“账号”。在管理后台->“通讯录”->点进某个成员的详情页,可以看到。 部门id 每个部门都…

【unity开发】怎么下载国际版的unity编辑器版本

有一天从公司那接手了一个项目,然后发现那个项目的版本我没有,我就去unity官网下载。 下载完了发现还是版本不对。 仔细一看发现,他们用的版本号末尾少了个"c1"。c1的意思是中国特供版,好像是说有微信api的支持。那么我应该怎么做呢? 下面随便一个版本为例子1.点…

html+js实现选中左边的数据到右边

效果后台要开发个功能,给游戏内的用户赠送道具,先把道具列表展示,然后选择要增送的道具,可以加上道具图片之类的,美化 index.html 页面没有美化,只是实现了效果。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&qu…

《代理选择与反爬虫策略探究:如何优化网络爬虫效率与稳定性》

本文全面介绍了在选择合适的代理时应考虑的因素,涵盖了各种代理类型(如高匿代理、隧道代理等)的特点及其适用场景。文章深入探讨了常见的反爬虫策略,以及如何通过调整爬虫策略来应对这些策略,从而提升爬虫的效率和稳定性。适合对网络爬虫开发和代理技术感兴趣的读者阅读。…

Redis部署与使用

一、关系型数据库与非关系型数据库 1.关系型数据库 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录。 SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作。 主流的关系型数据库…

excel表格中怎样将一列的数值全部加上一个数值

1、打开目标文件2、然后在B1或者其它单元格中输入数字“10”,如图所示。3、然后鼠标右击此单元格,在右键菜单中执行“复制”命令。4、然后选中要加10的所有数据,在右键菜单中点击“选择性粘贴”选项5、然后在出现的窗口中,点击运算区域的“加”选项,进行确定。6、完成以上…

CRC我就拿下了

国人讲CRC的没有什么能讲明白的文章,除了一篇《我学习 CRC32、CRC16、CRC 原理和算法的总结(与 WINRAR 结果一致)》,这里先感谢他,另,他也有一些没有说明白的地方,怎么说呢,还是鄙人自己来吧。 我弄明白CRC这个原理和算法主要参考的是上面的国人的那篇和这个外国的《A …

在vscode中打开浏览器

在html页面右键,选择 open in default browser 即可打开默认浏览器 布局——<!-- 文档类型为html --> <!DOCTYPE html> <html lang="en"> <head><!-- 字符集为utf-8 --><meta charset="UTF-8"><!-- 设置浏览器兼容…

[Java]“不同族”基本数据类型间只能“强转”吗?

本篇文章标题即摘要,就不赘述。 如果文中有不妥或不对的,多多交流。【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18298193 出自【进步*于辰的博客】本文阐述需要计算不同位二进制的表示范围,引用博文《[MySQ…

还在困惑需要多少数据吗?来看看这份估计指南 | CVPR 2022

论文基于实验验证,为数据需求预测这一问题提供了比较有用的建议,详情可以直接看看Conclusion部分。 来源:晓飞的算法工程笔记 公众号论文: How Much More Data Do I Need? Estimating Requirements for Downstream Tasks论文地址:https://arxiv.org/abs/2207.01725 论文代…

uniapp实现问卷多项填空

产品提出了一个需求,需要实现类似问卷星的记录单,要求有单选,多选,填空,以及多项填空。前三者好实现,最后一个花费了我挺长的时间。 在pc端后台管理模板选项设置的时候,保存是将整个问题保存进去,以三个或三个以上的下划线为一个空,保存的形式例为: cm* cm*___ cm…