Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix arabic_high_hamza check #4981

Merged
merged 4 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ A more detailed list of changes is available in the corresponding milestones for
### Changes to existing checks
### On the Universal profile.
- **[no_debugging_tables]** and **[vttclean]** are now merged into unwanted_tables. (issues #4972 and #4975)
- **[arabic_high_hamza]** now checks U+0674 ARABIC LETTER HIGH HAMZA and not U+0675 ARABIC LETTER HIGH HAMZA ALEF, and the size check of _high hamza_ is now a warning instead of a fauilre. (issue #4290)

### On the OpenType Profile
- **[opentype/slant_direction]:** SKIP instead of ERROR if a font does not contain 'H' (PR #4969)
Expand Down
60 changes: 32 additions & 28 deletions Lib/fontbakery/checks/arabic_high_hamza.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fontbakery.prelude import FAIL, SKIP, Message, check
from fontbakery.prelude import FAIL, SKIP, WARN, Message, check
from fontbakery.utils import get_glyph_name


Expand All @@ -8,10 +8,10 @@
"https://github.com/googlefonts/fontbakery/issues/4290",
],
rationale="""
Many fonts incorrectly treat ARABIC LETTER HIGH HAMZA (U+0675) as a variant of
Many fonts incorrectly treat ARABIC LETTER HIGH HAMZA (U+0674) as a variant of
ARABIC HAMZA ABOVE (U+0654) and make it a combining mark of the same size.

But U+0675 is a base letter and should be a variant of ARABIC LETTER HAMZA
But U+0674 is a base letter and should be a variant of ARABIC LETTER HAMZA
(U+0621) but raised slightly above baseline.

Not doing so effectively makes the font useless for Jawi and
Expand All @@ -20,37 +20,41 @@
severity=4,
)
def check_arabic_high_hamza(ttFont):
"""Check that glyph for U+0675 ARABIC LETTER HIGH HAMZA is not a mark."""
"""Check that glyph for U+0674 ARABIC LETTER HIGH HAMZA is not a mark."""
from fontTools.pens.areaPen import AreaPen
from copy import deepcopy

# This check modifies the font file with `.draw(pen)`
# so here we'll work with a copy of the object so that we
# do not affect other checks:
ttFont_copy = deepcopy(ttFont)

ARABIC_LETTER_HAMZA = 0x0621
ARABIC_LETTER_HIGH_HAMZA = 0x0675
ARABIC_LETTER_HIGH_HAMZA = 0x0674

cmap = ttFont_copy.getBestCmap()
if ARABIC_LETTER_HAMZA not in cmap or ARABIC_LETTER_HIGH_HAMZA not in cmap:
cmap = ttFont.getBestCmap()
if ARABIC_LETTER_HIGH_HAMZA not in cmap:
yield SKIP, Message(
"glyphs-missing",
"This check will only run on fonts that have both glyphs U+0621 and U+0675",
"This check will only run on fonts that have U+0674 glyph",
)
return

if "GDEF" in ttFont_copy and ttFont_copy["GDEF"].table.GlyphClassDef:
class_def = ttFont_copy["GDEF"].table.GlyphClassDef.classDefs
reverseCmap = ttFont_copy["cmap"].buildReversed()
glyphOrder = ttFont_copy.getGlyphOrder()
for name in glyphOrder:
if ARABIC_LETTER_HIGH_HAMZA in reverseCmap.get(name, set()):
if name in class_def and class_def[name] == 3:
yield FAIL, Message(
"mark-in-gdef",
f'"{name}" is defined in GDEF as a mark (class 3).',
)
if "GDEF" in ttFont and ttFont["GDEF"].table.GlyphClassDef:
class_def = ttFont["GDEF"].table.GlyphClassDef.classDefs
name = get_glyph_name(ttFont, ARABIC_LETTER_HIGH_HAMZA)
if name in class_def and class_def[name] == 3:
yield FAIL, Message(
"mark-in-gdef",
f'"{name}" is defined in GDEF as a mark (class 3).',
)

if ARABIC_LETTER_HAMZA not in cmap:
yield SKIP, Message(
"glyphs-missing",
"This check will only run on fonts that have both glyphs U+0621 and U+0674",
)
return

# This check modifies the font file with `.draw(pen)`
# so here we'll work with a copy of the object so that we
# do not affect other checks:
ttFont_copy = deepcopy(ttFont)

# Also validate the bounding box of the glyph and compare
# it to U+0621 expecting them to have roughly the same size
Expand All @@ -66,9 +70,9 @@ def check_arabic_high_hamza(ttFont):
high_hamza_area = area_pen.value

if abs((high_hamza_area - hamza_area) / hamza_area) > 0.1:
yield FAIL, Message(
yield WARN, Message(
"glyph-area",
"The arabic letter high hamza (U+0675) should have roughly"
" the same size the arabic letter hamza (U+0621),"
" but a different glyph outline area was detected.",
"The arabic letter high hamza (U+0674) should have roughly"
" the same size the arabic letter hamza (U+0621) while raised"
" above baseline, but a different glyph outline area was detected.",
)