line_box.rs

 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}