Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions Libraries/LibWeb/Rust/src/layout/flex_formatting_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,13 +865,35 @@ impl<'pass> FlexFormattingContext<'pass> {
}

fn calculate_min_content_inline_size(&self, index: usize) -> CssPixels {
self.sizing()
.calculate_min_content_inline_size(self.flex_items[index].box_, self.item_containing_block_constraints())
let sizing = self.sizing();
let node = self.flex_items[index].box_;
let constraints = self.item_containing_block_constraints();
let used = self.item_used(index);
if used.has_definite_block_size() {
sizing.calculate_min_content_inline_size_at_definite_block_size(
node,
constraints,
used.content_block_size.get(),
)
} else {
sizing.calculate_min_content_inline_size(node, constraints)
}
}

fn calculate_max_content_inline_size(&self, index: usize) -> CssPixels {
self.sizing()
.calculate_max_content_inline_size(self.flex_items[index].box_, self.item_containing_block_constraints())
let sizing = self.sizing();
let node = self.flex_items[index].box_;
let constraints = self.item_containing_block_constraints();
let used = self.item_used(index);
if used.has_definite_block_size() {
sizing.calculate_max_content_inline_size_at_definite_block_size(
node,
constraints,
used.content_block_size.get(),
)
} else {
sizing.calculate_max_content_inline_size(node, constraints)
}
}

fn calculate_min_content_block_size(&self, index: usize, inline_size: CssPixels) -> CssPixels {
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/Rust/src/layout/formatting_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,12 @@ impl MeasurementState {

fn cache_key(
measured_at_inline_size: Option<CssPixels>,
measured_at_block_size: Option<CssPixels>,
constraints: ContainingBlockConstraints,
) -> IntrinsicSizeCacheKey {
IntrinsicSizeCacheKey {
measured_at_inline_size,
measured_at_block_size,
percentage_basis_inline_size: constraints.percentage_basis_inline_size,
percentage_basis_block_size: constraints.percentage_basis_block_size,
quirks_mode_percentage_basis_block_size: constraints.quirks_mode_percentage_basis_block_size,
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/Rust/src/layout/layout_node_arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(crate) const SLOTS_PER_CHUNK: usize = 256;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct IntrinsicSizeCacheKey {
pub(crate) measured_at_inline_size: Option<CssPixels>,
pub(crate) measured_at_block_size: Option<CssPixels>,
pub(crate) percentage_basis_inline_size: Option<CssPixels>,
pub(crate) percentage_basis_block_size: Option<CssPixels>,
pub(crate) quirks_mode_percentage_basis_block_size: Option<CssPixels>,
Expand All @@ -42,6 +43,7 @@ impl Hash for IntrinsicSizeCacheKey {
}

hash_optional(self.measured_at_inline_size, state);
hash_optional(self.measured_at_block_size, state);
hash_optional(self.percentage_basis_inline_size, state);
hash_optional(self.percentage_basis_block_size, state);
hash_optional(self.quirks_mode_percentage_basis_block_size, state);
Expand Down
67 changes: 58 additions & 9 deletions Libraries/LibWeb/Rust/src/layout/sizing_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ impl SizingContext {
self.intrinsic_inline_measurement_cache_get(
node,
IntrinsicSizeCacheKind::MaxContentInline,
cache_key(None, constraints),
cache_key(None, None, constraints),
)?
.min_content_inline_size_from_max_content_layout?
} else {
Expand Down Expand Up @@ -1322,7 +1322,11 @@ impl SizingContext {
AvailableSize::MaxContent => IntrinsicSizeCacheKind::MaxContentInline,
AvailableSize::Definite(_) | AvailableSize::Indefinite => return None,
};
let measurement = self.intrinsic_inline_measurement_cache_get(node, kind, cache_key(None, constraints))?;
let measurement = self.intrinsic_inline_measurement_cache_get(
node,
kind,
cache_key(None, None, constraints),
)?;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if measurement.available_block_size != available_block_size {
return None;
}
Expand Down Expand Up @@ -1383,6 +1387,24 @@ impl SizingContext {
&self,
node: Node,
constraints: ContainingBlockConstraints,
) -> CssPixels {
self.calculate_min_content_inline_size_with_block_size(node, constraints, None)
}

pub(crate) fn calculate_min_content_inline_size_at_definite_block_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: CssPixels,
) -> CssPixels {
self.calculate_min_content_inline_size_with_block_size(node, constraints, Some(block_size))
}

fn calculate_min_content_inline_size_with_block_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: Option<CssPixels>,
) -> CssPixels {
let facts = self.facts(node);
let style = self.style(node);
Expand Down Expand Up @@ -1432,25 +1454,26 @@ impl SizingContext {
if let Some(cached) = self.intrinsic_inline_measurement_cache_get(
node,
IntrinsicSizeCacheKind::MinContentInline,
cache_key(None, constraints),
cache_key(None, block_size, constraints),
) {
return cached.automatic_content_inline_size;
}
if let Some(min_content_inline_size) = self.paired_min_content_inline_size(node, constraints) {
if let Some(min_content_inline_size) = self.paired_min_content_inline_size(node, constraints, block_size) {
return min_content_inline_size;
}
self.measure_intrinsic_inline_size(node, constraints, IntrinsicSizeCacheKind::MinContentInline)
self.measure_intrinsic_inline_size(node, constraints, block_size, IntrinsicSizeCacheKind::MinContentInline)
}

fn paired_min_content_inline_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: Option<CssPixels>,
) -> Option<CssPixels> {
self.intrinsic_inline_measurement_cache_get(
node,
IntrinsicSizeCacheKind::MaxContentInline,
cache_key(None, constraints),
cache_key(None, block_size, constraints),
)?
.min_content_inline_size_from_max_content_layout
}
Expand All @@ -1459,6 +1482,24 @@ impl SizingContext {
&self,
node: Node,
constraints: ContainingBlockConstraints,
) -> CssPixels {
self.calculate_max_content_inline_size_with_block_size(node, constraints, None)
}

pub(crate) fn calculate_max_content_inline_size_at_definite_block_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: CssPixels,
) -> CssPixels {
self.calculate_max_content_inline_size_with_block_size(node, constraints, Some(block_size))
}

fn calculate_max_content_inline_size_with_block_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: Option<CssPixels>,
) -> CssPixels {
let facts = self.facts(node);
let style = self.style(node);
Expand Down Expand Up @@ -1614,28 +1655,36 @@ impl SizingContext {
if !self.has_children(node) {
return CssPixels::default();
}
self.measure_intrinsic_inline_size(node, constraints, IntrinsicSizeCacheKind::MaxContentInline)
self.measure_intrinsic_inline_size(node, constraints, block_size, IntrinsicSizeCacheKind::MaxContentInline)
}

// Lays `node` out under an intrinsic inline-size constraint, reusing and populating the measurement cache.
fn measure_intrinsic_inline_size(
&self,
node: Node,
constraints: ContainingBlockConstraints,
block_size: Option<CssPixels>,
kind: IntrinsicSizeCacheKind,
) -> CssPixels {
let (size_constraint, available_inline_size) = match kind {
IntrinsicSizeCacheKind::MinContentInline => (SizeConstraint::MinContent, AvailableSize::MinContent),
IntrinsicSizeCacheKind::MaxContentInline => (SizeConstraint::MaxContent, AvailableSize::MaxContent),
_ => unreachable!("inline measurement cache kind must use the inline axis"),
};
let key = cache_key(None, constraints);
let key = cache_key(None, block_size, constraints);
if let Some(cached) = self.intrinsic_inline_measurement_cache_get(node, kind, key) {
return cached.automatic_content_inline_size;
}

let measurement = MeasurementState::create(self.callbacks);
let root = measurement.create_used_values(node, constraints);
// NB: A parent layout can assign a definite block size that is not present in computed style,
// such as the stretched cross size of a flex item. Preserve it so descendant percentages
// resolve against the same size during intrinsic measurement.
if let Some(block_size) = block_size {
root.set_content_block_size(block_size);
root.has_definite_block_size.set(true);
}
root.inline_size_constraint.set(size_constraint);
root.has_definite_inline_size.set(false);
let block_size = if root.has_definite_block_size() {
Expand Down Expand Up @@ -1677,7 +1726,7 @@ impl SizingContext {
IntrinsicSizeCacheKind::MaxContentBlock => (SizeConstraint::MaxContent, AvailableSize::MaxContent),
_ => unreachable!("block size cache kind must use the block axis"),
};
let key = cache_key(Some(inline_size), constraints);
let key = cache_key(Some(inline_size), None, constraints);
if let Some(cached) = self.intrinsic_block_cache_get(node, kind, key) {
return cached;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
item width: 400
child width: 400
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!doctype html>
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#intrinsic-item-contributions">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers">
<script src="include.js"></script>
<style>
#container {
display: flex;
width: 300px;
height: 200px;
}

#item {
display: flex;
flex-shrink: 0;
}

#child {
width: auto;
height: 100%;
aspect-ratio: 2 / 1;
}
</style>
<div id="container">
<div id="item">
<div id="child"></div>
</div>
</div>
<script>
test(() => {
println(`item width: ${item.getBoundingClientRect().width}`);
println(`child width: ${child.getBoundingClientRect().width}`);
});
</script>
Loading