1use std::rc::Rc;
9
10use crate::glue::Glue;
11use crate::token::TokenList;
12
13pub const LUATEX_NODE_TYPES: &str = include_str!("../data/luatex-node-types.txt");
17
18pub fn type_name(t: u8) -> String {
20 LUATEX_NODE_TYPES
21 .lines()
22 .filter_map(|l| l.strip_prefix("type "))
23 .find_map(|l| {
24 let mut it = l.split_whitespace();
25 let n: u8 = it.next()?.parse().ok()?;
26 (n == t).then(|| it.next().unwrap_or("").to_owned())
27 })
28 .unwrap_or_default()
29}
30
31#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, PartialOrd, Ord)]
34pub struct NodeRef(pub u32);
35
36impl NodeRef {
37 pub const NULL: NodeRef = NodeRef(0);
39
40 #[inline]
42 pub const fn is_null(self) -> bool {
43 self.0 == 0
44 }
45}
46
47pub const RUNNING: i32 = -0o10000000000;
49
50#[allow(missing_docs)]
52pub mod id {
53 pub const HLIST: u8 = 0;
54 pub const VLIST: u8 = 1;
55 pub const RULE: u8 = 2;
56 pub const INS: u8 = 3;
57 pub const MARK: u8 = 4;
58 pub const ADJUST: u8 = 5;
59 pub const BOUNDARY: u8 = 6;
60 pub const DISC: u8 = 7;
61 pub const WHATSIT: u8 = 8;
62 pub const LOCAL_PAR: u8 = 9;
63 pub const DIR: u8 = 10;
64 pub const MATH: u8 = 11;
65 pub const GLUE: u8 = 12;
66 pub const KERN: u8 = 13;
67 pub const PENALTY: u8 = 14;
68 pub const UNSET: u8 = 15;
69 pub const STYLE: u8 = 16;
70 pub const CHOICE: u8 = 17;
71 pub const NOAD: u8 = 18;
72 pub const RADICAL: u8 = 19;
73 pub const FRACTION: u8 = 20;
74 pub const ACCENT: u8 = 21;
75 pub const FENCE: u8 = 22;
76 pub const MATH_CHAR: u8 = 23;
77 pub const SUB_BOX: u8 = 24;
78 pub const SUB_MLIST: u8 = 25;
79 pub const MATH_TEXT_CHAR: u8 = 26;
80 pub const DELIM: u8 = 27;
81 pub const MARGIN_KERN: u8 = 28;
82 pub const GLYPH: u8 = 29;
83 pub const ALIGN_RECORD: u8 = 30;
84 pub const PAGE_INSERT: u8 = 33;
85 pub const SPLIT_INSERT: u8 = 34;
86 pub const GLUE_SPEC: u8 = 39;
89 pub const TEMP: u8 = 41;
90 pub const FREE: u8 = 255;
92}
93
94pub const MAX_NESTING: u32 = 50_000;
98
99#[allow(missing_docs)]
101pub mod glue_sub {
102 pub const USER: u16 = 0;
103 pub const LINE_SKIP: u16 = 1;
104 pub const BASELINE_SKIP: u16 = 2;
105 pub const PAR_SKIP: u16 = 3;
106 pub const ABOVE_DISPLAY: u16 = 4;
107 pub const BELOW_DISPLAY: u16 = 5;
108 pub const ABOVE_DISPLAY_SHORT: u16 = 6;
109 pub const BELOW_DISPLAY_SHORT: u16 = 7;
110 pub const LEFT_SKIP: u16 = 8;
111 pub const RIGHT_SKIP: u16 = 9;
112 pub const TOP_SKIP: u16 = 10;
113 pub const SPLIT_TOP_SKIP: u16 = 11;
114 pub const TAB_SKIP: u16 = 12;
115 pub const SPACE_SKIP: u16 = 13;
116 pub const XSPACE_SKIP: u16 = 14;
117 pub const PAR_FILL_SKIP: u16 = 15;
118 pub const MATH_SKIP: u16 = 16;
119 pub const THIN_MU_SKIP: u16 = 17;
120 pub const MED_MU_SKIP: u16 = 18;
121 pub const THICK_MU_SKIP: u16 = 19;
122 pub const COND_MATH_GLUE: u16 = 98;
123 pub const MU_GLUE: u16 = 99;
124 pub const A_LEADERS: u16 = 100;
125 pub const C_LEADERS: u16 = 101;
126 pub const X_LEADERS: u16 = 102;
127 pub const G_LEADERS: u16 = 103;
128}
129
130pub mod list_sub {
133 pub const MATH_CHAR: u16 = 9;
135 pub const H_EXTENSIBLE: u16 = 10;
137 pub const V_EXTENSIBLE: u16 = 11;
139 pub const V_DELIMITER: u16 = 13;
141 pub const OVER_DELIMITER: u16 = 14;
143 pub const UNDER_DELIMITER: u16 = 15;
145 pub const NUMERATOR: u16 = 16;
147 pub const DENOMINATOR: u16 = 17;
149 pub const LIMITS: u16 = 18;
151 pub const FRACTION: u16 = 19;
153 pub const NUCLEUS: u16 = 20;
155 pub const SUP: u16 = 21;
157 pub const SUB: u16 = 22;
159 pub const DEGREE: u16 = 23;
161 pub const SCRIPTS: u16 = 24;
163 pub const OVER: u16 = 25;
165 pub const UNDER: u16 = 26;
167 pub const ACCENT: u16 = 27;
169 pub const RADICAL: u16 = 28;
171}
172
173#[allow(missing_docs)]
175pub mod kern_sub {
176 pub const FONT: u16 = 0;
177 pub const USER: u16 = 1;
178 pub const ACCENT: u16 = 2;
179 pub const ITALIC: u16 = 3;
180}
181
182#[allow(missing_docs)]
184pub mod glyph_sub {
185 pub const CHARACTER: u16 = 1;
186 pub const LIGATURE: u16 = 2;
187 pub const GHOST: u16 = 4;
188 pub const LEFT: u16 = 8;
189 pub const RIGHT: u16 = 16;
190}
191
192#[allow(missing_docs)]
194pub mod whatsit_sub {
195 pub const OPEN: u16 = 0;
196 pub const WRITE: u16 = 1;
197 pub const CLOSE: u16 = 2;
198 pub const SPECIAL: u16 = 3;
199 pub const LATE_SPECIAL: u16 = 4;
200 pub const SAVE_POS: u16 = 7;
201 pub const LATE_LUA: u16 = 8;
202 pub const USER_DEFINED: u16 = 9;
203 pub const PDF_LITERAL: u16 = 16;
204 pub const PDF_LATE_LITERAL: u16 = 17;
205 pub const PDF_REFOBJ: u16 = 18;
206 pub const PDF_ANNOT: u16 = 19;
207 pub const PDF_START_LINK: u16 = 20;
208 pub const PDF_END_LINK: u16 = 21;
209 pub const PDF_DEST: u16 = 22;
210 pub const PDF_ACTION: u16 = 23;
211 pub const PDF_THREAD: u16 = 24;
212 pub const PDF_START_THREAD: u16 = 25;
213 pub const PDF_END_THREAD: u16 = 26;
214 pub const PDF_COLORSTACK: u16 = 29;
215 pub const PDF_SETMATRIX: u16 = 30;
216 pub const PDF_SAVE: u16 = 31;
217 pub const PDF_RESTORE: u16 = 32;
218 pub const PDF_LINK_STATE: u16 = 33;
219}
220
221pub type AttrList = Rc<[(u32, i32)]>;
223
224#[derive(Clone, Debug, Default, PartialEq)]
226pub struct BoxData {
227 pub width: i32,
229 pub depth: i32,
231 pub height: i32,
233 pub dir: i8,
235 pub shift: i32,
237 pub glue_order: u8,
239 pub glue_sign: u8,
241 pub glue_set: f64,
244 pub head: NodeRef,
246}
247
248#[derive(Clone, Debug, Default, PartialEq)]
250pub struct GlyphData {
251 pub chr: u32,
253 pub font: u32,
255 pub lang: u16,
257 pub left: u8,
259 pub right: u8,
261 pub uchyph: bool,
263 pub components: NodeRef,
265 pub xoffset: i32,
267 pub yoffset: i32,
269 pub expansion_factor: i32,
271 pub data: i32,
273}
274
275#[derive(Clone, Debug, PartialEq)]
277pub enum NodeData {
278 Temp,
280 Box(Box<BoxData>),
282 Rule {
284 width: i32,
286 depth: i32,
288 height: i32,
290 dir: i8,
292 index: i32,
294 left: i32,
296 right: i32,
298 },
299 Ins {
301 cost: i32,
303 depth: i32,
305 height: i32,
307 spec: Glue,
309 head: NodeRef,
311 },
312 Mark {
314 class: u32,
316 mark: TokenList,
318 },
319 Adjust {
321 head: NodeRef,
323 },
324 Boundary {
326 value: i32,
328 },
329 Disc {
331 pre: NodeRef,
333 post: NodeRef,
335 replace: NodeRef,
337 penalty: i32,
339 },
340 Whatsit(Box<Whatsit>),
342 LocalPar {
344 pen_inter: i32,
346 pen_broken: i32,
348 dir: i8,
350 box_left: NodeRef,
352 box_left_width: i32,
354 box_right: NodeRef,
356 box_right_width: i32,
358 },
359 Dir {
361 dir: i8,
363 level: i32,
365 },
366 Math {
368 surround: i32,
370 glue: Glue,
372 },
373 Glue {
375 spec: Glue,
377 leader: NodeRef,
379 },
380 Kern {
382 kern: i32,
384 expansion_factor: i32,
386 },
387 Penalty {
389 penalty: i32,
391 },
392 Unset {
394 b: Box<BoxData>,
396 span_count: u16,
398 stretch: i32,
400 shrink: i32,
402 stretch_order: u8,
404 shrink_order: u8,
406 },
407 Glyph(GlyphData),
409 MarginKern {
411 width: i32,
413 glyph: NodeRef,
415 },
416 Noad(Box<NoadData>),
418 Fraction(Box<FractionData>),
420 Fence(Box<FenceData>),
422 Style {
424 style: u8,
426 },
427 Choice(Box<[NodeRef; 4]>),
429 MathChar {
431 fam: u32,
433 chr: u32,
435 },
436 SubList {
438 head: NodeRef,
440 },
441 Delim {
443 small_fam: u32,
445 small_char: u32,
447 large_fam: u32,
449 large_char: u32,
451 },
452 Other(Vec<i64>),
454}
455
456#[derive(Clone, Debug, Default, PartialEq)]
460pub struct NoadData {
461 pub nucleus: NodeRef,
463 pub sub: NodeRef,
465 pub sup: NodeRef,
467 pub options: u32,
469 pub left: NodeRef,
471 pub degree: NodeRef,
473 pub width: i32,
475 pub accent: NodeRef,
477 pub bot_accent: NodeRef,
479 pub fraction: i32,
481 pub new_hlist: NodeRef,
484}
485
486#[derive(Clone, Debug, PartialEq)]
488pub struct FractionData {
489 pub thickness: i32,
491 pub num: NodeRef,
493 pub denom: NodeRef,
495 pub left: NodeRef,
497 pub right: NodeRef,
499 pub middle: NodeRef,
501 pub options: u32,
503 pub new_hlist: NodeRef,
505}
506
507#[derive(Clone, Debug, Default, PartialEq)]
509pub struct FenceData {
510 pub delim: NodeRef,
512 pub italic: i32,
514 pub height: i32,
516 pub depth: i32,
518 pub options: u32,
520 pub class: i32,
522 pub new_hlist: NodeRef,
524}
525
526pub const DEFAULT_CODE: i32 = 0o10000000000;
529
530#[allow(missing_docs)]
532pub mod noad_sub {
533 pub const ORD: u16 = 0;
534 pub const OP_DISPLAY_LIMITS: u16 = 1;
535 pub const OP_LIMITS: u16 = 2;
536 pub const OP_NO_LIMITS: u16 = 3;
537 pub const BIN: u16 = 4;
538 pub const REL: u16 = 5;
539 pub const OPEN: u16 = 6;
540 pub const CLOSE: u16 = 7;
541 pub const PUNCT: u16 = 8;
542 pub const INNER: u16 = 9;
543 pub const UNDER: u16 = 10;
544 pub const OVER: u16 = 11;
545 pub const VCENTER: u16 = 12;
546}
547
548#[allow(missing_docs)]
550pub mod radical_sub {
551 pub const RADICAL: u16 = 0;
552 pub const URADICAL: u16 = 1;
553 pub const UROOT: u16 = 2;
554 pub const UUNDERDELIMITER: u16 = 3;
555 pub const UOVERDELIMITER: u16 = 4;
556 pub const UDELIMITERUNDER: u16 = 5;
557 pub const UDELIMITEROVER: u16 = 6;
558 pub const UHEXTENSIBLE: u16 = 7;
559}
560
561#[allow(missing_docs)]
563pub mod fence_sub {
564 pub const UNSET: u16 = 0;
565 pub const LEFT: u16 = 1;
566 pub const MIDDLE: u16 = 2;
567 pub const RIGHT: u16 = 3;
568 pub const NO: u16 = 4;
569}
570
571#[allow(missing_docs)]
573pub mod accent_sub {
574 pub const BOTH_FLEXIBLE: u16 = 0;
575 pub const FIXED_TOP: u16 = 1;
576 pub const FIXED_BOTTOM: u16 = 2;
577 pub const FIXED_BOTH: u16 = 3;
578}
579
580#[allow(missing_docs)]
582pub mod noad_opt {
583 pub const SET: u32 = 0x08;
584 pub const AXIS: u32 = 0x02 | SET;
585 pub const NO_AXIS: u32 = 0x04 | SET;
586 pub const EXACT: u32 = 0x10 | SET;
587 pub const LEFT: u32 = 0x11 | SET;
588 pub const MIDDLE: u32 = 0x12 | SET;
589 pub const RIGHT: u32 = 0x14 | SET;
590 pub const NO_SUB_SCRIPT: u32 = 0x21 | SET;
591 pub const NO_SUPER_SCRIPT: u32 = 0x22 | SET;
592 pub const OVERLAY: u32 = 0x100;
594}
595
596#[derive(Clone, Debug, PartialEq)]
598pub enum Whatsit {
599 Open {
601 stream: u32,
603 name: Vec<u8>,
605 },
606 Write {
608 stream: i32,
610 data: TokenList,
612 },
613 Close {
615 stream: u32,
617 },
618 Special {
620 data: Vec<u8>,
622 },
623 LateLua {
625 data: LateData,
627 name: Vec<u8>,
629 },
630 PdfLiteral {
632 mode: u8,
634 data: LateData,
636 late: bool,
638 },
639 SavePos,
641 PdfColorstack {
643 stack: i32,
645 cmd: u8,
647 data: Vec<u8>,
649 },
650 PdfSetmatrix {
652 data: Vec<u8>,
654 },
655 PdfSave,
657 PdfRestore,
659 PdfAnnot {
661 dims: [i32; 3],
663 objnum: i32,
665 data: Vec<u8>,
667 },
668 PdfStartLink {
670 dims: [i32; 3],
672 objnum: i32,
674 attr: Vec<u8>,
676 action: crate::pdfext::PdfAction,
678 },
679 PdfEndLink,
681 PdfDest {
683 id: crate::pdfext::DestId,
685 view: crate::pdfext::DestView,
687 structure: Option<i32>,
690 },
691 PdfRefobj {
693 objnum: i32,
695 },
696 PdfLinkState {
698 state: i32,
700 },
701 UserDefined {
703 user_id: i32,
705 value: UserValue,
707 },
708 Other {
710 fields: Vec<i64>,
712 data: Vec<u8>,
714 },
715}
716
717#[derive(Clone, Debug, PartialEq)]
719pub enum LateData {
720 Tokens(TokenList),
722 Bytes(Vec<u8>),
724 Lua {
727 data: Vec<u8>,
729 reference: i32,
731 },
732}
733
734impl LateData {
735 pub fn bytes(&self) -> Option<&[u8]> {
737 match self {
738 LateData::Bytes(b) | LateData::Lua { data: b, .. } => Some(b),
739 LateData::Tokens(_) => None,
740 }
741 }
742}
743
744#[derive(Clone, Debug, PartialEq)]
747pub enum UserValue {
748 Int(i32),
750 Str(Vec<u8>),
752 Tokens(TokenList),
754 Nodes(NodeRef),
756 Lua(i32),
758 Attr,
760}
761
762#[derive(Clone, Debug, PartialEq)]
764pub struct Node {
765 pub id: u8,
767 pub subtype: u16,
769 pub next: NodeRef,
771 pub prev: NodeRef,
773 pub attr: Option<AttrList>,
775 pub data: NodeData,
777}
778
779impl Node {
780 fn temp() -> Node {
782 Node {
783 id: id::TEMP,
784 subtype: 0,
785 next: NodeRef::NULL,
786 prev: NodeRef::NULL,
787 attr: None,
788 data: NodeData::Temp,
789 }
790 }
791}
792
793#[derive(Debug, Clone, Copy, PartialEq, Eq)]
796pub enum PropEvent {
797 Flush(u32),
799 Copy(u32, u32),
801}
802
803#[derive(Debug, Clone, Default)]
807pub struct Properties {
808 pub nodes: std::collections::HashSet<u32>,
810 pub flush: bool,
812 pub copy: bool,
814 pub events: Vec<PropEvent>,
816}
817
818#[derive(Debug, Clone)]
820pub struct Nodes {
821 nodes: Vec<Node>,
822 copy_depth: u32,
824 sink: Node,
827 free: Vec<u32>,
828 pub in_use: usize,
830 pub props: Properties,
832 pub sync: Option<Box<SyncFields>>,
835 pub double_free: Option<(u8, u32)>,
839 pub par_temp: NodeRef,
842 pub lua_refs: LuaRefs,
844}
845
846#[derive(Debug, Clone, Default)]
853pub struct LuaRefs {
854 pub next: i32,
856 pub free: Vec<i32>,
858 pub copies: Vec<(i32, i32)>,
861}
862
863impl LuaRefs {
864 pub fn take(&mut self) -> i32 {
866 if let Some(r) = self.free.pop() {
867 return r;
868 }
869 if self.next == 0 {
870 self.next = 780;
871 }
872 let r = self.next;
873 self.next += 1;
874 r
875 }
876
877 pub fn release(&mut self, r: i32) {
879 if r > 0 {
880 self.free.push(r);
881 }
882 }
883
884 pub fn font_defined(&mut self, temporary: bool) {
887 if temporary {
888 let t = self.take();
889 self.take();
890 self.release(t);
891 } else {
892 self.take();
893 }
894 }
895}
896
897fn lua_ref_mut(data: &mut NodeData) -> Option<&mut i32> {
899 match data {
900 NodeData::Whatsit(w) => match &mut **w {
901 Whatsit::LateLua {
902 data: LateData::Lua { reference, .. },
903 ..
904 }
905 | Whatsit::PdfLiteral {
906 data: LateData::Lua { reference, .. },
907 ..
908 } => Some(reference),
909 Whatsit::UserDefined {
910 value: UserValue::Lua(r),
911 ..
912 } if *r > 0 => Some(r),
913 _ => None,
914 },
915 _ => None,
916 }
917}
918
919#[derive(Debug, Clone, Default)]
927pub struct SyncFields {
928 pub cur: (u32, i32),
930 fields: Vec<(u32, i32)>,
931}
932
933impl SyncFields {
934 #[inline]
935 fn set(&mut self, i: u32, f: (u32, i32)) {
936 let i = i as usize;
937 if i >= self.fields.len() {
938 self.fields.resize(i + 1, (0, 0));
939 }
940 self.fields[i] = f;
941 }
942}
943
944impl Default for Nodes {
945 fn default() -> Self {
946 Self::new()
947 }
948}
949
950impl Nodes {
951 pub fn new() -> Self {
953 Nodes {
954 nodes: vec![Node::temp()],
955 copy_depth: 0,
956 sink: Node::temp(),
957 free: Vec::new(),
958 in_use: 0,
959 props: Properties::default(),
960 sync: None,
961 lua_refs: LuaRefs::default(),
962 double_free: None,
963 par_temp: NodeRef::NULL,
964 }
965 }
966
967 pub fn enable_sync(&mut self) {
969 if self.sync.is_none() {
970 self.sync = Some(Box::default());
971 }
972 }
973
974 #[inline]
976 pub fn sync_fields(&self, p: NodeRef) -> (u32, i32) {
977 self.sync
978 .as_ref()
979 .and_then(|s| s.fields.get(p.0 as usize).copied())
980 .unwrap_or((0, 0))
981 }
982
983 pub fn set_sync_fields(&mut self, p: NodeRef, f: (u32, i32)) {
985 if p.0 as usize >= self.nodes.len() {
986 return;
987 }
988 if let Some(s) = self.sync.as_deref_mut() {
989 s.set(p.0, f);
990 }
991 }
992
993 pub fn sync_as_copied(&mut self, p: NodeRef) {
997 if let Some(s) = self.sync.as_deref_mut() {
998 let cur = s.cur;
999 s.set(p.0, cur);
1000 }
1001 }
1002
1003 #[inline]
1005 fn at(&self, p: NodeRef) -> &Node {
1006 self.nodes.get(p.0 as usize).unwrap_or(&self.nodes[0])
1007 }
1008
1009 #[inline]
1012 fn at_mut(&mut self, p: NodeRef) -> &mut Node {
1013 match self.nodes.get_mut(p.0 as usize) {
1014 Some(n) => n,
1015 None => {
1016 self.sink = Node::temp();
1017 &mut self.sink
1018 }
1019 }
1020 }
1021
1022 pub fn capacity(&self) -> usize {
1024 self.nodes.len()
1025 }
1026
1027 pub fn alloc(&mut self, id: u8, subtype: u16, data: NodeData) -> NodeRef {
1029 let node = Node {
1030 id,
1031 subtype,
1032 next: NodeRef::NULL,
1033 prev: NodeRef::NULL,
1034 attr: None,
1035 data,
1036 };
1037 self.in_use += 1;
1038 let p = if let Some(i) = self.free.pop() {
1039 self.nodes[i as usize] = node;
1040 NodeRef(i)
1041 } else {
1042 self.nodes.push(node);
1043 NodeRef(self.nodes.len() as u32 - 1)
1044 };
1045 if let Some(s) = self.sync.as_deref_mut() {
1046 let f = if id == id::KERN || id == id::GLYPH {
1047 (0, 0)
1048 } else {
1049 s.cur
1050 };
1051 s.set(p.0, f);
1052 }
1053 p
1054 }
1055
1056 pub fn free(&mut self, p: NodeRef) {
1058 if p.is_null() || p.0 as usize >= self.nodes.len() {
1061 return;
1062 }
1063 if self.is_free(p) {
1064 if self.double_free.is_none() {
1065 self.double_free = Some((self.at(p).subtype as u8, p.0));
1066 }
1067 return;
1068 }
1069 let t = self.at(p).id;
1071 self.at_mut(p).subtype = u16::from(t);
1072 if let Some(r) = lua_ref_mut(&mut self.at_mut(p).data) {
1073 let r = *r;
1074 self.lua_refs.release(r);
1075 }
1076 self.at_mut(p).id = id::FREE;
1077 self.at_mut(p).data = NodeData::Temp;
1078 self.at_mut(p).attr = None;
1079 self.free.push(p.0);
1080 self.in_use -= 1;
1081 if !self.props.nodes.is_empty() && self.props.nodes.remove(&p.0) && self.props.flush {
1082 self.props.events.push(PropEvent::Flush(p.0));
1083 }
1084 }
1085
1086 pub fn lua_ref_of(&mut self, p: NodeRef) -> Option<i32> {
1088 lua_ref_mut(&mut self.at_mut(p).data).map(|r| *r)
1089 }
1090
1091 #[inline]
1093 pub fn is_free(&self, p: NodeRef) -> bool {
1094 self.at(p).id == id::FREE
1095 }
1096
1097 #[inline]
1099 pub fn get(&self, p: NodeRef) -> &Node {
1100 self.at(p)
1101 }
1102
1103 #[inline]
1105 pub fn get_mut(&mut self, p: NodeRef) -> &mut Node {
1106 self.at_mut(p)
1107 }
1108
1109 #[inline]
1111 pub fn id(&self, p: NodeRef) -> u8 {
1112 self.at(p).id
1113 }
1114
1115 #[inline]
1117 pub fn next(&self, p: NodeRef) -> NodeRef {
1118 self.at(p).next
1119 }
1120
1121 #[inline]
1123 pub fn link(&mut self, p: NodeRef, q: NodeRef) {
1124 self.at_mut(p).next = q;
1125 if !q.is_null() {
1126 self.at_mut(q).prev = p;
1127 }
1128 }
1129
1130 pub fn box_data(&self, p: NodeRef) -> Option<&BoxData> {
1132 match &self.at(p).data {
1133 NodeData::Box(b) => Some(b),
1134 NodeData::Unset { b, .. } => Some(b),
1135 _ => None,
1136 }
1137 }
1138
1139 pub fn box_data_mut(&mut self, p: NodeRef) -> Option<&mut BoxData> {
1141 match &mut self.at_mut(p).data {
1142 NodeData::Box(b) => Some(b),
1143 NodeData::Unset { b, .. } => Some(b),
1144 _ => None,
1145 }
1146 }
1147
1148 pub fn tail_of(&self, mut p: NodeRef) -> NodeRef {
1150 if p.is_null() {
1151 return p;
1152 }
1153 loop {
1154 let n = self.next(p);
1155 if n.is_null() {
1156 return p;
1157 }
1158 p = n;
1159 }
1160 }
1161
1162 pub fn bounded_tail(&self, mut p: NodeRef) -> Option<NodeRef> {
1165 if p.is_null() {
1166 return Some(p);
1167 }
1168 for _ in 0..self.nodes.len() {
1169 let n = self.next(p);
1170 if n.is_null() {
1171 return Some(p);
1172 }
1173 p = n;
1174 }
1175 None
1176 }
1177
1178 pub fn flush_list(&mut self, p: NodeRef) {
1180 let mut stack: Vec<NodeRef> = Vec::new();
1181 let mut p = p;
1182 loop {
1183 while !p.is_null() {
1184 if self.is_free(p) {
1185 self.free(p);
1188 break;
1189 }
1190 let next = self.next(p);
1191 match &self.at(p).data {
1192 NodeData::Box(b) => stack.push(b.head),
1193 NodeData::Unset { b, .. } => stack.push(b.head),
1194 NodeData::Ins { head, .. } | NodeData::Adjust { head } => stack.push(*head),
1195 NodeData::Disc {
1196 pre, post, replace, ..
1197 } => {
1198 stack.push(*pre);
1199 stack.push(*post);
1200 stack.push(*replace);
1201 }
1202 NodeData::Glue { leader, .. } => stack.push(*leader),
1203 NodeData::Glyph(g) => {
1204 if !g.components.is_null() {
1205 stack.push(g.components);
1206 }
1207 }
1208 NodeData::LocalPar {
1209 box_left,
1210 box_right,
1211 ..
1212 } => {
1213 stack.push(*box_left);
1214 stack.push(*box_right);
1215 }
1216 NodeData::Noad(n) => stack.extend([
1217 n.nucleus,
1218 n.sub,
1219 n.sup,
1220 n.left,
1221 n.degree,
1222 n.accent,
1223 n.bot_accent,
1224 n.new_hlist,
1225 ]),
1226 NodeData::Fraction(f) => {
1227 stack.extend([f.num, f.denom, f.left, f.right, f.middle, f.new_hlist])
1228 }
1229 NodeData::Fence(f) => stack.extend([f.delim, f.new_hlist]),
1230 NodeData::Choice(c) => stack.extend(c.iter().copied()),
1231 NodeData::SubList { head } => stack.push(*head),
1232 _ => {}
1233 }
1234 self.free(p);
1235 p = next;
1236 }
1237 match stack.pop() {
1238 Some(q) => p = q,
1239 None => return,
1240 }
1241 }
1242 }
1243
1244 pub fn copy_list(&mut self, mut p: NodeRef) -> NodeRef {
1246 let mut head = NodeRef::NULL;
1247 let mut tail = NodeRef::NULL;
1248 if self.copy_depth >= MAX_NESTING {
1251 return head;
1252 }
1253 self.copy_depth += 1;
1254 let mut left = self.nodes.len();
1257 while !p.is_null() && left > 0 {
1258 left -= 1;
1259 let q = self.copy_node(p);
1260 if head.is_null() {
1261 head = q;
1262 } else {
1263 self.link(tail, q);
1264 }
1265 tail = q;
1266 p = self.next(p);
1267 }
1268 self.copy_depth -= 1;
1269 head
1270 }
1271
1272 pub fn copy_node(&mut self, p: NodeRef) -> NodeRef {
1274 let mut node = self.at(p).clone();
1275 node.next = NodeRef::NULL;
1276 node.prev = NodeRef::NULL;
1277 match &mut node.data {
1278 NodeData::Box(b) => b.head = self.copy_list(b.head),
1279 NodeData::Unset { b, .. } => b.head = self.copy_list(b.head),
1280 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head = self.copy_list(*head),
1281 NodeData::Disc {
1282 pre, post, replace, ..
1283 } => {
1284 *pre = self.copy_list(*pre);
1285 *post = self.copy_list(*post);
1286 *replace = self.copy_list(*replace);
1287 }
1288 NodeData::Glue { leader, .. } => *leader = self.copy_list(*leader),
1289 NodeData::Glyph(g) => g.components = self.copy_list(g.components),
1290 NodeData::LocalPar {
1291 box_left,
1292 box_right,
1293 ..
1294 } => {
1295 *box_left = self.copy_list(*box_left);
1296 *box_right = self.copy_list(*box_right);
1297 }
1298 NodeData::Noad(n) => {
1299 for f in [
1300 &mut n.nucleus,
1301 &mut n.sub,
1302 &mut n.sup,
1303 &mut n.left,
1304 &mut n.degree,
1305 &mut n.accent,
1306 &mut n.bot_accent,
1307 &mut n.new_hlist,
1308 ] {
1309 *f = self.copy_list(*f);
1310 }
1311 }
1312 NodeData::Fraction(fr) => {
1313 for f in [
1314 &mut fr.num,
1315 &mut fr.denom,
1316 &mut fr.left,
1317 &mut fr.right,
1318 &mut fr.middle,
1319 &mut fr.new_hlist,
1320 ] {
1321 *f = self.copy_list(*f);
1322 }
1323 }
1324 NodeData::Fence(fe) => {
1325 fe.delim = self.copy_list(fe.delim);
1326 fe.new_hlist = self.copy_list(fe.new_hlist);
1327 }
1328 NodeData::Choice(c) => {
1329 for f in c.iter_mut() {
1330 *f = self.copy_list(*f);
1331 }
1332 }
1333 NodeData::SubList { head } => *head = self.copy_list(*head),
1334 _ => {}
1335 }
1336 if let Some(r) = lua_ref_mut(&mut node.data) {
1337 let old = *r;
1338 let new = self.lua_refs.take();
1339 *r = new;
1340 self.lua_refs.copies.push((new, old));
1341 }
1342 self.in_use += 1;
1343 let q = if let Some(i) = self.free.pop() {
1344 self.nodes[i as usize] = node;
1345 NodeRef(i)
1346 } else {
1347 self.nodes.push(node);
1348 NodeRef(self.nodes.len() as u32 - 1)
1349 };
1350 if self.props.copy && self.props.nodes.contains(&p.0) {
1351 self.props.nodes.insert(q.0);
1352 self.props.events.push(PropEvent::Copy(p.0, q.0));
1353 }
1354 if self.sync.is_some() {
1355 let id = self.at(q).id;
1356 let f = if id == id::KERN || id == id::MATH {
1357 self.sync.as_ref().map_or((0, 0), |s| s.cur)
1358 } else {
1359 self.sync_fields(p)
1360 };
1361 self.set_sync_fields(q, f);
1362 }
1363 q
1364 }
1365
1366 pub fn new_null_box(&mut self, hlist: bool) -> NodeRef {
1368 self.alloc(
1369 if hlist { id::HLIST } else { id::VLIST },
1370 0,
1371 NodeData::Box(Box::default()),
1372 )
1373 }
1374
1375 pub fn new_glue(&mut self, spec: Glue, subtype: u16) -> NodeRef {
1377 self.alloc(
1378 id::GLUE,
1379 subtype,
1380 NodeData::Glue {
1381 spec,
1382 leader: NodeRef::NULL,
1383 },
1384 )
1385 }
1386
1387 pub fn new_kern(&mut self, w: i32, subtype: u16) -> NodeRef {
1389 self.alloc(
1390 id::KERN,
1391 subtype,
1392 NodeData::Kern {
1393 kern: w,
1394 expansion_factor: 0,
1395 },
1396 )
1397 }
1398
1399 pub fn new_penalty(&mut self, m: i32, subtype: u16) -> NodeRef {
1401 self.alloc(id::PENALTY, subtype, NodeData::Penalty { penalty: m })
1402 }
1403
1404 pub fn new_temp(&mut self) -> NodeRef {
1406 self.alloc(id::TEMP, 0, NodeData::Temp)
1407 }
1408
1409 pub fn new_glyph(&mut self, font: u32, chr: u32) -> NodeRef {
1411 self.alloc(
1412 id::GLYPH,
1413 0,
1414 NodeData::Glyph(GlyphData {
1415 chr,
1416 font,
1417 ..GlyphData::default()
1418 }),
1419 )
1420 }
1421
1422 pub fn new_rule(&mut self, width: i32, height: i32, depth: i32) -> NodeRef {
1424 self.alloc(
1425 id::RULE,
1426 0,
1427 NodeData::Rule {
1428 width,
1429 depth,
1430 height,
1431 dir: 0,
1432 index: 0,
1433 left: 0,
1434 right: 0,
1435 },
1436 )
1437 }
1438
1439 pub fn new_disc(&mut self, subtype: u16, penalty: i32) -> NodeRef {
1441 self.alloc(
1442 id::DISC,
1443 subtype,
1444 NodeData::Disc {
1445 pre: NodeRef::NULL,
1446 post: NodeRef::NULL,
1447 replace: NodeRef::NULL,
1448 penalty,
1449 },
1450 )
1451 }
1452
1453 pub fn new_math(&mut self, surround: i32, subtype: u16) -> NodeRef {
1455 self.alloc(
1456 id::MATH,
1457 subtype,
1458 NodeData::Math {
1459 surround,
1460 glue: Glue::ZERO,
1461 },
1462 )
1463 }
1464
1465 #[inline]
1467 pub fn data(&self, p: NodeRef) -> &NodeData {
1468 &self.at(p).data
1469 }
1470
1471 #[inline]
1473 pub fn data_mut(&mut self, p: NodeRef) -> &mut NodeData {
1474 &mut self.at_mut(p).data
1475 }
1476
1477 #[inline]
1479 pub fn subtype(&self, p: NodeRef) -> u16 {
1480 self.at(p).subtype
1481 }
1482
1483 #[inline]
1485 pub fn set_subtype(&mut self, p: NodeRef, s: u16) {
1486 self.at_mut(p).subtype = s;
1487 }
1488
1489 #[inline]
1491 pub fn prev(&self, p: NodeRef) -> NodeRef {
1492 self.at(p).prev
1493 }
1494
1495 #[inline]
1497 pub fn set_next(&mut self, p: NodeRef, q: NodeRef) {
1498 self.at_mut(p).next = q;
1499 }
1500
1501 #[inline]
1503 pub fn set_prev(&mut self, p: NodeRef, q: NodeRef) {
1504 self.at_mut(p).prev = q;
1505 }
1506
1507 #[inline]
1509 pub fn is_glyph(&self, p: NodeRef) -> bool {
1510 self.at(p).id == id::GLYPH
1511 }
1512
1513 #[inline]
1515 pub fn glyph(&self, p: NodeRef) -> Option<&GlyphData> {
1516 match &self.at(p).data {
1517 NodeData::Glyph(g) => Some(g),
1518 _ => None,
1519 }
1520 }
1521
1522 #[inline]
1524 pub fn glyph_mut(&mut self, p: NodeRef) -> Option<&mut GlyphData> {
1525 match &mut self.at_mut(p).data {
1526 NodeData::Glyph(g) => Some(g),
1527 _ => None,
1528 }
1529 }
1530
1531 #[inline]
1533 pub fn glue_spec(&self, p: NodeRef) -> Glue {
1534 match &self.at(p).data {
1535 NodeData::Glue { spec, .. } => *spec,
1536 NodeData::Math { glue, .. } => *glue,
1537 _ => Glue::ZERO,
1538 }
1539 }
1540
1541 pub fn width(&self, p: NodeRef) -> i32 {
1545 match &self.at(p).data {
1546 NodeData::Box(b) => b.width,
1547 NodeData::Unset { b, .. } => b.width,
1548 NodeData::Rule { width, .. } => *width,
1549 NodeData::Glue { spec, .. } => spec.width,
1550 NodeData::Kern {
1551 kern,
1552 expansion_factor,
1553 } => *kern + *expansion_factor,
1554 NodeData::Math { surround, glue } => {
1555 if glue.width != 0 || glue.stretch != 0 || glue.shrink != 0 {
1556 glue.width
1557 } else {
1558 *surround
1559 }
1560 }
1561 NodeData::MarginKern { width, .. } => *width,
1562 _ => 0,
1563 }
1564 }
1565
1566 pub fn penalty(&self, p: NodeRef) -> i32 {
1568 match &self.at(p).data {
1569 NodeData::Penalty { penalty } => *penalty,
1570 NodeData::Disc { penalty, .. } => *penalty,
1571 _ => 0,
1572 }
1573 }
1574
1575 pub fn disc_lists(&self, p: NodeRef) -> (NodeRef, NodeRef, NodeRef) {
1577 match &self.at(p).data {
1578 NodeData::Disc {
1579 pre, post, replace, ..
1580 } => (*pre, *post, *replace),
1581 _ => (NodeRef::NULL, NodeRef::NULL, NodeRef::NULL),
1582 }
1583 }
1584
1585 pub fn set_disc_lists(&mut self, p: NodeRef, l: (NodeRef, NodeRef, NodeRef)) {
1587 if let NodeData::Disc {
1588 pre, post, replace, ..
1589 } = &mut self.at_mut(p).data
1590 {
1591 *pre = l.0;
1592 *post = l.1;
1593 *replace = l.2;
1594 }
1595 for q in [l.0, l.1, l.2] {
1596 if !q.is_null() {
1597 self.at_mut(q).prev = NodeRef::NULL;
1598 }
1599 }
1600 }
1601
1602 pub fn list_ptr(&self, p: NodeRef) -> NodeRef {
1604 match &self.at(p).data {
1605 NodeData::Box(b) => b.head,
1606 NodeData::Unset { b, .. } => b.head,
1607 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head,
1608 _ => NodeRef::NULL,
1609 }
1610 }
1611
1612 pub fn set_list_ptr(&mut self, p: NodeRef, l: NodeRef) {
1614 match &mut self.at_mut(p).data {
1615 NodeData::Box(b) => b.head = l,
1616 NodeData::Unset { b, .. } => b.head = l,
1617 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head = l,
1618 _ => {}
1619 }
1620 }
1621
1622 #[inline]
1624 pub fn attr(&self, p: NodeRef) -> Option<&AttrList> {
1625 self.at(p).attr.as_ref()
1626 }
1627
1628 #[inline]
1630 pub fn set_attr(&mut self, p: NodeRef, a: Option<AttrList>) {
1631 self.at_mut(p).attr = a;
1632 }
1633
1634 #[inline]
1636 pub fn noad(&self, p: NodeRef) -> Option<&NoadData> {
1637 match &self.at(p).data {
1638 NodeData::Noad(n) => Some(n),
1639 _ => None,
1640 }
1641 }
1642
1643 #[inline]
1645 pub fn noad_mut(&mut self, p: NodeRef) -> Option<&mut NoadData> {
1646 match &mut self.at_mut(p).data {
1647 NodeData::Noad(n) => Some(n),
1648 _ => None,
1649 }
1650 }
1651
1652 pub fn list_ptr_kernel(&self, p: NodeRef) -> NodeRef {
1654 if p.is_null() {
1655 return NodeRef::NULL;
1656 }
1657 match &self.at(p).data {
1658 NodeData::SubList { head } => *head,
1659 _ => NodeRef::NULL,
1660 }
1661 }
1662
1663 pub fn set_kernel_list(&mut self, p: NodeRef, l: NodeRef) {
1665 if p.is_null() {
1666 return;
1667 }
1668 if let NodeData::SubList { head } = &mut self.at_mut(p).data {
1669 *head = l;
1670 }
1671 }
1672
1673 pub fn scripts_allowed(&self, p: NodeRef) -> bool {
1675 matches!(self.at(p).data, NodeData::Noad(_))
1676 && matches!(self.id(p), id::NOAD | id::RADICAL | id::ACCENT)
1677 }
1678
1679 pub fn list_len(&self, mut p: NodeRef) -> usize {
1681 let mut n = 0;
1682 while !p.is_null() {
1683 n += 1;
1684 p = self.next(p);
1685 }
1686 n
1687 }
1688}
1689
1690pub fn glue_ratio(num: i32, den: i32) -> f64 {
1695 f64::from((f64::from(num) / f64::from(den)) as f32)
1696}
1697
1698#[cfg(test)]
1699mod tests {
1700 use super::*;
1701
1702 #[test]
1703 fn glue_ratio_is_single_precision() {
1704 assert_eq!(glue_ratio(1021537, 873808), 1.1690634489059448);
1706 }
1707
1708 #[test]
1709 fn alloc_link_copy_flush() {
1710 let mut n = Nodes::new();
1711 let b = n.new_null_box(true);
1712 let k = n.new_kern(5, kern_sub::USER);
1713 let g = n.new_glue(Glue::fixed(7), glue_sub::USER);
1714 n.link(k, g);
1715 n.box_data_mut(b).unwrap().head = k;
1716 assert_eq!(n.in_use, 3);
1717 let c = n.copy_node(b);
1718 assert_eq!(n.in_use, 6);
1719 let ch = n.box_data(c).unwrap().head;
1720 assert_ne!(ch, k);
1721 assert_eq!(n.get(n.next(ch)).data, n.get(g).data);
1722 n.flush_list(c);
1723 n.flush_list(b);
1724 assert_eq!(n.in_use, 0);
1725 }
1726
1727 #[test]
1730 fn circular_list() {
1731 let mut n = Nodes::new();
1732 let a = n.new_kern(1, kern_sub::USER);
1733 let b = n.new_glue(Glue::fixed(2), glue_sub::USER);
1734 n.link(a, b);
1735 n.link(b, a);
1736 assert_eq!(n.bounded_tail(a), None);
1737 let c = n.copy_list(a);
1738 assert!(!c.is_null());
1739 assert_eq!(n.double_free, None);
1740 n.flush_list(a);
1741 assert_eq!(n.double_free, Some((id::KERN, a.0)));
1742 assert_eq!(type_name(id::KERN), "kern");
1743 }
1744}