#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
mod annotated_text;
mod ascii_glyphs;
pub mod debug_toggles;
pub mod dev_overlay;
mod direct_mapped_cache;
pub const FRAME_CLEAR_COLOR: [f32; 4] = [18.0 / 255.0, 18.0 / 255.0, 24.0 / 255.0, 1.0];
pub mod brush_sampling;
mod font_features;
pub mod font_layout;
pub mod font_source;
mod font_tracking;
mod full_glyph_count;
pub mod geometry;
pub mod gpos_kerning;
pub mod graph;
mod graph_hash;
pub mod graph_scene;
pub mod hit_graph;
pub mod image_compare;
#[cfg(feature = "installed-fonts")]
pub mod installed_fonts;
pub mod layer_composition;
mod layer_recycling;
pub mod layer_shadow;
pub mod layer_transform;
pub mod primitive_emit;
pub mod raster_cache;
pub mod render_contract;
pub mod scene_builder;
pub mod shape_sdf;
pub mod software_text_raster;
pub mod style_shared;
mod text_cache_key;
pub mod text_hyphenation;
pub mod text_mask_gamma;
pub mod text_measure;
pub mod text_paint;
#[cfg(feature = "text-shaping")]
mod text_shaping;
mod thread_state;
#[cfg(test)]
#[path = "tests/pointer_slices.rs"]
mod pointer_slices;
use cranpose_core::{MemoryApplier, collections::map::HashSet};
use cranpose_foundation::nodes::input::PointerEvent;
use cranpose_ui::LayoutTree;
pub use cranpose_ui_graphics::Brush;
use cranpose_ui_graphics::Size;
#[derive(Clone, Copy, Debug, Default)]
pub struct SceneUpdates<'a> {
pub content: &'a [cranpose_core::NodeId],
pub layers: &'a [cranpose_core::NodeId],
pub moved: &'a [cranpose_core::NodeId],
}
impl<'a> SceneUpdates<'a> {
pub const fn content(nodes: &'a [cranpose_core::NodeId]) -> Self {
Self {
content: nodes,
layers: &[],
moved: &[],
}
}
pub const fn is_empty(self) -> bool {
self.content.is_empty() && self.layers.is_empty() && self.moved.is_empty()
}
}
pub trait HitTestTarget {
fn dispatch(&self, event: PointerEvent);
fn dispatch_with_applier(&self, _applier: &mut MemoryApplier, event: PointerEvent) {
self.dispatch(event);
}
fn node_id(&self) -> cranpose_core::NodeId;
fn pointer_icon(&self) -> Option<cranpose_ui_graphics::PointerIcon> {
None
}
fn capture_path(&self) -> Vec<cranpose_core::NodeId> {
vec![self.node_id()]
}
}
pub trait RenderScene {
type HitTarget: HitTestTarget + Clone;
fn clear(&mut self);
fn hit_test(&self, x: f32, y: f32) -> Vec<Self::HitTarget>;
fn hit_test_near(&self, _x: f32, _y: f32) -> Option<Self::HitTarget> {
None
}
fn hit_test_nodes(&self, x: f32, y: f32) -> Vec<cranpose_core::NodeId> {
self.hit_test(x, y)
.into_iter()
.map(|h| h.node_id())
.collect()
}
fn find_target(&self, node_id: cranpose_core::NodeId) -> Option<Self::HitTarget>;
fn collect_retained_visual_observation_nodes(
&self,
nodes: &mut HashSet<cranpose_core::NodeId>,
) -> bool {
nodes.clear();
false
}
}
pub trait Renderer {
type Scene: RenderScene;
type Error;
fn attach_app_context_services(&mut self, _app_context: &cranpose_ui::AppContext) {}
fn apply_installed_fonts(&mut self, _app_context: &cranpose_ui::AppContext) {}
fn set_root_scale(&mut self, _scale: f32) {}
fn scene(&self) -> &Self::Scene;
fn scene_mut(&mut self) -> &mut Self::Scene;
fn rebuild_scene(
&mut self,
layout_tree: &LayoutTree,
viewport: Size,
) -> Result<(), Self::Error>;
fn rebuild_scene_from_applier(
&mut self,
applier: &mut cranpose_core::MemoryApplier,
root: cranpose_core::NodeId,
viewport: Size,
) -> Result<(), Self::Error>;
fn update_scene_from_applier(
&mut self,
applier: &mut cranpose_core::MemoryApplier,
root: cranpose_core::NodeId,
viewport: Size,
updates: SceneUpdates<'_>,
) -> Result<(), Self::Error> {
let _ = updates;
self.rebuild_scene_from_applier(applier, root, viewport)
}
fn update_visual_scene_from_applier(
&mut self,
applier: &mut cranpose_core::MemoryApplier,
root: cranpose_core::NodeId,
viewport: Size,
updates: SceneUpdates<'_>,
) -> Result<(), Self::Error> {
self.update_scene_from_applier(applier, root, viewport, updates)
}
fn draw_dev_overlay(&mut self, _text: &str, _viewport: Size) {}
fn set_inspector_overlay(&mut self, _graph: Option<graph::RenderGraph>) {}
fn needs_frame_warmup(&self) -> bool {
false
}
fn awaits_pipelines(&self) -> bool {
false
}
}