use crate::color::Color; use crate::font::FaceId; use crate::geom::{Length, Path, Point, Size}; use crate::image::ImageId; use serde::{Deserialize, Serialize}; /// A finished layout with elements at fixed positions. #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Frame { /// The size of the frame. pub size: Size, /// The baseline of the frame measured from the top. pub baseline: Length, /// The elements composing this layout. pub elements: Vec<(Point, Element)>, } impl Frame { /// Create a new, empty frame. pub fn new(size: Size, baseline: Length) -> Self { assert!(size.is_finite()); Self { size, baseline, elements: vec![] } } /// Add an element at a position. pub fn push(&mut self, pos: Point, element: Element) { self.elements.push((pos, element)); } /// Add all elements of another frame, placing them relative to the given /// position. pub fn push_frame(&mut self, pos: Point, subframe: Self) { if pos == Point::zero() && self.elements.is_empty() { self.elements = subframe.elements; } else { for (subpos, element) in subframe.elements { self.push(pos + subpos, element); } } } } /// The building block frames are composed of. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Element { /// Shaped text. Text(Text), /// A filled geometric shape. Geometry(Shape, Fill), /// A raster image. Image(ImageId, Size), } /// A run of shaped text. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Text { /// The font face the glyphs are contained in. pub face_id: FaceId, /// The font size. pub size: Length, /// The glyph's fill color. pub fill: Fill, /// The glyphs. pub glyphs: Vec, } /// A glyph in a run of shaped text. #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub struct Glyph { /// The glyph's index in the face. pub id: u16, /// The advance width of the glyph. pub x_advance: Length, /// The horizontal offset of the glyph. pub x_offset: Length, } impl Text { /// Encode the glyph ids into a big-endian byte buffer. pub fn encode_glyphs_be(&self) -> Vec { let mut bytes = Vec::with_capacity(2 * self.glyphs.len()); for glyph in &self.glyphs { let id = glyph.id; bytes.push((id >> 8) as u8); bytes.push((id & 0xff) as u8); } bytes } } /// A geometric shape. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum Shape { /// A rectangle with its origin in the topleft corner. Rect(Size), /// An ellipse with its origin in the center. Ellipse(Size), /// A line to a `Point` (relative to its position) with a stroke width. Line(Point, Length), /// A bezier path. Path(Path), } /// How text and shapes are filled. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum Fill { /// A solid color. Color(Color), }