use crate::core::renderer; use crate::core::{Background, Color, Point, Rectangle, Transformation}; use crate::graphics::color; use crate::graphics::text::{Editor, Paragraph}; use crate::graphics::Mesh; use crate::image::{self, Image}; use crate::quad::{self, Quad}; use crate::text::{self, Text}; use crate::triangle; use std::cell::{self, RefCell}; use std::rc::Rc; pub enum Layer<'a> { Live(&'a Live), Cached(Transformation, cell::Ref<'a, Cached>), } pub enum LayerMut<'a> { Live(&'a mut Live), Cached(Transformation, cell::RefMut<'a, Cached>), } pub struct Stack { live: Vec, cached: Vec<(Transformation, Rc>)>, order: Vec, transformations: Vec, previous: Vec, current: usize, live_count: usize, } impl Stack { pub fn new() -> Self { Self { live: vec![Live::default()], cached: Vec::new(), order: vec![Kind::Live], transformations: vec![Transformation::IDENTITY], previous: Vec::new(), current: 0, live_count: 1, } } pub fn draw_quad(&mut self, quad: renderer::Quad, background: Background) { let transformation = self.transformations.last().unwrap(); let bounds = quad.bounds * *transformation; let quad = Quad { position: [bounds.x, bounds.y], size: [bounds.width, bounds.height], border_color: color::pack(quad.border.color), border_radius: quad.border.radius.into(), border_width: quad.border.width, shadow_color: color::pack(quad.shadow.color), shadow_offset: quad.shadow.offset.into(), shadow_blur_radius: quad.shadow.blur_radius, }; self.live[self.current].quads.add(quad, &background); } pub fn draw_paragraph( &mut self, paragraph: &Paragraph, position: Point, color: Color, clip_bounds: Rectangle, ) { let paragraph = Text::Paragraph { paragraph: paragraph.downgrade(), position, color, clip_bounds, transformation: self.transformations.last().copied().unwrap(), }; self.live[self.current].text.push(paragraph); } pub fn draw_editor( &mut self, editor: &Editor, position: Point, color: Color, clip_bounds: Rectangle, ) { let paragraph = Text::Editor { editor: editor.downgrade(), position, color, clip_bounds, transformation: self.transformation(), }; self.live[self.current].text.push(paragraph); } pub fn draw_text( &mut self, text: crate::core::Text, position: Point, color: Color, clip_bounds: Rectangle, ) { let transformation = self.transformation(); let paragraph = Text::Cached { content: text.content, bounds: Rectangle::new(position, text.bounds) * transformation, color, size: text.size * transformation.scale_factor(), line_height: text.line_height, font: text.font, horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, shaping: text.shaping, clip_bounds: clip_bounds * transformation, }; self.live[self.current].text.push(paragraph); } pub fn draw_image( &mut self, handle: crate::core::image::Handle, filter_method: crate::core::image::FilterMethod, bounds: Rectangle, ) { let image = Image::Raster { handle, filter_method, bounds: bounds * self.transformation(), }; self.live[self.current].images.push(image); } pub fn draw_svg( &mut self, handle: crate::core::svg::Handle, color: Option, bounds: Rectangle, ) { let svg = Image::Vector { handle, color, bounds: bounds * self.transformation(), }; self.live[self.current].images.push(svg); } pub fn draw_mesh(&mut self, mut mesh: Mesh) { match &mut mesh { Mesh::Solid { transformation, .. } | Mesh::Gradient { transformation, .. } => { *transformation = *transformation * self.transformation(); } } self.live[self.current].meshes.push(mesh); } pub fn draw_layer(&mut self, mut layer: Live) { layer.transformation = layer.transformation * self.transformation(); if self.live_count == self.live.len() { self.live.push(layer); } else { self.live[self.live_count] = layer; } self.live_count += 1; self.order.push(Kind::Live); } pub fn draw_cached_layer(&mut self, layer: &Rc>) { self.cached.push((self.transformation(), layer.clone())); self.order.push(Kind::Cache); } pub fn push_clip(&mut self, bounds: Option) { // self.previous.push(self.current); // self.order.push(Kind::Live); // self.current = self.live_count; // self.live_count += 1; // let bounds = bounds.map(|bounds| bounds * self.transformation()); // if self.current == self.live.len() { // self.live.push(Live { // bounds, // ..Live::default() // }); // } else { // self.live[self.current].bounds = bounds; // } } pub fn pop_clip(&mut self) { // self.current = self.previous.pop().unwrap(); } pub fn push_transformation(&mut self, transformation: Transformation) { self.transformations .push(self.transformation() * transformation); } pub fn pop_transformation(&mut self) { let _ = self.transformations.pop(); } fn transformation(&self) -> Transformation { self.transformations.last().copied().unwrap() } pub fn iter_mut(&mut self) -> impl Iterator> { dbg!(self.order.len()); let mut live = self.live.iter_mut(); let mut cached = self.cached.iter_mut(); self.order.iter().map(move |kind| match kind { Kind::Live => LayerMut::Live(live.next().unwrap()), Kind::Cache => { let (transformation, layer) = cached.next().unwrap(); let layer = layer.borrow_mut(); LayerMut::Cached(*transformation * layer.transformation, layer) } }) } pub fn iter(&self) -> impl Iterator> { let mut live = self.live.iter(); let mut cached = self.cached.iter(); self.order.iter().map(move |kind| match kind { Kind::Live => Layer::Live(live.next().unwrap()), Kind::Cache => { let (transformation, layer) = cached.next().unwrap(); let layer = layer.borrow(); Layer::Cached(*transformation * layer.transformation, layer) } }) } pub fn clear(&mut self) { for live in &mut self.live[..self.live_count] { live.bounds = None; live.transformation = Transformation::IDENTITY; live.quads.clear(); live.meshes.clear(); live.text.clear(); live.images.clear(); } self.current = 0; self.live_count = 1; self.order.clear(); self.order.push(Kind::Live); self.cached.clear(); self.previous.clear(); } } impl Default for Stack { fn default() -> Self { Self::new() } } #[derive(Default)] pub struct Live { pub bounds: Option, pub transformation: Transformation, pub quads: quad::Batch, pub meshes: triangle::Batch, pub text: text::Batch, pub images: image::Batch, } impl Live { pub fn into_cached(self) -> Cached { Cached { bounds: self.bounds, transformation: self.transformation, quads: quad::Cache::Staged(self.quads), meshes: triangle::Cache::Staged(self.meshes), text: text::Cache::Staged(self.text), images: self.images, } } } #[derive(Default)] pub struct Cached { pub bounds: Option, pub transformation: Transformation, pub quads: quad::Cache, pub meshes: triangle::Cache, pub text: text::Cache, pub images: image::Batch, } impl Cached { pub fn update(&mut self, live: Live) { self.bounds = live.bounds; self.quads.update(live.quads); self.meshes.update(live.meshes); self.text.update(live.text); self.images = live.images; } } enum Kind { Live, Cache, }