line_box.rs

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