render: resolve relative box edge lengths
This commit is contained in:
1 parent
7d74c15f31
commit
b13a1e5e71
3 files changed
+93
-11
No files matched your search
@@ -448,13 +448,38 @@ pub fn layout_dom_with_images(
|
|||||||
}
|
}
|
||||||
inh.box_sizing = style.box_sizing;
|
inh.box_sizing = style.box_sizing;
|
||||||
|
|
||||||
// Percentage padding/margin resolve against the containing
|
// Resolve font/viewport-relative box edges now that their
|
||||||
// block WIDTH on every side (per CSS: `padding-top:56.25%` in a
|
// reference sizes are known. Percentage padding/margin then
|
||||||
// 1000px block is 562.5px, not a fraction of the height). The
|
// resolve against the containing block WIDTH on every side
|
||||||
// f32 Edges cannot carry a percentage, so bake the resolved px
|
// (per CSS: `padding-top:56.25%` in a 1000px block is 562.5px,
|
||||||
// back into `padding`/`margin`, which then feed taffy.
|
// not a fraction of the height). Bake the resolved px back into
|
||||||
|
// `padding`/`margin`, which then feed taffy.
|
||||||
let cb_w = inh.cb_width;
|
let cb_w = inh.cb_width;
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
|
if let Some(relative) = style.padding_relative[i] {
|
||||||
|
if let crate::Dimension::Px(px) =
|
||||||
|
relative.resolve(em_px, root_fs, vw, vh)
|
||||||
|
{
|
||||||
|
match i {
|
||||||
|
0 => style.padding.top = px.max(0.0),
|
||||||
|
1 => style.padding.right = px.max(0.0),
|
||||||
|
2 => style.padding.bottom = px.max(0.0),
|
||||||
|
_ => style.padding.left = px.max(0.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(relative) = style.margin_relative[i] {
|
||||||
|
if let crate::Dimension::Px(px) =
|
||||||
|
relative.resolve(em_px, root_fs, vw, vh)
|
||||||
|
{
|
||||||
|
match i {
|
||||||
|
0 => style.margin.top = px,
|
||||||
|
1 => style.margin.right = px,
|
||||||
|
2 => style.margin.bottom = px,
|
||||||
|
_ => style.margin.left = px,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(frac) = style.padding_percent[i] {
|
if let Some(frac) = style.padding_percent[i] {
|
||||||
let px = (frac * cb_w).max(0.0);
|
let px = (frac * cb_w).max(0.0);
|
||||||
match i {
|
match i {
|
||||||
|
|||||||
@@ -197,6 +197,10 @@ pub struct LayoutStyle {
|
|||||||
/// percentage, so this is resolved to px during `dom::layout_dom`'s top-down
|
/// percentage, so this is resolved to px during `dom::layout_dom`'s top-down
|
||||||
/// pass once the containing-block width is known.
|
/// pass once the containing-block width is known.
|
||||||
pub margin_percent: [Option<f32>; 4],
|
pub margin_percent: [Option<f32>; 4],
|
||||||
|
/// Font- and viewport-relative margin lengths (top, right, bottom, left).
|
||||||
|
/// These retain their unit until the top-down pass knows the element font
|
||||||
|
/// size, root font size, and viewport dimensions.
|
||||||
|
pub margin_relative: [Option<Dimension>; 4],
|
||||||
pub padding: Edges,
|
pub padding: Edges,
|
||||||
/// Percentage padding per side (top, right, bottom, left) as a 0..1
|
/// Percentage padding per side (top, right, bottom, left) as a 0..1
|
||||||
/// fraction, `None` when the side is a fixed length. All four sides resolve
|
/// fraction, `None` when the side is a fixed length. All four sides resolve
|
||||||
@@ -206,6 +210,9 @@ pub struct LayoutStyle {
|
|||||||
/// resolved to px in `dom::layout_dom`'s top-down pass and written back into
|
/// resolved to px in `dom::layout_dom`'s top-down pass and written back into
|
||||||
/// `padding`, which then feeds taffy as a fixed length.
|
/// `padding`, which then feeds taffy as a fixed length.
|
||||||
pub padding_percent: [Option<f32>; 4],
|
pub padding_percent: [Option<f32>; 4],
|
||||||
|
/// Font- and viewport-relative padding lengths (top, right, bottom, left),
|
||||||
|
/// resolved alongside `margin_relative` during the top-down pass.
|
||||||
|
pub padding_relative: [Option<Dimension>; 4],
|
||||||
pub border: Edges,
|
pub border: Edges,
|
||||||
/// `border-radius` (uniform; the first value of the shorthand). Rounds the
|
/// `border-radius` (uniform; the first value of the shorthand). Rounds the
|
||||||
/// background fill and border. In px after resolution.
|
/// background fill and border. In px after resolution.
|
||||||
|
|||||||
@@ -1672,12 +1672,31 @@ fn set_margin_side(style: &mut LayoutStyle, idx: usize, value: &str) {
|
|||||||
let is_auto = v.eq_ignore_ascii_case("auto");
|
let is_auto = v.eq_ignore_ascii_case("auto");
|
||||||
if let Some(frac) = percent_fraction(v) {
|
if let Some(frac) = percent_fraction(v) {
|
||||||
style.margin_percent[idx] = Some(frac);
|
style.margin_percent[idx] = Some(frac);
|
||||||
|
style.margin_relative[idx] = None;
|
||||||
set_margin_px(&mut style.margin, idx, 0.0);
|
set_margin_px(&mut style.margin, idx, 0.0);
|
||||||
style.margin_auto[idx] = false;
|
style.margin_auto[idx] = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let px = if is_auto { 0.0 } else { px(value).unwrap_or(0.0) };
|
let dimension = dimension_value(v);
|
||||||
set_margin_px(&mut style.margin, idx, px);
|
match dimension {
|
||||||
|
crate::Dimension::Px(px) => {
|
||||||
|
set_margin_px(&mut style.margin, idx, px);
|
||||||
|
style.margin_relative[idx] = None;
|
||||||
|
}
|
||||||
|
crate::Dimension::Em(_)
|
||||||
|
| crate::Dimension::Rem(_)
|
||||||
|
| crate::Dimension::Vw(_)
|
||||||
|
| crate::Dimension::Vh(_)
|
||||||
|
| crate::Dimension::Vmin(_)
|
||||||
|
| crate::Dimension::Vmax(_) => {
|
||||||
|
set_margin_px(&mut style.margin, idx, 0.0);
|
||||||
|
style.margin_relative[idx] = Some(dimension);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
set_margin_px(&mut style.margin, idx, 0.0);
|
||||||
|
style.margin_relative[idx] = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
style.margin_auto[idx] = is_auto;
|
style.margin_auto[idx] = is_auto;
|
||||||
style.margin_percent[idx] = None;
|
style.margin_percent[idx] = None;
|
||||||
}
|
}
|
||||||
@@ -1696,14 +1715,31 @@ fn set_margin_px(margin: &mut Edges, idx: usize, px: f32) {
|
|||||||
/// recorded in `padding_percent` and resolved against the containing-block
|
/// recorded in `padding_percent` and resolved against the containing-block
|
||||||
/// width during the top-down pass; a length is stored directly.
|
/// width during the top-down pass; a length is stored directly.
|
||||||
fn set_padding_side(style: &mut LayoutStyle, idx: usize, value: &str) {
|
fn set_padding_side(style: &mut LayoutStyle, idx: usize, value: &str) {
|
||||||
if let Some(frac) = percent_fraction(value.trim()) {
|
let value = value.trim();
|
||||||
|
if let Some(frac) = percent_fraction(value) {
|
||||||
style.padding_percent[idx] = Some(frac);
|
style.padding_percent[idx] = Some(frac);
|
||||||
|
style.padding_relative[idx] = None;
|
||||||
set_padding_px(&mut style.padding, idx, 0.0);
|
set_padding_px(&mut style.padding, idx, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(px) = px(value) {
|
let dimension = dimension_value(value);
|
||||||
set_padding_px(&mut style.padding, idx, px);
|
match dimension {
|
||||||
style.padding_percent[idx] = None;
|
crate::Dimension::Px(px) => {
|
||||||
|
set_padding_px(&mut style.padding, idx, px);
|
||||||
|
style.padding_relative[idx] = None;
|
||||||
|
style.padding_percent[idx] = None;
|
||||||
|
}
|
||||||
|
crate::Dimension::Em(_)
|
||||||
|
| crate::Dimension::Rem(_)
|
||||||
|
| crate::Dimension::Vw(_)
|
||||||
|
| crate::Dimension::Vh(_)
|
||||||
|
| crate::Dimension::Vmin(_)
|
||||||
|
| crate::Dimension::Vmax(_) => {
|
||||||
|
set_padding_px(&mut style.padding, idx, 0.0);
|
||||||
|
style.padding_relative[idx] = Some(dimension);
|
||||||
|
style.padding_percent[idx] = None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2202,6 +2238,20 @@ mod tests {
|
|||||||
assert!(!s.margin_auto[3]);
|
assert!(!s.margin_auto[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn relative_box_edges_remain_unresolved() {
|
||||||
|
let s = compute_style(
|
||||||
|
"div",
|
||||||
|
Some("font-size:20px;margin:15vh auto 2em 10vw;padding:1rem 2vmin"),
|
||||||
|
);
|
||||||
|
assert_eq!(s.margin_relative[0], Some(crate::Dimension::Vh(15.0)));
|
||||||
|
assert!(s.margin_auto[1]);
|
||||||
|
assert_eq!(s.margin_relative[2], Some(crate::Dimension::Em(2.0)));
|
||||||
|
assert_eq!(s.margin_relative[3], Some(crate::Dimension::Vw(10.0)));
|
||||||
|
assert_eq!(s.padding_relative[0], Some(crate::Dimension::Rem(1.0)));
|
||||||
|
assert_eq!(s.padding_relative[1], Some(crate::Dimension::Vmin(2.0)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ua_defaults_and_ignore_unknown() {
|
fn ua_defaults_and_ignore_unknown() {
|
||||||
let s = compute_style("span", Some("color: red; ; bogus: ; display: none"));
|
let s = compute_style("span", Some("color: red; ; bogus: ; display: none"));
|
||||||
|
|||||||
Reference in new issue
Block a user