字的研究(3)fontTools-TrueType轮廓坐标的获取以及基于TrueType的Glyph实例的构建
前言
本文主要介绍如果使用Python第三方库fontTools提取OpenType字体文件中的TrueType轮廓坐标以及如何构建基于TrueType的Glyph实例
TrueType轮廓坐标的获取
对于TrueType轮廓描述的OpenType文件,除了前文提到的利用ttx组件将表结构转化为XML文件方法,利用如下代码也可以直接获取具体的轮廓数据:
from fontTools.ttLib import TTFont
font = TTFont("Resources/simsun.ttf")
glyph = font.getGlyphSet()["uni70E0"] # 获取_TTGlyph实例
print(glyph._glyph.coordinates) # 坐标
print(glyph._glyph.endPtsOfContours) # 轮廓结束点
print(list(glyph._glyph.flags)) # 点类型flag
运行结果如下:
GlyphCoordinates([(138, 118),(138, 86),(206, 86),(206, 118),(138, 80),(138, 49),(206, 49),(206, 80),(138, 43),(138, -19),(123, -26),(124, -5),(124, 16),(124, 99),(110, 81),(86, 67),(84, 70),(118, 100),(142, 158),(125, 158),(112, 158),(101, 155),(92, 164),(144, 164),(154, 192),(156, 209),(176, 197),(169, 192),(161, 170),(159, 164),(207, 164),(221, 177),(238, 158),(157, 158),(151, 142),(140, 124),(205, 124),(214, 134),(229, 119),(220, 114),(220, 1),(220, -17),(199, -25),(197, -9),(168, -4),(168, 0),(195, -2),(206, 0),(206, 8),(206, 43),(52, 206),(74, 194),(67, 187),(67, 123),(87, 148),(91, 161),(105, 147),(99, 146),(90, 137),(81, 128),(67, 115),(67, 91),(64, 57),(87, 46),(103, 29),(103, 22),(103, 18),(99, 7),(92, 9),(87, 22),(82, 34),(63, 52),(56, 8),(12, -26),(11, -23),(41, 13),(53, 74),(53, 149),(33, 140),(34, 126),(33, 104),(25, 92),(13, 88),(10, 95),(10, 97),(10, 102),(14, 105),(19, 109),(28, 128),(29, 140)])
[3, 7, 49, 77, 89]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1]
描述TrueType轮廓的数据主要由坐标、轮廓结束点以及各点的类型flag组成。其中,轮廓结束点为各轮廓的最后一个点的坐标;点类型flag则和坐标一一对应,说明该点是普通点还是贝塞尔曲线的控制点,0为控制点,1为普通点(注意,TrueType轮廓只包含二次贝塞尔曲线)。
相比之下,我个人更倾向将数据转化为如下由三元组组成的二维数组的形式,更方便理解和处理:
coordinates = list(glyph._glyph.coordinates)
endPts = glyph._glyph.endPtsOfContours
flags = list(glyph._glyph.flags)
contours = []
contour = []
for i, (x,y) in enumerate(coordinates):
contour.append((x,y,flags[i]))
if i in endPts:
contours.append(contour)
contour = []
print(contours)
运行结果如下:
[[(138, 118, 1), (138, 86, 1), (206, 86, 1), (206, 118, 1)],
[(138, 80, 1), (138, 49, 1), (206, 49, 1), (206, 80, 1)],
[(138, 43, 1), (138, -19, 1), (123, -26, 1), (124, -5, 0), (124, 16, 1), (124, 99, 1), (110, 81, 0), (86, 67, 1), (84, 70, 1), (118, 100, 0), (142, 158, 1), (125, 158, 1), (112, 158, 0), (101, 155, 1), (92, 164, 1), (144, 164, 1), (154, 192, 0), (156, 209, 1), (176, 197, 1), (169, 192, 1), (161, 170, 0), (159, 164, 1), (207, 164, 1), (221, 177, 1), (238, 158, 1), (157, 158, 1), (151, 142, 0), (140, 124, 1), (205, 124, 1), (214, 134, 1), (229, 119, 1), (220, 114, 1), (220, 1, 1), (220, -17, 0), (199, -25, 1), (197, -9, 0), (168, -4, 1), (168, 0, 1), (195, -2, 0), (206, 0, 0), (206, 8, 1), (206, 43, 1)],
[(52, 206, 1), (74, 194, 1), (67, 187, 1), (67, 123, 1), (87, 148, 0), (91, 161, 1), (105, 147, 1), (99, 146, 0), (90, 137, 1), (81, 128, 0), (67, 115, 1), (67, 91, 0), (64, 57, 1), (87, 46, 0), (103, 29, 0), (103, 22, 1), (103, 18, 0), (99, 7, 0), (92, 9, 0), (87, 22, 1), (82, 34, 0), (63, 52, 1), (56, 8, 0), (12, -26, 1), (11, -23, 1), (41, 13, 0), (53, 74, 0), (53, 149, 0)],
[(33, 140, 1), (34, 126, 0), (33, 104, 0), (25, 92, 0), (13, 88, 0), (10, 95, 0), (10, 97, 1), (10, 102, 0), (14, 105, 1), (19, 109, 0), (28, 128, 0), (29, 140, 1)]]
基于TrueType的Glyph实例的构建
构建fontTools中的Glyph实例主要可以用于后续建立新的基于TrueType轮廓的字体文件。所采用的方法是基于前文所提到的Pen对象的子类TTGlyphPointPen,输入坐标、轮廓结束点以及各点的类型flag三项数据,输出Glyph实例:
from fontTools.pens.ttGlyphPen import TTGlyphPointPen
coordinates = [(138, 118),(138, 86),(206, 86),(206, 118),(138, 80),(138, 49),(206, 49),(206, 80),(138, 43),(138, -19),(123, -26),(124, -5),(124, 16),(124, 99),(110, 81),(86, 67),(84, 70),(118, 100),(142, 158),(125, 158),(112, 158),(101, 155),(92, 164),(144, 164),(154, 192),(156, 209),(176, 197),(169, 192),(161, 170),(159, 164),(207, 164),(221, 177),(238, 158),(157, 158),(151, 142),(140, 124),(205, 124),(214, 134),(229, 119),(220, 114),(220, 1),(220, -17),(199, -25),(197, -9),(168, -4),(168, 0),(195, -2),(206, 0),(206, 8),(206, 43),(52, 206),(74, 194),(67, 187),(67, 123),(87, 148),(91, 161),(105, 147),(99, 146),(90, 137),(81, 128),(67, 115),(67, 91),(64, 57),(87, 46),(103, 29),(103, 22),(103, 18),(99, 7),(92, 9),(87, 22),(82, 34),(63, 52),(56, 8),(12, -26),(11, -23),(41, 13),(53, 74),(53, 149),(33, 140),(34, 126),(33, 104),(25, 92),(13, 88),(10, 95),(10, 97),(10, 102),(14, 105),(19, 109),(28, 128),(29, 140)]
endPts = [3, 7, 49, 77, 89]
flags = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1]
pen = TTGlyphPointPen(None)
beginflag = 0
for i, pt in enumerate(coordinates):
if pen._isClosed():
pen.beginPath()
if flags[i] == 1:
pen.addPoint(pt,segmentType="line")
else:
pen.addPoint(pt)
if i in endPts:
pen.endPath()
glyph = pen.glyph()
返回的glyph即为Glyph实例,可直接用于构建基于TrueType轮廓的字体文件。注意,Glyph对象只包含字形轮廓数据,属于glyf表,对应前一节提到的_TTGlyph中的_glyph属性,_TTGlyph中的字宽和上下沿等数据则来自在字体文件的其他表格。
字的研究(3)fontTools-TrueType轮廓坐标的获取以及基于TrueType的Glyph实例的构建的更多相关文章
- 字的研究(2)Fonttools-字体文件的解析
前言 本文主要介绍如果使用Python第三方库fontTools对TrueType字体文件(指使用TrueType描述轮廓的OpenType字体文件)的解析.修改和创建等操作. fontTools简介 ...
- Android自定义View研究--View中的原点坐标和XML中布局自定义View时View触摸原点问题
这里只做个汇总~.~独一无二 文章出处:http://blog.csdn.net/djy1992/article/details/9715047 Android自定义View研究--View中的原点坐 ...
- NetLink通信原理研究、Netlink底层源码分析、以及基于Netlink_Connector套接字监控系统进程行为技术研究
1. Netlink简介 0x1:基本概念 Netlink是一个灵活,高效的”内核-用户态“.”内核-内核“.”用户态-用户态“通信机制.通过将复杂的消息拷贝和消息通知机制封装在统一的socket a ...
- 【地图功能开发系列:一】根据当前坐标点获取距离不超过N公里的门店
在此处输入标题 声明变量 //假设当前坐标 double lon1 = 113.336028; double lat1 = 23.21745; //距离m double distance = 1000 ...
- maven坐标的获取
网址:https://mvnrepository.com 网站上可以搜索具体的组织或项目关键字,之后复制对应的坐标到pom.xml中.如:
- BaiduMap 鼠标绘制矩形选框四个顶角坐标的获取
雪影工作室版权全部.转载请注明[http://blog.csdn.net/lina791211] 1.博文产生原因 在使用百度Map开放API进行开发的时候,遇到了一个需求,非常easy的一个需求. ...
- android之View坐标系(view获取自身坐标的方法和点击事件中坐标的获取)
在做一个view背景特效的时候被坐标的各个获取方法搞晕了,几篇抄来抄去的博客也没弄很清楚. 现在把整个总结一下. 其实只要把下面这张图看明白就没问题了. 涉及到的方法一共有下面几个: view获取自身 ...
- event 下鼠标坐标的获取
event.clientX.event.clientY 鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条.IE事件和标准事件都定义了这2个属性 event.pageX ...
- python实现基于百度路径规划接口的坐标对获取两点驾车距离的计算
今天为大家介绍一种通过python实现坐标对间距离数据的获取方法.接口采用百度开发的路径规划接口. 1.调用接口: 接口:(传入起点坐标串,结束坐标串:ak值需要注册百度开发者) 接口详细说明 htt ...
随机推荐
- 【LeetCode】1180. Count Substrings with Only One Distinct Letter 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 组合数 日期 题目地址:https://leetcod ...
- 【机器学习】决策树(Decision Tree) 学习笔记
[机器学习]决策树(decision tree) 学习笔记 标签(空格分隔): 机器学习 决策树简介 决策树(decision tree)是一个树结构(可以是二叉树或非二叉树).其每个非叶节点表示一个 ...
- 【LeetCode】402. Remove K Digits 解题报告(Python)
[LeetCode]402. Remove K Digits 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http: ...
- 【剑指Offer】链表中环的入口结点 解题报告(Python)
[剑指Offer]链表中环的入口结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...
- Pikachu靶场SSRF学习
下载Pikachu靶场:https://github.com/zhuifengshaonianhanlu/pikachu Windows用phpstudy也行,记得要改config.inc文件 打开S ...
- 为什么加密后的数据往往都是base64输出而不是hex16进制输出
通常加密后的数据都是字节数组,比如流行的aes128对称加密,还有Rsa非对称加密,加密后得到了一个字节数组,这个字节数组存在内存中,往往我们需要输出得到我们人眼能看到的字符. 加密aes(xxx) ...
- null和空字符串对于查询where条件语句的影响
在数据库中我们进行数据处理的过程中,对于null值或者空字符串的情况对于这种数据我们进行计算平均值以及查询过程中如何进行对于这类数据的处理呢? step1:建表:create table a(id i ...
- 定义制造业操作(定义 MES/MOM 系统)
定义制造业操作(定义 MES/MOM 系统) 制造业操作包含众多工厂级活动,涉及设备(定义.使用.时间表和维护).材料(识别.属性.位置和状态).人员(资格.可用性和时间表),以及这些资源与包含其信息 ...
- 决策树之PEP(悲观剪枝)
引用这2篇文章 https://blog.csdn.net/taoqick/article/details/72818496 https://www.open-open.com/lib/view/op ...
- 3 - 基于ELK的ElasticSearch 7.8.x技术整理 - 高级篇( 偏理论 )
4.ES高级篇 4.1.集群部署 集群的意思:就是将多个节点归为一体罢了( 这个整体就有一个指定的名字了 ) 4.1.1.window中部署集群 - 了解即可 把下载好的window版的ES中的dat ...