OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org) | 3 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org) |
4 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
5 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 return true; | 122 return true; |
123 } | 123 } |
124 | 124 |
125 if (style()->logicalHeight().isIntrinsic()) | 125 if (style()->logicalHeight().isIntrinsic()) |
126 return true; | 126 return true; |
127 | 127 |
128 return false; | 128 return false; |
129 } | 129 } |
130 | 130 |
131 bool LayoutReplaced::needsPreferredWidthsRecalculation() const { | 131 bool LayoutReplaced::needsPreferredWidthsRecalculation() const { |
132 // If the height is a percentage and the width is auto, then the containingBlo cks's height changing can cause | 132 // If the height is a percentage and the width is auto, then the |
133 // this node to change it's preferred width because it maintains aspect ratio. | 133 // containingBlocks's height changing can cause this node to change it's |
134 // preferred width because it maintains aspect ratio. | |
134 return hasRelativeLogicalHeight() && style()->logicalWidth().isAuto() && | 135 return hasRelativeLogicalHeight() && style()->logicalWidth().isAuto() && |
135 !hasAutoHeightOrContainingBlockWithAutoHeight(); | 136 !hasAutoHeightOrContainingBlockWithAutoHeight(); |
136 } | 137 } |
137 | 138 |
138 static inline bool layoutObjectHasAspectRatio( | 139 static inline bool layoutObjectHasAspectRatio( |
139 const LayoutObject* layoutObject) { | 140 const LayoutObject* layoutObject) { |
140 ASSERT(layoutObject); | 141 ASSERT(layoutObject); |
141 return layoutObject->isImage() || layoutObject->isCanvas() || | 142 return layoutObject->isImage() || layoutObject->isCanvas() || |
142 layoutObject->isVideo(); | 143 layoutObject->isVideo(); |
143 } | 144 } |
144 | 145 |
145 void LayoutReplaced::computeIntrinsicSizingInfoForReplacedContent( | 146 void LayoutReplaced::computeIntrinsicSizingInfoForReplacedContent( |
146 LayoutReplaced* contentLayoutObject, | 147 LayoutReplaced* contentLayoutObject, |
147 IntrinsicSizingInfo& intrinsicSizingInfo) const { | 148 IntrinsicSizingInfo& intrinsicSizingInfo) const { |
148 if (contentLayoutObject) { | 149 if (contentLayoutObject) { |
149 contentLayoutObject->computeIntrinsicSizingInfo(intrinsicSizingInfo); | 150 contentLayoutObject->computeIntrinsicSizingInfo(intrinsicSizingInfo); |
150 | 151 |
151 // Handle zoom & vertical writing modes here, as the embedded document doesn 't know about them. | 152 // Handle zoom & vertical writing modes here, as the embedded document |
153 // doesn't know about them. | |
152 intrinsicSizingInfo.size.scale(style()->effectiveZoom()); | 154 intrinsicSizingInfo.size.scale(style()->effectiveZoom()); |
153 if (isLayoutImage()) | 155 if (isLayoutImage()) |
154 intrinsicSizingInfo.size.scale( | 156 intrinsicSizingInfo.size.scale( |
155 toLayoutImage(this)->imageDevicePixelRatio()); | 157 toLayoutImage(this)->imageDevicePixelRatio()); |
156 | 158 |
157 // Update our intrinsic size to match what the content layoutObject has comp uted, so that when we | 159 // Update our intrinsic size to match what the content layoutObject has |
158 // constrain the size below, the correct intrinsic size will be obtained for comparison against | 160 // computed, so that when we constrain the size below, the correct intrinsic |
159 // min and max widths. | 161 // size will be obtained for comparison against min and max widths. |
160 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && | 162 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && |
161 !intrinsicSizingInfo.size.isEmpty()) | 163 !intrinsicSizingInfo.size.isEmpty()) |
162 m_intrinsicSize = LayoutSize(intrinsicSizingInfo.size); | 164 m_intrinsicSize = LayoutSize(intrinsicSizingInfo.size); |
163 | 165 |
164 if (!isHorizontalWritingMode()) | 166 if (!isHorizontalWritingMode()) |
165 intrinsicSizingInfo.transpose(); | 167 intrinsicSizingInfo.transpose(); |
166 } else { | 168 } else { |
167 computeIntrinsicSizingInfo(intrinsicSizingInfo); | 169 computeIntrinsicSizingInfo(intrinsicSizingInfo); |
168 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && | 170 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && |
169 !intrinsicSizingInfo.size.isEmpty()) | 171 !intrinsicSizingInfo.size.isEmpty()) |
170 m_intrinsicSize = | 172 m_intrinsicSize = |
171 LayoutSize(isHorizontalWritingMode() | 173 LayoutSize(isHorizontalWritingMode() |
172 ? intrinsicSizingInfo.size | 174 ? intrinsicSizingInfo.size |
173 : intrinsicSizingInfo.size.transposedSize()); | 175 : intrinsicSizingInfo.size.transposedSize()); |
174 } | 176 } |
175 } | 177 } |
176 | 178 |
177 FloatSize LayoutReplaced::constrainIntrinsicSizeToMinMax( | 179 FloatSize LayoutReplaced::constrainIntrinsicSizeToMinMax( |
178 const IntrinsicSizingInfo& intrinsicSizingInfo) const { | 180 const IntrinsicSizingInfo& intrinsicSizingInfo) const { |
179 // Constrain the intrinsic size along each axis according to minimum and maxim um width/heights along the opposite | 181 // Constrain the intrinsic size along each axis according to minimum and |
180 // axis. So for example a maximum width that shrinks our width will result in the height we compute here having | 182 // maximum width/heights along the opposite axis. So for example a maximum |
181 // to shrink in order to preserve the aspect ratio. Because we compute these v alues independently along each | 183 // width that shrinks our width will result in the height we compute here |
182 // axis, the final returned size may in fact not preserve the aspect ratio. | 184 // having to shrink in order to preserve the aspect ratio. Because we compute |
185 // these values independently along each axis, the final returned size may in | |
186 // fact not preserve the aspect ratio. | |
183 // TODO(davve): Investigate using only the intrinsic aspect ratio here. | 187 // TODO(davve): Investigate using only the intrinsic aspect ratio here. |
184 FloatSize constrainedSize = intrinsicSizingInfo.size; | 188 FloatSize constrainedSize = intrinsicSizingInfo.size; |
185 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && | 189 if (!intrinsicSizingInfo.aspectRatio.isEmpty() && |
186 !intrinsicSizingInfo.size.isEmpty() && style()->logicalWidth().isAuto() && | 190 !intrinsicSizingInfo.size.isEmpty() && style()->logicalWidth().isAuto() && |
187 style()->logicalHeight().isAuto()) { | 191 style()->logicalHeight().isAuto()) { |
188 // We can't multiply or divide by 'intrinsicSizingInfo.aspectRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which | 192 // We can't multiply or divide by 'intrinsicSizingInfo.aspectRatio' here, it |
189 // can only be fixed once subpixel precision is available for things like in trinsicWidth/Height - which include zoom! | 193 // breaks tests, like fast/images/zoomed-img-size.html, which |
194 // can only be fixed once subpixel precision is available for things like | |
195 // intrinsicWidth/Height - which include zoom! | |
190 constrainedSize.setWidth(LayoutBox::computeReplacedLogicalHeight() * | 196 constrainedSize.setWidth(LayoutBox::computeReplacedLogicalHeight() * |
191 intrinsicSizingInfo.size.width() / | 197 intrinsicSizingInfo.size.width() / |
192 intrinsicSizingInfo.size.height()); | 198 intrinsicSizingInfo.size.height()); |
193 constrainedSize.setHeight(LayoutBox::computeReplacedLogicalWidth() * | 199 constrainedSize.setHeight(LayoutBox::computeReplacedLogicalWidth() * |
194 intrinsicSizingInfo.size.height() / | 200 intrinsicSizingInfo.size.height() / |
195 intrinsicSizingInfo.size.width()); | 201 intrinsicSizingInfo.size.width()); |
196 } | 202 } |
197 return constrainedSize; | 203 return constrainedSize; |
198 } | 204 } |
199 | 205 |
200 void LayoutReplaced::computePositionedLogicalWidth( | 206 void LayoutReplaced::computePositionedLogicalWidth( |
201 LogicalExtentComputedValues& computedValues) const { | 207 LogicalExtentComputedValues& computedValues) const { |
202 // The following is based off of the W3C Working Draft from April 11, 2006 of | 208 // The following is based off of the W3C Working Draft from April 11, 2006 of |
203 // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements" | 209 // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements" |
204 // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-widt h> | 210 // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-widt h> |
205 // (block-style-comments in this function correspond to text from the spec and | 211 // (block-style-comments in this function correspond to text from the spec and |
206 // the numbers correspond to numbers in spec) | 212 // the numbers correspond to numbers in spec). |
207 | 213 |
208 // We don't use containingBlock(), since we may be positioned by an enclosing | 214 // We don't use containingBlock(), since we may be positioned by an enclosing |
209 // relative positioned inline. | 215 // relative positioned inline. |
210 const LayoutBoxModelObject* containerBlock = | 216 const LayoutBoxModelObject* containerBlock = |
211 toLayoutBoxModelObject(container()); | 217 toLayoutBoxModelObject(container()); |
212 | 218 |
213 const LayoutUnit containerLogicalWidth = | 219 const LayoutUnit containerLogicalWidth = |
214 containingBlockLogicalWidthForPositioned(containerBlock); | 220 containingBlockLogicalWidthForPositioned(containerBlock); |
215 const LayoutUnit containerRelativeLogicalWidth = | 221 const LayoutUnit containerRelativeLogicalWidth = |
216 containingBlockLogicalWidthForPositioned(containerBlock, false); | 222 containingBlockLogicalWidthForPositioned(containerBlock, false); |
(...skipping 10 matching lines...) Expand all Loading... | |
227 isHorizontal ? style()->marginLeft() : style()->marginTop(); | 233 isHorizontal ? style()->marginLeft() : style()->marginTop(); |
228 Length marginLogicalRight = | 234 Length marginLogicalRight = |
229 isHorizontal ? style()->marginRight() : style()->marginBottom(); | 235 isHorizontal ? style()->marginRight() : style()->marginBottom(); |
230 LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() | 236 LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() |
231 ? computedValues.m_margins.m_start | 237 ? computedValues.m_margins.m_start |
232 : computedValues.m_margins.m_end; | 238 : computedValues.m_margins.m_end; |
233 LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() | 239 LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() |
234 ? computedValues.m_margins.m_end | 240 ? computedValues.m_margins.m_end |
235 : computedValues.m_margins.m_start; | 241 : computedValues.m_margins.m_start; |
236 | 242 |
237 /*-----------------------------------------------------------------------*\ | 243 // --------------------------------------------------------------------------- |
238 * 1. The used value of 'width' is determined as for inline replaced | 244 // 1. The used value of 'width' is determined as for inline replaced |
239 * elements. | 245 // elements. |
240 \*-----------------------------------------------------------------------*/ | 246 // --------------------------------------------------------------------------- |
241 // NOTE: This value of width is final in that the min/max width calculations | 247 // NOTE: This value of width is final in that the min/max width calculations |
242 // are dealt with in computeReplacedWidth(). This means that the steps to pro duce | 248 // are dealt with in computeReplacedWidth(). This means that the steps to |
243 // correct max/min in the non-replaced version, are not necessary. | 249 // produce correct max/min in the non-replaced version, are not necessary. |
244 computedValues.m_extent = | 250 computedValues.m_extent = |
245 computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth(); | 251 computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth(); |
246 | 252 |
247 const LayoutUnit availableSpace = | 253 const LayoutUnit availableSpace = |
248 containerLogicalWidth - computedValues.m_extent; | 254 containerLogicalWidth - computedValues.m_extent; |
249 | 255 |
250 /*-----------------------------------------------------------------------*\ | 256 // --------------------------------------------------------------------------- |
251 * 2. If both 'left' and 'right' have the value 'auto', then if 'direction' | 257 // 2. If both 'left' and 'right' have the value 'auto', then if 'direction' |
252 * of the containing block is 'ltr', set 'left' to the static position; | 258 // of the containing block is 'ltr', set 'left' to the static position; |
253 * else if 'direction' is 'rtl', set 'right' to the static position. | 259 // else if 'direction' is 'rtl', set 'right' to the static position. |
254 \*-----------------------------------------------------------------------*/ | 260 // --------------------------------------------------------------------------- |
255 // see FIXME 1 | 261 // see FIXME 1 |
256 computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, | 262 computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, |
257 containerLogicalWidth); | 263 containerLogicalWidth); |
258 | 264 |
259 /*-----------------------------------------------------------------------*\ | 265 // --------------------------------------------------------------------------- |
260 * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left' | 266 // 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left' |
261 * or 'margin-right' with '0'. | 267 // or 'margin-right' with '0'. |
262 \*-----------------------------------------------------------------------*/ | 268 // --------------------------------------------------------------------------- |
263 if (logicalLeft.isAuto() || logicalRight.isAuto()) { | 269 if (logicalLeft.isAuto() || logicalRight.isAuto()) { |
264 if (marginLogicalLeft.isAuto()) | 270 if (marginLogicalLeft.isAuto()) |
265 marginLogicalLeft.setValue(Fixed, 0); | 271 marginLogicalLeft.setValue(Fixed, 0); |
266 if (marginLogicalRight.isAuto()) | 272 if (marginLogicalRight.isAuto()) |
267 marginLogicalRight.setValue(Fixed, 0); | 273 marginLogicalRight.setValue(Fixed, 0); |
268 } | 274 } |
269 | 275 |
270 /*-----------------------------------------------------------------------*\ | 276 // --------------------------------------------------------------------------- |
271 * 4. If at this point both 'margin-left' and 'margin-right' are still | 277 // 4. If at this point both 'margin-left' and 'margin-right' are still 'auto', |
272 * 'auto', solve the equation under the extra constraint that the two | 278 // solve the equation under the extra constraint that the two margins must |
273 * margins must get equal values, unless this would make them negative, | 279 // get equal values, unless this would make them negative, in which case |
274 * in which case when the direction of the containing block is 'ltr' | 280 // when the direction of the containing block is 'ltr' ('rtl'), set |
275 * ('rtl'), set 'margin-left' ('margin-right') to zero and solve for | 281 // 'margin-left' ('margin-right') to zero and solve for 'margin-right' |
276 * 'margin-right' ('margin-left'). | 282 // ('margin-left'). |
277 \*-----------------------------------------------------------------------*/ | 283 // --------------------------------------------------------------------------- |
278 LayoutUnit logicalLeftValue; | 284 LayoutUnit logicalLeftValue; |
279 LayoutUnit logicalRightValue; | 285 LayoutUnit logicalRightValue; |
280 | 286 |
281 if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { | 287 if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { |
282 // 'left' and 'right' cannot be 'auto' due to step 3 | 288 // 'left' and 'right' cannot be 'auto' due to step 3 |
283 ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto())); | 289 ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto())); |
284 | 290 |
285 logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); | 291 logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); |
286 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); | 292 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); |
287 | 293 |
288 LayoutUnit difference = | 294 LayoutUnit difference = |
289 availableSpace - (logicalLeftValue + logicalRightValue); | 295 availableSpace - (logicalLeftValue + logicalRightValue); |
290 if (difference > LayoutUnit()) { | 296 if (difference > LayoutUnit()) { |
291 marginLogicalLeftAlias = difference / 2; // split the difference | 297 marginLogicalLeftAlias = difference / 2; // split the difference |
292 marginLogicalRightAlias = | 298 marginLogicalRightAlias = |
293 difference - | 299 difference - |
294 marginLogicalLeftAlias; // account for odd valued differences | 300 marginLogicalLeftAlias; // account for odd valued differences |
295 } else { | 301 } else { |
296 // Use the containing block's direction rather than the parent block's | 302 // Use the containing block's direction rather than the parent block's |
297 // per CSS 2.1 reference test abspos-replaced-width-margin-000. | 303 // per CSS 2.1 reference test abspos-replaced-width-margin-000. |
298 if (containerDirection == LTR) { | 304 if (containerDirection == LTR) { |
299 marginLogicalLeftAlias = LayoutUnit(); | 305 marginLogicalLeftAlias = LayoutUnit(); |
300 marginLogicalRightAlias = difference; // will be negative | 306 marginLogicalRightAlias = difference; // will be negative |
301 } else { | 307 } else { |
302 marginLogicalLeftAlias = difference; // will be negative | 308 marginLogicalLeftAlias = difference; // will be negative |
303 marginLogicalRightAlias = LayoutUnit(); | 309 marginLogicalRightAlias = LayoutUnit(); |
304 } | 310 } |
305 } | 311 } |
306 | 312 |
307 /*-----------------------------------------------------------------------*\ | 313 // ------------------------------------------------------------------------- |
308 * 5. If at this point there is an 'auto' left, solve the equation for | 314 // 5. If at this point there is an 'auto' left, solve the equation for that |
309 * that value. | 315 // value. |
310 \*-----------------------------------------------------------------------*/ | 316 // ------------------------------------------------------------------------- |
311 } else if (logicalLeft.isAuto()) { | 317 } else if (logicalLeft.isAuto()) { |
312 marginLogicalLeftAlias = | 318 marginLogicalLeftAlias = |
313 valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); | 319 valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); |
314 marginLogicalRightAlias = | 320 marginLogicalRightAlias = |
315 valueForLength(marginLogicalRight, containerRelativeLogicalWidth); | 321 valueForLength(marginLogicalRight, containerRelativeLogicalWidth); |
316 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); | 322 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); |
317 | 323 |
318 // Solve for 'left' | 324 // Solve for 'left' |
319 logicalLeftValue = | 325 logicalLeftValue = |
320 availableSpace - | 326 availableSpace - |
(...skipping 30 matching lines...) Expand all Loading... | |
351 availableSpace - | 357 availableSpace - |
352 (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias); | 358 (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias); |
353 } else { | 359 } else { |
354 // Nothing is 'auto', just calculate the values. | 360 // Nothing is 'auto', just calculate the values. |
355 marginLogicalLeftAlias = | 361 marginLogicalLeftAlias = |
356 valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); | 362 valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); |
357 marginLogicalRightAlias = | 363 marginLogicalRightAlias = |
358 valueForLength(marginLogicalRight, containerRelativeLogicalWidth); | 364 valueForLength(marginLogicalRight, containerRelativeLogicalWidth); |
359 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); | 365 logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); |
360 logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); | 366 logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); |
361 // If the containing block is right-to-left, then push the left position as far to the right as possible | 367 // If the containing block is right-to-left, then push the left position as |
368 // far to the right as possible | |
362 if (containerDirection == RTL) { | 369 if (containerDirection == RTL) { |
363 int totalLogicalWidth = | 370 int totalLogicalWidth = |
364 (computedValues.m_extent + logicalLeftValue + logicalRightValue + | 371 (computedValues.m_extent + logicalLeftValue + logicalRightValue + |
365 marginLogicalLeftAlias + marginLogicalRightAlias) | 372 marginLogicalLeftAlias + marginLogicalRightAlias) |
366 .toInt(); | 373 .toInt(); |
367 logicalLeftValue = | 374 logicalLeftValue = |
368 containerLogicalWidth - (totalLogicalWidth - logicalLeftValue); | 375 containerLogicalWidth - (totalLogicalWidth - logicalLeftValue); |
369 } | 376 } |
370 } | 377 } |
371 | 378 |
372 /*-----------------------------------------------------------------------*\ | 379 // --------------------------------------------------------------------------- |
373 * 6. If at this point the values are over-constrained, ignore the value | 380 // 6. If at this point the values are over-constrained, ignore the value for |
374 * for either 'left' (in case the 'direction' property of the | 381 // either 'left' (in case the 'direction' property of the containing block |
375 * containing block is 'rtl') or 'right' (in case 'direction' is | 382 // is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that |
376 * 'ltr') and solve for that value. | 383 // value. |
377 \*-----------------------------------------------------------------------*/ | 384 // --------------------------------------------------------------------------- |
378 // NOTE: Constraints imposed by the width of the containing block and its cont ent have already been accounted for above. | 385 // NOTE: Constraints imposed by the width of the containing block and its |
379 | 386 // content have already been accounted for above. |
380 // FIXME: Deal with differing writing modes here. Our offset needs to be in t he containing block's coordinate space, so that | 387 // |
388 // FIXME: Deal with differing writing modes here. Our offset needs to be in | |
389 // the containing block's coordinate space, so that | |
dgrogan
2016/10/07 19:37:06
suboptimal
| |
381 // can make the result here rather complicated to compute. | 390 // can make the result here rather complicated to compute. |
382 | 391 // |
383 // Use computed values to calculate the horizontal position. | 392 // Use computed values to calculate the horizontal position. |
384 | 393 // |
385 // FIXME: This hack is needed to calculate the logical left position for a 'rt l' relatively | 394 // FIXME: This hack is needed to calculate the logical left position for a |
386 // positioned, inline containing block because right now, it is using the logi cal left position | 395 // 'rtl' relatively positioned, inline containing block because right now, it |
387 // of the first line box when really it should use the last line box. When | 396 // is using the logical left position of the first line box when really it |
388 // this is fixed elsewhere, this block should be removed. | 397 // should use the last line box. When this is fixed elsewhere, this block |
398 // should be removed. | |
389 if (containerBlock->isLayoutInline() && | 399 if (containerBlock->isLayoutInline() && |
390 !containerBlock->style()->isLeftToRightDirection()) { | 400 !containerBlock->style()->isLeftToRightDirection()) { |
391 const LayoutInline* flow = toLayoutInline(containerBlock); | 401 const LayoutInline* flow = toLayoutInline(containerBlock); |
392 InlineFlowBox* firstLine = flow->firstLineBox(); | 402 InlineFlowBox* firstLine = flow->firstLineBox(); |
393 InlineFlowBox* lastLine = flow->lastLineBox(); | 403 InlineFlowBox* lastLine = flow->lastLineBox(); |
394 if (firstLine && lastLine && firstLine != lastLine) { | 404 if (firstLine && lastLine && firstLine != lastLine) { |
395 computedValues.m_position = | 405 computedValues.m_position = |
396 logicalLeftValue + marginLogicalLeftAlias + | 406 logicalLeftValue + marginLogicalLeftAlias + |
397 lastLine->borderLogicalLeft() + | 407 lastLine->borderLogicalLeft() + |
398 (lastLine->logicalLeft() - firstLine->logicalLeft()); | 408 (lastLine->logicalLeft() - firstLine->logicalLeft()); |
399 return; | 409 return; |
400 } | 410 } |
401 } | 411 } |
402 | 412 |
403 LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias; | 413 LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias; |
404 computeLogicalLeftPositionedOffset(logicalLeftPos, this, | 414 computeLogicalLeftPositionedOffset(logicalLeftPos, this, |
405 computedValues.m_extent, containerBlock, | 415 computedValues.m_extent, containerBlock, |
406 containerLogicalWidth); | 416 containerLogicalWidth); |
407 computedValues.m_position = logicalLeftPos; | 417 computedValues.m_position = logicalLeftPos; |
408 } | 418 } |
409 | 419 |
410 void LayoutReplaced::computePositionedLogicalHeight( | 420 void LayoutReplaced::computePositionedLogicalHeight( |
411 LogicalExtentComputedValues& computedValues) const { | 421 LogicalExtentComputedValues& computedValues) const { |
412 // The following is based off of the W3C Working Draft from April 11, 2006 of | 422 // The following is based off of the W3C Working Draft from April 11, 2006 of |
413 // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements" | 423 // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements" |
414 // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-heig ht> | 424 // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-heig ht> |
415 // (block-style-comments in this function correspond to text from the spec and | 425 // (block-style-comments in this function correspond to text from the spec and |
416 // the numbers correspond to numbers in spec) | 426 // the numbers correspond to numbers in spec) |
417 | 427 |
418 // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. | 428 // We don't use containingBlock(), since we may be positioned by an enclosing |
429 // relpositioned inline. | |
419 const LayoutBoxModelObject* containerBlock = | 430 const LayoutBoxModelObject* containerBlock = |
420 toLayoutBoxModelObject(container()); | 431 toLayoutBoxModelObject(container()); |
421 | 432 |
422 const LayoutUnit containerLogicalHeight = | 433 const LayoutUnit containerLogicalHeight = |
423 containingBlockLogicalHeightForPositioned(containerBlock); | 434 containingBlockLogicalHeightForPositioned(containerBlock); |
424 const LayoutUnit containerRelativeLogicalWidth = | 435 const LayoutUnit containerRelativeLogicalWidth = |
425 containingBlockLogicalWidthForPositioned(containerBlock, false); | 436 containingBlockLogicalWidthForPositioned(containerBlock, false); |
426 | 437 |
427 // Variables to solve. | 438 // Variables to solve. |
428 Length marginBefore = style()->marginBefore(); | 439 Length marginBefore = style()->marginBefore(); |
429 Length marginAfter = style()->marginAfter(); | 440 Length marginAfter = style()->marginAfter(); |
430 LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before; | 441 LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before; |
431 LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after; | 442 LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after; |
432 | 443 |
433 Length logicalTop = style()->logicalTop(); | 444 Length logicalTop = style()->logicalTop(); |
434 Length logicalBottom = style()->logicalBottom(); | 445 Length logicalBottom = style()->logicalBottom(); |
435 | 446 |
436 /*-----------------------------------------------------------------------*\ | 447 // --------------------------------------------------------------------------- |
437 * 1. The used value of 'height' is determined as for inline replaced | 448 // 1. The used value of 'height' is determined as for inline replaced |
438 * elements. | 449 // elements. |
439 \*-----------------------------------------------------------------------*/ | 450 // --------------------------------------------------------------------------- |
440 // NOTE: This value of height is final in that the min/max height calculations | 451 // NOTE: This value of height is final in that the min/max height calculations |
441 // are dealt with in computeReplacedHeight(). This means that the steps to pr oduce | 452 // are dealt with in computeReplacedHeight(). This means that the steps to |
442 // correct max/min in the non-replaced version, are not necessary. | 453 // produce correct max/min in the non-replaced version, are not necessary. |
443 computedValues.m_extent = | 454 computedValues.m_extent = |
444 computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight(); | 455 computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight(); |
445 const LayoutUnit availableSpace = | 456 const LayoutUnit availableSpace = |
446 containerLogicalHeight - computedValues.m_extent; | 457 containerLogicalHeight - computedValues.m_extent; |
447 | 458 |
448 /*-----------------------------------------------------------------------*\ | 459 // --------------------------------------------------------------------------- |
449 * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' | 460 // 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' with the |
450 * with the element's static position. | 461 // element's static position. |
451 \*-----------------------------------------------------------------------*/ | 462 // --------------------------------------------------------------------------- |
452 // see FIXME 1 | 463 // see FIXME 1 |
453 computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock); | 464 computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock); |
454 | 465 |
455 /*-----------------------------------------------------------------------*\ | 466 // --------------------------------------------------------------------------- |
456 * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or | 467 // 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or |
457 * 'margin-bottom' with '0'. | 468 // 'margin-bottom' with '0'. |
458 \*-----------------------------------------------------------------------*/ | 469 // --------------------------------------------------------------------------- |
459 // FIXME: The spec. says that this step should only be taken when bottom is | 470 // FIXME: The spec. says that this step should only be taken when bottom is |
460 // auto, but if only top is auto, this makes step 4 impossible. | 471 // auto, but if only top is auto, this makes step 4 impossible. |
461 if (logicalTop.isAuto() || logicalBottom.isAuto()) { | 472 if (logicalTop.isAuto() || logicalBottom.isAuto()) { |
462 if (marginBefore.isAuto()) | 473 if (marginBefore.isAuto()) |
463 marginBefore.setValue(Fixed, 0); | 474 marginBefore.setValue(Fixed, 0); |
464 if (marginAfter.isAuto()) | 475 if (marginAfter.isAuto()) |
465 marginAfter.setValue(Fixed, 0); | 476 marginAfter.setValue(Fixed, 0); |
466 } | 477 } |
467 | 478 |
468 /*-----------------------------------------------------------------------*\ | 479 // --------------------------------------------------------------------------- |
469 * 4. If at this point both 'margin-top' and 'margin-bottom' are still | 480 // 4. If at this point both 'margin-top' and 'margin-bottom' are still 'auto', |
470 * 'auto', solve the equation under the extra constraint that the two | 481 // solve the equation under the extra constraint that the two margins must |
471 * margins must get equal values. | 482 // get equal values. |
472 \*-----------------------------------------------------------------------*/ | 483 // --------------------------------------------------------------------------- |
473 LayoutUnit logicalTopValue; | 484 LayoutUnit logicalTopValue; |
474 LayoutUnit logicalBottomValue; | 485 LayoutUnit logicalBottomValue; |
475 | 486 |
476 if (marginBefore.isAuto() && marginAfter.isAuto()) { | 487 if (marginBefore.isAuto() && marginAfter.isAuto()) { |
477 // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined. | 488 // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined. |
478 ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto())); | 489 ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto())); |
479 | 490 |
480 logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); | 491 logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); |
481 logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); | 492 logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); |
482 | 493 |
483 LayoutUnit difference = | 494 LayoutUnit difference = |
484 availableSpace - (logicalTopValue + logicalBottomValue); | 495 availableSpace - (logicalTopValue + logicalBottomValue); |
485 // NOTE: This may result in negative values. | 496 // NOTE: This may result in negative values. |
486 marginBeforeAlias = difference / 2; // split the difference | 497 marginBeforeAlias = difference / 2; // split the difference |
487 marginAfterAlias = | 498 marginAfterAlias = |
488 difference - marginBeforeAlias; // account for odd valued differences | 499 difference - marginBeforeAlias; // account for odd valued differences |
489 | 500 |
490 /*-----------------------------------------------------------------------*\ | 501 // ------------------------------------------------------------------------- |
491 * 5. If at this point there is only one 'auto' left, solve the equation | 502 // 5. If at this point there is only one 'auto' left, solve the equation |
492 * for that value. | 503 // for that value. |
493 \*-----------------------------------------------------------------------*/ | 504 // ------------------------------------------------------------------------- |
494 } else if (logicalTop.isAuto()) { | 505 } else if (logicalTop.isAuto()) { |
495 marginBeforeAlias = | 506 marginBeforeAlias = |
496 valueForLength(marginBefore, containerRelativeLogicalWidth); | 507 valueForLength(marginBefore, containerRelativeLogicalWidth); |
497 marginAfterAlias = | 508 marginAfterAlias = |
498 valueForLength(marginAfter, containerRelativeLogicalWidth); | 509 valueForLength(marginAfter, containerRelativeLogicalWidth); |
499 logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); | 510 logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); |
500 | 511 |
501 // Solve for 'top' | 512 // Solve for 'top' |
502 logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + | 513 logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + |
503 marginAfterAlias); | 514 marginAfterAlias); |
(...skipping 29 matching lines...) Expand all Loading... | |
533 // Nothing is 'auto', just calculate the values. | 544 // Nothing is 'auto', just calculate the values. |
534 marginBeforeAlias = | 545 marginBeforeAlias = |
535 valueForLength(marginBefore, containerRelativeLogicalWidth); | 546 valueForLength(marginBefore, containerRelativeLogicalWidth); |
536 marginAfterAlias = | 547 marginAfterAlias = |
537 valueForLength(marginAfter, containerRelativeLogicalWidth); | 548 valueForLength(marginAfter, containerRelativeLogicalWidth); |
538 logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); | 549 logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); |
539 // NOTE: It is not necessary to solve for 'bottom' because we don't ever | 550 // NOTE: It is not necessary to solve for 'bottom' because we don't ever |
540 // use the value. | 551 // use the value. |
541 } | 552 } |
542 | 553 |
543 /*-----------------------------------------------------------------------*\ | 554 // --------------------------------------------------------------------------- |
544 * 6. If at this point the values are over-constrained, ignore the value | 555 // 6. If at this point the values are over-constrained, ignore the value for |
545 * for 'bottom' and solve for that value. | 556 // 'bottom' and solve for that value. |
546 \*-----------------------------------------------------------------------*/ | 557 // --------------------------------------------------------------------------- |
547 // NOTE: It is not necessary to do this step because we don't end up using | 558 // NOTE: It is not necessary to do this step because we don't end up using the |
548 // the value of 'bottom' regardless of whether the values are over-constrained | 559 // value of 'bottom' regardless of whether the values are over-constrained or |
549 // or not. | 560 // not. |
550 | 561 |
551 // Use computed values to calculate the vertical position. | 562 // Use computed values to calculate the vertical position. |
552 LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias; | 563 LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias; |
553 computeLogicalTopPositionedOffset(logicalTopPos, this, | 564 computeLogicalTopPositionedOffset(logicalTopPos, this, |
554 computedValues.m_extent, containerBlock, | 565 computedValues.m_extent, containerBlock, |
555 containerLogicalHeight); | 566 containerLogicalHeight); |
556 computedValues.m_position = logicalTopPos; | 567 computedValues.m_position = logicalTopPos; |
557 } | 568 } |
558 | 569 |
559 LayoutRect LayoutReplaced::computeObjectFit( | 570 LayoutRect LayoutReplaced::computeObjectFit( |
560 const LayoutSize* overriddenIntrinsicSize) const { | 571 const LayoutSize* overriddenIntrinsicSize) const { |
561 LayoutRect contentRect = contentBoxRect(); | 572 LayoutRect contentRect = contentBoxRect(); |
562 ObjectFit objectFit = style()->getObjectFit(); | 573 ObjectFit objectFit = style()->getObjectFit(); |
563 | 574 |
564 if (objectFit == ObjectFitFill && | 575 if (objectFit == ObjectFitFill && |
565 style()->objectPosition() == ComputedStyle::initialObjectPosition()) { | 576 style()->objectPosition() == ComputedStyle::initialObjectPosition()) { |
566 return contentRect; | 577 return contentRect; |
567 } | 578 } |
568 | 579 |
569 // TODO(davve): intrinsicSize doubles as both intrinsic size and intrinsic rat io. In the case of | 580 // TODO(davve): intrinsicSize doubles as both intrinsic size and intrinsic |
570 // SVG images this isn't correct since they can have intrinsic ratio but no in trinsic size. In | 581 // ratio. In the case of SVG images this isn't correct since they can have |
571 // order to maintain aspect ratio, the intrinsic size for SVG might be faked f rom the aspect | 582 // intrinsic ratio but no intrinsic size. In order to maintain aspect ratio, |
572 // ratio, see SVGImage::containerSize(). | 583 // the intrinsic size for SVG might be faked from the aspect ratio, |
584 // see SVGImage::containerSize(). | |
573 LayoutSize intrinsicSize = overriddenIntrinsicSize ? *overriddenIntrinsicSize | 585 LayoutSize intrinsicSize = overriddenIntrinsicSize ? *overriddenIntrinsicSize |
574 : this->intrinsicSize(); | 586 : this->intrinsicSize(); |
575 if (!intrinsicSize.width() || !intrinsicSize.height()) | 587 if (!intrinsicSize.width() || !intrinsicSize.height()) |
576 return contentRect; | 588 return contentRect; |
577 | 589 |
578 LayoutRect finalRect = contentRect; | 590 LayoutRect finalRect = contentRect; |
579 switch (objectFit) { | 591 switch (objectFit) { |
580 case ObjectFitContain: | 592 case ObjectFitContain: |
581 case ObjectFitScaleDown: | 593 case ObjectFitScaleDown: |
582 case ObjectFitCover: | 594 case ObjectFitCover: |
(...skipping 21 matching lines...) Expand all Loading... | |
604 | 616 |
605 return finalRect; | 617 return finalRect; |
606 } | 618 } |
607 | 619 |
608 LayoutRect LayoutReplaced::replacedContentRect() const { | 620 LayoutRect LayoutReplaced::replacedContentRect() const { |
609 return computeObjectFit(); | 621 return computeObjectFit(); |
610 } | 622 } |
611 | 623 |
612 void LayoutReplaced::computeIntrinsicSizingInfo( | 624 void LayoutReplaced::computeIntrinsicSizingInfo( |
613 IntrinsicSizingInfo& intrinsicSizingInfo) const { | 625 IntrinsicSizingInfo& intrinsicSizingInfo) const { |
614 // If there's an embeddedReplacedContent() of a remote, referenced document av ailable, this code-path should never be used. | 626 // If there's an embeddedReplacedContent() of a remote, referenced document |
627 // available, this code-path should never be used. | |
615 ASSERT(!embeddedReplacedContent()); | 628 ASSERT(!embeddedReplacedContent()); |
616 intrinsicSizingInfo.size = FloatSize(intrinsicLogicalWidth().toFloat(), | 629 intrinsicSizingInfo.size = FloatSize(intrinsicLogicalWidth().toFloat(), |
617 intrinsicLogicalHeight().toFloat()); | 630 intrinsicLogicalHeight().toFloat()); |
618 | 631 |
619 // Figure out if we need to compute an intrinsic ratio. | 632 // Figure out if we need to compute an intrinsic ratio. |
620 if (intrinsicSizingInfo.size.isEmpty() || !layoutObjectHasAspectRatio(this)) | 633 if (intrinsicSizingInfo.size.isEmpty() || !layoutObjectHasAspectRatio(this)) |
621 return; | 634 return; |
622 | 635 |
623 intrinsicSizingInfo.aspectRatio = intrinsicSizingInfo.size; | 636 intrinsicSizingInfo.aspectRatio = intrinsicSizingInfo.size; |
624 } | 637 } |
625 | 638 |
626 static inline LayoutUnit resolveWidthForRatio(LayoutUnit height, | 639 static inline LayoutUnit resolveWidthForRatio(LayoutUnit height, |
627 const FloatSize& aspectRatio) { | 640 const FloatSize& aspectRatio) { |
628 return LayoutUnit(height * aspectRatio.width() / aspectRatio.height()); | 641 return LayoutUnit(height * aspectRatio.width() / aspectRatio.height()); |
629 } | 642 } |
630 | 643 |
631 static inline LayoutUnit resolveHeightForRatio(LayoutUnit width, | 644 static inline LayoutUnit resolveHeightForRatio(LayoutUnit width, |
632 const FloatSize& aspectRatio) { | 645 const FloatSize& aspectRatio) { |
633 return LayoutUnit(width * aspectRatio.height() / aspectRatio.width()); | 646 return LayoutUnit(width * aspectRatio.height() / aspectRatio.width()); |
634 } | 647 } |
635 | 648 |
636 LayoutUnit LayoutReplaced::computeConstrainedLogicalWidth( | 649 LayoutUnit LayoutReplaced::computeConstrainedLogicalWidth( |
637 ShouldComputePreferred shouldComputePreferred) const { | 650 ShouldComputePreferred shouldComputePreferred) const { |
638 if (shouldComputePreferred == ComputePreferred) | 651 if (shouldComputePreferred == ComputePreferred) |
639 return computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit(), | 652 return computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit(), |
640 ComputePreferred); | 653 ComputePreferred); |
641 // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow: | 654 // The aforementioned 'constraint equation' used for block-level, non-replaced |
642 // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-r ight' + 'border-right-width' + 'margin-right' = width of containing block | 655 // elements in normal flow: |
656 // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + | |
657 // 'padding-right' + 'border-right-width' + 'margin-right' = width of | |
658 // containing block | |
643 LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth(); | 659 LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth(); |
644 | 660 |
645 // This solves above equation for 'width' (== logicalWidth). | 661 // This solves above equation for 'width' (== logicalWidth). |
646 LayoutUnit marginStart = | 662 LayoutUnit marginStart = |
647 minimumValueForLength(style()->marginStart(), logicalWidth); | 663 minimumValueForLength(style()->marginStart(), logicalWidth); |
648 LayoutUnit marginEnd = | 664 LayoutUnit marginEnd = |
649 minimumValueForLength(style()->marginEnd(), logicalWidth); | 665 minimumValueForLength(style()->marginEnd(), logicalWidth); |
650 logicalWidth = (logicalWidth - | 666 logicalWidth = (logicalWidth - |
651 (marginStart + marginEnd + (size().width() - clientWidth()))) | 667 (marginStart + marginEnd + (size().width() - clientWidth()))) |
652 .clampNegativeToZero(); | 668 .clampNegativeToZero(); |
653 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 669 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
654 logicalWidth, shouldComputePreferred); | 670 logicalWidth, shouldComputePreferred); |
655 } | 671 } |
656 | 672 |
657 LayoutUnit LayoutReplaced::computeReplacedLogicalWidth( | 673 LayoutUnit LayoutReplaced::computeReplacedLogicalWidth( |
658 ShouldComputePreferred shouldComputePreferred) const { | 674 ShouldComputePreferred shouldComputePreferred) const { |
659 if (style()->logicalWidth().isSpecified() || | 675 if (style()->logicalWidth().isSpecified() || |
660 style()->logicalWidth().isIntrinsic()) | 676 style()->logicalWidth().isIntrinsic()) |
661 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 677 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
662 computeReplacedLogicalWidthUsing(MainOrPreferredSize, | 678 computeReplacedLogicalWidthUsing(MainOrPreferredSize, |
663 style()->logicalWidth()), | 679 style()->logicalWidth()), |
664 shouldComputePreferred); | 680 shouldComputePreferred); |
665 | 681 |
666 LayoutReplaced* contentLayoutObject = embeddedReplacedContent(); | 682 LayoutReplaced* contentLayoutObject = embeddedReplacedContent(); |
667 | 683 |
668 // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#i nline-replaced-width | 684 // 10.3.2 Inline, replaced elements: |
685 // http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width | |
669 IntrinsicSizingInfo intrinsicSizingInfo; | 686 IntrinsicSizingInfo intrinsicSizingInfo; |
670 computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject, | 687 computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject, |
671 intrinsicSizingInfo); | 688 intrinsicSizingInfo); |
672 FloatSize constrainedSize = | 689 FloatSize constrainedSize = |
673 constrainIntrinsicSizeToMinMax(intrinsicSizingInfo); | 690 constrainIntrinsicSizeToMinMax(intrinsicSizingInfo); |
674 | 691 |
675 if (style()->logicalWidth().isAuto()) { | 692 if (style()->logicalWidth().isAuto()) { |
676 bool computedHeightIsAuto = style()->logicalHeight().isAuto(); | 693 bool computedHeightIsAuto = style()->logicalHeight().isAuto(); |
677 | 694 |
678 // If 'height' and 'width' both have computed values of 'auto' and the eleme nt also has an intrinsic width, then that intrinsic width is the used value of ' width'. | 695 // If 'height' and 'width' both have computed values of 'auto' and the |
696 // element also has an intrinsic width, then that intrinsic width is the | |
697 // used value of 'width'. | |
679 if (computedHeightIsAuto && intrinsicSizingInfo.hasWidth) | 698 if (computedHeightIsAuto && intrinsicSizingInfo.hasWidth) |
680 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 699 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
681 LayoutUnit(constrainedSize.width()), shouldComputePreferred); | 700 LayoutUnit(constrainedSize.width()), shouldComputePreferred); |
682 | 701 |
683 if (!intrinsicSizingInfo.aspectRatio.isEmpty()) { | 702 if (!intrinsicSizingInfo.aspectRatio.isEmpty()) { |
684 // If 'height' and 'width' both have computed values of 'auto' and the ele ment has no intrinsic width, but does have an intrinsic height and intrinsic rat io; | 703 // If 'height' and 'width' both have computed values of 'auto' and the |
685 // or if 'width' has a computed value of 'auto', 'height' has some other c omputed value, and the element does have an intrinsic ratio; then the used value | 704 // element has no intrinsic width, but does have an intrinsic height and |
686 // of 'width' is: (used height) * (intrinsic ratio) | 705 // intrinsic ratio; or if 'width' has a computed value of 'auto', 'height' |
706 // has some other computed value, and the element does have an intrinsic | |
707 // ratio; then the used value of 'width' is: (used height) * (intrinsic | |
708 // ratio). | |
687 if ((computedHeightIsAuto && !intrinsicSizingInfo.hasWidth && | 709 if ((computedHeightIsAuto && !intrinsicSizingInfo.hasWidth && |
688 intrinsicSizingInfo.hasHeight) || | 710 intrinsicSizingInfo.hasHeight) || |
689 !computedHeightIsAuto) { | 711 !computedHeightIsAuto) { |
690 LayoutUnit estimatedUsedWidth = | 712 LayoutUnit estimatedUsedWidth = |
691 intrinsicSizingInfo.hasWidth | 713 intrinsicSizingInfo.hasWidth |
692 ? LayoutUnit(constrainedSize.width()) | 714 ? LayoutUnit(constrainedSize.width()) |
693 : computeConstrainedLogicalWidth(shouldComputePreferred); | 715 : computeConstrainedLogicalWidth(shouldComputePreferred); |
694 LayoutUnit logicalHeight = | 716 LayoutUnit logicalHeight = |
695 computeReplacedLogicalHeight(estimatedUsedWidth); | 717 computeReplacedLogicalHeight(estimatedUsedWidth); |
696 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 718 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
697 resolveWidthForRatio(logicalHeight, | 719 resolveWidthForRatio(logicalHeight, |
698 intrinsicSizingInfo.aspectRatio), | 720 intrinsicSizingInfo.aspectRatio), |
699 shouldComputePreferred); | 721 shouldComputePreferred); |
700 } | 722 } |
701 | 723 |
702 // If 'height' and 'width' both have computed values of 'auto' and the ele ment has an intrinsic ratio but no intrinsic height or width, then the used valu e of | 724 // If 'height' and 'width' both have computed values of 'auto' and the |
703 // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then | 725 // element has an intrinsic ratio but no intrinsic height or width, then |
704 // the used value of 'width' is calculated from the constraint equation us ed for block-level, non-replaced elements in normal flow. | 726 // the used value of 'width' is undefined in CSS 2.1. However, it is |
727 // suggested that, if the containing block's width does not itself depend | |
728 // on the replaced element's width, then the used value of 'width' is | |
729 // calculated from the constraint equation used for block-level, | |
730 // non-replaced elements in normal flow. | |
705 if (computedHeightIsAuto && !intrinsicSizingInfo.hasWidth && | 731 if (computedHeightIsAuto && !intrinsicSizingInfo.hasWidth && |
706 !intrinsicSizingInfo.hasHeight) | 732 !intrinsicSizingInfo.hasHeight) |
707 return computeConstrainedLogicalWidth(shouldComputePreferred); | 733 return computeConstrainedLogicalWidth(shouldComputePreferred); |
708 } | 734 } |
709 | 735 |
710 // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'. | 736 // Otherwise, if 'width' has a computed value of 'auto', and the element has |
737 // an intrinsic width, then that intrinsic width is the used value of | |
738 // 'width'. | |
711 if (intrinsicSizingInfo.hasWidth) | 739 if (intrinsicSizingInfo.hasWidth) |
712 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 740 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
713 LayoutUnit(constrainedSize.width()), shouldComputePreferred); | 741 LayoutUnit(constrainedSize.width()), shouldComputePreferred); |
714 | 742 |
715 // Otherwise, if 'width' has a computed value of 'auto', but none of the con ditions above are met, then the used value of 'width' becomes 300px. If 300px is too | 743 // Otherwise, if 'width' has a computed value of 'auto', but none of the |
716 // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead. | 744 // conditions above are met, then the used value of 'width' becomes 300px. |
717 // Note: We fall through and instead return intrinsicLogicalWidth() here - t o preserve existing WebKit behavior, which might or might not be correct, or des ired. | 745 // If 300px is too wide to fit the device, UAs should use the width of the |
718 // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto) | 746 // largest rectangle that has a 2:1 ratio and fits the device instead. |
719 // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavi or since a long time. | 747 // Note: We fall through and instead return intrinsicLogicalWidth() here - |
748 // to preserve existing WebKit behavior, which might or might not be | |
749 // correct, or desired. | |
750 // Changing this to return cDefaultWidth, will affect lots of test results. | |
751 // Eg. some tests assume that a blank <img> tag (which implies | |
752 // width/height=auto) has no intrinsic size, which is wrong per CSS 2.1, but | |
753 // matches our behavior since a long time. | |
720 } | 754 } |
721 | 755 |
722 return computeReplacedLogicalWidthRespectingMinMaxWidth( | 756 return computeReplacedLogicalWidthRespectingMinMaxWidth( |
723 intrinsicLogicalWidth(), shouldComputePreferred); | 757 intrinsicLogicalWidth(), shouldComputePreferred); |
724 } | 758 } |
725 | 759 |
726 LayoutUnit LayoutReplaced::computeReplacedLogicalHeight( | 760 LayoutUnit LayoutReplaced::computeReplacedLogicalHeight( |
727 LayoutUnit estimatedUsedWidth) const { | 761 LayoutUnit estimatedUsedWidth) const { |
728 // 10.5 Content height: the 'height' property: http://www.w3.org/TR/CSS21/visu det.html#propdef-height | 762 // 10.5 Content height: the 'height' property: |
763 // http://www.w3.org/TR/CSS21/visudet.html#propdef-height | |
729 if (hasReplacedLogicalHeight()) | 764 if (hasReplacedLogicalHeight()) |
730 return computeReplacedLogicalHeightRespectingMinMaxHeight( | 765 return computeReplacedLogicalHeightRespectingMinMaxHeight( |
731 computeReplacedLogicalHeightUsing(MainOrPreferredSize, | 766 computeReplacedLogicalHeightUsing(MainOrPreferredSize, |
732 style()->logicalHeight())); | 767 style()->logicalHeight())); |
733 | 768 |
734 LayoutReplaced* contentLayoutObject = embeddedReplacedContent(); | 769 LayoutReplaced* contentLayoutObject = embeddedReplacedContent(); |
735 | 770 |
736 // 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#i nline-replaced-height | 771 // 10.6.2 Inline, replaced elements: |
772 // http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height | |
737 IntrinsicSizingInfo intrinsicSizingInfo; | 773 IntrinsicSizingInfo intrinsicSizingInfo; |
738 computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject, | 774 computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject, |
739 intrinsicSizingInfo); | 775 intrinsicSizingInfo); |
740 FloatSize constrainedSize = | 776 FloatSize constrainedSize = |
741 constrainIntrinsicSizeToMinMax(intrinsicSizingInfo); | 777 constrainIntrinsicSizeToMinMax(intrinsicSizingInfo); |
742 | 778 |
743 bool widthIsAuto = style()->logicalWidth().isAuto(); | 779 bool widthIsAuto = style()->logicalWidth().isAuto(); |
744 | 780 |
745 // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of ' height'. | 781 // If 'height' and 'width' both have computed values of 'auto' and the element |
782 // also has an intrinsic height, then that intrinsic height is the used value | |
783 // of 'height'. | |
746 if (widthIsAuto && intrinsicSizingInfo.hasHeight) | 784 if (widthIsAuto && intrinsicSizingInfo.hasHeight) |
747 return computeReplacedLogicalHeightRespectingMinMaxHeight( | 785 return computeReplacedLogicalHeightRespectingMinMaxHeight( |
748 LayoutUnit(constrainedSize.height())); | 786 LayoutUnit(constrainedSize.height())); |
749 | 787 |
750 // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is: | 788 // Otherwise, if 'height' has a computed value of 'auto', and the element has |
789 // an intrinsic ratio then the used value of 'height' is: | |
751 // (used width) / (intrinsic ratio) | 790 // (used width) / (intrinsic ratio) |
752 if (!intrinsicSizingInfo.aspectRatio.isEmpty()) { | 791 if (!intrinsicSizingInfo.aspectRatio.isEmpty()) { |
753 LayoutUnit usedWidth = | 792 LayoutUnit usedWidth = |
754 estimatedUsedWidth ? estimatedUsedWidth : availableLogicalWidth(); | 793 estimatedUsedWidth ? estimatedUsedWidth : availableLogicalWidth(); |
755 return computeReplacedLogicalHeightRespectingMinMaxHeight( | 794 return computeReplacedLogicalHeightRespectingMinMaxHeight( |
756 resolveHeightForRatio(usedWidth, intrinsicSizingInfo.aspectRatio)); | 795 resolveHeightForRatio(usedWidth, intrinsicSizingInfo.aspectRatio)); |
757 } | 796 } |
758 | 797 |
759 // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'. | 798 // Otherwise, if 'height' has a computed value of 'auto', and the element has |
799 // an intrinsic height, then that intrinsic height is the used value of | |
800 // 'height'. | |
760 if (intrinsicSizingInfo.hasHeight) | 801 if (intrinsicSizingInfo.hasHeight) |
761 return computeReplacedLogicalHeightRespectingMinMaxHeight( | 802 return computeReplacedLogicalHeightRespectingMinMaxHeight( |
762 LayoutUnit(constrainedSize.height())); | 803 LayoutUnit(constrainedSize.height())); |
763 | 804 |
764 // Otherwise, if 'height' has a computed value of 'auto', but none of the cond itions above are met, then the used value of 'height' must be set to the height | 805 // Otherwise, if 'height' has a computed value of 'auto', but none of the |
765 // of the largest rectangle that has a 2:1 ratio, has a height not greater tha n 150px, and has a width not greater than the device width. | 806 // conditions above are met, then the used value of 'height' must be set to |
807 // the height of the largest rectangle that has a 2:1 ratio, has a height not | |
808 // greater than 150px, and has a width not greater than the device width. | |
766 return computeReplacedLogicalHeightRespectingMinMaxHeight( | 809 return computeReplacedLogicalHeightRespectingMinMaxHeight( |
767 intrinsicLogicalHeight()); | 810 intrinsicLogicalHeight()); |
768 } | 811 } |
769 | 812 |
770 void LayoutReplaced::computeIntrinsicLogicalWidths( | 813 void LayoutReplaced::computeIntrinsicLogicalWidths( |
771 LayoutUnit& minLogicalWidth, | 814 LayoutUnit& minLogicalWidth, |
772 LayoutUnit& maxLogicalWidth) const { | 815 LayoutUnit& maxLogicalWidth) const { |
773 minLogicalWidth = maxLogicalWidth = intrinsicLogicalWidth(); | 816 minLogicalWidth = maxLogicalWidth = intrinsicLogicalWidth(); |
774 } | 817 } |
775 | 818 |
776 void LayoutReplaced::computePreferredLogicalWidths() { | 819 void LayoutReplaced::computePreferredLogicalWidths() { |
777 ASSERT(preferredLogicalWidthsDirty()); | 820 ASSERT(preferredLogicalWidthsDirty()); |
778 | 821 |
779 // We cannot resolve some logical width here (i.e. percent, fill-available or fit-content) | 822 // We cannot resolve some logical width here (i.e. percent, fill-available or |
780 // as the available logical width may not be set on our containing block. | 823 // fit-content) as the available logical width may not be set on our |
824 // containing block. | |
781 const Length& logicalWidth = style()->logicalWidth(); | 825 const Length& logicalWidth = style()->logicalWidth(); |
782 if (logicalWidth.isPercentOrCalc() || logicalWidth.isFillAvailable() || | 826 if (logicalWidth.isPercentOrCalc() || logicalWidth.isFillAvailable() || |
783 logicalWidth.isFitContent()) | 827 logicalWidth.isFitContent()) |
784 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, | 828 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, |
785 m_maxPreferredLogicalWidth); | 829 m_maxPreferredLogicalWidth); |
786 else | 830 else |
787 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = | 831 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = |
788 computeReplacedLogicalWidth(ComputePreferred); | 832 computeReplacedLogicalWidth(ComputePreferred); |
789 | 833 |
790 const ComputedStyle& styleToUse = styleRef(); | 834 const ComputedStyle& styleToUse = styleRef(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() | 910 ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom() |
867 : root.selectionTop() - inlineBoxWrapper()->logicalTop(); | 911 : root.selectionTop() - inlineBoxWrapper()->logicalTop(); |
868 if (root.block().style()->isHorizontalWritingMode()) | 912 if (root.block().style()->isHorizontalWritingMode()) |
869 return LayoutRect(LayoutUnit(), newLogicalTop, size().width(), | 913 return LayoutRect(LayoutUnit(), newLogicalTop, size().width(), |
870 root.selectionHeight()); | 914 root.selectionHeight()); |
871 return LayoutRect(newLogicalTop, LayoutUnit(), root.selectionHeight(), | 915 return LayoutRect(newLogicalTop, LayoutUnit(), root.selectionHeight(), |
872 size().height()); | 916 size().height()); |
873 } | 917 } |
874 | 918 |
875 void LayoutReplaced::setSelectionState(SelectionState state) { | 919 void LayoutReplaced::setSelectionState(SelectionState state) { |
876 // The selection state for our containing block hierarchy is updated by the ba se class call. | 920 // The selection state for our containing block hierarchy is updated by the |
921 // base class call. | |
877 LayoutBox::setSelectionState(state); | 922 LayoutBox::setSelectionState(state); |
878 | 923 |
879 if (!inlineBoxWrapper()) | 924 if (!inlineBoxWrapper()) |
880 return; | 925 return; |
881 | 926 |
882 // We only include the space below the baseline in our layer's cached paint in validation rect if the | 927 // We only include the space below the baseline in our layer's cached paint |
883 // image is selected. Since the selection state has changed update the rect. | 928 // invalidation rect if the image is selected. Since the selection state has |
929 // changed update the rect. | |
884 if (hasLayer()) { | 930 if (hasLayer()) { |
885 LayoutRect rect = localOverflowRectForPaintInvalidation(); | 931 LayoutRect rect = localOverflowRectForPaintInvalidation(); |
886 PaintLayer::mapRectToPaintInvalidationBacking( | 932 PaintLayer::mapRectToPaintInvalidationBacking( |
887 *this, containerForPaintInvalidation(), rect); | 933 *this, containerForPaintInvalidation(), rect); |
888 setPreviousPaintInvalidationRect(rect); | 934 setPreviousPaintInvalidationRect(rect); |
889 } | 935 } |
890 | 936 |
891 if (canUpdateSelectionOnRootLineBoxes()) | 937 if (canUpdateSelectionOnRootLineBoxes()) |
892 inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone); | 938 inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone); |
893 } | 939 } |
894 | 940 |
895 void LayoutReplaced::IntrinsicSizingInfo::transpose() { | 941 void LayoutReplaced::IntrinsicSizingInfo::transpose() { |
896 size = size.transposedSize(); | 942 size = size.transposedSize(); |
897 aspectRatio = aspectRatio.transposedSize(); | 943 aspectRatio = aspectRatio.transposedSize(); |
898 std::swap(hasWidth, hasHeight); | 944 std::swap(hasWidth, hasHeight); |
899 } | 945 } |
900 | 946 |
901 } // namespace blink | 947 } // namespace blink |
OLD | NEW |