rustyfi_backend/vbox.rs
1use crate::hbox::{DecoId, HookId, PureHorzBox};
2use crate::length::Length;
3
4/// A milestone-1 subset of `vert_box`: a typeset line or vertical space.
5#[derive(Clone, Debug, PartialEq)]
6pub enum VertBox {
7 /// One typeset line: boxes with their x offsets from the line start.
8 Line {
9 height: Length,
10 depth: Length,
11 /// Baseline-to-baseline distance to the *next* line: the `leading`
12 /// a `context` was set to when this line was assembled. `page-break`
13 /// takes no context, so the property rides the line itself, set by
14 /// `break_into_lines` from `ctx.leading`.
15 leading: Length,
16 contents: Vec<(Length, PureHorzBox)>,
17 },
18 /// Fixed vertical space (`block-skip`, frame padding, a paragraph's
19 /// *bottom* margin) — NOT padded by `min_first_line_ascender`.
20 Skip(Length),
21 /// A paragraph's TOP margin (`prim_line_break` prepends this from
22 /// `ctx.paragraph_top`). Distinguished from `Skip` because SATySFi pads
23 /// only the paragraph `margin_top` up to `min_first_line_ascender`
24 /// (`lineBreak.ml:857`) — `block-skip`s and frame pads get no such pad.
25 /// Accumulates into `pending_skip` exactly like `Skip`; the difference is
26 /// only that its presence enables the ascender pad on the following line.
27 ParagTop(Length),
28 /// A `block-frame-breakable` frame's internal top/bottom padding. Unlike
29 /// `Skip` (a margin, which max-COLLAPSES with adjacent margins), frame
30 /// padding is ADDITIVE — SATySFi adds it to the running height inside the
31 /// frame (`pageBreak.ml:323` `hgttotal +% pads.paddingT`, `:380`
32 /// `+% pads.paddingB`), so it stacks ON TOP of the surrounding
33 /// paragraph margin rather than being absorbed by it.
34 FramePad(Length),
35 /// `clear-page`'s marker (`primitives.cppo.ml`'s `VertClearPage`,
36 /// `horzBox.ml:346`) — forces the current page to end right here:
37 /// `chop_page` closes the page as soon as at least one real `Line` has
38 /// been placed, leaving everything from this marker onward for the next
39 /// page. Contributes zero height (`measure_block`), mirroring
40 /// `pageBreak.ml`'s `PBClearPage` (`solidify`'s
41 /// `ImVertFixedEmpty(Fixed, Length.zero)`).
42 ClearPage,
43 /// `hook-page-break-block`'s marker (`vminst.ml:632`
44 /// `BackendHookPageBreakBlock` / `horzBox.ml:347`'s `VertHookPageBreak`)
45 /// — the block-level analog of `PureHorzBox::HookPageBreak`: an opaque
46 /// index into a lang-side hook table, fired by `fire_hooks` with the
47 /// page's `pbinfo` and the point where it sits in the flow. Contributes
48 /// zero height, same as `ClearPage`.
49 HookPageBreak(HookId),
50 /// `block-frame-breakable`'s frame-extent markers: the frame's
51 /// indented contents sit between a `FrameStart(id)`/`FrameEnd(id)` pair;
52 /// `chop_page`/`place_block_at` place each as a zero-height marker
53 /// `PlacedLine` (the `HookPageBreak` pattern) and `fire_hooks` derives
54 /// each page fragment's rect from the real lines between them. The
55 /// frame's pads/width/deco-set live lang-side (`DecoEntry::Block`).
56 FrameStart(DecoId),
57 FrameEnd(DecoId),
58 /// an INERT reflow marker for list (`itemize`/`enumerate`) structure,
59 /// emitted by the `list-mark` primitive from
60 /// `lib-rustyfi/dist-v01/packages/itemize.satyh`'s
61 /// `listing`/`listing-item`/`listing-item-breakable`/`enumerate`/
62 /// `enumerate-item`. Zero height/depth, contributes nothing to any
63 /// measurement (`measure_block`) or placement (`chop_page`/
64 /// `place_block_at`) — it never reaches a `PlacedLine`, so PDF and
65 /// faithful HTML are byte-identical whether or not a document's stdlib
66 /// emits these. Read only by the reflow HTML walker (the `html-support`
67 /// branch's `rustyfi-html/src/reflow/block.rs`'s `walk_vboxes`), which
68 /// uses the Start/End nesting to rebuild real `<ul>`/`<ol>`/`<li>`
69 /// structure.
70 ListMark(ListMarkKind),
71}
72
73/// The marker kind a `VertBox::ListMark` carries. `ordered` on `ListStart`
74/// is the ONE piece of real data these markers carry (`listing` vs
75/// `enumerate` are distinct stdlib commands, so this is an exact bit, not a
76/// heuristic); nesting depth is recovered structurally by the reflow
77/// walker's stack from how markers are nested in the flat box stream, not
78/// stored here.
79#[derive(Clone, Copy, Debug, PartialEq, Eq)]
80pub enum ListMarkKind {
81 /// Opens a `<ul>` (`ordered = false`) or `<ol>` (`ordered = true`).
82 ListStart { ordered: bool },
83 /// Closes the innermost open list.
84 ListEnd,
85 /// Opens one `<li>`.
86 ItemStart,
87 /// Closes the innermost open `<li>`.
88 ItemEnd,
89}