1use crate::Engine;
34use crate::fonts::LigOp;
35use crate::nodes::{GlyphData, NodeData, NodeRef, glyph_sub, id, kern_sub};
36use crate::primitives_gen::assign_int as ip;
37
38#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum Context {
41 Hbox,
43 Paragraph,
45}
46
47#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub enum NodePass {
50 Hyphenate,
52 Ligaturing,
54 Kerning,
56}
57
58impl Engine {
59 pub fn lang_params(&self, l: u32) -> retex_hyph::Settings {
61 self.language(l).map(|x| x.settings).unwrap_or_default()
62 }
63
64 pub fn new_char_node(&mut self, f: u32, c: u32) -> NodeRef {
67 let lang = self.cur_lang() as u16;
68 let left = self.eqtb.int(ip::LEFTHYPHENMIN).clamp(0, 63) as u8;
69 let right = self.eqtb.int(ip::RIGHTHYPHENMIN).clamp(0, 63) as u8;
70 let uchyph = self.eqtb.int(ip::UCHYPH) > 0;
71 self.new_node(
72 id::GLYPH,
73 glyph_sub::CHARACTER,
74 NodeData::Glyph(GlyphData {
75 chr: c,
76 font: f,
77 lang,
78 left,
79 right,
80 uchyph,
81 ..GlyphData::default()
82 }),
83 )
84 }
85
86 pub fn node_process_list(&mut self, first: NodeRef, ctx: Context) -> NodeRef {
89 if first.is_null() {
90 return first;
91 }
92 self.fonts.sync_dense();
93 let head = self.nodes.new_temp();
94 self.nodes.link(head, first);
95 let saved_par_temp = self.nodes.par_temp;
96 if ctx == Context::Paragraph {
97 self.nodes.par_temp = head;
98 }
99 let host = self.lua.clone();
102 let pass = |e: &mut Engine, cb: &str| match &host {
103 Some(h) => h.node_pass(e, cb, head),
104 None => false,
105 };
106 if !pass(self, "hyphenate") {
107 self.hyphenate_list(head);
108 }
109 if !pass(self, "ligaturing") {
110 self.ligature_list(head, true);
111 }
112 if !pass(self, "kerning") {
113 self.kern_list(head);
114 }
115 self.nodes.par_temp = saved_par_temp;
116 let first = self.nodes.next(head);
117 if !first.is_null() {
118 self.nodes.set_prev(first, NodeRef::NULL);
119 }
120 self.nodes.free(head);
121 first
122 }
123
124 pub fn lua_node_pass(&mut self, pass: NodePass, head: NodeRef) -> (NodeRef, NodeRef) {
129 if head.is_null() {
130 return (head, head);
131 }
132 self.fonts.sync_dense();
133 let temp = self.nodes.id(head) == id::TEMP;
134 let h = if temp {
135 head
136 } else {
137 let t = self.nodes.new_temp();
138 self.nodes.link(t, head);
139 t
140 };
141 match pass {
142 NodePass::Hyphenate => self.hyphenate_list(h),
143 NodePass::Ligaturing => self.ligature_list(h, true),
144 NodePass::Kerning => self.kern_list(h),
145 }
146 let first = if temp {
147 head
148 } else {
149 let f = self.nodes.next(h);
150 if !f.is_null() {
151 self.nodes.set_prev(f, NodeRef::NULL);
152 }
153 self.nodes.free(h);
154 f
155 };
156 let tail = self.nodes.tail_of(first);
157 (first, tail)
158 }
159
160 fn hyphenate_list(&mut self, head: NodeRef) {
166 let ex = self.eqtb.int(ip::EXHYPHENCHAR);
167 let pen = self.eqtb.int(ip::EXHYPHENPENALTY);
168 if ex > 0 {
169 let ex = ex as u32;
170 let is_hyphen = |e: &Engine, n: NodeRef| e.nodes.glyph(n).is_some_and(|g| g.chr == ex);
171 let mut armed = true;
174 let mut prev = head;
175 let mut p = self.nodes.next(head);
176 while !p.is_null() {
177 if self.nodes.id(p) == id::MATH && self.nodes.subtype(p) == 0 {
180 let mut q = self.nodes.next(p);
181 while !(q.is_null()
182 || (self.nodes.id(q) == id::MATH && self.nodes.subtype(q) == 1))
183 {
184 q = self.nodes.next(q);
185 }
186 if q.is_null() {
187 break;
188 }
189 prev = q;
190 p = self.nodes.next(q);
191 continue;
192 }
193 if !is_hyphen(self, p) {
194 match self.nodes.id(p) {
195 id::GLUE => armed = true,
196 id::KERN => armed = false,
197 _ => {}
198 }
199 prev = p;
200 p = self.nodes.next(p);
201 continue;
202 }
203 let mut last = p;
205 let mut len = 1;
206 let mut q = self.nodes.next(p);
207 while !q.is_null() && is_hyphen(self, q) {
208 last = q;
209 len += 1;
210 q = self.nodes.next(q);
211 }
212 let followed = !q.is_null() && self.nodes.is_glyph(q);
213 let convert =
214 followed && (len == 1 || (armed && prev != head && self.has_hj_code(prev)));
215 if !convert {
216 prev = last;
217 p = q;
218 continue;
219 }
220 if len > 1 {
221 armed = false;
222 }
223 let before = if len == 1 {
225 prev
226 } else {
227 self.nodes.prev(last)
228 };
229 self.nodes.set_next(last, NodeRef::NULL);
230 let d = self.nodes.new_disc(2, pen);
231 if let Some(a) = self.nodes.attr(last).cloned() {
232 self.nodes.set_attr(d, Some(a));
233 }
234 let pre = self.nodes.copy_list(last);
235 self.nodes.set_prev(last, NodeRef::NULL);
236 self.nodes.set_disc_lists(d, (pre, NodeRef::NULL, last));
237 self.nodes.link(before, d);
238 self.nodes.link(d, q);
239 prev = d;
240 p = q;
241 }
242 }
243 if !self.languages.is_empty() {
244 self.pattern_hyphenate(head);
245 }
246 }
247
248 fn has_hj_code(&self, p: NodeRef) -> bool {
251 let Some(g) = self.nodes.glyph(p) else {
252 return false;
253 };
254 let lang = u32::from(g.lang);
255 let c = g.chr;
256 let code = match self.language(lang) {
257 Some(l) if l.has_hj_codes() => l.hj_code(c),
258 _ => self.eqtb.lc.get(c).max(0) as u32,
259 };
260 code != 0
261 }
262
263 fn pattern_hyphenate(&mut self, head: NodeRef) {
282 let hpen = self.eqtb.int(ip::HYPHENPENALTY);
283 let auto_ok = self.eqtb.int(ip::AUTOMATICHYPHENMODE) != 0;
284 let mut run: Vec<NodeRef> = Vec::new();
285 let mut word: Vec<NodeRef> = Vec::new();
286 let mut codes: Vec<u32> = Vec::new();
287 let mut pos: Vec<usize> = Vec::new();
288 let mut can_start = true;
289 let mut seen_glyph = false;
290 let mut skip_first = false;
293 let mut unit_kill: Option<bool> = None;
296 let mut p = self.nodes.next(head);
297 while !p.is_null() {
298 if self.nodes.is_glyph(p) && self.nodes.subtype(p) & glyph_sub::CHARACTER != 0 {
299 run.clear();
301 let mut q = p;
302 while !q.is_null()
303 && self.nodes.is_glyph(q)
304 && self.nodes.subtype(q) & glyph_sub::CHARACTER != 0
305 {
306 run.push(q);
307 q = self.nodes.next(q);
308 }
309 let end_ok = q.is_null()
310 || match self.nodes.id(q) {
311 id::DISC => auto_ok && self.nodes.subtype(q) == 2,
312 id::MATH | id::MARK => false,
313 _ => true,
314 };
315 let kill = *unit_kill.get_or_insert_with(|| self.unit_ends_badly(q));
316 let bounds = (can_start && !kill, end_ok, skip_first);
317 self.hyphenate_run(&run, hpen, bounds, &mut word, &mut codes, &mut pos);
318 seen_glyph = true;
319 skip_first = false;
320 p = q;
321 continue;
322 }
323 if !(self.nodes.id(p) == id::DISC && self.nodes.subtype(p) == 2) {
324 unit_kill = None;
325 }
326 if self.nodes.id(p) == id::MATH && self.nodes.subtype(p) == 0 {
330 let mut q = self.nodes.next(p);
331 while !(q.is_null() || (self.nodes.id(q) == id::MATH && self.nodes.subtype(q) == 1))
332 {
333 q = self.nodes.next(q);
334 }
335 p = if q.is_null() { q } else { self.nodes.next(q) };
336 continue;
337 }
338 match self.nodes.id(p) {
339 id::GLUE => can_start = true,
340 id::KERN | id::PENALTY | id::MARK | id::ADJUST => can_start &= !seen_glyph,
341 id::DISC if auto_ok && self.nodes.subtype(p) == 2 => can_start = true,
342 id::DISC if self.nodes.subtype(p) == 2 && self.single_hyphen_disc(p) => {
343 can_start = true;
344 skip_first = true;
345 }
346 id::DISC => can_start &= !seen_glyph,
347 _ => {}
348 }
349 p = self.nodes.next(p);
350 }
351 }
352
353 fn single_hyphen_disc(&self, d: NodeRef) -> bool {
356 let ex = self.eqtb.int(ip::EXHYPHENCHAR);
357 let prev = self.nodes.prev(d);
358 !prev.is_null()
359 && self
360 .nodes
361 .glyph(prev)
362 .is_some_and(|g| ex <= 0 || g.chr != ex as u32)
363 }
364
365 fn unit_ends_badly(&self, mut q: NodeRef) -> bool {
369 loop {
370 if q.is_null() {
371 return false;
372 }
373 match self.nodes.id(q) {
374 id::DISC if self.nodes.subtype(q) == 2 => {}
375 id::DISC | id::MATH | id::MARK => return true,
376 _ if self.nodes.is_glyph(q)
377 && self.nodes.subtype(q) & glyph_sub::CHARACTER != 0 => {}
378 _ => return false,
379 }
380 q = self.nodes.next(q);
381 }
382 }
383
384 fn hyphenate_run(
387 &mut self,
388 run: &[NodeRef],
389 hpen: i32,
390 bounds: (bool, bool, bool),
391 word: &mut Vec<NodeRef>,
392 codes: &mut Vec<u32>,
393 pos: &mut Vec<usize>,
394 ) {
395 if !bounds.0 {
396 return;
397 }
398 let mut i = 0;
399 while i < run.len() {
400 let Some(g0) = self.nodes.glyph(run[i]).cloned() else {
402 i += 1;
403 continue;
404 };
405 let lang = u32::from(g0.lang);
406 word.clear();
407 codes.clear();
408 let ex = self.eqtb.int(ip::EXHYPHENCHAR);
412 let mut with_hyphen = false;
413 while i < run.len() {
414 let Some(g) = self.nodes.glyph(run[i]) else {
415 break;
416 };
417 if u32::from(g.lang) != lang {
418 break;
419 }
420 let c = g.chr;
421 let code = match self.language(lang) {
422 Some(l) if l.has_hj_codes() => l.hj_code(c),
423 _ => self.eqtb.lc.get(c).max(0) as u32,
424 };
425 if code == 0 {
426 if word.is_empty() {
427 with_hyphen = ex > 0 && c == ex as u32;
428 i += 1;
429 continue;
430 }
431 with_hyphen |= ex > 0 && c == ex as u32;
432 break;
433 }
434 with_hyphen |= ex > 0 && c == ex as u32;
435 word.push(run[i]);
436 codes.push(code);
437 i += 1;
438 }
439 if word.len() < 2 || with_hyphen || (bounds.2 && word.first() == run.first()) {
440 continue;
441 }
442 if !bounds.1 && word.last() == run.last() {
443 continue;
444 }
445 let Some(first) = self.nodes.glyph(word[0]).cloned() else {
446 continue;
447 };
448 if first.font == 0 || self.font(first.font).hyphen_char < 0 {
449 continue;
450 }
451 if !first.uchyph && codes[0] != first.chr {
452 continue;
453 }
454 let Some(language) = self.language(lang) else {
455 continue;
456 };
457 pos.clear();
458 let _ =
459 language.hyphenate_into(codes, u32::from(first.left), u32::from(first.right), pos);
460 if pos.is_empty() {
461 continue;
462 }
463 let settings = language.settings;
464 pos.sort_unstable();
465 pos.dedup();
466 for &k in pos.iter().rev() {
467 if k == 0 || k >= word.len() {
468 continue;
469 }
470 let left = word[k - 1];
471 let right = word[k];
472 let f = self.nodes.glyph(left).map_or(0, |g| g.font);
473 let d = self.nodes.new_disc(3, hpen);
474 if let Some(a) = self.nodes.attr(left).cloned() {
475 self.nodes.set_attr(d, Some(a));
476 }
477 let mk = |e: &mut Engine, c: i32| {
478 if c > 0 {
479 let mut g = e.nodes.glyph(left).cloned().unwrap_or_default();
480 g.chr = c as u32;
481 g.font = f;
482 g.components = NodeRef::NULL;
483 let a = e.nodes.attr(left).cloned();
486 let n = e
487 .nodes
488 .alloc(id::GLYPH, glyph_sub::CHARACTER, NodeData::Glyph(g));
489 e.nodes.set_attr(n, a);
490 n
491 } else {
492 NodeRef::NULL
493 }
494 };
495 let pre = mk(self, settings.pre_hyphen_char);
496 let post = mk(self, settings.post_hyphen_char);
497 self.nodes.set_disc_lists(d, (pre, post, NodeRef::NULL));
498 self.nodes.link(left, d);
499 self.nodes.link(d, right);
500 }
501 }
502 }
503
504 #[inline]
508 fn glyph_of_font(&self, p: NodeRef, f: u32) -> Option<u32> {
509 if p.is_null() {
510 return None;
511 }
512 match self.nodes.data(p) {
513 NodeData::Glyph(g) if g.font == f && self.nodes.subtype(p) & glyph_sub::GHOST == 0 => {
514 Some(g.chr)
515 }
516 _ => None,
517 }
518 }
519
520 #[inline]
523 fn lig_step(&self, f: u32, l: u32, r: u32) -> Option<(u8, u32)> {
524 if self.font(f).ignore_ligatures != 0 {
525 return None;
526 }
527 match self.lig_kern_step(f, l, r) {
528 Some(LigOp::Lig { op, chr }) => Some((op, chr)),
529 _ => None,
530 }
531 }
532
533 fn take_components(&mut self, p: NodeRef) -> NodeRef {
536 let is_lig = self.nodes.subtype(p) & glyph_sub::LIGATURE != 0;
537 if is_lig {
538 let c = self
539 .nodes
540 .glyph_mut(p)
541 .map(|g| std::mem::take(&mut g.components));
542 let c = c.unwrap_or(NodeRef::NULL);
543 self.nodes.free(p);
544 if c.is_null() {
545 return NodeRef::NULL;
546 }
547 c
548 } else {
549 self.nodes.set_next(p, NodeRef::NULL);
550 self.nodes.set_prev(p, NodeRef::NULL);
551 let s = self.nodes.subtype(p) & !glyph_sub::CHARACTER;
552 self.nodes.set_subtype(p, s);
553 p
554 }
555 }
556
557 fn new_ligature(&mut self, model: NodeRef, c: u32, comps: NodeRef) -> NodeRef {
560 let mut g = self.nodes.glyph(model).cloned().unwrap_or_default();
561 g.chr = c;
562 g.components = comps;
563 let a = self.nodes.attr(model).cloned();
564 let n = self
565 .nodes
566 .alloc(id::GLYPH, glyph_sub::LIGATURE, NodeData::Glyph(g));
567 self.nodes.set_attr(n, a);
568 n
569 }
570
571 fn concat(&mut self, a: NodeRef, b: NodeRef) -> NodeRef {
573 if a.is_null() {
574 return b;
575 }
576 if !b.is_null() {
577 let t = self.nodes.tail_of(a);
578 self.nodes.link(t, b);
579 }
580 a
581 }
582
583 fn replace_node(&mut self, prev: NodeRef, old_next: NodeRef, new: NodeRef) {
585 self.nodes.link(prev, new);
586 self.nodes.link(new, old_next);
587 if old_next.is_null() {
588 self.nodes.set_next(new, NodeRef::NULL);
589 }
590 }
591
592 fn ligature_list(&mut self, head: NodeRef, main: bool) {
595 let mut prev = head;
596 let mut p = self.nodes.next(head);
597 while !p.is_null() {
598 match self.nodes.id(p) {
599 id::BOUNDARY if main => {
600 let n = self.nodes.next(p);
601 self.nodes.set_next(prev, n);
602 if !n.is_null() {
603 self.nodes.set_prev(n, prev);
604 }
605 self.nodes.free(p);
606 p = n;
607 }
608 id::GLYPH => {
609 let (last_prev, last) = self.ligature_run(prev, p);
610 let n = self.nodes.next(last);
613 if main
614 && (n.is_null()
615 || !matches!(self.nodes.id(n), id::GLYPH | id::DISC | id::BOUNDARY))
616 {
617 self.right_boundary_kern(last);
618 }
619 if !n.is_null() && self.nodes.id(n) == id::DISC {
620 let (np, nd) = self.lig_disc(last_prev, last, n);
621 prev = np;
622 p = nd;
623 } else {
624 prev = last;
625 p = n;
626 }
627 }
628 id::DISC => {
629 self.lig_disc_lists(p);
630 prev = p;
631 p = self.nodes.next(p);
632 }
633 _ => {
634 prev = p;
635 p = self.nodes.next(p);
636 }
637 }
638 }
639 }
640
641 fn right_boundary_kern(&mut self, p: NodeRef) {
647 let Some((f, l)) = self.nodes.glyph(p).map(|g| (g.font, g.chr)) else {
648 return;
649 };
650 let Some(b) = self.font(f).right_boundary else {
651 return;
652 };
653 if let Some(k) = self.kern_between(f, l, b) {
654 let kn = self.font_kern(k, p);
655 let n = self.nodes.next(p);
656 self.nodes.link(p, kn);
657 self.nodes.link(kn, n);
658 }
659 }
660
661 fn lig_disc_lists(&mut self, d: NodeRef) {
663 let (pre, post, rep) = self.nodes.disc_lists(d);
664 let pre = self.ligature_sublist(pre);
665 let post = self.ligature_sublist(post);
666 let rep = self.ligature_sublist(rep);
667 self.nodes.set_disc_lists(d, (pre, post, rep));
668 }
669
670 fn ligature_sublist(&mut self, l: NodeRef) -> NodeRef {
672 if l.is_null() {
673 return l;
674 }
675 let h = self.nodes.new_temp();
676 self.nodes.link(h, l);
677 self.ligature_list(h, false);
678 let r = self.nodes.next(h);
679 if !r.is_null() {
680 self.nodes.set_prev(r, NodeRef::NULL);
681 }
682 self.nodes.free(h);
683 r
684 }
685
686 fn lig_disc(&mut self, before: NodeRef, last: NodeRef, d: NodeRef) -> (NodeRef, NodeRef) {
691 let f = self.nodes.glyph(last).map_or(0, |g| g.font);
692 if self.font(f).lig_kern.is_empty() {
693 self.lig_disc_lists(d);
694 return (d, self.nodes.next(d));
695 }
696 let lc = self.nodes.glyph(last).map_or(0, |g| g.chr);
697 let (pre, post, rep) = self.nodes.disc_lists(d);
698 let after = self.nodes.next(d);
699 let crosses =
700 |e: &Engine, l: NodeRef| e.glyph_of_font(l, f).and_then(|c| e.lig_step(f, lc, c));
701 let left = crosses(self, pre).is_some()
702 || (!rep.is_null() && crosses(self, rep).is_some())
703 || (rep.is_null() && crosses(self, after).is_some());
704 let (mut pre, mut post, mut rep) = (pre, post, rep);
705 if left {
706 self.nodes.link(before, d);
708 self.nodes.set_next(last, NodeRef::NULL);
709 self.nodes.set_prev(last, NodeRef::NULL);
710 let copy = self.nodes.copy_node(last);
711 pre = self.concat(copy, pre);
712 rep = self.concat(last, rep);
713 }
714 loop {
717 let n = self.nodes.next(d);
718 let Some(nc) = self.glyph_of_font(n, f) else {
719 break;
720 };
721 let ends = |e: &Engine, l: NodeRef| {
722 if l.is_null() {
723 return false;
724 }
725 let t = e.nodes.tail_of(l);
726 e.glyph_of_font(t, f)
727 .is_some_and(|c| e.lig_step(f, c, nc).is_some())
728 };
729 if !(ends(self, post) || ends(self, rep)) {
730 break;
731 }
732 let nn = self.nodes.next(n);
733 self.nodes.link(d, nn);
734 if nn.is_null() {
735 self.nodes.set_next(d, NodeRef::NULL);
736 }
737 self.nodes.set_next(n, NodeRef::NULL);
738 self.nodes.set_prev(n, NodeRef::NULL);
739 let copy = self.nodes.copy_node(n);
740 post = self.concat(post, copy);
741 rep = self.concat(rep, n);
742 }
743 self.nodes.set_disc_lists(d, (pre, post, rep));
744 self.lig_disc_lists(d);
745 (d, self.nodes.next(d))
746 }
747
748 fn ligature_run(&mut self, prev: NodeRef, p: NodeRef) -> (NodeRef, NodeRef) {
752 let f = self.nodes.glyph(p).map_or(0, |g| g.font);
753 if self.font(f).lig_kern.is_empty() {
754 let (mut qp, mut q) = (prev, p);
756 loop {
757 let n = self.nodes.next(q);
758 if self.glyph_of_font(n, f).is_none() {
759 return (qp, q);
760 }
761 qp = q;
762 q = n;
763 }
764 }
765 let mut cur_prev = prev;
766 let mut cur = p;
767 let mut guard = 0u32;
768 loop {
769 let nxt = self.nodes.next(cur);
770 let (Some(l), Some(r)) = (self.glyph_of_font(cur, f), self.glyph_of_font(nxt, f))
771 else {
772 return (cur_prev, cur);
773 };
774 guard += 1;
775 if guard > 100_000 {
776 return (cur_prev, cur);
778 }
779 let Some((op, c)) = self.lig_step(f, l, r) else {
780 cur_prev = cur;
781 cur = nxt;
782 continue;
783 };
784 let after = self.nodes.next(nxt);
785 match op {
786 0 => {
787 let a = self.take_components(cur);
789 let b = self.take_components(nxt);
790 let comps = self.concat(a, b);
791 let model = if comps.is_null() { cur } else { comps };
792 let lig = self.new_ligature(model, c, comps);
793 self.replace_node(cur_prev, after, lig);
794 cur = lig;
795 }
796 1 | 5 => {
797 let a = self.take_components(cur);
799 let model = if a.is_null() { nxt } else { a };
800 let lig = self.new_ligature(model, c, a);
801 self.replace_node(cur_prev, nxt, lig);
802 if op == 5 {
803 cur_prev = lig;
804 cur = nxt;
805 } else {
806 cur = lig;
807 }
808 }
809 2 | 6 => {
810 let b = self.take_components(nxt);
812 let model = if b.is_null() { cur } else { b };
813 let lig = self.new_ligature(model, c, b);
814 self.replace_node(cur, after, lig);
815 if op == 6 {
816 cur_prev = cur;
817 cur = lig;
818 }
819 }
820 _ => {
821 let lig = self.new_ligature(cur, c, NodeRef::NULL);
823 self.nodes.set_subtype(lig, 0);
824 self.replace_node(cur, nxt, lig);
825 match op {
826 7 => {
827 cur_prev = cur;
828 cur = lig;
829 }
830 11 => {
831 cur_prev = lig;
832 cur = nxt;
833 }
834 _ => {}
835 }
836 }
837 }
838 }
839 }
840
841 #[inline]
845 fn kern_between(&self, f: u32, l: u32, r: u32) -> Option<i32> {
846 match self.lig_kern_step(f, l, r) {
847 Some(LigOp::Kern(k)) => Some(k),
848 _ => None,
849 }
850 }
851
852 fn font_kern(&mut self, k: i32, model: NodeRef) -> NodeRef {
854 let n = self.nodes.new_kern(k, kern_sub::FONT);
855 let a = self.nodes.attr(model).cloned();
856 self.nodes.set_attr(n, a);
857 n
858 }
859
860 fn kern_list(&mut self, head: NodeRef) {
863 let mut p = self.nodes.next(head);
864 while !p.is_null() {
865 match self.nodes.id(p) {
866 id::GLYPH => {
867 let s = self.nodes.subtype(p) & !glyph_sub::CHARACTER;
868 self.nodes.set_subtype(p, s);
869 let n = self.nodes.next(p);
870 if n.is_null() {
871 break;
872 }
873 let (f, l) = match self.nodes.glyph(p) {
874 Some(g) => (g.font, g.chr),
875 None => break,
876 };
877 if self.nodes.id(n) == id::GLYPH {
878 if let Some(r) = self.glyph_of_font(n, f)
879 && let Some(k) = self.kern_between(f, l, r)
880 {
881 let kn = self.font_kern(k, p);
882 self.nodes.link(p, kn);
883 self.nodes.link(kn, n);
884 }
885 p = n;
886 } else if self.nodes.id(n) == id::DISC {
887 self.kern_disc(p, n);
888 p = self.nodes.next(n);
889 } else {
890 p = n;
891 }
892 }
893 id::DISC => {
894 self.kern_disc(NodeRef::NULL, p);
895 p = self.nodes.next(p);
896 }
897 _ => p = self.nodes.next(p),
898 }
899 }
900 }
901
902 fn kern_disc(&mut self, before: NodeRef, d: NodeRef) {
905 let (mut pre, mut post, mut rep) = self.nodes.disc_lists(d);
906 pre = self.kern_sublist(pre);
907 post = self.kern_sublist(post);
908 let rep_was_empty = rep.is_null();
909 rep = self.kern_sublist(rep);
910 let after = self.nodes.next(d);
911 let bg = if before.is_null() {
912 None
913 } else {
914 self.nodes.glyph(before).map(|g| (g.font, g.chr))
915 };
916 let ag = if after.is_null() || self.nodes.id(after) != id::GLYPH {
917 None
918 } else {
919 self.nodes.glyph(after).map(|g| (g.font, g.chr))
920 };
921 let sub = self.nodes.subtype(d);
926 let left_kerns = !matches!(sub, 2 | 3);
927 if let Some((f, l)) = bg {
928 if left_kerns
929 && let Some(r) = self.glyph_of_font(pre, f)
930 && let Some(k) = self.kern_between(f, l, r)
931 {
932 let kn = self.font_kern(k, before);
933 self.nodes.link(kn, pre);
934 pre = kn;
935 }
936 if sub == 2 {
937 } else if !rep_was_empty {
939 if let Some(r) = self.glyph_of_font(rep, f)
940 && let Some(k) = self.kern_between(f, l, r)
941 {
942 let kn = self.font_kern(k, before);
943 self.nodes.link(kn, rep);
944 rep = kn;
945 }
946 } else if let Some((af, ac)) = ag
947 && af == f
948 && let Some(k) = self.kern_between(f, l, ac)
949 {
950 rep = self.font_kern(k, before);
951 }
952 }
953 if let Some((f, r)) = ag {
954 if !post.is_null() {
955 let t = self.nodes.tail_of(post);
956 if let Some(l) = self.glyph_of_font(t, f)
957 && let Some(k) = self.kern_between(f, l, r)
958 {
959 let kn = self.font_kern(k, after);
960 self.nodes.link(t, kn);
961 }
962 }
963 if !rep_was_empty {
964 let t = self.nodes.tail_of(rep);
965 if let Some(l) = self.glyph_of_font(t, f)
966 && let Some(k) = self.kern_between(f, l, r)
967 {
968 let kn = self.font_kern(k, after);
969 self.nodes.link(t, kn);
970 }
971 }
972 }
973 self.nodes.set_disc_lists(d, (pre, post, rep));
974 }
975
976 fn kern_sublist(&mut self, l: NodeRef) -> NodeRef {
978 if l.is_null() {
979 return l;
980 }
981 let h = self.nodes.new_temp();
982 self.nodes.link(h, l);
983 self.kern_list(h);
984 let r = self.nodes.next(h);
985 if !r.is_null() {
986 self.nodes.set_prev(r, NodeRef::NULL);
987 }
988 self.nodes.free(h);
989 r
990 }
991}