//! The trait render backends implement to consume a fragment tree. use std::error::Error; use std::fmt; use crate::display_list::{FragmentId, FragmentStore}; /// A renderer that can rasterize a fragment tree into its current target. /// /// How a backend acquires its target (a wgpu surface, a pixmap, …) is the /// backend's own affair, configured outside this trait; "render a fragment /// tree" is the only portable operation. pub trait RenderBackend { /// Render the tree rooted at `root` into the backend's target. /// /// The target is `width_px` × `height_px` physical pixels; `scale` is the /// logical-to-physical scale factor and is applied as the root transform, /// so fragment coordinates are in logical units. fn render( &mut self, root: FragmentId, store: &FragmentStore, width_px: u32, height_px: u32, scale: f64, ) -> Result<(), RenderError>; } /// Failure while rendering a fragment tree. #[derive(Debug)] pub enum RenderError { /// A fragment id in the tree does not exist in the store. MissingFragment(FragmentId), /// A fragment's display list has unbalanced push/pop items. UnbalancedFragment(FragmentId), /// Fragment nesting exceeded the depth limit, which almost always means /// the fragment graph contains a cycle. ExcessiveDepth(FragmentId), /// A backend-specific failure (device lost, surface error, …). Backend(Box), } impl fmt::Display for RenderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { RenderError::MissingFragment(id) => { write!(f, "fragment {id:?} is not present in the store") } RenderError::UnbalancedFragment(id) => { write!(f, "fragment {id:?} has unbalanced push/pop display items") } RenderError::ExcessiveDepth(id) => { write!( f, "fragment nesting exceeded the depth limit at {id:?}; the fragment graph likely contains a cycle" ) } RenderError::Backend(err) => write!(f, "render backend error: {err}"), } } } impl Error for RenderError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { RenderError::Backend(err) => Some(err.as_ref()), _ => None, } } }