1use crate::{
2 font_cache::FamilyId,
3 fonts::Properties,
4 geometry::{
5 rect::RectF,
6 vector::{vec2f, Vector2F},
7 },
8 json::{json, ToJson},
9 DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
10 SizeConstraint,
11};
12
13pub struct LineBox {
14 child: ElementBox,
15 family_id: FamilyId,
16 font_size: f32,
17 font_properties: Properties,
18}
19
20impl LineBox {
21 pub fn new(family_id: FamilyId, font_size: f32, child: ElementBox) -> Self {
22 Self {
23 child,
24 family_id,
25 font_size,
26 font_properties: Properties::default(),
27 }
28 }
29}
30
31impl Element for LineBox {
32 type LayoutState = f32;
33 type PaintState = ();
34
35 fn layout(
36 &mut self,
37 constraint: SizeConstraint,
38 cx: &mut LayoutContext,
39 ) -> (Vector2F, Self::LayoutState) {
40 match cx
41 .font_cache
42 .select_font(self.family_id, &self.font_properties)
43 {
44 Ok(font_id) => {
45 let line_height = cx.font_cache.line_height(font_id, self.font_size);
46 let character_height = cx.font_cache.ascent(font_id, self.font_size)
47 + cx.font_cache.descent(font_id, self.font_size);
48 let child_max = vec2f(constraint.max.x(), character_height);
49 let child_size = self.child.layout(
50 SizeConstraint::new(constraint.min.min(child_max), child_max),
51 cx,
52 );
53 let size = vec2f(child_size.x(), line_height);
54 (size, (line_height - character_height) / 2.)
55 }
56 Err(error) => {
57 log::error!("can't find font for LineBox: {}", error);
58 (constraint.min, 0.0)
59 }
60 }
61 }
62
63 fn paint(
64 &mut self,
65 bounds: pathfinder_geometry::rect::RectF,
66 padding_top: &mut f32,
67 cx: &mut PaintContext,
68 ) -> Self::PaintState {
69 self.child
70 .paint(bounds.origin() + vec2f(0., *padding_top), cx);
71 }
72
73 fn dispatch_event(
74 &mut self,
75 event: &Event,
76 _: pathfinder_geometry::rect::RectF,
77 _: &mut Self::LayoutState,
78 _: &mut Self::PaintState,
79 cx: &mut EventContext,
80 ) -> bool {
81 self.child.dispatch_event(event, cx)
82 }
83
84 fn debug(
85 &self,
86 bounds: RectF,
87 _: &Self::LayoutState,
88 _: &Self::PaintState,
89 cx: &DebugContext,
90 ) -> serde_json::Value {
91 json!({
92 "bounds": bounds.to_json(),
93 "font_family": cx.font_cache.family_name(self.family_id).unwrap(),
94 "font_size": self.font_size,
95 "font_properties": self.font_properties.to_json(),
96 "child": self.child.debug(cx),
97 })
98 }
99}