Fontbakery version 1.0.0
family/win_ascent_and_descent
A font's winAscent and winDescent values should be greater than or equal to the head table's yMax, abs(yMin) values. If they are less than these values, clipping can occur on Windows platforms (https://github.com/RedHatBrand/Overpass/issues/33).
If the font includes tall/deep writing systems such as Arabic or Devanagari, the winAscent and winDescent can be greater than the yMax and absolute yMin values to accommodate vowel marks.
When the 'win' Metrics are significantly greater than the UPM, the linespacing can appear too loose. To counteract this, enabling the OS/2 fsSelection bit 7 (Use_Typo_Metrics), will force Windows to use the OS/2 'typo' values instead. This means the font developer can control the linespacing with the 'typo' values, whilst avoiding clipping by setting the 'win' values to values greater than the yMax and absolute yMin.
OS/2.usWinAscent value should be equal or greater than 1022, but got 1000 instead
googlefonts/article/images
The purpose of this check is to ensure images (either raster or vector files) are not excessively large in filesize and resolution.
These constraints are loosely based on infrastructure limitations under default configurations.
It also ensures that the article page has a minimum length and includes at least one visual asset.
Family metadata at . does not have an article.
googlefonts/metadata/unreachable_subsetting
This check ensures that all encoded glyphs in the font are covered by a
subset declared in the METADATA.pb. Google Fonts splits the font into
a set of subset fonts based on the contents of the subsets
field and
the subset definitions in the glyphsets
repository.
Any encoded glyphs which are not by any of these subset definitions will not be served in the subsetted fonts, and so will be unreachable to the end user.
The following codepoints supported by the font are not covered by any subsets defined in the font's metadata file, and will never be served. You can solve this by either manually adding additional subset declarations to METADATA.pb, or by editing the glyphset definitions.
Use -F or --full-lists to disable shortening of long lists.
Or you can add the above codepoints to one of the subsets supported by the font: latin
, latin-ext
outline_alignment_miss
This check heuristically looks for on-curve points which are close to, but do not sit on, significant boundary coordinates. For example, a point which has a Y-coordinate of 1 or -1 might be a misplaced baseline point. As well as the baseline, here we also check for points near the x-height (but only for lowercase Latin letters), cap-height, ascender and descender Y coordinates.
Not all such misaligned curve points are a mistake, and sometimes the design may call for points in locations near the boundaries. As this check is liable to generate significant numbers of false positives, it will pass if there are more than 100 reported misalignments.
The following glyphs have on-curve points which have potentially incorrect y coordinates:
* ccedilla (U+00E7): X=244.0,Y=2.0 (should be at baseline 0?) * ccedilla (U+00E7): X=211.0,Y=2.0 (should be at baseline 0?) * Iogonek (U+012E): X=147.0,Y=2.0 (should be at baseline 0?) * Iogonek (U+012E): X=127.0,Y=2.0 (should be at baseline 0?) * Iogonek (U+012E): X=147.0,Y=2.0 (should be at baseline 0?) * uni0327 (U+0327): X=94.0,Y=2.0 (should be at baseline 0?) * uni0327 (U+0327): X=61.0,Y=2.0 (should be at baseline 0?) * uni0328 (U+0328): X=45.0,Y=2.0 (should be at baseline 0?) * uni0328 (U+0328): X=25.0,Y=2.0 (should be at baseline 0?) * uni0328 (U+0328): X=45.0,Y=2.0 (should be at baseline 0?) * uniE016 (U+E016): X=22.0,Y=1002.0 (should be at ascender 1000?)
googlefonts/meta/script_lang_tags
The OpenType 'meta' table originated at Apple. Microsoft added it to OT with just two DataMap records:
dlng: comma-separated ScriptLangTags that indicate which scripts, or languages and scripts, with possible variants, the font is designed for.
slng: comma-separated ScriptLangTags that indicate which scripts, or languages and scripts, with possible variants, the font supports.
The slng structure is intended to describe which languages and scripts the font overall supports. For example, a Traditional Chinese font that also contains Latin characters, can indicate Hant,Latn, showing that it supports Hant, the Traditional Chinese variant of the Hani script, and it also supports the Latn script.
The dlng structure is far more interesting. A font may contain various glyphs, but only a particular subset of the glyphs may be truly "leading" in the design, while other glyphs may have been included for technical reasons. Such a Traditional Chinese font could only list Hant there, showing that it’s designed for Traditional Chinese, but the font would omit Latn, because the developers don’t think the font is really recommended for purely Latin-script use.
The tags used in the structures can comprise just script, or also language and script. For example, if a font has Bulgarian Cyrillic alternates in the locl feature for the cyrl BGR OT languagesystem, it could also indicate in dlng explicitly that it supports bul-Cyrl. (Note that the scripts and languages in meta use the ISO language and script codes, not the OpenType ones).
This check ensures that the font has the meta table containing the slng and dlng structures.
All families in the Google Fonts collection should contain the 'meta' table. Windows 10 already uses it when deciding on which fonts to fall back to. The Google Fonts API and also other environments could use the data for smarter filtering. Most importantly, those entries should be added to the Noto fonts.
In the font making process, some environments store this data in external files already. But the meta table provides a convenient way to store this inside the font file, so some tools may add the data, and unrelated tools may read this data. This makes the solution much more portable and universal.
This font file does not have a 'meta' table.
googlefonts/vendor_id
Microsoft keeps a list of font vendors and their respective contact info. This list is updated regularly and is indexed by a 4-char "Vendor ID" which is stored in the achVendID field of the OS/2 table.
Registering your ID is not mandatory, but it is a good practice since some applications may display the type designer / type foundry contact info on some dialog and also because that info will be visible on Microsoft's website:
https://docs.microsoft.com/en-us/typography/vendors/
This check verifies whether or not a given font's vendor ID is registered in that list or if it has some of the default values used by the most common font editors.
Each new FontBakery release includes a cached copy of that list of vendor IDs. If you registered recently, you're safe to ignore warnings emitted by this check, since your ID will soon be included in one of our upcoming releases.
OS/2 VendorID value 'ASTS' is not yet recognized. If you registered it recently, then it's safe to ignore this warning message. Otherwise, you should set it to your own unique 4 character code, and register it with Microsoft at https://www.microsoft.com/typography/links/vendorlist.aspx
superfamily/list
This is a merely informative check that lists all sibling families detected by fontbakery.
Only the fontfiles in these directories will be considered in superfamily-level checks.
.
required_tables
According to the OpenType spec https://docs.microsoft.com/en-us/typography/opentype/spec/otff#required-tables
Whether TrueType or CFF outlines are used in an OpenType font, the following tables are required for the font to function correctly:
The spec also documents that variable fonts require the following table:
Depending on the typeface and coverage of a font, certain tables are recommended for optimum quality.
For example:⏎
This font contains the following optional tables:
- GPOS - GSUB
Font contains all required tables.
googlefonts/description/has_article
Fonts may have a longer article about them, or a description, but not both - except for Noto fonts which should have both!
This font doesn't have an ARTICLE.en_us.html file.
googlefonts/STAT/axis_order
This is (for now) a merely informative check to detect what's the axis ordering declared on the STAT table of fonts in the Google Fonts collection.
We may later update this to enforce some unified axis ordering scheme, yet to be determined.
This font does not have a STAT table: Font(file='OblataNeue-Regular.otf', context=CheckRunContext(testables=[...], config={'file_size': {'WARN_SIZE': 1048576, 'FAIL_SIZE': 9437184}, 'custom_order': None, 'explicit_checks': None, 'exclude_checks': com.google.fonts/check/fontbakery_version,com.daltonmaag/check/ufo_required_fields,com.daltonmaag/check/ufo_recommended_fields,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,com.google.fonts/check/shaping/regression,com.google.fonts/check/shaping/forbidden,com.google.fonts/check/shaping/collides,com.google.fonts/check/fontv, 'full_lists': False, 'skip_network': None}, is_multithreaded=False))
All of the fonts lack a STAT table.
fontbakery_version
Running old versions of FontBakery can lead to a poor report which may include false WARNs and FAILs due do bugs, as well as outdated quality assurance criteria.
Older versions will also not report problems that are detected by new checks added to the tool in more recent updates.
Failed with ModuleNotFoundError: No module named 'pip_api'
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 219, in _run_check subresults = check(**args) # Might raise. ^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/callable.py", line 99, in __call__ return self.__wrapped__(*args, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/fontbakery_version.py", line 80, in check_fontbakery_version import pip_api
fontdata_namecheck
We need to check names are not already used, and today the best place to check that is http://namecheck.fontdata.com
hinting_impact
This check is merely informative, displaying an useful comparison of filesizes of hinted versus unhinted font files.
Failed with TypeError: a bytes-like object is required, not 'MagicMock'
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 223, in _run_check subresults = list(subresults) ^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/hinting_impact.py", line 71, in check_hinting_impact stats = hinting_stats(font) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/hinting_impact.py", line 47, in hinting_stats pyftsubset(args) File "/lib/python3.11/site-packages/fontTools/misc/loggingTools.py", line 375, in wrapper return func(*args, **kwds) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontTools/subset/__init__.py", line 3826, in main save_font(font, outfile, options) File "/lib/python3.11/site-packages/fontTools/misc/loggingTools.py", line 375, in wrapper return func(*args, **kwds) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontTools/subset/__init__.py", line 3655, in save_font font.save(outfile, reorderTables=options.canonical_order) File "/lib/python3.11/site-packages/fontTools/ttLib/ttFont.py", line 226, in save writer_reordersTables = self._save(tmp) ^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontTools/ttLib/ttFont.py", line 273, in _save self._writeTable(tag, writer, done, tableCache) File "/lib/python3.11/site-packages/fontTools/ttLib/ttFont.py", line 729, in _writeTable writer[tag] = tabledata ~~~~~~^^^^^ File "/lib/python3.11/site-packages/fontTools/ttLib/sfnt.py", line 286, in __setitem__ entry.saveData(self.file, data) File "/lib/python3.11/site-packages/fontTools/ttLib/sfnt.py", line 518, in saveData file.write(data)
ots
The OpenType Sanitizer (OTS) is a tool that checks that the font is structually well-formed and passes various sanity checks. It is used by many web browsers to check web fonts before using them; fonts which fail such checks are blocked by browsers.
This check runs OTS on the font and reports any errors or warnings that it finds.
ttx_roundtrip
One way of testing whether or not fonts are well-formed at the binary level is to convert them to TTX and then back to binary. Structural problems within the binary font will show up as errors during conversion. This is not necessarily something that a designer will be able to address but is evidence of a potential bug in the font compiler used to generate the binary.
googlefonts/metadata/includes_production_subsets
Check METADATA.pb file includes the same subsets as the family in production.
googlefonts/glyphsets/shape_languages
This check uses a heuristic to determine which GF glyphsets a font supports. Then it checks the font for correct shaping behaviour for all languages in those glyphsets.
googlefonts/axes_match
An updated font family must include the same axes found in the Google " Fonts version, with the same axis ranges.
Failed with JSONDecodeError: Expecting value: line 1 column 1 (char 0)
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 152, in _get_check_dependencies val = bool(self._get(name, identity.iterargs, condition=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 134, in _get return getattr(specific_thing, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 371, in remote_style remote_styles = font.remote_styles ^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 333, in remote_styles if not font.context.network or not font.listed_on_gfonts_api: ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 254, in listed_on_gfonts_api for item in font.context.production_metadata["familyMetadataList"]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 487, in production_metadata return requests.get(meta_url, timeout=context.config.get("timeout")).json() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/requests/models.py", line 978, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
googlefonts/cjk_vertical_metrics
CJK fonts have different vertical metrics when compared to Latin fonts. We follow the schema developed by dr Ken Lunde for Source Han Sans and the Noto CJK fonts.
Our documentation includes further information: https://github.com/googlefonts/gf-docs/tree/main/Spec#cjk-vertical-metrics
Failed with JSONDecodeError: Expecting value: line 1 column 1 (char 0)
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 152, in _get_check_dependencies val = bool(self._get(name, identity.iterargs, condition=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 134, in _get return getattr(specific_thing, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 254, in listed_on_gfonts_api for item in font.context.production_metadata["familyMetadataList"]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 487, in production_metadata return requests.get(meta_url, timeout=context.config.get("timeout")).json() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/requests/models.py", line 978, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
googlefonts/cjk_vertical_metrics_regressions
Check CJK family has the same vertical metrics as the same family hosted on Google Fonts.
Failed with JSONDecodeError: Expecting value: line 1 column 1 (char 0)
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 152, in _get_check_dependencies val = bool(self._get(name, identity.iterargs, condition=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 134, in _get return getattr(specific_thing, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 381, in regular_remote_style remote_styles = font.remote_styles ^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 333, in remote_styles if not font.context.network or not font.listed_on_gfonts_api: ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 254, in listed_on_gfonts_api for item in font.context.production_metadata["familyMetadataList"]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 487, in production_metadata return requests.get(meta_url, timeout=context.config.get("timeout")).json() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/requests/models.py", line 978, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
googlefonts/vertical_metrics
This check generally enforces Google Fonts’ vertical metrics specifications. In particular:
The threshold levels 150% (WARN) and 200% (FAIL) are somewhat arbitrarily chosen and may hint at a glaring mistake in the metrics calculations or UPM settings.
Our documentation includes further information: https://github.com/googlefonts/gf-docs/tree/main/VerticalMetrics
Failed with JSONDecodeError: Expecting value: line 1 column 1 (char 0)
File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 152, in _get_check_dependencies val = bool(self._get(name, identity.iterargs, condition=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checkrunner.py", line 134, in _get return getattr(specific_thing, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 254, in listed_on_gfonts_api for item in font.context.production_metadata["familyMetadataList"]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/functools.py", line 1001, in __get__ val = self.func(instance) ^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/fontbakery/checks/vendorspecific/googlefonts/conditions.py", line 487, in production_metadata return requests.get(meta_url, timeout=context.config.get("timeout")).json() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python3.11/site-packages/requests/models.py", line 978, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
googlefonts/vertical_metrics_regressions
If the family already exists on Google Fonts, we need to ensure that the checked family's vertical metrics are similar. This check will test the following schema which was outlined in Font Bakery issue #1162 [1]:
The family should visually have the same vertical metrics as the Regular style hosted on Google Fonts.
If the family on Google Fonts has differing hhea and typo metrics, the family being checked should use the typo metrics for both the hhea and typo entries.
If the family on Google Fonts has use typo metrics not enabled and the family being checked has it enabled, the hhea and typo metrics should use the family on Google Fonts winAscent and winDescent values.
If the upms differ, the values must be scaled so the visual appearance is the same.