8from operator
import itemgetter
9from itertools
import groupby
16TRICKY_NAME =
"MingLiU"
21UPOS = -143 * 1000 // EM
22UWIDTH = 20 * 1000 // EM
26font = fontforge.font()
27font.familyname = TRICKY_NAME
33font.descent = -DESCENT
37font.os2_typolinegap = 0
39font.horizontalBaseline = (
40 (
"hang",
"ideo",
"romn"),
42 (
"latn",
"romn", (ASCENT, DESCENT, 0), ()),
43 (
"grek",
"romn", (ASCENT, DESCENT, 0), ()),
44 (
"hani",
"ideo", (ASCENT, DESCENT, 0), ()),
73gcd = math.gcd(ASCENT, EM)
83 {(ASCENT << 6) // gcd}
93font.setTableData(
"prep", fontforge.parseTTInstrs(prep_program))
121 for index, point
in enumerate([p
for contour
in glyph.foreground
for p
in contour]):
122 if point.y
not in [ASCENT, DESCENT]:
128 return fontforge.parseTTInstrs(instructions)
135 pen = glyph.glyphPen()
137 pen.moveTo((0, DESCENT))
138 pen.lineTo((0, ASCENT))
139 pen.lineTo((EM, ASCENT))
140 pen.lineTo((EM, DESCENT))
146 pen = glyph.glyphPen()
147 pen.moveTo((0, DESCENT))
150 pen.lineTo((EM, DESCENT))
156 pen = glyph.glyphPen()
158 pen.lineTo((0, ASCENT))
159 pen.lineTo((EM, ASCENT))
166 pen = glyph.glyphPen()
168 pen.moveTo((EM // 8, 0))
169 pen.lineTo((EM // 8, ASCENT))
170 pen.lineTo((EM - EM // 8, ASCENT))
171 pen.lineTo((EM - EM // 8, 0))
174 pen.moveTo((EM // 4, EM // 8))
175 pen.lineTo((EM - EM // 4, EM // 8))
176 pen.lineTo((EM - EM // 4, ASCENT - EM // 8))
177 pen.lineTo((EM // 4, ASCENT - EM // 8))
183 return range(fromUnicode, throughUnicode + 1)
199 [0x394, 0x3A5, 0x3A7, 0x3A9, 0x3BC, 0x3C0],
206 [0x2044, 0x2122, 0x2126, 0x2202, 0x2206, 0x220F],
209 [0x221E, 0x222B, 0x2248, 0x2260],
212 0x22F2, 0x25CA, 0x3007, 0x4E00, 0x4E03, 0x4E09, 0x4E5D, 0x4E8C, 0x4E94, 0x516B, 0x516D,
213 0x5341, 0x56D7, 0x56DB, 0x571F, 0x6728, 0x6C34, 0x706B, 0x91D1
217] + [0x70] + [ord(c)
for c
in "中文测试文本是否正确"]
219no_path_codepoints = [
239 glyph = font.createChar(-1, name)
248create_glyph(
"Descent Flushed", descent_flushed_glyph).unicode = 0xC9
253 name =
"Zero Advance" if advance_percentage == 0
else (
254 "Full Advance" if advance_percentage == 1
else f
"1/{(int)(1/advance_percentage)} Advance"
256 no_path_glyph = font.createChar(codepoint, name)
257 no_path_glyph.width = (int)(EM * advance_percentage)
261for (codepoint, advance_percentage)
in no_path_codepoints:
262 if (codepoint
in square_codepoints):
263 raise ValueError(f
"{hex(codepoint)} is occupied.")
266font.generate(sys.argv[1]
if len(sys.argv) >= 2
else "test_font.ttf")
271for glyph
in font.glyphs():
272 if glyph.unicode >= 0:
273 scripts.add(fontforge.scriptFromUnicode(glyph.unicode))
274 for codepoint, _, _
in glyph.altuni
or []:
275 scripts.add(fontforge.scriptFromUnicode(codepoint))
276script_list = list(scripts)
279print(f
"| \ Script <br />Glyph | {' | '.join(script_list)} |")
280print(
" | :--- " +
" | :----: " * len(script_list) +
"|")
282for glyph
in font.glyphs():
283 if glyph.unicode < 0
and not glyph.altuni:
286 if glyph.unicode >= 0:
287 glyph_mapping[fontforge.scriptFromUnicode(glyph.unicode)] = [glyph.unicode]
288 for codepoint, _, _
in glyph.altuni
or []:
289 script = fontforge.scriptFromUnicode(codepoint)
290 if script
in glyph_mapping:
291 glyph_mapping[script].
append(codepoint)
293 glyph_mapping[script] = [codepoint]
295 codepoints_by_script = [glyph_mapping.get(script, [])
for script
in script_list]
302 list(map(itemgetter(1), group))
303 for key, group
in groupby(enumerate(codepoints),
lambda x: x[0] - x[1])
305 characters = [chr(c)
for c
in codepoints]
312 if c.isprintable()
and (
not c.isspace()):
314 return "`<" + unicodedata.name(c, hex(ord(c))) +
">`"
316 full_list =
" ".join([map_char(c)
for c
in characters])
317 return "**codepoint(s):** " +
", ".join([
318 f
"{hex(r[0])}-{hex(r[-1])}" if len(r) > 1
else hex(r[0])
for r
in codepoint_ranges
319 ]) +
"<br />" +
"**character(s):** " + full_list
322 f
"| {glyph.glyphname} | {' | '.join([describe_codepoint_range(l) for l in codepoints_by_script])} |"
static void append(char **dst, size_t *count, const char *src, size_t n)
ascent_flushed_glyph(glyph)
describe_codepoint_range(codepoints)
create_no_path_glyph(codepoint, advance_percentage)
square_glyph(glyph)
Creating Glyphs Outlines.
descent_flushed_glyph(glyph)
create_glyph(name, contour)
unicode_range(fromUnicode, throughUnicode)