Skip to main content

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}