fix(render): lay out text nodes in taffy and implement inline flow

This commit is contained in:
SGavrl committed 2026-07-02 20:02:07 +00:00
1 parent 193e30deb5
commit 9c8d62e13b
4 files changed
+41 -6

No files matched your search

+19
View File
@@ -140,6 +140,25 @@ fn build(
styles: &HashMap<NodeId, crate::LayoutStyle>, styles: &HashMap<NodeId, crate::LayoutStyle>,
) -> Option<taffy::NodeId> { ) -> Option<taffy::NodeId> {
let node = tree.get_node(id)?; let node = tree.get_node(id)?;
if let obscura_dom::tree::NodeData::Text { contents } = &node.data {
let text = contents.trim();
if text.is_empty() {
return None;
}
let width = text.chars().count() as f32 * 9.0;
let style = taffy::Style {
size: taffy::Size {
width: taffy::Dimension::Length(width),
height: taffy::Dimension::Length(19.0),
},
..Default::default()
};
let taffy_id = taffy_tree.new_leaf(style).ok()?;
id_map.insert(taffy_id, id);
return Some(taffy_id);
}
let _name = node.as_element()?; let _name = node.as_element()?;
let style = styles.get(&id)?; let style = styles.get(&id)?;
let taffy_style = to_taffy_style(style); let taffy_style = to_taffy_style(style);
+6
View File
@@ -49,6 +49,7 @@ pub enum Display {
#[default] #[default]
Block, Block,
Flex, Flex,
Inline,
#[allow(dead_code)] #[allow(dead_code)]
None, None,
} }
@@ -144,8 +145,13 @@ pub(crate) fn to_taffy_style(style: &LayoutStyle) -> Style {
s.display = match style.display { s.display = match style.display {
Display::Block => taffy::style::Display::Block, Display::Block => taffy::style::Display::Block,
Display::Flex => taffy::style::Display::Flex, Display::Flex => taffy::style::Display::Flex,
Display::Inline => taffy::style::Display::Flex,
Display::None => taffy::style::Display::None, Display::None => taffy::style::Display::None,
}; };
if style.display == Display::Inline {
s.flex_direction = taffy::FlexDirection::Row;
}
s.flex_wrap = taffy::FlexWrap::Wrap;
s.size = taffy::Size { s.size = taffy::Size {
width: dimension(style.width), width: dimension(style.width),
height: dimension(style.height), height: dimension(style.height),
+10 -4
View File
@@ -117,17 +117,23 @@ fn paint_text_node(
) -> Option<()> { ) -> Option<()> {
let node = tree.get_node(nid)?; let node = tree.get_node(nid)?;
let text = match &node.data { let text = match &node.data {
obscura_dom::tree::NodeData::Text { contents } => contents, obscura_dom::tree::NodeData::Text { contents } => contents.trim(),
_ => return None, _ => return None,
}; };
if text.is_empty() {
return None;
}
// Find parent element to get geometry and color
let parent = node.parent?; let parent = node.parent?;
let rect = laid.rects.get(&parent)?;
let style = laid.styles.get(&parent)?; let style = laid.styles.get(&parent)?;
// Default color to black if not specified.
let color = style.color.unwrap_or([0, 0, 0, 255]); let color = style.color.unwrap_or([0, 0, 0, 255]);
// Get geometry of the text node itself!
let rect = match laid.rects.get(&nid) {
Some(r) => r,
None => return None,
};
// Paint text at rect.x, rect.y // Paint text at rect.x, rect.y
draw_text(pixmap, text, rect.x, rect.y, color); draw_text(pixmap, text, rect.x, rect.y, color);
Some(()) Some(())
+6 -2
View File
@@ -23,8 +23,11 @@ pub fn compute_style(tag: &str, inline_css: Option<&str>) -> LayoutStyle {
/// Built-in UA defaults. Inline elements currently map to block layout; real /// Built-in UA defaults. Inline elements currently map to block layout; real
/// inline/text layout arrives with the text/paint phase. /// inline/text layout arrives with the text/paint phase.
pub fn ua_style(tag: &str) -> LayoutStyle { pub fn ua_style(tag: &str) -> LayoutStyle {
let _ = tag; let display = match tag {
LayoutStyle { display: Display::Block, ..Default::default() } "span" | "a" | "b" | "i" | "strong" | "em" => Display::Inline,
_ => Display::Block,
};
LayoutStyle { display, ..Default::default() }
} }
pub fn apply_inline(style: &mut LayoutStyle, css: &str) { pub fn apply_inline(style: &mut LayoutStyle, css: &str) {
@@ -51,6 +54,7 @@ fn apply_value(style: &mut LayoutStyle, name: &str, value: &str) {
"display" => match value { "display" => match value {
"block" => style.display = Display::Block, "block" => style.display = Display::Block,
"flex" => style.display = Display::Flex, "flex" => style.display = Display::Flex,
"inline" => style.display = Display::Inline,
"none" => style.display = Display::None, "none" => style.display = Display::None,
_ => {} _ => {}
}, },