tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 788HTML 740Markdown 12TOML 62536 Definiciones

⎇ c2db86dfc600067c6f4d70c8ea398cbcc5d42dbd src/debug.rs Rust · 130 líneas · 4.0 KB Historia Quién tocó qué crudo

CSS Grid Benchmarks (#340) 1624a68d7 · Nico Burns ·

1use core::fmt::{Debug, Display, Write};
2use slotmap::Key;
3use std::sync::Mutex;
4
5use crate::node::Node;
6use crate::style;
7use crate::tree::LayoutTree;
8
9/// Prints a debug representation of the computed layout for a tree of nodes, starting with the passed root node.
10pub fn print_tree(tree: &impl LayoutTree, root: Node) {
11    println!("TREE");
12    print_node(tree, root, false, String::new());
13}
14
15fn print_node(tree: &impl LayoutTree, node: Node, has_sibling: bool, lines_string: String) {
16    let layout = tree.layout(node);
17    let style = tree.style(node);
18
19    let num_children = tree.child_count(node);
20
21    let display = match (num_children, style.display) {
22        (_, style::Display::None) => "NONE",
23        (0, _) => "LEAF",
24        (_, style::Display::Flex) => "FLEX",
25        #[cfg(feature = "grid")]
26        (_, style::Display::Grid) => "GRID",
27    };
28
29    let fork_string = if has_sibling { "├── " } else { "└── " };
30    println!(
31        "{lines}{fork} {display} [x: {x:<4} y: {y:<4} width: {width:<4} height: {height:<4}] ({key:?})",
32        lines = lines_string,
33        fork = fork_string,
34        display = display,
35        x = layout.location.x,
36        y = layout.location.y,
37        width = layout.size.width,
38        height = layout.size.height,
39        key = node.data(),
40    );
41    let bar = if has_sibling { "│   " } else { "    " };
42    let new_string = lines_string + bar;
43
44    // Recurse into children
45    for (index, child) in tree.children(node).enumerate() {
46        let has_sibling = index < num_children - 1;
47        print_node(tree, *child, has_sibling, new_string.clone());
48    }
49}
50
51#[doc(hidden)]
52pub struct DebugLogger {
53    stack: Mutex<Vec<String>>,
54}
55
56static EMPTY_STRING: String = String::new();
57impl DebugLogger {
58    pub const fn new() -> Self {
59        Self { stack: Mutex::new(Vec::new()) }
60    }
61
62    pub fn push_node(&self, new_key: impl Key) {
63        let mut stack = self.stack.lock().unwrap();
64        let mut key_string = String::new();
65        write!(&mut key_string, "{:?}", new_key.data()).unwrap();
66        stack.push(key_string);
67    }
68
69    pub fn pop_node(&self) {
70        let mut stack = self.stack.lock().unwrap();
71        stack.pop();
72    }
73
74    pub fn log(&self, message: impl Display) {
75        let stack = self.stack.lock().unwrap();
76        let key = stack.last().unwrap_or(&EMPTY_STRING);
77        let level = stack.len() * 4;
78        let space = " ";
79        println!("{space:level$}{key}: {message}");
80    }
81
82    pub fn labelled_log(&self, label: &str, message: impl Display) {
83        let stack = self.stack.lock().unwrap();
84        let key = stack.last().unwrap_or(&EMPTY_STRING);
85        let level = stack.len() * 4;
86        let space = " ";
87        println!("{space:level$}{key}: {label} {message}");
88    }
89
90    pub fn debug_log(&self, message: impl Debug) {
91        let stack = self.stack.lock().unwrap();
92        let key = stack.last().unwrap_or(&EMPTY_STRING);
93        let level = stack.len() * 4;
94        let space = " ";
95        println!("{space:level$}{key}: {message:?}");
96    }
97
98    pub fn labelled_debug_log(&self, label: &str, message: impl Debug) {
99        let stack = self.stack.lock().unwrap();
100        let key = stack.last().unwrap_or(&EMPTY_STRING);
101        let level = stack.len() * 4;
102        let space = " ";
103        println!("{space:level$}{key}: {label} {message:?}");
104    }
105}
106
107#[cfg(any(feature = "debug", feature = "profile"))]
108pub(crate) static NODE_LOGGER: DebugLogger = DebugLogger::new();
109
110#[cfg(feature = "profile")]
111#[allow(unused_macros)]
112macro_rules! time {
113    ($label:expr, $($code:tt)*) => {
114        let start = ::std::time::Instant::now();
115        $($code)*
116        let duration = ::std::time::Instant::now().duration_since(start);
117        crate::debug::NODE_LOGGER.log(format_args!("Performed {} in {}ms", $label, duration.as_millis()));
118    };
119}
120
121#[cfg(not(feature = "profile"))]
122#[allow(unused_macros)]
123macro_rules! time {
124    ($label:expr, $($code:tt)*) => {
125        $($code)*
126    };
127}
128
129#[allow(unused_imports)]
130pub(crate) use time;