-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathglyphs.py
More file actions
166 lines (152 loc) · 6.32 KB
/
glyphs.py
File metadata and controls
166 lines (152 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import os
import fontforge
def pen_action(pen, action):
'''
在字符上绘制或增绘曲线。
action_stack:操作及参数序列,已经按FF官方文档重整过。
'''
stack = []
for item in action:
if type(item) == tuple: # 坐标一定被改为数组形式
stack.append(item)
elif item == 'closepath':
pen.closePath()
elif item == 'curveto':
pen.curveTo(stack[-3], stack[-2], stack[-1])
stack = stack[:-3]
elif item == 'lineto':
pen.lineTo(stack[-1])
stack.pop()
elif item == 'moveto':
pen.moveTo(stack[-1])
stack.pop()
def create_stroke_pen(tmp_glyph, radius, matrix):
pen = tmp_glyph.glyphPen()
pen.moveTo((0, 0))
pen.endPath()
tmp_glyph.stroke('circular', radius)
if matrix is not None:
tmp_glyph.transform(matrix)
def draw_glyph(file, glyph, font):
stack = []
actions = []
transformation = [None]
linewidth = 0.0
cur_mode = 0 # 0:正像,1:负像
has_erase = False
def check_transformation():
if transformation[-1] is not None:
print('错误:不在默认坐标系下绘图, %4X' % glyph.unicode)
assert False
for line in file:
if line[0] == '%': continue # 注释
line = line.replace('[', ' [ ').replace(']', ' ] ') # 方便处理数组
for word in line.rstrip().split():
# 倒反天罡,把栈现有数值打包成一个数组项,到读到右括号的时候再恢复原有结构
if word == '[': stack = [stack]
elif word == ']': stack = stack[0] + [stack[1:]]
elif not word[0].isalpha():
stack.append(float(word))
# 处理命令
elif word in ['dtransform', 'truncate', 'idtransform']:
continue # 和Metapost似乎无关
elif word == 'closepath':
actions += ['closepath']
elif word == 'concat':
transformation[-1] = stack.pop()
elif word == 'curveto':
check_transformation()
actions += [(stack[-6], stack[-5]), (stack[-4], stack[-3]), (stack[-2], stack[-1]), 'curveto']
stack = stack[:-6]
elif word == 'fill':
pen_action(font[0xE000].glyphPen(), actions)
font[0xE000].correctDirection()
if cur_mode == 1:
tmp_layer = font[0xE000].foreground
for c in tmp_layer:
c.reverseDirection()
font[0xE000].layers[1] = tmp_layer
glyph.layers[1] += font[0xE000].foreground
glyph.removeOverlap()
elif word == 'gsave':
transformation.append(transformation[-1])
elif word == 'grestore':
transformation.pop()
elif word == 'lineto' or word == 'moveto':
check_transformation()
actions += [(stack[-2], stack[-1]), word]
stack = stack[:-2]
elif word == 'newpath':
actions = []
# pens[cur_pen] = glyph.glyphPen(replace=False)
elif word == 'pop' or word == 'setmiterlimit': # 不懂miter,暂时不处理
stack.pop()
elif word == 'setdash':
if stack[-2:] != [[], 0]:
print('暂不支持虚线, %4X' % glyph.unicode)
assert False
stack = stack[:-2]
elif word in ['setlinecap', 'setlinejoin']:
if stack.pop() != 1:
print('暂不支持非圆笔, %4X' % glyph.unicode)
assert False
elif word == 'setlinewidth':
linewidth = stack.pop()
elif word == 'setrgbcolor':
if stack[-3:] == [0.0, 0.0, 0.0]: # 暂不支持负像
cur_mode = 0
elif stack[-3:] == [1.0, 1.0, 1.0]:
cur_mode = 1
has_erase = True
else:
print('颜色错误, %04X' % glyph.unicode)
assert False
stack = stack[:-3]
elif word == 'showpage':
glyph.simplify()
glyph.round()
glyph.simplify()
glyph.round()
return has_erase # 结束了
elif word == 'stroke':
pen_action(font[0xE000].glyphPen(), actions)
create_stroke_pen(font[0xE001], linewidth, transformation[-1])
font[0xE000].stroke('convex', font[0xE001].foreground[0])
if cur_mode == 1:
tmp_layer = font[0xE000].foreground
for c in tmp_layer:
c.reverseDirection()
font[0xE000].layers[1] = tmp_layer
glyph.layers[1] += font[0xE000].foreground
else:
print('不支持的命令: %s, %04X' % (word, glyph.unicode))
assert False
print('Postscript格式错误: %04X' % glyph.unicode)
assert False
def process_glyphs(font_name, encoding_vector):
f = fontforge.font()
f.fontname = font_name
f.encoding = 'UnicodeBMP'
f.createChar(0xE000) # 用于处理fill类命令的临时字符
f.createChar(0xE001) # 用于处理纯笔画图形的临时字符
needs_manual_intervention = []
for i in range(256):
encoding = ord(encoding_vector[i])
if encoding == 0x20:
print('未编码字符 %02X' % i)
continue
g = f.createChar(encoding)
try:
file_name = font_name + '.%d' % i
ps_file = open(file_name)
print('[%d] U+%04X' % (i, encoding))
has_erase = draw_glyph(ps_file, g, f)
if has_erase:
needs_manual_intervention.append('U+%04X' % encoding)
ps_file.close()
os.remove(file_name)
except: continue
f[0xE000].clear()
f[0xE001].clear()
print('以下字符涉及erase,可能需要手工调整:' + str(sorted(needs_manual_intervention)))
return f