#[cfg(test)]
mod inline_intrinsic_width_tests {
use std::collections::BTreeMap;
use azul_core::{
dom::{Dom, DomId, FormattingContext, NodeType},
geom::{LogicalPosition, LogicalRect, LogicalSize},
styled_dom::StyledDom,
};
use azul_css::css::Css;
use crate::{
solver3::{
cache::LayoutCache,
layout_document,
LayoutError,
},
text3::cache::{FontManager, LayoutCache as TextLayoutCache},
};
use super::super::create_test_font_manager;
#[test]
fn test_inline_text_has_nonzero_intrinsic_width() {
let mut dom = Dom::create_body();
dom.add_child(Dom::create_text("Hello world"));
let mut styled_dom = StyledDom::create_node(&mut dom, Css::empty());
styled_dom.dom_id = DomId::ROOT_ID;
let viewport = LogicalRect {
origin: LogicalPosition::zero(),
size: LogicalSize::new(800.0, 600.0),
};
let mut layout_cache = LayoutCache {
tree: None,
calculated_positions: BTreeMap::new(),
viewport: None,
scroll_ids: BTreeMap::new(),
scroll_id_to_node_id: BTreeMap::new(),
counters: BTreeMap::new(),
float_cache: BTreeMap::new(),
cache_map: Default::default(),
};
let mut text_cache = TextLayoutCache::new();
let font_manager = create_test_font_manager().expect("Failed to create font manager");
let scroll_offsets = BTreeMap::new();
let selections = BTreeMap::new();
let text_selections = BTreeMap::new();
let mut debug_messages = None;
let result = layout_document(
&mut layout_cache,
&mut text_cache,
styled_dom,
viewport,
&font_manager,
&scroll_offsets,
&selections,
&text_selections,
&mut debug_messages,
None,
&azul_core::resources::RendererResources::default(),
azul_core::resources::IdNamespace(0),
DomId::ROOT_ID,
true, None, None, );
assert!(
result.is_ok(),
"Layout should succeed: {:?}",
result.err()
);
let tree = layout_cache.tree.as_ref()
.expect("Layout tree should exist after layout");
eprintln!("\nLAYOUT TREE");
for (idx, node) in tree.nodes.iter().enumerate() {
eprintln!("Node {}: {:?}", idx, node.dom_node_id);
eprintln!(" Formatting Context: {:?}", node.formatting_context);
eprintln!(" Intrinsic sizes: {:?}", node.intrinsic_sizes);
eprintln!(" Used size: {:?}", node.used_size);
eprintln!(" Children: {:?}", node.children);
}
let mut found_inline_with_zero_intrinsic = false;
let mut found_inline_with_nonzero_intrinsic = false;
for (idx, node) in tree.nodes.iter().enumerate() {
if let Some(intrinsic) = &node.intrinsic_sizes {
if matches!(node.formatting_context, FormattingContext::Inline) {
eprintln!("\nFound INLINE node at index {}", idx);
eprintln!(" max_content_width: {}", intrinsic.max_content_width);
eprintln!(" min_content_width: {}", intrinsic.min_content_width);
if intrinsic.max_content_width > 0.0 {
found_inline_with_nonzero_intrinsic = true;
} else {
found_inline_with_zero_intrinsic = true;
}
}
}
}
assert!(
!found_inline_with_zero_intrinsic,
"BUG DETECTED: Inline nodes with text have zero intrinsic width! \
This violates CSS Sizing Level 3 and causes incorrect line breaking."
);
assert!(
found_inline_with_nonzero_intrinsic,
"Expected to find at least one inline node with non-zero intrinsic width"
);
}
#[test]
fn test_inline_child_gets_correct_available_width_in_bfc() {
let mut dom = Dom::create_body();
dom.add_child(Dom::create_text("Test text that should wrap properly"));
let mut styled_dom = StyledDom::create_node(&mut dom, Css::empty());
styled_dom.dom_id = DomId::ROOT_ID;
let viewport = LogicalRect {
origin: LogicalPosition::zero(),
size: LogicalSize::new(400.0, 600.0), };
let mut layout_cache = LayoutCache {
tree: None,
calculated_positions: BTreeMap::new(),
viewport: None,
scroll_ids: BTreeMap::new(),
scroll_id_to_node_id: BTreeMap::new(),
counters: BTreeMap::new(),
float_cache: BTreeMap::new(),
cache_map: Default::default(),
};
let mut text_cache = TextLayoutCache::new();
let font_manager = create_test_font_manager().expect("Failed to create font manager");
let scroll_offsets = BTreeMap::new();
let selections = BTreeMap::new();
let text_selections = BTreeMap::new();
let mut debug_messages = Some(Vec::new());
let result = layout_document(
&mut layout_cache,
&mut text_cache,
styled_dom,
viewport,
&font_manager,
&scroll_offsets,
&selections,
&text_selections,
&mut debug_messages,
None,
&azul_core::resources::RendererResources::default(),
azul_core::resources::IdNamespace(0),
DomId::ROOT_ID,
true, None, None, azul_core::task::GetSystemTimeCallback { cb: azul_core::task::get_system_time_libstd },
);
assert!(result.is_ok(), "Layout should succeed");
if let Some(messages) = debug_messages {
eprintln!("\nDEBUG MESSAGES");
for msg in &messages {
eprintln!("{}", msg.message);
}
let has_zero_width_bug = messages.iter().any(|msg| {
msg.message.contains("available_width=0") &&
!msg.message.contains("available_width=0.0") && msg.message.contains("Inline")
});
assert!(
!has_zero_width_bug,
"BUG DETECTED: Inline elements are receiving available_width=0! \
This causes all characters to break onto separate lines."
);
}
let tree = layout_cache.tree.as_ref().expect("Layout tree should exist");
for (idx, node) in tree.nodes.iter().enumerate() {
if let Some(intrinsic) = &node.intrinsic_sizes {
if matches!(node.formatting_context, FormattingContext::Inline) {
eprintln!("Inline node {} intrinsic: max={}, min={}",
idx, intrinsic.max_content_width, intrinsic.min_content_width);
assert!(
intrinsic.max_content_width > 0.0,
"Inline node {} has zero max_content_width - violates CSS Sizing Level 3",
idx
);
}
}
}
}
}