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
18#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, PartialOrd, Ord)]
21pub struct NodeRef(pub u32);
22
23impl NodeRef {
24 pub const NULL: NodeRef = NodeRef(0);
26
27 #[inline]
29 pub const fn is_null(self) -> bool {
30 self.0 == 0
31 }
32}
33
34pub const RUNNING: i32 = -0o10000000000;
36
37#[allow(missing_docs)]
39pub mod id {
40 pub const HLIST: u8 = 0;
41 pub const VLIST: u8 = 1;
42 pub const RULE: u8 = 2;
43 pub const INS: u8 = 3;
44 pub const MARK: u8 = 4;
45 pub const ADJUST: u8 = 5;
46 pub const BOUNDARY: u8 = 6;
47 pub const DISC: u8 = 7;
48 pub const WHATSIT: u8 = 8;
49 pub const LOCAL_PAR: u8 = 9;
50 pub const DIR: u8 = 10;
51 pub const MATH: u8 = 11;
52 pub const GLUE: u8 = 12;
53 pub const KERN: u8 = 13;
54 pub const PENALTY: u8 = 14;
55 pub const UNSET: u8 = 15;
56 pub const STYLE: u8 = 16;
57 pub const CHOICE: u8 = 17;
58 pub const NOAD: u8 = 18;
59 pub const RADICAL: u8 = 19;
60 pub const FRACTION: u8 = 20;
61 pub const ACCENT: u8 = 21;
62 pub const FENCE: u8 = 22;
63 pub const MATH_CHAR: u8 = 23;
64 pub const SUB_BOX: u8 = 24;
65 pub const SUB_MLIST: u8 = 25;
66 pub const MATH_TEXT_CHAR: u8 = 26;
67 pub const DELIM: u8 = 27;
68 pub const MARGIN_KERN: u8 = 28;
69 pub const GLYPH: u8 = 29;
70 pub const ALIGN_RECORD: u8 = 30;
71 pub const PAGE_INSERT: u8 = 33;
72 pub const SPLIT_INSERT: u8 = 34;
73 pub const TEMP: u8 = 41;
74 pub const FREE: u8 = 255;
76}
77
78pub const MAX_NESTING: u32 = 50_000;
82
83#[allow(missing_docs)]
85pub mod glue_sub {
86 pub const USER: u16 = 0;
87 pub const LINE_SKIP: u16 = 1;
88 pub const BASELINE_SKIP: u16 = 2;
89 pub const PAR_SKIP: u16 = 3;
90 pub const ABOVE_DISPLAY: u16 = 4;
91 pub const BELOW_DISPLAY: u16 = 5;
92 pub const ABOVE_DISPLAY_SHORT: u16 = 6;
93 pub const BELOW_DISPLAY_SHORT: u16 = 7;
94 pub const LEFT_SKIP: u16 = 8;
95 pub const RIGHT_SKIP: u16 = 9;
96 pub const TOP_SKIP: u16 = 10;
97 pub const SPLIT_TOP_SKIP: u16 = 11;
98 pub const TAB_SKIP: u16 = 12;
99 pub const SPACE_SKIP: u16 = 13;
100 pub const XSPACE_SKIP: u16 = 14;
101 pub const PAR_FILL_SKIP: u16 = 15;
102 pub const MATH_SKIP: u16 = 16;
103 pub const THIN_MU_SKIP: u16 = 17;
104 pub const MED_MU_SKIP: u16 = 18;
105 pub const THICK_MU_SKIP: u16 = 19;
106 pub const COND_MATH_GLUE: u16 = 98;
107 pub const MU_GLUE: u16 = 99;
108 pub const A_LEADERS: u16 = 100;
109 pub const C_LEADERS: u16 = 101;
110 pub const X_LEADERS: u16 = 102;
111 pub const G_LEADERS: u16 = 103;
112}
113
114pub mod list_sub {
117 pub const MATH_CHAR: u16 = 9;
119 pub const H_EXTENSIBLE: u16 = 10;
121 pub const V_EXTENSIBLE: u16 = 11;
123 pub const V_DELIMITER: u16 = 13;
125 pub const OVER_DELIMITER: u16 = 14;
127 pub const UNDER_DELIMITER: u16 = 15;
129 pub const NUMERATOR: u16 = 16;
131 pub const DENOMINATOR: u16 = 17;
133 pub const LIMITS: u16 = 18;
135 pub const FRACTION: u16 = 19;
137 pub const NUCLEUS: u16 = 20;
139 pub const SUP: u16 = 21;
141 pub const SUB: u16 = 22;
143 pub const DEGREE: u16 = 23;
145 pub const SCRIPTS: u16 = 24;
147 pub const OVER: u16 = 25;
149 pub const UNDER: u16 = 26;
151 pub const ACCENT: u16 = 27;
153 pub const RADICAL: u16 = 28;
155}
156
157#[allow(missing_docs)]
159pub mod kern_sub {
160 pub const FONT: u16 = 0;
161 pub const USER: u16 = 1;
162 pub const ACCENT: u16 = 2;
163 pub const ITALIC: u16 = 3;
164}
165
166#[allow(missing_docs)]
168pub mod glyph_sub {
169 pub const CHARACTER: u16 = 1;
170 pub const LIGATURE: u16 = 2;
171 pub const GHOST: u16 = 4;
172 pub const LEFT: u16 = 8;
173 pub const RIGHT: u16 = 16;
174}
175
176#[allow(missing_docs)]
178pub mod whatsit_sub {
179 pub const OPEN: u16 = 0;
180 pub const WRITE: u16 = 1;
181 pub const CLOSE: u16 = 2;
182 pub const SPECIAL: u16 = 3;
183 pub const LATE_SPECIAL: u16 = 4;
184 pub const SAVE_POS: u16 = 7;
185 pub const LATE_LUA: u16 = 8;
186 pub const USER_DEFINED: u16 = 9;
187 pub const PDF_LITERAL: u16 = 16;
188 pub const PDF_LATE_LITERAL: u16 = 17;
189 pub const PDF_REFOBJ: u16 = 18;
190 pub const PDF_ANNOT: u16 = 19;
191 pub const PDF_START_LINK: u16 = 20;
192 pub const PDF_END_LINK: u16 = 21;
193 pub const PDF_DEST: u16 = 22;
194 pub const PDF_ACTION: u16 = 23;
195 pub const PDF_THREAD: u16 = 24;
196 pub const PDF_START_THREAD: u16 = 25;
197 pub const PDF_END_THREAD: u16 = 26;
198 pub const PDF_COLORSTACK: u16 = 29;
199 pub const PDF_SETMATRIX: u16 = 30;
200 pub const PDF_SAVE: u16 = 31;
201 pub const PDF_RESTORE: u16 = 32;
202 pub const PDF_LINK_STATE: u16 = 33;
203}
204
205pub type AttrList = Rc<[(u32, i32)]>;
207
208#[derive(Clone, Debug, Default, PartialEq)]
210pub struct BoxData {
211 pub width: i32,
213 pub depth: i32,
215 pub height: i32,
217 pub dir: i8,
219 pub shift: i32,
221 pub glue_order: u8,
223 pub glue_sign: u8,
225 pub glue_set: f64,
228 pub head: NodeRef,
230}
231
232#[derive(Clone, Debug, Default, PartialEq)]
234pub struct GlyphData {
235 pub chr: u32,
237 pub font: u32,
239 pub lang: u16,
241 pub left: u8,
243 pub right: u8,
245 pub uchyph: bool,
247 pub components: NodeRef,
249 pub xoffset: i32,
251 pub yoffset: i32,
253 pub expansion_factor: i32,
255 pub data: i32,
257}
258
259#[derive(Clone, Debug, PartialEq)]
261pub enum NodeData {
262 Temp,
264 Box(Box<BoxData>),
266 Rule {
268 width: i32,
270 depth: i32,
272 height: i32,
274 dir: i8,
276 index: i32,
278 left: i32,
280 right: i32,
282 },
283 Ins {
285 cost: i32,
287 depth: i32,
289 height: i32,
291 spec: Glue,
293 head: NodeRef,
295 },
296 Mark {
298 class: u32,
300 mark: TokenList,
302 },
303 Adjust {
305 head: NodeRef,
307 },
308 Boundary {
310 value: i32,
312 },
313 Disc {
315 pre: NodeRef,
317 post: NodeRef,
319 replace: NodeRef,
321 penalty: i32,
323 },
324 Whatsit(Box<Whatsit>),
326 LocalPar {
328 pen_inter: i32,
330 pen_broken: i32,
332 dir: i8,
334 box_left: NodeRef,
336 box_left_width: i32,
338 box_right: NodeRef,
340 box_right_width: i32,
342 },
343 Dir {
345 dir: i8,
347 level: i32,
349 },
350 Math {
352 surround: i32,
354 glue: Glue,
356 },
357 Glue {
359 spec: Glue,
361 leader: NodeRef,
363 },
364 Kern {
366 kern: i32,
368 expansion_factor: i32,
370 },
371 Penalty {
373 penalty: i32,
375 },
376 Unset {
378 b: Box<BoxData>,
380 span_count: u16,
382 stretch: i32,
384 shrink: i32,
386 stretch_order: u8,
388 shrink_order: u8,
390 },
391 Glyph(GlyphData),
393 MarginKern {
395 width: i32,
397 glyph: NodeRef,
399 },
400 Noad(Box<NoadData>),
402 Fraction(Box<FractionData>),
404 Fence(Box<FenceData>),
406 Style {
408 style: u8,
410 },
411 Choice(Box<[NodeRef; 4]>),
413 MathChar {
415 fam: u32,
417 chr: u32,
419 },
420 SubList {
422 head: NodeRef,
424 },
425 Delim {
427 small_fam: u32,
429 small_char: u32,
431 large_fam: u32,
433 large_char: u32,
435 },
436 Other(Vec<i64>),
438}
439
440#[derive(Clone, Debug, Default, PartialEq)]
444pub struct NoadData {
445 pub nucleus: NodeRef,
447 pub sub: NodeRef,
449 pub sup: NodeRef,
451 pub options: u32,
453 pub left: NodeRef,
455 pub degree: NodeRef,
457 pub width: i32,
459 pub accent: NodeRef,
461 pub bot_accent: NodeRef,
463 pub fraction: i32,
465 pub new_hlist: NodeRef,
468}
469
470#[derive(Clone, Debug, PartialEq)]
472pub struct FractionData {
473 pub thickness: i32,
475 pub num: NodeRef,
477 pub denom: NodeRef,
479 pub left: NodeRef,
481 pub right: NodeRef,
483 pub middle: NodeRef,
485 pub options: u32,
487 pub new_hlist: NodeRef,
489}
490
491#[derive(Clone, Debug, Default, PartialEq)]
493pub struct FenceData {
494 pub delim: NodeRef,
496 pub italic: i32,
498 pub height: i32,
500 pub depth: i32,
502 pub options: u32,
504 pub class: i32,
506 pub new_hlist: NodeRef,
508}
509
510pub const DEFAULT_CODE: i32 = 0o10000000000;
513
514#[allow(missing_docs)]
516pub mod noad_sub {
517 pub const ORD: u16 = 0;
518 pub const OP_DISPLAY_LIMITS: u16 = 1;
519 pub const OP_LIMITS: u16 = 2;
520 pub const OP_NO_LIMITS: u16 = 3;
521 pub const BIN: u16 = 4;
522 pub const REL: u16 = 5;
523 pub const OPEN: u16 = 6;
524 pub const CLOSE: u16 = 7;
525 pub const PUNCT: u16 = 8;
526 pub const INNER: u16 = 9;
527 pub const UNDER: u16 = 10;
528 pub const OVER: u16 = 11;
529 pub const VCENTER: u16 = 12;
530}
531
532#[allow(missing_docs)]
534pub mod radical_sub {
535 pub const RADICAL: u16 = 0;
536 pub const URADICAL: u16 = 1;
537 pub const UROOT: u16 = 2;
538 pub const UUNDERDELIMITER: u16 = 3;
539 pub const UOVERDELIMITER: u16 = 4;
540 pub const UDELIMITERUNDER: u16 = 5;
541 pub const UDELIMITEROVER: u16 = 6;
542 pub const UHEXTENSIBLE: u16 = 7;
543}
544
545#[allow(missing_docs)]
547pub mod fence_sub {
548 pub const UNSET: u16 = 0;
549 pub const LEFT: u16 = 1;
550 pub const MIDDLE: u16 = 2;
551 pub const RIGHT: u16 = 3;
552 pub const NO: u16 = 4;
553}
554
555#[allow(missing_docs)]
557pub mod accent_sub {
558 pub const BOTH_FLEXIBLE: u16 = 0;
559 pub const FIXED_TOP: u16 = 1;
560 pub const FIXED_BOTTOM: u16 = 2;
561 pub const FIXED_BOTH: u16 = 3;
562}
563
564#[allow(missing_docs)]
566pub mod noad_opt {
567 pub const SET: u32 = 0x08;
568 pub const AXIS: u32 = 0x02 | SET;
569 pub const NO_AXIS: u32 = 0x04 | SET;
570 pub const EXACT: u32 = 0x10 | SET;
571 pub const LEFT: u32 = 0x11 | SET;
572 pub const MIDDLE: u32 = 0x12 | SET;
573 pub const RIGHT: u32 = 0x14 | SET;
574 pub const NO_SUB_SCRIPT: u32 = 0x21 | SET;
575 pub const NO_SUPER_SCRIPT: u32 = 0x22 | SET;
576 pub const OVERLAY: u32 = 0x100;
578}
579
580#[derive(Clone, Debug, PartialEq)]
582pub enum Whatsit {
583 Open {
585 stream: u32,
587 name: Vec<u8>,
589 },
590 Write {
592 stream: i32,
594 data: TokenList,
596 },
597 Close {
599 stream: u32,
601 },
602 Special {
604 data: Vec<u8>,
606 },
607 LateLua {
609 data: LateData,
611 name: Vec<u8>,
613 },
614 PdfLiteral {
616 mode: u8,
618 data: LateData,
620 late: bool,
622 },
623 SavePos,
625 PdfColorstack {
627 stack: i32,
629 cmd: u8,
631 data: Vec<u8>,
633 },
634 PdfSetmatrix {
636 data: Vec<u8>,
638 },
639 PdfSave,
641 PdfRestore,
643 PdfAnnot {
645 dims: [i32; 3],
647 objnum: i32,
649 data: Vec<u8>,
651 },
652 PdfStartLink {
654 dims: [i32; 3],
656 objnum: i32,
658 attr: Vec<u8>,
660 action: crate::pdfext::PdfAction,
662 },
663 PdfEndLink,
665 PdfDest {
667 id: crate::pdfext::DestId,
669 view: crate::pdfext::DestView,
671 structure: Option<i32>,
674 },
675 PdfRefobj {
677 objnum: i32,
679 },
680 PdfLinkState {
682 state: i32,
684 },
685 UserDefined {
687 user_id: i32,
689 value: UserValue,
691 },
692 Other {
694 fields: Vec<i64>,
696 data: Vec<u8>,
698 },
699}
700
701#[derive(Clone, Debug, PartialEq)]
703pub enum LateData {
704 Tokens(TokenList),
706 Bytes(Vec<u8>),
708 Lua {
711 data: Vec<u8>,
713 reference: i32,
715 },
716}
717
718impl LateData {
719 pub fn bytes(&self) -> Option<&[u8]> {
721 match self {
722 LateData::Bytes(b) | LateData::Lua { data: b, .. } => Some(b),
723 LateData::Tokens(_) => None,
724 }
725 }
726}
727
728#[derive(Clone, Debug, PartialEq)]
731pub enum UserValue {
732 Int(i32),
734 Str(Vec<u8>),
736 Tokens(TokenList),
738 Nodes(NodeRef),
740 Lua(i32),
742 Attr,
744}
745
746#[derive(Clone, Debug, PartialEq)]
748pub struct Node {
749 pub id: u8,
751 pub subtype: u16,
753 pub next: NodeRef,
755 pub prev: NodeRef,
757 pub attr: Option<AttrList>,
759 pub data: NodeData,
761}
762
763impl Node {
764 fn temp() -> Node {
766 Node {
767 id: id::TEMP,
768 subtype: 0,
769 next: NodeRef::NULL,
770 prev: NodeRef::NULL,
771 attr: None,
772 data: NodeData::Temp,
773 }
774 }
775}
776
777#[derive(Debug, Clone, Copy, PartialEq, Eq)]
780pub enum PropEvent {
781 Flush(u32),
783 Copy(u32, u32),
785}
786
787#[derive(Debug, Clone, Default)]
791pub struct Properties {
792 pub nodes: std::collections::HashSet<u32>,
794 pub flush: bool,
796 pub copy: bool,
798 pub events: Vec<PropEvent>,
800}
801
802#[derive(Debug, Clone)]
804pub struct Nodes {
805 nodes: Vec<Node>,
806 copy_depth: u32,
808 sink: Node,
811 free: Vec<u32>,
812 pub in_use: usize,
814 pub props: Properties,
816 pub sync: Option<Box<SyncFields>>,
819 pub lua_refs: LuaRefs,
821}
822
823#[derive(Debug, Clone, Default)]
830pub struct LuaRefs {
831 pub next: i32,
833 pub free: Vec<i32>,
835 pub copies: Vec<(i32, i32)>,
838}
839
840impl LuaRefs {
841 pub fn take(&mut self) -> i32 {
843 if let Some(r) = self.free.pop() {
844 return r;
845 }
846 if self.next == 0 {
847 self.next = 780;
848 }
849 let r = self.next;
850 self.next += 1;
851 r
852 }
853
854 pub fn release(&mut self, r: i32) {
856 if r > 0 {
857 self.free.push(r);
858 }
859 }
860
861 pub fn font_defined(&mut self, temporary: bool) {
864 if temporary {
865 let t = self.take();
866 self.take();
867 self.release(t);
868 } else {
869 self.take();
870 }
871 }
872}
873
874fn lua_ref_mut(data: &mut NodeData) -> Option<&mut i32> {
876 match data {
877 NodeData::Whatsit(w) => match &mut **w {
878 Whatsit::LateLua {
879 data: LateData::Lua { reference, .. },
880 ..
881 }
882 | Whatsit::PdfLiteral {
883 data: LateData::Lua { reference, .. },
884 ..
885 } => Some(reference),
886 Whatsit::UserDefined {
887 value: UserValue::Lua(r),
888 ..
889 } if *r > 0 => Some(r),
890 _ => None,
891 },
892 _ => None,
893 }
894}
895
896#[derive(Debug, Clone, Default)]
904pub struct SyncFields {
905 pub cur: (u32, i32),
907 fields: Vec<(u32, i32)>,
908}
909
910impl SyncFields {
911 #[inline]
912 fn set(&mut self, i: u32, f: (u32, i32)) {
913 let i = i as usize;
914 if i >= self.fields.len() {
915 self.fields.resize(i + 1, (0, 0));
916 }
917 self.fields[i] = f;
918 }
919}
920
921impl Default for Nodes {
922 fn default() -> Self {
923 Self::new()
924 }
925}
926
927impl Nodes {
928 pub fn new() -> Self {
930 Nodes {
931 nodes: vec![Node::temp()],
932 copy_depth: 0,
933 sink: Node::temp(),
934 free: Vec::new(),
935 in_use: 0,
936 props: Properties::default(),
937 sync: None,
938 lua_refs: LuaRefs::default(),
939 }
940 }
941
942 pub fn enable_sync(&mut self) {
944 if self.sync.is_none() {
945 self.sync = Some(Box::default());
946 }
947 }
948
949 #[inline]
951 pub fn sync_fields(&self, p: NodeRef) -> (u32, i32) {
952 self.sync
953 .as_ref()
954 .and_then(|s| s.fields.get(p.0 as usize).copied())
955 .unwrap_or((0, 0))
956 }
957
958 pub fn set_sync_fields(&mut self, p: NodeRef, f: (u32, i32)) {
960 if p.0 as usize >= self.nodes.len() {
961 return;
962 }
963 if let Some(s) = self.sync.as_deref_mut() {
964 s.set(p.0, f);
965 }
966 }
967
968 pub fn sync_as_copied(&mut self, p: NodeRef) {
972 if let Some(s) = self.sync.as_deref_mut() {
973 let cur = s.cur;
974 s.set(p.0, cur);
975 }
976 }
977
978 #[inline]
980 fn at(&self, p: NodeRef) -> &Node {
981 self.nodes.get(p.0 as usize).unwrap_or(&self.nodes[0])
982 }
983
984 #[inline]
987 fn at_mut(&mut self, p: NodeRef) -> &mut Node {
988 match self.nodes.get_mut(p.0 as usize) {
989 Some(n) => n,
990 None => {
991 self.sink = Node::temp();
992 &mut self.sink
993 }
994 }
995 }
996
997 pub fn capacity(&self) -> usize {
999 self.nodes.len()
1000 }
1001
1002 pub fn alloc(&mut self, id: u8, subtype: u16, data: NodeData) -> NodeRef {
1004 let node = Node {
1005 id,
1006 subtype,
1007 next: NodeRef::NULL,
1008 prev: NodeRef::NULL,
1009 attr: None,
1010 data,
1011 };
1012 self.in_use += 1;
1013 let p = if let Some(i) = self.free.pop() {
1014 self.nodes[i as usize] = node;
1015 NodeRef(i)
1016 } else {
1017 self.nodes.push(node);
1018 NodeRef(self.nodes.len() as u32 - 1)
1019 };
1020 if let Some(s) = self.sync.as_deref_mut() {
1021 let f = if id == id::KERN || id == id::GLYPH {
1022 (0, 0)
1023 } else {
1024 s.cur
1025 };
1026 s.set(p.0, f);
1027 }
1028 p
1029 }
1030
1031 pub fn free(&mut self, p: NodeRef) {
1033 if p.is_null() || p.0 as usize >= self.nodes.len() || self.is_free(p) {
1036 return;
1037 }
1038 if let Some(r) = lua_ref_mut(&mut self.at_mut(p).data) {
1039 let r = *r;
1040 self.lua_refs.release(r);
1041 }
1042 self.at_mut(p).id = id::FREE;
1043 self.at_mut(p).data = NodeData::Temp;
1044 self.at_mut(p).attr = None;
1045 self.free.push(p.0);
1046 self.in_use -= 1;
1047 if !self.props.nodes.is_empty() && self.props.nodes.remove(&p.0) && self.props.flush {
1048 self.props.events.push(PropEvent::Flush(p.0));
1049 }
1050 }
1051
1052 pub fn lua_ref_of(&mut self, p: NodeRef) -> Option<i32> {
1054 lua_ref_mut(&mut self.at_mut(p).data).map(|r| *r)
1055 }
1056
1057 #[inline]
1059 pub fn is_free(&self, p: NodeRef) -> bool {
1060 self.at(p).id == id::FREE
1061 }
1062
1063 #[inline]
1065 pub fn get(&self, p: NodeRef) -> &Node {
1066 self.at(p)
1067 }
1068
1069 #[inline]
1071 pub fn get_mut(&mut self, p: NodeRef) -> &mut Node {
1072 self.at_mut(p)
1073 }
1074
1075 #[inline]
1077 pub fn id(&self, p: NodeRef) -> u8 {
1078 self.at(p).id
1079 }
1080
1081 #[inline]
1083 pub fn next(&self, p: NodeRef) -> NodeRef {
1084 self.at(p).next
1085 }
1086
1087 #[inline]
1089 pub fn link(&mut self, p: NodeRef, q: NodeRef) {
1090 self.at_mut(p).next = q;
1091 if !q.is_null() {
1092 self.at_mut(q).prev = p;
1093 }
1094 }
1095
1096 pub fn box_data(&self, p: NodeRef) -> Option<&BoxData> {
1098 match &self.at(p).data {
1099 NodeData::Box(b) => Some(b),
1100 NodeData::Unset { b, .. } => Some(b),
1101 _ => None,
1102 }
1103 }
1104
1105 pub fn box_data_mut(&mut self, p: NodeRef) -> Option<&mut BoxData> {
1107 match &mut self.at_mut(p).data {
1108 NodeData::Box(b) => Some(b),
1109 NodeData::Unset { b, .. } => Some(b),
1110 _ => None,
1111 }
1112 }
1113
1114 pub fn tail_of(&self, mut p: NodeRef) -> NodeRef {
1116 if p.is_null() {
1117 return p;
1118 }
1119 loop {
1120 let n = self.next(p);
1121 if n.is_null() {
1122 return p;
1123 }
1124 p = n;
1125 }
1126 }
1127
1128 pub fn flush_list(&mut self, p: NodeRef) {
1130 let mut stack: Vec<NodeRef> = Vec::new();
1131 let mut p = p;
1132 loop {
1133 while !p.is_null() {
1134 let next = self.next(p);
1135 match &self.at(p).data {
1136 NodeData::Box(b) => stack.push(b.head),
1137 NodeData::Unset { b, .. } => stack.push(b.head),
1138 NodeData::Ins { head, .. } | NodeData::Adjust { head } => stack.push(*head),
1139 NodeData::Disc {
1140 pre, post, replace, ..
1141 } => {
1142 stack.push(*pre);
1143 stack.push(*post);
1144 stack.push(*replace);
1145 }
1146 NodeData::Glue { leader, .. } => stack.push(*leader),
1147 NodeData::Glyph(g) => {
1148 if !g.components.is_null() {
1149 stack.push(g.components);
1150 }
1151 }
1152 NodeData::LocalPar {
1153 box_left,
1154 box_right,
1155 ..
1156 } => {
1157 stack.push(*box_left);
1158 stack.push(*box_right);
1159 }
1160 NodeData::Noad(n) => stack.extend([
1161 n.nucleus,
1162 n.sub,
1163 n.sup,
1164 n.left,
1165 n.degree,
1166 n.accent,
1167 n.bot_accent,
1168 n.new_hlist,
1169 ]),
1170 NodeData::Fraction(f) => {
1171 stack.extend([f.num, f.denom, f.left, f.right, f.middle, f.new_hlist])
1172 }
1173 NodeData::Fence(f) => stack.extend([f.delim, f.new_hlist]),
1174 NodeData::Choice(c) => stack.extend(c.iter().copied()),
1175 NodeData::SubList { head } => stack.push(*head),
1176 _ => {}
1177 }
1178 self.free(p);
1179 p = next;
1180 }
1181 match stack.pop() {
1182 Some(q) => p = q,
1183 None => return,
1184 }
1185 }
1186 }
1187
1188 pub fn copy_list(&mut self, mut p: NodeRef) -> NodeRef {
1190 let mut head = NodeRef::NULL;
1191 let mut tail = NodeRef::NULL;
1192 if self.copy_depth >= MAX_NESTING {
1195 return head;
1196 }
1197 self.copy_depth += 1;
1198 while !p.is_null() {
1199 let q = self.copy_node(p);
1200 if head.is_null() {
1201 head = q;
1202 } else {
1203 self.link(tail, q);
1204 }
1205 tail = q;
1206 p = self.next(p);
1207 }
1208 self.copy_depth -= 1;
1209 head
1210 }
1211
1212 pub fn copy_node(&mut self, p: NodeRef) -> NodeRef {
1214 let mut node = self.at(p).clone();
1215 node.next = NodeRef::NULL;
1216 node.prev = NodeRef::NULL;
1217 match &mut node.data {
1218 NodeData::Box(b) => b.head = self.copy_list(b.head),
1219 NodeData::Unset { b, .. } => b.head = self.copy_list(b.head),
1220 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head = self.copy_list(*head),
1221 NodeData::Disc {
1222 pre, post, replace, ..
1223 } => {
1224 *pre = self.copy_list(*pre);
1225 *post = self.copy_list(*post);
1226 *replace = self.copy_list(*replace);
1227 }
1228 NodeData::Glue { leader, .. } => *leader = self.copy_list(*leader),
1229 NodeData::Glyph(g) => g.components = self.copy_list(g.components),
1230 NodeData::LocalPar {
1231 box_left,
1232 box_right,
1233 ..
1234 } => {
1235 *box_left = self.copy_list(*box_left);
1236 *box_right = self.copy_list(*box_right);
1237 }
1238 NodeData::Noad(n) => {
1239 for f in [
1240 &mut n.nucleus,
1241 &mut n.sub,
1242 &mut n.sup,
1243 &mut n.left,
1244 &mut n.degree,
1245 &mut n.accent,
1246 &mut n.bot_accent,
1247 &mut n.new_hlist,
1248 ] {
1249 *f = self.copy_list(*f);
1250 }
1251 }
1252 NodeData::Fraction(fr) => {
1253 for f in [
1254 &mut fr.num,
1255 &mut fr.denom,
1256 &mut fr.left,
1257 &mut fr.right,
1258 &mut fr.middle,
1259 &mut fr.new_hlist,
1260 ] {
1261 *f = self.copy_list(*f);
1262 }
1263 }
1264 NodeData::Fence(fe) => {
1265 fe.delim = self.copy_list(fe.delim);
1266 fe.new_hlist = self.copy_list(fe.new_hlist);
1267 }
1268 NodeData::Choice(c) => {
1269 for f in c.iter_mut() {
1270 *f = self.copy_list(*f);
1271 }
1272 }
1273 NodeData::SubList { head } => *head = self.copy_list(*head),
1274 _ => {}
1275 }
1276 if let Some(r) = lua_ref_mut(&mut node.data) {
1277 let old = *r;
1278 let new = self.lua_refs.take();
1279 *r = new;
1280 self.lua_refs.copies.push((new, old));
1281 }
1282 self.in_use += 1;
1283 let q = if let Some(i) = self.free.pop() {
1284 self.nodes[i as usize] = node;
1285 NodeRef(i)
1286 } else {
1287 self.nodes.push(node);
1288 NodeRef(self.nodes.len() as u32 - 1)
1289 };
1290 if self.props.copy && self.props.nodes.contains(&p.0) {
1291 self.props.nodes.insert(q.0);
1292 self.props.events.push(PropEvent::Copy(p.0, q.0));
1293 }
1294 if self.sync.is_some() {
1295 let id = self.at(q).id;
1296 let f = if id == id::KERN || id == id::MATH {
1297 self.sync.as_ref().map_or((0, 0), |s| s.cur)
1298 } else {
1299 self.sync_fields(p)
1300 };
1301 self.set_sync_fields(q, f);
1302 }
1303 q
1304 }
1305
1306 pub fn new_null_box(&mut self, hlist: bool) -> NodeRef {
1308 self.alloc(
1309 if hlist { id::HLIST } else { id::VLIST },
1310 0,
1311 NodeData::Box(Box::default()),
1312 )
1313 }
1314
1315 pub fn new_glue(&mut self, spec: Glue, subtype: u16) -> NodeRef {
1317 self.alloc(
1318 id::GLUE,
1319 subtype,
1320 NodeData::Glue {
1321 spec,
1322 leader: NodeRef::NULL,
1323 },
1324 )
1325 }
1326
1327 pub fn new_kern(&mut self, w: i32, subtype: u16) -> NodeRef {
1329 self.alloc(
1330 id::KERN,
1331 subtype,
1332 NodeData::Kern {
1333 kern: w,
1334 expansion_factor: 0,
1335 },
1336 )
1337 }
1338
1339 pub fn new_penalty(&mut self, m: i32, subtype: u16) -> NodeRef {
1341 self.alloc(id::PENALTY, subtype, NodeData::Penalty { penalty: m })
1342 }
1343
1344 pub fn new_temp(&mut self) -> NodeRef {
1346 self.alloc(id::TEMP, 0, NodeData::Temp)
1347 }
1348
1349 pub fn new_glyph(&mut self, font: u32, chr: u32) -> NodeRef {
1351 self.alloc(
1352 id::GLYPH,
1353 0,
1354 NodeData::Glyph(GlyphData {
1355 chr,
1356 font,
1357 ..GlyphData::default()
1358 }),
1359 )
1360 }
1361
1362 pub fn new_rule(&mut self, width: i32, height: i32, depth: i32) -> NodeRef {
1364 self.alloc(
1365 id::RULE,
1366 0,
1367 NodeData::Rule {
1368 width,
1369 depth,
1370 height,
1371 dir: 0,
1372 index: 0,
1373 left: 0,
1374 right: 0,
1375 },
1376 )
1377 }
1378
1379 pub fn new_disc(&mut self, subtype: u16, penalty: i32) -> NodeRef {
1381 self.alloc(
1382 id::DISC,
1383 subtype,
1384 NodeData::Disc {
1385 pre: NodeRef::NULL,
1386 post: NodeRef::NULL,
1387 replace: NodeRef::NULL,
1388 penalty,
1389 },
1390 )
1391 }
1392
1393 pub fn new_math(&mut self, surround: i32, subtype: u16) -> NodeRef {
1395 self.alloc(
1396 id::MATH,
1397 subtype,
1398 NodeData::Math {
1399 surround,
1400 glue: Glue::ZERO,
1401 },
1402 )
1403 }
1404
1405 #[inline]
1407 pub fn data(&self, p: NodeRef) -> &NodeData {
1408 &self.at(p).data
1409 }
1410
1411 #[inline]
1413 pub fn data_mut(&mut self, p: NodeRef) -> &mut NodeData {
1414 &mut self.at_mut(p).data
1415 }
1416
1417 #[inline]
1419 pub fn subtype(&self, p: NodeRef) -> u16 {
1420 self.at(p).subtype
1421 }
1422
1423 #[inline]
1425 pub fn set_subtype(&mut self, p: NodeRef, s: u16) {
1426 self.at_mut(p).subtype = s;
1427 }
1428
1429 #[inline]
1431 pub fn prev(&self, p: NodeRef) -> NodeRef {
1432 self.at(p).prev
1433 }
1434
1435 #[inline]
1437 pub fn set_next(&mut self, p: NodeRef, q: NodeRef) {
1438 self.at_mut(p).next = q;
1439 }
1440
1441 #[inline]
1443 pub fn set_prev(&mut self, p: NodeRef, q: NodeRef) {
1444 self.at_mut(p).prev = q;
1445 }
1446
1447 #[inline]
1449 pub fn is_glyph(&self, p: NodeRef) -> bool {
1450 self.at(p).id == id::GLYPH
1451 }
1452
1453 #[inline]
1455 pub fn glyph(&self, p: NodeRef) -> Option<&GlyphData> {
1456 match &self.at(p).data {
1457 NodeData::Glyph(g) => Some(g),
1458 _ => None,
1459 }
1460 }
1461
1462 #[inline]
1464 pub fn glyph_mut(&mut self, p: NodeRef) -> Option<&mut GlyphData> {
1465 match &mut self.at_mut(p).data {
1466 NodeData::Glyph(g) => Some(g),
1467 _ => None,
1468 }
1469 }
1470
1471 #[inline]
1473 pub fn glue_spec(&self, p: NodeRef) -> Glue {
1474 match &self.at(p).data {
1475 NodeData::Glue { spec, .. } => *spec,
1476 NodeData::Math { glue, .. } => *glue,
1477 _ => Glue::ZERO,
1478 }
1479 }
1480
1481 pub fn width(&self, p: NodeRef) -> i32 {
1485 match &self.at(p).data {
1486 NodeData::Box(b) => b.width,
1487 NodeData::Unset { b, .. } => b.width,
1488 NodeData::Rule { width, .. } => *width,
1489 NodeData::Glue { spec, .. } => spec.width,
1490 NodeData::Kern {
1491 kern,
1492 expansion_factor,
1493 } => *kern + *expansion_factor,
1494 NodeData::Math { surround, glue } => {
1495 if glue.width != 0 || glue.stretch != 0 || glue.shrink != 0 {
1496 glue.width
1497 } else {
1498 *surround
1499 }
1500 }
1501 NodeData::MarginKern { width, .. } => *width,
1502 _ => 0,
1503 }
1504 }
1505
1506 pub fn penalty(&self, p: NodeRef) -> i32 {
1508 match &self.at(p).data {
1509 NodeData::Penalty { penalty } => *penalty,
1510 NodeData::Disc { penalty, .. } => *penalty,
1511 _ => 0,
1512 }
1513 }
1514
1515 pub fn disc_lists(&self, p: NodeRef) -> (NodeRef, NodeRef, NodeRef) {
1517 match &self.at(p).data {
1518 NodeData::Disc {
1519 pre, post, replace, ..
1520 } => (*pre, *post, *replace),
1521 _ => (NodeRef::NULL, NodeRef::NULL, NodeRef::NULL),
1522 }
1523 }
1524
1525 pub fn set_disc_lists(&mut self, p: NodeRef, l: (NodeRef, NodeRef, NodeRef)) {
1527 if let NodeData::Disc {
1528 pre, post, replace, ..
1529 } = &mut self.at_mut(p).data
1530 {
1531 *pre = l.0;
1532 *post = l.1;
1533 *replace = l.2;
1534 }
1535 for q in [l.0, l.1, l.2] {
1536 if !q.is_null() {
1537 self.at_mut(q).prev = NodeRef::NULL;
1538 }
1539 }
1540 }
1541
1542 pub fn list_ptr(&self, p: NodeRef) -> NodeRef {
1544 match &self.at(p).data {
1545 NodeData::Box(b) => b.head,
1546 NodeData::Unset { b, .. } => b.head,
1547 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head,
1548 _ => NodeRef::NULL,
1549 }
1550 }
1551
1552 pub fn set_list_ptr(&mut self, p: NodeRef, l: NodeRef) {
1554 match &mut self.at_mut(p).data {
1555 NodeData::Box(b) => b.head = l,
1556 NodeData::Unset { b, .. } => b.head = l,
1557 NodeData::Ins { head, .. } | NodeData::Adjust { head } => *head = l,
1558 _ => {}
1559 }
1560 }
1561
1562 #[inline]
1564 pub fn attr(&self, p: NodeRef) -> Option<&AttrList> {
1565 self.at(p).attr.as_ref()
1566 }
1567
1568 #[inline]
1570 pub fn set_attr(&mut self, p: NodeRef, a: Option<AttrList>) {
1571 self.at_mut(p).attr = a;
1572 }
1573
1574 #[inline]
1576 pub fn noad(&self, p: NodeRef) -> Option<&NoadData> {
1577 match &self.at(p).data {
1578 NodeData::Noad(n) => Some(n),
1579 _ => None,
1580 }
1581 }
1582
1583 #[inline]
1585 pub fn noad_mut(&mut self, p: NodeRef) -> Option<&mut NoadData> {
1586 match &mut self.at_mut(p).data {
1587 NodeData::Noad(n) => Some(n),
1588 _ => None,
1589 }
1590 }
1591
1592 pub fn list_ptr_kernel(&self, p: NodeRef) -> NodeRef {
1594 if p.is_null() {
1595 return NodeRef::NULL;
1596 }
1597 match &self.at(p).data {
1598 NodeData::SubList { head } => *head,
1599 _ => NodeRef::NULL,
1600 }
1601 }
1602
1603 pub fn set_kernel_list(&mut self, p: NodeRef, l: NodeRef) {
1605 if p.is_null() {
1606 return;
1607 }
1608 if let NodeData::SubList { head } = &mut self.at_mut(p).data {
1609 *head = l;
1610 }
1611 }
1612
1613 pub fn scripts_allowed(&self, p: NodeRef) -> bool {
1615 matches!(self.at(p).data, NodeData::Noad(_))
1616 && matches!(self.id(p), id::NOAD | id::RADICAL | id::ACCENT)
1617 }
1618
1619 pub fn list_len(&self, mut p: NodeRef) -> usize {
1621 let mut n = 0;
1622 while !p.is_null() {
1623 n += 1;
1624 p = self.next(p);
1625 }
1626 n
1627 }
1628}
1629
1630pub fn glue_ratio(num: i32, den: i32) -> f64 {
1635 f64::from((f64::from(num) / f64::from(den)) as f32)
1636}
1637
1638#[cfg(test)]
1639mod tests {
1640 use super::*;
1641
1642 #[test]
1643 fn glue_ratio_is_single_precision() {
1644 assert_eq!(glue_ratio(1021537, 873808), 1.1690634489059448);
1646 }
1647
1648 #[test]
1649 fn alloc_link_copy_flush() {
1650 let mut n = Nodes::new();
1651 let b = n.new_null_box(true);
1652 let k = n.new_kern(5, kern_sub::USER);
1653 let g = n.new_glue(Glue::fixed(7), glue_sub::USER);
1654 n.link(k, g);
1655 n.box_data_mut(b).unwrap().head = k;
1656 assert_eq!(n.in_use, 3);
1657 let c = n.copy_node(b);
1658 assert_eq!(n.in_use, 6);
1659 let ch = n.box_data(c).unwrap().head;
1660 assert_ne!(ch, k);
1661 assert_eq!(n.get(n.next(ch)).data, n.get(g).data);
1662 n.flush_list(c);
1663 n.flush_list(b);
1664 assert_eq!(n.in_use, 0);
1665 }
1666}