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))
96def glyph_program(glyph):
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)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
def describe_codepoint_range(codepoints)
def create_no_path_glyph(codepoint, advance_percentage)
def unicode_range(fromUnicode, throughUnicode)
def descent_flushed_glyph(glyph)
def create_glyph(name, contour)
def ascent_flushed_glyph(glyph)
def square_glyph(glyph)
Creating Glyphs Outlines.
def print(*args, **kwargs)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
static SkString join(const CommandLineFlags::StringArray &)