1use crate::{
2 font_cache::FamilyId,
3 fonts::Properties,
4 geometry::{
5 rect::RectF,
6 vector::{vec2f, Vector2F},
7 },
8 json::{json, ToJson},
9 AfterLayoutContext, DebugContext, Element, ElementBox, Event, EventContext, LayoutContext,
10 PaintContext, 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 after_layout(
64 &mut self,
65 _: Vector2F,
66 _: &mut Self::LayoutState,
67 cx: &mut AfterLayoutContext,
68 ) {
69 self.child.after_layout(cx);
70 }
71
72 fn paint(
73 &mut self,
74 bounds: pathfinder_geometry::rect::RectF,
75 padding_top: &mut f32,
76 cx: &mut PaintContext,
77 ) -> Self::PaintState {
78 self.child
79 .paint(bounds.origin() + vec2f(0., *padding_top), cx);
80 }
81
82 fn dispatch_event(
83 &mut self,
84 event: &Event,
85 _: pathfinder_geometry::rect::RectF,
86 _: &mut Self::LayoutState,
87 _: &mut Self::PaintState,
88 cx: &mut EventContext,
89 ) -> bool {
90 self.child.dispatch_event(event, cx)
91 }
92
93 fn debug(
94 &self,
95 bounds: RectF,
96 _: &Self::LayoutState,
97 _: &Self::PaintState,
98 cx: &DebugContext,
99 ) -> serde_json::Value {
100 json!({
101 "bounds": bounds.to_json(),
102 "font_family": cx.font_cache.family_name(self.family_id).unwrap(),
103 "font_size": self.font_size,
104 "font_properties": self.font_properties.to_json(),
105 "child": self.child.debug(cx),
106 })
107 }
108}