1use alloc::boxed::Box;
43use alloc::vec::Vec;
44
45use gfx::path::Path;
46use rt::fx::{floor_i, sqrt};
47
48use crate::cff::Cff;
49use crate::colr;
50use crate::font::*;
51use crate::outline::{Outline, OLT_ON};
52use crate::var::{tag_u32, Var, VAR_BUDGET};
53
54pub const ERR_FAIL: i32 = -1;
55pub const ERR_TRUNC: i32 = -1;
56pub const ERR_HDR: i32 = -2;
57pub const ERR_NOMEM: i32 = -8;
58pub const ERR_UNSUPPORTED: i32 = -9;
59pub const ERR_IO: i32 = -13;
60pub const ERR_LIMIT: i32 = -15;
61
62const TAG_TTCF: u32 = 0x7474_6366;
63const TAG_TRUE: u32 = 0x7472_7565;
64const TAG_OTTO: u32 = 0x4F54_544F;
65const TAG_V1: u32 = 0x0001_0000;
66const TAG_DFLT: u32 = 0x4446_4C54;
67const TAG_LATN: u32 = 0x6C61_746E;
68const TAG_KERNF: u32 = 0x6B65_726E;
69pub const FILE_MAX: u64 = 0x7FFF_FFF0;
70const GLYF_DEPTH: u32 = 16;
71const GLYF_BUDGET: i32 = 4096;
72const GPOS_LK_MAX: usize = 64;
73const KERN_SUB_MAX: usize = 8;
74const GPOS_SUB_MAX: usize = 96;
75pub const NAME_CAP: usize = 256;
76
77pub const TT_HEAD: usize = 0;
79pub const TT_HHEA: usize = 1;
80pub const TT_HMTX: usize = 2;
81pub const TT_MAXP: usize = 3;
82pub const TT_LOCA: usize = 4;
83pub const TT_GLYF: usize = 5;
84pub const TT_CMAP: usize = 6;
85pub const TT_OS2: usize = 7;
86pub const TT_POST: usize = 8;
87pub const TT_NAME: usize = 9;
88pub const TT_KERN: usize = 10;
89pub const TT_GPOS: usize = 11;
90pub const TT_CFF: usize = 12;
91pub const TT_COLR: usize = 13;
92pub const TT_CPAL: usize = 14;
93pub const TT_CBDT: usize = 15;
94pub const TT_CBLC: usize = 16;
95pub const TT_FVAR: usize = 17;
96pub const TT_CFF2: usize = 18;
97pub const TT_AVAR: usize = 20;
98pub const TT_GVAR: usize = 21;
99pub const TT_HVAR: usize = 22;
100pub const TT_MVAR: usize = 23;
101pub const TT_GDEF: usize = 24;
102pub const TT_COUNT: usize = 25;
103
104pub const TFK_TTF: u32 = 1;
105pub const TFK_CFF: u32 = 2;
106
107pub const TFF_LOCA_LONG: u32 = 2;
108pub const TFF_SYMBOL: u32 = 4;
109pub const TFF_COLR: u32 = 8;
110pub const TFF_CBDT: u32 = 16;
111pub const TFF_MACCMAP: u32 = 32;
112
113static TT_TAGS: [u32; TT_COUNT] = [
115 0x6865_6164, 0x6868_6561, 0x686D_7478, 0x6D61_7870, 0x6C6F_6361, 0x676C_7966, 0x636D_6170,
116 0x4F53_2F32, 0x706F_7374, 0x6E61_6D65, 0x6B65_726E, 0x4750_4F53, 0x4346_4620, 0x434F_4C52,
117 0x4350_414C, 0x4342_4454, 0x4342_4C43, 0x6676_6172, 0x4346_4632, 0x7668_6561, 0x6176_6172,
118 0x6776_6172, 0x4856_4152, 0x4D56_4152, 0x4744_4546,
119];
120static NAME_IDS: [u32; 5] = [FN_FAMILY, FN_STYLE, FN_FULL, FN_TYPO_FAMILY, FN_TYPO_STYLE];
121const F_INV16384: f32 = 0.000_061_035_156_25;
122
123static CP1252_HI: [u16; 32] = [
125 0x20AC, 0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0,
126 0x017D, 0, 0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A,
127 0x0153, 0, 0x017E, 0x0178,
128];
129
130pub static MAC_ROMAN: [u16; 128] = [
132 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5,
133 0x00E7, 0x00E9, 0x00E8, 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4,
134 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6,
135 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, 0x221E, 0x00B1, 0x2264, 0x2265,
136 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, 0x00BF,
137 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5,
138 0x0152, 0x0153, 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044,
139 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1,
140 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9,
141 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7,
142];
143
144pub(crate) fn be16(d: &[u8], o: usize) -> u32 {
147 u16::from_be_bytes([d[o], d[o + 1]]) as u32
148}
149
150pub(crate) fn be32(d: &[u8], o: usize) -> u32 {
151 u32::from_be_bytes([d[o], d[o + 1], d[o + 2], d[o + 3]])
152}
153
154#[derive(Clone, Copy)]
157pub struct Tb<'a>(pub &'a [u8]);
158
159impl Tb<'_> {
160 pub fn len(&self) -> u32 {
161 self.0.len() as u32
162 }
163
164 pub fn u8(&self, off: u32) -> i32 {
165 if off as usize >= self.0.len() { -1 } else { self.0[off as usize] as i32 }
166 }
167
168 pub fn u16(&self, off: u32) -> i32 {
170 if off as u64 + 2 > self.0.len() as u64 { -1 } else { be16(self.0, off as usize) as i32 }
171 }
172
173 pub fn u32(&self, off: u32) -> i64 {
175 if off as u64 + 4 > self.0.len() as u64 { -1 } else { be32(self.0, off as usize) as i64 }
176 }
177}
178
179fn popcnt8(v: u32) -> u32 {
180 (v & 0xFF).count_ones()
181}
182
183fn utf8_put(out: &mut Vec<u8>, cp: u32) {
184 if cp < 0x80 {
185 out.push(cp as u8);
186 } else if cp < 0x800 {
187 out.push(0xC0 | (cp >> 6) as u8);
188 out.push(0x80 | (cp & 0x3F) as u8);
189 } else if cp < 0x10000 {
190 out.push(0xE0 | (cp >> 12) as u8);
191 out.push(0x80 | ((cp >> 6) & 0x3F) as u8);
192 out.push(0x80 | (cp & 0x3F) as u8);
193 } else {
194 out.push(0xF0 | (cp >> 18) as u8);
195 out.push(0x80 | ((cp >> 12) & 0x3F) as u8);
196 out.push(0x80 | ((cp >> 6) & 0x3F) as u8);
197 out.push(0x80 | (cp & 0x3F) as u8);
198 }
199}
200
201pub fn face_count(d: &[u8]) -> i32 {
203 if d.len() < 12 {
204 return ERR_TRUNC;
205 }
206 match be32(d, 0) {
207 TAG_TTCF => {
208 let n = be32(d, 8);
209 if n == 0 || n > 65536 {
210 return ERR_HDR;
211 }
212 if n as u64 * 4 + 12 > d.len() as u64 {
213 return ERR_TRUNC;
214 }
215 n as i32
216 }
217 TAG_V1 | TAG_TRUE | TAG_OTTO => 1,
218 _ => ERR_HDR,
219 }
220}
221
222pub fn sfnt_name(tb: Tb, id: u32, cap: usize) -> Vec<u8> {
224 let mut out = Vec::new();
225 if cap == 0 || tb.len() < 6 {
226 return out;
227 }
228 let count = tb.u16(2) as u32;
229 let (mut best, mut best_rec) = (0u32, 0u32);
230 let mut i = 0u32;
231 while i < count {
232 let rec = i.wrapping_mul(12).wrapping_add(6);
233 let nid = tb.u16(rec.wrapping_add(6));
234 if nid < 0 {
235 break;
236 }
237 if nid as u32 == id {
238 let pid = tb.u16(rec) as u32;
239 let eid = tb.u16(rec.wrapping_add(2)) as u32;
240 let lang = tb.u16(rec.wrapping_add(4)) as u32;
241 let score = if pid == 3 {
242 if eid == 1 || eid == 10 || eid == 0 {
243 if lang == 0x0407 {
244 100
245 } else if lang & 0x3FF == 0x07 {
246 95
247 } else if lang == 0x0409 {
248 90
249 } else {
250 50
251 }
252 } else {
253 0
254 }
255 } else if pid == 0 {
256 60
257 } else if pid == 1 && eid == 0 && lang == 0 {
258 40
259 } else {
260 0
261 };
262 if score > best {
263 best = score;
264 best_rec = rec;
265 }
266 }
267 i += 1;
268 }
269 if best == 0 {
270 return out;
271 }
272 let r = best_rec;
273 let mut s = (tb.u16(4) as u32).wrapping_add(tb.u16(r.wrapping_add(10)) as u32);
274 let mut len = tb.u16(r.wrapping_add(8)) as u32;
275 let tl = tb.len();
276 if tl <= s {
277 return out;
278 }
279 if len > tl - s {
280 len = tl - s;
281 }
282 let end = len + s;
283 let mac = tb.u16(r) == 1;
284 let d = tb.0;
285 while s < end {
286 let mut cp;
287 if mac {
288 cp = d[s as usize] as u32;
289 s += 1;
290 if cp >= 0x80 {
291 cp = MAC_ROMAN[(cp - 0x80) as usize] as u32;
292 }
293 } else {
294 if s + 2 > end {
295 break;
296 }
297 cp = be16(d, s as usize);
298 s += 2;
299 let hi = cp & 0xFC00;
300 if hi == 0xD800 {
301 if s + 2 > end {
303 cp = 0xFFFD;
304 } else {
305 let lo = be16(d, s as usize);
306 if lo & 0xFC00 != 0xDC00 {
307 cp = 0xFFFD;
308 } else {
309 s += 2;
310 cp = (((cp & 0x3FF) << 10) | (lo & 0x3FF)) + 0x10000;
311 }
312 }
313 } else if hi == 0xDC00 {
314 cp = 0xFFFD;
315 }
316 }
317 if cp == 0 {
318 continue;
319 }
320 if cp < 0x20 {
321 cp = 0x20; }
323 if cap - out.len() < 5 {
324 break; }
326 utf8_put(&mut out, cp);
327 }
328 out
329}
330
331struct GlyfSt<'a> {
335 budget: i32,
336 xmin: i32,
337 rg: u32,
338 hasx: bool,
339 coords: &'a [i16],
340 pp: (f32, f32),
341 vbudget: u32,
342}
343
344impl GlyfSt<'_> {
345 fn new(coords: &[i16]) -> GlyfSt<'_> {
346 GlyfSt { budget: GLYF_BUDGET, xmin: 0, rg: 0, hasx: false, coords, pp: (0.0, 0.0), vbudget: VAR_BUDGET }
347 }
348}
349
350const MV_HASC: u32 = tag_u32(*b"hasc");
352const MV_HDSC: u32 = tag_u32(*b"hdsc");
353const MV_HLGP: u32 = tag_u32(*b"hlgp");
354const MV_HCLA: u32 = tag_u32(*b"hcla");
355const MV_HCLD: u32 = tag_u32(*b"hcld");
356const MV_XHGT: u32 = tag_u32(*b"xhgt");
357const MV_CPHT: u32 = tag_u32(*b"cpht");
358const MV_UNDO: u32 = tag_u32(*b"undo");
359const MV_UNDS: u32 = tag_u32(*b"unds");
360const MV_STRO: u32 = tag_u32(*b"stro");
361const MV_STRS: u32 = tag_u32(*b"strs");
362
363pub struct TtFont {
365 pub face_index: u32,
366 pub data: Vec<u8>,
367 pub hdr: Hdr,
368 pub fm: Metrics,
369 pub serial: u64, pub kind: u32,
371 pub flags: u32,
372 pub nglyphs: u32,
373 pub upem: u32,
374 nhm: u32,
375 cmap: u32,
376 cmapend: u32,
377 cmapfmt: u32,
378 pub tab: [(u32, u32); TT_COUNT],
379 kernsub: Vec<(u32, u32)>,
380 gpossub: Vec<(u32, u32)>,
381 pub names: [Vec<u8>; 5],
382 cff: Option<Box<Cff>>,
383 pub cpal: u32,
384 pub cpaln: u32,
385 pub(crate) var: Option<Box<Var>>,
387}
388
389impl TtFont {
390 pub(crate) fn tb(&self, idx: usize) -> Tb<'_> {
392 let (o, l) = self.tab[idx];
393 Tb(&self.data[o as usize..(o + l) as usize])
394 }
395
396 pub fn open(data: Vec<u8>, face: u32, ol: &mut Outline, serial: u64) -> Result<Box<TtFont>, i32> {
398 let len = data.len() as u64;
399 if len < 12 {
400 return Err(ERR_TRUNC);
401 }
402 if len > FILE_MAX {
403 return Err(ERR_LIMIT);
404 }
405 let mut dir = 0u32;
406 if be32(&data, 0) == TAG_TTCF {
407 let nfonts = be32(&data, 8);
408 if face >= nfonts {
409 return Err(ERR_FAIL);
410 }
411 if face as u64 * 4 + 16 > len {
412 return Err(ERR_TRUNC);
413 }
414 dir = be32(&data, face as usize * 4 + 12);
415 } else if face != 0 {
416 return Err(ERR_FAIL);
417 }
418 if dir as u64 + 12 > len {
419 return Err(ERR_TRUNC);
420 }
421 let v = be32(&data, dir as usize);
422 if v != TAG_V1 && v != TAG_TRUE && v != TAG_OTTO {
423 return Err(ERR_HDR);
424 }
425 let ntab = be16(&data, dir as usize + 4);
426 if ((ntab as u64) << 4) + dir as u64 + 12 > len {
427 return Err(ERR_TRUNC);
428 }
429 let mut f = Box::new(TtFont {
430 face_index: face,
431 data: Vec::new(),
432 hdr: Hdr::default(),
433 fm: Metrics::default(),
434 serial,
435 kind: 0,
436 flags: 0,
437 nglyphs: 0,
438 upem: 0,
439 nhm: 0,
440 cmap: 0,
441 cmapend: 0,
442 cmapfmt: 0,
443 tab: [(0, 0); TT_COUNT],
444 kernsub: Vec::new(),
445 gpossub: Vec::new(),
446 names: Default::default(),
447 cff: None,
448 cpal: 0,
449 cpaln: 0,
450 var: None,
451 });
452 for i in 0..ntab {
454 let r = (dir + 12 + i * 16) as usize;
455 let tag = be32(&data, r);
456 let off = be32(&data, r + 8);
457 let tl = be32(&data, r + 12);
458 let Some(k) = TT_TAGS.iter().position(|&t| t == tag) else { continue };
459 if f.tab[k].1 != 0 || off as u64 >= len {
460 continue;
461 }
462 let avail = len - off as u64;
463 let l = (tl as u64).min(avail) as u32;
464 if l == 0 {
465 continue;
466 }
467 f.tab[k] = (off, l);
468 }
469 if f.tab[TT_HEAD].1 < 54 {
471 return Err(ERR_HDR);
472 }
473 let h = f.tab[TT_HEAD].0 as usize;
474 let upem = be16(&data, h + 18);
475 if !(16..=16384).contains(&upem) {
476 return Err(ERR_HDR);
477 }
478 f.upem = upem;
479 if be16(&data, h + 50) as u16 != 0 {
480 f.flags |= TFF_LOCA_LONG;
481 }
482 if f.tab[TT_MAXP].1 < 6 {
484 return Err(ERR_HDR);
485 }
486 let ng = be16(&data, f.tab[TT_MAXP].0 as usize + 4);
487 if ng == 0 {
488 return Err(ERR_HDR);
489 }
490 f.nglyphs = ng;
491 let mut nhm = 0;
493 if f.tab[TT_HHEA].1 >= 36 {
494 nhm = be16(&data, f.tab[TT_HHEA].0 as usize + 34);
495 }
496 nhm = nhm.min(f.tab[TT_HMTX].1 >> 2).min(f.nglyphs);
497 f.nhm = nhm;
498 f.data = data;
499 if f.tab[TT_GLYF].1 != 0 && f.tab[TT_LOCA].1 != 0 {
501 f.kind = TFK_TTF;
502 } else if f.tab[TT_CFF2].1 != 0 || f.tab[TT_CFF].1 != 0 {
503 f.kind = TFK_CFF;
504 let mut r = Err(ERR_UNSUPPORTED);
505 if f.tab[TT_CFF2].1 != 0 {
506 r = Cff::open2(f.tb(TT_CFF2), f.upem);
507 }
508 if r.is_err() && f.tab[TT_CFF].1 != 0 {
509 r = Cff::open(f.tb(TT_CFF), f.upem);
510 }
511 f.cff = Some(Box::new(r?));
512 } else if f.tab[TT_CBDT].1 != 0 {
513 f.kind = TFK_TTF; } else {
515 return Err(ERR_UNSUPPORTED);
516 }
517 f.cmap_setup();
518 f.names_setup();
519 f.kern_setup();
520 f.gpos_setup();
521 colr::open(&mut f);
522 if f.tab[TT_FVAR].1 != 0 {
523 let v = Var::parse(f.tb(TT_FVAR), f.tb(TT_AVAR), f.tb(TT_GVAR), f.tb(TT_HVAR), f.tb(TT_MVAR), f.tb(TT_GDEF), f.tb(TT_NAME));
524 f.var = v.map(Box::new);
525 }
526 let (m, h) = f.metrics_calc(&[], None, ol);
527 f.fm = m;
528 f.hdr = h;
529 Ok(f)
530 }
531
532 fn cmap_score(pid: u32, eid: u32, fmt: u32) -> u32 {
536 match fmt {
537 12 => {
538 if pid == 3 {
539 match eid {
540 10 => 10,
541 1 => 8,
542 0 => 5,
543 _ => 0,
544 }
545 } else if pid == 0 {
546 9
547 } else {
548 0
549 }
550 }
551 4 => {
552 if pid == 3 {
553 match eid {
554 1 => 8,
555 0 => 5,
556 _ => 0,
557 }
558 } else if pid == 0 {
559 7
560 } else {
561 0
562 }
563 }
564 6 | 0 => {
565 let s = if fmt == 6 { 4 } else { 3 };
566 if pid == 0 || (pid == 3 && eid == 1) {
567 s
568 } else if pid == 1 && eid == 0 {
569 2
570 } else {
571 0
572 }
573 }
574 13 => {
575 if pid == 0 || (pid == 3 && eid == 10) {
576 1
577 } else {
578 0
579 }
580 }
581 _ => 0,
582 }
583 }
584
585 fn cmap_setup(&mut self) {
587 let tb = self.tb(TT_CMAP);
588 if tb.len() < 4 {
589 return;
590 }
591 let n = tb.u16(2);
592 if n < 0 {
593 return;
594 }
595 let (mut best, mut boff, mut bfmt, mut bpid, mut beid) = (0u32, 0u32, 0u32, 0u32, 0u32);
596 for i in 0..n as u32 {
597 let pid = tb.u16(i * 8 + 4);
598 if pid < 0 {
599 break;
600 }
601 let eid = tb.u16(i * 8 + 6) as u32;
602 let off = tb.u32(i * 8 + 8);
603 if off < 0 {
604 break;
605 }
606 let off = off as u32;
607 let fmt = tb.u16(off);
608 if fmt < 0 {
609 continue;
610 }
611 let s = Self::cmap_score(pid as u32, eid, fmt as u32);
612 if s > best {
613 best = s;
614 boff = off;
615 bfmt = fmt as u32;
616 bpid = pid as u32;
617 beid = eid;
618 }
619 }
620 if best == 0 {
621 return;
622 }
623 let l: i64 = if bfmt < 8 { tb.u16(boff.wrapping_add(2)) as i64 } else { tb.u32(boff.wrapping_add(4)) };
625 if l < 0 {
626 return;
627 }
628 let left = tb.len().wrapping_sub(boff); let mut l = (l as u64).min(left as u64) as u32;
630 if bfmt == 4 {
631 l = left; }
633 let start = self.tab[TT_CMAP].0.wrapping_add(boff);
634 self.cmap = start;
635 self.cmapend = l.wrapping_add(start);
636 self.cmapfmt = bfmt;
637 if bpid == 1 {
638 self.flags |= TFF_MACCMAP;
639 }
640 if bpid == 3 && beid == 0 {
641 self.flags |= TFF_SYMBOL;
642 }
643 }
644
645 fn cmap_raw(&self, cp: u32) -> u32 {
647 if self.cmap == 0 {
648 return 0;
649 }
650 let tb = Tb(&self.data[self.cmap as usize..self.cmapend as usize]);
651 let mut cp = cp;
652 if self.flags & TFF_MACCMAP != 0 && cp >= 0x80 {
654 match MAC_ROMAN.iter().position(|&u| u as u32 == cp) {
655 Some(i) => cp = i as u32 + 0x80,
656 None => return 0,
657 }
658 }
659 let g: u32 = match self.cmapfmt {
660 0 => {
661 if cp >= 256 || cp + 6 >= tb.len() {
662 return 0;
663 }
664 tb.0[(cp + 6) as usize] as u32
665 }
666 6 => {
667 let first = tb.u16(6);
668 if first < 0 || cp < first as u32 {
669 return 0;
670 }
671 let i = cp - first as u32;
672 if i >= tb.u16(8) as u32 {
673 return 0;
674 }
675 let g = tb.u16(i.wrapping_mul(2).wrapping_add(10));
676 if g < 0 {
677 return 0;
678 }
679 g as u32
680 }
681 4 => {
682 if cp > 0xFFFF {
683 return 0;
684 }
685 let sx2 = tb.u16(6);
686 if sx2 < 0 {
687 return 0;
688 }
689 let sx2 = sx2 as u32 & !1;
690 if sx2 == 0 {
691 return 0;
692 }
693 let (mut lo, mut hi) = (0u32, sx2 >> 1);
694 while lo < hi {
695 let mid = (lo + hi) >> 1;
696 let end = tb.u16(mid * 2 + 14);
697 if end < 0 {
698 return 0;
699 }
700 if end as u32 >= cp {
701 hi = mid;
702 } else {
703 lo = mid + 1;
704 }
705 }
706 if lo >= sx2 >> 1 {
707 return 0;
708 }
709 let start = tb.u16(sx2 + lo * 2 + 16);
710 if start < 0 || start as u32 > cp {
711 return 0;
712 }
713 let delta = tb.u16(sx2 * 2 + 16 + lo * 2);
714 if delta < 0 {
715 return 0;
716 }
717 let ro_pos = sx2 * 3 + 16 + lo * 2;
718 let ro = tb.u16(ro_pos);
719 if ro < 0 {
720 return 0;
721 }
722 if ro == 0 {
723 cp.wrapping_add(delta as u32) & 0xFFFF
724 } else {
725 let p = (ro as u32).wrapping_add(ro_pos).wrapping_add((cp - start as u32).wrapping_mul(2));
726 let g = tb.u16(p);
727 if g <= 0 {
728 return 0;
729 }
730 (g as u32).wrapping_add(delta as u32) & 0xFFFF
731 }
732 }
733 12 | 13 => {
734 let n = tb.u32(12);
735 if n < 0 || tb.len() < 16 {
736 return 0;
737 }
738 let n = (n as u32).min((tb.len() - 16) / 12);
739 let (mut lo, mut hi) = (0u32, n);
740 let mut found = None;
741 while lo < hi {
742 let mid = (lo + hi) >> 1;
743 let rec = mid * 12 + 16;
744 let start = tb.u32(rec) as u32;
745 if cp < start {
746 hi = mid;
747 continue;
748 }
749 let end = tb.u32(rec + 4) as u32;
750 if cp > end {
751 lo = mid + 1;
752 continue;
753 }
754 let mut g = tb.u32(rec + 8) as u32;
755 if self.cmapfmt != 13 {
756 g = g.wrapping_add(cp - start);
757 }
758 found = Some(g);
759 break;
760 }
761 match found {
762 Some(g) if g <= 0xFFFF => g,
763 _ => return 0,
764 }
765 }
766 _ => return 0,
767 };
768 if g < self.nglyphs { g } else { 0 }
769 }
770
771 pub fn glyph(&self, cp: u32) -> u32 {
774 let g = self.cmap_raw(cp);
775 if g != 0 || self.flags & TFF_SYMBOL == 0 {
776 return g;
777 }
778 let b = if cp <= 0xFF {
779 cp
780 } else {
781 match CP1252_HI.iter().position(|&u| u as u32 == cp) {
782 Some(i) => i as u32 + 0x80,
783 None => return 0,
784 }
785 };
786 self.cmap_raw(b + 0xF000)
787 }
788
789 pub fn has(&self, cp: u32) -> bool {
790 self.glyph(cp) != 0
791 }
792
793 pub fn adv(&self, g: u32) -> i32 {
795 if self.nhm == 0 {
796 return 0;
797 }
798 let i = g.min(self.nhm - 1);
799 be16(&self.data, (self.tab[TT_HMTX].0 + i * 4) as usize) as i32
800 }
801
802 fn kern_setup(&mut self) {
806 let tb = self.tb(TT_KERN);
807 if tb.len() < 4 {
808 return;
809 }
810 let kbase = self.tab[TT_KERN].0;
811 let mut subs = Vec::new();
812 let add = |subs: &mut Vec<(u32, u32)>, off: u32, np: u32| {
814 if subs.len() >= KERN_SUB_MAX || tb.len() <= off {
815 return;
816 }
817 let fit = (tb.len() - off) / 6;
818 let np = np.min(fit);
819 if np == 0 {
820 return;
821 }
822 subs.push((off.wrapping_add(kbase), np));
823 };
824 if tb.u32(0) == 0x0001_0000 {
825 let n = tb.u32(4);
827 if n < 0 {
828 self.kernsub = subs;
829 return;
830 }
831 let mut n = (n as u32).min(64);
832 let mut off = 8u32;
833 while n > 0 {
834 n -= 1;
835 let l = tb.u32(off);
836 if l < 0 {
837 break;
838 }
839 let cov = tb.u16(off.wrapping_add(4));
840 if cov < 0 {
841 break;
842 }
843 if cov & 0xE000 == 0 && cov & 0xFF == 0 {
844 let np = tb.u16(off.wrapping_add(8));
845 if np < 0 {
846 break;
847 }
848 add(&mut subs, off.wrapping_add(16), np as u32);
849 }
850 let l = l as u32;
851 if l < 8 {
852 break;
853 }
854 let (o2, carry) = off.overflowing_add(l);
855 if carry {
856 break;
857 }
858 off = o2;
859 }
860 } else if tb.u16(0) == 0 {
861 let mut n = tb.u16(2) as u32;
863 let mut off = 4u32;
864 while n > 0 {
865 n -= 1;
866 let l = tb.u16(off.wrapping_add(2));
867 if l < 0 {
868 break;
869 }
870 let cov = tb.u16(off.wrapping_add(4));
871 if cov < 0 {
872 break;
873 }
874 if cov >> 8 == 0 && cov & 7 == 1 {
875 let np = tb.u16(off.wrapping_add(6));
876 if np < 0 {
877 break;
878 }
879 add(&mut subs, off.wrapping_add(14), np as u32);
880 let np = tb.u16(off.wrapping_add(6)) as u32;
882 off = off.wrapping_add(np.wrapping_mul(6)).wrapping_add(14);
883 continue;
884 }
885 if (l as u32) < 6 {
886 break;
887 }
888 off = off.wrapping_add(l as u32);
889 }
890 }
891 self.kernsub = subs;
892 }
893
894 pub fn kern_table(&self, g1: u32, g2: u32) -> i32 {
896 let key = (g1 << 16) | g2;
897 let mut sum = 0i32;
898 let d = &self.data;
899 for &(off, np) in &self.kernsub {
900 let (mut lo, mut hi) = (0u32, np);
901 while lo < hi {
902 let mid = (lo + hi) >> 1;
903 let o = off as usize + mid as usize * 6;
904 let k = be32(d, o);
905 if key < k {
906 hi = mid;
907 } else if key > k {
908 lo = mid + 1;
909 } else {
910 sum = sum.wrapping_add(be16(d, o + 4) as u16 as i16 as i32);
911 break;
912 }
913 }
914 }
915 sum
916 }
917
918 pub fn kern(&self, g1: u32, g2: u32) -> i32 {
920 if self.gpossub.is_empty() { self.kern_table(g1, g2) } else { self.kern_gpos(g1, g2) }
921 }
922
923 fn gpos_setup(&mut self) {
927 let tb = self.tb(TT_GPOS);
928 if tb.len() < 10 || tb.u16(0) != 1 {
929 return;
930 }
931 let sl = tb.u16(4) as u32;
932 let fl = tb.u16(6) as u32;
933 let ll = tb.u16(8) as u32;
934 let mut lks: Vec<u16> = Vec::new();
935 let ns = tb.u16(sl);
937 if ns > 0 {
938 let mut found = false;
939 for i in 0..ns as u32 {
940 let rec = i.wrapping_mul(6).wrapping_add(sl).wrapping_add(2);
941 let tag = tb.u32(rec) as u32;
942 if tag == TAG_DFLT || tag == TAG_LATN {
943 let o = tb.u16(rec.wrapping_add(4));
944 if o < 0 {
945 continue;
946 }
947 gs_langsys(tb, (o as u32).wrapping_add(sl), fl, &mut lks);
948 found = true;
949 }
950 }
951 if !found {
952 let o = tb.u16(sl.wrapping_add(6));
954 if o >= 0 {
955 gs_langsys(tb, (o as u32).wrapping_add(sl), fl, &mut lks);
956 }
957 }
958 }
959 lks.sort_unstable();
960 let lcount = tb.u16(ll);
962 if lcount <= 0 {
963 return;
964 }
965 let mut subs = Vec::new();
966 'lk: for (ord, &li) in lks.iter().enumerate() {
967 if li as i32 >= lcount {
968 continue;
969 }
970 let lo = tb.u16(ll.wrapping_add(li as u32 * 2).wrapping_add(2));
971 if lo < 0 {
972 continue;
973 }
974 let lt = (lo as u32).wrapping_add(ll);
975 let ty = tb.u16(lt);
976 if ty != 2 && ty != 9 {
977 continue;
978 }
979 let nsub = tb.u16(lt.wrapping_add(4));
980 if nsub <= 0 {
981 continue;
982 }
983 for s in 0..nsub as u32 {
984 let so = tb.u16(lt.wrapping_add(s * 2).wrapping_add(6));
985 if so < 0 {
986 continue 'lk;
987 }
988 let mut sub = (so as u32).wrapping_add(lt);
989 if ty == 9 {
990 if tb.u16(sub) != 1 || tb.u16(sub.wrapping_add(2)) != 2 {
992 continue;
993 }
994 let off = tb.u32(sub.wrapping_add(4));
995 if off < 0 {
996 continue;
997 }
998 let s64 = sub as u64 + off as u64;
999 if s64 >= tb.len() as u64 {
1000 continue;
1001 }
1002 sub = s64 as u32;
1003 }
1004 if subs.len() >= GPOS_SUB_MAX {
1005 break 'lk;
1006 }
1007 subs.push((sub, ord as u32));
1008 }
1009 }
1010 self.gpossub = subs;
1011 }
1012
1013 fn kern_gpos(&self, g1: u32, g2: u32) -> i32 {
1015 let tb = self.tb(TT_GPOS);
1016 let mut sum = 0i32;
1017 let mut done = u32::MAX;
1018 for &(sub, ord) in &self.gpossub {
1019 if ord == done {
1020 continue; }
1022 if let Some(v) = gp_pair(tb, sub, g1, g2) {
1023 sum = sum.wrapping_add(v);
1024 done = ord;
1025 }
1026 }
1027 sum
1028 }
1029
1030 fn names_setup(&mut self) {
1034 let tb = self.tb(TT_NAME);
1035 let mut names: [Vec<u8>; 5] = Default::default();
1036 for (i, &id) in NAME_IDS.iter().enumerate() {
1037 names[i] = sfnt_name(tb, id, NAME_CAP);
1038 }
1039 if names[3].is_empty() {
1041 names[3] = names[0].clone();
1042 }
1043 if names[4].is_empty() {
1044 names[4] = names[1].clone();
1045 }
1046 self.names = names;
1047 }
1048
1049 pub fn name(&self, which: u32) -> &[u8] {
1051 match which {
1052 FN_FAMILY => &self.names[0],
1053 FN_STYLE => &self.names[1],
1054 FN_FULL => &self.names[2],
1055 FN_TYPO_FAMILY => &self.names[3],
1056 FN_TYPO_STYLE => &self.names[4],
1057 _ => b"",
1058 }
1059 }
1060
1061 fn metrics_calc(&self, coords: &[i16], wght: Option<f32>, ol: &mut Outline) -> (Metrics, Hdr) {
1067 let mac_style = self.tb(TT_HEAD).u16(44) as u32;
1068 let mv = |tag: u32| -> i32 {
1070 match (&self.var, coords.is_empty()) {
1071 (Some(v), false) => floor_i(v.mvar_delta(self.tb(TT_MVAR), tag, coords) + 0.5),
1072 _ => 0,
1073 }
1074 };
1075 let mut m = Metrics { upem: self.upem as i32, nglyphs: self.nglyphs as i32, ..Default::default() };
1076 m.asc = (self.upem * 4 / 5) as i32;
1078 m.desc = m.asc - self.upem as i32;
1079 let t = self.tb(TT_HHEA);
1080 if t.len() >= 36 {
1081 m.asc = (t.u16(4) as i16 as i32).wrapping_add(mv(MV_HASC));
1082 m.desc = (t.u16(6) as i16 as i32).wrapping_add(mv(MV_HDSC));
1083 m.gap = (t.u16(8) as i16 as i32).wrapping_add(mv(MV_HLGP));
1084 m.advmax = t.u16(10);
1085 }
1086 m.typo_asc = m.asc;
1088 m.win_asc = m.asc;
1089 m.typo_desc = m.desc;
1090 m.win_desc = m.desc.wrapping_neg();
1091 m.typo_gap = m.gap;
1092 m.weight = 400;
1093 m.width = 5;
1094 let mut fl = 0i32;
1095 if mac_style & 1 != 0 {
1096 fl |= FMF_BOLD;
1097 m.weight = 700;
1098 }
1099 if mac_style & 2 != 0 {
1100 fl |= FMF_ITALIC;
1101 }
1102 let t = self.tb(TT_OS2);
1103 if t.len() >= 68 {
1104 fl = 0; let mut w = t.u16(4) as u32;
1106 if w < 10 {
1107 w *= 100; }
1109 if w > 1000 {
1110 w = 1000;
1111 }
1112 if w == 0 {
1113 w = 400;
1114 }
1115 m.weight = w as i32;
1116 m.width = t.u16(6);
1117 m.st_thick = (t.u16(26) as i16 as i32).wrapping_add(mv(MV_STRS));
1118 m.st_pos = (t.u16(28) as i16 as i32).wrapping_add(mv(MV_STRO));
1119 let s = t.u16(62);
1120 if s & 1 != 0 {
1121 fl |= FMF_ITALIC;
1122 }
1123 if s & 0x20 != 0 {
1124 fl |= FMF_BOLD;
1125 }
1126 if s & 0x200 != 0 {
1127 fl |= FMF_OBLIQUE;
1128 }
1129 if s & 0x80 != 0 {
1130 fl |= FMF_TYPO;
1131 }
1132 if t.len() >= 78 {
1133 m.typo_asc = (t.u16(68) as i16 as i32).wrapping_add(mv(MV_HASC));
1134 m.typo_desc = (t.u16(70) as i16 as i32).wrapping_add(mv(MV_HDSC));
1135 m.typo_gap = (t.u16(72) as i16 as i32).wrapping_add(mv(MV_HLGP));
1136 m.win_asc = t.u16(74).wrapping_add(mv(MV_HCLA));
1137 m.win_desc = t.u16(76).wrapping_add(mv(MV_HCLD));
1138 }
1139 if t.len() >= 90 && t.u16(0) >= 2 {
1140 m.xh = (t.u16(86) as i16 as i32).wrapping_add(mv(MV_XHGT));
1141 m.caph = (t.u16(88) as i16 as i32).wrapping_add(mv(MV_CPHT));
1142 }
1143 }
1144 if let Some(w) = wght {
1146 m.weight = floor_i(w + 0.5).clamp(1, 1000);
1147 }
1148 let t = self.tb(TT_POST);
1149 if t.len() >= 16 {
1150 m.ul_pos = (t.u16(8) as i16 as i32).wrapping_add(mv(MV_UNDO));
1151 m.ul_thick = (t.u16(10) as i16 as i32).wrapping_add(mv(MV_UNDS));
1152 if t.u32(12) as u32 != 0 {
1153 fl |= FMF_MONO;
1154 }
1155 }
1156 if self.kind == TFK_CFF {
1157 fl |= FMF_CFF;
1158 }
1159 if self.tab[TT_FVAR].1 != 0 {
1160 fl |= FMF_VAR;
1161 }
1162 if self.flags & TFF_SYMBOL != 0 {
1163 fl |= FMF_SYMBOL;
1164 }
1165 if self.flags & TFF_COLR != 0 {
1166 fl |= FMF_COLOR;
1167 }
1168 if self.flags & TFF_CBDT != 0 {
1169 fl |= FMF_COLOR | FMF_BITMAP;
1170 }
1171 if !self.kernsub.is_empty() || !self.gpossub.is_empty() {
1172 fl |= FMF_KERN;
1173 }
1174 m.flags = fl;
1175 if fl & FMF_SYMBOL == 0 {
1177 if m.xh <= 0 {
1178 m.xh = self.glyph_ymax('x' as u32, coords, ol);
1179 }
1180 if m.caph <= 0 {
1181 m.caph = self.glyph_ymax('H' as u32, coords, ol);
1182 }
1183 }
1184 let mut d = (self.upem / 14) as i32;
1186 if d == 0 {
1187 d = 1;
1188 }
1189 if m.ul_thick <= 0 {
1190 m.ul_thick = d;
1191 }
1192 if m.ul_pos >= 0 {
1193 m.ul_pos = (m.ul_thick + m.ul_thick).wrapping_neg();
1194 }
1195 if m.st_thick <= 0 {
1196 m.st_thick = m.ul_thick;
1197 }
1198 if m.st_pos <= 0 {
1199 let mut c = m.xh;
1200 if c <= 0 {
1201 c = (self.upem >> 1) as i32;
1202 }
1203 m.st_pos = c.wrapping_add(m.st_thick) >> 1;
1204 }
1205 let mut flags = SGH_RUNTIME;
1207 if self.flags & TFF_COLR != 0 {
1208 flags |= SGH_COLR;
1209 }
1210 if self.flags & TFF_CBDT != 0 {
1211 flags |= SGH_CBDT;
1212 }
1213 let c16 = |v: i32| v.clamp(-32768, 32767);
1214 let hdr = Hdr {
1215 flags,
1216 upem: self.upem as i32,
1217 asc: c16(m.asc),
1218 desc: c16(m.desc),
1219 gap: c16(m.gap),
1220 caph: c16(m.caph),
1221 xh: if fl & FMF_SYMBOL != 0 { 0 } else { c16(m.xh) }, ulpos: c16(m.ul_pos),
1223 ulthick: c16(m.ul_thick),
1224 nglyphs: self.nglyphs & 0xFFFF,
1225 baseid: 0,
1226 };
1227 (m, hdr)
1228 }
1229
1230 pub(crate) fn metrics_var(&self, coords: &[i16], wght: Option<f32>, ol: &mut Outline) -> (Metrics, Hdr) {
1233 self.metrics_calc(coords, wght, ol)
1234 }
1235
1236 fn glyph_ymax(&self, cp: u32, coords: &[i16], ol: &mut Outline) -> i32 {
1238 let g = self.glyph(cp);
1239 if g == 0 {
1240 return 0;
1241 }
1242 let ok = if coords.is_empty() { self.prep(g, ol) } else { self.prep_var(g, coords, 0, ol) };
1244 if ok { ol.bbox().map_or(0, |b| b[3]) } else { 0 }
1245 }
1246
1247 pub fn prep(&self, glyph: u32, ol: &mut Outline) -> bool {
1252 self.prep_at(glyph, &[], self.serial, ol)
1253 }
1254
1255 pub(crate) fn prep_var(&self, glyph: u32, coords: &[i16], serial: u64, ol: &mut Outline) -> bool {
1258 let varies = self.var.as_ref().is_some_and(|v| v.has_gvar()) || self.cff.as_ref().is_some_and(|c| c.varies());
1259 let coords = if varies { coords } else { &[] };
1260 self.prep_at(glyph, coords, serial, ol)
1261 }
1262
1263 fn prep_at(&self, glyph: u32, coords: &[i16], serial: u64, ol: &mut Outline) -> bool {
1264 ol.reset();
1265 let ok = if self.kind == TFK_CFF {
1266 match &self.cff {
1267 Some(c) => c.outline_var(self.tb(if c.is_v2() { TT_CFF2 } else { TT_CFF }), glyph, coords, ol),
1268 None => false,
1269 }
1270 } else {
1271 let mut st = GlyfSt::new(coords);
1272 let ok = self.glyf_decode(glyph, 0, ol, &mut st);
1273 if ok && st.hasx {
1274 if let Some(lsb) = self.lsb(st.rg) {
1277 let d = lsb.wrapping_sub(st.xmin);
1278 if coords.is_empty() {
1279 if d != 0 {
1280 ol.translate(0, d as f32, 0.0);
1281 }
1282 } else {
1283 let df = d as f32 - st.pp.0;
1284 if df != 0.0 {
1285 ol.translate(0, df, 0.0);
1286 }
1287 }
1288 }
1289 }
1290 ok
1291 };
1292 if !ok || ol.err {
1293 ol.reset();
1294 ol.owner_set(serial, glyph);
1295 return false;
1296 }
1297 ol.owner_set(serial, glyph);
1298 ol.npts() != 0
1299 }
1300
1301 pub(crate) fn adv_var(&self, g: u32, coords: &[i16]) -> i32 {
1304 let a = self.adv(g);
1305 match &self.var {
1306 Some(v) if !coords.is_empty() => match v.hvar_delta(self.tb(TT_HVAR), g, coords) {
1307 Some(d) => a.wrapping_add(floor_i(d + 0.5)).max(0),
1308 None => a,
1309 },
1310 _ => a,
1311 }
1312 }
1313
1314 pub(crate) fn adv_table(&self, coords: &[i16], ol: &mut Outline) -> Vec<i32> {
1318 let Some(v) = &self.var else { return Vec::new() };
1319 if v.has_hvar() || !v.has_gvar() || self.kind != TFK_TTF || coords.iter().all(|&c| c == 0) {
1320 return Vec::new();
1321 }
1322 let mut out = Vec::with_capacity(self.nglyphs as usize);
1323 for g in 0..self.nglyphs {
1324 ol.reset();
1325 let mut st = GlyfSt::new(coords);
1326 let a = if self.glyf_decode(g, 0, ol, &mut st) {
1327 self.adv(st.rg).wrapping_add(floor_i(st.pp.1 - st.pp.0 + 0.5)).max(0)
1328 } else {
1329 self.adv(g)
1330 };
1331 out.push(a);
1332 }
1333 ol.reset();
1334 out
1335 }
1336
1337 pub(crate) fn kern_var(&self, g1: u32, g2: u32, coords: &[i16]) -> i32 {
1340 let Some(v) = &self.var else { return self.kern(g1, g2) };
1341 if self.gpossub.is_empty() || coords.is_empty() {
1342 return self.kern(g1, g2);
1343 }
1344 let tb = self.tb(TT_GPOS);
1345 let gdef = self.tb(TT_GDEF);
1346 let mut sum = 0i32;
1347 let mut done = u32::MAX;
1348 for &(sub, ord) in &self.gpossub {
1349 if ord == done {
1350 continue;
1351 }
1352 if let Some((rec, vf1, base)) = gp_value(tb, sub, g1, g2) {
1353 let mut val = 0i32;
1354 if vf1 & 4 != 0 {
1355 let x = tb.u16(rec.wrapping_add(popcnt8(vf1 & 3) * 2));
1356 if x >= 0 {
1357 val = x as u16 as i16 as i32;
1358 }
1359 }
1360 if vf1 & 0x40 != 0 {
1362 let dev = tb.u16(rec.wrapping_add(popcnt8(vf1 & 0x3F) * 2));
1363 if dev > 0 {
1364 let d = base.wrapping_add(dev as u32);
1365 if tb.u16(d.wrapping_add(4)) == 0x8000 {
1366 let (o, i) = (tb.u16(d), tb.u16(d.wrapping_add(2)));
1367 if o >= 0 && i >= 0 {
1368 val = val.wrapping_add(floor_i(v.gdef_delta(gdef, o as u32, i as u32, coords) + 0.5));
1369 }
1370 }
1371 }
1372 }
1373 sum = sum.wrapping_add(val);
1374 done = ord;
1375 }
1376 }
1377 sum
1378 }
1379
1380 fn lsb(&self, g: u32) -> Option<i32> {
1382 let nhm = self.nhm;
1383 let off = if g < nhm { g * 4 + 2 } else { (nhm * 4).wrapping_add((g - nhm).wrapping_mul(2)) };
1384 if off.wrapping_add(2) > self.tab[TT_HMTX].1 {
1385 return None;
1386 }
1387 Some(be16(&self.data, (self.tab[TT_HMTX].0 + off) as usize) as u16 as i16 as i32)
1388 }
1389
1390 pub fn bbox(&self, g: u32, ol: &mut Outline) -> Option<[i32; 4]> {
1392 if self.prep(g, ol) { ol.bbox() } else { None }
1393 }
1394
1395 pub fn path(&self, g: u32, ol: &mut Outline, path: &mut Path, gp: &Gp) {
1397 if !ol.owner_is(self.serial, g) {
1398 self.prep(g, ol);
1399 }
1400 if ol.npts() != 0 {
1401 ol.emit(path, gp, None);
1402 }
1403 }
1404
1405 fn gvar_pts(&self, glyph: u32, st: &mut GlyfSt, orig: &[(f32, f32)], ends: &[usize], out: &mut [(f32, f32)]) -> bool {
1408 match &self.var {
1409 Some(v) => v.gvar_deltas(self.tb(TT_GVAR), glyph, st.coords, orig, ends, out, &mut st.vbudget),
1410 None => true,
1411 }
1412 }
1413
1414 fn gvar_phantom(&self, glyph: u32, st: &mut GlyfSt) -> Option<(f32, f32)> {
1416 let mut out = [(0.0f32, 0.0f32); 4];
1417 if !self.gvar_pts(glyph, st, &[], &[], &mut out) {
1418 return None;
1419 }
1420 Some((out[0].0, out[1].0))
1421 }
1422
1423 fn glyf_decode(&self, glyph: u32, depth: u32, ol: &mut Outline, st: &mut GlyfSt) -> bool {
1427 let mut my_rg = glyph; let mut my_xmin = 0i32;
1429 let mut my_pp = (0.0f32, 0.0f32);
1430 if depth > GLYF_DEPTH {
1431 return false;
1432 }
1433 st.budget -= 1;
1434 if st.budget < 0 {
1435 return false;
1436 }
1437 let ok = |st: &mut GlyfSt, xmin: i32, rg: u32, pp: (f32, f32)| {
1438 st.xmin = xmin;
1439 st.rg = rg;
1440 st.pp = pp;
1441 st.hasx = true;
1442 true
1443 };
1444 let var = !st.coords.is_empty();
1445 if glyph >= self.nglyphs {
1446 return ok(st, my_xmin, my_rg, my_pp);
1447 }
1448 let d = &self.data;
1449 let (loca, lcl) = self.tab[TT_LOCA];
1451 let (start, end);
1452 if self.flags & TFF_LOCA_LONG != 0 {
1453 if glyph as u64 * 4 + 8 > lcl as u64 {
1454 return ok(st, my_xmin, my_rg, my_pp); }
1456 let p = loca as usize + glyph as usize * 4;
1457 start = be32(d, p);
1458 end = be32(d, p + 4);
1459 } else {
1460 if glyph as u64 * 2 + 4 > lcl as u64 {
1461 return ok(st, my_xmin, my_rg, my_pp);
1462 }
1463 let p = loca as usize + glyph as usize * 2;
1464 start = be16(d, p) * 2;
1465 end = be16(d, p + 2) * 2;
1466 }
1467 if end <= start || (end <= self.tab[TT_GLYF].1 && end - start < 10) {
1468 if var {
1470 match self.gvar_phantom(glyph, st) {
1471 Some(pp) => my_pp = pp,
1472 None => return false,
1473 }
1474 }
1475 return ok(st, my_xmin, my_rg, my_pp);
1476 }
1477 if end > self.tab[TT_GLYF].1 {
1478 return false;
1479 }
1480 let gl = self.tab[TT_GLYF].0 as usize;
1481 let p = gl + start as usize;
1482 let pend = gl + end as usize;
1483 my_xmin = be16(d, p + 2) as u16 as i16 as i32; let nc = be16(d, p) as u16 as i16 as i32;
1485 if nc == 0 {
1486 if var {
1487 match self.gvar_phantom(glyph, st) {
1488 Some(pp) => my_pp = pp,
1489 None => return false,
1490 }
1491 }
1492 return ok(st, my_xmin, my_rg, my_pp);
1493 }
1494 if nc > 0 {
1495 let nc = nc as usize;
1497 if p + nc * 2 + 12 > pend {
1498 return false;
1499 }
1500 let npts = be16(d, p + nc * 2 + 8) as usize + 1;
1501 let ins = be16(d, p + nc * 2 + 10) as usize;
1502 let mut q = p + nc * 2 + 12 + ins;
1503 if q > pend {
1504 return false;
1505 }
1506 let Some(base) = ol.reserve(npts) else { return false };
1507 let mut i = 0;
1508 while i < npts {
1509 if q >= pend {
1510 return false;
1511 }
1512 let f = d[q];
1513 q += 1;
1514 ol.tags[base + i] = f;
1515 i += 1;
1516 if f & 8 == 0 {
1517 continue;
1518 }
1519 if q >= pend {
1520 return false;
1521 }
1522 let mut r = d[q];
1523 q += 1;
1524 while r != 0 && i < npts {
1525 ol.tags[base + i] = f;
1526 i += 1;
1527 r -= 1;
1528 }
1529 }
1530 let mut x = 0i32;
1531 for i in 0..npts {
1532 let f = ol.tags[base + i];
1533 if f & 2 != 0 {
1534 if q >= pend {
1535 return false;
1536 }
1537 let mut v = d[q] as i32;
1538 q += 1;
1539 if f & 16 == 0 {
1540 v = -v;
1541 }
1542 x = x.wrapping_add(v);
1543 } else if f & 16 == 0 {
1544 if q + 2 > pend {
1545 return false;
1546 }
1547 x = x.wrapping_add(be16(d, q) as u16 as i16 as i32);
1548 q += 2;
1549 }
1550 ol.pts[base + i].0 = x as f32;
1551 }
1552 let mut y = 0i32;
1553 for i in 0..npts {
1554 let f = ol.tags[base + i];
1555 if f & 4 != 0 {
1556 if q >= pend {
1557 return false;
1558 }
1559 let mut v = d[q] as i32;
1560 q += 1;
1561 if f & 32 == 0 {
1562 v = -v;
1563 }
1564 y = y.wrapping_add(v);
1565 } else if f & 32 == 0 {
1566 if q + 2 > pend {
1567 return false;
1568 }
1569 y = y.wrapping_add(be16(d, q) as u16 as i16 as i32);
1570 q += 2;
1571 }
1572 ol.pts[base + i].1 = y as f32;
1573 }
1574 for i in 0..npts {
1575 ol.tags[base + i] &= OLT_ON;
1576 }
1577 let mut prev = -1i32;
1578 let mut ends: Vec<usize> = Vec::new();
1579 for c in 0..nc {
1580 let e = be16(d, p + 10 + c * 2) as i32;
1581 if e as usize >= npts || e < prev {
1582 return false;
1583 }
1584 if e == prev {
1585 continue;
1586 }
1587 prev = e;
1588 if !ol.contour(base as u32 + e as u32) {
1589 return false;
1590 }
1591 if var {
1592 ends.push(e as usize);
1593 }
1594 }
1595 if var {
1596 let orig: Vec<(f32, f32)> = ol.pts[base..base + npts].to_vec();
1598 let mut dl = alloc::vec![(0.0f32, 0.0f32); npts + 4];
1599 if !self.gvar_pts(glyph, st, &orig, &ends, &mut dl) {
1600 return false;
1601 }
1602 for (pt, dv) in ol.pts[base..base + npts].iter_mut().zip(&dl) {
1603 pt.0 += dv.0;
1604 pt.1 += dv.1;
1605 }
1606 my_pp = (dl[npts].0, dl[npts + 1].0);
1607 }
1608 return ok(st, my_xmin, my_rg, my_pp);
1609 }
1610 let mut q = p + 10;
1612 let cbase = ol.npts() as u32; let mut cd: Vec<(f32, f32)> = Vec::new();
1615 if var {
1616 let mut r = q;
1617 let mut n = 0usize;
1618 loop {
1619 if r + 4 > pend {
1620 return false;
1621 }
1622 let fl = be16(d, r);
1623 r += 4 + if fl & 1 != 0 { 4 } else { 2 };
1624 r += if fl & 8 != 0 {
1625 2
1626 } else if fl & 0x40 != 0 {
1627 4
1628 } else if fl & 0x80 != 0 {
1629 8
1630 } else {
1631 0
1632 };
1633 n += 1;
1634 if fl & 0x20 == 0 {
1635 break;
1636 }
1637 }
1638 cd = alloc::vec![(0.0f32, 0.0f32); n + 4];
1639 if !self.gvar_pts(glyph, st, &[], &[], &mut cd) {
1640 return false;
1641 }
1642 my_pp = (cd[n].0, cd[n + 1].0);
1643 }
1644 let mut k = 0usize;
1645 loop {
1646 if q + 4 > pend {
1647 return false;
1648 }
1649 let flags = be16(d, q);
1650 let comp = be16(d, q + 2);
1651 q += 4;
1652 let (a1, a2): (i32, i32);
1653 if flags & 1 != 0 {
1654 if q + 4 > pend {
1655 return false;
1656 }
1657 let (u, v) = (be16(d, q), be16(d, q + 2));
1658 if flags & 2 != 0 {
1659 a1 = u as u16 as i16 as i32;
1660 a2 = v as u16 as i16 as i32;
1661 } else {
1662 a1 = u as i32;
1663 a2 = v as i32;
1664 }
1665 q += 4;
1666 } else {
1667 if q + 2 > pend {
1668 return false;
1669 }
1670 if flags & 2 != 0 {
1671 a1 = d[q] as i8 as i32;
1672 a2 = d[q + 1] as i8 as i32;
1673 } else {
1674 a1 = d[q] as i32;
1675 a2 = d[q + 1] as i32;
1676 }
1677 q += 2;
1678 }
1679 let f2 = |o: usize| (be16(d, o) as u16 as i16 as i32) as f32 * F_INV16384;
1681 let (mut ma, mut mb, mut mc, mut md) = (0.0f32, 0.0f32, 0.0f32, 0.0f32);
1682 let mut hasmat = true;
1683 if flags & 0x08 != 0 {
1684 if q + 2 > pend {
1685 return false;
1686 }
1687 ma = f2(q);
1688 md = ma;
1689 q += 2;
1690 } else if flags & 0x40 != 0 {
1691 if q + 4 > pend {
1692 return false;
1693 }
1694 ma = f2(q);
1695 md = f2(q + 2);
1696 q += 4;
1697 } else if flags & 0x80 != 0 {
1698 if q + 8 > pend {
1699 return false;
1700 }
1701 ma = f2(q);
1702 mb = f2(q + 2);
1703 mc = f2(q + 4);
1704 md = f2(q + 6);
1705 q += 8;
1706 } else {
1707 hasmat = false;
1708 }
1709 let from = ol.npts();
1710 if !self.glyf_decode(comp, depth + 1, ol, st) {
1711 return false;
1712 }
1713 if flags & 0x200 != 0 {
1714 my_xmin = st.xmin;
1716 my_rg = st.rg;
1717 my_pp = st.pp;
1718 }
1719 if hasmat {
1720 ol.transform(from, ma, mb, mc, md);
1721 }
1722 if flags & 2 != 0 {
1723 let mut dx = a1 as f32;
1724 let mut dy = a2 as f32;
1725 if let Some(v) = cd.get(k) {
1726 dx += v.0;
1728 dy += v.1;
1729 }
1730 if hasmat && flags & 0x800 != 0 && flags & 0x1000 == 0 {
1731 dx = dx * sqrt(ma * ma + mb * mb);
1733 dy = dy * sqrt(mc * mc + md * md);
1734 }
1735 ol.translate(from, dx, dy);
1736 } else {
1737 let pa = (a1 as u32).wrapping_add(cbase);
1740 let pb = (a2 as u32).wrapping_add(from as u32);
1741 if (pa as usize) < from && (pb as usize) < ol.npts() {
1742 let (xa, ya) = ol.pts[pa as usize];
1743 let (xb, yb) = ol.pts[pb as usize];
1744 ol.translate(from, xa - xb, ya - yb);
1745 }
1746 }
1747 k += 1;
1748 if flags & 0x20 == 0 {
1749 break;
1750 }
1751 }
1752 ok(st, my_xmin, my_rg, my_pp)
1753 }
1754}
1755
1756fn gs_langsys(tb: Tb, script: u32, fl: u32, lks: &mut Vec<u16>) {
1760 let o = tb.u16(script);
1761 if o <= 0 {
1762 return;
1763 }
1764 let ls = script.wrapping_add(o as u32);
1765 let req = tb.u16(ls.wrapping_add(2));
1766 if req != 0xFFFF {
1767 if req < 0 {
1768 return;
1769 }
1770 gs_feature(tb, req as u32, fl, lks);
1771 }
1772 let n = tb.u16(ls.wrapping_add(4));
1773 if n <= 0 {
1774 return;
1775 }
1776 for i in 0..n as u32 {
1777 let fi = tb.u16(ls.wrapping_add(i * 2).wrapping_add(6));
1778 if fi < 0 {
1779 return;
1780 }
1781 gs_feature(tb, fi as u32, fl, lks);
1782 }
1783}
1784
1785fn gs_feature(tb: Tb, index: u32, fl: u32, lks: &mut Vec<u16>) {
1787 if index >= tb.u16(fl) as u32 {
1788 return;
1789 }
1790 let rec = index.wrapping_mul(6).wrapping_add(fl).wrapping_add(2);
1791 if tb.u32(rec) as u32 != TAG_KERNF {
1792 return;
1793 }
1794 let o = tb.u16(rec.wrapping_add(4));
1795 if o < 0 {
1796 return;
1797 }
1798 let ft = (o as u32).wrapping_add(fl);
1799 let n = tb.u16(ft.wrapping_add(2));
1800 if n <= 0 {
1801 return;
1802 }
1803 for i in 0..n as u32 {
1804 let li = tb.u16(ft.wrapping_add(i * 2).wrapping_add(4));
1805 if li < 0 {
1806 return;
1807 }
1808 let li = li as u16;
1809 if lks.contains(&li) {
1810 continue;
1811 }
1812 if lks.len() >= GPOS_LK_MAX {
1813 return;
1814 }
1815 lks.push(li);
1816 }
1817}
1818
1819fn gp_coverage(tb: Tb, off: u32, g: u32) -> i32 {
1821 match tb.u16(off) {
1822 1 => {
1823 let n = tb.u16(off.wrapping_add(2));
1824 if n <= 0 {
1825 return -1;
1826 }
1827 let (mut lo, mut hi) = (0u32, n as u32);
1828 while lo < hi {
1829 let mid = (lo + hi) >> 1;
1830 let v = tb.u16(off.wrapping_add(mid * 2).wrapping_add(4));
1831 if v < 0 {
1832 return -1;
1833 }
1834 let v = v as u32;
1835 if g < v {
1836 hi = mid;
1837 } else if g > v {
1838 lo = mid + 1;
1839 } else {
1840 return mid as i32;
1841 }
1842 }
1843 -1
1844 }
1845 2 => {
1846 let n = tb.u16(off.wrapping_add(2));
1847 if n <= 0 {
1848 return -1;
1849 }
1850 let (mut lo, mut hi) = (0u32, n as u32);
1851 while lo < hi {
1852 let mid = (lo + hi) >> 1;
1853 let r = mid.wrapping_mul(6).wrapping_add(off).wrapping_add(4);
1854 let s = tb.u16(r);
1855 if s < 0 {
1856 return -1;
1857 }
1858 if g < s as u32 {
1859 hi = mid;
1860 continue;
1861 }
1862 let e = tb.u16(r.wrapping_add(2));
1863 if e < 0 {
1864 return -1;
1865 }
1866 if g > e as u32 {
1867 lo = mid + 1;
1868 continue;
1869 }
1870 let si = tb.u16(r.wrapping_add(4));
1871 if si < 0 {
1872 return -1;
1873 }
1874 return (si as u32).wrapping_add(g).wrapping_sub(s as u32) as i32;
1875 }
1876 -1
1877 }
1878 _ => -1,
1879 }
1880}
1881
1882fn gp_class(tb: Tb, off: u32, g: u32) -> u32 {
1884 match tb.u16(off) {
1885 1 => {
1886 let s = tb.u16(off.wrapping_add(2));
1887 if s < 0 || g < s as u32 {
1888 return 0;
1889 }
1890 let i = g - s as u32;
1891 if i >= tb.u16(off.wrapping_add(4)) as u32 {
1892 return 0;
1893 }
1894 let c = tb.u16(off.wrapping_add(i.wrapping_mul(2)).wrapping_add(6));
1895 if c < 0 { 0 } else { c as u32 }
1896 }
1897 2 => {
1898 let n = tb.u16(off.wrapping_add(2));
1899 if n <= 0 {
1900 return 0;
1901 }
1902 let (mut lo, mut hi) = (0u32, n as u32);
1903 while lo < hi {
1904 let mid = (lo + hi) >> 1;
1905 let r = mid.wrapping_mul(6).wrapping_add(off).wrapping_add(4);
1906 let s = tb.u16(r);
1907 if s < 0 {
1908 return 0;
1909 }
1910 if g < s as u32 {
1911 hi = mid;
1912 continue;
1913 }
1914 let e = tb.u16(r.wrapping_add(2));
1915 if e < 0 {
1916 return 0;
1917 }
1918 if g > e as u32 {
1919 lo = mid + 1;
1920 continue;
1921 }
1922 let c = tb.u16(r.wrapping_add(4));
1923 return if c < 0 { 0 } else { c as u32 };
1924 }
1925 0
1926 }
1927 _ => 0,
1928 }
1929}
1930
1931fn gp_pair(tb: Tb, sub: u32, g1: u32, g2: u32) -> Option<i32> {
1933 let (value, vf1, _) = gp_value(tb, sub, g1, g2)?;
1934 if vf1 & 4 == 0 {
1935 return Some(0);
1936 }
1937 let v = tb.u16((popcnt8(vf1 & 3) * 2).wrapping_add(value));
1938 if v < 0 { Some(0) } else { Some(v as u16 as i16 as i32) }
1939}
1940
1941fn gp_value(tb: Tb, sub: u32, g1: u32, g2: u32) -> Option<(u32, u32, u32)> {
1945 let vf1 = tb.u16(sub.wrapping_add(4));
1946 if vf1 < 0 {
1947 return None;
1948 }
1949 let vf1 = vf1 as u32;
1950 let vf1_size = popcnt8(vf1) * 2;
1951 let vf2 = tb.u16(sub.wrapping_add(6));
1952 if vf2 < 0 {
1953 return None;
1954 }
1955 let rec = popcnt8(vf2 as u32) * 2 + vf1_size; let co = tb.u16(sub.wrapping_add(2));
1957 if co < 0 {
1958 return None;
1959 }
1960 let cov = gp_coverage(tb, sub.wrapping_add(co as u32), g1);
1961 if cov < 0 {
1962 return None;
1963 }
1964 let mut base = sub;
1965 let value = match tb.u16(sub) {
1966 2 => {
1967 let c1o = tb.u16(sub.wrapping_add(8));
1969 if c1o < 0 {
1970 return None;
1971 }
1972 let c1 = gp_class(tb, sub.wrapping_add(c1o as u32), g1);
1973 let c2o = tb.u16(sub.wrapping_add(10));
1974 if c2o < 0 {
1975 return None;
1976 }
1977 let c2 = gp_class(tb, sub.wrapping_add(c2o as u32), g2);
1978 if c1 >= tb.u16(sub.wrapping_add(12)) as u32 {
1979 return None;
1980 }
1981 let n2 = tb.u16(sub.wrapping_add(14));
1982 if n2 <= 0 || c2 >= n2 as u32 {
1983 return None;
1984 }
1985 (n2 as u32).wrapping_mul(c1).wrapping_add(c2).wrapping_mul(rec).wrapping_add(16).wrapping_add(sub)
1986 }
1987 1 => {
1988 let cov = cov as u32;
1990 if cov >= tb.u16(sub.wrapping_add(8)) as u32 {
1991 return None;
1992 }
1993 let pso = tb.u16(sub.wrapping_add(cov.wrapping_mul(2)).wrapping_add(10));
1994 if pso < 0 {
1995 return None;
1996 }
1997 let ps = (pso as u32).wrapping_add(sub);
1998 base = ps;
1999 let n = tb.u16(ps);
2000 if n <= 0 {
2001 return None;
2002 }
2003 let size = rec + 2; let (mut lo, mut hi) = (0u32, n as u32);
2005 let mut found = None;
2006 while lo < hi {
2007 let mid = (lo + hi) >> 1;
2008 let r = ps.wrapping_add(mid.wrapping_mul(size)).wrapping_add(2);
2009 let s = tb.u16(r);
2010 if s < 0 {
2011 return None;
2012 }
2013 if g2 < s as u32 {
2014 hi = mid;
2015 } else if g2 > s as u32 {
2016 lo = mid + 1;
2017 } else {
2018 found = Some(r.wrapping_add(2));
2019 break;
2020 }
2021 }
2022 found?
2023 }
2024 _ => return None,
2025 };
2026 Some((value, vf1, base))
2027}