tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

Special-case "compressible replaced elements" in grid sizing algorithm (#807)

Signed-off-by: Nico Burns <nico@nicoburns.com>

a4b481f99f435f2b304ef63d272bbd49136d4f14 · por Nico Burns · (hace 1 año) · padre 8437796cc · ver el árbol en este commit

Delta semántico · 10

src/compute/grid/types/grid_item.rs

src/style/mod.rs

2 archivos · +37 −1

diff --git a/src/compute/grid/types/grid_item.rs b/src/compute/grid/types/grid_item.rs
index a84c77429..5746303c4 100644
--- a/src/compute/grid/types/grid_item.rs
+++ b/src/compute/grid/types/grid_item.rs
@@ -28,6 +28,9 @@ pub(in super::super) struct GridItem {
     /// (in origin-zero coordinates)
     pub column: Line<OriginZeroLine>,
 
+    /// Is it a compressible replaced element?
+    /// https://drafts.csswg.org/css-sizing-3/#min-content-zero
+    pub is_compressible_replaced: bool,
     /// The item's overflow style
     pub overflow: Point<Overflow>,
     /// The item's box_sizing style
@@ -104,6 +107,7 @@ impl GridItem {
             source_order,
             row: row_span,
             column: col_span,
+            is_compressible_replaced: style.is_compressible_replaced(),
             overflow: style.overflow(),
             box_sizing: style.box_sizing(),
             size: style.size(),
@@ -504,7 +508,20 @@ impl GridItem {
 
                 // Otherwise, the automatic minimum size is zero, as usual.
                 if use_content_based_minimum {
-                    self.min_content_contribution_cached(axis, tree, known_dimensions, inner_node_size)
+                    let mut minimum_contribution =
+                        self.min_content_contribution_cached(axis, tree, known_dimensions, inner_node_size);
+
+                    // If the item is a compressible replaced element, and has a definite preferred size or maximum size in the
+                    // relevant axis, the size suggestion is capped by those sizes; for this purpose, any indefinite percentages
+                    // in these sizes are resolved against zero (and considered definite).
+                    if self.is_compressible_replaced {
+                        let size = self.size.get(axis).maybe_resolve(Some(0.0), |val, basis| tree.calc(val, basis));
+                        let max_size =
+                            self.max_size.get(axis).maybe_resolve(Some(0.0), |val, basis| tree.calc(val, basis));
+                        minimum_contribution = minimum_contribution.maybe_min(size).maybe_min(max_size);
+                    }
+
+                    minimum_contribution
                 } else {
                     0.0
                 }
diff --git a/src/style/mod.rs b/src/style/mod.rs
index e1709ef2a..41cef747a 100644
--- a/src/style/mod.rs
+++ b/src/style/mod.rs
@@ -54,6 +54,12 @@ pub trait CoreStyle {
     fn is_block(&self) -> bool {
         false
     }
+    /// Is it a compressible replaced element?
+    /// https://drafts.csswg.org/css-sizing-3/#min-content-zero
+    #[inline(always)]
+    fn is_compressible_replaced(&self) -> bool {
+        false
+    }
     /// Which box do size styles apply to
     #[inline(always)]
     fn box_sizing(&self) -> BoxSizing {
@@ -338,6 +344,9 @@ pub struct Style {
     /// Whether a child is display:table or not. This affects children of block layouts.
     /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
     pub item_is_table: bool,
+    /// Is it a replaced element like an image or form field?
+    /// https://drafts.csswg.org/css-sizing-3/#min-content-zero
+    pub item_is_replaced: bool,
     /// Should size styles apply to the content box or the border box of the node
     pub box_sizing: BoxSizing,
 
@@ -465,6 +474,7 @@ impl Style {
     pub const DEFAULT: Style = Style {
         display: Display::DEFAULT,
         item_is_table: false,
+        item_is_replaced: false,
         box_sizing: BoxSizing::BorderBox,
         overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
         scrollbar_width: 0.0,
@@ -544,6 +554,10 @@ impl CoreStyle for Style {
         matches!(self.display, Display::Block)
     }
     #[inline(always)]
+    fn is_compressible_replaced(&self) -> bool {
+        self.item_is_replaced
+    }
+    #[inline(always)]
     fn box_sizing(&self) -> BoxSizing {
         self.box_sizing
     }
@@ -603,6 +617,10 @@ impl<T: CoreStyle> CoreStyle for &'_ T {
         (*self).is_block()
     }
     #[inline(always)]
+    fn is_compressible_replaced(&self) -> bool {
+        (*self).is_compressible_replaced()
+    }
+    #[inline(always)]
     fn box_sizing(&self) -> BoxSizing {
         (*self).box_sizing()
     }
@@ -939,6 +957,7 @@ mod tests {
         let old_defaults = Style {
             display: Default::default(),
             item_is_table: false,
+            item_is_replaced: false,
             box_sizing: Default::default(),
             overflow: Default::default(),
             scrollbar_width: 0.0,