What font is that in?
Issue 34; 07 Jul 2020
, Missing glyph U+2BC3, you say? Ok. Where is it?
A couple of months ago, I stumbled over a missing glyph message while trying to generate a PDF. It didn’t take too long to find a very helpful answer from Martin Monperrus on superuser. I gleefully stole it.
Over the past few weeks, I’ve edited that script maybe half a dozen times to change the search character. Last night, I decided to just fix it:
#!/usr/bin/env python3
"""Given a Unicode character reference, return a list of the fonts
that contain that character. Credit to Martin Monperrus in
https://superuser.com/questions/876572 for the actual code. I just
wrapped a bit of Click around it."""
import sys
import os
import unicodedata
import click
from fontTools.ttLib import TTFont
# YMMV.
FONTPATH = [os.path.expanduser("~") + "/Library/Fonts",
os.path.expanduser("~") + "/fonts",
"/System/Library/Fonts",
"/Library/Fonts",
"/usr/local/AHFormatterV70/fonts"]
@click.command()
@click.argument('charref')
def checkfonts(charref):
"""Looks for the character identified by charref in FONTPATH. The
charref can be a decimal number, a hexadecimal number optionally
preceded by "U+", or a single (Unicode) character. "65", "U+41"
and "A" are all equivalent. It searches for that character in the
(TrueType) fonts that it finds on FONTPATH.
"""
if len(charref) > 1:
try:
codepoint = int(charref)
except ValueError:
try:
if charref.startswith('U+'):
codepoint = int(charref[2:], 16)
else:
codepoint = int(charref, 16)
except ValueError:
print("Bad character reference:", charref)
sys.exit(1)
else:
codepoint = ord(charref)
char = chr(codepoint)
fonts = findfonts()
count = 0
for fontpath in fonts:
font = TTFont(fontpath)
if char_in_font(char, font):
count += 1
print(fontpath)
# Space before ";" below is intentional so that
# wide characters don't overlap the semicolon.
if count == 0:
print("Could not find '%s' (%s ; codepoint=U+%X) in %d fonts"
% (charref, char, codepoint, len(fonts)))
elif count == 1:
print("contains '%s' (%s ; codepoint=U+%X)"
% (unicodedata.name(char), char, codepoint))
else:
print("%d fonts contain '%s' (%s ; codepoint=U+%X)"
% (count, unicodedata.name(char), char, codepoint))
def findfonts():
"""Returns all the TrueType fonts that are found on FONTPATH."""
fonts = []
for path in FONTPATH:
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".ttf"):
fonts.append(os.path.join(root, file))
return fonts
def char_in_font(unicode_char, font):
"""Tests to see if unicode_char appears in font."""
for cmap in font['cmap'].tables:
if cmap.isUnicode():
if ord(unicode_char) in cmap.cmap:
return True
return False
if __name__ == "__main__":
checkfonts()
Oh, and by the way,
$ font-check 2bc3
/Users/ndw/Library/Fonts/Symbola_hint.ttf
contains 'HORIZONTAL BLACK OCTAGON' (⯃ ; codepoint=U+2BC3)
Share and enjoy.