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}