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    AfterLayoutContext, DebugContext, Element, ElementBox, Event, EventContext, LayoutContext,
 10    PaintContext, 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 after_layout(
 64        &mut self,
 65        _: Vector2F,
 66        _: &mut Self::LayoutState,
 67        cx: &mut AfterLayoutContext,
 68    ) {
 69        self.child.after_layout(cx);
 70    }
 71
 72    fn paint(
 73        &mut self,
 74        bounds: pathfinder_geometry::rect::RectF,
 75        padding_top: &mut f32,
 76        cx: &mut PaintContext,
 77    ) -> Self::PaintState {
 78        self.child
 79            .paint(bounds.origin() + vec2f(0., *padding_top), cx);
 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        cx: &mut EventContext,
 89    ) -> bool {
 90        self.child.dispatch_event(event, cx)
 91    }
 92
 93    fn debug(
 94        &self,
 95        bounds: RectF,
 96        _: &Self::LayoutState,
 97        _: &Self::PaintState,
 98        cx: &DebugContext,
 99    ) -> serde_json::Value {
100        json!({
101            "bounds": bounds.to_json(),
102            "font_family": cx.font_cache.family_name(self.family_id).unwrap(),
103            "font_size": self.font_size,
104            "font_properties": self.font_properties.to_json(),
105            "child": self.child.debug(cx),
106        })
107    }
108}