line_box.rs

 1use crate::{
 2    fonts::{FamilyId, FontId, Properties},
 3    geometry::vector::{vec2f, Vector2F},
 4    AfterLayoutContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
 5    SizeConstraint,
 6};
 7
 8pub struct LineBox {
 9    child: ElementBox,
10    family_id: FamilyId,
11    font_size: f32,
12    font_properties: Properties,
13}
14
15impl LineBox {
16    pub fn new(family_id: FamilyId, font_size: f32, child: ElementBox) -> Self {
17        Self {
18            child,
19            family_id,
20            font_size,
21            font_properties: Properties::default(),
22        }
23    }
24}
25
26impl Element for LineBox {
27    type LayoutState = Option<FontId>;
28    type PaintState = ();
29
30    fn layout(
31        &mut self,
32        constraint: SizeConstraint,
33        ctx: &mut LayoutContext,
34    ) -> (Vector2F, Self::LayoutState) {
35        match ctx
36            .font_cache
37            .select_font(self.family_id, &self.font_properties)
38        {
39            Ok(font_id) => {
40                let line_height = ctx.font_cache.bounding_box(font_id, self.font_size).y();
41                let child_max = vec2f(
42                    constraint.max.x(),
43                    ctx.font_cache.ascent(font_id, self.font_size)
44                        - ctx.font_cache.descent(font_id, self.font_size),
45                );
46                let child_size = self.child.layout(
47                    SizeConstraint::new(constraint.min.min(child_max), child_max),
48                    ctx,
49                );
50                let size = vec2f(child_size.x(), line_height);
51                (size, Some(font_id))
52            }
53            Err(error) => {
54                log::error!("can't find font for LineBox: {}", error);
55                (constraint.min, None)
56            }
57        }
58    }
59
60    fn after_layout(
61        &mut self,
62        _: Vector2F,
63        _: &mut Self::LayoutState,
64        ctx: &mut AfterLayoutContext,
65    ) {
66        self.child.after_layout(ctx);
67    }
68
69    fn paint(
70        &mut self,
71        bounds: pathfinder_geometry::rect::RectF,
72        font_id: &mut Option<FontId>,
73        ctx: &mut PaintContext,
74    ) -> Self::PaintState {
75        if let Some(font_id) = font_id {
76            let descent = ctx.font_cache.descent(*font_id, self.font_size);
77            self.child
78                .paint(bounds.origin() + vec2f(0.0, -descent), ctx);
79        }
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        ctx: &mut EventContext,
89    ) -> bool {
90        self.child.dispatch_event(event, ctx)
91    }
92}