kozan_core/layout/inline/item.rs
1//! Inline item — the atomic unit of inline layout.
2//!
3//! Chrome equivalent: `NGInlineItem`. A flat list of items representing
4//! the inline content of a block container.
5//!
6//! The flat list is a deliberate Chrome optimization — not a tree.
7//! It's cache-friendly and fast to iterate during line breaking.
8
9use std::sync::Arc;
10use style::properties::ComputedValues;
11
12/// Stylo Arc for computed styles.
13type StyleArc<T> = servo_arc::Arc<T>;
14
15/// An item in the inline formatting context.
16///
17/// Chrome equivalent: `NGInlineItem` with its type.
18#[derive(Debug, Clone)]
19pub enum InlineItem {
20 /// A text run — a segment of text with uniform style.
21 /// The text will be shaped (future: via Parley/harfrust).
22 Text {
23 /// The text content.
24 content: Arc<str>,
25 /// Style for this text (font, color, etc.).
26 style: StyleArc<ComputedValues>,
27 /// Measured width (set during shaping/measurement).
28 measured_width: f32,
29 /// Measured height (ascent + descent).
30 measured_height: f32,
31 /// Baseline offset from top.
32 baseline: f32,
33 },
34
35 /// Open tag — start of an inline element (e.g., `<span>`).
36 /// Chrome: `kOpenTag`.
37 OpenTag {
38 style: StyleArc<ComputedValues>,
39 /// Inline margin/border/padding on the start side.
40 margin_inline_start: f32,
41 border_inline_start: f32,
42 padding_inline_start: f32,
43 },
44
45 /// Close tag — end of an inline element.
46 /// Chrome: `kCloseTag`.
47 CloseTag {
48 /// Inline margin/border/padding on the end side.
49 margin_inline_end: f32,
50 border_inline_end: f32,
51 padding_inline_end: f32,
52 },
53
54 /// An atomic inline — an inline-block, replaced element (img), etc.
55 /// These are measured as a single unit and cannot be broken across lines.
56 AtomicInline {
57 /// The fragment produced by laying out this atomic inline.
58 width: f32,
59 height: f32,
60 baseline: f32,
61 /// Index into the layout tree.
62 layout_id: u32,
63 /// Style for this atomic inline (vertical-align, etc.).
64 style: StyleArc<ComputedValues>,
65 },
66
67 /// A forced line break (`<br>`).
68 ForcedBreak,
69}
70
71impl InlineItem {
72 /// Get the inline size (width) of this item.
73 #[must_use]
74 pub fn inline_size(&self) -> f32 {
75 match self {
76 InlineItem::Text { measured_width, .. } => *measured_width,
77 InlineItem::OpenTag {
78 margin_inline_start,
79 border_inline_start,
80 padding_inline_start,
81 ..
82 } => margin_inline_start + border_inline_start + padding_inline_start,
83 InlineItem::CloseTag {
84 margin_inline_end,
85 border_inline_end,
86 padding_inline_end,
87 ..
88 } => margin_inline_end + border_inline_end + padding_inline_end,
89 InlineItem::AtomicInline { width, .. } => *width,
90 InlineItem::ForcedBreak => 0.0,
91 }
92 }
93
94 /// Whether this item forces a line break.
95 #[must_use]
96 pub fn is_forced_break(&self) -> bool {
97 matches!(self, InlineItem::ForcedBreak)
98 }
99
100 /// Whether this item is breakable (text can be split across lines).
101 #[must_use]
102 pub fn is_breakable(&self) -> bool {
103 matches!(self, InlineItem::Text { .. })
104 }
105}