Skip to content

Commit

Permalink
New designspace checks added to Universal Profile
Browse files Browse the repository at this point in the history
 - com.google.fonts/check/designspace_has_sources: "Check that all sources in a designspace can be loaded successfully."
 - com.google.fonts/check/designspace_has_default_master: "Check that a default master is defined."
 - com.google.fonts/check/designspace_has_consistent_glyphset: "Check that non-default masters do not contain glyphs not found in the default master."
 - com.google.fonts/check/designspace_has_consistent_codepoints: "Check that Unicode assignments are consistent between masters."
(Follow-up to PR #3168)
  • Loading branch information
simoncozens authored and felipesanches committed Jan 19, 2022
1 parent 970c563 commit 1a91db5
Show file tree
Hide file tree
Showing 20 changed files with 461 additions and 7 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
Below are the most important changes from each release.
A more detailed list of changes is available in the corresponding milestones for each release in the Github issue tracker (https://github.com/googlefonts/fontbakery/milestones?state=closed).

## 0.8.5 (2021-Dec-??)
## 0.8.6 (2022-Feb-??)
### New Checks
#### Added to the Universal Profile
- **[com.google.fonts/check/designspace_has_sources]:** Check that all sources in a designspace can be loaded successfully. (PR #3168)
- **[com.google.fonts/check/designspace_has_default_master]:** Check that a default master is defined. (PR #3168)
- **[com.google.fonts/check/designspace_has_consistent_glyphset]:** Check that non-default masters do not contain glyphs not found in the default master. (PR #3168)
- **[com.google.fonts/check/designspace_has_consistent_codepoints]:** Check that Unicode assignments are consistent between masters. (PR #3168)


## 0.8.5 (2022-Jan-13)
### Noteworthy code-changes
- New command line flag: `-F, --full-list` to print full lists (`pretty_print_list` method) even when the total number of items exceeds a certain threashold. (issues #3173 and #3512)
- Included a few of the more recently added profiles that were still missing on our online docs (issue #3518)
Expand Down
2 changes: 2 additions & 0 deletions Lib/fontbakery/codetesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ def __call__(self, values, condition_overrides={}):
values = {'readme_md': values}
elif values.endswith('.ufo'):
values = {'ufo': values}
elif values.endswith('.designspace'):
values = {'designspace': values}
elif values.endswith('METADATA.pb'):
fonts = [os.path.join(os.path.dirname(values), f.filename)
for f in family_metadata(values).fonts]
Expand Down
27 changes: 27 additions & 0 deletions Lib/fontbakery/profiles/shared_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,33 @@ def variable_font_filename(ttFont):
return f"{familyname}{tags}.ttf"


@condition
def designSpace(designspace):
"""
Given a filepath for a designspace file, parse it
and return a DesignSpaceDocument, which is
'an object to read, write and edit
interpolation systems for typefaces'.
"""
if designspace:
from fontTools.designspaceLib import DesignSpaceDocument
import defcon
DS = DesignSpaceDocument.fromfile(designspace)
DS.loadSourceFonts(defcon.Font)
return DS


@condition
def designspace_sources(designSpace):
"""
Given a DesignSpaceDocument object,
return a set of UFO font sources.
"""
if designSpace:
import defcon
return designSpace.loadSourceFonts(defcon.Font)


@condition
def family_directory(font):
"""Get the path of font project directory."""
Expand Down
110 changes: 110 additions & 0 deletions Lib/fontbakery/profiles/universal.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@
'com.google.fonts/check/superfamily/vertical_metrics',
]

DESIGNSPACE_CHECKS = [
'com.google.fonts/check/designspace_has_sources',
'com.google.fonts/check/designspace_has_default_master',
'com.google.fonts/check/designspace_has_consistent_glyphset',
'com.google.fonts/check/designspace_has_consistent_codepoints',
]

UNIVERSAL_PROFILE_CHECKS = \
DESIGNSPACE_CHECKS + \
OPENTYPE_PROFILE_CHECKS + \
OUTLINE_PROFILE_CHECKS + \
SHAPING_PROFILE_CHECKS + \
Expand Down Expand Up @@ -56,6 +64,7 @@
'com.google.fonts/check/cjk_chws_feature'
]


@check(
id = 'com.google.fonts/check/name/trailing_spaces',
proposal = 'https://github.com/googlefonts/fontbakery/issues/2417'
Expand Down Expand Up @@ -1008,6 +1017,107 @@ def com_google_fonts_check_rupee(ttFont):
'Please add a glyph for Indian Rupee Sign “₹” at codepoint U+20B9.')
else:
yield PASS, "Looks good!"


@check(
id = "com.google.fonts/check/designspace_has_sources",
rationale = """
This check parses a designspace file and tries to load the source files specified.
This is meant to ensure that the file is not malformed, can be properly parsed and does include valid source file references.
""",
proposal = 'https://github.com/googlefonts/fontbakery/pull/3168'
)
def com_google_fonts_check_designspace_has_sources(designspace_sources):
"""See if we can actually load the source files."""
if not designspace_sources:
yield FAIL, \
Message("no-sources",
"Unable to load source files.")
else:
yield PASS, "OK"


@check(
id = "com.google.fonts/check/designspace_has_default_master",
rationale = """
We expect that designspace files declare on of the masters as default.
""",
proposal = 'https://github.com/googlefonts/fontbakery/pull/3168'
)
def com_google_fonts_check_designspace_has_default_master(designSpace):
"""Ensure a default master is defined."""
if not designSpace.findDefault():
yield FAIL, \
Message("not-found",
"Unable to find a default master.")
else:
yield PASS, "We located a default master."


@check(
id = "com.google.fonts/check/designspace_has_consistent_glyphset",
rationale = """
This check ensures that non-default masters don't have glyphs not present in the default one.
""",
conditions = ["designspace_sources"],
proposal = 'https://github.com/googlefonts/fontbakery/pull/3168'
)
def com_google_fonts_check_designspace_has_consistent_glyphset(designSpace, config):
"""Check consistency of glyphset in a designspace file."""
from fontbakery.utils import bullet_list

default_glyphset = set(designSpace.findDefault().font.keys())
failures = []
for source in designSpace.sources:
master_glyphset = set(source.font.keys())
outliers = master_glyphset - default_glyphset
if outliers:
outliers = ", ".join(list(outliers))
failures.append(f"Source {source.filename} has glyphs not present"
f" in the default master: {outliers}")
if failures:
yield FAIL,\
Message("inconsistent-glyphset",
f"Glyphsets were not consistent:\n"
f"{bullet_list(config, failures)}")
else:
yield PASS, "Glyphsets were consistent."


@check(
id = "com.google.fonts/check/designspace_has_consistent_codepoints",
rationale = """
This check ensures that Unicode assignments are consistent across all sources specified in a designspace file.
""",
conditions = ["designspace_sources"],
proposal = 'https://github.com/googlefonts/fontbakery/pull/3168'
)
def com_google_fonts_check_designspace_has_consistent_codepoints(designSpace, config):
"""Check codepoints consistency in a designspace file."""
from fontbakery.utils import bullet_list

default_source = designSpace.findDefault()
default_unicodes = {g.name: g.unicode for g in default_source.font}
failures = []
for source in designSpace.sources:
for g in source.font:
if g.name not in default_unicodes:
# Previous test will cover this
continue

if g.unicode != default_unicodes[g.name]:
failures.append(f"Source {source.filename} has"
f" {g.name}={g.unicode};"
f" default master has"
f" {g.name}={default_unicodes[g.name]}")
if failures:
yield FAIL,\
Message("inconsistent-codepoints",
f"Unicode assignments were not consistent:\n"
f"{bullet_list(config, failures)}")
else:
yield PASS, "Unicode assignments were consistent."


@check(
Expand Down
13 changes: 7 additions & 6 deletions Lib/fontbakery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,13 @@ def pretty_print_list(config, values, shorten=10, sep=", ", glue="and"):
return f"{sep} {glue} {str(values[-1])}"


def bullet_list(config, values, bullet="-", shorten=10):
return f" {bullet} " + pretty_print_list(config,
values,
shorten=shorten,
sep=f"\n {bullet} ",
glue=f"\n {bullet} And")
def bullet_list(config, items, bullet="-", indentation="\t"):
return f"{indentation}{bullet} " +\
pretty_print_list(config,
items,
sep=f"\n{indentation}{bullet} ",
glue=f"\n{indentation}{bullet} And")


def get_regular(fonts):
# TODO: Maybe also support getting a regular instance from a variable font?
Expand Down
40 changes: 40 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/fontinfo.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ascender</key>
<integer>800</integer>
<key>capHeight</key>
<integer>700</integer>
<key>descender</key>
<integer>-200</integer>
<key>openTypeHeadCreated</key>
<string>2021/02/05 10:10:29</string>
<key>postscriptBlueValues</key>
<array>
<real>-16.0</real>
<real>0.0</real>
<real>500.0</real>
<real>516.0</real>
<real>700.0</real>
<real>716.0</real>
<real>800.0</real>
<real>816.0</real>
</array>
<key>postscriptOtherBlues</key>
<array>
<real>-216.0</real>
<real>-200.0</real>
</array>
<key>styleName</key>
<string>Regular</string>
<key>unitsPerEm</key>
<integer>1000</integer>
<key>versionMajor</key>
<integer>1</integer>
<key>versionMinor</key>
<integer>0</integer>
<key>xHeight</key>
<integer>500</integer>
</dict>
</plist>
22 changes: 22 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/glyphs/A_.glif
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="A" format="2">
<advance width="888"/>
<unicode hex="0041"/>
<outline>
<contour>
<point x="694" y="-8" type="line"/>
<point x="883" y="-8" type="line"/>
<point x="549" y="728" type="line"/>
<point x="339" y="728" type="line"/>
<point x="5" y="-8" type="line"/>
<point x="184" y="-8" type="line"/>
<point x="281" y="207" type="line"/>
<point x="596" y="207" type="line"/>
</contour>
<contour>
<point x="319" y="343" type="line"/>
<point x="439" y="600" type="line"/>
<point x="558" y="343" type="line"/>
</contour>
</outline>
</glyph>
22 changes: 22 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/glyphs/B_.glif
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<glyph name="B" format="2">
<advance width="600"/>
<unicode hex="0042"/>
<outline>
<contour>
<point x="573" y="252" type="line"/>
<point x="809" y="524" type="line"/>
<point x="549" y="728" type="line"/>
<point x="95" y="728" type="line"/>
<point x="63" y="-8" type="line"/>
<point x="281" y="-8" type="line"/>
<point x="399" y="163" type="line"/>
<point x="728" y="-62" type="line"/>
</contour>
<contour>
<point x="281" y="343" type="line"/>
<point x="291" y="600" type="line"/>
<point x="558" y="504" type="line"/>
</contour>
</outline>
</glyph>
10 changes: 10 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/glyphs/contents.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>A</key>
<string>A_.glif</string>
<key>B</key>
<string>B_.glif</string>
</dict>
</plist>
10 changes: 10 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/layercontents.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<array>
<string>public.default</string>
<string>glyphs</string>
</array>
</array>
</plist>
19 changes: 19 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/lib.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.schriftgestaltung.disablesAutomaticAlignment</key>
<false/>
<key>com.schriftgestaltung.fontMasterID</key>
<string>m01</string>
<key>com.schriftgestaltung.glyphOrder</key>
<false/>
<key>com.schriftgestaltung.useNiceNames</key>
<true/>
<key>public.glyphOrder</key>
<array>
<string>A</string>
<string>B</string>
</array>
</dict>
</plist>
10 changes: 10 additions & 0 deletions data/test/stupidfont/Stupid Font Bold.ufo/metainfo.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>creator</key>
<string>com.schriftgestaltung.GlyphsUFOExport</string>
<key>formatVersion</key>
<integer>3</integer>
</dict>
</plist>
40 changes: 40 additions & 0 deletions data/test/stupidfont/Stupid Font Regular.ufo/fontinfo.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ascender</key>
<integer>800</integer>
<key>capHeight</key>
<integer>700</integer>
<key>descender</key>
<integer>-200</integer>
<key>openTypeHeadCreated</key>
<string>2021/02/05 10:10:29</string>
<key>postscriptBlueValues</key>
<array>
<real>-16.0</real>
<real>0.0</real>
<real>500.0</real>
<real>516.0</real>
<real>700.0</real>
<real>716.0</real>
<real>800.0</real>
<real>816.0</real>
</array>
<key>postscriptOtherBlues</key>
<array>
<real>-216.0</real>
<real>-200.0</real>
</array>
<key>styleName</key>
<string>Regular</string>
<key>unitsPerEm</key>
<integer>1000</integer>
<key>versionMajor</key>
<integer>1</integer>
<key>versionMinor</key>
<integer>0</integer>
<key>xHeight</key>
<integer>500</integer>
</dict>
</plist>
Loading

0 comments on commit 1a91db5

Please sign in to comment.