#![allow(non_snake_case)]
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use repose_core::*;
use repose_tree::{NodeId, TreeStats, ViewTree};
use rustc_hash::FxHashMap;
use taffy::TaffyTree;
#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct TextBaselines {
pub(crate) first: f32,
pub(crate) last: f32,
pub(crate) content_h: f32,
}
pub(crate) struct ScopeLayoutTree {
pub(crate) taffy: TaffyTree<NodeContext>,
pub(crate) taffy_map: FxHashMap<NodeId, taffy::NodeId>,
pub(crate) reverse_map: FxHashMap<taffy::NodeId, NodeId>,
pub(crate) root_taffy_id: Option<taffy::NodeId>,
pub(crate) last_constraints:
Option<(taffy::Size<Option<f32>>, taffy::Size<taffy::AvailableSpace>)>,
pub(crate) cached_size: Option<taffy::Size<f32>>,
pub(crate) text_cache: FxHashMap<NodeId, TextLayout>,
pub(crate) valid: bool,
pub(crate) baseline_map: FxHashMap<NodeId, TextBaselines>,
pub(crate) baseline_shifts: FxHashMap<NodeId, f32>,
}
impl ScopeLayoutTree {
pub(crate) fn new() -> Self {
Self {
taffy: TaffyTree::new(),
taffy_map: FxHashMap::default(),
reverse_map: FxHashMap::default(),
root_taffy_id: None,
last_constraints: None,
cached_size: None,
text_cache: FxHashMap::default(),
valid: false,
baseline_map: FxHashMap::default(),
baseline_shifts: FxHashMap::default(),
}
}
}
pub struct LayoutEngine {
pub(crate) tree: ViewTree,
pub(crate) taffy: TaffyTree<NodeContext>,
pub(crate) taffy_map: FxHashMap<NodeId, taffy::NodeId>,
pub(crate) reverse_map: FxHashMap<taffy::NodeId, NodeId>,
pub(crate) scope_trees: HashMap<String, ScopeLayoutTree>,
pub(crate) scope_root_map: FxHashMap<NodeId, String>,
pub(crate) node_to_scope: FxHashMap<NodeId, String>,
pub(crate) text_cache: FxHashMap<NodeId, TextLayout>,
pub(crate) baseline_map: FxHashMap<NodeId, TextBaselines>,
pub(crate) baseline_shifts: FxHashMap<NodeId, f32>,
pub(crate) last_size_px: Option<(u32, u32)>,
pub(crate) layout_valid: bool,
pub(crate) paint_cache: FxHashMap<NodeId, PaintCacheEntry>,
pub stats: LayoutStats,
pub(crate) prev_focused: Option<u64>,
pub(crate) focus_callbacks: FxHashMap<u64, Rc<dyn Fn(bool)>>,
pub(crate) last_locals_stamp: Option<u64>,
pub(crate) view_ids: FxHashMap<NodeId, u64>,
pub(crate) next_view_id: u64,
pub(crate) layer_id_counter: u32,
pub(crate) prev_observed_rects: FxHashMap<u64, repose_core::Rect>,
pub(crate) focus_group_stack: Vec<u64>,
pub(crate) focus_interaction_sources: FxHashMap<u64, InteractionSource>,
}
#[derive(Clone, Debug, Default)]
pub struct LayoutStats {
pub tree: TreeStats,
pub taffy_created: usize,
pub taffy_reused: usize,
pub layout_hits: usize,
pub layout_misses: usize,
pub paint_cache_hits: usize,
pub paint_cache_misses: usize,
pub paint_culled: usize,
pub layout_time_ms: f32,
pub paint_time_ms: f32,
}
#[derive(Clone)]
pub(crate) struct PaintCacheEntry {
pub(crate) subtree_hash: u64,
pub(crate) stamp: u64,
pub(crate) rect: repose_core::Rect,
pub(crate) parent_offset_px: (f32, f32),
pub(crate) sem_parent: Option<u64>,
pub(crate) alpha_q: u8,
pub(crate) nodes: Rc<Vec<SceneNode>>,
pub(crate) hits: Rc<Vec<HitRegion>>,
pub(crate) sems: Rc<Vec<SemNode>>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IntrinsicSizeMode {
MinContent,
MaxContent,
}
#[derive(Clone)]
pub(crate) enum NodeContext {
Text {
text: String,
font_dp: f32,
soft_wrap: bool,
max_lines: Option<usize>,
overflow: TextOverflow,
font_family: Option<&'static str>,
font_weight: FontWeight,
font_style: FontStyle,
letter_spacing: f32,
line_height: f32,
font_variation_settings: Option<Arc<str>>,
annotations: Option<Arc<[TextSpan]>>,
},
Container,
ScrollContainer,
TextInput {
multiline: bool,
},
}
#[derive(Clone)]
pub(crate) struct TextLayout {
pub(crate) lines: Vec<String>,
pub(crate) line_ranges: Vec<(usize, usize)>,
pub(crate) size_px: f32,
pub(crate) line_h_px: f32,
pub(crate) line_widths: Vec<f32>,
pub(crate) line_heights: Vec<f32>,
}