1use crate::Engine;
11use crate::cmd::Cmd;
12use crate::glue::Glue;
13use crate::nodes::glue_sub;
14use crate::primitives_gen::{assign_glue as gp, assign_int as ip};
15
16#[inline]
18fn is_zero(g: &Glue) -> bool {
19 g.width == 0 && g.stretch == 0 && g.shrink == 0
20}
21
22impl Engine {
23 pub fn main_loop_char(&mut self) {
27 let tracing = self.eqtb.int(ip::TRACINGCOMMANDS) > 0;
28 loop {
29 self.append_char(self.cur_chr);
30 if tracing {
31 self.get_x_token();
33 return;
34 }
35 self.get_next();
36 if matches!(self.cur_cmd, Cmd::Letter | Cmd::OtherChar | Cmd::CharGiven) {
37 continue;
38 }
39 self.x_token();
40 match self.cur_cmd {
41 Cmd::Letter | Cmd::OtherChar | Cmd::CharGiven => continue,
42 Cmd::CharNum => {
43 self.scan_char_num();
44 self.cur_chr = self.cur_val as u32;
45 continue;
46 }
47 _ => return,
48 }
49 }
50 }
51
52 #[inline]
55 fn append_char(&mut self, c: u32) {
56 let s = self.eqtb.sf.get(c) as i32;
57 let cl = self.cur_list_mut();
58 if s == 1000 {
59 cl.space_factor = 1000;
60 } else if s < 1000 {
61 if s > 0 {
62 cl.space_factor = s;
63 }
64 } else if cl.space_factor < 1000 {
65 cl.space_factor = 1000;
66 } else {
67 cl.space_factor = s;
68 }
69 let f = self.eqtb.cur_font.val;
70 let g = self.new_char_node(f, c);
71 self.tail_append(g);
72 }
73
74 fn font_glue(&self, f: u32) -> Glue {
76 let p = &self.font(f).params;
77 Glue {
78 width: p.get(2).copied().unwrap_or(0),
79 stretch: p.get(3).copied().unwrap_or(0),
80 shrink: p.get(4).copied().unwrap_or(0),
81 ..Glue::ZERO
82 }
83 }
84
85 pub fn app_space_main(&mut self) {
87 if self.cur_list().space_factor == 1000 {
88 self.append_normal_space();
89 } else {
90 self.app_space();
91 }
92 }
93
94 pub fn app_explicit_space(&mut self) {
96 self.append_normal_space();
97 }
98
99 fn append_normal_space(&mut self) {
101 let ss = self.eqtb.glue(gp::SPACESKIP);
102 let g = if is_zero(&ss) {
103 self.font_glue(self.eqtb.cur_font.val)
104 } else {
105 ss
106 };
107 let p = self.new_glue_node(g, glue_sub::SPACE_SKIP);
108 self.tail_append(p);
109 }
110
111 fn app_space(&mut self) {
113 let sf = self.cur_list().space_factor;
114 let xs = self.eqtb.glue(gp::XSPACESKIP);
115 let p = if sf >= 2000 && !is_zero(&xs) {
116 self.new_glue_node(xs, glue_sub::XSPACE_SKIP)
117 } else {
118 let ss = self.eqtb.glue(gp::SPACESKIP);
119 let f = self.eqtb.cur_font.val;
120 let mut g = if is_zero(&ss) { self.font_glue(f) } else { ss };
121 if sf >= 2000 {
122 g.width += self.font(f).params.get(7).copied().unwrap_or(0);
123 }
124 g.stretch = retex_arith::xn_over_d(g.stretch, sf, 1000)
125 .map(|r| r.quotient)
126 .unwrap_or(g.stretch);
127 g.shrink = retex_arith::xn_over_d(g.shrink, 1000, sf)
128 .map(|r| r.quotient)
129 .unwrap_or(g.shrink);
130 self.new_glue_node(g, glue_sub::SPACE_SKIP)
131 };
132 self.tail_append(p);
133 }
134}