Merge pull request #323 from kabisa/windows-compat

Build Windows compatible font
pull/325/head
Cosimo Lupo 2020-12-08 09:22:57 +00:00 committed by GitHub
commit 750cf68f2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 13 deletions

View File

@ -13,7 +13,8 @@
# limitations under the License. # limitations under the License.
EMOJI = NotoColorEmoji EMOJI = NotoColorEmoji
font: $(EMOJI).ttf EMOJI_WINDOWS = NotoColorEmoji_WindowsCompatible
all: $(EMOJI).ttf $(EMOJI_WINDOWS).ttf
CFLAGS = -std=c99 -Wall -Wextra `pkg-config --cflags --libs cairo` CFLAGS = -std=c99 -Wall -Wextra `pkg-config --cflags --libs cairo`
LDFLAGS = -lm `pkg-config --libs cairo` LDFLAGS = -lm `pkg-config --libs cairo`
@ -199,8 +200,11 @@ $(COMPRESSED_DIR)/%.png: $(QUANTIZED_DIR)/%.png | check_tools $(COMPRESSED_DIR)
# ... # ...
# Run make without -j if this happens. # Run make without -j if this happens.
%.ttx: %.ttx.tmpl $(ADD_GLYPHS) $(ALL_COMPRESSED_FILES) $(EMOJI).tmpl.ttx: $(EMOJI).tmpl.ttx.tmpl $(ADD_GLYPHS) $(ALL_COMPRESSED_FILES)
@$(PYTHON) $(ADD_GLYPHS) -f "$<" -o "$@" -d "$(COMPRESSED_DIR)" $(ADD_GLYPHS_FLAGS) $(PYTHON) $(ADD_GLYPHS) -f "$<" -o "$@" -d "$(COMPRESSED_DIR)" $(ADD_GLYPHS_FLAGS)
$(EMOJI_WINDOWS).tmpl.ttx: $(EMOJI).tmpl.ttx.tmpl $(ADD_GLYPHS) $(ALL_COMPRESSED_FILES)
$(PYTHON) $(ADD_GLYPHS) --add_cmap4 --add_glyf -f "$<" -o "$@" -d "$(COMPRESSED_DIR)" $(ADD_GLYPHS_FLAGS)
%.ttf: %.ttx %.ttf: %.ttx
@rm -f "$@" @rm -f "$@"
@ -215,6 +219,16 @@ $(EMOJI).ttf: check_sequence $(EMOJI).tmpl.ttf $(EMOJI_BUILDER) $(PUA_ADDER) \
@mv "$@-with-pua-varsel" "$@" @mv "$@-with-pua-varsel" "$@"
@rm "$@-with-pua" @rm "$@-with-pua"
$(EMOJI_WINDOWS).ttf: check_sequence $(EMOJI_WINDOWS).tmpl.ttf $(EMOJI_BUILDER) $(PUA_ADDER) \
$(ALL_COMPRESSED_FILES) | check_tools
@$(PYTHON) $(EMOJI_BUILDER) -O $(SMALL_METRICS) -V $(word 2,$^) "$@" "$(COMPRESSED_DIR)/emoji_u"
@$(PYTHON) $(PUA_ADDER) "$@" "$@-with-pua"
@$(VS_ADDER) -vs 2640 2642 2695 --dstdir '.' -o "$@-with-pua-varsel" "$@-with-pua"
@mv "$@-with-pua-varsel" "$@"
@rm "$@-with-pua"
check_sequence: check_sequence:
ifdef BYPASS_SEQUENCE_CHECK ifdef BYPASS_SEQUENCE_CHECK
@echo Bypassing the emoji sequence checks @echo Bypassing the emoji sequence checks
@ -223,7 +237,7 @@ else
endif endif
clean: clean:
rm -f $(EMOJI).ttf $(EMOJI).tmpl.ttf $(EMOJI).tmpl.ttx rm -f $(EMOJI).ttf $(EMOJI_WINDOWS).ttf $(EMOJI).tmpl.ttf $(EMOJI_WINDOWS).tmpl.ttf $(EMOJI).tmpl.ttx $(EMOJI_WINDOWS).tmpl.ttx
rm -f waveflag rm -f waveflag
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@ -18,6 +18,9 @@ import sys
from fontTools import ttx from fontTools import ttx
from fontTools.ttLib.tables import otTables from fontTools.ttLib.tables import otTables
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable
from fontTools.ttLib import newTable
import add_emoji_gsub import add_emoji_gsub
import add_aliases import add_aliases
@ -139,7 +142,7 @@ def get_font_cmap(font):
return font['cmap'].tables[0].cmap return font['cmap'].tables[0].cmap
def add_glyph_data(font, seqs, seq_to_advance, vadvance): def add_glyph_data(font, seqs, seq_to_advance, vadvance, add_glyf):
"""Add hmtx and GlyphOrder data for all sequences in seqs, and ensures there's """Add hmtx and GlyphOrder data for all sequences in seqs, and ensures there's
a cmap entry for each single-codepoint sequence. Seqs not in seq_to_advance a cmap entry for each single-codepoint sequence. Seqs not in seq_to_advance
will get a zero advance.""" will get a zero advance."""
@ -163,6 +166,16 @@ def add_glyph_data(font, seqs, seq_to_advance, vadvance):
hmtx = font['hmtx'].metrics hmtx = font['hmtx'].metrics
vmtx = font['vmtx'].metrics vmtx = font['vmtx'].metrics
# Add glyf table so empty glyphs will be added to ensure compatibility
# with systems requiring a glyf table, like Windows 10.
if add_glyf:
pen = TTGlyphPen(None)
empty_glyph = pen.glyph()
font['loca'] = newTable("loca")
font['glyf'] = glyf_table = newTable("glyf")
glyf_table.glyphOrder = font.getGlyphOrder()
glyf_table.glyphs = {g: empty_glyph for g in glyf_table.glyphOrder}
# We don't expect sequences to be in the glyphOrder, since we removed all the # We don't expect sequences to be in the glyphOrder, since we removed all the
# single-cp sequences from it and don't expect it to already contain names # single-cp sequences from it and don't expect it to already contain names
# corresponding to multiple-cp sequencess. But just in case, we use # corresponding to multiple-cp sequencess. But just in case, we use
@ -186,11 +199,12 @@ def add_glyph_data(font, seqs, seq_to_advance, vadvance):
if name not in reverseGlyphMap: if name not in reverseGlyphMap:
font.glyphOrder.append(name) font.glyphOrder.append(name)
updatedGlyphOrder=True updatedGlyphOrder=True
if add_glyf:
glyf_table[name] = empty_glyph
if updatedGlyphOrder: if updatedGlyphOrder:
delattr(font, '_reverseGlyphOrderDict') delattr(font, '_reverseGlyphOrderDict')
def add_aliases_to_cmap(font, aliases): def add_aliases_to_cmap(font, aliases):
"""Some aliases might map a single codepoint to some other sequence. These """Some aliases might map a single codepoint to some other sequence. These
should map directly to the glyph for that sequence in the cmap. (Others will should map directly to the glyph for that sequence in the cmap. (Others will
@ -327,14 +341,30 @@ def add_ligature_sequences(font, seqs, aliases):
for seq, name in pairs: for seq, name in pairs:
add_ligature(lookup, cmap, seq, name) add_ligature(lookup, cmap, seq, name)
def add_cmap_format_4(font):
"""Add cmap format 4 table for Windows support, based on the
format 12 cmap."""
def update_font_data(font, seq_to_advance, vadvance, aliases): cmap = get_font_cmap(font)
newtable = CmapSubtable.newSubtable(4)
newtable.platformID = 3
newtable.platEncID = 1
newtable.language = 0
# Format 4 only has unicode values 0x0000 to 0xFFFF
newtable.cmap = {cp: name for cp, name in cmap.items() if cp <= 0xFFFF}
font['cmap'].tables.append(newtable)
def update_font_data(font, seq_to_advance, vadvance, aliases, add_cmap4, add_glyf):
"""Update the font's cmap, hmtx, GSUB, and GlyphOrder tables.""" """Update the font's cmap, hmtx, GSUB, and GlyphOrder tables."""
seqs = get_all_seqs(font, seq_to_advance) seqs = get_all_seqs(font, seq_to_advance)
add_glyph_data(font, seqs, seq_to_advance, vadvance) add_glyph_data(font, seqs, seq_to_advance, vadvance, add_glyf)
add_aliases_to_cmap(font, aliases) add_aliases_to_cmap(font, aliases)
add_ligature_sequences(font, seqs, aliases) add_ligature_sequences(font, seqs, aliases)
if add_cmap4:
add_cmap_format_4(font)
def apply_aliases(seq_dict, aliases): def apply_aliases(seq_dict, aliases):
"""Aliases is a mapping from sequence to replacement sequence. We can use """Aliases is a mapping from sequence to replacement sequence. We can use
@ -350,7 +380,7 @@ def apply_aliases(seq_dict, aliases):
return usable_aliases return usable_aliases
def update_ttx(in_file, out_file, image_dirs, prefix, ext, aliases_file): def update_ttx(in_file, out_file, image_dirs, prefix, ext, aliases_file, add_cmap4, add_glyf):
if ext != '.png': if ext != '.png':
raise Exception('extension "%s" not supported' % ext) raise Exception('extension "%s" not supported' % ext)
@ -374,7 +404,7 @@ def update_ttx(in_file, out_file, image_dirs, prefix, ext, aliases_file):
vadvance = font['vhea'].advanceHeightMax if 'vhea' in font else lineheight vadvance = font['vhea'].advanceHeightMax if 'vhea' in font else lineheight
update_font_data(font, seq_to_advance, vadvance, aliases) update_font_data(font, seq_to_advance, vadvance, aliases, add_cmap4, add_glyf)
font.saveXML(out_file) font.saveXML(out_file)
@ -397,11 +427,15 @@ def main():
parser.add_argument( parser.add_argument(
'-a', '--aliases', help='process alias table', const='emoji_aliases.txt', '-a', '--aliases', help='process alias table', const='emoji_aliases.txt',
nargs='?', metavar='file') nargs='?', metavar='file')
parser.add_argument(
'--add_cmap4', help='add cmap format 4 table', dest='add_cmap4', action='store_true')
parser.add_argument(
'--add_glyf', help='add glyf and loca tables', dest='add_glyf', action='store_true')
args = parser.parse_args() args = parser.parse_args()
update_ttx( update_ttx(
args.in_file, args.out_file, args.image_dirs, args.prefix, args.ext, args.in_file, args.out_file, args.image_dirs, args.prefix, args.ext,
args.aliases) args.aliases, args.add_cmap4, args.add_glyf)
if __name__ == '__main__': if __name__ == '__main__':

Binary file not shown.

Binary file not shown.