Playing with sbix format
diff --git a/cbdt2sbix.py b/cbdt2sbix.py
new file mode 100755
index 0000000..fee84eb
--- /dev/null
+++ b/cbdt2sbix.py
@@ -0,0 +1,95 @@
+#!/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()
\ No newline at end of file