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.
| 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 |
| 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.