use crate::core::image;
use crate::core::renderer::Quad;
use crate::core::svg;
use crate::core::{Background, Color, Point, Rectangle, Transformation};
use crate::graphics::layer;
use crate::graphics::text::{Editor, Paragraph, Text};
use crate::graphics::{self, Image};
use crate::Primitive;
use std::rc::Rc;
pub type Stack = layer::Stack<Layer>;
#[derive(Debug, Clone)]
pub struct Layer {
pub bounds: Rectangle,
pub quads: Vec<(Quad, Background)>,
pub primitives: Vec<Item<Primitive>>,
pub text: Vec<Item<Text>>,
pub images: Vec<Image>,
}
#[derive(Debug, Clone)]
pub enum Item<T> {
Live(T),
Group(Vec<T>, Rectangle, Transformation),
Cached(Rc<[T]>, Rectangle, Transformation),
}
impl<T> Item<T> {
pub fn transformation(&self) -> Transformation {
match self {
Item::Live(_) => Transformation::IDENTITY,
Item::Group(_, _, transformation)
| Item::Cached(_, _, transformation) => *transformation,
}
}
pub fn clip_bounds(&self) -> Rectangle {
match self {
Item::Live(_) => Rectangle::INFINITE,
Item::Group(_, clip_bounds, _)
| Item::Cached(_, clip_bounds, _) => *clip_bounds,
}
}
pub fn as_slice(&self) -> &[T] {
match self {
Item::Live(item) => std::slice::from_ref(item),
Item::Group(group, _, _) => group.as_slice(),
Item::Cached(cache, _, _) => cache,
}
}
}
impl Layer {
pub fn draw_quad(
&mut self,
mut quad: Quad,
background: Background,
transformation: Transformation,
) {
quad.bounds = quad.bounds * transformation;
self.quads.push((quad, background));
}
pub fn draw_paragraph(
&mut self,
paragraph: &Paragraph,
position: Point,
color: Color,
clip_bounds: Rectangle,
transformation: Transformation,
) {
let paragraph = Text::Paragraph {
paragraph: paragraph.downgrade(),
position,
color,
clip_bounds,
transformation,
};
self.text.push(Item::Live(paragraph));
}
pub fn draw_editor(
&mut self,
editor: &Editor,
position: Point,
color: Color,
clip_bounds: Rectangle,
transformation: Transformation,
) {
let editor = Text::Editor {
editor: editor.downgrade(),
position,
color,
clip_bounds,
transformation,
};
self.text.push(Item::Live(editor));
}
pub fn draw_text(
&mut self,
text: crate::core::Text,
position: Point,
color: Color,
clip_bounds: Rectangle,
transformation: Transformation,
) {
let text = Text::Cached {
content: text.content,
bounds: Rectangle::new(position, text.bounds) * transformation,
color,
size: text.size * transformation.scale_factor(),
line_height: text.line_height.to_absolute(text.size)
* transformation.scale_factor(),
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
clip_bounds: clip_bounds * transformation,
};
self.text.push(Item::Live(text));
}
pub fn draw_text_group(
&mut self,
text: Vec<Text>,
clip_bounds: Rectangle,
transformation: Transformation,
) {
self.text
.push(Item::Group(text, clip_bounds, transformation));
}
pub fn draw_text_cache(
&mut self,
text: Rc<[Text]>,
clip_bounds: Rectangle,
transformation: Transformation,
) {
self.text
.push(Item::Cached(text, clip_bounds, transformation));
}
pub fn draw_image(
&mut self,
handle: image::Handle,
filter_method: image::FilterMethod,
bounds: Rectangle,
transformation: Transformation,
) {
let image = Image::Raster {
handle,
filter_method,
bounds: bounds * transformation,
};
self.images.push(image);
}
pub fn draw_svg(
&mut self,
handle: svg::Handle,
color: Option<Color>,
bounds: Rectangle,
transformation: Transformation,
) {
let svg = Image::Vector {
handle,
color,
bounds: bounds * transformation,
};
self.images.push(svg);
}
pub fn draw_primitive_group(
&mut self,
primitives: Vec<Primitive>,
clip_bounds: Rectangle,
transformation: Transformation,
) {
self.primitives.push(Item::Group(
primitives,
clip_bounds,
transformation,
));
}
pub fn draw_primitive_cache(
&mut self,
primitives: Rc<[Primitive]>,
clip_bounds: Rectangle,
transformation: Transformation,
) {
self.primitives.push(Item::Cached(
primitives,
clip_bounds,
transformation,
));
}
}
impl Default for Layer {
fn default() -> Self {
Self {
bounds: Rectangle::INFINITE,
quads: Vec::new(),
primitives: Vec::new(),
text: Vec::new(),
images: Vec::new(),
}
}
}
impl graphics::Layer for Layer {
fn with_bounds(bounds: Rectangle) -> Self {
Self {
bounds,
..Self::default()
}
}
fn flush(&mut self) {}
fn resize(&mut self, bounds: graphics::core::Rectangle) {
self.bounds = bounds;
}
fn reset(&mut self) {
self.bounds = Rectangle::INFINITE;
self.quads.clear();
self.text.clear();
self.primitives.clear();
self.images.clear();
}
}