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 !is_hyphen(self, p) {
178 match self.nodes.id(p) {
179 id::GLUE => armed = true,
180 id::KERN => armed = false,
181 _ => {}
182 }
183 prev = p;
184 p = self.nodes.next(p);
185 continue;
186 }
187 let mut last = p;
189 let mut len = 1;
190 let mut q = self.nodes.next(p);
191 while !q.is_null() && is_hyphen(self, q) {
192 last = q;
193 len += 1;
194 q = self.nodes.next(q);
195 }
196 let followed = !q.is_null() && self.nodes.is_glyph(q);
197 let convert =
198 followed && (len == 1 || (armed && prev != head && self.has_hj_code(prev)));
199 if !convert {
200 prev = last;
201 p = q;
202 continue;
203 }
204 if len > 1 {
205 armed = false;
206 }
207 let before = if len == 1 {
209 prev
210 } else {
211 self.nodes.prev(last)
212 };
213 self.nodes.set_next(last, NodeRef::NULL);
214 let d = self.nodes.new_disc(2, pen);
215 if let Some(a) = self.nodes.attr(last).cloned() {
216 self.nodes.set_attr(d, Some(a));
217 }
218 let pre = self.nodes.copy_list(last);
219 self.nodes.set_prev(last, NodeRef::NULL);
220 self.nodes.set_disc_lists(d, (pre, NodeRef::NULL, last));
221 self.nodes.link(before, d);
222 self.nodes.link(d, q);
223 prev = d;
224 p = q;
225 }
226 }
227 if !self.languages.is_empty() {
228 self.pattern_hyphenate(head);
229 }
230 }
231
232 fn has_hj_code(&self, p: NodeRef) -> bool {
235 let Some(g) = self.nodes.glyph(p) else {
236 return false;
237 };
238 let lang = u32::from(g.lang);
239 let c = g.chr;
240 let code = match self.language(lang) {
241 Some(l) if l.has_hj_codes() => l.hj_code(c),
242 _ => self.eqtb.lc.get(c).max(0) as u32,
243 };
244 code != 0
245 }
246
247 fn pattern_hyphenate(&mut self, head: NodeRef) {
260 let hpen = self.eqtb.int(ip::HYPHENPENALTY);
261 let auto_ok = self.eqtb.int(ip::AUTOMATICHYPHENMODE) != 0;
262 let mut run: Vec<NodeRef> = Vec::new();
263 let mut word: Vec<NodeRef> = Vec::new();
264 let mut codes: Vec<u32> = Vec::new();
265 let mut pos: Vec<usize> = Vec::new();
266 let mut can_start = true;
267 let mut seen_glyph = false;
268 let mut p = self.nodes.next(head);
269 while !p.is_null() {
270 if self.nodes.is_glyph(p) && self.nodes.subtype(p) & glyph_sub::CHARACTER != 0 {
271 run.clear();
273 let mut q = p;
274 while !q.is_null()
275 && self.nodes.is_glyph(q)
276 && self.nodes.subtype(q) & glyph_sub::CHARACTER != 0
277 {
278 run.push(q);
279 q = self.nodes.next(q);
280 }
281 let end_ok = q.is_null()
282 || match self.nodes.id(q) {
283 id::DISC => auto_ok && self.nodes.subtype(q) == 2,
284 id::MATH | id::MARK => false,
285 _ => true,
286 };
287 let bounds = (can_start, end_ok);
288 self.hyphenate_run(&run, hpen, bounds, &mut word, &mut codes, &mut pos);
289 seen_glyph = true;
290 p = q;
291 continue;
292 }
293 match self.nodes.id(p) {
294 id::GLUE => can_start = true,
295 id::KERN | id::PENALTY | id::MARK | id::ADJUST => can_start &= !seen_glyph,
296 id::DISC if auto_ok && self.nodes.subtype(p) == 2 => can_start = true,
297 id::DISC => can_start &= !seen_glyph,
298 _ => {}
299 }
300 p = self.nodes.next(p);
301 }
302 }
303
304 fn hyphenate_run(
307 &mut self,
308 run: &[NodeRef],
309 hpen: i32,
310 bounds: (bool, bool),
311 word: &mut Vec<NodeRef>,
312 codes: &mut Vec<u32>,
313 pos: &mut Vec<usize>,
314 ) {
315 if !bounds.0 {
316 return;
317 }
318 let mut i = 0;
319 while i < run.len() {
320 let Some(g0) = self.nodes.glyph(run[i]).cloned() else {
322 i += 1;
323 continue;
324 };
325 let lang = u32::from(g0.lang);
326 word.clear();
327 codes.clear();
328 let ex = self.eqtb.int(ip::EXHYPHENCHAR);
332 let mut with_hyphen = false;
333 while i < run.len() {
334 let Some(g) = self.nodes.glyph(run[i]) else {
335 break;
336 };
337 if u32::from(g.lang) != lang {
338 break;
339 }
340 let c = g.chr;
341 let code = match self.language(lang) {
342 Some(l) if l.has_hj_codes() => l.hj_code(c),
343 _ => self.eqtb.lc.get(c).max(0) as u32,
344 };
345 if code == 0 {
346 if word.is_empty() {
347 with_hyphen = ex > 0 && c == ex as u32;
348 i += 1;
349 continue;
350 }
351 with_hyphen |= ex > 0 && c == ex as u32;
352 break;
353 }
354 with_hyphen |= ex > 0 && c == ex as u32;
355 word.push(run[i]);
356 codes.push(code);
357 i += 1;
358 }
359 if word.len() < 2 || with_hyphen {
360 continue;
361 }
362 if !bounds.1 && word.last() == run.last() {
363 continue;
364 }
365 let Some(first) = self.nodes.glyph(word[0]).cloned() else {
366 continue;
367 };
368 if first.font == 0 || self.font(first.font).hyphen_char < 0 {
369 continue;
370 }
371 if !first.uchyph && codes[0] != first.chr {
372 continue;
373 }
374 let Some(language) = self.language(lang) else {
375 continue;
376 };
377 pos.clear();
378 let _ =
379 language.hyphenate_into(codes, u32::from(first.left), u32::from(first.right), pos);
380 if pos.is_empty() {
381 continue;
382 }
383 let settings = language.settings;
384 pos.sort_unstable();
385 pos.dedup();
386 for &k in pos.iter().rev() {
387 if k == 0 || k >= word.len() {
388 continue;
389 }
390 let left = word[k - 1];
391 let right = word[k];
392 let f = self.nodes.glyph(left).map_or(0, |g| g.font);
393 let d = self.nodes.new_disc(3, hpen);
394 if let Some(a) = self.nodes.attr(left).cloned() {
395 self.nodes.set_attr(d, Some(a));
396 }
397 let mk = |e: &mut Engine, c: i32| {
398 if c > 0 {
399 let mut g = e.nodes.glyph(left).cloned().unwrap_or_default();
400 g.chr = c as u32;
401 g.font = f;
402 g.components = NodeRef::NULL;
403 let a = e.nodes.attr(left).cloned();
406 let n = e
407 .nodes
408 .alloc(id::GLYPH, glyph_sub::CHARACTER, NodeData::Glyph(g));
409 e.nodes.set_attr(n, a);
410 n
411 } else {
412 NodeRef::NULL
413 }
414 };
415 let pre = mk(self, settings.pre_hyphen_char);
416 let post = mk(self, settings.post_hyphen_char);
417 self.nodes.set_disc_lists(d, (pre, post, NodeRef::NULL));
418 self.nodes.link(left, d);
419 self.nodes.link(d, right);
420 }
421 }
422 }
423
424 #[inline]
428 fn glyph_of_font(&self, p: NodeRef, f: u32) -> Option<u32> {
429 if p.is_null() {
430 return None;
431 }
432 match self.nodes.data(p) {
433 NodeData::Glyph(g) if g.font == f && self.nodes.subtype(p) & glyph_sub::GHOST == 0 => {
434 Some(g.chr)
435 }
436 _ => None,
437 }
438 }
439
440 #[inline]
442 fn lig_step(&self, f: u32, l: u32, r: u32) -> Option<(u8, u32)> {
443 match self.lig_kern_step(f, l, r) {
444 Some(LigOp::Lig { op, chr }) => Some((op, chr)),
445 _ => None,
446 }
447 }
448
449 fn take_components(&mut self, p: NodeRef) -> NodeRef {
452 let is_lig = self.nodes.subtype(p) & glyph_sub::LIGATURE != 0;
453 if is_lig {
454 let c = self
455 .nodes
456 .glyph_mut(p)
457 .map(|g| std::mem::take(&mut g.components));
458 let c = c.unwrap_or(NodeRef::NULL);
459 self.nodes.free(p);
460 if c.is_null() {
461 return NodeRef::NULL;
462 }
463 c
464 } else {
465 self.nodes.set_next(p, NodeRef::NULL);
466 self.nodes.set_prev(p, NodeRef::NULL);
467 let s = self.nodes.subtype(p) & !glyph_sub::CHARACTER;
468 self.nodes.set_subtype(p, s);
469 p
470 }
471 }
472
473 fn new_ligature(&mut self, model: NodeRef, c: u32, comps: NodeRef) -> NodeRef {
476 let mut g = self.nodes.glyph(model).cloned().unwrap_or_default();
477 g.chr = c;
478 g.components = comps;
479 let a = self.nodes.attr(model).cloned();
480 let n = self
481 .nodes
482 .alloc(id::GLYPH, glyph_sub::LIGATURE, NodeData::Glyph(g));
483 self.nodes.set_attr(n, a);
484 n
485 }
486
487 fn concat(&mut self, a: NodeRef, b: NodeRef) -> NodeRef {
489 if a.is_null() {
490 return b;
491 }
492 if !b.is_null() {
493 let t = self.nodes.tail_of(a);
494 self.nodes.link(t, b);
495 }
496 a
497 }
498
499 fn replace_node(&mut self, prev: NodeRef, old_next: NodeRef, new: NodeRef) {
501 self.nodes.link(prev, new);
502 self.nodes.link(new, old_next);
503 if old_next.is_null() {
504 self.nodes.set_next(new, NodeRef::NULL);
505 }
506 }
507
508 fn ligature_list(&mut self, head: NodeRef, main: bool) {
511 let mut prev = head;
512 let mut p = self.nodes.next(head);
513 while !p.is_null() {
514 match self.nodes.id(p) {
515 id::BOUNDARY if main => {
516 let n = self.nodes.next(p);
517 self.nodes.set_next(prev, n);
518 if !n.is_null() {
519 self.nodes.set_prev(n, prev);
520 }
521 self.nodes.free(p);
522 p = n;
523 }
524 id::GLYPH => {
525 let (last_prev, last) = self.ligature_run(prev, p);
526 let n = self.nodes.next(last);
529 if main
530 && (n.is_null()
531 || !matches!(self.nodes.id(n), id::GLYPH | id::DISC | id::BOUNDARY))
532 {
533 self.right_boundary_kern(last);
534 }
535 if !n.is_null() && self.nodes.id(n) == id::DISC {
536 let (np, nd) = self.lig_disc(last_prev, last, n);
537 prev = np;
538 p = nd;
539 } else {
540 prev = last;
541 p = n;
542 }
543 }
544 id::DISC => {
545 self.lig_disc_lists(p);
546 prev = p;
547 p = self.nodes.next(p);
548 }
549 _ => {
550 prev = p;
551 p = self.nodes.next(p);
552 }
553 }
554 }
555 }
556
557 fn right_boundary_kern(&mut self, p: NodeRef) {
563 let Some((f, l)) = self.nodes.glyph(p).map(|g| (g.font, g.chr)) else {
564 return;
565 };
566 let Some(b) = self.font(f).right_boundary else {
567 return;
568 };
569 if let Some(k) = self.kern_between(f, l, b) {
570 let kn = self.font_kern(k, p);
571 let n = self.nodes.next(p);
572 self.nodes.link(p, kn);
573 self.nodes.link(kn, n);
574 }
575 }
576
577 fn lig_disc_lists(&mut self, d: NodeRef) {
579 let (pre, post, rep) = self.nodes.disc_lists(d);
580 let pre = self.ligature_sublist(pre);
581 let post = self.ligature_sublist(post);
582 let rep = self.ligature_sublist(rep);
583 self.nodes.set_disc_lists(d, (pre, post, rep));
584 }
585
586 fn ligature_sublist(&mut self, l: NodeRef) -> NodeRef {
588 if l.is_null() {
589 return l;
590 }
591 let h = self.nodes.new_temp();
592 self.nodes.link(h, l);
593 self.ligature_list(h, false);
594 let r = self.nodes.next(h);
595 if !r.is_null() {
596 self.nodes.set_prev(r, NodeRef::NULL);
597 }
598 self.nodes.free(h);
599 r
600 }
601
602 fn lig_disc(&mut self, before: NodeRef, last: NodeRef, d: NodeRef) -> (NodeRef, NodeRef) {
607 let f = self.nodes.glyph(last).map_or(0, |g| g.font);
608 if self.font(f).lig_kern.is_empty() {
609 self.lig_disc_lists(d);
610 return (d, self.nodes.next(d));
611 }
612 let lc = self.nodes.glyph(last).map_or(0, |g| g.chr);
613 let (pre, post, rep) = self.nodes.disc_lists(d);
614 let after = self.nodes.next(d);
615 let crosses =
616 |e: &Engine, l: NodeRef| e.glyph_of_font(l, f).and_then(|c| e.lig_step(f, lc, c));
617 let left = crosses(self, pre).is_some()
618 || (!rep.is_null() && crosses(self, rep).is_some())
619 || (rep.is_null() && crosses(self, after).is_some());
620 let (mut pre, mut post, mut rep) = (pre, post, rep);
621 if left {
622 self.nodes.link(before, d);
624 self.nodes.set_next(last, NodeRef::NULL);
625 self.nodes.set_prev(last, NodeRef::NULL);
626 let copy = self.nodes.copy_node(last);
627 pre = self.concat(copy, pre);
628 rep = self.concat(last, rep);
629 }
630 loop {
633 let n = self.nodes.next(d);
634 let Some(nc) = self.glyph_of_font(n, f) else {
635 break;
636 };
637 let ends = |e: &Engine, l: NodeRef| {
638 if l.is_null() {
639 return false;
640 }
641 let t = e.nodes.tail_of(l);
642 e.glyph_of_font(t, f)
643 .is_some_and(|c| e.lig_step(f, c, nc).is_some())
644 };
645 if !(ends(self, post) || ends(self, rep)) {
646 break;
647 }
648 let nn = self.nodes.next(n);
649 self.nodes.link(d, nn);
650 if nn.is_null() {
651 self.nodes.set_next(d, NodeRef::NULL);
652 }
653 self.nodes.set_next(n, NodeRef::NULL);
654 self.nodes.set_prev(n, NodeRef::NULL);
655 let copy = self.nodes.copy_node(n);
656 post = self.concat(post, copy);
657 rep = self.concat(rep, n);
658 }
659 self.nodes.set_disc_lists(d, (pre, post, rep));
660 self.lig_disc_lists(d);
661 (d, self.nodes.next(d))
662 }
663
664 fn ligature_run(&mut self, prev: NodeRef, p: NodeRef) -> (NodeRef, NodeRef) {
668 let f = self.nodes.glyph(p).map_or(0, |g| g.font);
669 if self.font(f).lig_kern.is_empty() {
670 let (mut qp, mut q) = (prev, p);
672 loop {
673 let n = self.nodes.next(q);
674 if self.glyph_of_font(n, f).is_none() {
675 return (qp, q);
676 }
677 qp = q;
678 q = n;
679 }
680 }
681 let mut cur_prev = prev;
682 let mut cur = p;
683 let mut guard = 0u32;
684 loop {
685 let nxt = self.nodes.next(cur);
686 let (Some(l), Some(r)) = (self.glyph_of_font(cur, f), self.glyph_of_font(nxt, f))
687 else {
688 return (cur_prev, cur);
689 };
690 guard += 1;
691 if guard > 100_000 {
692 return (cur_prev, cur);
694 }
695 let Some((op, c)) = self.lig_step(f, l, r) else {
696 cur_prev = cur;
697 cur = nxt;
698 continue;
699 };
700 let after = self.nodes.next(nxt);
701 match op {
702 0 => {
703 let a = self.take_components(cur);
705 let b = self.take_components(nxt);
706 let comps = self.concat(a, b);
707 let model = if comps.is_null() { cur } else { comps };
708 let lig = self.new_ligature(model, c, comps);
709 self.replace_node(cur_prev, after, lig);
710 cur = lig;
711 }
712 1 | 5 => {
713 let a = self.take_components(cur);
715 let model = if a.is_null() { nxt } else { a };
716 let lig = self.new_ligature(model, c, a);
717 self.replace_node(cur_prev, nxt, lig);
718 if op == 5 {
719 cur_prev = lig;
720 cur = nxt;
721 } else {
722 cur = lig;
723 }
724 }
725 2 | 6 => {
726 let b = self.take_components(nxt);
728 let model = if b.is_null() { cur } else { b };
729 let lig = self.new_ligature(model, c, b);
730 self.replace_node(cur, after, lig);
731 if op == 6 {
732 cur_prev = cur;
733 cur = lig;
734 }
735 }
736 _ => {
737 let lig = self.new_ligature(cur, c, NodeRef::NULL);
739 self.nodes.set_subtype(lig, 0);
740 self.replace_node(cur, nxt, lig);
741 match op {
742 7 => {
743 cur_prev = cur;
744 cur = lig;
745 }
746 11 => {
747 cur_prev = lig;
748 cur = nxt;
749 }
750 _ => {}
751 }
752 }
753 }
754 }
755 }
756
757 #[inline]
761 fn kern_between(&self, f: u32, l: u32, r: u32) -> Option<i32> {
762 match self.lig_kern_step(f, l, r) {
763 Some(LigOp::Kern(k)) => Some(k),
764 _ => None,
765 }
766 }
767
768 fn font_kern(&mut self, k: i32, model: NodeRef) -> NodeRef {
770 let n = self.nodes.new_kern(k, kern_sub::FONT);
771 let a = self.nodes.attr(model).cloned();
772 self.nodes.set_attr(n, a);
773 n
774 }
775
776 fn kern_list(&mut self, head: NodeRef) {
779 let mut p = self.nodes.next(head);
780 while !p.is_null() {
781 match self.nodes.id(p) {
782 id::GLYPH => {
783 let s = self.nodes.subtype(p) & !glyph_sub::CHARACTER;
784 self.nodes.set_subtype(p, s);
785 let n = self.nodes.next(p);
786 if n.is_null() {
787 break;
788 }
789 let (f, l) = match self.nodes.glyph(p) {
790 Some(g) => (g.font, g.chr),
791 None => break,
792 };
793 if self.nodes.id(n) == id::GLYPH {
794 if let Some(r) = self.glyph_of_font(n, f)
795 && let Some(k) = self.kern_between(f, l, r)
796 {
797 let kn = self.font_kern(k, p);
798 self.nodes.link(p, kn);
799 self.nodes.link(kn, n);
800 }
801 p = n;
802 } else if self.nodes.id(n) == id::DISC {
803 self.kern_disc(p, n);
804 p = self.nodes.next(n);
805 } else {
806 p = n;
807 }
808 }
809 id::DISC => {
810 self.kern_disc(NodeRef::NULL, p);
811 p = self.nodes.next(p);
812 }
813 _ => p = self.nodes.next(p),
814 }
815 }
816 }
817
818 fn kern_disc(&mut self, before: NodeRef, d: NodeRef) {
821 let (mut pre, mut post, mut rep) = self.nodes.disc_lists(d);
822 pre = self.kern_sublist(pre);
823 post = self.kern_sublist(post);
824 let rep_was_empty = rep.is_null();
825 rep = self.kern_sublist(rep);
826 let after = self.nodes.next(d);
827 let bg = if before.is_null() {
828 None
829 } else {
830 self.nodes.glyph(before).map(|g| (g.font, g.chr))
831 };
832 let ag = if after.is_null() || self.nodes.id(after) != id::GLYPH {
833 None
834 } else {
835 self.nodes.glyph(after).map(|g| (g.font, g.chr))
836 };
837 let sub = self.nodes.subtype(d);
842 let left_kerns = !matches!(sub, 2 | 3);
843 if let Some((f, l)) = bg {
844 if left_kerns
845 && let Some(r) = self.glyph_of_font(pre, f)
846 && let Some(k) = self.kern_between(f, l, r)
847 {
848 let kn = self.font_kern(k, before);
849 self.nodes.link(kn, pre);
850 pre = kn;
851 }
852 if sub == 2 {
853 } else if !rep_was_empty {
855 if let Some(r) = self.glyph_of_font(rep, f)
856 && let Some(k) = self.kern_between(f, l, r)
857 {
858 let kn = self.font_kern(k, before);
859 self.nodes.link(kn, rep);
860 rep = kn;
861 }
862 } else if let Some((af, ac)) = ag
863 && af == f
864 && let Some(k) = self.kern_between(f, l, ac)
865 {
866 rep = self.font_kern(k, before);
867 }
868 }
869 if let Some((f, r)) = ag {
870 if !post.is_null() {
871 let t = self.nodes.tail_of(post);
872 if let Some(l) = self.glyph_of_font(t, f)
873 && let Some(k) = self.kern_between(f, l, r)
874 {
875 let kn = self.font_kern(k, after);
876 self.nodes.link(t, kn);
877 }
878 }
879 if !rep_was_empty {
880 let t = self.nodes.tail_of(rep);
881 if let Some(l) = self.glyph_of_font(t, f)
882 && let Some(k) = self.kern_between(f, l, r)
883 {
884 let kn = self.font_kern(k, after);
885 self.nodes.link(t, kn);
886 }
887 }
888 }
889 self.nodes.set_disc_lists(d, (pre, post, rep));
890 }
891
892 fn kern_sublist(&mut self, l: NodeRef) -> NodeRef {
894 if l.is_null() {
895 return l;
896 }
897 let h = self.nodes.new_temp();
898 self.nodes.link(h, l);
899 self.kern_list(h);
900 let r = self.nodes.next(h);
901 if !r.is_null() {
902 self.nodes.set_prev(r, NodeRef::NULL);
903 }
904 self.nodes.free(h);
905 r
906 }
907}