mirror of
https://github.com/google/fonts.git
synced 2024-12-13 05:32:35 +03:00
108 lines
2.7 KiB
Python
108 lines
2.7 KiB
Python
|
|
||
|
import contextlib
|
||
|
import os
|
||
|
|
||
|
|
||
|
from fontTools import ttLib
|
||
|
|
||
|
from google.apputils import app
|
||
|
from util import google_fonts as fonts
|
||
|
|
||
|
|
||
|
def _LoadGlyf(font, char, name, problems):
|
||
|
"""Loads a glyf and expands (populates fields) it.
|
||
|
|
||
|
Args:
|
||
|
font: A TTFont.
|
||
|
char: int id of char, e.g. ord('C').
|
||
|
name: name to use in problems string describing char. e.g. SPACE.
|
||
|
problems: set to add problems to.
|
||
|
Returns:
|
||
|
2-tuple of (cmap_key, glyph). (None, None) if a problem occurred. Adds
|
||
|
to problems if a problem occurred.
|
||
|
"""
|
||
|
if 'glyf' not in font:
|
||
|
problems.add('NO_GLYF_TABLE')
|
||
|
return (None, None)
|
||
|
|
||
|
cmap = fonts.UnicodeCmapTables(font).next().cmap
|
||
|
if char not in cmap:
|
||
|
problems.add('NO_%s' % name)
|
||
|
return (None, None)
|
||
|
|
||
|
key = cmap[char]
|
||
|
glyph = font['glyf'].glyphs[key]
|
||
|
glyph.expand(font['glyf'])
|
||
|
|
||
|
return (key, glyph)
|
||
|
|
||
|
|
||
|
def _HasInk(font, glyph_name):
|
||
|
"""Checks if specified glyph has any ink.
|
||
|
|
||
|
That is, that it has at least one defined contour associated. Composites are
|
||
|
considered to have ink if any of their components have ink.
|
||
|
|
||
|
Args:
|
||
|
font: A TTFont that has a 'glyf' table.
|
||
|
glyph_name: The name of the glyph to check for ink.
|
||
|
Returns:
|
||
|
True if the font has at least one contour associated with it.
|
||
|
"""
|
||
|
glyph = font['glyf'].glyphs[glyph_name]
|
||
|
glyph.expand(font['glyf'])
|
||
|
|
||
|
if not glyph.isComposite():
|
||
|
if glyph.numberOfContours == 0:
|
||
|
return False
|
||
|
(coords, _, _) = glyph.getCoordinates(font['glyf'])
|
||
|
# you need at least 3 points to draw
|
||
|
return len(coords) > 2
|
||
|
|
||
|
# composite is blank if composed of blanks
|
||
|
# if you setup a font with cycles you are just a bad person
|
||
|
for glyph_name in glyph.getComponentNames(glyph.components):
|
||
|
if _HasInk(font, glyph_name):
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
|
||
|
def _CheckFont(font):
|
||
|
"""Inspects a font for space/nbsp issues.
|
||
|
|
||
|
Args:
|
||
|
font: A TTFont.
|
||
|
Returns:
|
||
|
A set of strings describing problems found in the font. Empty set if none.
|
||
|
"""
|
||
|
problems = set()
|
||
|
|
||
|
(space_cmap, _) = _LoadGlyf(font, 0x0020, 'SPACE', problems)
|
||
|
(nbsp_cmap, _) = _LoadGlyf(font, 0x00A0, 'NBSP', problems)
|
||
|
|
||
|
if nbsp_cmap and _HasInk(font, nbsp_cmap):
|
||
|
problems.add('NBSP_HAS_INK')
|
||
|
|
||
|
if space_cmap and _HasInk(font, space_cmap):
|
||
|
problems.add('SPACE_HAS_INK')
|
||
|
|
||
|
if nbsp_cmap and space_cmap:
|
||
|
if font['hmtx'][nbsp_cmap][0] != font['hmtx'][space_cmap][0]:
|
||
|
problems.add('SPACE_NBSP_WIDTH_MISMATCH')
|
||
|
|
||
|
return set(problems)
|
||
|
|
||
|
|
||
|
def main(argv):
|
||
|
for filename in argv[1:]:
|
||
|
with contextlib.closing(ttLib.TTFont(filename)) as font:
|
||
|
problems = _CheckFont(font)
|
||
|
if not problems:
|
||
|
problems.add('OK')
|
||
|
print '{:48} {}'.format(os.path.basename(filename),
|
||
|
','.join(sorted(problems)))
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
app.run()
|