Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/ng/ng_absolute_utils.h" | 5 #include "core/layout/ng/ng_absolute_utils.h" |
| 6 | 6 |
| 7 #include "core/layout/ng/ng_constraint_space.h" | 7 #include "core/layout/ng/ng_constraint_space.h" |
| 8 #include "core/layout/ng/ng_length_utils.h" | 8 #include "core/layout/ng/ng_length_utils.h" |
| 9 #include "core/style/ComputedStyle.h" | 9 #include "core/style/ComputedStyle.h" |
| 10 #include "platform/LengthFunctions.h" | 10 #include "platform/LengthFunctions.h" |
| 11 | 11 |
| 12 namespace blink { | 12 namespace blink { |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 // Extends Length::valueForLength with default value if length type is auto. | |
| 17 LayoutUnit CustomValueForLength(const Length& length, | |
| 18 LayoutUnit max_value, | |
| 19 LayoutUnit default_value = NGSizeIndefinite) { | |
| 20 if (length.isAuto()) | |
| 21 return default_value; | |
| 22 DCHECK(!length.isPercentOrCalc() || max_value != NGSizeIndefinite); | |
| 23 return valueForLength(length, max_value); | |
| 24 } | |
| 25 | |
| 26 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { | 16 bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) { |
| 27 return style.width().isAuto() && | 17 Length width = style.width(); |
| 28 (style.left().isAuto() || style.right().isAuto()); | 18 return width.isIntrinsic() || |
| 19 (width.isAuto() && (style.left().isAuto() || style.right().isAuto())); | |
| 29 } | 20 } |
| 30 | 21 |
| 31 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { | 22 bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) { |
| 32 return style.height().isAuto() && | 23 Length height = style.height(); |
| 33 (style.top().isAuto() || style.bottom().isAuto()); | 24 return height.isIntrinsic() || |
| 25 (height.isAuto() && (style.top().isAuto() || style.bottom().isAuto())); | |
| 34 } | 26 } |
| 35 | 27 |
| 36 // Implement absolute horizontal size resolution algorithm. | 28 // Implement absolute horizontal size resolution algorithm. |
| 37 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width | 29 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width |
| 38 void ComputeAbsoluteHorizontal(const NGConstraintSpace& space, | 30 void ComputeAbsoluteHorizontal( |
| 39 const ComputedStyle& style, | 31 const NGConstraintSpace& space, |
| 40 const NGStaticPosition& static_position, | 32 const ComputedStyle& style, |
| 41 const Optional<LayoutUnit>& child_auto_width, | 33 const NGStaticPosition& static_position, |
| 42 NGAbsolutePhysicalPosition* position) { | 34 const Optional<MinAndMaxContentSizes>& child_minmax, |
| 43 // Always use inline_size for percent resolution. | 35 NGAbsolutePhysicalPosition* position) { |
| 44 // TODO(atotic) test whether inline_size is correct in vertical modes. | 36 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
| 45 LayoutUnit percentage_resolution_size = | 37 NGPhysicalSize percentage_physical = |
| 46 space.PercentageResolutionSize().inline_size; | 38 percentage_logical.ConvertToPhysical(space.WritingMode()); |
| 47 LayoutUnit border_left(style.borderLeftWidth()); | 39 LayoutUnit border_left(style.borderLeftWidth()); |
| 48 LayoutUnit border_right(style.borderRightWidth()); | 40 LayoutUnit border_right(style.borderRightWidth()); |
| 49 LayoutUnit padding_left = CustomValueForLength( | 41 LayoutUnit padding_left = |
| 50 style.paddingLeft(), percentage_resolution_size, LayoutUnit()); | 42 valueForLength(style.paddingLeft(), percentage_logical.block_size); |
|
cbiesinger
2017/01/05 16:48:23
Why is this resolved against the block size?
atotic
2017/01/05 19:03:26
done. also paddingRight
my brain still has a hard
| |
| 51 LayoutUnit padding_right = CustomValueForLength( | 43 LayoutUnit padding_right = |
| 52 style.paddingRight(), percentage_resolution_size, LayoutUnit()); | 44 valueForLength(style.paddingRight(), percentage_logical.block_size); |
| 53 LayoutUnit margin_left = | 45 Optional<LayoutUnit> margin_left; |
| 54 CustomValueForLength(style.marginLeft(), percentage_resolution_size); | 46 if (!style.marginLeft().isAuto()) |
| 55 LayoutUnit margin_right = | 47 margin_left = |
| 56 CustomValueForLength(style.marginRight(), percentage_resolution_size); | 48 valueForLength(style.marginLeft(), percentage_logical.inline_size); |
| 57 LayoutUnit left = | 49 Optional<LayoutUnit> margin_right; |
| 58 CustomValueForLength(style.left(), percentage_resolution_size); | 50 if (!style.marginRight().isAuto()) |
| 59 LayoutUnit right = | 51 margin_right = |
| 60 CustomValueForLength(style.right(), percentage_resolution_size); | 52 valueForLength(style.marginRight(), percentage_logical.inline_size); |
| 53 Optional<LayoutUnit> left; | |
| 54 if (!style.left().isAuto()) | |
| 55 left = valueForLength(style.left(), percentage_physical.width); | |
| 56 Optional<LayoutUnit> right; | |
| 57 if (!style.right().isAuto()) | |
| 58 right = valueForLength(style.right(), percentage_physical.width); | |
| 61 LayoutUnit border_padding = | 59 LayoutUnit border_padding = |
| 62 border_left + border_right + padding_left + padding_right; | 60 border_left + border_right + padding_left + padding_right; |
| 63 // TODO(atotic): This should use Resolve{Inline,Block}Length | 61 Optional<LayoutUnit> width; |
| 64 LayoutUnit width = | 62 if (!style.width().isAuto()) { |
| 65 CustomValueForLength(style.width(), percentage_resolution_size); | 63 if (space.WritingMode() == kHorizontalTopBottom) { |
| 66 | 64 width = ResolveInlineLength(space, style, child_minmax, style.width(), |
| 67 // Normalize width to border-box sizing. | 65 LengthResolveType::kContentSize); |
| 68 if (style.boxSizing() == EBoxSizing::BoxSizingContentBox && | 66 } else { |
| 69 width != NGSizeIndefinite) | 67 LayoutUnit computed_width = |
| 70 width += border_padding; | 68 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); |
| 69 width = ResolveBlockLength(space, style, style.width(), computed_width, | |
| 70 LengthResolveType::kContentSize); | |
| 71 } | |
| 72 } | |
| 71 | 73 |
| 72 NGPhysicalSize container_size = | 74 NGPhysicalSize container_size = |
| 73 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 75 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
| 74 DCHECK(container_size.width != NGSizeIndefinite); | 76 DCHECK(container_size.width != NGSizeIndefinite); |
| 75 | 77 |
| 76 // Solving the equation: | 78 // Solving the equation: |
| 77 // left + marginLeft + width + marginRight + right = container width | 79 // left + marginLeft + width + marginRight + right = container width |
| 78 if (left == NGSizeIndefinite && right == NGSizeIndefinite && | 80 if (!left && !right && !width) { |
| 79 width == NGSizeIndefinite) { | |
| 80 // Standard: "If all three of left, width, and right are auto:" | 81 // Standard: "If all three of left, width, and right are auto:" |
| 81 if (margin_left == NGSizeIndefinite) | 82 if (!margin_left) |
| 82 margin_left = LayoutUnit(); | 83 margin_left = LayoutUnit(); |
| 83 if (margin_right == NGSizeIndefinite) | 84 if (!margin_right) |
| 84 margin_right = LayoutUnit(); | 85 margin_right = LayoutUnit(); |
| 85 DCHECK(child_auto_width.has_value()); | 86 DCHECK(child_minmax.has_value()); |
| 86 width = *child_auto_width; | 87 width = child_minmax->ShrinkToFit(container_size.width); |
| 87 if (space.Direction() == TextDirection::Ltr) { | 88 if (space.Direction() == TextDirection::Ltr) { |
| 88 left = static_position.LeftPosition(container_size.width, width, | 89 left = static_position.LeftPosition(container_size.width, *width, |
| 89 margin_left, margin_right); | 90 *margin_left, *margin_right); |
| 90 } else { | 91 } else { |
| 91 right = static_position.RightPosition(container_size.width, width, | 92 right = static_position.RightPosition(container_size.width, *width, |
| 92 margin_left, margin_right); | 93 *margin_left, *margin_right); |
| 93 } | 94 } |
| 94 } else if (left != NGSizeIndefinite && right != NGSizeIndefinite && | 95 } else if (left && right && width) { |
| 95 width != NGSizeIndefinite) { | |
| 96 // Standard: "If left, right, and width are not auto:" | 96 // Standard: "If left, right, and width are not auto:" |
| 97 // Compute margins. | 97 // Compute margins. |
| 98 LayoutUnit margin_space = container_size.width - left - right - width; | 98 LayoutUnit margin_space = container_size.width - *left - *right - *width; |
| 99 // When both margins are auto. | 99 // When both margins are auto. |
| 100 if (margin_left == NGSizeIndefinite && margin_right == NGSizeIndefinite) { | 100 if (!margin_left && !margin_right) { |
| 101 if (margin_space > 0) { | 101 if (margin_space > 0) { |
| 102 margin_left = margin_space / 2; | 102 margin_left = margin_space / 2; |
| 103 margin_right = margin_space / 2; | 103 margin_right = margin_space / 2; |
| 104 } else { | 104 } else { |
| 105 // Margins are negative. | 105 // Margins are negative. |
| 106 if (space.Direction() == TextDirection::Ltr) { | 106 if (space.Direction() == TextDirection::Ltr) { |
| 107 margin_left = LayoutUnit(); | 107 margin_left = LayoutUnit(); |
| 108 margin_right = margin_space; | 108 margin_right = margin_space; |
| 109 } else { | 109 } else { |
| 110 margin_right = LayoutUnit(); | 110 margin_right = LayoutUnit(); |
| 111 margin_left = margin_space; | 111 margin_left = margin_space; |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 } else if (margin_left == NGSizeIndefinite) { | 114 } else if (!margin_left) { |
| 115 margin_left = margin_space; | 115 margin_left = margin_space; |
| 116 } else if (margin_right == NGSizeIndefinite) { | 116 } else if (!margin_right) { |
| 117 margin_right = margin_space; | 117 margin_right = margin_space; |
| 118 } else { | 118 } else { |
| 119 // Are values overconstrained? | 119 // Are values overconstrained? |
| 120 if (margin_left + margin_right != margin_space) { | 120 if (*margin_left + *margin_right != margin_space) { |
| 121 // Relax the end. | 121 // Relax the end. |
| 122 if (space.Direction() == TextDirection::Ltr) | 122 if (space.Direction() == TextDirection::Ltr) |
| 123 right -= margin_left + margin_right - margin_space; | 123 right = *right - *margin_left + *margin_right - margin_space; |
| 124 else | 124 else |
| 125 left -= margin_left + margin_right - margin_space; | 125 left = *left - *margin_left + *margin_right - margin_space; |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 | 129 |
| 130 // Set unknown margins. | 130 // Set unknown margins. |
| 131 if (margin_left == NGSizeIndefinite) | 131 if (!margin_left) |
| 132 margin_left = LayoutUnit(); | 132 margin_left = LayoutUnit(); |
| 133 if (margin_right == NGSizeIndefinite) | 133 if (!margin_right) |
| 134 margin_right = LayoutUnit(); | 134 margin_right = LayoutUnit(); |
| 135 | 135 |
| 136 // Rules 1 through 3, 2 out of 3 are unknown. | 136 // Rules 1 through 3, 2 out of 3 are unknown. |
| 137 if (left == NGSizeIndefinite && width == NGSizeIndefinite) { | 137 if (!left && !width) { |
| 138 // Rule 1: left/width are unknown. | 138 // Rule 1: left/width are unknown. |
| 139 DCHECK_NE(right, NGSizeIndefinite); | 139 DCHECK(right.has_value()); |
| 140 DCHECK(child_auto_width.has_value()); | 140 DCHECK(child_minmax.has_value()); |
| 141 width = *child_auto_width; | 141 width = child_minmax->ShrinkToFit(container_size.width); |
| 142 } else if (left == NGSizeIndefinite && right == NGSizeIndefinite) { | 142 } else if (!left && !right) { |
| 143 // Rule 2. | 143 // Rule 2. |
| 144 DCHECK_NE(width, NGSizeIndefinite); | 144 DCHECK(width.has_value()); |
| 145 if (space.Direction() == TextDirection::Ltr) | 145 if (space.Direction() == TextDirection::Ltr) |
| 146 left = static_position.LeftPosition(container_size.width, width, | 146 left = static_position.LeftPosition(container_size.width, *width, |
| 147 margin_left, margin_right); | 147 *margin_left, *margin_right); |
| 148 else | 148 else |
| 149 right = static_position.RightPosition(container_size.width, width, | 149 right = static_position.RightPosition(container_size.width, *width, |
| 150 margin_left, margin_right); | 150 *margin_left, *margin_right); |
| 151 } else if (width == NGSizeIndefinite && right == NGSizeIndefinite) { | 151 } else if (!width && !right) { |
| 152 // Rule 3. | 152 // Rule 3. |
| 153 DCHECK(child_auto_width.has_value()); | 153 DCHECK(child_minmax.has_value()); |
| 154 width = *child_auto_width; | 154 width = child_minmax->ShrinkToFit(container_size.width); |
| 155 } | 155 } |
| 156 | 156 |
| 157 // Rules 4 through 6, 1 out of 3 are unknown. | 157 // Rules 4 through 6, 1 out of 3 are unknown. |
| 158 if (left == NGSizeIndefinite) { | 158 if (!left) { |
| 159 left = container_size.width - right - width - margin_left - margin_right; | 159 left = |
| 160 } else if (right == NGSizeIndefinite) { | 160 container_size.width - *right - *width - *margin_left - *margin_right; |
| 161 right = container_size.width - left - width - margin_left - margin_right; | 161 } else if (!right) { |
| 162 } else if (width == NGSizeIndefinite) { | 162 right = |
| 163 width = container_size.width - left - right - margin_left - margin_right; | 163 container_size.width - *left - *width - *margin_left - *margin_right; |
| 164 } else if (!width) { | |
| 165 width = | |
| 166 container_size.width - *left - *right - *margin_left - *margin_right; | |
| 164 } | 167 } |
| 165 DCHECK_EQ(container_size.width, | 168 DCHECK_EQ(container_size.width, |
| 166 left + right + margin_left + margin_right + width); | 169 *left + *right + *margin_left + *margin_right + *width); |
| 167 | 170 |
| 168 // Negative widths are not allowed. | 171 // Negative widths are not allowed. |
| 169 width = std::max(width, border_padding); | 172 width = std::max(*width, border_padding); |
| 170 | 173 |
| 171 position->inset.left = left + margin_left; | 174 position->inset.left = *left + *margin_left; |
| 172 position->inset.right = right + margin_right; | 175 position->inset.right = *right + *margin_right; |
| 173 position->size.width = width; | 176 position->size.width = *width; |
| 174 } | 177 } |
| 175 | 178 |
| 176 // Implements absolute vertical size resolution algorithm. | 179 // Implements absolute vertical size resolution algorithm. |
| 177 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height | 180 // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height |
| 178 void ComputeAbsoluteVertical(const NGConstraintSpace& space, | 181 void ComputeAbsoluteVertical( |
| 179 const ComputedStyle& style, | 182 const NGConstraintSpace& space, |
| 180 const NGStaticPosition& static_position, | 183 const ComputedStyle& style, |
| 181 const Optional<LayoutUnit>& child_auto_height, | 184 const NGStaticPosition& static_position, |
| 182 NGAbsolutePhysicalPosition* position) { | 185 const Optional<MinAndMaxContentSizes>& child_minmax, |
| 183 // TODO(atotic) check percentage resolution for vertical writing modes. | 186 NGAbsolutePhysicalPosition* position) { |
| 184 LayoutUnit percentage_inline_size = | 187 NGLogicalSize percentage_logical = space.PercentageResolutionSize(); |
| 185 space.PercentageResolutionSize().inline_size; | 188 NGPhysicalSize percentage_physical = |
| 186 LayoutUnit percentage_block_size = | 189 percentage_logical.ConvertToPhysical(space.WritingMode()); |
| 187 space.PercentageResolutionSize().block_size; | 190 |
| 188 LayoutUnit border_top(style.borderTopWidth()); | 191 LayoutUnit border_top(style.borderTopWidth()); |
| 189 LayoutUnit border_bottom(style.borderBottomWidth()); | 192 LayoutUnit border_bottom(style.borderBottomWidth()); |
| 190 LayoutUnit padding_top = CustomValueForLength( | 193 LayoutUnit padding_top = |
| 191 style.paddingTop(), percentage_inline_size, LayoutUnit()); | 194 valueForLength(style.paddingTop(), percentage_logical.block_size); |
|
cbiesinger
2017/01/05 16:48:23
This should also use inline_size, right?
atotic
2017/01/05 19:03:25
done.
| |
| 192 LayoutUnit padding_bottom = CustomValueForLength( | 195 LayoutUnit padding_bottom = |
| 193 style.paddingBottom(), percentage_inline_size, LayoutUnit()); | 196 valueForLength(style.paddingBottom(), percentage_logical.block_size); |
| 194 LayoutUnit margin_top = | 197 Optional<LayoutUnit> margin_top; |
| 195 CustomValueForLength(style.marginTop(), percentage_inline_size); | 198 if (!style.marginTop().isAuto()) |
| 196 LayoutUnit margin_bottom = | 199 margin_top = |
| 197 CustomValueForLength(style.marginBottom(), percentage_inline_size); | 200 valueForLength(style.marginTop(), percentage_logical.inline_size); |
| 198 LayoutUnit top = CustomValueForLength(style.top(), percentage_block_size); | 201 Optional<LayoutUnit> margin_bottom; |
| 199 LayoutUnit bottom = | 202 if (!style.marginBottom().isAuto()) |
| 200 CustomValueForLength(style.bottom(), percentage_block_size); | 203 margin_bottom = |
| 204 valueForLength(style.marginBottom(), percentage_logical.inline_size); | |
| 205 Optional<LayoutUnit> top; | |
| 206 if (!style.top().isAuto()) | |
| 207 top = valueForLength(style.top(), percentage_physical.height); | |
| 208 Optional<LayoutUnit> bottom; | |
| 209 if (!style.bottom().isAuto()) | |
| 210 bottom = valueForLength(style.bottom(), percentage_physical.height); | |
| 201 LayoutUnit border_padding = | 211 LayoutUnit border_padding = |
| 202 border_top + border_bottom + padding_top + padding_bottom; | 212 border_top + border_bottom + padding_top + padding_bottom; |
| 203 // TODO(atotic): This should use Resolve{Inline,Block}Length. | |
| 204 LayoutUnit height = | |
| 205 CustomValueForLength(style.height(), percentage_block_size); | |
| 206 | 213 |
| 207 if (style.boxSizing() == EBoxSizing::BoxSizingContentBox && | 214 Optional<LayoutUnit> height; |
| 208 height != NGSizeIndefinite) | 215 if (!style.height().isAuto()) { |
| 209 height += border_padding; | 216 if (space.WritingMode() == kHorizontalTopBottom) { |
| 217 LayoutUnit computed_height = | |
| 218 child_minmax.has_value() ? child_minmax->max_content : LayoutUnit(); | |
| 219 height = ResolveBlockLength(space, style, style.height(), computed_height, | |
| 220 LengthResolveType::kContentSize); | |
| 221 } else { | |
| 222 height = ResolveInlineLength(space, style, child_minmax, style.height(), | |
| 223 LengthResolveType::kContentSize); | |
| 224 } | |
| 225 } | |
| 210 | 226 |
| 211 NGPhysicalSize container_size = | 227 NGPhysicalSize container_size = |
| 212 space.AvailableSize().ConvertToPhysical(space.WritingMode()); | 228 space.AvailableSize().ConvertToPhysical(space.WritingMode()); |
| 213 DCHECK(container_size.height != NGSizeIndefinite); | 229 DCHECK(container_size.height != NGSizeIndefinite); |
| 214 | 230 |
| 215 // Solving the equation: | 231 // Solving the equation: |
| 216 // top + marginTop + height + marginBottom + bottom | 232 // top + marginTop + height + marginBottom + bottom |
| 217 // + border_padding = container height | 233 // + border_padding = container height |
| 218 if (top == NGSizeIndefinite && bottom == NGSizeIndefinite && | 234 if (!top && !bottom && !height) { |
| 219 height == NGSizeIndefinite) { | |
| 220 // Standard: "If all three of top, height, and bottom are auto:" | 235 // Standard: "If all three of top, height, and bottom are auto:" |
| 221 if (margin_top == NGSizeIndefinite) | 236 if (!margin_top) |
| 222 margin_top = LayoutUnit(); | 237 margin_top = LayoutUnit(); |
| 223 if (margin_bottom == NGSizeIndefinite) | 238 if (!margin_bottom) |
| 224 margin_bottom = LayoutUnit(); | 239 margin_bottom = LayoutUnit(); |
| 225 DCHECK(child_auto_height.has_value()); | 240 DCHECK(child_minmax.has_value()); |
| 226 height = *child_auto_height; | 241 height = child_minmax->ShrinkToFit(container_size.height); |
| 227 top = static_position.TopPosition(container_size.height, height, margin_top, | 242 top = static_position.TopPosition(container_size.height, *height, |
| 228 margin_bottom); | 243 *margin_top, *margin_bottom); |
| 229 } else if (top != NGSizeIndefinite && bottom != NGSizeIndefinite && | 244 } else if (top && bottom && height) { |
| 230 height != NGSizeIndefinite) { | |
| 231 // Standard: "If top, bottom, and height are not auto:" | 245 // Standard: "If top, bottom, and height are not auto:" |
| 232 // Compute margins. | 246 // Compute margins. |
| 233 LayoutUnit margin_space = container_size.height - top - bottom - height; | 247 LayoutUnit margin_space = container_size.height - *top - *bottom - *height; |
| 234 // When both margins are auto. | 248 // When both margins are auto. |
| 235 if (margin_top == NGSizeIndefinite && margin_bottom == NGSizeIndefinite) { | 249 if (!margin_top && !margin_bottom) { |
| 236 if (margin_space > 0) { | 250 if (margin_space > 0) { |
| 237 margin_top = margin_space / 2; | 251 margin_top = margin_space / 2; |
| 238 margin_bottom = margin_space / 2; | 252 margin_bottom = margin_space / 2; |
| 239 } else { | 253 } else { |
| 240 // Margin space is over-constrained. | 254 // Margin space is over-constrained. |
| 241 margin_top = LayoutUnit(); | 255 margin_top = LayoutUnit(); |
| 242 margin_bottom = margin_space; | 256 margin_bottom = margin_space; |
| 243 } | 257 } |
| 244 } else if (margin_top == NGSizeIndefinite) { | 258 } else if (!margin_top) { |
| 245 margin_top = margin_space; | 259 margin_top = margin_space; |
| 246 } else if (margin_bottom == NGSizeIndefinite) { | 260 } else if (!margin_bottom) { |
| 247 margin_bottom = margin_space; | 261 margin_bottom = margin_space; |
| 248 } else { | 262 } else { |
| 249 // Are values overconstrained? | 263 // Are values overconstrained? |
| 250 if (margin_top + margin_bottom != margin_space) { | 264 if (*margin_top + *margin_bottom != margin_space) { |
| 251 // Relax the end. | 265 // Relax the end. |
| 252 bottom -= margin_top + margin_bottom - margin_space; | 266 bottom = *bottom - *margin_top + *margin_bottom - margin_space; |
| 253 } | 267 } |
| 254 } | 268 } |
| 255 } | 269 } |
| 256 | 270 |
| 257 // Set unknown margins. | 271 // Set unknown margins. |
| 258 if (margin_top == NGSizeIndefinite) | 272 if (!margin_top) |
| 259 margin_top = LayoutUnit(); | 273 margin_top = LayoutUnit(); |
| 260 if (margin_bottom == NGSizeIndefinite) | 274 if (!margin_bottom) |
| 261 margin_bottom = LayoutUnit(); | 275 margin_bottom = LayoutUnit(); |
| 262 | 276 |
| 263 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. | 277 // Rules 1 through 3, 2 out of 3 are unknown, fix 1. |
| 264 if (top == NGSizeIndefinite && height == NGSizeIndefinite) { | 278 if (!top && !height) { |
| 265 // Rule 1. | 279 // Rule 1. |
| 266 DCHECK_NE(bottom, NGSizeIndefinite); | 280 DCHECK(bottom.has_value()); |
| 267 DCHECK(child_auto_height.has_value()); | 281 DCHECK(child_minmax.has_value()); |
| 268 height = *child_auto_height; | 282 height = child_minmax->ShrinkToFit(container_size.height); |
| 269 } else if (top == NGSizeIndefinite && bottom == NGSizeIndefinite) { | 283 } else if (!top && !bottom) { |
| 270 // Rule 2. | 284 // Rule 2. |
| 271 DCHECK_NE(height, NGSizeIndefinite); | 285 DCHECK(height.has_value()); |
| 272 top = static_position.TopPosition(container_size.height, height, margin_top, | 286 top = static_position.TopPosition(container_size.height, *height, |
| 273 margin_bottom); | 287 *margin_top, *margin_bottom); |
| 274 } else if (height == NGSizeIndefinite && bottom == NGSizeIndefinite) { | 288 } else if (!height && !bottom) { |
| 275 // Rule 3. | 289 // Rule 3. |
| 276 DCHECK(child_auto_height.has_value()); | 290 DCHECK(child_minmax.has_value()); |
| 277 height = *child_auto_height; | 291 height = child_minmax->ShrinkToFit(container_size.height); |
| 278 } | 292 } |
| 279 | 293 |
| 280 // Rules 4 through 6, 1 out of 3 are unknown. | 294 // Rules 4 through 6, 1 out of 3 are unknown. |
| 281 if (top == NGSizeIndefinite) { | 295 if (!top) { |
| 282 top = container_size.height - bottom - height - margin_top - margin_bottom; | 296 top = container_size.height - *bottom - *height - *margin_top - |
| 283 } else if (bottom == NGSizeIndefinite) { | 297 *margin_bottom; |
| 284 bottom = container_size.height - top - height - margin_top - margin_bottom; | 298 } else if (!bottom) { |
| 285 } else if (height == NGSizeIndefinite) { | 299 bottom = |
| 286 height = container_size.height - top - bottom - margin_top - margin_bottom; | 300 container_size.height - *top - *height - *margin_top - *margin_bottom; |
| 301 } else if (!height) { | |
| 302 height = | |
| 303 container_size.height - *top - *bottom - *margin_top - *margin_bottom; | |
| 287 } | 304 } |
| 288 DCHECK_EQ(container_size.height, | 305 DCHECK_EQ(container_size.height, |
| 289 top + bottom + margin_top + margin_bottom + height); | 306 *top + *bottom + *margin_top + *margin_bottom + *height); |
| 290 | 307 |
| 291 // Negative heights are not allowed. | 308 // Negative heights are not allowed. |
| 292 height = std::max(height, border_padding); | 309 height = std::max(*height, border_padding); |
| 293 | 310 |
| 294 position->inset.top = top + margin_top; | 311 position->inset.top = *top + *margin_top; |
| 295 position->inset.bottom = bottom + margin_bottom; | 312 position->inset.bottom = *bottom + *margin_bottom; |
| 296 position->size.height = height; | 313 position->size.height = *height; |
| 297 } | 314 } |
| 298 | 315 |
| 299 } // namespace | 316 } // namespace |
| 300 | 317 |
| 301 String NGAbsolutePhysicalPosition::ToString() const { | 318 String NGAbsolutePhysicalPosition::ToString() const { |
| 302 return String::format("INSET(LRTB):%d,%d,%d,%d SIZE:%dx%d", | 319 return String::format("INSET(LRTB):%d,%d,%d,%d SIZE:%dx%d", |
| 303 inset.left.toInt(), inset.right.toInt(), | 320 inset.left.toInt(), inset.right.toInt(), |
| 304 inset.top.toInt(), inset.bottom.toInt(), | 321 inset.top.toInt(), inset.bottom.toInt(), |
| 305 size.width.toInt(), size.height.toInt()); | 322 size.width.toInt(), size.height.toInt()); |
| 306 } | 323 } |
| 307 | 324 |
| 308 bool AbsoluteNeedsChildBlockSize(const ComputedStyle& style) { | 325 bool AbsoluteNeedsChildBlockSize(const ComputedStyle& style) { |
| 309 if (style.isHorizontalWritingMode()) | 326 if (style.isHorizontalWritingMode()) |
| 310 return AbsoluteVerticalNeedsEstimate(style); | 327 return AbsoluteVerticalNeedsEstimate(style); |
| 311 else | 328 else |
| 312 return AbsoluteHorizontalNeedsEstimate(style); | 329 return AbsoluteHorizontalNeedsEstimate(style); |
| 313 } | 330 } |
| 314 | 331 |
| 315 bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) { | 332 bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) { |
| 316 if (style.isHorizontalWritingMode()) | 333 if (style.isHorizontalWritingMode()) |
| 317 return AbsoluteHorizontalNeedsEstimate(style); | 334 return AbsoluteHorizontalNeedsEstimate(style); |
| 318 else | 335 else |
| 319 return AbsoluteVerticalNeedsEstimate(style); | 336 return AbsoluteVerticalNeedsEstimate(style); |
| 320 } | 337 } |
| 321 | 338 |
| 322 NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize( | 339 NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize( |
| 323 const NGConstraintSpace& space, | 340 const NGConstraintSpace& space, |
| 324 const ComputedStyle& style, | 341 const ComputedStyle& style, |
| 325 const NGStaticPosition& static_position, | 342 const NGStaticPosition& static_position, |
| 326 const Optional<LayoutUnit>& child_inline_size) { | 343 const Optional<MinAndMaxContentSizes>& child_minmax) { |
| 327 NGAbsolutePhysicalPosition position; | 344 NGAbsolutePhysicalPosition position; |
| 328 if (style.isHorizontalWritingMode()) | 345 if (style.isHorizontalWritingMode()) |
| 329 ComputeAbsoluteHorizontal(space, style, static_position, child_inline_size, | 346 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, |
| 330 &position); | 347 &position); |
| 331 else | 348 else { |
| 332 ComputeAbsoluteVertical(space, style, static_position, child_inline_size, | 349 ComputeAbsoluteVertical(space, style, static_position, child_minmax, |
| 333 &position); | 350 &position); |
| 351 } | |
| 334 return position; | 352 return position; |
| 335 } | 353 } |
| 336 | 354 |
| 337 void ComputeFullAbsoluteWithChildBlockSize( | 355 void ComputeFullAbsoluteWithChildBlockSize( |
| 338 const NGConstraintSpace& space, | 356 const NGConstraintSpace& space, |
| 339 const ComputedStyle& style, | 357 const ComputedStyle& style, |
| 340 const NGStaticPosition& static_position, | 358 const NGStaticPosition& static_position, |
| 341 const Optional<LayoutUnit>& child_block_size, | 359 const Optional<LayoutUnit>& child_block_size, |
| 342 NGAbsolutePhysicalPosition* position) { | 360 NGAbsolutePhysicalPosition* position) { |
| 361 // After partial size has been computed, child block size is either | |
| 362 // unknown, or fully computed, there is no minmax. | |
| 363 // To express this, a 'fixed' minmax is created where | |
| 364 // min and max are the same. | |
| 365 Optional<MinAndMaxContentSizes> child_minmax; | |
| 366 if (child_block_size.has_value()) { | |
| 367 child_minmax = MinAndMaxContentSizes{*child_block_size, *child_block_size}; | |
|
cbiesinger
2017/01/05 16:48:23
This should use the overflow size, I think?
atotic
2017/01/05 19:03:26
I am unsure. child_minmax was originally used for
| |
| 368 } | |
| 343 if (style.isHorizontalWritingMode()) | 369 if (style.isHorizontalWritingMode()) |
| 344 ComputeAbsoluteVertical(space, style, static_position, child_block_size, | 370 ComputeAbsoluteVertical(space, style, static_position, child_minmax, |
| 345 position); | 371 position); |
| 346 else | 372 else { |
| 347 ComputeAbsoluteHorizontal(space, style, static_position, child_block_size, | 373 ComputeAbsoluteHorizontal(space, style, static_position, child_minmax, |
| 348 position); | 374 position); |
| 375 } | |
| 349 } | 376 } |
| 350 | 377 |
| 351 } // namespace blink | 378 } // namespace blink |
| OLD | NEW |