Font library · coverage and rendering measured

Rendering and coverage

What each of the 57 Arabic families actually contains, and what the browser actually does with it. Coverage comes from each file's own character map; joining, the zero-width non-joiner, kashida and marks come from drawing the file in Chromium 156. Both are facts about a file, not opinions about a typeface.

A word on what this table is for. “Free Arabic font” is a claim about licensing, not about coverage: a family can be OFL, ship an arabic subset, and still have no kashida, no Quranic marks, or no Persian letters. Those absences do not matter to a Latin UI with one Arabic heading. They matter a great deal to a Persian interface form, an Urdu newspaper, or a Quranic reader — and until they are measured, the person choosing the font finds out in production.

Rendering drawn in Chromium 156 on 2026-10-27; coverage read from each file's character map on 2026-10-27. Printed as two tables rather than one eleven-column table, which on a phone is a scroll box with a header somewhere off to the right. On a narrow screen each table scrolls sideways and the family column stays put.

Rendering, drawn in HeadlessChrome/156.0.0.0
family joins (lam-alef) ZWNJ between two letters kashida (tatweel) marks above the baseline
Alan Sans shapes 0.64 honoured drawn raised
Alexandria shapes 0.705 honoured drawn raised
Alkalami shapes 0.846 honoured drawn raised
Almarai shapes 0.664 honoured drawn raised
Alyamama shapes 0.63 honoured drawn raised
Amiri shapes 0.783 honoured drawn raised
Amiri Quran shapes 0.783 honoured drawn raised
Aref Ruqaa inconclusive 0.934 honoured inconclusive raised
Aref Ruqaa Ink inconclusive 0.934 honoured inconclusive raised
Badeen Display shapes 0.677 honoured drawn raised
Baloo Bhaijaan 2 shapes 0.591 honoured drawn raised
Beiruti shapes 0.729 honoured drawn raised
Blaka shapes 0.816 honoured no kashida raised
Blaka Hollow shapes 0.816 honoured no kashida raised
Blaka Ink shapes 0.816 honoured no kashida raised
Cairo shapes 0.689 honoured drawn raised
Cairo Play shapes 0.689 honoured drawn raised
Cascadia Code shapes 0.5 honoured drawn raised
Cascadia Mono shapes 0.5 inconclusive drawn raised
Changa shapes 0.673 honoured drawn raised
El Messiri shapes 0.699 honoured drawn raised
Estedad shapes 0.597 honoured drawn raised
Fustat shapes 0.724 honoured drawn raised
Gulzar shapes 0.456 honoured no kashida raised
Handjet shapes 0.727 honoured drawn raised
Harmattan shapes 0.609 honoured drawn raised
IBM Plex Sans Arabic shapes 0.589 honoured drawn raised
Jomhuria shapes 0.596 honoured drawn raised
Katibeh shapes 0.695 honoured drawn raised
Kufam shapes 0.678 honoured drawn raised
Lalezar shapes 0.546 honoured drawn raised
Lateef shapes 0.894 honoured drawn raised
Lemonada shapes 0.688 honoured drawn raised
Mada shapes 0.555 honoured drawn raised
Marhey shapes 0.7 honoured drawn raised
Markazi Text shapes 0.686 honoured drawn raised
Mirza shapes 0.627 honoured drawn raised
Noto Kufi Arabic shapes 0.691 honoured drawn raised
Noto Naskh Arabic shapes 0.622 honoured drawn raised
Noto Nastaliq Urdu shapes 0.425 honoured inconclusive raised
Noto Sans Arabic shapes 0.624 honoured drawn raised
Oi shapes 0.615 honoured drawn raised
Parastoo shapes 0.673 honoured drawn raised
Playpen Sans Arabic shapes 0.655 honoured drawn raised
Qahiri shapes 0.655 honoured drawn raised
Rakkas shapes 0.899 honoured drawn raised
Readex Pro shapes 0.517 honoured drawn raised
Reem Kufi shapes 0.507 honoured drawn raised
Reem Kufi Fun shapes 0.507 honoured drawn raised
Reem Kufi Ink shapes 0.507 honoured drawn raised
Rubik shapes 0.616 honoured drawn raised
Ruwudu shapes 0.603 honoured drawn raised
Scheherazade New shapes 0.769 honoured drawn raised
Tajawal shapes 0.663 honoured drawn raised
Vazirmatn shapes 0.652 honoured drawn raised
Vibes inconclusive 0.937 honoured drawn raised
Zain shapes 0.615 honoured drawn raised
Coverage, read from the cmap. Tatweel, both digit sets, the superscript alef and ZWJ are counted on each specimen page.
family missing letters Persian Urdu letters harakat Quranic
Alan Sans none +29 other chars 4/4 6/6 36/41 8/8 0/24
Alexandria none +29 other chars 4/4 6/6 36/41 8/8 0/24
Alkalami چٹڈڑھ +35 other chars 3/4 2/6 37/41 8/8 3/24
Almarai none +29 other chars 4/4 6/6 36/41 8/8 0/24
Alyamama none +28 other chars 4/4 6/6 36/41 8/8 1/24
Amiri none 4/4 6/6 41/41 8/8 24/24
Amiri Quran پچژگٹڈڑےھ +5 other chars 0/4 1/6 36/41 8/8 24/24
Aref Ruqaa none +28 other chars 4/4 6/6 36/41 8/8 1/24
Aref Ruqaa Ink none +28 other chars 4/4 6/6 36/41 8/8 1/24
Badeen Display none +29 other chars 4/4 6/6 36/41 8/8 0/24
Baloo Bhaijaan 2 none +29 other chars 4/4 6/6 36/41 8/8 0/24
Beiruti none +29 other chars 4/4 6/6 36/41 8/8 0/24
Blaka none +31 other chars 4/4 6/6 36/41 8/8 0/24
Blaka Hollow none +31 other chars 4/4 6/6 36/41 8/8 0/24
Blaka Ink none +31 other chars 4/4 6/6 36/41 8/8 0/24
Cairo none +29 other chars 4/4 6/6 36/41 8/8 0/24
Cairo Play none +29 other chars 4/4 6/6 36/41 8/8 0/24
Cascadia Code none +20 other chars 4/4 6/6 41/41 8/8 4/24
Cascadia Mono none +20 other chars 4/4 6/6 41/41 8/8 4/24
Changa none +29 other chars 4/4 6/6 36/41 8/8 0/24
El Messiri none +29 other chars 4/4 6/6 36/41 8/8 0/24
Estedad none 4/4 6/6 41/41 8/8 24/24
Fustat none +24 other chars 4/4 6/6 41/41 8/8 0/24
Gulzar none +29 other chars 4/4 6/6 36/41 8/8 1/24
Handjet none +29 other chars 4/4 6/6 36/41 8/8 0/24
Harmattan none 4/4 6/6 41/41 8/8 24/24
IBM Plex Sans Arabic none 4/4 6/6 41/41 8/8 24/24
Jomhuria none 4/4 6/6 41/41 8/8 24/24
Katibeh none +1 other chars 4/4 6/6 41/41 8/8 23/24
Kufam none +22 other chars 4/4 6/6 41/41 8/8 2/24
Lalezar none +28 other chars 4/4 6/6 36/41 8/8 1/24
Lateef none 4/4 6/6 41/41 8/8 24/24
Lemonada none +29 other chars 4/4 6/6 36/41 8/8 0/24
Mada none 4/4 6/6 41/41 8/8 24/24
Marhey none +29 other chars 4/4 6/6 36/41 8/8 0/24
Markazi Text none +29 other chars 4/4 6/6 36/41 8/8 0/24
Mirza none +1 other chars 4/4 6/6 41/41 8/8 23/24
Noto Kufi Arabic none 4/4 6/6 41/41 8/8 24/24
Noto Naskh Arabic none 4/4 6/6 41/41 8/8 24/24
Noto Nastaliq Urdu none +19 other chars 4/4 6/6 41/41 8/8 5/24
Noto Sans Arabic none 4/4 6/6 41/41 8/8 24/24
Oi none +29 other chars 4/4 6/6 36/41 8/8 0/24
Parastoo ٹڈڑے +29 other chars 4/4 2/6 36/41 8/8 0/24
Playpen Sans Arabic none +28 other chars 4/4 6/6 36/41 8/8 1/24
Qahiri none +29 other chars 4/4 6/6 36/41 8/8 0/24
Rakkas none +27 other chars 4/4 6/6 36/41 8/8 2/24
Readex Pro پچژگٹڈڑےھ +39 other chars 0/4 1/6 36/41 8/8 0/24
Reem Kufi none +27 other chars 4/4 6/6 36/41 8/8 2/24
Reem Kufi Fun none +27 other chars 4/4 6/6 36/41 8/8 2/24
Reem Kufi Ink none +27 other chars 4/4 6/6 36/41 8/8 2/24
Rubik ٹڈڑےھ +29 other chars 4/4 1/6 36/41 8/8 0/24
Ruwudu چٹڈڑھ +35 other chars 3/4 2/6 37/41 8/8 3/24
Scheherazade New none 4/4 6/6 41/41 8/8 24/24
Tajawal چژگٹڈڑںےھ +39 other chars 1/4 0/6 36/41 8/8 0/24
Vazirmatn none +24 other chars 4/4 6/6 37/41 8/8 4/24
Vibes ٹڈڑےھ +29 other chars 4/4 1/6 36/41 8/8 0/24
Zain none +28 other chars 4/4 6/6 36/41 8/8 1/24

