quran-qcf4
v1.1.0
Published
Developer-friendly Quran database using QCF v4 (King Fahd Complex Font) with Hafs recitation — includes fonts, page JSON, verse index, and font map.
Maintainers
Readme
QCF4 Quran Database
▶ Live Demo · Renders any Mushaf page in the browser using QCF4 fonts via CDN.
🔤 QBSML Glyph Viewer · Browse every decoded surah/juz header and ornament glyph from the QBSML font.
A developer-friendly Quran database using QCF v4 (Quran Complex Font, version 4) glyph rendering for the Hafs recitation.
About QCF4
QCF4 is a new, previously unpublished Quranic font based on the Madinah Mushaf (1441 AH), written by the calligrapher Uthman Taha and produced by the King Fahd Complex in Madinah.
It is an improved and modern edition of the second Madinah font (QCF2, 2013), with the following enhancements:
- Improved quality of letter shapes and diacritical marks
- Removal of whitespace gaps between words
- Reduced font file count to just 47 files (down from 604 in QCF1/QCF2 which required one font per page)
- Updated verse-end marker design
خط قرآن مصحف المدينة النبوية ١٤٤١هـ الإصدار الرابع — رواية حفص عن عاصم. عُثمان طه. مُجمّع الملك فهد — QCF4
Font version by Ahmad ElGharib — Telegram Channel
What's Included
├── pages/ # 604 JSON files (one per Mushaf page)
│ ├── 001.json
│ ├── 002.json
│ └── ...
├── fonts/ # 47 QCF4 Hafs font files + BSML header font
│ ├── QCF4_Hafs_01_W.ttf
│ ├── QCF4_Hafs_02_W.ttf
│ ├── ...
│ └── QCF4_QBSML.ttf
├── fonts-woff2/ # 47 QCF4 Hafs woff2 font files + BSML header font
│ ├── QCF4_Hafs_01_W.woff2
│ ├── QCF4_Hafs_02_W.woff2
│ ├── ...
│ └── QCF4_QBSML.woff2
├── index.json # Master index with chapter metadata
├── verses.json # Verse-key → page/line lookup index
├── font-map.json # Page number → font name mapping
└── qbsml.json # Decoded glyph set for the QBSML surah/juz-header fontPage JSON Schema
Each pages/NNN.json file represents one Mushaf page:
{
"page": 1,
"font": "QCF4_Hafs_01",
"surahs": [
{
"id": 1,
"name": "Al-Fatihah",
"name_arabic": "الفاتحة",
"verse_start": 1,
"verse_end": 7
}
],
"lines": [
{
"line": 1,
"words": [
{
"code": 61696,
"char": "\uF100",
"font": "QCF4_QBSML",
"text": "سُورَةُ الفَاتِحَةِ",
"type": "surah_header",
"sura": 1
}
]
},
{
"line": 2,
"words": [
{
"code": 61696,
"char": "\uF100",
"font": "QCF4_Hafs_01",
"text": "بِسْمِ",
"type": "word",
"verse_key": "1:1",
"position": 1
},
...
]
}
]
}Word Types
| Type | Description |
|------|-------------|
| word | Quranic word — has verse_key and position |
| end | Verse-end marker (circled number) — has verse_key and position |
| surah_header | Surah title banner — has sura, uses QCF4_QBSML font |
| bismillah | Bismillah glyph — has sura, uses QCF4_Hafs_01 font |
| quarter | Quarter-hizb marker (۞) |
Verse Index (verses.json)
Quick lookup to find any verse by key:
{
"1:1": {
"page": 1,
"lines": [
{ "line": 2, "word_start": 1, "word_end": 5 }
]
},
"2:255": {
"page": 42,
"lines": [
{ "line": 6, "word_start": 1, "word_end": 8 },
{ "line": 7, "word_start": 9, "word_end": 19 },
{ "line": 8, "word_start": 20, "word_end": 28 }
]
}
}A verse can span multiple lines. Each entry tells you which page, which lines, and the word positions on each line.
Font Map (font-map.json)
Maps each page number to its font name:
{
"1": "QCF4_Hafs_01",
"2": "QCF4_Hafs_01",
...
"604": "QCF4_Hafs_47"
}QBSML Glyph Set (qbsml.json)
QCF4_QBSML.ttf is a second, small font (separate from the 47 QCF4_Hafs_NN
page fonts) used only for surah headers, juz' headers, the Bismillah, and
opening-page ornaments — the same font referenced by surah_header and
bismillah words in the page JSON (see Word Types above).
qbsml.json documents every non-empty glyph in that font: which Unicode PUA
code point it lives at, and what it renders (a surah name, a juz' label, a
Bismillah word-part, etc). It's most useful if you want to render a surah or
juz' header standalone, without loading a full page.
{
"font": "QCF4_QBSML",
"description": "Deciphered glyph sets in the QCF4 Bismillah/surah-header font (QBSML)...",
"total_glyphs_in_font": 2564,
"non_empty_glyphs_investigated": 532,
"sets": [
{
"name": "surah_headers_style_a",
"label": "Surah name headers — Style A (spaced)",
"codepoint_range": "0xF100-0xF171",
"count": 114,
"entries": [
{
"sura": 1,
"name_arabic": "الفاتحة",
"name_en": "Al-Fatihah",
"codepoint": 61696,
"hex": "F100",
"char": "\uf100",
"glyph_name": "glyph4",
"advance_width": 7665,
"bbox": [-3, -806, 7667, 1414]
}
]
}
]
}There are 7 sets in total:
| Set | Count | Contents |
|---|---|---|
| surah_headers_style_a | 114 | One glyph per surah name, normally-kerned |
| surah_headers_style_a_merged | 98 | Short surah names sharing a glyph, Style A |
| juz_headers_style_a | 30 | One glyph per juz' (para) label, Style A |
| surah_headers_style_b | 114 | Same 114 surah names, tighter/compact kerning |
| surah_headers_style_b_merged | 98 | Short surah names sharing a glyph, Style B |
| juz_headers_style_b | 30 | One glyph per juz' label, Style B |
| opening_matter_and_ornaments | 48 | Bismillah word-parts, Isti'adhah, and decorative ornaments |
Style A and Style B are two complete, interchangeable renderings of the same
114 surah names / 30 juz' labels — Style A uses normal letter spacing, Style
B is tighter/more compact. Corresponding Style B glyphs sit exactly 0xF8
code points above their Style A counterpart (e.g. surah 1 Style A is
0xF100, Style B is 0xF1F8), so you can compute one from the other without
a lookup table if you need to.
The font has no GSUB/ligature table — every code point maps straight to one
precomposed glyph, so no OpenType shaping engine is required to render these
correctly; a plain font-family + character is enough.
Render any entry the same way you'd render a page word — set
font-family: "QCF4_QBSML" and write out String.fromCodePoint(entry.codepoint)
(or the char field directly).
How to Render
1. Load the Font
Each page uses one main font. Load it via CSS @font-face:
@font-face {
font-family: "QCF4_Hafs_01";
src: url("fonts/QCF4_Hafs_01_W.ttf");
}
@font-face {
font-family: "QCF4_QBSML";
src: url("fonts/QCF4_QBSML.ttf");
}2. Render Words
Each word has a char field containing the Unicode character that maps to the correct glyph in the font:
<span style="font-family: 'QCF4_Hafs_01'; font-size: 28px;"></span>Or using JavaScript:
const span = document.createElement("span");
span.style.fontFamily = word.font;
span.textContent = word.char;3. Layout
Words are organized by lines as they appear on the physical Mushaf page. Render each line as a row (RTL direction), and each word as an inline element within that row.
CDN Usage (No Install Required)
You can use the data and fonts directly via jsDelivr — no npm install needed:
<!-- Load a font -->
<style>
@font-face {
font-family: "QCF4_Hafs_01";
src: url("https://cdn.jsdelivr.net/gh/MohamadHajjRabee/quran-qcf4@main/fonts-woff2/QCF4_Hafs_01_W.woff2");
}
</style>// Fetch page data
const page = await fetch(
"https://raw.githubusercontent.com/MohamadHajjRabee/quran-qcf4/main/pages/001.json"
).then(r => r.json());Note: Use
raw.githubusercontent.comfor JSON data (always up to date) andcdn.jsdelivr.netfor font files (cached for performance).
Index (index.json)
Contains metadata for all 114 chapters:
{
"meta": {
"schema_version": "1.0.0",
"total_pages": 604,
"total_chapters": 114,
"total_verses": 6236,
"font_count": 47
},
"chapters": [
{
"id": 1,
"name": "Al-Fatihah",
"name_arabic": "الفاتحة",
"revelation_place": "makkah",
"revelation_order": 5,
"bismillah_pre": false,
"verses_count": 7,
"pages": [1, 1],
"translated_name": "The Opener"
}
]
}Credits
- QCF4 Fonts: Madinah Mushaf 1441 AH, calligraphy by Uthman Taha, produced by the King Fahd Quran Complex (مُجمّع الملك فهد لطباعة المصحف الشريف). QCF4 font version by Ahmad ElGharib — Telegram Channel
- Chapter metadata: Derived from Quran.com open data
- QBSML glyph decoding (
qbsml.json,qbsml.html): Contributed by [b-acksla-sh](https://github.com/ b-acksla-sh)
License
The font files are provided for Quranic rendering purposes. Please respect the original creator's terms of use.
