kozan_core/layout/inline/
context.rs1use smallvec::SmallVec;
6
7use super::item::InlineItem;
8use style::properties::ComputedValues;
9
10#[derive(Debug, Clone)]
15pub struct InlineFormattingContext {
16 pub items: SmallVec<[InlineItem; 16]>,
19}
20
21impl InlineFormattingContext {
22 #[must_use]
23 pub fn new() -> Self {
24 Self {
25 items: SmallVec::new(),
26 }
27 }
28
29 pub fn add_text(
38 &mut self,
39 content: std::sync::Arc<str>,
40 style: servo_arc::Arc<ComputedValues>,
41 measurer: &dyn super::measurer::TextMeasurer,
42 ) {
43 let font_size = style.clone_font_size().computed_size().px();
44 let text_metrics = measurer.measure(&content, font_size);
45 let font_metrics = measurer.font_metrics(font_size);
46
47 let line_height = super::measurer::resolve_line_height(
49 &style.clone_line_height(),
50 font_size,
51 &font_metrics,
52 );
53
54 let font_height =
57 super::measurer::FontHeight::from_metrics_and_line_height(&font_metrics, line_height);
58
59 self.items.push(InlineItem::Text {
60 content,
61 style,
62 measured_width: text_metrics.width,
63 measured_height: font_height.height(),
64 baseline: font_height.ascent,
65 });
66 }
67
68 pub fn add_break(&mut self) {
70 self.items.push(InlineItem::ForcedBreak);
71 }
72
73 pub fn add_atomic(
75 &mut self,
76 width: f32,
77 height: f32,
78 baseline: f32,
79 layout_id: u32,
80 style: servo_arc::Arc<ComputedValues>,
81 ) {
82 self.items.push(InlineItem::AtomicInline {
83 width,
84 height,
85 baseline,
86 layout_id,
87 style,
88 });
89 }
90
91 pub fn add_open_tag(&mut self, style: servo_arc::Arc<ComputedValues>) {
93 let margin_start = resolve_stylo_margin(&style.get_margin().margin_left);
96 let border_start = style.get_border().border_left_width.0.to_f32_px();
97 let padding_start = resolve_stylo_lp(&style.get_padding().padding_left.0);
98
99 self.items.push(InlineItem::OpenTag {
100 style,
101 margin_inline_start: margin_start,
102 border_inline_start: border_start,
103 padding_inline_start: padding_start,
104 });
105 }
106
107 pub fn add_close_tag(&mut self, style: &ComputedValues) {
109 let margin_end = resolve_stylo_margin(&style.get_margin().margin_right);
111 let border_end = style.get_border().border_right_width.0.to_f32_px();
112 let padding_end = resolve_stylo_lp(&style.get_padding().padding_right.0);
113
114 self.items.push(InlineItem::CloseTag {
115 margin_inline_end: margin_end,
116 border_inline_end: border_end,
117 padding_inline_end: padding_end,
118 });
119 }
120
121 #[must_use]
123 pub fn is_empty(&self) -> bool {
124 self.items.is_empty()
125 }
126}
127
128fn resolve_stylo_margin(
130 value: &style::values::generics::length::GenericMargin<
131 style::values::computed::LengthPercentage,
132 >,
133) -> f32 {
134 use style::values::generics::length::GenericMargin;
135 match value {
136 GenericMargin::LengthPercentage(lp) => resolve_stylo_lp(lp),
137 GenericMargin::Auto => 0.0,
138 _ => 0.0, }
140}
141
142fn resolve_stylo_lp(value: &style::values::computed::LengthPercentage) -> f32 {
144 value
145 .percentage_relative_to(style::values::computed::CSSPixelLength::new(0.0))
146 .px()
147}
148
149impl Default for InlineFormattingContext {
150 fn default() -> Self {
151 Self::new()
152 }
153}