How this was measured

Coverage is the cmap table of the exact WOFF2 file the specimen pages set — the file whose size the library counts, read offline with fontTools 4.66.0. The character groups are fixed and named: the Arabic letters block U+0621–U+064A, the four Persian additions, the six Urdu additions, tatweel, ZWNJ and ZWJ, both digit sets, the eight harakat, the superscript alef, and the Quranic marks U+06D6–U+06ED. A family missing one of those is missing a character, which is all the table claims.

Rendering is drawn, not inferred. Each family is declared with its own file, then four pairs of strings are measured with the browser's canvas text metrics at 160px: لا against ل plus ا for the lam-alef ligature, بب against ب‌ب for ZWNJ, بب against بـب for kashida, and a vocalised word against a bare one for marks. A ratio under 0.9 means the ligature was formed; a difference under 1px is reported as inconclusive rather than rounded into a yes.

Run twice, the probe returns the same number for every family — 57 ratios, largest difference 0.0000 — so the families sitting a few thousandths either side of 0.9 are there by measurement rather than by noise. The date and browser version below belong to that pair of runs.

Three limits, stated rather than glossed. One browser. These numbers come from Chromium 156 on Linux; Safari and Firefox ship different shapers and can legitimately disagree. One platform. Canvas metrics include the font file and the browser's layout, not the operating system's text rasteriser. Nothing here judges design. Whether the joins look right, whether the kashida is drawn well, whether the marks sit at a comfortable height: those need eyes on a page, and this table has none of them. It says what is present and what happened when it was drawn.

Two characters are counted but never scored. ZWNJ and ZWJ are control characters with no glyph, so their absence from a cmap is normal and says nothing; whether the shaper honours them is the ZWNJ column, which is drawn. The same reasoning keeps a missing glyph out of a rendering verdict: if a file has no kashida, the column says “no kashida” instead of measuring the system font that would have been substituted.

Reproduce it: /usr/bin/python3 scripts/probe-coverage.py then node scripts/probe-rendering.mjs. Both run offline against the cached WOFF2 files and rewrite src/data/coverage.json and src/data/rendering.json. If the cache is empty, the scripts say which families they could not read instead of skipping them quietly.