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
42                    .font_cache
43                    .bounding_box(font_id, self.font_size)
44                    .y()
45                    .ceil();
46                let child_max = vec2f(
47                    constraint.max.x(),
48                    ctx.font_cache.ascent(font_id, self.font_size)
49                        - ctx.font_cache.descent(font_id, self.font_size),
50                );
51                let child_size = self.child.layout(
52                    SizeConstraint::new(constraint.min.min(child_max), child_max),
53                    ctx,
54                );
55                let size = vec2f(child_size.x(), line_height);
56                (size, Some(font_id))
57            }
58            Err(error) => {
59                log::error!("can't find font for LineBox: {}", error);
60                (constraint.min, None)
61            }
62        }
63    }
64
65    fn after_layout(
66        &mut self,
67        _: Vector2F,
68        _: &mut Self::LayoutState,
69        ctx: &mut AfterLayoutContext,
70    ) {
71        self.child.after_layout(ctx);
72    }
73
74    fn paint(
75        &mut self,
76        bounds: pathfinder_geometry::rect::RectF,
77        font_id: &mut Option<FontId>,
78        ctx: &mut PaintContext,
79    ) -> Self::PaintState {
80        if let Some(font_id) = font_id {
81            let descent = ctx.font_cache.descent(*font_id, self.font_size);
82            self.child
83                .paint(bounds.origin() + vec2f(0.0, -descent), ctx);
84        }
85    }
86
87    fn dispatch_event(
88        &mut self,
89        event: &Event,
90        _: pathfinder_geometry::rect::RectF,
91        _: &mut Self::LayoutState,
92        _: &mut Self::PaintState,
93        ctx: &mut EventContext,
94    ) -> bool {
95        self.child.dispatch_event(event, ctx)
96    }
97}