#![warn(missing_docs)]
use super::graphics::RenderingCache;
use super::items::*;
use crate::component::ComponentRc;
use crate::graphics::Point;
use crate::item_tree::ItemVisitorResult;
use core::pin::Pin;
use std::cell::{Cell, RefCell};
#[derive(Default, Debug)]
#[repr(C)]
pub struct CachedRenderingData {
pub(crate) cache_index: Cell<usize>,
pub(crate) cache_ok: Cell<bool>,
}
impl CachedRenderingData {
pub fn ensure_up_to_date<T: Clone>(
&self,
cache: &mut RenderingCache<T>,
update_fn: impl FnOnce() -> T,
) -> T {
if self.cache_ok.get() {
let index = self.cache_index.get();
let existing_entry = cache.get_mut(index).unwrap();
if existing_entry.dependency_tracker.is_dirty() {
existing_entry.data = existing_entry.dependency_tracker.as_ref().evaluate(update_fn)
}
existing_entry.data.clone()
} else {
self.cache_index.set(cache.insert(crate::graphics::CachedGraphicsData::new(update_fn)));
self.cache_ok.set(true);
cache.get(self.cache_index.get()).unwrap().data.clone()
}
}
pub fn release<T>(&self, cache: &mut RenderingCache<T>) {
if self.cache_ok.get() {
let index = self.cache_index.get();
cache.remove(index);
}
}
}
pub fn render_component_items(
component: &ComponentRc,
renderer: &mut dyn ItemRenderer,
origin: crate::graphics::Point,
) {
let renderer = RefCell::new(renderer);
crate::item_tree::visit_items_with_post_visit(
component,
crate::item_tree::TraversalOrder::BackToFront,
|_, item, _, translation| {
renderer.borrow_mut().save_state();
item.as_ref()
.render(*translation, &mut (*renderer.borrow_mut() as &mut dyn ItemRenderer));
let origin = item.as_ref().geometry().origin;
let translation = *translation + euclid::Vector2D::new(origin.x, origin.y);
(ItemVisitorResult::Continue(translation), ())
},
|_, _, _| {
renderer.borrow_mut().restore_state();
},
origin,
);
}
#[allow(missing_docs)]
pub trait ItemRenderer {
fn draw_rectangle(&mut self, pos: Point, rect: Pin<&Rectangle>);
fn draw_border_rectangle(&mut self, pos: Point, rect: Pin<&BorderRectangle>);
fn draw_image(&mut self, pos: Point, image: Pin<&Image>);
fn draw_clipped_image(&mut self, pos: Point, image: Pin<&ClippedImage>);
fn draw_text(&mut self, pos: Point, text: Pin<&Text>);
fn draw_text_input(&mut self, pos: Point, text_input: Pin<&TextInput>);
fn draw_path(&mut self, pos: Point, path: Pin<&Path>);
fn draw_box_shadow(&mut self, pos: Point, box_shadow: Pin<&BoxShadow>);
fn combine_clip(&mut self, pos: Point, clip: Pin<&Clip>);
fn save_state(&mut self);
fn restore_state(&mut self);
fn scale_factor(&self) -> f32;
fn draw_cached_pixmap(
&mut self,
item_cache: &CachedRenderingData,
pos: Point,
update_fn: &dyn Fn(&mut dyn FnMut(u32, u32, &[u8])),
);
fn as_any(&mut self) -> &mut dyn core::any::Any;
}