render: correct list and mixed float geometry
This commit is contained in:
1 parent
3863833ca4
commit
eff74fc38c
3 files changed
+90
-7
No files matched your search
@@ -146,6 +146,7 @@ pub(crate) fn resolve_translate(d: crate::Dimension, basis: f32) -> f32 {
|
|||||||
crate::Dimension::Px(px) => px,
|
crate::Dimension::Px(px) => px,
|
||||||
crate::Dimension::Percent(p) => p * basis,
|
crate::Dimension::Percent(p) => p * basis,
|
||||||
crate::Dimension::Em(v) | crate::Dimension::Rem(v) => v * 16.0,
|
crate::Dimension::Em(v) | crate::Dimension::Rem(v) => v * 16.0,
|
||||||
|
crate::Dimension::Ex(v) => v * 16.0 * 0.528_320_3,
|
||||||
crate::Dimension::Vw(v)
|
crate::Dimension::Vw(v)
|
||||||
| crate::Dimension::Vh(v)
|
| crate::Dimension::Vh(v)
|
||||||
| crate::Dimension::Vmin(v)
|
| crate::Dimension::Vmin(v)
|
||||||
@@ -2860,10 +2861,76 @@ fn build_children_with_float_zone(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if float_count >= 2 {
|
if float_count >= 2 {
|
||||||
let run_children: Vec<taffy::NodeId> = dom_children[float_idx..run_end]
|
let mut run_children: Vec<taffy::NodeId> = dom_children[float_idx..run_end]
|
||||||
.iter()
|
.iter()
|
||||||
|
// Formatting whitespace between floats does not generate an
|
||||||
|
// in-flow flex item or consume horizontal space.
|
||||||
|
.filter(|&&cid| styles.get(&cid).and_then(|s| s.float) == float_side)
|
||||||
.flat_map(|&cid| build_any(tree, cid, taffy_tree, id_map, words, engine, ifc_items, styles))
|
.flat_map(|&cid| build_any(tree, cid, taffy_tree, id_map, words, engine, ifc_items, styles))
|
||||||
.collect();
|
.collect();
|
||||||
|
// A common navigation-bar shape is a run of left floats followed by
|
||||||
|
// one right float. The right float still scans the current float band:
|
||||||
|
// it does not start a new row merely because multiple left floats
|
||||||
|
// precede it. Keep the run in one wrapping row and use an auto inline
|
||||||
|
// margin to reserve all remaining space before the opposing float.
|
||||||
|
//
|
||||||
|
// This stays deliberately narrower than a general float manager. In
|
||||||
|
// particular, multiple right floats have reverse source-order
|
||||||
|
// placement semantics and need their own representation.
|
||||||
|
let trailing_right = (float_side == Some(crate::Float::Left)
|
||||||
|
&& dom_children
|
||||||
|
.get(run_end)
|
||||||
|
.and_then(|cid| styles.get(cid))
|
||||||
|
.and_then(|style| style.float)
|
||||||
|
== Some(crate::Float::Right))
|
||||||
|
.then(|| dom_children[run_end]);
|
||||||
|
if let Some(right_dom) = trailing_right {
|
||||||
|
let right = build(
|
||||||
|
tree,
|
||||||
|
right_dom,
|
||||||
|
taffy_tree,
|
||||||
|
id_map,
|
||||||
|
words,
|
||||||
|
engine,
|
||||||
|
ifc_items,
|
||||||
|
styles,
|
||||||
|
);
|
||||||
|
if let Some(right) = right {
|
||||||
|
if let Ok(current) = taffy_tree.style(right) {
|
||||||
|
let mut pushed_right = current.clone();
|
||||||
|
pushed_right.margin.left =
|
||||||
|
taffy::style::LengthPercentageAuto::auto();
|
||||||
|
let _ = taffy_tree.set_style(right, pushed_right);
|
||||||
|
}
|
||||||
|
run_children.push(right);
|
||||||
|
let row_style = taffy::Style {
|
||||||
|
display: taffy::style::Display::Flex,
|
||||||
|
flex_direction: taffy::FlexDirection::Row,
|
||||||
|
flex_wrap: taffy::FlexWrap::Wrap,
|
||||||
|
align_items: Some(taffy::AlignItems::FLEX_START),
|
||||||
|
size: taffy::Size {
|
||||||
|
width: taffy::Dimension::percent(1.0),
|
||||||
|
height: taffy::Dimension::auto(),
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
if let Ok(row) = taffy_tree.new_with_children(row_style, &run_children) {
|
||||||
|
result.push(row);
|
||||||
|
}
|
||||||
|
result.extend(build_children_with_float_zone(
|
||||||
|
tree,
|
||||||
|
parent_id,
|
||||||
|
&dom_children[run_end + 1..],
|
||||||
|
taffy_tree,
|
||||||
|
id_map,
|
||||||
|
words,
|
||||||
|
engine,
|
||||||
|
ifc_items,
|
||||||
|
styles,
|
||||||
|
));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
let row_style = taffy::Style {
|
let row_style = taffy::Style {
|
||||||
display: taffy::style::Display::Flex,
|
display: taffy::style::Display::Flex,
|
||||||
flex_direction: taffy::FlexDirection::Row,
|
flex_direction: taffy::FlexDirection::Row,
|
||||||
|
|||||||
@@ -133,9 +133,11 @@ pub enum Dimension {
|
|||||||
/// Font-relative and viewport-relative units, kept unresolved at parse
|
/// Font-relative and viewport-relative units, kept unresolved at parse
|
||||||
/// time (the element font-size and viewport are not known then) and
|
/// time (the element font-size and viewport are not known then) and
|
||||||
/// resolved to `Px` during `dom::layout_dom`'s top-down pass via
|
/// resolved to `Px` during `dom::layout_dom`'s top-down pass via
|
||||||
/// [`Dimension::resolve`]. Resolving em/rem/vw against a hardcoded 16px at
|
/// [`Dimension::resolve`]. Resolving font/viewport units against a
|
||||||
|
/// hardcoded 16px at
|
||||||
/// parse time (the old behavior) silently corrupted every relative length.
|
/// parse time (the old behavior) silently corrupted every relative length.
|
||||||
Em(f32),
|
Em(f32),
|
||||||
|
Ex(f32),
|
||||||
Rem(f32),
|
Rem(f32),
|
||||||
Vw(f32),
|
Vw(f32),
|
||||||
Vh(f32),
|
Vh(f32),
|
||||||
@@ -151,6 +153,10 @@ impl Dimension {
|
|||||||
pub fn resolve(self, em_px: f32, rem_px: f32, vw: f32, vh: f32) -> Dimension {
|
pub fn resolve(self, em_px: f32, rem_px: f32, vw: f32, vh: f32) -> Dimension {
|
||||||
match self {
|
match self {
|
||||||
Dimension::Em(v) => Dimension::Px(v * em_px),
|
Dimension::Em(v) => Dimension::Px(v * em_px),
|
||||||
|
// Liberation Sans is the deterministic generic sans face used by
|
||||||
|
// the renderer. This is its x-height as a fraction of the em,
|
||||||
|
// matching Chromium's generic sans face on the capture host.
|
||||||
|
Dimension::Ex(v) => Dimension::Px(v * em_px * 0.528_320_3),
|
||||||
Dimension::Rem(v) => Dimension::Px(v * rem_px),
|
Dimension::Rem(v) => Dimension::Px(v * rem_px),
|
||||||
Dimension::Vw(v) => Dimension::Px(v * vw),
|
Dimension::Vw(v) => Dimension::Px(v * vw),
|
||||||
Dimension::Vh(v) => Dimension::Px(v * vh),
|
Dimension::Vh(v) => Dimension::Px(v * vh),
|
||||||
@@ -813,6 +819,7 @@ fn dimension(v: Dimension) -> taffy::style::Dimension {
|
|||||||
// through unresolved, fall back to its raw magnitude (em/rem ~16px)
|
// through unresolved, fall back to its raw magnitude (em/rem ~16px)
|
||||||
// rather than panicking.
|
// rather than panicking.
|
||||||
Dimension::Em(v) | Dimension::Rem(v) => taffy::style::Dimension::length(v * 16.0),
|
Dimension::Em(v) | Dimension::Rem(v) => taffy::style::Dimension::length(v * 16.0),
|
||||||
|
Dimension::Ex(v) => taffy::style::Dimension::length(v * 16.0 * 0.528_320_3),
|
||||||
Dimension::Vw(v) | Dimension::Vh(v) | Dimension::Vmin(v) | Dimension::Vmax(v) => taffy::style::Dimension::length(v),
|
Dimension::Vw(v) | Dimension::Vh(v) | Dimension::Vmin(v) | Dimension::Vmax(v) => taffy::style::Dimension::length(v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,15 +91,15 @@ pub fn ua_style(tag: &str) -> LayoutStyle {
|
|||||||
style.font_size = Some(16.0);
|
style.font_size = Some(16.0);
|
||||||
style.font_weight = Some("bold".to_string());
|
style.font_weight = Some("bold".to_string());
|
||||||
style.margin = Edges { top: 21.0, bottom: 21.0, left: 0.0, right: 0.0 };
|
style.margin = Edges { top: 21.0, bottom: 21.0, left: 0.0, right: 0.0 };
|
||||||
} else if tag == "p" || tag == "ul" || tag == "ol" {
|
} else if matches!(tag, "p" | "ul" | "ol" | "menu" | "dir") {
|
||||||
style.margin = Edges { top: 16.0, bottom: 16.0, left: 0.0, right: 0.0 };
|
style.margin = Edges { top: 16.0, bottom: 16.0, left: 0.0, right: 0.0 };
|
||||||
if tag == "ul" {
|
if matches!(tag, "ul" | "menu" | "dir") {
|
||||||
style.list_style = Some(crate::ListStyle::Disc);
|
style.list_style = Some(crate::ListStyle::Disc);
|
||||||
|
style.padding.left = 40.0;
|
||||||
} else if tag == "ol" {
|
} else if tag == "ol" {
|
||||||
style.list_style = Some(crate::ListStyle::Decimal);
|
style.list_style = Some(crate::ListStyle::Decimal);
|
||||||
|
style.padding.left = 40.0;
|
||||||
}
|
}
|
||||||
} else if tag == "li" {
|
|
||||||
style.margin = Edges { top: 0.0, bottom: 0.0, left: 40.0, right: 0.0 };
|
|
||||||
} else if tag == "b" || tag == "strong" {
|
} else if tag == "b" || tag == "strong" {
|
||||||
style.font_weight = Some("bold".to_string());
|
style.font_weight = Some("bold".to_string());
|
||||||
} else if tag == "i" || tag == "em" || tag == "cite" || tag == "var" || tag == "dfn" || tag == "address" {
|
} else if tag == "i" || tag == "em" || tag == "cite" || tag == "var" || tag == "dfn" || tag == "address" {
|
||||||
@@ -1757,6 +1757,9 @@ fn contextual_atom(value: &str, context: &LengthContext) -> Option<f32> {
|
|||||||
if let Some(value) = lower.strip_suffix("em").and_then(parse) {
|
if let Some(value) = lower.strip_suffix("em").and_then(parse) {
|
||||||
return Some(value * context.em_px);
|
return Some(value * context.em_px);
|
||||||
}
|
}
|
||||||
|
if let Some(value) = lower.strip_suffix("ex").and_then(parse) {
|
||||||
|
return Some(value * context.em_px * 0.528_320_3);
|
||||||
|
}
|
||||||
if let Some(value) = lower.strip_suffix("vmin").and_then(parse) {
|
if let Some(value) = lower.strip_suffix("vmin").and_then(parse) {
|
||||||
return Some(value * context.vw.min(context.vh));
|
return Some(value * context.vw.min(context.vh));
|
||||||
}
|
}
|
||||||
@@ -2153,7 +2156,7 @@ fn is_font_size_token(value: &str) -> bool {
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
["px", "pt", "em", "rem", "vw", "vh", "vmin", "vmax", "%"]
|
["px", "pt", "em", "ex", "rem", "vw", "vh", "vmin", "vmax", "%"]
|
||||||
.iter()
|
.iter()
|
||||||
.any(|unit| lower.strip_suffix(unit).and_then(|number| number.parse::<f32>().ok()).is_some())
|
.any(|unit| lower.strip_suffix(unit).and_then(|number| number.parse::<f32>().ok()).is_some())
|
||||||
}
|
}
|
||||||
@@ -2177,6 +2180,7 @@ fn dimension_value(tok: &str) -> crate::Dimension {
|
|||||||
// Order matters: check `rem` before `em`, `vmin`/`vmax` before `vw`/`vh`.
|
// Order matters: check `rem` before `em`, `vmin`/`vmax` before `vw`/`vh`.
|
||||||
if let Some(v) = lower.strip_suffix("rem").and_then(parse) { return Dimension::Rem(v); }
|
if let Some(v) = lower.strip_suffix("rem").and_then(parse) { return Dimension::Rem(v); }
|
||||||
if let Some(v) = lower.strip_suffix("em").and_then(parse) { return Dimension::Em(v); }
|
if let Some(v) = lower.strip_suffix("em").and_then(parse) { return Dimension::Em(v); }
|
||||||
|
if let Some(v) = lower.strip_suffix("ex").and_then(parse) { return Dimension::Ex(v); }
|
||||||
if let Some(v) = lower.strip_suffix("vmin").and_then(parse) { return Dimension::Vmin(v); }
|
if let Some(v) = lower.strip_suffix("vmin").and_then(parse) { return Dimension::Vmin(v); }
|
||||||
if let Some(v) = lower.strip_suffix("vmax").and_then(parse) { return Dimension::Vmax(v); }
|
if let Some(v) = lower.strip_suffix("vmax").and_then(parse) { return Dimension::Vmax(v); }
|
||||||
if let Some(v) = lower.strip_suffix("vw").and_then(parse) { return Dimension::Vw(v); }
|
if let Some(v) = lower.strip_suffix("vw").and_then(parse) { return Dimension::Vw(v); }
|
||||||
@@ -2231,6 +2235,7 @@ fn set_margin_side(style: &mut LayoutStyle, idx: usize, value: &str) {
|
|||||||
style.margin_relative[idx] = None;
|
style.margin_relative[idx] = None;
|
||||||
}
|
}
|
||||||
crate::Dimension::Em(_)
|
crate::Dimension::Em(_)
|
||||||
|
| crate::Dimension::Ex(_)
|
||||||
| crate::Dimension::Rem(_)
|
| crate::Dimension::Rem(_)
|
||||||
| crate::Dimension::Vw(_)
|
| crate::Dimension::Vw(_)
|
||||||
| crate::Dimension::Vh(_)
|
| crate::Dimension::Vh(_)
|
||||||
@@ -2285,6 +2290,7 @@ fn set_padding_side(style: &mut LayoutStyle, idx: usize, value: &str) {
|
|||||||
style.padding_percent[idx] = None;
|
style.padding_percent[idx] = None;
|
||||||
}
|
}
|
||||||
crate::Dimension::Em(_)
|
crate::Dimension::Em(_)
|
||||||
|
| crate::Dimension::Ex(_)
|
||||||
| crate::Dimension::Rem(_)
|
| crate::Dimension::Rem(_)
|
||||||
| crate::Dimension::Vw(_)
|
| crate::Dimension::Vw(_)
|
||||||
| crate::Dimension::Vh(_)
|
| crate::Dimension::Vh(_)
|
||||||
@@ -2366,6 +2372,9 @@ fn px_value(tok: &str) -> Option<f32> {
|
|||||||
} else if n.ends_with("em") || n.ends_with("rem") {
|
} else if n.ends_with("em") || n.ends_with("rem") {
|
||||||
n = n.trim_end_matches(|c: char| c.is_ascii_alphabetic());
|
n = n.trim_end_matches(|c: char| c.is_ascii_alphabetic());
|
||||||
scale = 16.0; // 1em = 16px
|
scale = 16.0; // 1em = 16px
|
||||||
|
} else if n.ends_with("ex") {
|
||||||
|
n = n.trim_end_matches(|c: char| c.is_ascii_alphabetic());
|
||||||
|
scale = 16.0 * 0.528_320_3;
|
||||||
} else if n.ends_with('%') {
|
} else if n.ends_with('%') {
|
||||||
n = &n[..n.len() - 1];
|
n = &n[..n.len() - 1];
|
||||||
scale = 16.0 / 100.0;
|
scale = 16.0 / 100.0;
|
||||||
|
|||||||
Reference in new issue
Block a user