cadmus_core/font/
mod.rs

1mod freetype_sys;
2mod harfbuzz_sys;
3
4use self::freetype_sys::*;
5use self::harfbuzz_sys::*;
6
7use crate::color::Color;
8use crate::device::CURRENT_DEVICE;
9use crate::framebuffer::Framebuffer;
10use crate::geom::{Point, Vec2};
11use crate::helpers::IsHidden;
12use anyhow::{format_err, Error};
13use bitflags::bitflags;
14use fxhash::FxHashMap;
15use globset::Glob;
16use lazy_static::lazy_static;
17use std::collections::BTreeSet;
18use std::ffi::{CStr, CString};
19use std::os::unix::ffi::OsStrExt;
20use std::path::Path;
21use std::path::PathBuf;
22use std::ptr;
23use std::rc::Rc;
24use std::slice;
25use std::str;
26use thiserror::Error;
27use tracing::{error, warn};
28use walkdir::WalkDir;
29
30// Font sizes in 1/64th of a point
31pub const FONT_SIZES: [u32; 3] = [349, 524, 629];
32
33pub const KEYBOARD_FONT_SIZES: [u32; 2] = [337, 843];
34
35pub const DISPLAY_FONT_SIZE: u32 = 2516;
36
37pub const NORMAL_STYLE: Style = Style {
38    family: Family::SansSerif,
39    variant: Variant::REGULAR,
40    size: FONT_SIZES[1],
41};
42
43pub const SPECIAL_STYLE: Style = Style {
44    family: Family::SansSerif,
45    variant: Variant::ITALIC,
46    size: FONT_SIZES[1],
47};
48
49pub const KBD_CHAR: Style = Style {
50    family: Family::Keyboard,
51    variant: Variant::REGULAR,
52    size: KEYBOARD_FONT_SIZES[1],
53};
54
55pub const KBD_LABEL: Style = Style {
56    family: Family::Keyboard,
57    variant: Variant::REGULAR,
58    size: FONT_SIZES[0],
59};
60
61pub const DISPLAY_STYLE: Style = Style {
62    family: Family::Display,
63    variant: Variant::REGULAR,
64    size: DISPLAY_FONT_SIZE,
65};
66
67lazy_static! {
68    pub static ref MD_TITLE: Style = {
69        // Compute the ratio between the physical width of the
70        // current device and that of the Aura ONE.
71        let ratio = (CURRENT_DEVICE.dims.0 as f32 * 300.0) /
72                    (CURRENT_DEVICE.dpi as f32 * 1404.0);
73        let size = ((FONT_SIZES[2] as f32 * ratio) as u32).clamp(FONT_SIZES[1],
74                                                                 FONT_SIZES[2]);
75        Style {
76            family: Family::Serif,
77            variant: Variant::ITALIC,
78            size,
79        }
80    };
81}
82
83pub const MD_AUTHOR: Style = Style {
84    family: Family::Serif,
85    variant: Variant::REGULAR,
86    size: FONT_SIZES[1],
87};
88
89pub const MD_YEAR: Style = NORMAL_STYLE;
90
91pub const MD_KIND: Style = Style {
92    family: Family::SansSerif,
93    variant: Variant::BOLD,
94    size: FONT_SIZES[0],
95};
96
97pub const MD_SIZE: Style = Style {
98    family: Family::SansSerif,
99    variant: Variant::REGULAR,
100    size: FONT_SIZES[0],
101};
102
103#[cfg(any(not(target_os = "linux"), target_arch = "arm"))]
104#[link(name = "mupdf")]
105extern "C" {
106    // Based on the outputs of:
107    // arm-linux-gnueabihf-readelf -Ws ./libs/libmupdf.so | grep '\b_binary_' | \
108    // grep -v '_size$' | awk '{print $8, strtonum($3)-1}' | sort -u
109    pub static _binary_DroidSansFallback_ttf: [libc::c_uchar; 3556308];
110    pub static _binary_NotoEmoji_Regular_ttf: [libc::c_uchar; 418804];
111    pub static _binary_NotoMusic_Regular_otf: [libc::c_uchar; 60812];
112    pub static _binary_NotoNaskhArabic_Regular_otf: [libc::c_uchar; 119664];
113    pub static _binary_NotoNastaliqUrdu_Regular_otf: [libc::c_uchar; 373220];
114    pub static _binary_NotoSans_Regular_otf: [libc::c_uchar; 290336];
115    pub static _binary_NotoSansAdlam_Regular_otf: [libc::c_uchar; 33448];
116    pub static _binary_NotoSansAnatolianHieroglyphs_Regular_otf: [libc::c_uchar; 134420];
117    pub static _binary_NotoSansAvestan_Regular_otf: [libc::c_uchar; 9300];
118    pub static _binary_NotoSansBamum_Regular_otf: [libc::c_uchar; 103668];
119    pub static _binary_NotoSansBassaVah_Regular_otf: [libc::c_uchar; 6300];
120    pub static _binary_NotoSansBatak_Regular_otf: [libc::c_uchar; 11108];
121    pub static _binary_NotoSansBhaiksuki_Regular_otf: [libc::c_uchar; 121620];
122    pub static _binary_NotoSansBrahmi_Regular_otf: [libc::c_uchar; 29544];
123    pub static _binary_NotoSansBuginese_Regular_otf: [libc::c_uchar; 6256];
124    pub static _binary_NotoSansBuhid_Regular_otf: [libc::c_uchar; 5076];
125    pub static _binary_NotoSansCanadianAboriginal_Regular_otf: [libc::c_uchar; 38068];
126    pub static _binary_NotoSansCarian_Regular_otf: [libc::c_uchar; 5592];
127    pub static _binary_NotoSansCaucasianAlbanian_Regular_otf: [libc::c_uchar; 17388];
128    pub static _binary_NotoSansChakma_Regular_otf: [libc::c_uchar; 29488];
129    pub static _binary_NotoSansCham_Regular_otf: [libc::c_uchar; 21224];
130    pub static _binary_NotoSansCherokee_Regular_otf: [libc::c_uchar; 57308];
131    pub static _binary_NotoSansChorasmian_Regular_otf: [libc::c_uchar; 12460];
132    pub static _binary_NotoSansCoptic_Regular_otf: [libc::c_uchar; 21380];
133    pub static _binary_NotoSansCuneiform_Regular_otf: [libc::c_uchar; 416308];
134    pub static _binary_NotoSansCypriot_Regular_otf: [libc::c_uchar; 7024];
135    pub static _binary_NotoSansCyproMinoan_Regular_otf: [libc::c_uchar; 8568];
136    pub static _binary_NotoSansDeseret_Regular_otf: [libc::c_uchar; 9016];
137    pub static _binary_NotoSansDuployan_Regular_otf: [libc::c_uchar; 10276];
138    pub static _binary_NotoSansEgyptianHieroglyphs_Regular_otf: [libc::c_uchar; 362960];
139    pub static _binary_NotoSansElbasan_Regular_otf: [libc::c_uchar; 8684];
140    pub static _binary_NotoSansElymaic_Regular_otf: [libc::c_uchar; 7620];
141    pub static _binary_NotoSansGlagolitic_Regular_otf: [libc::c_uchar; 17176];
142    pub static _binary_NotoSansGothic_Regular_otf: [libc::c_uchar; 5416];
143    pub static _binary_NotoSansGunjalaGondi_Regular_otf: [libc::c_uchar; 32372];
144    pub static _binary_NotoSansHanifiRohingya_Regular_otf: [libc::c_uchar; 16576];
145    pub static _binary_NotoSansHanunoo_Regular_otf: [libc::c_uchar; 6596];
146    pub static _binary_NotoSansHatran_Regular_otf: [libc::c_uchar; 4324];
147    pub static _binary_NotoSansImperialAramaic_Regular_otf: [libc::c_uchar; 5436];
148    pub static _binary_NotoSansInscriptionalPahlavi_Regular_otf: [libc::c_uchar; 5464];
149    pub static _binary_NotoSansInscriptionalParthian_Regular_otf: [libc::c_uchar; 6788];
150    pub static _binary_NotoSansJavanese_Regular_otf: [libc::c_uchar; 86944];
151    pub static _binary_NotoSansKaithi_Regular_otf: [libc::c_uchar; 39756];
152    pub static _binary_NotoSansKawi_Regular_otf: [libc::c_uchar; 30940];
153    pub static _binary_NotoSansKayahLi_Regular_otf: [libc::c_uchar; 7100];
154    pub static _binary_NotoSansKharoshthi_Regular_otf: [libc::c_uchar; 27708];
155    pub static _binary_NotoSansKhudawadi_Regular_otf: [libc::c_uchar; 14764];
156    pub static _binary_NotoSansLepcha_Regular_otf: [libc::c_uchar; 18832];
157    pub static _binary_NotoSansLimbu_Regular_otf: [libc::c_uchar; 10040];
158    pub static _binary_NotoSansLinearA_Regular_otf: [libc::c_uchar; 33640];
159    pub static _binary_NotoSansLinearB_Regular_otf: [libc::c_uchar; 36892];
160    pub static _binary_NotoSansLisu_Regular_otf: [libc::c_uchar; 5688];
161    pub static _binary_NotoSansLycian_Regular_otf: [libc::c_uchar; 4108];
162    pub static _binary_NotoSansLydian_Regular_otf: [libc::c_uchar; 4088];
163    pub static _binary_NotoSansMahajani_Regular_otf: [libc::c_uchar; 10136];
164    pub static _binary_NotoSansMandaic_Regular_otf: [libc::c_uchar; 13160];
165    pub static _binary_NotoSansManichaean_Regular_otf: [libc::c_uchar; 16496];
166    pub static _binary_NotoSansMarchen_Regular_otf: [libc::c_uchar; 69240];
167    pub static _binary_NotoSansMasaramGondi_Regular_otf: [libc::c_uchar; 23052];
168    pub static _binary_NotoSansMath_Regular_otf: [libc::c_uchar; 258796];
169    pub static _binary_NotoSansMedefaidrin_Regular_otf: [libc::c_uchar; 27060];
170    pub static _binary_NotoSansMeeteiMayek_Regular_otf: [libc::c_uchar; 13056];
171    pub static _binary_NotoSansMendeKikakui_Regular_otf: [libc::c_uchar; 19664];
172    pub static _binary_NotoSansMeroitic_Regular_otf: [libc::c_uchar; 19980];
173    pub static _binary_NotoSansMiao_Regular_otf: [libc::c_uchar; 26460];
174    pub static _binary_NotoSansModi_Regular_otf: [libc::c_uchar; 29412];
175    pub static _binary_NotoSansMongolian_Regular_otf: [libc::c_uchar; 111040];
176    pub static _binary_NotoSansMro_Regular_otf: [libc::c_uchar; 5608];
177    pub static _binary_NotoSansMultani_Regular_otf: [libc::c_uchar; 7852];
178    pub static _binary_NotoSansNabataean_Regular_otf: [libc::c_uchar; 6448];
179    pub static _binary_NotoSansNagMundari_Regular_otf: [libc::c_uchar; 8612];
180    pub static _binary_NotoSansNandinagari_Regular_otf: [libc::c_uchar; 86940];
181    pub static _binary_NotoSansNewa_Regular_otf: [libc::c_uchar; 99568];
182    pub static _binary_NotoSansNewTaiLue_Regular_otf: [libc::c_uchar; 10884];
183    pub static _binary_NotoSansNKo_Regular_otf: [libc::c_uchar; 15164];
184    pub static _binary_NotoSansNushu_Regular_otf: [libc::c_uchar; 72472];
185    pub static _binary_NotoSansOgham_Regular_otf: [libc::c_uchar; 3720];
186    pub static _binary_NotoSansOlChiki_Regular_otf: [libc::c_uchar; 7024];
187    pub static _binary_NotoSansOldHungarian_Regular_otf: [libc::c_uchar; 44628];
188    pub static _binary_NotoSansOldItalic_Regular_otf: [libc::c_uchar; 6360];
189    pub static _binary_NotoSansOldNorthArabian_Regular_otf: [libc::c_uchar; 6132];
190    pub static _binary_NotoSansOldPermic_Regular_otf: [libc::c_uchar; 8512];
191    pub static _binary_NotoSansOldPersian_Regular_otf: [libc::c_uchar; 9856];
192    pub static _binary_NotoSansOldSogdian_Regular_otf: [libc::c_uchar; 12260];
193    pub static _binary_NotoSansOldSouthArabian_Regular_otf: [libc::c_uchar; 4624];
194    pub static _binary_NotoSansOldTurkic_Regular_otf: [libc::c_uchar; 6884];
195    pub static _binary_NotoSansOsage_Regular_otf: [libc::c_uchar; 9292];
196    pub static _binary_NotoSansOsmanya_Regular_otf: [libc::c_uchar; 6784];
197    pub static _binary_NotoSansPahawhHmong_Regular_otf: [libc::c_uchar; 13024];
198    pub static _binary_NotoSansPalmyrene_Regular_otf: [libc::c_uchar; 8480];
199    pub static _binary_NotoSansPauCinHau_Regular_otf: [libc::c_uchar; 8124];
200    pub static _binary_NotoSansPhagsPa_Regular_otf: [libc::c_uchar; 24036];
201    pub static _binary_NotoSansPhoenician_Regular_otf: [libc::c_uchar; 5288];
202    pub static _binary_NotoSansPsalterPahlavi_Regular_otf: [libc::c_uchar; 12748];
203    pub static _binary_NotoSansRejang_Regular_otf: [libc::c_uchar; 6440];
204    pub static _binary_NotoSansRunic_Regular_otf: [libc::c_uchar; 7200];
205    pub static _binary_NotoSansSamaritan_Regular_otf: [libc::c_uchar; 9024];
206    pub static _binary_NotoSansSaurashtra_Regular_otf: [libc::c_uchar; 16020];
207    pub static _binary_NotoSansSharada_Regular_otf: [libc::c_uchar; 32824];
208    pub static _binary_NotoSansShavian_Regular_otf: [libc::c_uchar; 5468];
209    pub static _binary_NotoSansSiddham_Regular_otf: [libc::c_uchar; 91992];
210    pub static _binary_NotoSansSignWriting_Regular_otf: [libc::c_uchar; 2780224];
211    pub static _binary_NotoSansSogdian_Regular_otf: [libc::c_uchar; 48356];
212    pub static _binary_NotoSansSoraSompeng_Regular_otf: [libc::c_uchar; 6332];
213    pub static _binary_NotoSansSoyombo_Regular_otf: [libc::c_uchar; 52036];
214    pub static _binary_NotoSansSundanese_Regular_otf: [libc::c_uchar; 9420];
215    pub static _binary_NotoSansSylotiNagri_Regular_otf: [libc::c_uchar; 12852];
216    pub static _binary_NotoSansSymbols_Regular_otf: [libc::c_uchar; 109696];
217    pub static _binary_NotoSansSymbols2_Regular_otf: [libc::c_uchar; 375388];
218    pub static _binary_NotoSansSyriac_Regular_otf: [libc::c_uchar; 124756];
219    pub static _binary_NotoSansTagalog_Regular_otf: [libc::c_uchar; 5500];
220    pub static _binary_NotoSansTagbanwa_Regular_otf: [libc::c_uchar; 5356];
221    pub static _binary_NotoSansTaiLe_Regular_otf: [libc::c_uchar; 8616];
222    pub static _binary_NotoSansTaiTham_Regular_otf: [libc::c_uchar; 76880];
223    pub static _binary_NotoSansTaiViet_Regular_otf: [libc::c_uchar; 12280];
224    pub static _binary_NotoSansTakri_Regular_otf: [libc::c_uchar; 17864];
225    pub static _binary_NotoSansTangsa_Regular_otf: [libc::c_uchar; 16908];
226    pub static _binary_NotoSansThaana_Regular_otf: [libc::c_uchar; 12392];
227    pub static _binary_NotoSansTifinagh_Regular_otf: [libc::c_uchar; 24776];
228    pub static _binary_NotoSansTirhuta_Regular_otf: [libc::c_uchar; 52432];
229    pub static _binary_NotoSansUgaritic_Regular_otf: [libc::c_uchar; 5048];
230    pub static _binary_NotoSansVai_Regular_otf: [libc::c_uchar; 24088];
231    pub static _binary_NotoSansWancho_Regular_otf: [libc::c_uchar; 15140];
232    pub static _binary_NotoSansWarangCiti_Regular_otf: [libc::c_uchar; 23484];
233    pub static _binary_NotoSansYi_Regular_otf: [libc::c_uchar; 92164];
234    pub static _binary_NotoSansZanabazarSquare_Regular_otf: [libc::c_uchar; 13804];
235    pub static _binary_NotoSerif_Regular_otf: [libc::c_uchar; 289412];
236    pub static _binary_NotoSerifAhom_Regular_otf: [libc::c_uchar; 14516];
237    pub static _binary_NotoSerifArmenian_Regular_otf: [libc::c_uchar; 14160];
238    pub static _binary_NotoSerifBalinese_Regular_otf: [libc::c_uchar; 32348];
239    pub static _binary_NotoSerifBengali_Regular_otf: [libc::c_uchar; 101332];
240    pub static _binary_NotoSerifDevanagari_Regular_otf: [libc::c_uchar; 169744];
241    pub static _binary_NotoSerifDivesAkuru_Regular_otf: [libc::c_uchar; 27972];
242    pub static _binary_NotoSerifDogra_Regular_otf: [libc::c_uchar; 19944];
243    pub static _binary_NotoSerifEthiopic_Regular_otf: [libc::c_uchar; 113328];
244    pub static _binary_NotoSerifGeorgian_Regular_otf: [libc::c_uchar; 31988];
245    pub static _binary_NotoSerifGrantha_Regular_otf: [libc::c_uchar; 368396];
246    pub static _binary_NotoSerifGujarati_Regular_otf: [libc::c_uchar; 64848];
247    pub static _binary_NotoSerifGurmukhi_Regular_otf: [libc::c_uchar; 26992];
248    pub static _binary_NotoSerifHebrew_Regular_otf: [libc::c_uchar; 15320];
249    pub static _binary_NotoSerifKannada_Regular_otf: [libc::c_uchar; 89032];
250    pub static _binary_NotoSerifKhitanSmallScript_Regular_otf: [libc::c_uchar; 508920];
251    pub static _binary_NotoSerifKhmer_Regular_otf: [libc::c_uchar; 40436];
252    pub static _binary_NotoSerifKhojki_Regular_otf: [libc::c_uchar; 60112];
253    pub static _binary_NotoSerifLao_Regular_otf: [libc::c_uchar; 16196];
254    pub static _binary_NotoSerifMakasar_Regular_otf: [libc::c_uchar; 5864];
255    pub static _binary_NotoSerifMalayalam_Regular_otf: [libc::c_uchar; 45668];
256    pub static _binary_NotoSerifMyanmar_Regular_otf: [libc::c_uchar; 127564];
257    pub static _binary_NotoSerifNyiakengPuachueHmong_Regular_otf: [libc::c_uchar; 12208];
258    pub static _binary_NotoSerifOldUyghur_Regular_otf: [libc::c_uchar; 15620];
259    pub static _binary_NotoSerifOriya_Regular_otf: [libc::c_uchar; 105824];
260    pub static _binary_NotoSerifSinhala_Regular_otf: [libc::c_uchar; 74924];
261    pub static _binary_NotoSerifTamil_Regular_otf: [libc::c_uchar; 33752];
262    pub static _binary_NotoSerifTelugu_Regular_otf: [libc::c_uchar; 82032];
263    pub static _binary_NotoSerifThai_Regular_otf: [libc::c_uchar; 17556];
264    pub static _binary_NotoSerifTibetan_Regular_otf: [libc::c_uchar; 334156];
265    pub static _binary_NotoSerifToto_Regular_otf: [libc::c_uchar; 5732];
266    pub static _binary_NotoSerifVithkuqi_Regular_otf: [libc::c_uchar; 42508];
267    pub static _binary_NotoSerifYezidi_Regular_otf: [libc::c_uchar; 8664];
268}
269
270#[cfg(all(target_os = "linux", not(target_arch = "arm")))]
271#[link(name = "mupdf")]
272extern "C" {
273    pub static _binary_resources_fonts_droid_DroidSansFallback_ttf_start: [libc::c_uchar; 3556308];
274    pub static _binary_resources_fonts_noto_NotoEmoji_Regular_ttf_start: [libc::c_uchar; 418804];
275    pub static _binary_resources_fonts_noto_NotoMusic_Regular_otf_start: [libc::c_uchar; 60812];
276    pub static _binary_resources_fonts_noto_NotoNaskhArabic_Regular_otf_start:
277        [libc::c_uchar; 119664];
278    pub static _binary_resources_fonts_noto_NotoNastaliqUrdu_Regular_otf_start:
279        [libc::c_uchar; 373220];
280    pub static _binary_resources_fonts_noto_NotoSans_Regular_otf_start: [libc::c_uchar; 290336];
281    pub static _binary_resources_fonts_noto_NotoSansAdlam_Regular_otf_start: [libc::c_uchar; 33448];
282    pub static _binary_resources_fonts_noto_NotoSansAnatolianHieroglyphs_Regular_otf_start:
283        [libc::c_uchar; 134420];
284    pub static _binary_resources_fonts_noto_NotoSansAvestan_Regular_otf_start:
285        [libc::c_uchar; 9300];
286    pub static _binary_resources_fonts_noto_NotoSansBamum_Regular_otf_start:
287        [libc::c_uchar; 103668];
288    pub static _binary_resources_fonts_noto_NotoSansBassaVah_Regular_otf_start:
289        [libc::c_uchar; 6300];
290    pub static _binary_resources_fonts_noto_NotoSansBatak_Regular_otf_start: [libc::c_uchar; 11108];
291    pub static _binary_resources_fonts_noto_NotoSansBhaiksuki_Regular_otf_start:
292        [libc::c_uchar; 121620];
293    pub static _binary_resources_fonts_noto_NotoSansBrahmi_Regular_otf_start:
294        [libc::c_uchar; 29544];
295    pub static _binary_resources_fonts_noto_NotoSansBuginese_Regular_otf_start:
296        [libc::c_uchar; 6256];
297    pub static _binary_resources_fonts_noto_NotoSansBuhid_Regular_otf_start: [libc::c_uchar; 5076];
298    pub static _binary_resources_fonts_noto_NotoSansCanadianAboriginal_Regular_otf_start:
299        [libc::c_uchar; 38068];
300    pub static _binary_resources_fonts_noto_NotoSansCarian_Regular_otf_start: [libc::c_uchar; 5592];
301    pub static _binary_resources_fonts_noto_NotoSansCaucasianAlbanian_Regular_otf_start:
302        [libc::c_uchar; 17388];
303    pub static _binary_resources_fonts_noto_NotoSansChakma_Regular_otf_start:
304        [libc::c_uchar; 29488];
305    pub static _binary_resources_fonts_noto_NotoSansCham_Regular_otf_start: [libc::c_uchar; 21224];
306    pub static _binary_resources_fonts_noto_NotoSansCherokee_Regular_otf_start:
307        [libc::c_uchar; 57308];
308    pub static _binary_resources_fonts_noto_NotoSansChorasmian_Regular_otf_start:
309        [libc::c_uchar; 12460];
310    pub static _binary_resources_fonts_noto_NotoSansCoptic_Regular_otf_start:
311        [libc::c_uchar; 21380];
312    pub static _binary_resources_fonts_noto_NotoSansCuneiform_Regular_otf_start:
313        [libc::c_uchar; 416308];
314    pub static _binary_resources_fonts_noto_NotoSansCypriot_Regular_otf_start:
315        [libc::c_uchar; 7024];
316    pub static _binary_resources_fonts_noto_NotoSansCyproMinoan_Regular_otf_start:
317        [libc::c_uchar; 8568];
318    pub static _binary_resources_fonts_noto_NotoSansDeseret_Regular_otf_start:
319        [libc::c_uchar; 9016];
320    pub static _binary_resources_fonts_noto_NotoSansDuployan_Regular_otf_start:
321        [libc::c_uchar; 10276];
322    pub static _binary_resources_fonts_noto_NotoSansEgyptianHieroglyphs_Regular_otf_start:
323        [libc::c_uchar; 362960];
324    pub static _binary_resources_fonts_noto_NotoSansElbasan_Regular_otf_start:
325        [libc::c_uchar; 8684];
326    pub static _binary_resources_fonts_noto_NotoSansElymaic_Regular_otf_start:
327        [libc::c_uchar; 7620];
328    pub static _binary_resources_fonts_noto_NotoSansGlagolitic_Regular_otf_start:
329        [libc::c_uchar; 17176];
330    pub static _binary_resources_fonts_noto_NotoSansGothic_Regular_otf_start: [libc::c_uchar; 5416];
331    pub static _binary_resources_fonts_noto_NotoSansGunjalaGondi_Regular_otf_start:
332        [libc::c_uchar; 32372];
333    pub static _binary_resources_fonts_noto_NotoSansHanifiRohingya_Regular_otf_start:
334        [libc::c_uchar; 16576];
335    pub static _binary_resources_fonts_noto_NotoSansHanunoo_Regular_otf_start:
336        [libc::c_uchar; 6596];
337    pub static _binary_resources_fonts_noto_NotoSansHatran_Regular_otf_start: [libc::c_uchar; 4324];
338    pub static _binary_resources_fonts_noto_NotoSansImperialAramaic_Regular_otf_start:
339        [libc::c_uchar; 5436];
340    pub static _binary_resources_fonts_noto_NotoSansInscriptionalPahlavi_Regular_otf_start:
341        [libc::c_uchar; 5464];
342    pub static _binary_resources_fonts_noto_NotoSansInscriptionalParthian_Regular_otf_start:
343        [libc::c_uchar; 6788];
344    pub static _binary_resources_fonts_noto_NotoSansJavanese_Regular_otf_start:
345        [libc::c_uchar; 86944];
346    pub static _binary_resources_fonts_noto_NotoSansKaithi_Regular_otf_start:
347        [libc::c_uchar; 39756];
348    pub static _binary_resources_fonts_noto_NotoSansKawi_Regular_otf_start: [libc::c_uchar; 30940];
349    pub static _binary_resources_fonts_noto_NotoSansKayahLi_Regular_otf_start:
350        [libc::c_uchar; 7100];
351    pub static _binary_resources_fonts_noto_NotoSansKharoshthi_Regular_otf_start:
352        [libc::c_uchar; 27708];
353    pub static _binary_resources_fonts_noto_NotoSansKhudawadi_Regular_otf_start:
354        [libc::c_uchar; 14764];
355    pub static _binary_resources_fonts_noto_NotoSansLepcha_Regular_otf_start:
356        [libc::c_uchar; 18832];
357    pub static _binary_resources_fonts_noto_NotoSansLimbu_Regular_otf_start: [libc::c_uchar; 10040];
358    pub static _binary_resources_fonts_noto_NotoSansLinearA_Regular_otf_start:
359        [libc::c_uchar; 33640];
360    pub static _binary_resources_fonts_noto_NotoSansLinearB_Regular_otf_start:
361        [libc::c_uchar; 36892];
362    pub static _binary_resources_fonts_noto_NotoSansLisu_Regular_otf_start: [libc::c_uchar; 5688];
363    pub static _binary_resources_fonts_noto_NotoSansLycian_Regular_otf_start: [libc::c_uchar; 4108];
364    pub static _binary_resources_fonts_noto_NotoSansLydian_Regular_otf_start: [libc::c_uchar; 4088];
365    pub static _binary_resources_fonts_noto_NotoSansMahajani_Regular_otf_start:
366        [libc::c_uchar; 10136];
367    pub static _binary_resources_fonts_noto_NotoSansMandaic_Regular_otf_start:
368        [libc::c_uchar; 13160];
369    pub static _binary_resources_fonts_noto_NotoSansManichaean_Regular_otf_start:
370        [libc::c_uchar; 16496];
371    pub static _binary_resources_fonts_noto_NotoSansMarchen_Regular_otf_start:
372        [libc::c_uchar; 69240];
373    pub static _binary_resources_fonts_noto_NotoSansMasaramGondi_Regular_otf_start:
374        [libc::c_uchar; 23052];
375    pub static _binary_resources_fonts_noto_NotoSansMath_Regular_otf_start: [libc::c_uchar; 258796];
376    pub static _binary_resources_fonts_noto_NotoSansMedefaidrin_Regular_otf_start:
377        [libc::c_uchar; 27060];
378    pub static _binary_resources_fonts_noto_NotoSansMeeteiMayek_Regular_otf_start:
379        [libc::c_uchar; 13056];
380    pub static _binary_resources_fonts_noto_NotoSansMendeKikakui_Regular_otf_start:
381        [libc::c_uchar; 19664];
382    pub static _binary_resources_fonts_noto_NotoSansMeroitic_Regular_otf_start:
383        [libc::c_uchar; 19980];
384    pub static _binary_resources_fonts_noto_NotoSansMiao_Regular_otf_start: [libc::c_uchar; 26460];
385    pub static _binary_resources_fonts_noto_NotoSansModi_Regular_otf_start: [libc::c_uchar; 29412];
386    pub static _binary_resources_fonts_noto_NotoSansMongolian_Regular_otf_start:
387        [libc::c_uchar; 111040];
388    pub static _binary_resources_fonts_noto_NotoSansMro_Regular_otf_start: [libc::c_uchar; 5608];
389    pub static _binary_resources_fonts_noto_NotoSansMultani_Regular_otf_start:
390        [libc::c_uchar; 7852];
391    pub static _binary_resources_fonts_noto_NotoSansNabataean_Regular_otf_start:
392        [libc::c_uchar; 6448];
393    pub static _binary_resources_fonts_noto_NotoSansNagMundari_Regular_otf_start:
394        [libc::c_uchar; 8612];
395    pub static _binary_resources_fonts_noto_NotoSansNandinagari_Regular_otf_start:
396        [libc::c_uchar; 86940];
397    pub static _binary_resources_fonts_noto_NotoSansNewa_Regular_otf_start: [libc::c_uchar; 99568];
398    pub static _binary_resources_fonts_noto_NotoSansNewTaiLue_Regular_otf_start:
399        [libc::c_uchar; 10884];
400    pub static _binary_resources_fonts_noto_NotoSansNKo_Regular_otf_start: [libc::c_uchar; 15164];
401    pub static _binary_resources_fonts_noto_NotoSansNushu_Regular_otf_start: [libc::c_uchar; 72472];
402    pub static _binary_resources_fonts_noto_NotoSansOgham_Regular_otf_start: [libc::c_uchar; 3720];
403    pub static _binary_resources_fonts_noto_NotoSansOlChiki_Regular_otf_start:
404        [libc::c_uchar; 7024];
405    pub static _binary_resources_fonts_noto_NotoSansOldHungarian_Regular_otf_start:
406        [libc::c_uchar; 44628];
407    pub static _binary_resources_fonts_noto_NotoSansOldItalic_Regular_otf_start:
408        [libc::c_uchar; 6360];
409    pub static _binary_resources_fonts_noto_NotoSansOldNorthArabian_Regular_otf_start:
410        [libc::c_uchar; 6132];
411    pub static _binary_resources_fonts_noto_NotoSansOldPermic_Regular_otf_start:
412        [libc::c_uchar; 8512];
413    pub static _binary_resources_fonts_noto_NotoSansOldPersian_Regular_otf_start:
414        [libc::c_uchar; 9856];
415    pub static _binary_resources_fonts_noto_NotoSansOldSogdian_Regular_otf_start:
416        [libc::c_uchar; 12260];
417    pub static _binary_resources_fonts_noto_NotoSansOldSouthArabian_Regular_otf_start:
418        [libc::c_uchar; 4624];
419    pub static _binary_resources_fonts_noto_NotoSansOldTurkic_Regular_otf_start:
420        [libc::c_uchar; 6884];
421    pub static _binary_resources_fonts_noto_NotoSansOsage_Regular_otf_start: [libc::c_uchar; 9292];
422    pub static _binary_resources_fonts_noto_NotoSansOsmanya_Regular_otf_start:
423        [libc::c_uchar; 6784];
424    pub static _binary_resources_fonts_noto_NotoSansPahawhHmong_Regular_otf_start:
425        [libc::c_uchar; 13024];
426    pub static _binary_resources_fonts_noto_NotoSansPalmyrene_Regular_otf_start:
427        [libc::c_uchar; 8480];
428    pub static _binary_resources_fonts_noto_NotoSansPauCinHau_Regular_otf_start:
429        [libc::c_uchar; 8124];
430    pub static _binary_resources_fonts_noto_NotoSansPhagsPa_Regular_otf_start:
431        [libc::c_uchar; 24036];
432    pub static _binary_resources_fonts_noto_NotoSansPhoenician_Regular_otf_start:
433        [libc::c_uchar; 5288];
434    pub static _binary_resources_fonts_noto_NotoSansPsalterPahlavi_Regular_otf_start:
435        [libc::c_uchar; 12748];
436    pub static _binary_resources_fonts_noto_NotoSansRejang_Regular_otf_start: [libc::c_uchar; 6440];
437    pub static _binary_resources_fonts_noto_NotoSansRunic_Regular_otf_start: [libc::c_uchar; 7200];
438    pub static _binary_resources_fonts_noto_NotoSansSamaritan_Regular_otf_start:
439        [libc::c_uchar; 9024];
440    pub static _binary_resources_fonts_noto_NotoSansSaurashtra_Regular_otf_start:
441        [libc::c_uchar; 16020];
442    pub static _binary_resources_fonts_noto_NotoSansSharada_Regular_otf_start:
443        [libc::c_uchar; 32824];
444    pub static _binary_resources_fonts_noto_NotoSansShavian_Regular_otf_start:
445        [libc::c_uchar; 5468];
446    pub static _binary_resources_fonts_noto_NotoSansSiddham_Regular_otf_start:
447        [libc::c_uchar; 91992];
448    pub static _binary_resources_fonts_noto_NotoSansSignWriting_Regular_otf_start:
449        [libc::c_uchar; 2780224];
450    pub static _binary_resources_fonts_noto_NotoSansSogdian_Regular_otf_start:
451        [libc::c_uchar; 48356];
452    pub static _binary_resources_fonts_noto_NotoSansSoraSompeng_Regular_otf_start:
453        [libc::c_uchar; 6332];
454    pub static _binary_resources_fonts_noto_NotoSansSoyombo_Regular_otf_start:
455        [libc::c_uchar; 52036];
456    pub static _binary_resources_fonts_noto_NotoSansSundanese_Regular_otf_start:
457        [libc::c_uchar; 9420];
458    pub static _binary_resources_fonts_noto_NotoSansSylotiNagri_Regular_otf_start:
459        [libc::c_uchar; 12852];
460    pub static _binary_resources_fonts_noto_NotoSansSymbols_Regular_otf_start:
461        [libc::c_uchar; 109696];
462    pub static _binary_resources_fonts_noto_NotoSansSymbols2_Regular_otf_start:
463        [libc::c_uchar; 375388];
464    pub static _binary_resources_fonts_noto_NotoSansSyriac_Regular_otf_start:
465        [libc::c_uchar; 124756];
466    pub static _binary_resources_fonts_noto_NotoSansTagalog_Regular_otf_start:
467        [libc::c_uchar; 5500];
468    pub static _binary_resources_fonts_noto_NotoSansTagbanwa_Regular_otf_start:
469        [libc::c_uchar; 5356];
470    pub static _binary_resources_fonts_noto_NotoSansTaiLe_Regular_otf_start: [libc::c_uchar; 8616];
471    pub static _binary_resources_fonts_noto_NotoSansTaiTham_Regular_otf_start:
472        [libc::c_uchar; 76880];
473    pub static _binary_resources_fonts_noto_NotoSansTaiViet_Regular_otf_start:
474        [libc::c_uchar; 12280];
475    pub static _binary_resources_fonts_noto_NotoSansTakri_Regular_otf_start: [libc::c_uchar; 17864];
476    pub static _binary_resources_fonts_noto_NotoSansTangsa_Regular_otf_start:
477        [libc::c_uchar; 16908];
478    pub static _binary_resources_fonts_noto_NotoSansThaana_Regular_otf_start:
479        [libc::c_uchar; 12392];
480    pub static _binary_resources_fonts_noto_NotoSansTifinagh_Regular_otf_start:
481        [libc::c_uchar; 24776];
482    pub static _binary_resources_fonts_noto_NotoSansTirhuta_Regular_otf_start:
483        [libc::c_uchar; 52432];
484    pub static _binary_resources_fonts_noto_NotoSansUgaritic_Regular_otf_start:
485        [libc::c_uchar; 5048];
486    pub static _binary_resources_fonts_noto_NotoSansVai_Regular_otf_start: [libc::c_uchar; 24088];
487    pub static _binary_resources_fonts_noto_NotoSansWancho_Regular_otf_start:
488        [libc::c_uchar; 15140];
489    pub static _binary_resources_fonts_noto_NotoSansWarangCiti_Regular_otf_start:
490        [libc::c_uchar; 23484];
491    pub static _binary_resources_fonts_noto_NotoSansYi_Regular_otf_start: [libc::c_uchar; 92164];
492    pub static _binary_resources_fonts_noto_NotoSansZanabazarSquare_Regular_otf_start:
493        [libc::c_uchar; 13804];
494    pub static _binary_resources_fonts_noto_NotoSerif_Regular_otf_start: [libc::c_uchar; 289412];
495    pub static _binary_resources_fonts_noto_NotoSerifAhom_Regular_otf_start: [libc::c_uchar; 14516];
496    pub static _binary_resources_fonts_noto_NotoSerifArmenian_Regular_otf_start:
497        [libc::c_uchar; 14160];
498    pub static _binary_resources_fonts_noto_NotoSerifBalinese_Regular_otf_start:
499        [libc::c_uchar; 32348];
500    pub static _binary_resources_fonts_noto_NotoSerifBengali_Regular_otf_start:
501        [libc::c_uchar; 101332];
502    pub static _binary_resources_fonts_noto_NotoSerifDevanagari_Regular_otf_start:
503        [libc::c_uchar; 169744];
504    pub static _binary_resources_fonts_noto_NotoSerifDivesAkuru_Regular_otf_start:
505        [libc::c_uchar; 27972];
506    pub static _binary_resources_fonts_noto_NotoSerifDogra_Regular_otf_start:
507        [libc::c_uchar; 19944];
508    pub static _binary_resources_fonts_noto_NotoSerifEthiopic_Regular_otf_start:
509        [libc::c_uchar; 113328];
510    pub static _binary_resources_fonts_noto_NotoSerifGeorgian_Regular_otf_start:
511        [libc::c_uchar; 31988];
512    pub static _binary_resources_fonts_noto_NotoSerifGrantha_Regular_otf_start:
513        [libc::c_uchar; 368396];
514    pub static _binary_resources_fonts_noto_NotoSerifGujarati_Regular_otf_start:
515        [libc::c_uchar; 64848];
516    pub static _binary_resources_fonts_noto_NotoSerifGurmukhi_Regular_otf_start:
517        [libc::c_uchar; 26992];
518    pub static _binary_resources_fonts_noto_NotoSerifHebrew_Regular_otf_start:
519        [libc::c_uchar; 15320];
520    pub static _binary_resources_fonts_noto_NotoSerifKannada_Regular_otf_start:
521        [libc::c_uchar; 89032];
522    pub static _binary_resources_fonts_noto_NotoSerifKhitanSmallScript_Regular_otf_start:
523        [libc::c_uchar; 508920];
524    pub static _binary_resources_fonts_noto_NotoSerifKhmer_Regular_otf_start:
525        [libc::c_uchar; 40436];
526    pub static _binary_resources_fonts_noto_NotoSerifKhojki_Regular_otf_start:
527        [libc::c_uchar; 60112];
528    pub static _binary_resources_fonts_noto_NotoSerifLao_Regular_otf_start: [libc::c_uchar; 16196];
529    pub static _binary_resources_fonts_noto_NotoSerifMakasar_Regular_otf_start:
530        [libc::c_uchar; 5864];
531    pub static _binary_resources_fonts_noto_NotoSerifMalayalam_Regular_otf_start:
532        [libc::c_uchar; 45668];
533    pub static _binary_resources_fonts_noto_NotoSerifMyanmar_Regular_otf_start:
534        [libc::c_uchar; 127564];
535    pub static _binary_resources_fonts_noto_NotoSerifNyiakengPuachueHmong_Regular_otf_start:
536        [libc::c_uchar; 12208];
537    pub static _binary_resources_fonts_noto_NotoSerifOldUyghur_Regular_otf_start:
538        [libc::c_uchar; 15620];
539    pub static _binary_resources_fonts_noto_NotoSerifOriya_Regular_otf_start:
540        [libc::c_uchar; 105824];
541    pub static _binary_resources_fonts_noto_NotoSerifSinhala_Regular_otf_start:
542        [libc::c_uchar; 74924];
543    pub static _binary_resources_fonts_noto_NotoSerifTamil_Regular_otf_start:
544        [libc::c_uchar; 33752];
545    pub static _binary_resources_fonts_noto_NotoSerifTelugu_Regular_otf_start:
546        [libc::c_uchar; 82032];
547    pub static _binary_resources_fonts_noto_NotoSerifThai_Regular_otf_start: [libc::c_uchar; 17556];
548    pub static _binary_resources_fonts_noto_NotoSerifTibetan_Regular_otf_start:
549        [libc::c_uchar; 334156];
550    pub static _binary_resources_fonts_noto_NotoSerifToto_Regular_otf_start: [libc::c_uchar; 5732];
551    pub static _binary_resources_fonts_noto_NotoSerifVithkuqi_Regular_otf_start:
552        [libc::c_uchar; 42508];
553    pub static _binary_resources_fonts_noto_NotoSerifYezidi_Regular_otf_start:
554        [libc::c_uchar; 8664];
555}
556
557pub const SLIDER_VALUE: Style = MD_SIZE;
558
559pub struct FontFamily {
560    pub regular: Font,
561    pub italic: Font,
562    pub bold: Font,
563    pub bold_italic: Font,
564}
565
566pub fn family_names<P: AsRef<Path>>(search_path: P) -> Result<BTreeSet<String>, Error> {
567    if !search_path.as_ref().exists() {
568        return Err(format_err!("the search path doesn't exist"));
569    }
570
571    let opener = FontOpener::new()?;
572    let glob = Glob::new("**/*.[ot]tf")?.compile_matcher();
573
574    let mut families = BTreeSet::new();
575
576    for entry in WalkDir::new(search_path.as_ref())
577        .min_depth(1)
578        .into_iter()
579        .filter_entry(|e| !e.is_hidden())
580    {
581        if entry.is_err() {
582            continue;
583        }
584        let entry = entry.unwrap();
585        let path = entry.path();
586        if !glob.is_match(path) {
587            continue;
588        }
589        if let Ok(font) = opener
590            .open(path)
591            .map_err(|e| error!("Can't open '{}': {:#}.", path.display(), e))
592        {
593            if let Some(family_name) = font.family_name() {
594                families.insert(family_name.to_string());
595            } else {
596                warn!("Can't get the family name of '{}'.", path.display());
597            }
598        }
599    }
600
601    Ok(families)
602}
603
604impl FontFamily {
605    pub fn from_name<P: AsRef<Path>>(
606        family_name: &str,
607        search_path: P,
608    ) -> Result<FontFamily, Error> {
609        let opener = FontOpener::new()?;
610        let glob = Glob::new("**/*.[ot]tf")?.compile_matcher();
611        let mut styles = FxHashMap::default();
612
613        for entry in WalkDir::new(search_path.as_ref())
614            .min_depth(1)
615            .into_iter()
616            .filter_entry(|e| !e.is_hidden())
617        {
618            if entry.is_err() {
619                continue;
620            }
621            let entry = entry.unwrap();
622            let path = entry.path();
623            if !glob.is_match(path) {
624                continue;
625            }
626            if let Ok(font) = opener
627                .open(path)
628                .map_err(|e| error!("Can't open '{}': {:#}.", path.display(), e))
629            {
630                if font.family_name() == Some(family_name) {
631                    styles.insert(
632                        font.style_name()
633                            .map(String::from)
634                            .unwrap_or_else(|| "Regular".to_string()),
635                        path.to_path_buf(),
636                    );
637                }
638            }
639        }
640
641        let regular_path = if styles.len() == 1 {
642            styles.values().next().unwrap()
643        } else {
644            styles
645                .get("Regular")
646                .or_else(|| styles.get("Roman"))
647                .or_else(|| styles.get("Book"))
648                .ok_or_else(|| format_err!("can't find regular style"))?
649        };
650        let italic_path = styles
651            .get("Italic")
652            .or_else(|| styles.get("Book Italic"))
653            .or_else(|| styles.get("Regular Italic"))
654            .unwrap_or(regular_path);
655        let bold_path = styles
656            .get("Bold")
657            .or_else(|| styles.get("Semibold"))
658            .or_else(|| styles.get("SemiBold"))
659            .or_else(|| styles.get("Medium"))
660            .unwrap_or(regular_path);
661        let bold_italic_path = styles
662            .get("Bold Italic")
663            .or_else(|| styles.get("SemiBold Italic"))
664            .or_else(|| styles.get("Medium Italic"))
665            .unwrap_or(italic_path);
666        Ok(FontFamily {
667            regular: opener.open(regular_path)?,
668            italic: opener.open(italic_path)?,
669            bold: opener.open(bold_path)?,
670            bold_italic: opener.open(bold_italic_path)?,
671        })
672    }
673}
674
675pub struct Fonts {
676    pub sans_serif: FontFamily,
677    pub serif: FontFamily,
678    pub monospace: FontFamily,
679    pub keyboard: Font,
680    pub display: Font,
681}
682
683impl Fonts {
684    fn _load(root_dir: Option<PathBuf>) -> Result<Fonts, Error> {
685        let search_path = if let Some(root_dir) = root_dir {
686            root_dir.join("fonts")
687        } else {
688            PathBuf::from("fonts")
689        };
690
691        let opener = FontOpener::new()?;
692        let mut fonts = Fonts {
693            sans_serif: FontFamily {
694                regular: opener.open(search_path.join("NotoSans-Regular.ttf").as_path())?,
695                italic: opener.open(search_path.join("NotoSans-Italic.ttf").as_path())?,
696                bold: opener.open(search_path.join("NotoSans-Bold.ttf").as_path())?,
697                bold_italic: opener.open(search_path.join("NotoSans-BoldItalic.ttf").as_path())?,
698            },
699            serif: FontFamily {
700                regular: opener.open(search_path.join("NotoSerif-Regular.ttf").as_path())?,
701                italic: opener.open(search_path.join("NotoSerif-Italic.ttf").as_path())?,
702                bold: opener.open(search_path.join("NotoSerif-Bold.ttf").as_path())?,
703                bold_italic: opener.open(search_path.join("NotoSerif-BoldItalic.ttf").as_path())?,
704            },
705            monospace: FontFamily {
706                regular: opener.open(search_path.join("SourceCodeVariable-Roman.otf").as_path())?,
707                italic: opener.open(search_path.join("SourceCodeVariable-Italic.otf").as_path())?,
708                bold: opener.open(search_path.join("SourceCodeVariable-Roman.otf").as_path())?,
709                bold_italic: opener
710                    .open(search_path.join("SourceCodeVariable-Italic.otf").as_path())?,
711            },
712            keyboard: opener.open(search_path.join("VarelaRound-Regular.ttf").as_path())?,
713            display: opener.open(search_path.join("Cormorant-Regular.ttf").as_path())?,
714        };
715        fonts.monospace.bold.set_variations(&["wght=600"]);
716        fonts.monospace.bold_italic.set_variations(&["wght=600"]);
717        Ok(fonts)
718    }
719
720    pub fn load() -> Result<Fonts, Error> {
721        Fonts::_load(None)
722    }
723
724    pub fn load_from(root_dir: PathBuf) -> Result<Fonts, Error> {
725        Fonts::_load(Some(root_dir))
726    }
727}
728
729bitflags! {
730    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
731    pub struct Variant: u8 {
732        const REGULAR = 0;
733        const ITALIC = 1;
734        const BOLD = 2;
735    }
736}
737
738#[derive(Debug, Copy, Clone, Eq, PartialEq)]
739pub enum Family {
740    SansSerif,
741    Serif,
742    Monospace,
743    Keyboard,
744    Display,
745}
746
747pub struct Style {
748    family: Family,
749    variant: Variant,
750    pub size: u32,
751}
752
753pub fn font_from_variant(family: &mut FontFamily, variant: Variant) -> &mut Font {
754    if variant.contains(Variant::ITALIC | Variant::BOLD) {
755        &mut family.bold_italic
756    } else if variant.contains(Variant::ITALIC) {
757        &mut family.italic
758    } else if variant.contains(Variant::BOLD) {
759        &mut family.bold
760    } else {
761        &mut family.regular
762    }
763}
764
765pub fn font_from_style<'a>(fonts: &'a mut Fonts, style: &Style, dpi: u16) -> &'a mut Font {
766    let font = match style.family {
767        Family::SansSerif => {
768            let family = &mut fonts.sans_serif;
769            font_from_variant(family, style.variant)
770        }
771        Family::Serif => {
772            let family = &mut fonts.serif;
773            font_from_variant(family, style.variant)
774        }
775        Family::Monospace => {
776            let family = &mut fonts.monospace;
777            font_from_variant(family, style.variant)
778        }
779        Family::Keyboard => &mut fonts.keyboard,
780        Family::Display => &mut fonts.display,
781    };
782    font.set_size(style.size, dpi);
783    font
784}
785
786#[inline]
787unsafe fn font_data_from_script(script: HbScript) -> &'static [libc::c_uchar] {
788    // Extracted from mupdf in source/fitz/noto.c
789    #[cfg(any(not(target_os = "linux"), target_arch = "arm"))]
790    match script {
791        HB_SCRIPT_HANGUL | HB_SCRIPT_HIRAGANA | HB_SCRIPT_KATAKANA | HB_SCRIPT_BOPOMOFO
792        | HB_SCRIPT_HAN => &_binary_DroidSansFallback_ttf,
793
794        HB_SCRIPT_ARABIC => &_binary_NotoNaskhArabic_Regular_otf,
795        HB_SCRIPT_SYRIAC => &_binary_NotoSansSyriac_Regular_otf,
796        HB_SCRIPT_MEROITIC_CURSIVE | HB_SCRIPT_MEROITIC_HIEROGLYPHS => {
797            &_binary_NotoSansMeroitic_Regular_otf
798        }
799
800        HB_SCRIPT_ADLAM => &_binary_NotoSansAdlam_Regular_otf,
801        HB_SCRIPT_AHOM => &_binary_NotoSerifAhom_Regular_otf,
802        HB_SCRIPT_ANATOLIAN_HIEROGLYPHS => &_binary_NotoSansAnatolianHieroglyphs_Regular_otf,
803        HB_SCRIPT_ARMENIAN => &_binary_NotoSerifArmenian_Regular_otf,
804        HB_SCRIPT_AVESTAN => &_binary_NotoSansAvestan_Regular_otf,
805        HB_SCRIPT_BALINESE => &_binary_NotoSerifBalinese_Regular_otf,
806        HB_SCRIPT_BAMUM => &_binary_NotoSansBamum_Regular_otf,
807        HB_SCRIPT_BASSA_VAH => &_binary_NotoSansBassaVah_Regular_otf,
808        HB_SCRIPT_BATAK => &_binary_NotoSansBatak_Regular_otf,
809        HB_SCRIPT_BENGALI => &_binary_NotoSerifBengali_Regular_otf,
810        HB_SCRIPT_BHAIKSUKI => &_binary_NotoSansBhaiksuki_Regular_otf,
811        HB_SCRIPT_BRAHMI => &_binary_NotoSansBrahmi_Regular_otf,
812        HB_SCRIPT_BUGINESE => &_binary_NotoSansBuginese_Regular_otf,
813        HB_SCRIPT_BUHID => &_binary_NotoSansBuhid_Regular_otf,
814        HB_SCRIPT_CANADIAN_SYLLABICS => &_binary_NotoSansCanadianAboriginal_Regular_otf,
815        HB_SCRIPT_CARIAN => &_binary_NotoSansCarian_Regular_otf,
816        HB_SCRIPT_CAUCASIAN_ALBANIAN => &_binary_NotoSansCaucasianAlbanian_Regular_otf,
817        HB_SCRIPT_CHAKMA => &_binary_NotoSansChakma_Regular_otf,
818        HB_SCRIPT_CHAM => &_binary_NotoSansCham_Regular_otf,
819        HB_SCRIPT_CHEROKEE => &_binary_NotoSansCherokee_Regular_otf,
820        HB_SCRIPT_CHORASMIAN => &_binary_NotoSansChorasmian_Regular_otf,
821        HB_SCRIPT_COPTIC => &_binary_NotoSansCoptic_Regular_otf,
822        HB_SCRIPT_CUNEIFORM => &_binary_NotoSansCuneiform_Regular_otf,
823        HB_SCRIPT_CYPRIOT => &_binary_NotoSansCypriot_Regular_otf,
824        HB_SCRIPT_CYPRO_MINOAN => &_binary_NotoSansCyproMinoan_Regular_otf,
825        HB_SCRIPT_DESERET => &_binary_NotoSansDeseret_Regular_otf,
826        HB_SCRIPT_DEVANAGARI => &_binary_NotoSerifDevanagari_Regular_otf,
827        HB_SCRIPT_DIVES_AKURU => &_binary_NotoSerifDivesAkuru_Regular_otf,
828        HB_SCRIPT_DOGRA => &_binary_NotoSerifDogra_Regular_otf,
829        HB_SCRIPT_DUPLOYAN => &_binary_NotoSansDuployan_Regular_otf,
830        HB_SCRIPT_EGYPTIAN_HIEROGLYPHS => &_binary_NotoSansEgyptianHieroglyphs_Regular_otf,
831        HB_SCRIPT_ELBASAN => &_binary_NotoSansElbasan_Regular_otf,
832        HB_SCRIPT_ELYMAIC => &_binary_NotoSansElymaic_Regular_otf,
833        HB_SCRIPT_ETHIOPIC => &_binary_NotoSerifEthiopic_Regular_otf,
834        HB_SCRIPT_GEORGIAN => &_binary_NotoSerifGeorgian_Regular_otf,
835        HB_SCRIPT_GLAGOLITIC => &_binary_NotoSansGlagolitic_Regular_otf,
836        HB_SCRIPT_GOTHIC => &_binary_NotoSansGothic_Regular_otf,
837        HB_SCRIPT_GRANTHA => &_binary_NotoSerifGrantha_Regular_otf,
838        HB_SCRIPT_GUJARATI => &_binary_NotoSerifGujarati_Regular_otf,
839        HB_SCRIPT_GUNJALA_GONDI => &_binary_NotoSansGunjalaGondi_Regular_otf,
840        HB_SCRIPT_GURMUKHI => &_binary_NotoSerifGurmukhi_Regular_otf,
841        HB_SCRIPT_HANIFI_ROHINGYA => &_binary_NotoSansHanifiRohingya_Regular_otf,
842        HB_SCRIPT_HANUNOO => &_binary_NotoSansHanunoo_Regular_otf,
843        HB_SCRIPT_HATRAN => &_binary_NotoSansHatran_Regular_otf,
844        HB_SCRIPT_HEBREW => &_binary_NotoSerifHebrew_Regular_otf,
845        HB_SCRIPT_IMPERIAL_ARAMAIC => &_binary_NotoSansImperialAramaic_Regular_otf,
846        HB_SCRIPT_INSCRIPTIONAL_PAHLAVI => &_binary_NotoSansInscriptionalPahlavi_Regular_otf,
847        HB_SCRIPT_INSCRIPTIONAL_PARTHIAN => &_binary_NotoSansInscriptionalParthian_Regular_otf,
848        HB_SCRIPT_JAVANESE => &_binary_NotoSansJavanese_Regular_otf,
849        HB_SCRIPT_KAITHI => &_binary_NotoSansKaithi_Regular_otf,
850        HB_SCRIPT_KANNADA => &_binary_NotoSerifKannada_Regular_otf,
851        HB_SCRIPT_KAWI => &_binary_NotoSansKawi_Regular_otf,
852        HB_SCRIPT_KAYAH_LI => &_binary_NotoSansKayahLi_Regular_otf,
853        HB_SCRIPT_KHAROSHTHI => &_binary_NotoSansKharoshthi_Regular_otf,
854        HB_SCRIPT_KHITAN_SMALL_SCRIPT => &_binary_NotoSerifKhitanSmallScript_Regular_otf,
855        HB_SCRIPT_KHMER => &_binary_NotoSerifKhmer_Regular_otf,
856        HB_SCRIPT_KHOJKI => &_binary_NotoSerifKhojki_Regular_otf,
857        HB_SCRIPT_KHUDAWADI => &_binary_NotoSansKhudawadi_Regular_otf,
858        HB_SCRIPT_LAO => &_binary_NotoSerifLao_Regular_otf,
859        HB_SCRIPT_LEPCHA => &_binary_NotoSansLepcha_Regular_otf,
860        HB_SCRIPT_LIMBU => &_binary_NotoSansLimbu_Regular_otf,
861        HB_SCRIPT_LINEAR_A => &_binary_NotoSansLinearA_Regular_otf,
862        HB_SCRIPT_LINEAR_B => &_binary_NotoSansLinearB_Regular_otf,
863        HB_SCRIPT_LISU => &_binary_NotoSansLisu_Regular_otf,
864        HB_SCRIPT_LYCIAN => &_binary_NotoSansLycian_Regular_otf,
865        HB_SCRIPT_LYDIAN => &_binary_NotoSansLydian_Regular_otf,
866        HB_SCRIPT_MAHAJANI => &_binary_NotoSansMahajani_Regular_otf,
867        HB_SCRIPT_MAKASAR => &_binary_NotoSerifMakasar_Regular_otf,
868        HB_SCRIPT_MALAYALAM => &_binary_NotoSerifMalayalam_Regular_otf,
869        HB_SCRIPT_MANDAIC => &_binary_NotoSansMandaic_Regular_otf,
870        HB_SCRIPT_MANICHAEAN => &_binary_NotoSansManichaean_Regular_otf,
871        HB_SCRIPT_MARCHEN => &_binary_NotoSansMarchen_Regular_otf,
872        HB_SCRIPT_MASARAM_GONDI => &_binary_NotoSansMasaramGondi_Regular_otf,
873        HB_SCRIPT_MEDEFAIDRIN => &_binary_NotoSansMedefaidrin_Regular_otf,
874        HB_SCRIPT_MEETEI_MAYEK => &_binary_NotoSansMeeteiMayek_Regular_otf,
875        HB_SCRIPT_MENDE_KIKAKUI => &_binary_NotoSansMendeKikakui_Regular_otf,
876        HB_SCRIPT_MIAO => &_binary_NotoSansMiao_Regular_otf,
877        HB_SCRIPT_MODI => &_binary_NotoSansModi_Regular_otf,
878        HB_SCRIPT_MONGOLIAN => &_binary_NotoSansMongolian_Regular_otf,
879        HB_SCRIPT_MRO => &_binary_NotoSansMro_Regular_otf,
880        HB_SCRIPT_MULTANI => &_binary_NotoSansMultani_Regular_otf,
881        HB_SCRIPT_MYANMAR => &_binary_NotoSerifMyanmar_Regular_otf,
882        HB_SCRIPT_NABATAEAN => &_binary_NotoSansNabataean_Regular_otf,
883        HB_SCRIPT_NAG_MUNDARI => &_binary_NotoSansNagMundari_Regular_otf,
884        HB_SCRIPT_NANDINAGARI => &_binary_NotoSansNandinagari_Regular_otf,
885        HB_SCRIPT_NEWA => &_binary_NotoSansNewa_Regular_otf,
886        HB_SCRIPT_NEW_TAI_LUE => &_binary_NotoSansNewTaiLue_Regular_otf,
887        HB_SCRIPT_NKO => &_binary_NotoSansNKo_Regular_otf,
888        HB_SCRIPT_NUSHU => &_binary_NotoSansNushu_Regular_otf,
889        HB_SCRIPT_NYIAKENG_PUACHUE_HMONG => &_binary_NotoSerifNyiakengPuachueHmong_Regular_otf,
890        HB_SCRIPT_OGHAM => &_binary_NotoSansOgham_Regular_otf,
891        HB_SCRIPT_OLD_HUNGARIAN => &_binary_NotoSansOldHungarian_Regular_otf,
892        HB_SCRIPT_OLD_ITALIC => &_binary_NotoSansOldItalic_Regular_otf,
893        HB_SCRIPT_OLD_NORTH_ARABIAN => &_binary_NotoSansOldNorthArabian_Regular_otf,
894        HB_SCRIPT_OLD_PERMIC => &_binary_NotoSansOldPermic_Regular_otf,
895        HB_SCRIPT_OLD_PERSIAN => &_binary_NotoSansOldPersian_Regular_otf,
896        HB_SCRIPT_OLD_SOGDIAN => &_binary_NotoSansOldSogdian_Regular_otf,
897        HB_SCRIPT_OLD_SOUTH_ARABIAN => &_binary_NotoSansOldSouthArabian_Regular_otf,
898        HB_SCRIPT_OLD_TURKIC => &_binary_NotoSansOldTurkic_Regular_otf,
899        HB_SCRIPT_OLD_UYGHUR => &_binary_NotoSerifOldUyghur_Regular_otf,
900        HB_SCRIPT_OL_CHIKI => &_binary_NotoSansOlChiki_Regular_otf,
901        HB_SCRIPT_ORIYA => &_binary_NotoSerifOriya_Regular_otf,
902        HB_SCRIPT_OSAGE => &_binary_NotoSansOsage_Regular_otf,
903        HB_SCRIPT_OSMANYA => &_binary_NotoSansOsmanya_Regular_otf,
904        HB_SCRIPT_PAHAWH_HMONG => &_binary_NotoSansPahawhHmong_Regular_otf,
905        HB_SCRIPT_PALMYRENE => &_binary_NotoSansPalmyrene_Regular_otf,
906        HB_SCRIPT_PAU_CIN_HAU => &_binary_NotoSansPauCinHau_Regular_otf,
907        HB_SCRIPT_PHAGS_PA => &_binary_NotoSansPhagsPa_Regular_otf,
908        HB_SCRIPT_PHOENICIAN => &_binary_NotoSansPhoenician_Regular_otf,
909        HB_SCRIPT_PSALTER_PAHLAVI => &_binary_NotoSansPsalterPahlavi_Regular_otf,
910        HB_SCRIPT_REJANG => &_binary_NotoSansRejang_Regular_otf,
911        HB_SCRIPT_RUNIC => &_binary_NotoSansRunic_Regular_otf,
912        HB_SCRIPT_SAMARITAN => &_binary_NotoSansSamaritan_Regular_otf,
913        HB_SCRIPT_SAURASHTRA => &_binary_NotoSansSaurashtra_Regular_otf,
914        HB_SCRIPT_SHARADA => &_binary_NotoSansSharada_Regular_otf,
915        HB_SCRIPT_SHAVIAN => &_binary_NotoSansShavian_Regular_otf,
916        HB_SCRIPT_SIDDHAM => &_binary_NotoSansSiddham_Regular_otf,
917        HB_SCRIPT_SIGNWRITING => &_binary_NotoSansSignWriting_Regular_otf,
918        HB_SCRIPT_SINHALA => &_binary_NotoSerifSinhala_Regular_otf,
919        HB_SCRIPT_SOGDIAN => &_binary_NotoSansSogdian_Regular_otf,
920        HB_SCRIPT_SORA_SOMPENG => &_binary_NotoSansSoraSompeng_Regular_otf,
921        HB_SCRIPT_SOYOMBO => &_binary_NotoSansSoyombo_Regular_otf,
922        HB_SCRIPT_SUNDANESE => &_binary_NotoSansSundanese_Regular_otf,
923        HB_SCRIPT_SYLOTI_NAGRI => &_binary_NotoSansSylotiNagri_Regular_otf,
924        HB_SCRIPT_TAGALOG => &_binary_NotoSansTagalog_Regular_otf,
925        HB_SCRIPT_TAGBANWA => &_binary_NotoSansTagbanwa_Regular_otf,
926        HB_SCRIPT_TAI_LE => &_binary_NotoSansTaiLe_Regular_otf,
927        HB_SCRIPT_TAI_THAM => &_binary_NotoSansTaiTham_Regular_otf,
928        HB_SCRIPT_TAI_VIET => &_binary_NotoSansTaiViet_Regular_otf,
929        HB_SCRIPT_TAKRI => &_binary_NotoSansTakri_Regular_otf,
930        HB_SCRIPT_TAMIL => &_binary_NotoSerifTamil_Regular_otf,
931        HB_SCRIPT_TANGSA => &_binary_NotoSansTangsa_Regular_otf,
932        HB_SCRIPT_TELUGU => &_binary_NotoSerifTelugu_Regular_otf,
933        HB_SCRIPT_THAANA => &_binary_NotoSansThaana_Regular_otf,
934        HB_SCRIPT_THAI => &_binary_NotoSerifThai_Regular_otf,
935        HB_SCRIPT_TIBETAN => &_binary_NotoSerifTibetan_Regular_otf,
936        HB_SCRIPT_TIFINAGH => &_binary_NotoSansTifinagh_Regular_otf,
937        HB_SCRIPT_TIRHUTA => &_binary_NotoSansTirhuta_Regular_otf,
938        HB_SCRIPT_TOTO => &_binary_NotoSerifToto_Regular_otf,
939        HB_SCRIPT_UGARITIC => &_binary_NotoSansUgaritic_Regular_otf,
940        HB_SCRIPT_VAI => &_binary_NotoSansVai_Regular_otf,
941        HB_SCRIPT_VITHKUQI => &_binary_NotoSerifVithkuqi_Regular_otf,
942        HB_SCRIPT_WANCHO => &_binary_NotoSansWancho_Regular_otf,
943        HB_SCRIPT_WARANG_CITI => &_binary_NotoSansWarangCiti_Regular_otf,
944        HB_SCRIPT_YEZIDI => &_binary_NotoSerifYezidi_Regular_otf,
945        HB_SCRIPT_YI => &_binary_NotoSansYi_Regular_otf,
946        HB_SCRIPT_ZANABAZAR_SQUARE => &_binary_NotoSansZanabazarSquare_Regular_otf,
947
948        HB_SYMBOL_MATHS => &_binary_NotoSansMath_Regular_otf,
949        HB_SYMBOL_MUSIC => &_binary_NotoMusic_Regular_otf,
950        HB_SYMBOL_MISC_ONE => &_binary_NotoSansSymbols_Regular_otf,
951        HB_SCRIPT_BRAILLE | HB_SYMBOL_MISC_TWO => &_binary_NotoSansSymbols2_Regular_otf,
952        HB_SYMBOL_EMOJI => &_binary_NotoEmoji_Regular_ttf,
953
954        _ => &_binary_DroidSansFallback_ttf,
955    }
956
957    #[cfg(all(target_os = "linux", not(target_arch = "arm")))]
958    match script {
959        HB_SCRIPT_HANGUL | HB_SCRIPT_HIRAGANA | HB_SCRIPT_KATAKANA | HB_SCRIPT_BOPOMOFO
960        | HB_SCRIPT_HAN => &_binary_resources_fonts_droid_DroidSansFallback_ttf_start,
961
962        HB_SCRIPT_ARABIC => &_binary_resources_fonts_noto_NotoNaskhArabic_Regular_otf_start,
963        HB_SCRIPT_SYRIAC => &_binary_resources_fonts_noto_NotoSansSyriac_Regular_otf_start,
964        HB_SCRIPT_MEROITIC_CURSIVE | HB_SCRIPT_MEROITIC_HIEROGLYPHS => {
965            &_binary_resources_fonts_noto_NotoSansMeroitic_Regular_otf_start
966        }
967
968        HB_SCRIPT_ADLAM => &_binary_resources_fonts_noto_NotoSansAdlam_Regular_otf_start,
969        HB_SCRIPT_AHOM => &_binary_resources_fonts_noto_NotoSerifAhom_Regular_otf_start,
970        HB_SCRIPT_ANATOLIAN_HIEROGLYPHS => {
971            &_binary_resources_fonts_noto_NotoSansAnatolianHieroglyphs_Regular_otf_start
972        }
973        HB_SCRIPT_ARMENIAN => &_binary_resources_fonts_noto_NotoSerifArmenian_Regular_otf_start,
974        HB_SCRIPT_AVESTAN => &_binary_resources_fonts_noto_NotoSansAvestan_Regular_otf_start,
975        HB_SCRIPT_BALINESE => &_binary_resources_fonts_noto_NotoSerifBalinese_Regular_otf_start,
976        HB_SCRIPT_BAMUM => &_binary_resources_fonts_noto_NotoSansBamum_Regular_otf_start,
977        HB_SCRIPT_BASSA_VAH => &_binary_resources_fonts_noto_NotoSansBassaVah_Regular_otf_start,
978        HB_SCRIPT_BATAK => &_binary_resources_fonts_noto_NotoSansBatak_Regular_otf_start,
979        HB_SCRIPT_BENGALI => &_binary_resources_fonts_noto_NotoSerifBengali_Regular_otf_start,
980        HB_SCRIPT_BHAIKSUKI => &_binary_resources_fonts_noto_NotoSansBhaiksuki_Regular_otf_start,
981        HB_SCRIPT_BRAHMI => &_binary_resources_fonts_noto_NotoSansBrahmi_Regular_otf_start,
982        HB_SCRIPT_BUGINESE => &_binary_resources_fonts_noto_NotoSansBuginese_Regular_otf_start,
983        HB_SCRIPT_BUHID => &_binary_resources_fonts_noto_NotoSansBuhid_Regular_otf_start,
984        HB_SCRIPT_CANADIAN_SYLLABICS => {
985            &_binary_resources_fonts_noto_NotoSansCanadianAboriginal_Regular_otf_start
986        }
987        HB_SCRIPT_CARIAN => &_binary_resources_fonts_noto_NotoSansCarian_Regular_otf_start,
988        HB_SCRIPT_CAUCASIAN_ALBANIAN => {
989            &_binary_resources_fonts_noto_NotoSansCaucasianAlbanian_Regular_otf_start
990        }
991        HB_SCRIPT_CHAKMA => &_binary_resources_fonts_noto_NotoSansChakma_Regular_otf_start,
992        HB_SCRIPT_CHAM => &_binary_resources_fonts_noto_NotoSansCham_Regular_otf_start,
993        HB_SCRIPT_CHEROKEE => &_binary_resources_fonts_noto_NotoSansCherokee_Regular_otf_start,
994        HB_SCRIPT_CHORASMIAN => &_binary_resources_fonts_noto_NotoSansChorasmian_Regular_otf_start,
995        HB_SCRIPT_COPTIC => &_binary_resources_fonts_noto_NotoSansCoptic_Regular_otf_start,
996        HB_SCRIPT_CUNEIFORM => &_binary_resources_fonts_noto_NotoSansCuneiform_Regular_otf_start,
997        HB_SCRIPT_CYPRIOT => &_binary_resources_fonts_noto_NotoSansCypriot_Regular_otf_start,
998        HB_SCRIPT_CYPRO_MINOAN => {
999            &_binary_resources_fonts_noto_NotoSansCyproMinoan_Regular_otf_start
1000        }
1001        HB_SCRIPT_DESERET => &_binary_resources_fonts_noto_NotoSansDeseret_Regular_otf_start,
1002        HB_SCRIPT_DEVANAGARI => &_binary_resources_fonts_noto_NotoSerifDevanagari_Regular_otf_start,
1003        HB_SCRIPT_DIVES_AKURU => {
1004            &_binary_resources_fonts_noto_NotoSerifDivesAkuru_Regular_otf_start
1005        }
1006        HB_SCRIPT_DOGRA => &_binary_resources_fonts_noto_NotoSerifDogra_Regular_otf_start,
1007        HB_SCRIPT_DUPLOYAN => &_binary_resources_fonts_noto_NotoSansDuployan_Regular_otf_start,
1008        HB_SCRIPT_EGYPTIAN_HIEROGLYPHS => {
1009            &_binary_resources_fonts_noto_NotoSansEgyptianHieroglyphs_Regular_otf_start
1010        }
1011        HB_SCRIPT_ELBASAN => &_binary_resources_fonts_noto_NotoSansElbasan_Regular_otf_start,
1012        HB_SCRIPT_ELYMAIC => &_binary_resources_fonts_noto_NotoSansElymaic_Regular_otf_start,
1013        HB_SCRIPT_ETHIOPIC => &_binary_resources_fonts_noto_NotoSerifEthiopic_Regular_otf_start,
1014        HB_SCRIPT_GEORGIAN => &_binary_resources_fonts_noto_NotoSerifGeorgian_Regular_otf_start,
1015        HB_SCRIPT_GLAGOLITIC => &_binary_resources_fonts_noto_NotoSansGlagolitic_Regular_otf_start,
1016        HB_SCRIPT_GOTHIC => &_binary_resources_fonts_noto_NotoSansGothic_Regular_otf_start,
1017        HB_SCRIPT_GRANTHA => &_binary_resources_fonts_noto_NotoSerifGrantha_Regular_otf_start,
1018        HB_SCRIPT_GUJARATI => &_binary_resources_fonts_noto_NotoSerifGujarati_Regular_otf_start,
1019        HB_SCRIPT_GUNJALA_GONDI => {
1020            &_binary_resources_fonts_noto_NotoSansGunjalaGondi_Regular_otf_start
1021        }
1022        HB_SCRIPT_GURMUKHI => &_binary_resources_fonts_noto_NotoSerifGurmukhi_Regular_otf_start,
1023        HB_SCRIPT_HANIFI_ROHINGYA => {
1024            &_binary_resources_fonts_noto_NotoSansHanifiRohingya_Regular_otf_start
1025        }
1026        HB_SCRIPT_HANUNOO => &_binary_resources_fonts_noto_NotoSansHanunoo_Regular_otf_start,
1027        HB_SCRIPT_HATRAN => &_binary_resources_fonts_noto_NotoSansHatran_Regular_otf_start,
1028        HB_SCRIPT_HEBREW => &_binary_resources_fonts_noto_NotoSerifHebrew_Regular_otf_start,
1029        HB_SCRIPT_IMPERIAL_ARAMAIC => {
1030            &_binary_resources_fonts_noto_NotoSansImperialAramaic_Regular_otf_start
1031        }
1032        HB_SCRIPT_INSCRIPTIONAL_PAHLAVI => {
1033            &_binary_resources_fonts_noto_NotoSansInscriptionalPahlavi_Regular_otf_start
1034        }
1035        HB_SCRIPT_INSCRIPTIONAL_PARTHIAN => {
1036            &_binary_resources_fonts_noto_NotoSansInscriptionalParthian_Regular_otf_start
1037        }
1038        HB_SCRIPT_JAVANESE => &_binary_resources_fonts_noto_NotoSansJavanese_Regular_otf_start,
1039        HB_SCRIPT_KAITHI => &_binary_resources_fonts_noto_NotoSansKaithi_Regular_otf_start,
1040        HB_SCRIPT_KANNADA => &_binary_resources_fonts_noto_NotoSerifKannada_Regular_otf_start,
1041        HB_SCRIPT_KAWI => &_binary_resources_fonts_noto_NotoSansKawi_Regular_otf_start,
1042        HB_SCRIPT_KAYAH_LI => &_binary_resources_fonts_noto_NotoSansKayahLi_Regular_otf_start,
1043        HB_SCRIPT_KHAROSHTHI => &_binary_resources_fonts_noto_NotoSansKharoshthi_Regular_otf_start,
1044        HB_SCRIPT_KHITAN_SMALL_SCRIPT => {
1045            &_binary_resources_fonts_noto_NotoSerifKhitanSmallScript_Regular_otf_start
1046        }
1047        HB_SCRIPT_KHMER => &_binary_resources_fonts_noto_NotoSerifKhmer_Regular_otf_start,
1048        HB_SCRIPT_KHOJKI => &_binary_resources_fonts_noto_NotoSerifKhojki_Regular_otf_start,
1049        HB_SCRIPT_KHUDAWADI => &_binary_resources_fonts_noto_NotoSansKhudawadi_Regular_otf_start,
1050        HB_SCRIPT_LAO => &_binary_resources_fonts_noto_NotoSerifLao_Regular_otf_start,
1051        HB_SCRIPT_LEPCHA => &_binary_resources_fonts_noto_NotoSansLepcha_Regular_otf_start,
1052        HB_SCRIPT_LIMBU => &_binary_resources_fonts_noto_NotoSansLimbu_Regular_otf_start,
1053        HB_SCRIPT_LINEAR_A => &_binary_resources_fonts_noto_NotoSansLinearA_Regular_otf_start,
1054        HB_SCRIPT_LINEAR_B => &_binary_resources_fonts_noto_NotoSansLinearB_Regular_otf_start,
1055        HB_SCRIPT_LISU => &_binary_resources_fonts_noto_NotoSansLisu_Regular_otf_start,
1056        HB_SCRIPT_LYCIAN => &_binary_resources_fonts_noto_NotoSansLycian_Regular_otf_start,
1057        HB_SCRIPT_LYDIAN => &_binary_resources_fonts_noto_NotoSansLydian_Regular_otf_start,
1058        HB_SCRIPT_MAHAJANI => &_binary_resources_fonts_noto_NotoSansMahajani_Regular_otf_start,
1059        HB_SCRIPT_MAKASAR => &_binary_resources_fonts_noto_NotoSerifMakasar_Regular_otf_start,
1060        HB_SCRIPT_MALAYALAM => &_binary_resources_fonts_noto_NotoSerifMalayalam_Regular_otf_start,
1061        HB_SCRIPT_MANDAIC => &_binary_resources_fonts_noto_NotoSansMandaic_Regular_otf_start,
1062        HB_SCRIPT_MANICHAEAN => &_binary_resources_fonts_noto_NotoSansManichaean_Regular_otf_start,
1063        HB_SCRIPT_MARCHEN => &_binary_resources_fonts_noto_NotoSansMarchen_Regular_otf_start,
1064        HB_SCRIPT_MASARAM_GONDI => {
1065            &_binary_resources_fonts_noto_NotoSansMasaramGondi_Regular_otf_start
1066        }
1067        HB_SCRIPT_MEDEFAIDRIN => {
1068            &_binary_resources_fonts_noto_NotoSansMedefaidrin_Regular_otf_start
1069        }
1070        HB_SCRIPT_MEETEI_MAYEK => {
1071            &_binary_resources_fonts_noto_NotoSansMeeteiMayek_Regular_otf_start
1072        }
1073        HB_SCRIPT_MENDE_KIKAKUI => {
1074            &_binary_resources_fonts_noto_NotoSansMendeKikakui_Regular_otf_start
1075        }
1076        HB_SCRIPT_MIAO => &_binary_resources_fonts_noto_NotoSansMiao_Regular_otf_start,
1077        HB_SCRIPT_MODI => &_binary_resources_fonts_noto_NotoSansModi_Regular_otf_start,
1078        HB_SCRIPT_MONGOLIAN => &_binary_resources_fonts_noto_NotoSansMongolian_Regular_otf_start,
1079        HB_SCRIPT_MRO => &_binary_resources_fonts_noto_NotoSansMro_Regular_otf_start,
1080        HB_SCRIPT_MULTANI => &_binary_resources_fonts_noto_NotoSansMultani_Regular_otf_start,
1081        HB_SCRIPT_MYANMAR => &_binary_resources_fonts_noto_NotoSerifMyanmar_Regular_otf_start,
1082        HB_SCRIPT_NABATAEAN => &_binary_resources_fonts_noto_NotoSansNabataean_Regular_otf_start,
1083        HB_SCRIPT_NAG_MUNDARI => &_binary_resources_fonts_noto_NotoSansNagMundari_Regular_otf_start,
1084        HB_SCRIPT_NANDINAGARI => {
1085            &_binary_resources_fonts_noto_NotoSansNandinagari_Regular_otf_start
1086        }
1087        HB_SCRIPT_NEWA => &_binary_resources_fonts_noto_NotoSansNewa_Regular_otf_start,
1088        HB_SCRIPT_NEW_TAI_LUE => &_binary_resources_fonts_noto_NotoSansNewTaiLue_Regular_otf_start,
1089        HB_SCRIPT_NKO => &_binary_resources_fonts_noto_NotoSansNKo_Regular_otf_start,
1090        HB_SCRIPT_NUSHU => &_binary_resources_fonts_noto_NotoSansNushu_Regular_otf_start,
1091        HB_SCRIPT_NYIAKENG_PUACHUE_HMONG => {
1092            &_binary_resources_fonts_noto_NotoSerifNyiakengPuachueHmong_Regular_otf_start
1093        }
1094        HB_SCRIPT_OGHAM => &_binary_resources_fonts_noto_NotoSansOgham_Regular_otf_start,
1095        HB_SCRIPT_OLD_HUNGARIAN => {
1096            &_binary_resources_fonts_noto_NotoSansOldHungarian_Regular_otf_start
1097        }
1098        HB_SCRIPT_OLD_ITALIC => &_binary_resources_fonts_noto_NotoSansOldItalic_Regular_otf_start,
1099        HB_SCRIPT_OLD_NORTH_ARABIAN => {
1100            &_binary_resources_fonts_noto_NotoSansOldNorthArabian_Regular_otf_start
1101        }
1102        HB_SCRIPT_OLD_PERMIC => &_binary_resources_fonts_noto_NotoSansOldPermic_Regular_otf_start,
1103        HB_SCRIPT_OLD_PERSIAN => &_binary_resources_fonts_noto_NotoSansOldPersian_Regular_otf_start,
1104        HB_SCRIPT_OLD_SOGDIAN => &_binary_resources_fonts_noto_NotoSansOldSogdian_Regular_otf_start,
1105        HB_SCRIPT_OLD_SOUTH_ARABIAN => {
1106            &_binary_resources_fonts_noto_NotoSansOldSouthArabian_Regular_otf_start
1107        }
1108        HB_SCRIPT_OLD_TURKIC => &_binary_resources_fonts_noto_NotoSansOldTurkic_Regular_otf_start,
1109        HB_SCRIPT_OLD_UYGHUR => &_binary_resources_fonts_noto_NotoSerifOldUyghur_Regular_otf_start,
1110        HB_SCRIPT_OL_CHIKI => &_binary_resources_fonts_noto_NotoSansOlChiki_Regular_otf_start,
1111        HB_SCRIPT_ORIYA => &_binary_resources_fonts_noto_NotoSerifOriya_Regular_otf_start,
1112        HB_SCRIPT_OSAGE => &_binary_resources_fonts_noto_NotoSansOsage_Regular_otf_start,
1113        HB_SCRIPT_OSMANYA => &_binary_resources_fonts_noto_NotoSansOsmanya_Regular_otf_start,
1114        HB_SCRIPT_PAHAWH_HMONG => {
1115            &_binary_resources_fonts_noto_NotoSansPahawhHmong_Regular_otf_start
1116        }
1117        HB_SCRIPT_PALMYRENE => &_binary_resources_fonts_noto_NotoSansPalmyrene_Regular_otf_start,
1118        HB_SCRIPT_PAU_CIN_HAU => &_binary_resources_fonts_noto_NotoSansPauCinHau_Regular_otf_start,
1119        HB_SCRIPT_PHAGS_PA => &_binary_resources_fonts_noto_NotoSansPhagsPa_Regular_otf_start,
1120        HB_SCRIPT_PHOENICIAN => &_binary_resources_fonts_noto_NotoSansPhoenician_Regular_otf_start,
1121        HB_SCRIPT_PSALTER_PAHLAVI => {
1122            &_binary_resources_fonts_noto_NotoSansPsalterPahlavi_Regular_otf_start
1123        }
1124        HB_SCRIPT_REJANG => &_binary_resources_fonts_noto_NotoSansRejang_Regular_otf_start,
1125        HB_SCRIPT_RUNIC => &_binary_resources_fonts_noto_NotoSansRunic_Regular_otf_start,
1126        HB_SCRIPT_SAMARITAN => &_binary_resources_fonts_noto_NotoSansSamaritan_Regular_otf_start,
1127        HB_SCRIPT_SAURASHTRA => &_binary_resources_fonts_noto_NotoSansSaurashtra_Regular_otf_start,
1128        HB_SCRIPT_SHARADA => &_binary_resources_fonts_noto_NotoSansSharada_Regular_otf_start,
1129        HB_SCRIPT_SHAVIAN => &_binary_resources_fonts_noto_NotoSansShavian_Regular_otf_start,
1130        HB_SCRIPT_SIDDHAM => &_binary_resources_fonts_noto_NotoSansSiddham_Regular_otf_start,
1131        HB_SCRIPT_SIGNWRITING => {
1132            &_binary_resources_fonts_noto_NotoSansSignWriting_Regular_otf_start
1133        }
1134        HB_SCRIPT_SINHALA => &_binary_resources_fonts_noto_NotoSerifSinhala_Regular_otf_start,
1135        HB_SCRIPT_SOGDIAN => &_binary_resources_fonts_noto_NotoSansSogdian_Regular_otf_start,
1136        HB_SCRIPT_SORA_SOMPENG => {
1137            &_binary_resources_fonts_noto_NotoSansSoraSompeng_Regular_otf_start
1138        }
1139        HB_SCRIPT_SOYOMBO => &_binary_resources_fonts_noto_NotoSansSoyombo_Regular_otf_start,
1140        HB_SCRIPT_SUNDANESE => &_binary_resources_fonts_noto_NotoSansSundanese_Regular_otf_start,
1141        HB_SCRIPT_SYLOTI_NAGRI => {
1142            &_binary_resources_fonts_noto_NotoSansSylotiNagri_Regular_otf_start
1143        }
1144        HB_SCRIPT_TAGALOG => &_binary_resources_fonts_noto_NotoSansTagalog_Regular_otf_start,
1145        HB_SCRIPT_TAGBANWA => &_binary_resources_fonts_noto_NotoSansTagbanwa_Regular_otf_start,
1146        HB_SCRIPT_TAI_LE => &_binary_resources_fonts_noto_NotoSansTaiLe_Regular_otf_start,
1147        HB_SCRIPT_TAI_THAM => &_binary_resources_fonts_noto_NotoSansTaiTham_Regular_otf_start,
1148        HB_SCRIPT_TAI_VIET => &_binary_resources_fonts_noto_NotoSansTaiViet_Regular_otf_start,
1149        HB_SCRIPT_TAKRI => &_binary_resources_fonts_noto_NotoSansTakri_Regular_otf_start,
1150        HB_SCRIPT_TAMIL => &_binary_resources_fonts_noto_NotoSerifTamil_Regular_otf_start,
1151        HB_SCRIPT_TANGSA => &_binary_resources_fonts_noto_NotoSansTangsa_Regular_otf_start,
1152        HB_SCRIPT_TELUGU => &_binary_resources_fonts_noto_NotoSerifTelugu_Regular_otf_start,
1153        HB_SCRIPT_THAANA => &_binary_resources_fonts_noto_NotoSansThaana_Regular_otf_start,
1154        HB_SCRIPT_THAI => &_binary_resources_fonts_noto_NotoSerifThai_Regular_otf_start,
1155        HB_SCRIPT_TIBETAN => &_binary_resources_fonts_noto_NotoSerifTibetan_Regular_otf_start,
1156        HB_SCRIPT_TIFINAGH => &_binary_resources_fonts_noto_NotoSansTifinagh_Regular_otf_start,
1157        HB_SCRIPT_TIRHUTA => &_binary_resources_fonts_noto_NotoSansTirhuta_Regular_otf_start,
1158        HB_SCRIPT_TOTO => &_binary_resources_fonts_noto_NotoSerifToto_Regular_otf_start,
1159        HB_SCRIPT_UGARITIC => &_binary_resources_fonts_noto_NotoSansUgaritic_Regular_otf_start,
1160        HB_SCRIPT_VAI => &_binary_resources_fonts_noto_NotoSansVai_Regular_otf_start,
1161        HB_SCRIPT_VITHKUQI => &_binary_resources_fonts_noto_NotoSerifVithkuqi_Regular_otf_start,
1162        HB_SCRIPT_WANCHO => &_binary_resources_fonts_noto_NotoSansWancho_Regular_otf_start,
1163        HB_SCRIPT_WARANG_CITI => &_binary_resources_fonts_noto_NotoSansWarangCiti_Regular_otf_start,
1164        HB_SCRIPT_YEZIDI => &_binary_resources_fonts_noto_NotoSerifYezidi_Regular_otf_start,
1165        HB_SCRIPT_YI => &_binary_resources_fonts_noto_NotoSansYi_Regular_otf_start,
1166        HB_SCRIPT_ZANABAZAR_SQUARE => {
1167            &_binary_resources_fonts_noto_NotoSansZanabazarSquare_Regular_otf_start
1168        }
1169
1170        HB_SYMBOL_MATHS => &_binary_resources_fonts_noto_NotoSansMath_Regular_otf_start,
1171        HB_SYMBOL_MUSIC => &_binary_resources_fonts_noto_NotoMusic_Regular_otf_start,
1172        HB_SYMBOL_MISC_ONE => &_binary_resources_fonts_noto_NotoSansSymbols_Regular_otf_start,
1173        HB_SCRIPT_BRAILLE | HB_SYMBOL_MISC_TWO => {
1174            &_binary_resources_fonts_noto_NotoSansSymbols2_Regular_otf_start
1175        }
1176        HB_SYMBOL_EMOJI => &_binary_resources_fonts_noto_NotoEmoji_Regular_ttf_start,
1177
1178        _ => &_binary_resources_fonts_droid_DroidSansFallback_ttf_start,
1179    }
1180}
1181
1182#[inline]
1183fn script_from_code(code: u32) -> HbScript {
1184    // Can be updated when the font changes by comparing the expanded output of
1185    // `ttfdump -t cmap` for each font.
1186    match code {
1187        0x2032..=0x2037
1188        | 0x2057
1189        | 0x20D0..=0x20DC
1190        | 0x20E1
1191        | 0x20E5..=0x20EF
1192        | 0x2102
1193        | 0x210A..=0x210E
1194        | 0x2110..=0x2112
1195        | 0x2115
1196        | 0x2119..=0x211D
1197        | 0x2124
1198        | 0x2128
1199        | 0x212C
1200        | 0x212D
1201        | 0x212F..=0x2131
1202        | 0x2133..=0x2138
1203        | 0x213C..=0x2140
1204        | 0x2145..=0x2149
1205        | 0x2190..=0x21AE
1206        | 0x21B0..=0x21E5
1207        | 0x21F1
1208        | 0x21F2
1209        | 0x21F4..=0x22FF
1210        | 0x2308..=0x230B
1211        | 0x2310
1212        | 0x2319
1213        | 0x231C..=0x2321
1214        | 0x2336..=0x237A
1215        | 0x237C
1216        | 0x2395
1217        | 0x239B..=0x23B6
1218        | 0x23D0
1219        | 0x23DC..=0x23E1
1220        | 0x2474
1221        | 0x2475
1222        | 0x25AF
1223        | 0x25B3
1224        | 0x25B7
1225        | 0x25BD
1226        | 0x25C1
1227        | 0x25CA
1228        | 0x25CC
1229        | 0x25FB
1230        | 0x266D..=0x266F
1231        | 0x27C0..=0x27FF
1232        | 0x2900..=0x2AFF
1233        | 0x2B0E..=0x2B11
1234        | 0x2B30..=0x2B4C
1235        | 0x2BFE
1236        | 0xFF5B
1237        | 0xFF5D
1238        | 0x1D400..=0x1D454
1239        | 0x1D456..=0x1D49C
1240        | 0x1D49E
1241        | 0x1D49F
1242        | 0x1D4A2
1243        | 0x1D4A5
1244        | 0x1D4A6
1245        | 0x1D4A9..=0x1D4AC
1246        | 0x1D4AE..=0x1D4B9
1247        | 0x1D4BB
1248        | 0x1D4BD..=0x1D4C3
1249        | 0x1D4C5..=0x1D505
1250        | 0x1D507..=0x1D50A
1251        | 0x1D50D..=0x1D514
1252        | 0x1D516..=0x1D51C
1253        | 0x1D51E..=0x1D539
1254        | 0x1D53B..=0x1D53E
1255        | 0x1D540..=0x1D544
1256        | 0x1D546
1257        | 0x1D54A..=0x1D550
1258        | 0x1D552..=0x1D6A5
1259        | 0x1D6A8..=0x1D7CB
1260        | 0x1D7CE..=0x1D7FF
1261        | 0x1EE00..=0x1EE03
1262        | 0x1EE05..=0x1EE1F
1263        | 0x1EE21
1264        | 0x1EE22
1265        | 0x1EE24
1266        | 0x1EE27
1267        | 0x1EE29..=0x1EE32
1268        | 0x1EE34..=0x1EE37
1269        | 0x1EE39
1270        | 0x1EE3B
1271        | 0x1EE42
1272        | 0x1EE47
1273        | 0x1EE49
1274        | 0x1EE4B
1275        | 0x1EE4D..=0x1EE4F
1276        | 0x1EE51
1277        | 0x1EE52
1278        | 0x1EE54
1279        | 0x1EE57
1280        | 0x1EE59
1281        | 0x1EE5B
1282        | 0x1EE5D
1283        | 0x1EE5F
1284        | 0x1EE61
1285        | 0x1EE62
1286        | 0x1EE64
1287        | 0x1EE67..=0x1EE6A
1288        | 0x1EE6C..=0x1EE72
1289        | 0x1EE74..=0x1EE77
1290        | 0x1EE79..=0x1EE7C
1291        | 0x1EE7E
1292        | 0x1EE80..=0x1EE89
1293        | 0x1EE8B..=0x1EE9B
1294        | 0x1EEA1..=0x1EEA3
1295        | 0x1EEA5..=0x1EEA9
1296        | 0x1EEAB..=0x1EEBB
1297        | 0x1EEF0
1298        | 0x1EEF1 => HB_SYMBOL_MATHS,
1299
1300        0x1D000..=0x1D0F5 | 0x1D100..=0x1D126 | 0x1D129..=0x1D1E8 | 0x1D200..=0x1D245 => {
1301            HB_SYMBOL_MUSIC
1302        }
1303
1304        0x20DD..=0x20E0
1305        | 0x20E2..=0x20E4
1306        | 0x2160..=0x2183
1307        | 0x2185..=0x2188
1308        | 0x218A
1309        | 0x218B
1310        | 0x2300..=0x230F
1311        | 0x2311..=0x2315
1312        | 0x2317
1313        | 0x2322
1314        | 0x2323
1315        | 0x2329
1316        | 0x232A
1317        | 0x232C..=0x2335
1318        | 0x2380..=0x2394
1319        | 0x2396..=0x239A
1320        | 0x23BE..=0x23CD
1321        | 0x23D1..=0x23DB
1322        | 0x23E2..=0x23E8
1323        | 0x2460..=0x24FF
1324        | 0x260A..=0x260D
1325        | 0x2613
1326        | 0x2624..=0x262F
1327        | 0x2638..=0x263B
1328        | 0x263D..=0x2653
1329        | 0x2669..=0x267E
1330        | 0x2690..=0x269D
1331        | 0x26A2..=0x26A9
1332        | 0x26AD..=0x26BC
1333        | 0x26CE
1334        | 0x26E2..=0x26FF
1335        | 0x271D..=0x2721
1336        | 0x2776..=0x2793
1337        | 0x1F100..=0x1F10C
1338        | 0x1F110..=0x1F12F
1339        | 0x1F130..=0x1F16C
1340        | 0x1F170..=0x1F190
1341        | 0x1F19B..=0x1F1AC
1342        | 0x1F546..=0x1F549
1343        | 0x1F54F
1344        | 0x1F610
1345        | 0x1F700..=0x1F773 => HB_SYMBOL_MISC_ONE,
1346
1347        0x2022
1348        | 0x21AF
1349        | 0x21E6..=0x21F0
1350        | 0x21F3
1351        | 0x2316
1352        | 0x2318
1353        | 0x231A
1354        | 0x231B
1355        | 0x2324..=0x2328
1356        | 0x232B
1357        | 0x237B
1358        | 0x237D..=0x237F
1359        | 0x23CE
1360        | 0x23CF
1361        | 0x23E9
1362        | 0x23ED..=0x23EF
1363        | 0x23F1..=0x23FF
1364        | 0x2400..=0x2426
1365        | 0x2440..=0x244A
1366        | 0x25A0..=0x2609
1367        | 0x260E..=0x2612
1368        | 0x2614..=0x2623
1369        | 0x2630..=0x2637
1370        | 0x263C
1371        | 0x2654..=0x2668
1372        | 0x267F..=0x268F
1373        | 0x269E..=0x26A1
1374        | 0x26AA..=0x26AC
1375        | 0x26BD..=0x26CD
1376        | 0x26CF..=0x26E1
1377        | 0x2700..=0x2704
1378        | 0x2706..=0x2709
1379        | 0x270B..=0x271C
1380        | 0x2722..=0x2727
1381        | 0x2729..=0x274B
1382        | 0x274D
1383        | 0x274F..=0x2752
1384        | 0x2756..=0x2775
1385        | 0x2794
1386        | 0x2798..=0x27AF
1387        | 0x27B1..=0x27BE
1388        | 0x2800..=0x28FF
1389        | 0x2B00..=0x2B0D
1390        | 0x2B12..=0x2B2F
1391        | 0x2B4D..=0x2B73
1392        | 0x2B76..=0x2B95
1393        | 0x2B97..=0x2BFD
1394        | 0x2BFF
1395        | 0x4DC0..=0x4DFF
1396        | 0xFFF9..=0xFFFB
1397        | 0x10140..=0x1018E
1398        | 0x10190..=0x1019C
1399        | 0x101A0
1400        | 0x101D0..=0x101FD
1401        | 0x102E0..=0x102FB
1402        | 0x10E60..=0x10E7E
1403        | 0x1D2E0..=0x1D2F3
1404        | 0x1D300..=0x1D356
1405        | 0x1D360..=0x1D378
1406        | 0x1F000..=0x1F02B
1407        | 0x1F030..=0x1F093
1408        | 0x1F0A0..=0x1F0AE
1409        | 0x1F0B1..=0x1F0BF
1410        | 0x1F0C1..=0x1F0CF
1411        | 0x1F0D1..=0x1F0F5
1412        | 0x1F30D..=0x1F30F
1413        | 0x1F315
1414        | 0x1F31C
1415        | 0x1F321..=0x1F32C
1416        | 0x1F336
1417        | 0x1F378
1418        | 0x1F37D
1419        | 0x1F394..=0x1F39F
1420        | 0x1F3A7
1421        | 0x1F3AC..=0x1F3AE
1422        | 0x1F3C2
1423        | 0x1F3CB..=0x1F3CE
1424        | 0x1F3D4..=0x1F3DF
1425        | 0x1F3ED
1426        | 0x1F3F1..=0x1F3F3
1427        | 0x1F3F5..=0x1F3F7
1428        | 0x1F408
1429        | 0x1F415
1430        | 0x1F41F
1431        | 0x1F426
1432        | 0x1F43F
1433        | 0x1F441
1434        | 0x1F446..=0x1F449
1435        | 0x1F44C..=0x1F44E
1436        | 0x1F453
1437        | 0x1F46A
1438        | 0x1F47D
1439        | 0x1F4A3
1440        | 0x1F4B0
1441        | 0x1F4B3
1442        | 0x1F4B9
1443        | 0x1F4BB
1444        | 0x1F4BF
1445        | 0x1F4C8..=0x1F4CB
1446        | 0x1F4DA
1447        | 0x1F4DF
1448        | 0x1F4E4..=0x1F4E6
1449        | 0x1F4EA..=0x1F4ED
1450        | 0x1F4F9..=0x1F4FB
1451        | 0x1F4FD
1452        | 0x1F4FE
1453        | 0x1F503
1454        | 0x1F507..=0x1F50A
1455        | 0x1F50D
1456        | 0x1F512
1457        | 0x1F513
1458        | 0x1F53E..=0x1F545
1459        | 0x1F54A
1460        | 0x1F550..=0x1F579
1461        | 0x1F57B..=0x1F594
1462        | 0x1F597..=0x1F5A3
1463        | 0x1F5A5..=0x1F5FA
1464        | 0x1F650..=0x1F67F
1465        | 0x1F687
1466        | 0x1F68D
1467        | 0x1F691
1468        | 0x1F694
1469        | 0x1F698
1470        | 0x1F6AD
1471        | 0x1F6B2
1472        | 0x1F6B9
1473        | 0x1F6BA
1474        | 0x1F6BC
1475        | 0x1F6C6..=0x1F6CB
1476        | 0x1F6CD..=0x1F6CF
1477        | 0x1F6D3..=0x1F6D7
1478        | 0x1F6E0..=0x1F6EA
1479        | 0x1F6F0..=0x1F6F3
1480        | 0x1F6F7..=0x1F6FC
1481        | 0x1F780..=0x1F7D8
1482        | 0x1F7E0..=0x1F7EB
1483        | 0x1F800..=0x1F80B
1484        | 0x1F810..=0x1F847
1485        | 0x1F850..=0x1F859
1486        | 0x1F860..=0x1F887
1487        | 0x1F890..=0x1F8AD
1488        | 0x1F8B0..=0x1F8B1
1489        | 0x1F93B
1490        | 0x1F946
1491        | 0x1FA00..=0x1FA53
1492        | 0x1FA60..=0x1FA6D
1493        | 0x1FA70..=0x1FA74
1494        | 0x1FA78..=0x1FA7A
1495        | 0x1FA80..=0x1FA86
1496        | 0x1FA90..=0x1FAA8
1497        | 0x1FAB0..=0x1FAB6
1498        | 0x1FAC0..=0x1FAC2
1499        | 0x1FAD0..=0x1FAD6
1500        | 0x1FB00..=0x1FBCA
1501        | 0x1FBF0..=0x1FBF9 => HB_SYMBOL_MISC_TWO,
1502
1503        0x2049
1504        | 0x2122
1505        | 0x2139
1506        | 0x23EA..=0x23EC
1507        | 0x23F0
1508        | 0x2705
1509        | 0x2708..=0x270C
1510        | 0x2728
1511        | 0x274C
1512        | 0x274E
1513        | 0x2753..=0x2755
1514        | 0x2795..=0x2797
1515        | 0x27B0
1516        | 0x27BF
1517        | 0x3030
1518        | 0x303D
1519        | 0x3297
1520        | 0x3299
1521        | 0xFEFF
1522        | 0x1F191..=0x1F19A
1523        | 0x1F1E6..=0x1F1FF
1524        | 0x1F201
1525        | 0x1F202
1526        | 0x1F21A
1527        | 0x1F22F
1528        | 0x1F232..=0x1F23A
1529        | 0x1F250
1530        | 0x1F251
1531        | 0x1F300..=0x1F320
1532        | 0x1F330..=0x1F335
1533        | 0x1F337..=0x1F37C
1534        | 0x1F380..=0x1F393
1535        | 0x1F3A0..=0x1F3C4
1536        | 0x1F3C6..=0x1F3CA
1537        | 0x1F3E0..=0x1F3F0
1538        | 0x1F400..=0x1F429
1539        | 0x1F42B..=0x1F43E
1540        | 0x1F440
1541        | 0x1F442..=0x1F4F7
1542        | 0x1F4F9..=0x1F4FC
1543        | 0x1F500..=0x1F53D
1544        | 0x1F5FB..=0x1F640
1545        | 0x1F645..=0x1F64F
1546        | 0x1F680..=0x1F697
1547        | 0x1F699..=0x1F6C5
1548        | 0xFE4E5..=0xFE4EE
1549        | 0xFE82C
1550        | 0xFE82E..=0xFE837 => HB_SYMBOL_EMOJI,
1551
1552        _ => HB_SCRIPT_UNKNOWN,
1553    }
1554}
1555
1556pub struct FontLibrary(*mut FtLibrary);
1557
1558pub struct FontOpener(Rc<FontLibrary>);
1559
1560pub struct Font {
1561    lib: Rc<FontLibrary>,
1562    face: *mut FtFace,
1563    font: *mut HbFont,
1564    size: u32,
1565    dpi: u16,
1566    // used as truncation mark
1567    pub ellipsis: RenderPlan,
1568    // lowercase and uppercase x heights
1569    pub x_heights: (u32, u32),
1570    space_codepoint: u32,
1571}
1572
1573impl FontOpener {
1574    pub fn new() -> Result<FontOpener, Error> {
1575        unsafe {
1576            let mut lib = ptr::null_mut();
1577            let ret = FT_Init_FreeType(&mut lib);
1578            if ret != FT_ERR_OK {
1579                Err(Error::from(FreetypeError::from(ret)))
1580            } else {
1581                Ok(FontOpener(Rc::new(FontLibrary(lib))))
1582            }
1583        }
1584    }
1585
1586    pub fn open<P: AsRef<Path>>(&self, path: P) -> Result<Font, Error> {
1587        unsafe {
1588            let mut face = ptr::null_mut();
1589            let c_path = CString::new(path.as_ref().as_os_str().as_bytes()).unwrap();
1590            let ret = FT_New_Face((self.0).0, c_path.as_ptr(), 0, &mut face);
1591            if ret != FT_ERR_OK {
1592                return Err(Error::from(FreetypeError::from(ret)));
1593            }
1594            let font = ptr::null_mut();
1595            let ellipsis = RenderPlan::default();
1596            let x_heights = (0, 0);
1597            let space_codepoint = FT_Get_Char_Index(face, ' ' as libc::c_ulong);
1598            Ok(Font {
1599                lib: self.0.clone(),
1600                face,
1601                font,
1602                size: 0,
1603                dpi: 0,
1604                ellipsis,
1605                x_heights,
1606                space_codepoint,
1607            })
1608        }
1609    }
1610
1611    pub fn open_memory(&self, buf: &[u8]) -> Result<Font, Error> {
1612        unsafe {
1613            let mut face = ptr::null_mut();
1614            let ret = FT_New_Memory_Face(
1615                (self.0).0,
1616                buf.as_ptr() as *const FtByte,
1617                buf.len() as libc::c_long,
1618                0,
1619                &mut face,
1620            );
1621            if ret != FT_ERR_OK {
1622                return Err(Error::from(FreetypeError::from(ret)));
1623            }
1624            let ellipsis = RenderPlan::default();
1625            let font = ptr::null_mut();
1626            let x_heights = (0, 0);
1627            let space_codepoint = FT_Get_Char_Index(face, ' ' as libc::c_ulong);
1628            Ok(Font {
1629                lib: self.0.clone(),
1630                face,
1631                font,
1632                size: 0,
1633                dpi: 0,
1634                ellipsis,
1635                x_heights,
1636                space_codepoint,
1637            })
1638        }
1639    }
1640}
1641
1642impl Font {
1643    pub fn family_name(&self) -> Option<&str> {
1644        unsafe {
1645            let ptr = (*self.face).family_name;
1646            if ptr.is_null() {
1647                return None;
1648            }
1649            CStr::from_ptr(ptr).to_str().ok()
1650        }
1651    }
1652
1653    pub fn style_name(&self) -> Option<&str> {
1654        unsafe {
1655            let ptr = (*self.face).style_name;
1656            if ptr.is_null() {
1657                return None;
1658            }
1659            CStr::from_ptr(ptr).to_str().ok()
1660        }
1661    }
1662
1663    pub fn set_size(&mut self, size: u32, dpi: u16) {
1664        if !self.font.is_null() && self.size == size && self.dpi == dpi {
1665            return;
1666        }
1667
1668        self.size = size;
1669        self.dpi = dpi;
1670
1671        unsafe {
1672            let ret = FT_Set_Char_Size(self.face, size as FtF26Dot6, 0, dpi as libc::c_uint, 0);
1673
1674            if ret != FT_ERR_OK {
1675                return;
1676            }
1677
1678            if self.font.is_null() {
1679                self.font = hb_ft_font_create(self.face, ptr::null());
1680            } else {
1681                hb_ft_font_changed(self.font);
1682            }
1683
1684            self.ellipsis = self.plan("…", None, None);
1685            self.x_heights = (self.height('x'), self.height('X'));
1686        }
1687    }
1688
1689    pub fn set_variations(&mut self, specs: &[&str]) {
1690        unsafe {
1691            let mut varia = ptr::null_mut();
1692            let ret = FT_Get_MM_Var(self.face, &mut varia);
1693
1694            if ret != FT_ERR_OK {
1695                return;
1696            }
1697
1698            let axes_count = (*varia).num_axis as usize;
1699            let mut coords = Vec::with_capacity(axes_count);
1700
1701            for i in 0..(axes_count as isize) {
1702                let axis = ((*varia).axis).offset(i);
1703                coords.push((*axis).def);
1704            }
1705
1706            for s in specs {
1707                let tn = s[..4].as_bytes();
1708                let tag = tag(tn[0], tn[1], tn[2], tn[3]);
1709                let value: f32 = s[5..].parse().unwrap_or_default();
1710
1711                for i in 0..(axes_count as isize) {
1712                    let axis = ((*varia).axis).offset(i);
1713
1714                    if (*axis).tag == tag as libc::c_ulong {
1715                        let scaled_value = ((value * 65536.0) as FtFixed)
1716                            .min((*axis).maximum)
1717                            .max((*axis).minimum);
1718                        *coords.get_unchecked_mut(i as usize) = scaled_value;
1719                        break;
1720                    }
1721                }
1722            }
1723
1724            let ret = FT_Set_Var_Design_Coordinates(
1725                self.face,
1726                coords.len() as libc::c_uint,
1727                coords.as_ptr(),
1728            );
1729
1730            if ret == FT_ERR_OK && !self.font.is_null() {
1731                hb_ft_font_changed(self.font);
1732            }
1733
1734            FT_Done_MM_Var(self.lib.0, varia);
1735        }
1736    }
1737
1738    pub fn set_variations_from_name(&mut self, name: &str) -> bool {
1739        let mut found = false;
1740
1741        unsafe {
1742            let mut varia = ptr::null_mut();
1743            let ret = FT_Get_MM_Var(self.face, &mut varia);
1744
1745            if ret != FT_ERR_OK {
1746                return found;
1747            }
1748
1749            let styles_count = (*varia).num_namedstyles as isize;
1750            let names_count = FT_Get_Sfnt_Name_Count(self.face);
1751            let mut sfnt_name = FtSfntName::default();
1752
1753            'outer: for i in 0..styles_count {
1754                let style = ((*varia).namedstyle).offset(i);
1755                let strid = (*style).strid as libc::c_ushort;
1756                for j in 0..names_count {
1757                    let ret = FT_Get_Sfnt_Name(self.face, j, &mut sfnt_name);
1758
1759                    if ret != FT_ERR_OK || sfnt_name.name_id != strid {
1760                        continue;
1761                    }
1762
1763                    if sfnt_name.platform_id != TT_PLATFORM_MICROSOFT
1764                        || sfnt_name.encoding_id != TT_MS_ID_UNICODE_CS
1765                        || sfnt_name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES
1766                    {
1767                        continue;
1768                    }
1769
1770                    let slice = slice::from_raw_parts(sfnt_name.text, sfnt_name.len as usize);
1771                    // We're assuming ASCII encoded as UTF_16BE
1772                    let vec_ascii: Vec<u8> = slice
1773                        .iter()
1774                        .enumerate()
1775                        .filter_map(|x| if x.0 % 2 == 0 { None } else { Some(*x.1) })
1776                        .collect();
1777
1778                    if let Ok(name_str) = str::from_utf8(&vec_ascii[..]) {
1779                        if name.eq_ignore_ascii_case(name_str) {
1780                            found = true;
1781                            let ret = FT_Set_Var_Design_Coordinates(
1782                                self.face,
1783                                (*varia).num_axis,
1784                                (*style).coords,
1785                            );
1786                            if ret == FT_ERR_OK && !self.font.is_null() {
1787                                hb_ft_font_changed(self.font);
1788                            }
1789                            break 'outer;
1790                        }
1791                    }
1792                }
1793            }
1794
1795            FT_Done_MM_Var(self.lib.0, varia);
1796        }
1797
1798        found
1799    }
1800
1801    #[inline]
1802    unsafe fn patch(
1803        &mut self,
1804        txt: &str,
1805        features: &[HbFeature],
1806        render_plan: &mut RenderPlan,
1807        missing_glyphs: Vec<(usize, usize)>,
1808        buf: *mut HbBuffer,
1809    ) {
1810        let mut drift = 0;
1811        for (mut start, mut end) in missing_glyphs.into_iter() {
1812            start = (start as i32 + drift).max(0) as usize;
1813            end = (end as i32 + drift).max(0) as usize;
1814            hb_buffer_clear_contents(buf);
1815            let start_index = render_plan.glyphs[start].cluster;
1816            let end_index = render_plan
1817                .glyphs
1818                .get(end)
1819                .map(|g| g.cluster)
1820                .unwrap_or_else(|| txt.len());
1821            let chunk = &txt[start_index..end_index];
1822            hb_buffer_add_utf8(
1823                buf,
1824                chunk.as_ptr() as *const libc::c_char,
1825                chunk.len() as libc::c_int,
1826                0,
1827                -1,
1828            );
1829            hb_buffer_guess_segment_properties(buf);
1830            let mut script = hb_buffer_get_script(buf);
1831            if script == HB_SCRIPT_INVALID || script == HB_SCRIPT_UNKNOWN {
1832                if let Some(c) = chunk.chars().next() {
1833                    script = script_from_code(u32::from(c));
1834                }
1835            }
1836            let font_data = font_data_from_script(script);
1837            let mut face = ptr::null_mut();
1838            FT_New_Memory_Face(
1839                (self.lib).0,
1840                font_data.as_ptr() as *const FtByte,
1841                font_data.len() as libc::c_long,
1842                0,
1843                &mut face,
1844            );
1845            FT_Set_Pixel_Sizes(face, (*(*self.face).size).metrics.x_ppem as libc::c_uint, 0);
1846            let font = hb_ft_font_create(face, ptr::null());
1847            hb_shape(font, buf, features.as_ptr(), features.len() as libc::c_uint);
1848            let len = hb_buffer_get_length(buf) as usize;
1849            let info = hb_buffer_get_glyph_infos(buf, ptr::null_mut());
1850            let pos = hb_buffer_get_glyph_positions(buf, ptr::null_mut());
1851            let mut glyphs = Vec::with_capacity(len);
1852
1853            for i in 0..len {
1854                let pos_i = &*pos.add(i);
1855                let info_i = &*info.add(i);
1856                render_plan.width += pos_i.x_advance >> 6;
1857                glyphs.push(GlyphPlan {
1858                    codepoint: info_i.codepoint,
1859                    cluster: start_index + info_i.cluster as usize,
1860                    advance: pt!(pos_i.x_advance >> 6, pos_i.y_advance >> 6),
1861                    offset: pt!(pos_i.x_offset >> 6, -pos_i.y_offset >> 6),
1862                });
1863                render_plan.scripts.insert(start + i, script);
1864            }
1865
1866            render_plan.glyphs.splice(start..end, glyphs.into_iter());
1867            drift += len as i32 - (end - start) as i32;
1868
1869            hb_font_destroy(font);
1870            FT_Done_Face(face);
1871        }
1872    }
1873
1874    pub fn plan<S: AsRef<str>>(
1875        &mut self,
1876        text: S,
1877        max_width: Option<i32>,
1878        features: Option<&[String]>,
1879    ) -> RenderPlan {
1880        unsafe {
1881            let buf = hb_buffer_create();
1882            hb_buffer_add_utf8(
1883                buf,
1884                text.as_ref().as_ptr() as *const libc::c_char,
1885                text.as_ref().len() as libc::c_int,
1886                0,
1887                -1,
1888            );
1889
1890            // If the direction is RTL, the clusters are given in reverse order.
1891            hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
1892            hb_buffer_guess_segment_properties(buf);
1893
1894            let features_vec: Vec<HbFeature> = features
1895                .map(|ftr| {
1896                    ftr.iter()
1897                        .filter_map(|f| {
1898                            let mut feature = HbFeature::default();
1899                            let ret = hb_feature_from_string(
1900                                f.as_ptr() as *const libc::c_char,
1901                                f.len() as libc::c_int,
1902                                &mut feature,
1903                            );
1904                            if ret == 1 {
1905                                Some(feature)
1906                            } else {
1907                                None
1908                            }
1909                        })
1910                        .collect()
1911                })
1912                .unwrap_or_default();
1913
1914            hb_shape(
1915                self.font,
1916                buf,
1917                features_vec.as_ptr(),
1918                features_vec.len() as libc::c_uint,
1919            );
1920
1921            let len = hb_buffer_get_length(buf) as usize;
1922            let info = hb_buffer_get_glyph_infos(buf, ptr::null_mut());
1923            let pos = hb_buffer_get_glyph_positions(buf, ptr::null_mut());
1924            let mut render_plan = RenderPlan::default();
1925            let mut missing_glyphs = Vec::new();
1926
1927            for i in 0..len {
1928                let pos_i = &*pos.add(i);
1929                let info_i = &*info.add(i);
1930                if info_i.codepoint == 0 {
1931                    if let Some((start, end)) = missing_glyphs.pop() {
1932                        if i == end {
1933                            missing_glyphs.push((start, end + 1));
1934                        } else {
1935                            missing_glyphs.push((start, end));
1936                            missing_glyphs.push((i, i + 1));
1937                        }
1938                    } else {
1939                        missing_glyphs.push((i, i + 1));
1940                    }
1941                } else {
1942                    render_plan.width += pos_i.x_advance >> 6;
1943                }
1944                let glyph = GlyphPlan {
1945                    codepoint: info_i.codepoint,
1946                    cluster: info_i.cluster as usize,
1947                    advance: pt!(pos_i.x_advance >> 6, pos_i.y_advance >> 6),
1948                    offset: pt!(pos_i.x_offset >> 6, -pos_i.y_offset >> 6),
1949                };
1950                render_plan.glyphs.push(glyph);
1951            }
1952
1953            self.patch(
1954                text.as_ref(),
1955                &features_vec,
1956                &mut render_plan,
1957                missing_glyphs,
1958                buf,
1959            );
1960
1961            hb_buffer_destroy(buf);
1962
1963            if let Some(mw) = max_width {
1964                self.crop_right(&mut render_plan, mw);
1965            }
1966
1967            render_plan
1968        }
1969    }
1970
1971    #[inline]
1972    pub fn crop_right(&self, render_plan: &mut RenderPlan, max_width: i32) {
1973        if render_plan.width <= max_width {
1974            return;
1975        }
1976
1977        render_plan.width += self.ellipsis.width;
1978
1979        while let Some(gp) = render_plan.glyphs.pop() {
1980            render_plan.width -= gp.advance.x;
1981            if render_plan.width <= max_width {
1982                break;
1983            }
1984        }
1985
1986        let len = render_plan.glyphs.len();
1987        render_plan.scripts.retain(|&k, _| k < len);
1988        render_plan
1989            .glyphs
1990            .extend_from_slice(&self.ellipsis.glyphs[..]);
1991    }
1992
1993    #[inline]
1994    pub fn trim_left(&self, render_plan: &mut RenderPlan) {
1995        if render_plan.glyphs.is_empty() {
1996            return;
1997        }
1998
1999        let mut i = 0;
2000
2001        while render_plan.glyphs[i].codepoint == self.space_codepoint {
2002            render_plan.width -= render_plan.glyphs[i].advance.x;
2003            i += 1;
2004        }
2005
2006        render_plan.glyphs.drain(..i);
2007        render_plan.scripts = render_plan
2008            .scripts
2009            .iter()
2010            .filter_map(|(&k, &v)| if k < i { None } else { Some((k - i, v)) })
2011            .collect();
2012    }
2013
2014    #[inline]
2015    pub fn crop_around(&self, render_plan: &mut RenderPlan, index: usize, max_width: i32) -> usize {
2016        if render_plan.width <= max_width {
2017            return 0;
2018        }
2019
2020        let len = render_plan.glyphs.len();
2021        let mut width = 0;
2022        let mut polarity = 0;
2023        let mut upper_index = index;
2024        let mut lower_index = index as i32 - 1;
2025
2026        loop {
2027            let next_width;
2028            if upper_index < len && (polarity % 2 == 0 || lower_index < 0) {
2029                next_width = width + render_plan.glyphs[upper_index].advance.x;
2030                if next_width > max_width {
2031                    break;
2032                } else {
2033                    width = next_width;
2034                }
2035                upper_index += 1;
2036            } else if lower_index >= 0 && (polarity % 2 == 1 || upper_index == len) {
2037                next_width = width + render_plan.glyphs[lower_index as usize].advance.x;
2038                if next_width > max_width {
2039                    break;
2040                } else {
2041                    width = next_width;
2042                }
2043                lower_index -= 1;
2044            }
2045            polarity += 1;
2046        }
2047
2048        if upper_index < len {
2049            width += self.ellipsis.width;
2050            upper_index -= 1;
2051            while width > max_width && upper_index > (lower_index.max(0) as usize) {
2052                width -= render_plan.glyphs[upper_index].advance.x;
2053                upper_index -= 1;
2054            }
2055            render_plan.glyphs.truncate(upper_index + 1);
2056            render_plan
2057                .glyphs
2058                .extend_from_slice(&self.ellipsis.glyphs[..]);
2059        }
2060
2061        if lower_index >= 0 {
2062            width += self.ellipsis.width;
2063            lower_index += 1;
2064            while width > max_width && (lower_index as usize) < upper_index {
2065                width -= render_plan.glyphs[lower_index as usize].advance.x;
2066                lower_index += 1;
2067            }
2068            render_plan.glyphs = self
2069                .ellipsis
2070                .glyphs
2071                .iter()
2072                .chain(render_plan.glyphs[lower_index as usize..].iter())
2073                .cloned()
2074                .collect();
2075        }
2076
2077        render_plan
2078            .scripts
2079            .retain(|&k, _| k >= lower_index.max(0) as usize && k <= upper_index);
2080        if lower_index > 0 {
2081            render_plan.scripts = render_plan
2082                .scripts
2083                .drain()
2084                .map(|(k, v)| (k - lower_index as usize + 1, v))
2085                .collect();
2086        }
2087        render_plan.width = width;
2088
2089        if lower_index < 0 {
2090            0
2091        } else {
2092            lower_index as usize
2093        }
2094    }
2095
2096    pub fn cut_point(&self, render_plan: &RenderPlan, max_width: i32) -> (usize, i32) {
2097        let mut width = render_plan.width;
2098        let glyphs = &render_plan.glyphs;
2099        let mut i = glyphs.len() - 1;
2100
2101        width -= glyphs[i].advance.x;
2102
2103        while i > 0 && width > max_width {
2104            i -= 1;
2105            width -= glyphs[i].advance.x;
2106        }
2107
2108        let j = i;
2109        let last_width = width;
2110
2111        while i > 0 && glyphs[i].codepoint != self.space_codepoint {
2112            i -= 1;
2113            width -= glyphs[i].advance.x;
2114        }
2115
2116        if i == 0 {
2117            i = j;
2118            width = last_width;
2119        }
2120
2121        (i, width)
2122    }
2123
2124    pub fn render(
2125        &mut self,
2126        fb: &mut dyn Framebuffer,
2127        color: Color,
2128        render_plan: &RenderPlan,
2129        origin: Point,
2130    ) {
2131        unsafe {
2132            let mut pos = origin;
2133            let mut fallback_faces = FxHashMap::default();
2134
2135            for (index, glyph) in render_plan.glyphs.iter().enumerate() {
2136                let face = if let Some(script) = render_plan.scripts.get(&index) {
2137                    *fallback_faces.entry(script).or_insert_with(|| {
2138                        let font_data = font_data_from_script(*script);
2139                        let mut face = ptr::null_mut();
2140                        FT_New_Memory_Face(
2141                            (self.lib).0,
2142                            font_data.as_ptr() as *const FtByte,
2143                            font_data.len() as libc::c_long,
2144                            0,
2145                            &mut face,
2146                        );
2147                        FT_Set_Pixel_Sizes(
2148                            face,
2149                            (*(*self.face).size).metrics.x_ppem as libc::c_uint,
2150                            0,
2151                        );
2152                        face
2153                    })
2154                } else {
2155                    self.face
2156                };
2157
2158                FT_Load_Glyph(face, glyph.codepoint, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
2159
2160                let glyph_slot = (*face).glyph;
2161                let top_left =
2162                    pos + glyph.offset + pt!((*glyph_slot).bitmap_left, -(*glyph_slot).bitmap_top);
2163                let bitmap = &(*glyph_slot).bitmap;
2164
2165                for y in 0..bitmap.rows {
2166                    for x in 0..bitmap.width {
2167                        let blackness = *bitmap.buffer.offset((bitmap.pitch * y + x) as isize);
2168                        let alpha = blackness as f32 / 255.0;
2169                        let pt = top_left + pt!(x, y);
2170                        fb.set_blended_pixel(pt.x as u32, pt.y as u32, color, alpha);
2171                    }
2172                }
2173
2174                pos += glyph.advance;
2175            }
2176
2177            for (_, face) in fallback_faces {
2178                FT_Done_Face(face);
2179            }
2180        }
2181    }
2182
2183    pub fn height(&self, c: char) -> u32 {
2184        unsafe {
2185            FT_Load_Char(self.face, c as libc::c_ulong, FT_LOAD_DEFAULT);
2186            let metrics = &((*(*self.face).glyph).metrics);
2187            (metrics.height >> 6) as u32
2188        }
2189    }
2190
2191    pub fn em(&self) -> u16 {
2192        unsafe { (*(*self.face).size).metrics.x_ppem as u16 }
2193    }
2194
2195    pub fn ascender(&self) -> i32 {
2196        unsafe { (*(*self.face).size).metrics.ascender as i32 / 64 }
2197    }
2198
2199    pub fn descender(&self) -> i32 {
2200        unsafe { (*(*self.face).size).metrics.descender as i32 / 64 }
2201    }
2202
2203    pub fn line_height(&self) -> i32 {
2204        unsafe { (*(*self.face).size).metrics.height as i32 / 64 }
2205    }
2206}
2207
2208#[derive(Debug, Copy, Clone)]
2209struct GlyphPlan {
2210    codepoint: u32,
2211    cluster: usize,
2212    offset: Point,
2213    advance: Point,
2214}
2215
2216#[derive(Debug, Clone)]
2217pub struct RenderPlan {
2218    pub width: i32,
2219    scripts: FxHashMap<usize, HbScript>,
2220    glyphs: Vec<GlyphPlan>,
2221}
2222
2223impl Default for RenderPlan {
2224    fn default() -> RenderPlan {
2225        RenderPlan {
2226            width: 0,
2227            scripts: FxHashMap::default(),
2228            glyphs: Vec::new(),
2229        }
2230    }
2231}
2232
2233impl RenderPlan {
2234    pub fn scale(&self, scale: f32) -> RenderPlan {
2235        let width = (scale * self.width as f32) as i32;
2236        let scripts = self.scripts.clone();
2237        let glyphs = self
2238            .glyphs
2239            .iter()
2240            .map(|gp| GlyphPlan {
2241                offset: Point::from(scale * Vec2::from(gp.offset)),
2242                advance: Point::from(scale * Vec2::from(gp.advance)),
2243                ..*gp
2244            })
2245            .collect();
2246        RenderPlan {
2247            width,
2248            scripts,
2249            glyphs,
2250        }
2251    }
2252
2253    pub fn space_out(&mut self, letter_spacing: i32) {
2254        if letter_spacing == 0 {
2255            return;
2256        }
2257
2258        if let Some((_, start)) = self.glyphs.split_last_mut() {
2259            let len = start.len() as i32;
2260            for glyph in start {
2261                glyph.advance.x += letter_spacing;
2262            }
2263            self.width += len * letter_spacing;
2264        }
2265    }
2266
2267    pub fn split_off(&mut self, index: usize, width: i32) -> RenderPlan {
2268        let mut next_scripts = FxHashMap::default();
2269        if !self.scripts.is_empty() {
2270            for i in index..self.glyphs.len() {
2271                self.scripts
2272                    .remove_entry(&i)
2273                    .map(|(k, v)| next_scripts.insert(k - index, v));
2274            }
2275        }
2276        let next_glyphs = self.glyphs.split_off(index);
2277        let next_width = self.width - width;
2278        self.width = width;
2279        RenderPlan {
2280            width: next_width,
2281            scripts: next_scripts,
2282            glyphs: next_glyphs,
2283        }
2284    }
2285
2286    pub fn index_from_advance(&self, advance: i32) -> usize {
2287        let mut sum = 0;
2288        let mut index = 0;
2289        while index < self.glyphs.len() {
2290            let gad = self.glyph_advance(index);
2291            sum += gad;
2292            if sum > advance {
2293                if sum - advance < advance - sum + gad {
2294                    index += 1;
2295                }
2296                break;
2297            }
2298            index += 1;
2299        }
2300        index
2301    }
2302
2303    pub fn append(&mut self, other: &mut Self) {
2304        let next_index = self.glyphs.len();
2305        self.scripts
2306            .extend(other.scripts.iter().map(|(k, v)| (next_index + k, *v)));
2307        self.glyphs.append(&mut other.glyphs);
2308        self.width += other.width;
2309    }
2310
2311    pub fn total_advance(&self, index: usize) -> i32 {
2312        self.glyphs.iter().take(index).map(|g| g.advance.x).sum()
2313    }
2314
2315    #[inline]
2316    pub fn glyph_advance(&self, index: usize) -> i32 {
2317        self.glyphs[index].advance.x
2318    }
2319}
2320
2321impl Drop for FontLibrary {
2322    fn drop(&mut self) {
2323        unsafe {
2324            FT_Done_FreeType(self.0);
2325        }
2326    }
2327}
2328
2329impl Drop for Font {
2330    fn drop(&mut self) {
2331        unsafe {
2332            FT_Done_Face(self.face);
2333            if !self.font.is_null() {
2334                hb_font_destroy(self.font);
2335            }
2336        }
2337    }
2338}
2339
2340#[inline]
2341fn tag(c1: u8, c2: u8, c3: u8, c4: u8) -> u32 {
2342    ((c1 as u32) << 24) | ((c2 as u32) << 16) | ((c3 as u32) << 8) | c4 as u32
2343}
2344
2345#[derive(Error, Debug)]
2346enum FreetypeError {
2347    #[error("Unknown error with code {0}.")]
2348    UnknownError(FtError),
2349
2350    #[error("Cannot open resource.")]
2351    CannotOpenResource,
2352
2353    #[error("Unknown file format.")]
2354    UnknownFileFormat,
2355
2356    #[error("Broken file.")]
2357    InvalidFileFormat,
2358
2359    #[error("Invalid FreeType version.")]
2360    InvalidVersion,
2361
2362    #[error("Module version is too low.")]
2363    LowerModuleVersion,
2364
2365    #[error("Invalid argument.")]
2366    InvalidArgument,
2367
2368    #[error("Unimplemented feature.")]
2369    UnimplementedFeature,
2370
2371    #[error("Broken table.")]
2372    InvalidTable,
2373
2374    #[error("Broken offset within table.")]
2375    InvalidOffset,
2376
2377    #[error("Array allocation size too large.")]
2378    ArrayTooLarge,
2379
2380    #[error("Missing module.")]
2381    MissingModule,
2382
2383    #[error("Missing property.")]
2384    MissingProperty,
2385
2386    #[error("Invalid glyph index.")]
2387    InvalidGlyphIndex,
2388
2389    #[error("Invalid character code.")]
2390    InvalidCharacterCode,
2391
2392    #[error("Unsupported glyph image format.")]
2393    InvalidGlyphFormat,
2394
2395    #[error("Cannot render this glyph format.")]
2396    CannotRenderGlyph,
2397
2398    #[error("Invalid outline.")]
2399    InvalidOutline,
2400
2401    #[error("Invalid composite glyph.")]
2402    InvalidComposite,
2403
2404    #[error("Too many hints.")]
2405    TooManyHints,
2406
2407    #[error("Invalid pixel size.")]
2408    InvalidPixelSize,
2409
2410    #[error("Invalid object handle.")]
2411    InvalidHandle,
2412
2413    #[error("Invalid library handle.")]
2414    InvalidLibraryHandle,
2415
2416    #[error("Invalid module handle.")]
2417    InvalidDriverHandle,
2418
2419    #[error("Invalid face handle.")]
2420    InvalidFaceHandle,
2421
2422    #[error("Invalid size handle.")]
2423    InvalidSizeHandle,
2424
2425    #[error("Invalid glyph slot handle.")]
2426    InvalidSlotHandle,
2427
2428    #[error("Invalid charmap handle.")]
2429    InvalidCharMapHandle,
2430
2431    #[error("Invalid cache manager handle.")]
2432    InvalidCacheHandle,
2433
2434    #[error("Invalid stream handle.")]
2435    InvalidStreamHandle,
2436
2437    #[error("Too many modules.")]
2438    TooManyDrivers,
2439
2440    #[error("Too many extensions.")]
2441    TooManyExtensions,
2442
2443    #[error("Out of memory.")]
2444    OutOfMemory,
2445
2446    #[error("Unlisted object.")]
2447    UnlistedObject,
2448
2449    #[error("Cannot open stream.")]
2450    CannotOpenStream,
2451
2452    #[error("Invalid stream seek.")]
2453    InvalidStreamSeek,
2454
2455    #[error("Invalid stream skip.")]
2456    InvalidStreamSkip,
2457
2458    #[error("Invalid stream read.")]
2459    InvalidStreamRead,
2460
2461    #[error("Invalid stream operation.")]
2462    InvalidStreamOperation,
2463
2464    #[error("Invalid frame operation.")]
2465    InvalidFrameOperation,
2466
2467    #[error("Nested frame access.")]
2468    NestedFrameAccess,
2469
2470    #[error("Invalid frame read.")]
2471    InvalidFrameRead,
2472
2473    #[error("Raster uninitialized.")]
2474    RasterUninitialized,
2475
2476    #[error("Raster corrupted.")]
2477    RasterCorrupted,
2478
2479    #[error("Raster overflow.")]
2480    RasterOverflow,
2481
2482    #[error("Negative height while rastering.")]
2483    RasterNegativeHeight,
2484
2485    #[error("Too many registered caches.")]
2486    TooManyCaches,
2487
2488    #[error("Invalid opcode.")]
2489    InvalidOpcode,
2490
2491    #[error("Too few arguments.")]
2492    TooFewArguments,
2493
2494    #[error("Stack overflow.")]
2495    StackOverflow,
2496
2497    #[error("Code overflow.")]
2498    CodeOverflow,
2499
2500    #[error("Bad argument.")]
2501    BadArgument,
2502
2503    #[error("Division by zero.")]
2504    DivideByZero,
2505
2506    #[error("Invalid reference.")]
2507    InvalidReference,
2508
2509    #[error("Found debug opcode.")]
2510    DebugOpCode,
2511
2512    #[error("Found ENDF opcode in execution stream.")]
2513    ENDFInExecStream,
2514
2515    #[error("Nested DEFS.")]
2516    NestedDEFS,
2517
2518    #[error("Invalid code range.")]
2519    InvalidCodeRange,
2520
2521    #[error("Execution context too long.")]
2522    ExecutionTooLong,
2523
2524    #[error("Too many function definitions.")]
2525    TooManyFunctionDefs,
2526
2527    #[error("Too many instruction definitions.")]
2528    TooManyInstructionDefs,
2529
2530    #[error("SFNT font table missing.")]
2531    TableMissing,
2532
2533    #[error("Horizontal header (hhea) table missing.")]
2534    HorizHeaderMissing,
2535
2536    #[error("Locations (loca) table missing.")]
2537    LocationsMissing,
2538
2539    #[error("Name table missing.")]
2540    NameTableMissing,
2541
2542    #[error("Character map (cmap) table missing.")]
2543    CMapTableMissing,
2544
2545    #[error("Horizontal metrics (hmtx) table missing.")]
2546    HmtxTableMissing,
2547
2548    #[error("PostScript (post) table missing.")]
2549    PostTableMissing,
2550
2551    #[error("Invalid horizontal metrics.")]
2552    InvalidHorizMetrics,
2553
2554    #[error("Invalid character map (cmap) format.")]
2555    InvalidCharMapFormat,
2556
2557    #[error("Invalid ppem value.")]
2558    InvalidPPem,
2559
2560    #[error("Invalid vertical metrics.")]
2561    InvalidVertMetrics,
2562
2563    #[error("Could not find context.")]
2564    CouldNotFindContext,
2565
2566    #[error("Invalid PostScript (post) table format.")]
2567    InvalidPostTableFormat,
2568
2569    #[error("Invalid PostScript (post) table.")]
2570    InvalidPostTable,
2571
2572    #[error("Found FDEF or IDEF opcode in glyf bytecode.")]
2573    DEFInGlyfBytecode,
2574
2575    #[error("Missing bitmap in strike.")]
2576    MissingBitmap,
2577
2578    #[error("Opcode syntax error.")]
2579    SyntaxError,
2580
2581    #[error("Argument stack underflow.")]
2582    StackUnderflow,
2583
2584    #[error("Ignore.")]
2585    Ignore,
2586
2587    #[error("No Unicode glyph name found.")]
2588    NoUnicodeGlyphName,
2589
2590    #[error("Glyph too big for hinting.")]
2591    GlyphTooBig,
2592
2593    #[error("`STARTFONT' field missing.")]
2594    MissingStartfontField,
2595
2596    #[error("`FONT' field missing.")]
2597    MissingFontField,
2598
2599    #[error("`SIZE' field missing.")]
2600    MissingSizeField,
2601
2602    #[error("`FONTBOUNDINGBOX' field missing.")]
2603    MissingFontboundingboxField,
2604
2605    #[error("`CHARS' field missing.")]
2606    MissingCharsField,
2607
2608    #[error("`STARTCHAR' field missing.")]
2609    MissingStartcharField,
2610
2611    #[error("`ENCODING' field missing.")]
2612    MissingEncodingField,
2613
2614    #[error("`BBX' field missing.")]
2615    MissingBbxField,
2616
2617    #[error("`BBX' too big.")]
2618    BbxTooBig,
2619
2620    #[error("Font header corrupted or missing fields.")]
2621    CorruptedFontHeader,
2622
2623    #[error("Font glyphs corrupted or missing fields.")]
2624    CorruptedFontGlyphs,
2625}
2626
2627impl From<FtError> for FreetypeError {
2628    fn from(code: FtError) -> FreetypeError {
2629        match code {
2630            0x01 => FreetypeError::CannotOpenResource,
2631            0x02 => FreetypeError::UnknownFileFormat,
2632            0x03 => FreetypeError::InvalidFileFormat,
2633            0x04 => FreetypeError::InvalidVersion,
2634            0x05 => FreetypeError::LowerModuleVersion,
2635            0x06 => FreetypeError::InvalidArgument,
2636            0x07 => FreetypeError::UnimplementedFeature,
2637            0x08 => FreetypeError::InvalidTable,
2638            0x09 => FreetypeError::InvalidOffset,
2639            0x0A => FreetypeError::ArrayTooLarge,
2640            0x0B => FreetypeError::MissingModule,
2641            0x0C => FreetypeError::MissingProperty,
2642            0x10 => FreetypeError::InvalidGlyphIndex,
2643            0x11 => FreetypeError::InvalidCharacterCode,
2644            0x12 => FreetypeError::InvalidGlyphFormat,
2645            0x13 => FreetypeError::CannotRenderGlyph,
2646            0x14 => FreetypeError::InvalidOutline,
2647            0x15 => FreetypeError::InvalidComposite,
2648            0x16 => FreetypeError::TooManyHints,
2649            0x17 => FreetypeError::InvalidPixelSize,
2650            0x20 => FreetypeError::InvalidHandle,
2651            0x21 => FreetypeError::InvalidLibraryHandle,
2652            0x22 => FreetypeError::InvalidDriverHandle,
2653            0x23 => FreetypeError::InvalidFaceHandle,
2654            0x24 => FreetypeError::InvalidSizeHandle,
2655            0x25 => FreetypeError::InvalidSlotHandle,
2656            0x26 => FreetypeError::InvalidCharMapHandle,
2657            0x27 => FreetypeError::InvalidCacheHandle,
2658            0x28 => FreetypeError::InvalidStreamHandle,
2659            0x30 => FreetypeError::TooManyDrivers,
2660            0x31 => FreetypeError::TooManyExtensions,
2661            0x40 => FreetypeError::OutOfMemory,
2662            0x41 => FreetypeError::UnlistedObject,
2663            0x51 => FreetypeError::CannotOpenStream,
2664            0x52 => FreetypeError::InvalidStreamSeek,
2665            0x53 => FreetypeError::InvalidStreamSkip,
2666            0x54 => FreetypeError::InvalidStreamRead,
2667            0x55 => FreetypeError::InvalidStreamOperation,
2668            0x56 => FreetypeError::InvalidFrameOperation,
2669            0x57 => FreetypeError::NestedFrameAccess,
2670            0x58 => FreetypeError::InvalidFrameRead,
2671            0x60 => FreetypeError::RasterUninitialized,
2672            0x61 => FreetypeError::RasterCorrupted,
2673            0x62 => FreetypeError::RasterOverflow,
2674            0x63 => FreetypeError::RasterNegativeHeight,
2675            0x70 => FreetypeError::TooManyCaches,
2676            0x80 => FreetypeError::InvalidOpcode,
2677            0x81 => FreetypeError::TooFewArguments,
2678            0x82 => FreetypeError::StackOverflow,
2679            0x83 => FreetypeError::CodeOverflow,
2680            0x84 => FreetypeError::BadArgument,
2681            0x85 => FreetypeError::DivideByZero,
2682            0x86 => FreetypeError::InvalidReference,
2683            0x87 => FreetypeError::DebugOpCode,
2684            0x88 => FreetypeError::ENDFInExecStream,
2685            0x89 => FreetypeError::NestedDEFS,
2686            0x8A => FreetypeError::InvalidCodeRange,
2687            0x8B => FreetypeError::ExecutionTooLong,
2688            0x8C => FreetypeError::TooManyFunctionDefs,
2689            0x8D => FreetypeError::TooManyInstructionDefs,
2690            0x8E => FreetypeError::TableMissing,
2691            0x8F => FreetypeError::HorizHeaderMissing,
2692            0x90 => FreetypeError::LocationsMissing,
2693            0x91 => FreetypeError::NameTableMissing,
2694            0x92 => FreetypeError::CMapTableMissing,
2695            0x93 => FreetypeError::HmtxTableMissing,
2696            0x94 => FreetypeError::PostTableMissing,
2697            0x95 => FreetypeError::InvalidHorizMetrics,
2698            0x96 => FreetypeError::InvalidCharMapFormat,
2699            0x97 => FreetypeError::InvalidPPem,
2700            0x98 => FreetypeError::InvalidVertMetrics,
2701            0x99 => FreetypeError::CouldNotFindContext,
2702            0x9A => FreetypeError::InvalidPostTableFormat,
2703            0x9B => FreetypeError::InvalidPostTable,
2704            0x9C => FreetypeError::DEFInGlyfBytecode,
2705            0x9D => FreetypeError::MissingBitmap,
2706            0xA0 => FreetypeError::SyntaxError,
2707            0xA1 => FreetypeError::StackUnderflow,
2708            0xA2 => FreetypeError::Ignore,
2709            0xA3 => FreetypeError::NoUnicodeGlyphName,
2710            0xA4 => FreetypeError::GlyphTooBig,
2711            0xB0 => FreetypeError::MissingStartfontField,
2712            0xB1 => FreetypeError::MissingFontField,
2713            0xB2 => FreetypeError::MissingSizeField,
2714            0xB3 => FreetypeError::MissingFontboundingboxField,
2715            0xB4 => FreetypeError::MissingCharsField,
2716            0xB5 => FreetypeError::MissingStartcharField,
2717            0xB6 => FreetypeError::MissingEncodingField,
2718            0xB7 => FreetypeError::MissingBbxField,
2719            0xB8 => FreetypeError::BbxTooBig,
2720            0xB9 => FreetypeError::CorruptedFontHeader,
2721            0xBA => FreetypeError::CorruptedFontGlyphs,
2722            _ => FreetypeError::UnknownError(code),
2723        }
2724    }
2725}