Browse Source

When updating repo dump out updated codepoint files

rsheeter 4 years ago
parent
commit
9840b8cd28
3 changed files with 71 additions and 0 deletions
  1. 66 0
      update/icons.py
  2. 1 0
      update/requirements.txt
  3. 4 0
      update/update_repo.py

+ 66 - 0
update/icons.py

@@ -0,0 +1,66 @@
+# Copyright 2020 Google LLC
+#
+# 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.
+
+"""Utility to generate codepoint files for Google-style iconfonts."""
+
+from fontTools import ttLib
+import functools
+from pathlib import Path
+
+
+_PUA_CODEPOINTS = [
+    range(0xE000, 0xF8FF + 1),
+    range(0xF0000, 0xFFFFD + 1),
+    range(0x100000, 0x10FFFD + 1)
+]
+
+
+def _is_pua(codepoint):
+  return any(r for r in _PUA_CODEPOINTS if codepoint in r)
+
+
+def _cmap(ttfont):
+
+  def _cmap_reducer(acc, u):
+    acc.update(u)
+    return acc
+
+  unicode_cmaps = (t.cmap for t in ttfont['cmap'].tables if t.isUnicode())
+  return functools.reduce(_cmap_reducer, unicode_cmaps, {})
+
+
+def _ligatures(ttfont):
+  liga_lookups = tuple(
+      filter(lambda l: l.LookupType == 4,
+             ttfont['GSUB'].table.LookupList.Lookup))
+  for lookup in liga_lookups:
+    for subtable in lookup.SubTable:
+      yield subtable.ligatures
+
+
+def enumerate(font_file: Path):
+  """Yields (icon name, codepoint) tuples for icon font."""
+  with ttLib.TTFont(font_file) as ttfont:
+    cmap = _cmap(ttfont)
+    rev_cmap = {v: k for k, v in cmap.items()}
+
+    for lig_root in _ligatures(ttfont):
+      for first_glyph_name, ligatures in lig_root.items():
+        for ligature in ligatures:
+          glyph_names = (first_glyph_name,) + tuple(ligature.Component)
+          icon_name = ''.join(chr(rev_cmap[n]) for n in glyph_names)
+          codepoint = rev_cmap[ligature.LigGlyph]
+          if not _is_pua(codepoint):
+            continue
+          yield (icon_name, codepoint)

+ 1 - 0
update/requirements.txt

@@ -5,6 +5,7 @@ black==19.10b0
 certifi==2020.6.20
 chardet==3.0.4
 click==7.1.2
+fonttools==4.14.0
 idna==2.10
 pathspec==0.8.0
 regex==2020.7.14

+ 4 - 0
update/update_repo.py

@@ -16,6 +16,7 @@
 
 from absl import app
 from absl import flags
+import icons
 import json
 from pathlib import Path
 import re
@@ -179,6 +180,9 @@ def _fetch_fonts(css_files: Sequence[Path]):
         fetch = Fetch(url, css_file.parent / (css_file.stem + url[-4:]))
         _do_fetch(fetch)
         css_file.unlink()
+        with open(fetch.dest_file.with_suffix(".codepoints"), "w") as f:
+            for name, codepoint in sorted(icons.enumerate(fetch.dest_file)):
+                f.write(f"{name} {codepoint:04x}\n")
 
 
 def _is_css(p: Path):