Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions engine/core/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ use crate::text::Fonts;
use crate::tree::{LayoutRect, Tree};

/// Measure context attached to text leaves (taffy NodeContext).
///
/// Deliberately minimal: the solve-time measure closure reads only `size`,
/// and shaping happens once in `MeasureCtx::shaped` (build/restyle) against
/// the freshly collected run — storing slot/tracking/line_height here (or
/// the run itself) would be dead weight duplicated per text node.
pub struct MeasureCtx {
pub text: String,
pub slot: u8,
pub tracking: f32,
/// NAN = atlas default.
pub line_height: f32,
/// Shaped size, computed ONCE when the context is (re)built. Text
/// shaping is the expensive half of layout on the PSP; the taffy
/// measure closure must never re-shape per solve pass.
Expand All @@ -38,14 +38,14 @@ pub struct MeasureCtx {
impl MeasureCtx {
fn shaped(
fonts: &Fonts,
text: String,
text: &str,
slot: u8,
tracking: f32,
line_height: f32,
native: bool,
) -> MeasureCtx {
let size = fonts.measure_run_provider(native, &text, slot, tracking, line_height);
MeasureCtx { text, slot, tracking, line_height, size }
let size = fonts.measure_run_provider(native, text, slot, tracking, line_height);
MeasureCtx { size }
}
}

Expand Down Expand Up @@ -265,7 +265,7 @@ fn build(
tree.slots[slot as usize].text_native = native;
let ctx = MeasureCtx::shaped(
fonts,
run,
&run,
resolved.font_slot as u8,
resolved.tracking,
resolved.line_height,
Expand All @@ -275,9 +275,10 @@ fn build(
tree.slots[slot as usize].taffy = Some(nid);
return Some(nid);
}
let children = tree.slots[slot as usize].children.clone();
let mut kids: Vec<taffy::NodeId> = Vec::with_capacity(children.len());
for c in children {
let child_count = tree.slots[slot as usize].children.len();
let mut kids: Vec<taffy::NodeId> = Vec::with_capacity(child_count);
for i in 0..child_count {
let c = tree.slots[slot as usize].children[i];
if let Some(cs) = tree.resolve(c) {
if let Some(k) = build(tree, styles, fonts, taffy, cs, in_transform) {
kids.push(k);
Expand Down Expand Up @@ -389,7 +390,7 @@ pub fn relayout_root(
tree.slots[slot as usize].text_native = native;
let ctx = MeasureCtx::shaped(
fonts,
run,
&run,
resolved.font_slot as u8,
resolved.tracking,
resolved.line_height,
Expand Down
8 changes: 2 additions & 6 deletions engine/core/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,7 @@ impl Tree {
pub fn collect_subtree(&self, id: i32, out: &mut Vec<u32>) {
let Some(slot) = self.resolve(id) else { return };
out.push(slot);
// Children Vec is cloned per level to keep borrowck simple; subtree
// destruction is not a per-frame hot path.
let children = self.slots[slot as usize].children.clone();
for c in children {
for &c in &self.slots[slot as usize].children {
self.collect_subtree(c, out);
}
}
Expand All @@ -333,8 +330,7 @@ impl Tree {
pub fn collect_run(&self, slot: u32, out: &mut String) {
let node = &self.slots[slot as usize];
out.push_str(&node.text);
let children = node.children.clone();
for c in children {
for &c in &node.children {
if let Some(cs) = self.resolve(c) {
if self.slots[cs as usize].node_type == spec::NodeType::Text as u8 {
self.collect_run(cs, out);
Expand Down