run black on colrv1_postproc.py script to fix indentation
parent
831faf480d
commit
5d4f4d6b38
|
@ -17,21 +17,15 @@ from colrv1_add_soft_light_to_flags import add_soft_light_to_flags
|
||||||
|
|
||||||
|
|
||||||
def _is_colrv1(font):
|
def _is_colrv1(font):
|
||||||
return (
|
return "COLR" in font and font["COLR"].version == 1
|
||||||
"COLR" in font
|
|
||||||
and font["COLR"].version == 1
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _is_cbdt(font):
|
def _is_cbdt(font):
|
||||||
return "CBDT" in font
|
return "CBDT" in font
|
||||||
|
|
||||||
|
|
||||||
def _is_compat_font(font):
|
def _is_compat_font(font):
|
||||||
return (
|
return "meta" in font and "Emji" in font["meta"].data
|
||||||
"meta" in font
|
|
||||||
and "Emji" in font["meta"].data
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _copy_emojicompat_data(colr_font, cbdt_font):
|
def _copy_emojicompat_data(colr_font, cbdt_font):
|
||||||
|
@ -39,146 +33,149 @@ def _copy_emojicompat_data(colr_font, cbdt_font):
|
||||||
|
|
||||||
|
|
||||||
def _set_name(name_table, nameID):
|
def _set_name(name_table, nameID):
|
||||||
name_table.getName(value, nameID, 3, 1, 0x409)
|
name_table.getName(value, nameID, 3, 1, 0x409)
|
||||||
|
|
||||||
|
|
||||||
def _set_name(name_table, nameID, value):
|
def _set_name(name_table, nameID, value):
|
||||||
name_table.setName(value, nameID, 3, 1, 0x409)
|
name_table.setName(value, nameID, 3, 1, 0x409)
|
||||||
|
|
||||||
|
|
||||||
def _copy_names(colr_font, cbdt_font):
|
def _copy_names(colr_font, cbdt_font):
|
||||||
colr_font["name"] = cbdt_font["name"]
|
colr_font["name"] = cbdt_font["name"]
|
||||||
name_table = colr_font["name"]
|
name_table = colr_font["name"]
|
||||||
assert all((n.platformID, n.platEncID, n.langID) == (3, 1, 0x409)
|
assert all(
|
||||||
for n in name_table.names), "Should only have names Android uses"
|
(n.platformID, n.platEncID, n.langID) == (3, 1, 0x409) for n in name_table.names
|
||||||
|
), "Should only have names Android uses"
|
||||||
|
|
||||||
# Amendments
|
# Amendments
|
||||||
_set_name(name_table, 10, "Color emoji font using COLRv1.")
|
_set_name(name_table, 10, "Color emoji font using COLRv1.")
|
||||||
_set_name(name_table, 11, "https://github.com/googlefonts/noto-emoji")
|
_set_name(name_table, 11, "https://github.com/googlefonts/noto-emoji")
|
||||||
_set_name(name_table, 12, "https://github.com/googlefonts/noto-emoji")
|
_set_name(name_table, 12, "https://github.com/googlefonts/noto-emoji")
|
||||||
|
|
||||||
|
|
||||||
# CBDT build step: @$(VS_ADDER) -vs 2640 2642 2695 --dstdir '.' -o "$@-with-pua-varsel" "$@-with-pua"
|
# CBDT build step: @$(VS_ADDER) -vs 2640 2642 2695 --dstdir '.' -o "$@-with-pua-varsel" "$@-with-pua"
|
||||||
def _add_vs_cmap(colr_font):
|
def _add_vs_cmap(colr_font):
|
||||||
emoji_variants = unicode_data.get_unicode_emoji_variants() | {0x2640, 0x2642, 0x2695}
|
emoji_variants = unicode_data.get_unicode_emoji_variants() | {
|
||||||
add_vs_cmap.modify_font("COLRv1 Emoji", colr_font, "emoji", emoji_variants)
|
0x2640,
|
||||||
|
0x2642,
|
||||||
|
0x2695,
|
||||||
|
}
|
||||||
|
add_vs_cmap.modify_font("COLRv1 Emoji", colr_font, "emoji", emoji_variants)
|
||||||
|
|
||||||
|
|
||||||
def _is_variation_selector_cmap_table(table):
|
def _is_variation_selector_cmap_table(table):
|
||||||
assert table.format in {4, 12, 14}
|
assert table.format in {4, 12, 14}
|
||||||
return table.format == 14
|
return table.format == 14
|
||||||
|
|
||||||
|
|
||||||
def _lookup_in_cmap(colr_font, codepoint):
|
def _lookup_in_cmap(colr_font, codepoint):
|
||||||
result = set()
|
result = set()
|
||||||
for table in colr_font["cmap"].tables:
|
for table in colr_font["cmap"].tables:
|
||||||
if _is_variation_selector_cmap_table(table):
|
if _is_variation_selector_cmap_table(table):
|
||||||
continue
|
continue
|
||||||
assert codepoint in table.cmap
|
assert codepoint in table.cmap
|
||||||
result.add(table.cmap[codepoint])
|
result.add(table.cmap[codepoint])
|
||||||
assert len(result) == 1, f"Ambiguous mapping for {codepoint}: {result}"
|
assert len(result) == 1, f"Ambiguous mapping for {codepoint}: {result}"
|
||||||
return next(iter(result))
|
return next(iter(result))
|
||||||
|
|
||||||
|
|
||||||
def _add_cmap_entries(colr_font, codepoint, glyph_name):
|
def _add_cmap_entries(colr_font, codepoint, glyph_name):
|
||||||
for table in colr_font["cmap"].tables:
|
for table in colr_font["cmap"].tables:
|
||||||
if _is_variation_selector_cmap_table(table):
|
if _is_variation_selector_cmap_table(table):
|
||||||
continue
|
continue
|
||||||
if not _is_bmp(codepoint) and table.format == 4:
|
if not _is_bmp(codepoint) and table.format == 4:
|
||||||
continue
|
continue
|
||||||
table.cmap[codepoint] = glyph_name
|
table.cmap[codepoint] = glyph_name
|
||||||
print(f"Map 0x{codepoint:04x} to {glyph_name}, format {table.format}")
|
print(f"Map 0x{codepoint:04x} to {glyph_name}, format {table.format}")
|
||||||
|
|
||||||
|
|
||||||
def _map_missing_flag_tag_chars_to_empty_glyphs(colr_font):
|
def _map_missing_flag_tag_chars_to_empty_glyphs(colr_font):
|
||||||
# Add all tag characters used in flags
|
# Add all tag characters used in flags
|
||||||
tag_cps = (
|
tag_cps = set(range(0xE0030, 0xE0039 + 1)) | set(range(0xE0061, 0xE007A + 1))
|
||||||
set(range(0xE0030, 0xE0039 + 1))
|
|
||||||
| set(range(0xE0061, 0xE007A + 1))
|
|
||||||
)
|
|
||||||
|
|
||||||
# Cancel tag
|
# Cancel tag
|
||||||
tag_cps |= {0xE007F}
|
tag_cps |= {0xE007F}
|
||||||
|
|
||||||
# Anything already cmap'd is fine
|
# Anything already cmap'd is fine
|
||||||
tag_cps -= set(_Cmap(colr_font).keys())
|
tag_cps -= set(_Cmap(colr_font).keys())
|
||||||
|
|
||||||
# CBDT maps these to blank glyphs
|
# CBDT maps these to blank glyphs
|
||||||
glyf_table = colr_font["glyf"]
|
glyf_table = colr_font["glyf"]
|
||||||
hmtx_table = colr_font["hmtx"]
|
hmtx_table = colr_font["hmtx"]
|
||||||
glyph_order_size = len(glyf_table.glyphOrder)
|
glyph_order_size = len(glyf_table.glyphOrder)
|
||||||
for cp in tag_cps:
|
for cp in tag_cps:
|
||||||
print(f"Map 0x{cp:04x} to a blank glyf")
|
print(f"Map 0x{cp:04x} to a blank glyf")
|
||||||
glyph_name = f"u{cp:04X}"
|
glyph_name = f"u{cp:04X}"
|
||||||
assert glyph_name not in glyf_table, f"{glyph_name} already in glyf"
|
assert glyph_name not in glyf_table, f"{glyph_name} already in glyf"
|
||||||
assert glyph_name not in hmtx_table.metrics, f"{glyph_name} already in hmtx"
|
assert glyph_name not in hmtx_table.metrics, f"{glyph_name} already in hmtx"
|
||||||
glyf_table[glyph_name] = glyf.Glyph()
|
glyf_table[glyph_name] = glyf.Glyph()
|
||||||
hmtx_table[glyph_name] = (0, 0)
|
hmtx_table[glyph_name] = (0, 0)
|
||||||
|
|
||||||
_add_cmap_entries(colr_font, cp, glyph_name)
|
_add_cmap_entries(colr_font, cp, glyph_name)
|
||||||
|
|
||||||
|
|
||||||
def _is_bmp(cp):
|
def _is_bmp(cp):
|
||||||
return cp in range(0x0000, 0xFFFF + 1)
|
return cp in range(0x0000, 0xFFFF + 1)
|
||||||
|
|
||||||
|
|
||||||
def _ligaset_for_glyph(lookup_list, glyph_name):
|
def _ligaset_for_glyph(lookup_list, glyph_name):
|
||||||
for lookup in lookup_list.Lookup:
|
for lookup in lookup_list.Lookup:
|
||||||
if lookup.LookupType != 4:
|
if lookup.LookupType != 4:
|
||||||
continue
|
continue
|
||||||
for liga_set in lookup.SubTable:
|
for liga_set in lookup.SubTable:
|
||||||
if glyph_name in liga_set.ligatures:
|
if glyph_name in liga_set.ligatures:
|
||||||
return liga_set.ligatures[glyph_name]
|
return liga_set.ligatures[glyph_name]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _Cmap(ttfont):
|
def _Cmap(ttfont):
|
||||||
|
def _Reducer(acc, u):
|
||||||
|
acc.update(u)
|
||||||
|
return acc
|
||||||
|
|
||||||
def _Reducer(acc, u):
|
unicode_cmaps = (t.cmap for t in ttfont["cmap"].tables if t.isUnicode())
|
||||||
acc.update(u)
|
return functools.reduce(_Reducer, unicode_cmaps, {})
|
||||||
return acc
|
|
||||||
|
|
||||||
unicode_cmaps = (t.cmap for t in ttfont['cmap'].tables if t.isUnicode())
|
|
||||||
return functools.reduce(_Reducer, unicode_cmaps, {})
|
|
||||||
|
|
||||||
|
|
||||||
def _map_empty_flag_tag_to_black_flag(colr_font):
|
def _map_empty_flag_tag_to_black_flag(colr_font):
|
||||||
# fontchain_lint wants direct support for empty flag tags
|
# fontchain_lint wants direct support for empty flag tags
|
||||||
# so map them to the default flag to match cbdt behavior
|
# so map them to the default flag to match cbdt behavior
|
||||||
|
|
||||||
# if the emoji font starts using extensions this code will require revision
|
# if the emoji font starts using extensions this code will require revision
|
||||||
|
|
||||||
cmap = _Cmap(colr_font)
|
cmap = _Cmap(colr_font)
|
||||||
black_flag_glyph = cmap[0x1f3f4]
|
black_flag_glyph = cmap[0x1F3F4]
|
||||||
cancel_tag_glyph = cmap[0xe007f]
|
cancel_tag_glyph = cmap[0xE007F]
|
||||||
lookup_list = colr_font["GSUB"].table.LookupList
|
lookup_list = colr_font["GSUB"].table.LookupList
|
||||||
liga_set = _ligaset_for_glyph(lookup_list, black_flag_glyph)
|
liga_set = _ligaset_for_glyph(lookup_list, black_flag_glyph)
|
||||||
assert liga_set is not None, "There should be existing ligatures using black flag"
|
assert liga_set is not None, "There should be existing ligatures using black flag"
|
||||||
|
|
||||||
# Map black flag + cancel tag to just black flag
|
# Map black flag + cancel tag to just black flag
|
||||||
# Since this is the ligature set for black flag, component is just cancel tag
|
# Since this is the ligature set for black flag, component is just cancel tag
|
||||||
# Since we only have one component its safe to put our rule at the front
|
# Since we only have one component its safe to put our rule at the front
|
||||||
liga = ot.Ligature()
|
liga = ot.Ligature()
|
||||||
liga.Component = [cancel_tag_glyph]
|
liga.Component = [cancel_tag_glyph]
|
||||||
liga.LigGlyph = black_flag_glyph
|
liga.LigGlyph = black_flag_glyph
|
||||||
liga_set.insert(0, liga)
|
liga_set.insert(0, liga)
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
if len(argv) != 3:
|
if len(argv) != 3:
|
||||||
raise ValueError("Must have two args, a COLRv1 font and a CBDT emojicompat font")
|
raise ValueError(
|
||||||
|
"Must have two args, a COLRv1 font and a CBDT emojicompat font"
|
||||||
|
)
|
||||||
|
|
||||||
colr_file = Path(argv[1])
|
colr_file = Path(argv[1])
|
||||||
assert colr_file.is_file()
|
assert colr_file.is_file()
|
||||||
colr_font = ttLib.TTFont(colr_file)
|
colr_font = ttLib.TTFont(colr_file)
|
||||||
if not _is_colrv1(colr_font):
|
if not _is_colrv1(colr_font):
|
||||||
raise ValueError("First arg must be a COLRv1 font")
|
raise ValueError("First arg must be a COLRv1 font")
|
||||||
|
|
||||||
cbdt_file = Path(argv[2])
|
cbdt_file = Path(argv[2])
|
||||||
assert cbdt_file.is_file()
|
assert cbdt_file.is_file()
|
||||||
cbdt_font = ttLib.TTFont(cbdt_file)
|
cbdt_font = ttLib.TTFont(cbdt_file)
|
||||||
if not _is_cbdt(cbdt_font) or not _is_compat_font(cbdt_font):
|
if not _is_cbdt(cbdt_font) or not _is_compat_font(cbdt_font):
|
||||||
raise ValueError("Second arg must be a CBDT emojicompat font")
|
raise ValueError("Second arg must be a CBDT emojicompat font")
|
||||||
|
|
||||||
print(f"COLR {colr_file.absolute()}")
|
print(f"COLR {colr_file.absolute()}")
|
||||||
print(f"CBDT {cbdt_file.absolute()}")
|
print(f"CBDT {cbdt_file.absolute()}")
|
||||||
|
@ -197,7 +194,7 @@ def main(argv):
|
||||||
|
|
||||||
add_soft_light_to_flags(colr_font)
|
add_soft_light_to_flags(colr_font)
|
||||||
|
|
||||||
out_file = Path('fonts/Noto-COLRv1-noflags.ttf').absolute()
|
out_file = Path("fonts/Noto-COLRv1-noflags.ttf").absolute()
|
||||||
print("Writing", out_file)
|
print("Writing", out_file)
|
||||||
colr_font.save(out_file)
|
colr_font.save(out_file)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue