Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(566)

Unified Diff: third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc

Issue 2616613003: Fix calculation of abspos style properties: left/padding/width/height... (Closed)
Patch Set: Rebase for merge conflicts Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc
index c83bf5a54b1583fb37785921e2b4e15ab867c040..22653a09c43f3a17d3f0580f8d87f318a398fe25 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_absolute_utils.cc
@@ -13,61 +13,63 @@ namespace blink {
namespace {
-// Extends Length::valueForLength with default value if length type is auto.
-LayoutUnit CustomValueForLength(const Length& length,
- LayoutUnit max_value,
- LayoutUnit default_value = NGSizeIndefinite) {
- if (length.isAuto())
- return default_value;
- DCHECK(!length.isPercentOrCalc() || max_value != NGSizeIndefinite);
- return valueForLength(length, max_value);
-}
-
bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) {
- return style.width().isAuto() &&
- (style.left().isAuto() || style.right().isAuto());
+ Length width = style.width();
+ return width.isIntrinsic() ||
+ (width.isAuto() && (style.left().isAuto() || style.right().isAuto()));
}
bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) {
- return style.height().isAuto() &&
- (style.top().isAuto() || style.bottom().isAuto());
+ Length height = style.height();
+ return height.isIntrinsic() ||
+ (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto()));
}
// Implement absolute horizontal size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
-void ComputeAbsoluteHorizontal(const NGConstraintSpace& space,
- const ComputedStyle& style,
- const NGStaticPosition& static_position,
- const Optional<LayoutUnit>& child_auto_width,
- NGAbsolutePhysicalPosition* position) {
- // Always use inline_size for percent resolution.
- // TODO(atotic) test whether inline_size is correct in vertical modes.
- LayoutUnit percentage_resolution_size =
- space.PercentageResolutionSize().inline_size;
+void ComputeAbsoluteHorizontal(
+ const NGConstraintSpace& space,
+ const ComputedStyle& style,
+ const NGStaticPosition& static_position,
+ const Optional<MinAndMaxContentSizes>& child_minmax,
+ NGAbsolutePhysicalPosition* position) {
+ NGLogicalSize percentage_logical = space.PercentageResolutionSize();
+ NGPhysicalSize percentage_physical =
+ percentage_logical.ConvertToPhysical(space.WritingMode());
LayoutUnit border_left(style.borderLeftWidth());
LayoutUnit border_right(style.borderRightWidth());
- LayoutUnit padding_left = CustomValueForLength(
- style.paddingLeft(), percentage_resolution_size, LayoutUnit());
- LayoutUnit padding_right = CustomValueForLength(
- style.paddingRight(), percentage_resolution_size, LayoutUnit());
- LayoutUnit margin_left =
- CustomValueForLength(style.marginLeft(), percentage_resolution_size);
- LayoutUnit margin_right =
- CustomValueForLength(style.marginRight(), percentage_resolution_size);
- LayoutUnit left =
- CustomValueForLength(style.left(), percentage_resolution_size);
- LayoutUnit right =
- CustomValueForLength(style.right(), percentage_resolution_size);
+ LayoutUnit padding_left =
+ valueForLength(style.paddingLeft(), percentage_logical.inline_size);
+ LayoutUnit padding_right =
+ valueForLength(style.paddingRight(), percentage_logical.inline_size);
+ Optional<LayoutUnit> margin_left;
+ if (!style.marginLeft().isAuto())
+ margin_left =
+ valueForLength(style.marginLeft(), percentage_logical.inline_size);
+ Optional<LayoutUnit> margin_right;
+ if (!style.marginRight().isAuto())
+ margin_right =
+ valueForLength(style.marginRight(), percentage_logical.inline_size);
+ Optional<LayoutUnit> left;
+ if (!style.left().isAuto())
+ left = valueForLength(style.left(), percentage_physical.width);
+ Optional<LayoutUnit> right;
+ if (!style.right().isAuto())
+ right = valueForLength(style.right(), percentage_physical.width);
LayoutUnit border_padding =
border_left + border_right + padding_left + padding_right;
- // TODO(atotic): This should use Resolve{Inline,Block}Length
- LayoutUnit width =
- CustomValueForLength(style.width(), percentage_resolution_size);
-
- // Normalize width to border-box sizing.
- if (style.boxSizing() == EBoxSizing::BoxSizingContentBox &&
- width != NGSizeIndefinite)
- width += border_padding;
+ Optional<LayoutUnit> width;
+ if (!style.width().isAuto()) {
+ if (space.WritingMode() == kHorizontalTopBottom) {
+ width = ResolveInlineLength(space, style, child_minmax, style.width(),
+ LengthResolveType::kContentSize);
+ } else {
+ LayoutUnit computed_width =
+ child_minmax.has_value() ? child_minmax->max_content : LayoutUnit();
+ width = ResolveBlockLength(space, style, style.width(), computed_width,
+ LengthResolveType::kContentSize);
+ }
+ }
NGPhysicalSize container_size =
space.AvailableSize().ConvertToPhysical(space.WritingMode());
@@ -75,29 +77,27 @@ void ComputeAbsoluteHorizontal(const NGConstraintSpace& space,
// Solving the equation:
// left + marginLeft + width + marginRight + right = container width
- if (left == NGSizeIndefinite && right == NGSizeIndefinite &&
- width == NGSizeIndefinite) {
+ if (!left && !right && !width) {
// Standard: "If all three of left, width, and right are auto:"
- if (margin_left == NGSizeIndefinite)
+ if (!margin_left)
margin_left = LayoutUnit();
- if (margin_right == NGSizeIndefinite)
+ if (!margin_right)
margin_right = LayoutUnit();
- DCHECK(child_auto_width.has_value());
- width = *child_auto_width;
+ DCHECK(child_minmax.has_value());
+ width = child_minmax->ShrinkToFit(container_size.width);
if (space.Direction() == TextDirection::Ltr) {
- left = static_position.LeftPosition(container_size.width, width,
- margin_left, margin_right);
+ left = static_position.LeftPosition(container_size.width, *width,
+ *margin_left, *margin_right);
} else {
- right = static_position.RightPosition(container_size.width, width,
- margin_left, margin_right);
+ right = static_position.RightPosition(container_size.width, *width,
+ *margin_left, *margin_right);
}
- } else if (left != NGSizeIndefinite && right != NGSizeIndefinite &&
- width != NGSizeIndefinite) {
+ } else if (left && right && width) {
// Standard: "If left, right, and width are not auto:"
// Compute margins.
- LayoutUnit margin_space = container_size.width - left - right - width;
+ LayoutUnit margin_space = container_size.width - *left - *right - *width;
// When both margins are auto.
- if (margin_left == NGSizeIndefinite && margin_right == NGSizeIndefinite) {
+ if (!margin_left && !margin_right) {
if (margin_space > 0) {
margin_left = margin_space / 2;
margin_right = margin_space / 2;
@@ -111,102 +111,118 @@ void ComputeAbsoluteHorizontal(const NGConstraintSpace& space,
margin_left = margin_space;
}
}
- } else if (margin_left == NGSizeIndefinite) {
+ } else if (!margin_left) {
margin_left = margin_space;
- } else if (margin_right == NGSizeIndefinite) {
+ } else if (!margin_right) {
margin_right = margin_space;
} else {
// Are values overconstrained?
- if (margin_left + margin_right != margin_space) {
+ if (*margin_left + *margin_right != margin_space) {
// Relax the end.
if (space.Direction() == TextDirection::Ltr)
- right -= margin_left + margin_right - margin_space;
+ right = *right - *margin_left + *margin_right - margin_space;
else
- left -= margin_left + margin_right - margin_space;
+ left = *left - *margin_left + *margin_right - margin_space;
}
}
}
// Set unknown margins.
- if (margin_left == NGSizeIndefinite)
+ if (!margin_left)
margin_left = LayoutUnit();
- if (margin_right == NGSizeIndefinite)
+ if (!margin_right)
margin_right = LayoutUnit();
// Rules 1 through 3, 2 out of 3 are unknown.
- if (left == NGSizeIndefinite && width == NGSizeIndefinite) {
+ if (!left && !width) {
// Rule 1: left/width are unknown.
- DCHECK_NE(right, NGSizeIndefinite);
- DCHECK(child_auto_width.has_value());
- width = *child_auto_width;
- } else if (left == NGSizeIndefinite && right == NGSizeIndefinite) {
+ DCHECK(right.has_value());
+ DCHECK(child_minmax.has_value());
+ width = child_minmax->ShrinkToFit(container_size.width);
+ } else if (!left && !right) {
// Rule 2.
- DCHECK_NE(width, NGSizeIndefinite);
+ DCHECK(width.has_value());
if (space.Direction() == TextDirection::Ltr)
- left = static_position.LeftPosition(container_size.width, width,
- margin_left, margin_right);
+ left = static_position.LeftPosition(container_size.width, *width,
+ *margin_left, *margin_right);
else
- right = static_position.RightPosition(container_size.width, width,
- margin_left, margin_right);
- } else if (width == NGSizeIndefinite && right == NGSizeIndefinite) {
+ right = static_position.RightPosition(container_size.width, *width,
+ *margin_left, *margin_right);
+ } else if (!width && !right) {
// Rule 3.
- DCHECK(child_auto_width.has_value());
- width = *child_auto_width;
+ DCHECK(child_minmax.has_value());
+ width = child_minmax->ShrinkToFit(container_size.width);
}
// Rules 4 through 6, 1 out of 3 are unknown.
- if (left == NGSizeIndefinite) {
- left = container_size.width - right - width - margin_left - margin_right;
- } else if (right == NGSizeIndefinite) {
- right = container_size.width - left - width - margin_left - margin_right;
- } else if (width == NGSizeIndefinite) {
- width = container_size.width - left - right - margin_left - margin_right;
+ if (!left) {
+ left =
+ container_size.width - *right - *width - *margin_left - *margin_right;
+ } else if (!right) {
+ right =
+ container_size.width - *left - *width - *margin_left - *margin_right;
+ } else if (!width) {
+ width =
+ container_size.width - *left - *right - *margin_left - *margin_right;
}
DCHECK_EQ(container_size.width,
- left + right + margin_left + margin_right + width);
+ *left + *right + *margin_left + *margin_right + *width);
// Negative widths are not allowed.
- width = std::max(width, border_padding);
+ width = std::max(*width, border_padding);
- position->inset.left = left + margin_left;
- position->inset.right = right + margin_right;
- position->size.width = width;
+ position->inset.left = *left + *margin_left;
+ position->inset.right = *right + *margin_right;
+ position->size.width = *width;
}
// Implements absolute vertical size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-height
-void ComputeAbsoluteVertical(const NGConstraintSpace& space,
- const ComputedStyle& style,
- const NGStaticPosition& static_position,
- const Optional<LayoutUnit>& child_auto_height,
- NGAbsolutePhysicalPosition* position) {
- // TODO(atotic) check percentage resolution for vertical writing modes.
- LayoutUnit percentage_inline_size =
- space.PercentageResolutionSize().inline_size;
- LayoutUnit percentage_block_size =
- space.PercentageResolutionSize().block_size;
+void ComputeAbsoluteVertical(
+ const NGConstraintSpace& space,
+ const ComputedStyle& style,
+ const NGStaticPosition& static_position,
+ const Optional<MinAndMaxContentSizes>& child_minmax,
+ NGAbsolutePhysicalPosition* position) {
+ NGLogicalSize percentage_logical = space.PercentageResolutionSize();
+ NGPhysicalSize percentage_physical =
+ percentage_logical.ConvertToPhysical(space.WritingMode());
+
LayoutUnit border_top(style.borderTopWidth());
LayoutUnit border_bottom(style.borderBottomWidth());
- LayoutUnit padding_top = CustomValueForLength(
- style.paddingTop(), percentage_inline_size, LayoutUnit());
- LayoutUnit padding_bottom = CustomValueForLength(
- style.paddingBottom(), percentage_inline_size, LayoutUnit());
- LayoutUnit margin_top =
- CustomValueForLength(style.marginTop(), percentage_inline_size);
- LayoutUnit margin_bottom =
- CustomValueForLength(style.marginBottom(), percentage_inline_size);
- LayoutUnit top = CustomValueForLength(style.top(), percentage_block_size);
- LayoutUnit bottom =
- CustomValueForLength(style.bottom(), percentage_block_size);
+ LayoutUnit padding_top =
+ valueForLength(style.paddingTop(), percentage_logical.inline_size);
+ LayoutUnit padding_bottom =
+ valueForLength(style.paddingBottom(), percentage_logical.inline_size);
+ Optional<LayoutUnit> margin_top;
+ if (!style.marginTop().isAuto())
+ margin_top =
+ valueForLength(style.marginTop(), percentage_logical.inline_size);
+ Optional<LayoutUnit> margin_bottom;
+ if (!style.marginBottom().isAuto())
+ margin_bottom =
+ valueForLength(style.marginBottom(), percentage_logical.inline_size);
+ Optional<LayoutUnit> top;
+ if (!style.top().isAuto())
+ top = valueForLength(style.top(), percentage_physical.height);
+ Optional<LayoutUnit> bottom;
+ if (!style.bottom().isAuto())
+ bottom = valueForLength(style.bottom(), percentage_physical.height);
LayoutUnit border_padding =
border_top + border_bottom + padding_top + padding_bottom;
- // TODO(atotic): This should use Resolve{Inline,Block}Length.
- LayoutUnit height =
- CustomValueForLength(style.height(), percentage_block_size);
- if (style.boxSizing() == EBoxSizing::BoxSizingContentBox &&
- height != NGSizeIndefinite)
- height += border_padding;
+ Optional<LayoutUnit> height;
+ if (!style.height().isAuto()) {
+ if (space.WritingMode() == kHorizontalTopBottom) {
+ LayoutUnit computed_height =
+ child_minmax.has_value() ? child_minmax->max_content : LayoutUnit();
+ height = ResolveBlockLength(space, style, style.height(), computed_height,
+ LengthResolveType::kContentSize);
+ } else {
+ height = ResolveInlineLength(space, style, child_minmax, style.height(),
+ LengthResolveType::kContentSize);
+ }
+ }
NGPhysicalSize container_size =
space.AvailableSize().ConvertToPhysical(space.WritingMode());
@@ -215,24 +231,22 @@ void ComputeAbsoluteVertical(const NGConstraintSpace& space,
// Solving the equation:
// top + marginTop + height + marginBottom + bottom
// + border_padding = container height
- if (top == NGSizeIndefinite && bottom == NGSizeIndefinite &&
- height == NGSizeIndefinite) {
+ if (!top && !bottom && !height) {
// Standard: "If all three of top, height, and bottom are auto:"
- if (margin_top == NGSizeIndefinite)
+ if (!margin_top)
margin_top = LayoutUnit();
- if (margin_bottom == NGSizeIndefinite)
+ if (!margin_bottom)
margin_bottom = LayoutUnit();
- DCHECK(child_auto_height.has_value());
- height = *child_auto_height;
- top = static_position.TopPosition(container_size.height, height, margin_top,
- margin_bottom);
- } else if (top != NGSizeIndefinite && bottom != NGSizeIndefinite &&
- height != NGSizeIndefinite) {
+ DCHECK(child_minmax.has_value());
+ height = child_minmax->ShrinkToFit(container_size.height);
+ top = static_position.TopPosition(container_size.height, *height,
+ *margin_top, *margin_bottom);
+ } else if (top && bottom && height) {
// Standard: "If top, bottom, and height are not auto:"
// Compute margins.
- LayoutUnit margin_space = container_size.height - top - bottom - height;
+ LayoutUnit margin_space = container_size.height - *top - *bottom - *height;
// When both margins are auto.
- if (margin_top == NGSizeIndefinite && margin_bottom == NGSizeIndefinite) {
+ if (!margin_top && !margin_bottom) {
if (margin_space > 0) {
margin_top = margin_space / 2;
margin_bottom = margin_space / 2;
@@ -241,59 +255,62 @@ void ComputeAbsoluteVertical(const NGConstraintSpace& space,
margin_top = LayoutUnit();
margin_bottom = margin_space;
}
- } else if (margin_top == NGSizeIndefinite) {
+ } else if (!margin_top) {
margin_top = margin_space;
- } else if (margin_bottom == NGSizeIndefinite) {
+ } else if (!margin_bottom) {
margin_bottom = margin_space;
} else {
// Are values overconstrained?
- if (margin_top + margin_bottom != margin_space) {
+ if (*margin_top + *margin_bottom != margin_space) {
// Relax the end.
- bottom -= margin_top + margin_bottom - margin_space;
+ bottom = *bottom - *margin_top + *margin_bottom - margin_space;
}
}
}
// Set unknown margins.
- if (margin_top == NGSizeIndefinite)
+ if (!margin_top)
margin_top = LayoutUnit();
- if (margin_bottom == NGSizeIndefinite)
+ if (!margin_bottom)
margin_bottom = LayoutUnit();
// Rules 1 through 3, 2 out of 3 are unknown, fix 1.
- if (top == NGSizeIndefinite && height == NGSizeIndefinite) {
+ if (!top && !height) {
// Rule 1.
- DCHECK_NE(bottom, NGSizeIndefinite);
- DCHECK(child_auto_height.has_value());
- height = *child_auto_height;
- } else if (top == NGSizeIndefinite && bottom == NGSizeIndefinite) {
+ DCHECK(bottom.has_value());
+ DCHECK(child_minmax.has_value());
+ height = child_minmax->ShrinkToFit(container_size.height);
+ } else if (!top && !bottom) {
// Rule 2.
- DCHECK_NE(height, NGSizeIndefinite);
- top = static_position.TopPosition(container_size.height, height, margin_top,
- margin_bottom);
- } else if (height == NGSizeIndefinite && bottom == NGSizeIndefinite) {
+ DCHECK(height.has_value());
+ top = static_position.TopPosition(container_size.height, *height,
+ *margin_top, *margin_bottom);
+ } else if (!height && !bottom) {
// Rule 3.
- DCHECK(child_auto_height.has_value());
- height = *child_auto_height;
+ DCHECK(child_minmax.has_value());
+ height = child_minmax->ShrinkToFit(container_size.height);
}
// Rules 4 through 6, 1 out of 3 are unknown.
- if (top == NGSizeIndefinite) {
- top = container_size.height - bottom - height - margin_top - margin_bottom;
- } else if (bottom == NGSizeIndefinite) {
- bottom = container_size.height - top - height - margin_top - margin_bottom;
- } else if (height == NGSizeIndefinite) {
- height = container_size.height - top - bottom - margin_top - margin_bottom;
+ if (!top) {
+ top = container_size.height - *bottom - *height - *margin_top -
+ *margin_bottom;
+ } else if (!bottom) {
+ bottom =
+ container_size.height - *top - *height - *margin_top - *margin_bottom;
+ } else if (!height) {
+ height =
+ container_size.height - *top - *bottom - *margin_top - *margin_bottom;
}
DCHECK_EQ(container_size.height,
- top + bottom + margin_top + margin_bottom + height);
+ *top + *bottom + *margin_top + *margin_bottom + *height);
// Negative heights are not allowed.
- height = std::max(height, border_padding);
+ height = std::max(*height, border_padding);
- position->inset.top = top + margin_top;
- position->inset.bottom = bottom + margin_bottom;
- position->size.height = height;
+ position->inset.top = *top + *margin_top;
+ position->inset.bottom = *bottom + *margin_bottom;
+ position->size.height = *height;
}
} // namespace
@@ -323,14 +340,15 @@ NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize(
const NGConstraintSpace& space,
const ComputedStyle& style,
const NGStaticPosition& static_position,
- const Optional<LayoutUnit>& child_inline_size) {
+ const Optional<MinAndMaxContentSizes>& child_minmax) {
NGAbsolutePhysicalPosition position;
if (style.isHorizontalWritingMode())
- ComputeAbsoluteHorizontal(space, style, static_position, child_inline_size,
+ ComputeAbsoluteHorizontal(space, style, static_position, child_minmax,
&position);
- else
- ComputeAbsoluteVertical(space, style, static_position, child_inline_size,
+ else {
+ ComputeAbsoluteVertical(space, style, static_position, child_minmax,
&position);
+ }
return position;
}
@@ -340,12 +358,21 @@ void ComputeFullAbsoluteWithChildBlockSize(
const NGStaticPosition& static_position,
const Optional<LayoutUnit>& child_block_size,
NGAbsolutePhysicalPosition* position) {
+ // After partial size has been computed, child block size is either
+ // unknown, or fully computed, there is no minmax.
+ // To express this, a 'fixed' minmax is created where
+ // min and max are the same.
+ Optional<MinAndMaxContentSizes> child_minmax;
+ if (child_block_size.has_value()) {
+ child_minmax = MinAndMaxContentSizes{*child_block_size, *child_block_size};
+ }
if (style.isHorizontalWritingMode())
- ComputeAbsoluteVertical(space, style, static_position, child_block_size,
+ ComputeAbsoluteVertical(space, style, static_position, child_minmax,
position);
- else
- ComputeAbsoluteHorizontal(space, style, static_position, child_block_size,
+ else {
+ ComputeAbsoluteHorizontal(space, style, static_position, child_minmax,
position);
+ }
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698