#!/usr/bin/env python3 # Copyright 2021 Google, Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Google Author(s): Rod Sheeter import argparse import contextlib from fontTools import ttLib from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.ttLib.tables import sbixStrike from fontTools.ttLib.tables import sbixGlyph from nototools import tool_utils # https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt#glyph-bitmap-data-formats _CBDT_FORMAT_SMALL_METRIC_PNG = 17 def _del_table(font, tag): if tag in font: del font[tag] def _make_sbix(cblc, cbdt): # Ref https://gist.github.com/anthrotype/8c08eb372df2fb5da311887b32c2b9ac sbix = ttLib.newTable("sbix") # Apple Emoji uses this resolution = 72 # Noto CBLC will tell you 109 ppem but that makes the sbix assets seem too big ppem = 128 sbix_strike = sbixStrike.Strike(ppem=ppem, resolution=resolution) sbix.strikes[sbix_strike.ppem] = sbix_strike for strike in cbdt.strikeData: for glyph_name, cbdt_bitmap in strike.items(): cbdt_bitmap.decompile() # populate .metrics, .imageData assert cbdt_bitmap.getFormat() in {_CBDT_FORMAT_SMALL_METRIC_PNG} # only format for now sbix_strike.glyphs[glyph_name] = sbixGlyph.Glyph( glyphName=glyph_name, graphicType="png", imageData=cbdt_bitmap.imageData, # Apple Color Emoji seem to always be 0 # but then our glyphs are too high originOffsetY=-20, #originOffsetX=cbdt_bitmap.metrics.BearingX, #originOffsetY=cbdt_bitmap.metrics.BearingY, ) return sbix def _add_empty_glyf_glyphs(font): pen = TTGlyphPen(None) empty_glyph = pen.glyph() font['loca'] = ttLib.newTable("loca") font['glyf'] = glyf_table = ttLib.newTable("glyf") glyf_table.glyphOrder = font.getGlyphOrder() glyf_table.glyphs = {g: empty_glyph for g in glyf_table.glyphOrder} def main(): parser = argparse.ArgumentParser( description="Creates an SBIX (Apple style) bitmap font from a CBDT (Google style) bitmap font.") parser.add_argument( '-i', '--in_file', help='Input file', default="fonts/NotoColorEmoji.ttf") parser.add_argument( '-o', '--out_file', help='Output file', default="fonts/NotoColorEmoji_AppleCompatible.ttf") args = parser.parse_args() with contextlib.closing(ttLib.TTFont(args.in_file)) as font: font["sbix"] = _make_sbix(font["CBLC"], font["CBDT"]) _add_empty_glyf_glyphs(font) _del_table(font, "CBDT") _del_table(font, "CBLC") print(f"Writing {args.out_file}...") font.save(args.out_file) if __name__ == '__main__': main()