OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) | 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) |
3 * (C) 1997 Torben Weis (weis@kde.org) | 3 * (C) 1997 Torben Weis (weis@kde.org) |
4 * (C) 1998 Waldo Bastian (bastian@kde.org) | 4 * (C) 1998 Waldo Bastian (bastian@kde.org) |
5 * (C) 1999 Lars Knoll (knoll@kde.org) | 5 * (C) 1999 Lars Knoll (knoll@kde.org) |
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 6 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc.
All rights reserved. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. |
| 8 * All rights reserved. |
8 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
9 * | 10 * |
10 * This library is free software; you can redistribute it and/or | 11 * This library is free software; you can redistribute it and/or |
11 * modify it under the terms of the GNU Library General Public | 12 * modify it under the terms of the GNU Library General Public |
12 * License as published by the Free Software Foundation; either | 13 * License as published by the Free Software Foundation; either |
13 * version 2 of the License, or (at your option) any later version. | 14 * version 2 of the License, or (at your option) any later version. |
14 * | 15 * |
15 * This library is distributed in the hope that it will be useful, | 16 * This library is distributed in the hope that it will be useful, |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 // In the collapsed border model, there is no cell spacing. | 82 // In the collapsed border model, there is no cell spacing. |
82 m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing(); | 83 m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing(); |
83 m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing(); | 84 m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing(); |
84 m_effectiveColumnPositions[0] = m_hSpacing; | 85 m_effectiveColumnPositions[0] = m_hSpacing; |
85 | 86 |
86 if (!m_tableLayout || style()->isFixedTableLayout() != oldFixedTableLayout) { | 87 if (!m_tableLayout || style()->isFixedTableLayout() != oldFixedTableLayout) { |
87 if (m_tableLayout) | 88 if (m_tableLayout) |
88 m_tableLayout->willChangeTableLayout(); | 89 m_tableLayout->willChangeTableLayout(); |
89 | 90 |
90 // According to the CSS2 spec, you only use fixed table layout if an | 91 // According to the CSS2 spec, you only use fixed table layout if an |
91 // explicit width is specified on the table. Auto width implies auto table
layout. | 92 // explicit width is specified on the table. Auto width implies auto table |
| 93 // layout. |
92 if (style()->isFixedTableLayout()) | 94 if (style()->isFixedTableLayout()) |
93 m_tableLayout = wrapUnique(new TableLayoutAlgorithmFixed(this)); | 95 m_tableLayout = wrapUnique(new TableLayoutAlgorithmFixed(this)); |
94 else | 96 else |
95 m_tableLayout = wrapUnique(new TableLayoutAlgorithmAuto(this)); | 97 m_tableLayout = wrapUnique(new TableLayoutAlgorithmAuto(this)); |
96 } | 98 } |
97 | 99 |
98 // If border was changed, invalidate collapsed borders cache. | 100 // If border was changed, invalidate collapsed borders cache. |
99 if (!needsLayout() && oldStyle && oldStyle->border() != style()->border()) | 101 if (!needsLayout() && oldStyle && oldStyle->border() != style()->border()) |
100 invalidateCollapsedBorders(); | 102 invalidateCollapsedBorders(); |
101 if (LayoutTableBoxComponent::doCellsHaveDirtyWidth(*this, *this, diff, | 103 if (LayoutTableBoxComponent::doCellsHaveDirtyWidth(*this, *this, diff, |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 LayoutUnit containerWidthInInlineDirection = | 273 LayoutUnit containerWidthInInlineDirection = |
272 hasPerpendicularContainingBlock | 274 hasPerpendicularContainingBlock |
273 ? perpendicularContainingBlockLogicalHeight() | 275 ? perpendicularContainingBlockLogicalHeight() |
274 : availableLogicalWidth; | 276 : availableLogicalWidth; |
275 | 277 |
276 Length styleLogicalWidth = style()->logicalWidth(); | 278 Length styleLogicalWidth = style()->logicalWidth(); |
277 if (!isLogicalWidthAuto()) { | 279 if (!isLogicalWidthAuto()) { |
278 setLogicalWidth(convertStyleLogicalWidthToComputedWidth( | 280 setLogicalWidth(convertStyleLogicalWidthToComputedWidth( |
279 styleLogicalWidth, containerWidthInInlineDirection)); | 281 styleLogicalWidth, containerWidthInInlineDirection)); |
280 } else { | 282 } else { |
281 // Subtract out any fixed margins from our available width for auto width ta
bles. | 283 // Subtract out any fixed margins from our available width for auto width |
| 284 // tables. |
282 LayoutUnit marginStart = | 285 LayoutUnit marginStart = |
283 minimumValueForLength(style()->marginStart(), availableLogicalWidth); | 286 minimumValueForLength(style()->marginStart(), availableLogicalWidth); |
284 LayoutUnit marginEnd = | 287 LayoutUnit marginEnd = |
285 minimumValueForLength(style()->marginEnd(), availableLogicalWidth); | 288 minimumValueForLength(style()->marginEnd(), availableLogicalWidth); |
286 LayoutUnit marginTotal = marginStart + marginEnd; | 289 LayoutUnit marginTotal = marginStart + marginEnd; |
287 | 290 |
288 // Subtract out our margins to get the available content width. | 291 // Subtract out our margins to get the available content width. |
289 LayoutUnit availableContentLogicalWidth = | 292 LayoutUnit availableContentLogicalWidth = |
290 (containerWidthInInlineDirection - marginTotal).clampNegativeToZero(); | 293 (containerWidthInInlineDirection - marginTotal).clampNegativeToZero(); |
291 if (shrinkToAvoidFloats() && cb->isLayoutBlockFlow() && | 294 if (shrinkToAvoidFloats() && cb->isLayoutBlockFlow() && |
292 toLayoutBlockFlow(cb)->containsFloats() && | 295 toLayoutBlockFlow(cb)->containsFloats() && |
293 !hasPerpendicularContainingBlock) | 296 !hasPerpendicularContainingBlock) |
294 availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats( | 297 availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats( |
295 marginStart, marginEnd, toLayoutBlockFlow(cb)); | 298 marginStart, marginEnd, toLayoutBlockFlow(cb)); |
296 | 299 |
297 // Ensure we aren't bigger than our available width. | 300 // Ensure we aren't bigger than our available width. |
298 LayoutUnit maxWidth = maxPreferredLogicalWidth(); | 301 LayoutUnit maxWidth = maxPreferredLogicalWidth(); |
299 // scaledWidthFromPercentColumns depends on m_layoutStruct in TableLayoutAlg
orithmAuto, which | 302 // scaledWidthFromPercentColumns depends on m_layoutStruct in |
300 // maxPreferredLogicalWidth fills in. So scaledWidthFromPercentColumns has t
o be called after | 303 // TableLayoutAlgorithmAuto, which maxPreferredLogicalWidth fills in. So |
| 304 // scaledWidthFromPercentColumns has to be called after |
301 // maxPreferredLogicalWidth. | 305 // maxPreferredLogicalWidth. |
302 LayoutUnit scaledWidth = m_tableLayout->scaledWidthFromPercentColumns() + | 306 LayoutUnit scaledWidth = m_tableLayout->scaledWidthFromPercentColumns() + |
303 bordersPaddingAndSpacingInRowDirection(); | 307 bordersPaddingAndSpacingInRowDirection(); |
304 maxWidth = std::max(scaledWidth, maxWidth); | 308 maxWidth = std::max(scaledWidth, maxWidth); |
305 setLogicalWidth( | 309 setLogicalWidth( |
306 LayoutUnit(std::min(availableContentLogicalWidth, maxWidth).floor())); | 310 LayoutUnit(std::min(availableContentLogicalWidth, maxWidth).floor())); |
307 } | 311 } |
308 | 312 |
309 // Ensure we aren't bigger than our max-width style. | 313 // Ensure we aren't bigger than our max-width style. |
310 Length styleMaxLogicalWidth = style()->logicalMaxWidth(); | 314 Length styleMaxLogicalWidth = style()->logicalMaxWidth(); |
311 if ((styleMaxLogicalWidth.isSpecified() && | 315 if ((styleMaxLogicalWidth.isSpecified() && |
312 !styleMaxLogicalWidth.isNegative()) || | 316 !styleMaxLogicalWidth.isNegative()) || |
313 styleMaxLogicalWidth.isIntrinsic()) { | 317 styleMaxLogicalWidth.isIntrinsic()) { |
314 LayoutUnit computedMaxLogicalWidth = | 318 LayoutUnit computedMaxLogicalWidth = |
315 convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, | 319 convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, |
316 availableLogicalWidth); | 320 availableLogicalWidth); |
317 setLogicalWidth( | 321 setLogicalWidth( |
318 LayoutUnit(std::min(logicalWidth(), computedMaxLogicalWidth).floor())); | 322 LayoutUnit(std::min(logicalWidth(), computedMaxLogicalWidth).floor())); |
319 } | 323 } |
320 | 324 |
321 // Ensure we aren't smaller than our min preferred width. This MUST be done af
ter 'max-width' as | 325 // Ensure we aren't smaller than our min preferred width. This MUST be done |
322 // we ignore it if it means we wouldn't accommodate our content. | 326 // after 'max-width' as we ignore it if it means we wouldn't accommodate our |
| 327 // content. |
323 setLogicalWidth( | 328 setLogicalWidth( |
324 LayoutUnit(std::max(logicalWidth(), minPreferredLogicalWidth()).floor())); | 329 LayoutUnit(std::max(logicalWidth(), minPreferredLogicalWidth()).floor())); |
325 | 330 |
326 // Ensure we aren't smaller than our min-width style. | 331 // Ensure we aren't smaller than our min-width style. |
327 Length styleMinLogicalWidth = style()->logicalMinWidth(); | 332 Length styleMinLogicalWidth = style()->logicalMinWidth(); |
328 if ((styleMinLogicalWidth.isSpecified() && | 333 if ((styleMinLogicalWidth.isSpecified() && |
329 !styleMinLogicalWidth.isNegative()) || | 334 !styleMinLogicalWidth.isNegative()) || |
330 styleMinLogicalWidth.isIntrinsic()) { | 335 styleMinLogicalWidth.isIntrinsic()) { |
331 LayoutUnit computedMinLogicalWidth = | 336 LayoutUnit computedMinLogicalWidth = |
332 convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, | 337 convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, |
333 availableLogicalWidth); | 338 availableLogicalWidth); |
334 setLogicalWidth( | 339 setLogicalWidth( |
335 LayoutUnit(std::max(logicalWidth(), computedMinLogicalWidth).floor())); | 340 LayoutUnit(std::max(logicalWidth(), computedMinLogicalWidth).floor())); |
336 } | 341 } |
337 | 342 |
338 // Finally, with our true width determined, compute our margins for real. | 343 // Finally, with our true width determined, compute our margins for real. |
339 ComputedMarginValues marginValues; | 344 ComputedMarginValues marginValues; |
340 computeMarginsForDirection(InlineDirection, cb, availableLogicalWidth, | 345 computeMarginsForDirection(InlineDirection, cb, availableLogicalWidth, |
341 logicalWidth(), marginValues.m_start, | 346 logicalWidth(), marginValues.m_start, |
342 marginValues.m_end, style()->marginStart(), | 347 marginValues.m_end, style()->marginStart(), |
343 style()->marginEnd()); | 348 style()->marginEnd()); |
344 setMarginStart(marginValues.m_start); | 349 setMarginStart(marginValues.m_start); |
345 setMarginEnd(marginValues.m_end); | 350 setMarginEnd(marginValues.m_end); |
346 | 351 |
347 // We should NEVER shrink the table below the min-content logical width, or el
se the table can't accommodate | 352 // We should NEVER shrink the table below the min-content logical width, or |
348 // its own content which doesn't match CSS nor what authors expect. | 353 // else the table can't accommodate its own content which doesn't match CSS |
349 // FIXME: When we convert to sub-pixel layout for tables we can remove the int
conversion | 354 // nor what authors expect. |
350 // https://code.google.com/p/chromium/issues/detail?id=241198 | 355 // FIXME: When we convert to sub-pixel layout for tables we can remove the int |
| 356 // conversion. http://crbug.com/241198 |
351 ASSERT(logicalWidth().floor() >= minPreferredLogicalWidth().floor()); | 357 ASSERT(logicalWidth().floor() >= minPreferredLogicalWidth().floor()); |
352 } | 358 } |
353 | 359 |
354 // This method takes a ComputedStyle's logical width, min-width, or max-width le
ngth and computes its actual value. | 360 // This method takes a ComputedStyle's logical width, min-width, or max-width |
| 361 // length and computes its actual value. |
355 LayoutUnit LayoutTable::convertStyleLogicalWidthToComputedWidth( | 362 LayoutUnit LayoutTable::convertStyleLogicalWidthToComputedWidth( |
356 const Length& styleLogicalWidth, | 363 const Length& styleLogicalWidth, |
357 LayoutUnit availableWidth) { | 364 LayoutUnit availableWidth) { |
358 if (styleLogicalWidth.isIntrinsic()) | 365 if (styleLogicalWidth.isIntrinsic()) |
359 return computeIntrinsicLogicalWidthUsing( | 366 return computeIntrinsicLogicalWidthUsing( |
360 styleLogicalWidth, availableWidth, | 367 styleLogicalWidth, availableWidth, |
361 bordersPaddingAndSpacingInRowDirection()); | 368 bordersPaddingAndSpacingInRowDirection()); |
362 | 369 |
363 // HTML tables' width styles already include borders and paddings, but CSS tab
les' width styles do not. | 370 // HTML tables' width styles already include borders and paddings, but CSS |
| 371 // tables' width styles do not. |
364 LayoutUnit borders; | 372 LayoutUnit borders; |
365 bool isCSSTable = !isHTMLTableElement(node()); | 373 bool isCSSTable = !isHTMLTableElement(node()); |
366 if (isCSSTable && styleLogicalWidth.isSpecified() && | 374 if (isCSSTable && styleLogicalWidth.isSpecified() && |
367 styleLogicalWidth.isPositive() && | 375 styleLogicalWidth.isPositive() && |
368 style()->boxSizing() == BoxSizingContentBox) | 376 style()->boxSizing() == BoxSizingContentBox) |
369 borders = | 377 borders = |
370 borderStart() + borderEnd() + | 378 borderStart() + borderEnd() + |
371 (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd()); | 379 (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd()); |
372 | 380 |
373 return minimumValueForLength(styleLogicalWidth, availableWidth) + borders; | 381 return minimumValueForLength(styleLogicalWidth, availableWidth) + borders; |
374 } | 382 } |
375 | 383 |
376 LayoutUnit LayoutTable::convertStyleLogicalHeightToComputedHeight( | 384 LayoutUnit LayoutTable::convertStyleLogicalHeightToComputedHeight( |
377 const Length& styleLogicalHeight) { | 385 const Length& styleLogicalHeight) { |
378 LayoutUnit borderAndPaddingBefore = | 386 LayoutUnit borderAndPaddingBefore = |
379 borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore()); | 387 borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore()); |
380 LayoutUnit borderAndPaddingAfter = | 388 LayoutUnit borderAndPaddingAfter = |
381 borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter()); | 389 borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter()); |
382 LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter; | 390 LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter; |
383 LayoutUnit computedLogicalHeight; | 391 LayoutUnit computedLogicalHeight; |
384 if (styleLogicalHeight.isFixed()) { | 392 if (styleLogicalHeight.isFixed()) { |
385 // HTML tables size as though CSS height includes border/padding, CSS tables
do not. | 393 // HTML tables size as though CSS height includes border/padding, CSS tables |
| 394 // do not. |
386 LayoutUnit borders = LayoutUnit(); | 395 LayoutUnit borders = LayoutUnit(); |
387 // FIXME: We cannot apply box-sizing: content-box on <table> which other bro
wsers allow. | 396 // FIXME: We cannot apply box-sizing: content-box on <table> which other |
| 397 // browsers allow. |
388 if (isHTMLTableElement(node()) || | 398 if (isHTMLTableElement(node()) || |
389 style()->boxSizing() == BoxSizingBorderBox) { | 399 style()->boxSizing() == BoxSizingBorderBox) { |
390 borders = borderAndPadding; | 400 borders = borderAndPadding; |
391 } | 401 } |
392 computedLogicalHeight = LayoutUnit(styleLogicalHeight.value() - borders); | 402 computedLogicalHeight = LayoutUnit(styleLogicalHeight.value() - borders); |
393 } else if (styleLogicalHeight.isPercentOrCalc()) { | 403 } else if (styleLogicalHeight.isPercentOrCalc()) { |
394 computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight); | 404 computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight); |
395 } else if (styleLogicalHeight.isIntrinsic()) { | 405 } else if (styleLogicalHeight.isIntrinsic()) { |
396 computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing( | 406 computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing( |
397 styleLogicalHeight, logicalHeight() - borderAndPadding, | 407 styleLogicalHeight, logicalHeight() - borderAndPadding, |
398 borderAndPadding); | 408 borderAndPadding); |
399 } else { | 409 } else { |
400 ASSERT_NOT_REACHED(); | 410 ASSERT_NOT_REACHED(); |
401 } | 411 } |
402 return computedLogicalHeight.clampNegativeToZero(); | 412 return computedLogicalHeight.clampNegativeToZero(); |
403 } | 413 } |
404 | 414 |
405 void LayoutTable::layoutCaption(LayoutTableCaption& caption) { | 415 void LayoutTable::layoutCaption(LayoutTableCaption& caption) { |
406 if (caption.needsLayout()) { | 416 if (caption.needsLayout()) { |
407 // The margins may not be available but ensure the caption is at least locat
ed beneath any previous sibling caption | 417 // The margins may not be available but ensure the caption is at least |
408 // so that it does not mistakenly think any floats in the previous caption i
ntrude into it. | 418 // located beneath any previous sibling caption so that it does not |
| 419 // mistakenly think any floats in the previous caption intrude into it. |
409 caption.setLogicalLocation( | 420 caption.setLogicalLocation( |
410 LayoutPoint(caption.marginStart(), | 421 LayoutPoint(caption.marginStart(), |
411 collapsedMarginBeforeForChild(caption) + logicalHeight())); | 422 collapsedMarginBeforeForChild(caption) + logicalHeight())); |
412 // If LayoutTableCaption ever gets a layout() function, use it here. | 423 // If LayoutTableCaption ever gets a layout() function, use it here. |
413 caption.layoutIfNeeded(); | 424 caption.layoutIfNeeded(); |
414 } | 425 } |
415 // Apply the margins to the location now that they are definitely available fr
om layout | 426 // Apply the margins to the location now that they are definitely available |
| 427 // from layout |
416 LayoutUnit captionLogicalTop = | 428 LayoutUnit captionLogicalTop = |
417 collapsedMarginBeforeForChild(caption) + logicalHeight(); | 429 collapsedMarginBeforeForChild(caption) + logicalHeight(); |
418 caption.setLogicalLocation( | 430 caption.setLogicalLocation( |
419 LayoutPoint(caption.marginStart(), captionLogicalTop)); | 431 LayoutPoint(caption.marginStart(), captionLogicalTop)); |
420 | 432 |
421 if (!selfNeedsLayout()) | 433 if (!selfNeedsLayout()) |
422 caption.setMayNeedPaintInvalidation(); | 434 caption.setMayNeedPaintInvalidation(); |
423 | 435 |
424 setLogicalHeight(logicalHeight() + caption.logicalHeight() + | 436 setLogicalHeight(logicalHeight() + caption.logicalHeight() + |
425 collapsedMarginBeforeForChild(caption) + | 437 collapsedMarginBeforeForChild(caption) + |
426 collapsedMarginAfterForChild(caption)); | 438 collapsedMarginAfterForChild(caption)); |
427 } | 439 } |
428 | 440 |
429 void LayoutTable::distributeExtraLogicalHeight(int extraLogicalHeight) { | 441 void LayoutTable::distributeExtraLogicalHeight(int extraLogicalHeight) { |
430 if (extraLogicalHeight <= 0) | 442 if (extraLogicalHeight <= 0) |
431 return; | 443 return; |
432 | 444 |
433 // FIXME: Distribute the extra logical height between all table sections inste
ad of giving it all to the first one. | 445 // FIXME: Distribute the extra logical height between all table sections |
| 446 // instead of giving it all to the first one. |
434 if (LayoutTableSection* section = firstBody()) | 447 if (LayoutTableSection* section = firstBody()) |
435 extraLogicalHeight -= | 448 extraLogicalHeight -= |
436 section->distributeExtraLogicalHeightToRows(extraLogicalHeight); | 449 section->distributeExtraLogicalHeightToRows(extraLogicalHeight); |
437 | 450 |
438 // FIXME: We really would like to enable this ASSERT to ensure that all the ex
tra space has been distributed. | 451 // FIXME: We really would like to enable this ASSERT to ensure that all the |
439 // However our current distribution algorithm does not round properly and thus
we can have some remaining height. | 452 // extra space has been distributed. |
| 453 // However our current distribution algorithm does not round properly and thus |
| 454 // we can have some remaining height. |
440 // ASSERT(!topSection() || !extraLogicalHeight); | 455 // ASSERT(!topSection() || !extraLogicalHeight); |
441 } | 456 } |
442 | 457 |
443 void LayoutTable::simplifiedNormalFlowLayout() { | 458 void LayoutTable::simplifiedNormalFlowLayout() { |
444 // FIXME: We should walk through the items in the tree in tree order to do the
layout here | 459 // FIXME: We should walk through the items in the tree in tree order to do the |
445 // instead of walking through individual parts of the tree. crbug.com/442737 | 460 // layout here instead of walking through individual parts of the tree. |
| 461 // crbug.com/442737 |
446 for (auto& caption : m_captions) | 462 for (auto& caption : m_captions) |
447 caption->layoutIfNeeded(); | 463 caption->layoutIfNeeded(); |
448 | 464 |
449 for (LayoutTableSection* section = topSection(); section; | 465 for (LayoutTableSection* section = topSection(); section; |
450 section = sectionBelow(section)) { | 466 section = sectionBelow(section)) { |
451 section->layoutIfNeeded(); | 467 section->layoutIfNeeded(); |
452 section->layoutRows(); | 468 section->layoutRows(); |
453 section->computeOverflowFromCells(); | 469 section->computeOverflowFromCells(); |
454 section->updateLayerTransformAfterLayout(); | 470 section->updateLayerTransformAfterLayout(); |
455 section->addVisualEffectOverflow(); | 471 section->addVisualEffectOverflow(); |
456 } | 472 } |
457 } | 473 } |
458 | 474 |
459 bool LayoutTable::recalcChildOverflowAfterStyleChange() { | 475 bool LayoutTable::recalcChildOverflowAfterStyleChange() { |
460 ASSERT(childNeedsOverflowRecalcAfterStyleChange()); | 476 ASSERT(childNeedsOverflowRecalcAfterStyleChange()); |
461 clearChildNeedsOverflowRecalcAfterStyleChange(); | 477 clearChildNeedsOverflowRecalcAfterStyleChange(); |
462 | 478 |
463 // If the table sections we keep pointers to have gone away then the table wil
l be rebuilt and | 479 // If the table sections we keep pointers to have gone away then the table |
464 // overflow will get recalculated anyway so return early. | 480 // will be rebuilt and overflow will get recalculated anyway so return early. |
465 if (needsSectionRecalc()) | 481 if (needsSectionRecalc()) |
466 return false; | 482 return false; |
467 | 483 |
468 bool childrenOverflowChanged = false; | 484 bool childrenOverflowChanged = false; |
469 for (LayoutTableSection* section = topSection(); section; | 485 for (LayoutTableSection* section = topSection(); section; |
470 section = sectionBelow(section)) { | 486 section = sectionBelow(section)) { |
471 if (!section->childNeedsOverflowRecalcAfterStyleChange()) | 487 if (!section->childNeedsOverflowRecalcAfterStyleChange()) |
472 continue; | 488 continue; |
473 childrenOverflowChanged = section->recalcChildOverflowAfterStyleChange() || | 489 childrenOverflowChanged = section->recalcChildOverflowAfterStyleChange() || |
474 childrenOverflowChanged; | 490 childrenOverflowChanged; |
475 } | 491 } |
476 return recalcPositionedDescendantsOverflowAfterStyleChange() || | 492 return recalcPositionedDescendantsOverflowAfterStyleChange() || |
477 childrenOverflowChanged; | 493 childrenOverflowChanged; |
478 } | 494 } |
479 | 495 |
480 void LayoutTable::layout() { | 496 void LayoutTable::layout() { |
481 ASSERT(needsLayout()); | 497 ASSERT(needsLayout()); |
482 LayoutAnalyzer::Scope analyzer(*this); | 498 LayoutAnalyzer::Scope analyzer(*this); |
483 | 499 |
484 if (simplifiedLayout()) | 500 if (simplifiedLayout()) |
485 return; | 501 return; |
486 | 502 |
487 // Note: LayoutTable is handled differently than other LayoutBlocks and the La
youtScope | 503 // Note: LayoutTable is handled differently than other LayoutBlocks and the |
| 504 // LayoutScope |
488 // must be created before the table begins laying out. | 505 // must be created before the table begins laying out. |
489 TextAutosizer::LayoutScope textAutosizerLayoutScope(this); | 506 TextAutosizer::LayoutScope textAutosizerLayoutScope(this); |
490 | 507 |
491 recalcSectionsIfNeeded(); | 508 recalcSectionsIfNeeded(); |
492 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we
don't have to make sure | 509 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we |
493 // to call this before we call borderStart/borderEnd to avoid getting a stale
value. | 510 // don't have to make sure to call this before we call borderStart/borderEnd |
| 511 // to avoid getting a stale value. |
494 recalcBordersInRowDirection(); | 512 recalcBordersInRowDirection(); |
495 | 513 |
496 SubtreeLayoutScope layouter(*this); | 514 SubtreeLayoutScope layouter(*this); |
497 | 515 |
498 // If any table section moved vertically, we will just issue paint invalidatio
ns for everything from that | 516 // If any table section moved vertically, we will just issue paint |
499 // section down (it is quite unlikely that any of the following sections | 517 // invalidations for everything from that section down (it is quite unlikely |
500 // did not shift). | 518 // that any of the following sections did not shift). |
501 bool sectionMoved = false; | 519 bool sectionMoved = false; |
502 { | 520 { |
503 LayoutState state(*this, locationOffset()); | 521 LayoutState state(*this, locationOffset()); |
504 LayoutUnit oldLogicalWidth = logicalWidth(); | 522 LayoutUnit oldLogicalWidth = logicalWidth(); |
505 LayoutUnit oldLogicalHeight = logicalHeight(); | 523 LayoutUnit oldLogicalHeight = logicalHeight(); |
506 | 524 |
507 setLogicalHeight(LayoutUnit()); | 525 setLogicalHeight(LayoutUnit()); |
508 updateLogicalWidth(); | 526 updateLogicalWidth(); |
509 | 527 |
510 if (logicalWidth() != oldLogicalWidth) { | 528 if (logicalWidth() != oldLogicalWidth) { |
(...skipping 27 matching lines...) Expand all Loading... |
538 layouter.setChildNeedsLayout(section); | 556 layouter.setChildNeedsLayout(section); |
539 section->layoutIfNeeded(); | 557 section->layoutIfNeeded(); |
540 totalSectionLogicalHeight += section->calcRowLogicalHeight(); | 558 totalSectionLogicalHeight += section->calcRowLogicalHeight(); |
541 if (collapsing) | 559 if (collapsing) |
542 section->recalcOuterBorder(); | 560 section->recalcOuterBorder(); |
543 ASSERT(!section->needsLayout()); | 561 ASSERT(!section->needsLayout()); |
544 } else if (child->isLayoutTableCol()) { | 562 } else if (child->isLayoutTableCol()) { |
545 child->layoutIfNeeded(); | 563 child->layoutIfNeeded(); |
546 ASSERT(!child->needsLayout()); | 564 ASSERT(!child->needsLayout()); |
547 } else { | 565 } else { |
548 // FIXME: We should never have other type of children (they should be wr
apped in an | 566 // FIXME: We should never have other type of children (they should be |
549 // anonymous table section) but our code is too crazy and this can happe
n in practice. | 567 // wrapped in an anonymous table section) but our code is too crazy and |
550 // Until this is fixed, let's make sure we don't leave non laid out chil
dren in the tree. | 568 // this can happen in practice. Until this is fixed, let's make sure we |
| 569 // don't leave non laid out children in the tree. |
551 child->layoutIfNeeded(); | 570 child->layoutIfNeeded(); |
552 } | 571 } |
553 } | 572 } |
554 | 573 |
555 // FIXME: Collapse caption margin. | 574 // FIXME: Collapse caption margin. |
556 if (!m_captions.isEmpty()) { | 575 if (!m_captions.isEmpty()) { |
557 for (unsigned i = 0; i < m_captions.size(); i++) { | 576 for (unsigned i = 0; i < m_captions.size(); i++) { |
558 if (m_captions[i]->style()->captionSide() == ECaptionSide::Bottom) | 577 if (m_captions[i]->style()->captionSide() == ECaptionSide::Bottom) |
559 continue; | 578 continue; |
560 layoutCaption(*m_captions[i]); | 579 layoutCaption(*m_captions[i]); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 | 621 |
603 bool isPaginated = view()->layoutState()->isPaginated(); | 622 bool isPaginated = view()->layoutState()->isPaginated(); |
604 LayoutTableSection* topSection = this->topSection(); | 623 LayoutTableSection* topSection = this->topSection(); |
605 LayoutUnit logicalOffset = | 624 LayoutUnit logicalOffset = |
606 topSection ? topSection->logicalTop() : LayoutUnit(); | 625 topSection ? topSection->logicalTop() : LayoutUnit(); |
607 for (LayoutTableSection* section = topSection; section; | 626 for (LayoutTableSection* section = topSection; section; |
608 section = sectionBelow(section)) { | 627 section = sectionBelow(section)) { |
609 section->setLogicalTop(logicalOffset); | 628 section->setLogicalTop(logicalOffset); |
610 section->layoutRows(); | 629 section->layoutRows(); |
611 logicalOffset += section->logicalHeight(); | 630 logicalOffset += section->logicalHeight(); |
612 // If the section is a repeating header group that allows at least one row
of content then store the | 631 // If the section is a repeating header group that allows at least one row |
613 // offset for other sections to offset their rows against. | 632 // of content then store the offset for other sections to offset their |
| 633 // rows against. |
614 if (isPaginated && m_head && m_head == section && | 634 if (isPaginated && m_head && m_head == section && |
615 section->logicalHeight() < | 635 section->logicalHeight() < |
616 section->pageLogicalHeightForOffset(logicalOffset) && | 636 section->pageLogicalHeightForOffset(logicalOffset) && |
617 section->getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { | 637 section->getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { |
618 LayoutUnit offsetForTableHeaders = state.heightOffsetForTableHeaders(); | 638 LayoutUnit offsetForTableHeaders = state.heightOffsetForTableHeaders(); |
619 // Don't include any strut in the header group - we only want the height
from its content. | 639 // Don't include any strut in the header group - we only want the height |
| 640 // from its content. |
620 offsetForTableHeaders += section->logicalHeight(); | 641 offsetForTableHeaders += section->logicalHeight(); |
621 if (LayoutTableRow* row = section->firstRow()) | 642 if (LayoutTableRow* row = section->firstRow()) |
622 offsetForTableHeaders -= row->paginationStrut(); | 643 offsetForTableHeaders -= row->paginationStrut(); |
623 state.setHeightOffsetForTableHeaders(offsetForTableHeaders); | 644 state.setHeightOffsetForTableHeaders(offsetForTableHeaders); |
624 } | 645 } |
625 } | 646 } |
626 | 647 |
627 if (!topSection && computedLogicalHeight > totalSectionLogicalHeight && | 648 if (!topSection && computedLogicalHeight > totalSectionLogicalHeight && |
628 !document().inQuirksMode()) { | 649 !document().inQuirksMode()) { |
629 // Completely empty tables (with no sections or anything) should at least
honor specified height | 650 // Completely empty tables (with no sections or anything) should at least |
630 // in strict mode. | 651 // honor specified height in strict mode. |
631 setLogicalHeight(logicalHeight() + computedLogicalHeight); | 652 setLogicalHeight(logicalHeight() + computedLogicalHeight); |
632 } | 653 } |
633 | 654 |
634 LayoutUnit sectionLogicalLeft = LayoutUnit( | 655 LayoutUnit sectionLogicalLeft = LayoutUnit( |
635 style()->isLeftToRightDirection() ? borderStart() : borderEnd()); | 656 style()->isLeftToRightDirection() ? borderStart() : borderEnd()); |
636 if (!collapsing) | 657 if (!collapsing) |
637 sectionLogicalLeft += | 658 sectionLogicalLeft += |
638 style()->isLeftToRightDirection() ? paddingStart() : paddingEnd(); | 659 style()->isLeftToRightDirection() ? paddingStart() : paddingEnd(); |
639 | 660 |
640 // position the table sections | 661 // position the table sections |
641 LayoutTableSection* section = topSection; | 662 LayoutTableSection* section = topSection; |
642 while (section) { | 663 while (section) { |
643 if (!sectionMoved && section->logicalTop() != logicalHeight()) | 664 if (!sectionMoved && section->logicalTop() != logicalHeight()) |
644 sectionMoved = true; | 665 sectionMoved = true; |
645 section->setLogicalLocation( | 666 section->setLogicalLocation( |
646 LayoutPoint(sectionLogicalLeft, logicalHeight())); | 667 LayoutPoint(sectionLogicalLeft, logicalHeight())); |
647 | 668 |
648 // As we may skip invalidation on the table, we need to ensure that sectio
ns are invalidated when they moved. | 669 // As we may skip invalidation on the table, we need to ensure that |
| 670 // sections are invalidated when they moved. |
649 if (sectionMoved && !section->selfNeedsLayout()) | 671 if (sectionMoved && !section->selfNeedsLayout()) |
650 section->setMayNeedPaintInvalidation(); | 672 section->setMayNeedPaintInvalidation(); |
651 | 673 |
652 setLogicalHeight(logicalHeight() + section->logicalHeight()); | 674 setLogicalHeight(logicalHeight() + section->logicalHeight()); |
653 | 675 |
654 section->updateLayerTransformAfterLayout(); | 676 section->updateLayerTransformAfterLayout(); |
655 section->addVisualEffectOverflow(); | 677 section->addVisualEffectOverflow(); |
656 | 678 |
657 section = sectionBelow(section); | 679 section = sectionBelow(section); |
658 } | 680 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 void LayoutTable::invalidateCollapsedBorders() { | 718 void LayoutTable::invalidateCollapsedBorders() { |
697 m_collapsedBorders.clear(); | 719 m_collapsedBorders.clear(); |
698 if (!collapseBorders()) | 720 if (!collapseBorders()) |
699 return; | 721 return; |
700 | 722 |
701 m_collapsedBordersValid = false; | 723 m_collapsedBordersValid = false; |
702 setMayNeedPaintInvalidation(); | 724 setMayNeedPaintInvalidation(); |
703 } | 725 } |
704 | 726 |
705 // Collect all the unique border values that we want to paint in a sorted list. | 727 // Collect all the unique border values that we want to paint in a sorted list. |
706 // During the collection, each cell saves its recalculated borders into the cach
e | 728 // During the collection, each cell saves its recalculated borders into the |
707 // of its containing section, and invalidates itself if any border changes. | 729 // cache of its containing section, and invalidates itself if any border |
708 // This method doesn't affect layout. | 730 // changes. This method doesn't affect layout. |
709 void LayoutTable::recalcCollapsedBordersIfNeeded() { | 731 void LayoutTable::recalcCollapsedBordersIfNeeded() { |
710 if (m_collapsedBordersValid || !collapseBorders()) | 732 if (m_collapsedBordersValid || !collapseBorders()) |
711 return; | 733 return; |
712 m_collapsedBordersValid = true; | 734 m_collapsedBordersValid = true; |
713 m_collapsedBorders.clear(); | 735 m_collapsedBorders.clear(); |
714 for (LayoutObject* section = firstChild(); section; | 736 for (LayoutObject* section = firstChild(); section; |
715 section = section->nextSibling()) { | 737 section = section->nextSibling()) { |
716 if (!section->isTableSection()) | 738 if (!section->isTableSection()) |
717 continue; | 739 continue; |
718 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row; | 740 for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row; |
719 row = row->nextRow()) { | 741 row = row->nextRow()) { |
720 for (LayoutTableCell* cell = row->firstCell(); cell; | 742 for (LayoutTableCell* cell = row->firstCell(); cell; |
721 cell = cell->nextCell()) { | 743 cell = cell->nextCell()) { |
722 ASSERT(cell->table() == this); | 744 ASSERT(cell->table() == this); |
723 cell->collectBorderValues(m_collapsedBorders); | 745 cell->collectBorderValues(m_collapsedBorders); |
724 } | 746 } |
725 } | 747 } |
726 } | 748 } |
727 LayoutTableCell::sortBorderValues(m_collapsedBorders); | 749 LayoutTableCell::sortBorderValues(m_collapsedBorders); |
728 } | 750 } |
729 | 751 |
730 void LayoutTable::addOverflowFromChildren() { | 752 void LayoutTable::addOverflowFromChildren() { |
731 // Add overflow from borders. | 753 // Add overflow from borders. |
732 // Technically it's odd that we are incorporating the borders into layout over
flow, which is only supposed to be about overflow from our | 754 // Technically it's odd that we are incorporating the borders into layout |
733 // descendant objects, but since tables don't support overflow:auto, this work
s out fine. | 755 // overflow, which is only supposed to be about overflow from our |
| 756 // descendant objects, but since tables don't support overflow:auto, this |
| 757 // works out fine. |
734 if (collapseBorders()) { | 758 if (collapseBorders()) { |
735 int rightBorderOverflow = | 759 int rightBorderOverflow = |
736 (size().width() + outerBorderRight() - borderRight()).toInt(); | 760 (size().width() + outerBorderRight() - borderRight()).toInt(); |
737 int leftBorderOverflow = borderLeft() - outerBorderLeft(); | 761 int leftBorderOverflow = borderLeft() - outerBorderLeft(); |
738 int bottomBorderOverflow = | 762 int bottomBorderOverflow = |
739 (size().height() + outerBorderBottom() - borderBottom()).toInt(); | 763 (size().height() + outerBorderBottom() - borderBottom()).toInt(); |
740 int topBorderOverflow = borderTop() - outerBorderTop(); | 764 int topBorderOverflow = borderTop() - outerBorderTop(); |
741 IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, | 765 IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, |
742 rightBorderOverflow - leftBorderOverflow, | 766 rightBorderOverflow - leftBorderOverflow, |
743 bottomBorderOverflow - topBorderOverflow); | 767 bottomBorderOverflow - topBorderOverflow); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 } | 825 } |
802 | 826 |
803 void LayoutTable::paintMask(const PaintInfo& paintInfo, | 827 void LayoutTable::paintMask(const PaintInfo& paintInfo, |
804 const LayoutPoint& paintOffset) const { | 828 const LayoutPoint& paintOffset) const { |
805 TablePainter(*this).paintMask(paintInfo, paintOffset); | 829 TablePainter(*this).paintMask(paintInfo, paintOffset); |
806 } | 830 } |
807 | 831 |
808 void LayoutTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, | 832 void LayoutTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, |
809 LayoutUnit& maxWidth) const { | 833 LayoutUnit& maxWidth) const { |
810 recalcSectionsIfNeeded(); | 834 recalcSectionsIfNeeded(); |
811 // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast thi
s call. | 835 // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast |
812 // Then m_borderStart/m_borderEnd will be transparent a cache and it removes t
he possibility | 836 // this call. |
813 // of reading out stale values. | 837 // Then m_borderStart/m_borderEnd will be transparent a cache and it removes |
| 838 // the possibility of reading out stale values. |
814 const_cast<LayoutTable*>(this)->recalcBordersInRowDirection(); | 839 const_cast<LayoutTable*>(this)->recalcBordersInRowDirection(); |
815 // FIXME: Restructure the table layout code so that we can make this method co
nst. | 840 // FIXME: Restructure the table layout code so that we can make this method |
| 841 // const. |
816 const_cast<LayoutTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths( | 842 const_cast<LayoutTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths( |
817 minWidth, maxWidth); | 843 minWidth, maxWidth); |
818 | 844 |
819 // FIXME: We should include captions widths here like we do in computePreferre
dLogicalWidths. | 845 // FIXME: We should include captions widths here like we do in |
| 846 // computePreferredLogicalWidths. |
820 } | 847 } |
821 | 848 |
822 void LayoutTable::computePreferredLogicalWidths() { | 849 void LayoutTable::computePreferredLogicalWidths() { |
823 ASSERT(preferredLogicalWidthsDirty()); | 850 ASSERT(preferredLogicalWidthsDirty()); |
824 | 851 |
825 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, | 852 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, |
826 m_maxPreferredLogicalWidth); | 853 m_maxPreferredLogicalWidth); |
827 | 854 |
828 int bordersPaddingAndSpacing = | 855 int bordersPaddingAndSpacing = |
829 bordersPaddingAndSpacingInRowDirection().toInt(); | 856 bordersPaddingAndSpacingInRowDirection().toInt(); |
830 m_minPreferredLogicalWidth += bordersPaddingAndSpacing; | 857 m_minPreferredLogicalWidth += bordersPaddingAndSpacing; |
831 m_maxPreferredLogicalWidth += bordersPaddingAndSpacing; | 858 m_maxPreferredLogicalWidth += bordersPaddingAndSpacing; |
832 | 859 |
833 m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, | 860 m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, |
834 m_maxPreferredLogicalWidth); | 861 m_maxPreferredLogicalWidth); |
835 | 862 |
836 for (unsigned i = 0; i < m_captions.size(); i++) | 863 for (unsigned i = 0; i < m_captions.size(); i++) |
837 m_minPreferredLogicalWidth = std::max( | 864 m_minPreferredLogicalWidth = std::max( |
838 m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth()); | 865 m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth()); |
839 | 866 |
840 const ComputedStyle& styleToUse = styleRef(); | 867 const ComputedStyle& styleToUse = styleRef(); |
841 // FIXME: This should probably be checking for isSpecified since you should be
able to use percentage or calc values for min-width. | 868 // FIXME: This should probably be checking for isSpecified since you should be |
| 869 // able to use percentage or calc values for min-width. |
842 if (styleToUse.logicalMinWidth().isFixed() && | 870 if (styleToUse.logicalMinWidth().isFixed() && |
843 styleToUse.logicalMinWidth().value() > 0) { | 871 styleToUse.logicalMinWidth().value() > 0) { |
844 m_maxPreferredLogicalWidth = std::max( | 872 m_maxPreferredLogicalWidth = std::max( |
845 m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( | 873 m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( |
846 styleToUse.logicalMinWidth().value())); | 874 styleToUse.logicalMinWidth().value())); |
847 m_minPreferredLogicalWidth = std::max( | 875 m_minPreferredLogicalWidth = std::max( |
848 m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( | 876 m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( |
849 styleToUse.logicalMinWidth().value())); | 877 styleToUse.logicalMinWidth().value())); |
850 } | 878 } |
851 | 879 |
852 // FIXME: This should probably be checking for isSpecified since you should be
able to use percentage or calc values for maxWidth. | 880 // FIXME: This should probably be checking for isSpecified since you should be |
| 881 // able to use percentage or calc values for maxWidth. |
853 if (styleToUse.logicalMaxWidth().isFixed()) { | 882 if (styleToUse.logicalMaxWidth().isFixed()) { |
854 // We don't constrain m_minPreferredLogicalWidth as the table should be at l
east the size of its min-content, regardless of 'max-width'. | 883 // We don't constrain m_minPreferredLogicalWidth as the table should be at |
| 884 // least the size of its min-content, regardless of 'max-width'. |
855 m_maxPreferredLogicalWidth = std::min( | 885 m_maxPreferredLogicalWidth = std::min( |
856 m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( | 886 m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing( |
857 styleToUse.logicalMaxWidth().value())); | 887 styleToUse.logicalMaxWidth().value())); |
858 m_maxPreferredLogicalWidth = | 888 m_maxPreferredLogicalWidth = |
859 std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); | 889 std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); |
860 } | 890 } |
861 | 891 |
862 // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLa
yout->computePreferredLogicalWidths already does, | 892 // FIXME: We should be adding borderAndPaddingLogicalWidth here, but |
863 // so a bunch of tests break doing this naively. | 893 // m_tableLayout->computePreferredLogicalWidths already does, so a bunch of |
| 894 // tests break doing this naively. |
864 clearPreferredLogicalWidthsDirty(); | 895 clearPreferredLogicalWidthsDirty(); |
865 } | 896 } |
866 | 897 |
867 LayoutTableSection* LayoutTable::topNonEmptySection() const { | 898 LayoutTableSection* LayoutTable::topNonEmptySection() const { |
868 LayoutTableSection* section = topSection(); | 899 LayoutTableSection* section = topSection(); |
869 if (section && !section->numRows()) | 900 if (section && !section->numRows()) |
870 section = sectionBelow(section, SkipEmptySections); | 901 section = sectionBelow(section, SkipEmptySections); |
871 return section; | 902 return section; |
872 } | 903 } |
873 | 904 |
874 void LayoutTable::splitEffectiveColumn(unsigned index, unsigned firstSpan) { | 905 void LayoutTable::splitEffectiveColumn(unsigned index, unsigned firstSpan) { |
875 // We split the column at |index|, taking |firstSpan| cells from the span. | 906 // We split the column at |index|, taking |firstSpan| cells from the span. |
876 ASSERT(m_effectiveColumns[index].span > firstSpan); | 907 ASSERT(m_effectiveColumns[index].span > firstSpan); |
877 m_effectiveColumns.insert(index, firstSpan); | 908 m_effectiveColumns.insert(index, firstSpan); |
878 m_effectiveColumns[index + 1].span -= firstSpan; | 909 m_effectiveColumns[index + 1].span -= firstSpan; |
879 | 910 |
880 // Propagate the change in our columns representation to the sections that don
't need | 911 // Propagate the change in our columns representation to the sections that |
881 // cell recalc. If they do, they will be synced up directly with m_columns lat
er. | 912 // don't need cell recalc. If they do, they will be synced up directly with |
| 913 // m_columns later. |
882 for (LayoutObject* child = firstChild(); child; | 914 for (LayoutObject* child = firstChild(); child; |
883 child = child->nextSibling()) { | 915 child = child->nextSibling()) { |
884 if (!child->isTableSection()) | 916 if (!child->isTableSection()) |
885 continue; | 917 continue; |
886 | 918 |
887 LayoutTableSection* section = toLayoutTableSection(child); | 919 LayoutTableSection* section = toLayoutTableSection(child); |
888 if (section->needsCellRecalc()) | 920 if (section->needsCellRecalc()) |
889 continue; | 921 continue; |
890 | 922 |
891 section->splitEffectiveColumn(index, firstSpan); | 923 section->splitEffectiveColumn(index, firstSpan); |
892 } | 924 } |
893 | 925 |
894 m_effectiveColumnPositions.grow(numEffectiveColumns() + 1); | 926 m_effectiveColumnPositions.grow(numEffectiveColumns() + 1); |
895 } | 927 } |
896 | 928 |
897 void LayoutTable::appendEffectiveColumn(unsigned span) { | 929 void LayoutTable::appendEffectiveColumn(unsigned span) { |
898 unsigned newColumnIndex = m_effectiveColumns.size(); | 930 unsigned newColumnIndex = m_effectiveColumns.size(); |
899 m_effectiveColumns.append(span); | 931 m_effectiveColumns.append(span); |
900 | 932 |
901 // Unless the table has cell(s) with colspan that exceed the number of columns
afforded | 933 // Unless the table has cell(s) with colspan that exceed the number of columns |
902 // by the other rows in the table we can use the fast path when mapping column
s to effective columns. | 934 // afforded by the other rows in the table we can use the fast path when |
| 935 // mapping columns to effective columns. |
903 if (span == 1 && m_noCellColspanAtLeast + 1 == numEffectiveColumns()) { | 936 if (span == 1 && m_noCellColspanAtLeast + 1 == numEffectiveColumns()) { |
904 m_noCellColspanAtLeast++; | 937 m_noCellColspanAtLeast++; |
905 } | 938 } |
906 | 939 |
907 // Propagate the change in our columns representation to the sections that don
't need | 940 // Propagate the change in our columns representation to the sections that |
908 // cell recalc. If they do, they will be synced up directly with m_columns lat
er. | 941 // don't need cell recalc. If they do, they will be synced up directly with |
| 942 // m_columns later. |
909 for (LayoutObject* child = firstChild(); child; | 943 for (LayoutObject* child = firstChild(); child; |
910 child = child->nextSibling()) { | 944 child = child->nextSibling()) { |
911 if (!child->isTableSection()) | 945 if (!child->isTableSection()) |
912 continue; | 946 continue; |
913 | 947 |
914 LayoutTableSection* section = toLayoutTableSection(child); | 948 LayoutTableSection* section = toLayoutTableSection(child); |
915 if (section->needsCellRecalc()) | 949 if (section->needsCellRecalc()) |
916 continue; | 950 continue; |
917 | 951 |
918 section->appendEffectiveColumn(newColumnIndex); | 952 section->appendEffectiveColumn(newColumnIndex); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 if (!m_firstBody) | 1063 if (!m_firstBody) |
1030 m_firstBody = section; | 1064 m_firstBody = section; |
1031 section->recalcCellsIfNeeded(); | 1065 section->recalcCellsIfNeeded(); |
1032 } | 1066 } |
1033 break; | 1067 break; |
1034 default: | 1068 default: |
1035 break; | 1069 break; |
1036 } | 1070 } |
1037 } | 1071 } |
1038 | 1072 |
1039 // repair column count (addChild can grow it too much, because it always adds
elements to the last row of a section) | 1073 // repair column count (addChild can grow it too much, because it always adds |
| 1074 // elements to the last row of a section) |
1040 unsigned maxCols = 0; | 1075 unsigned maxCols = 0; |
1041 for (LayoutObject* child = firstChild(); child; | 1076 for (LayoutObject* child = firstChild(); child; |
1042 child = child->nextSibling()) { | 1077 child = child->nextSibling()) { |
1043 if (child->isTableSection()) { | 1078 if (child->isTableSection()) { |
1044 LayoutTableSection* section = toLayoutTableSection(child); | 1079 LayoutTableSection* section = toLayoutTableSection(child); |
1045 unsigned sectionCols = section->numEffectiveColumns(); | 1080 unsigned sectionCols = section->numEffectiveColumns(); |
1046 if (sectionCols > maxCols) | 1081 if (sectionCols > maxCols) |
1047 maxCols = sectionCols; | 1082 maxCols = sectionCols; |
1048 } | 1083 } |
1049 } | 1084 } |
1050 | 1085 |
1051 m_effectiveColumns.resize(maxCols); | 1086 m_effectiveColumns.resize(maxCols); |
1052 m_effectiveColumnPositions.resize(maxCols + 1); | 1087 m_effectiveColumnPositions.resize(maxCols + 1); |
1053 | 1088 |
1054 ASSERT(selfNeedsLayout()); | 1089 ASSERT(selfNeedsLayout()); |
1055 | 1090 |
1056 m_needsSectionRecalc = false; | 1091 m_needsSectionRecalc = false; |
1057 } | 1092 } |
1058 | 1093 |
1059 int LayoutTable::calcBorderStart() const { | 1094 int LayoutTable::calcBorderStart() const { |
1060 if (!collapseBorders()) | 1095 if (!collapseBorders()) |
1061 return LayoutBlock::borderStart(); | 1096 return LayoutBlock::borderStart(); |
1062 | 1097 |
1063 // Determined by the first cell of the first row. See the CSS 2.1 spec, sectio
n 17.6.2. | 1098 // Determined by the first cell of the first row. See the CSS 2.1 spec, |
| 1099 // section 17.6.2. |
1064 if (!numEffectiveColumns()) | 1100 if (!numEffectiveColumns()) |
1065 return 0; | 1101 return 0; |
1066 | 1102 |
1067 int borderWidth = 0; | 1103 int borderWidth = 0; |
1068 | 1104 |
1069 const BorderValue& tableStartBorder = style()->borderStart(); | 1105 const BorderValue& tableStartBorder = style()->borderStart(); |
1070 if (tableStartBorder.style() == BorderStyleHidden) | 1106 if (tableStartBorder.style() == BorderStyleHidden) |
1071 return 0; | 1107 return 0; |
1072 if (tableStartBorder.style() > BorderStyleHidden) | 1108 if (tableStartBorder.style() > BorderStyleHidden) |
1073 borderWidth = tableStartBorder.width(); | 1109 borderWidth = tableStartBorder.width(); |
1074 | 1110 |
1075 // TODO(dgrogan): This logic doesn't properly account for the first column in
the first column-group case. | 1111 // TODO(dgrogan): This logic doesn't properly account for the first column in |
| 1112 // the first column-group case. |
1076 if (LayoutTableCol* column = | 1113 if (LayoutTableCol* column = |
1077 colElementAtAbsoluteColumn(0).innermostColOrColGroup()) { | 1114 colElementAtAbsoluteColumn(0).innermostColOrColGroup()) { |
1078 // FIXME: We don't account for direction on columns and column groups. | 1115 // FIXME: We don't account for direction on columns and column groups. |
1079 const BorderValue& columnAdjoiningBorder = column->style()->borderStart(); | 1116 const BorderValue& columnAdjoiningBorder = column->style()->borderStart(); |
1080 if (columnAdjoiningBorder.style() == BorderStyleHidden) | 1117 if (columnAdjoiningBorder.style() == BorderStyleHidden) |
1081 return 0; | 1118 return 0; |
1082 if (columnAdjoiningBorder.style() > BorderStyleHidden) | 1119 if (columnAdjoiningBorder.style() > BorderStyleHidden) |
1083 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width()); | 1120 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width()); |
1084 } | 1121 } |
1085 | 1122 |
(...skipping 26 matching lines...) Expand all Loading... |
1112 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width()); | 1149 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width()); |
1113 } | 1150 } |
1114 } | 1151 } |
1115 return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2; | 1152 return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2; |
1116 } | 1153 } |
1117 | 1154 |
1118 int LayoutTable::calcBorderEnd() const { | 1155 int LayoutTable::calcBorderEnd() const { |
1119 if (!collapseBorders()) | 1156 if (!collapseBorders()) |
1120 return LayoutBlock::borderEnd(); | 1157 return LayoutBlock::borderEnd(); |
1121 | 1158 |
1122 // Determined by the last cell of the first row. See the CSS 2.1 spec, section
17.6.2. | 1159 // Determined by the last cell of the first row. See the CSS 2.1 spec, section |
| 1160 // 17.6.2. |
1123 if (!numEffectiveColumns()) | 1161 if (!numEffectiveColumns()) |
1124 return 0; | 1162 return 0; |
1125 | 1163 |
1126 int borderWidth = 0; | 1164 int borderWidth = 0; |
1127 | 1165 |
1128 const BorderValue& tableEndBorder = style()->borderEnd(); | 1166 const BorderValue& tableEndBorder = style()->borderEnd(); |
1129 if (tableEndBorder.style() == BorderStyleHidden) | 1167 if (tableEndBorder.style() == BorderStyleHidden) |
1130 return 0; | 1168 return 0; |
1131 if (tableEndBorder.style() > BorderStyleHidden) | 1169 if (tableEndBorder.style() > BorderStyleHidden) |
1132 borderWidth = tableEndBorder.width(); | 1170 borderWidth = tableEndBorder.width(); |
1133 | 1171 |
1134 unsigned endColumn = numEffectiveColumns() - 1; | 1172 unsigned endColumn = numEffectiveColumns() - 1; |
1135 | 1173 |
1136 // TODO(dgrogan): This logic doesn't properly account for the last column in t
he last column-group case. | 1174 // TODO(dgrogan): This logic doesn't properly account for the last column in |
| 1175 // the last column-group case. |
1137 if (LayoutTableCol* column = | 1176 if (LayoutTableCol* column = |
1138 colElementAtAbsoluteColumn(endColumn).innermostColOrColGroup()) { | 1177 colElementAtAbsoluteColumn(endColumn).innermostColOrColGroup()) { |
1139 // FIXME: We don't account for direction on columns and column groups. | 1178 // FIXME: We don't account for direction on columns and column groups. |
1140 const BorderValue& columnAdjoiningBorder = column->style()->borderEnd(); | 1179 const BorderValue& columnAdjoiningBorder = column->style()->borderEnd(); |
1141 if (columnAdjoiningBorder.style() == BorderStyleHidden) | 1180 if (columnAdjoiningBorder.style() == BorderStyleHidden) |
1142 return 0; | 1181 return 0; |
1143 if (columnAdjoiningBorder.style() > BorderStyleHidden) | 1182 if (columnAdjoiningBorder.style() > BorderStyleHidden) |
1144 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width()); | 1183 borderWidth = std::max(borderWidth, columnAdjoiningBorder.width()); |
1145 } | 1184 } |
1146 | 1185 |
(...skipping 23 matching lines...) Expand all Loading... |
1170 if (endCellAdjoiningBorder.style() > BorderStyleHidden) | 1209 if (endCellAdjoiningBorder.style() > BorderStyleHidden) |
1171 borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width()); | 1210 borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width()); |
1172 if (firstRowAdjoiningBorder.style() > BorderStyleHidden) | 1211 if (firstRowAdjoiningBorder.style() > BorderStyleHidden) |
1173 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width()); | 1212 borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width()); |
1174 } | 1213 } |
1175 } | 1214 } |
1176 return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2; | 1215 return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2; |
1177 } | 1216 } |
1178 | 1217 |
1179 void LayoutTable::recalcBordersInRowDirection() { | 1218 void LayoutTable::recalcBordersInRowDirection() { |
1180 // FIXME: We need to compute the collapsed before / after borders in the same
fashion. | 1219 // FIXME: We need to compute the collapsed before / after borders in the same |
| 1220 // fashion. |
1181 m_borderStart = calcBorderStart(); | 1221 m_borderStart = calcBorderStart(); |
1182 m_borderEnd = calcBorderEnd(); | 1222 m_borderEnd = calcBorderEnd(); |
1183 } | 1223 } |
1184 | 1224 |
1185 int LayoutTable::borderBefore() const { | 1225 int LayoutTable::borderBefore() const { |
1186 if (collapseBorders()) { | 1226 if (collapseBorders()) { |
1187 recalcSectionsIfNeeded(); | 1227 recalcSectionsIfNeeded(); |
1188 return outerBorderBefore(); | 1228 return outerBorderBefore(); |
1189 } | 1229 } |
1190 return LayoutBlock::borderBefore(); | 1230 return LayoutBlock::borderBefore(); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1446 return LayoutBox::baselinePosition(baselineType, firstLine, direction, | 1486 return LayoutBox::baselinePosition(baselineType, firstLine, direction, |
1447 linePositionMode); | 1487 linePositionMode); |
1448 } | 1488 } |
1449 | 1489 |
1450 int LayoutTable::inlineBlockBaseline(LineDirectionMode) const { | 1490 int LayoutTable::inlineBlockBaseline(LineDirectionMode) const { |
1451 // Tables are skipped when computing an inline-block's baseline. | 1491 // Tables are skipped when computing an inline-block's baseline. |
1452 return -1; | 1492 return -1; |
1453 } | 1493 } |
1454 | 1494 |
1455 int LayoutTable::firstLineBoxBaseline() const { | 1495 int LayoutTable::firstLineBoxBaseline() const { |
1456 // The baseline of a 'table' is the same as the 'inline-table' baseline per CS
S 3 Flexbox (CSS 2.1 | 1496 // The baseline of a 'table' is the same as the 'inline-table' baseline per |
1457 // doesn't define the baseline of a 'table' only an 'inline-table'). | 1497 // CSS 3 Flexbox (CSS 2.1 doesn't define the baseline of a 'table' only an |
1458 // This is also needed to properly determine the baseline of a cell if it has
a table child. | 1498 // 'inline-table'). This is also needed to properly determine the baseline of |
| 1499 // a cell if it has a table child. |
1459 | 1500 |
1460 if (isWritingModeRoot()) | 1501 if (isWritingModeRoot()) |
1461 return -1; | 1502 return -1; |
1462 | 1503 |
1463 recalcSectionsIfNeeded(); | 1504 recalcSectionsIfNeeded(); |
1464 | 1505 |
1465 const LayoutTableSection* topNonEmptySection = this->topNonEmptySection(); | 1506 const LayoutTableSection* topNonEmptySection = this->topNonEmptySection(); |
1466 if (!topNonEmptySection) | 1507 if (!topNonEmptySection) |
1467 return -1; | 1508 return -1; |
1468 | 1509 |
1469 int baseline = topNonEmptySection->firstLineBoxBaseline(); | 1510 int baseline = topNonEmptySection->firstLineBoxBaseline(); |
1470 if (baseline >= 0) | 1511 if (baseline >= 0) |
1471 return (topNonEmptySection->logicalTop() + baseline).toInt(); | 1512 return (topNonEmptySection->logicalTop() + baseline).toInt(); |
1472 | 1513 |
1473 // FF, Presto and IE use the top of the section as the baseline if its first r
ow is empty of cells or content. | 1514 // FF, Presto and IE use the top of the section as the baseline if its first |
| 1515 // row is empty of cells or content. |
1474 // The baseline of an empty row isn't specified by CSS 2.1. | 1516 // The baseline of an empty row isn't specified by CSS 2.1. |
1475 if (topNonEmptySection->firstRow() && | 1517 if (topNonEmptySection->firstRow() && |
1476 !topNonEmptySection->firstRow()->firstCell()) | 1518 !topNonEmptySection->firstRow()->firstCell()) |
1477 return topNonEmptySection->logicalTop().toInt(); | 1519 return topNonEmptySection->logicalTop().toInt(); |
1478 | 1520 |
1479 return -1; | 1521 return -1; |
1480 } | 1522 } |
1481 | 1523 |
1482 LayoutRect LayoutTable::overflowClipRect( | 1524 LayoutRect LayoutTable::overflowClipRect( |
1483 const LayoutPoint& location, | 1525 const LayoutPoint& location, |
1484 OverlayScrollbarClipBehavior overlayScrollbarClipBehavior) const { | 1526 OverlayScrollbarClipBehavior overlayScrollbarClipBehavior) const { |
1485 LayoutRect rect = | 1527 LayoutRect rect = |
1486 LayoutBlock::overflowClipRect(location, overlayScrollbarClipBehavior); | 1528 LayoutBlock::overflowClipRect(location, overlayScrollbarClipBehavior); |
1487 | 1529 |
1488 // If we have a caption, expand the clip to include the caption. | 1530 // If we have a caption, expand the clip to include the caption. |
1489 // FIXME: Technically this is wrong, but it's virtually impossible to fix this | 1531 // FIXME: Technically this is wrong, but it's virtually impossible to fix this |
1490 // for real until captions have been re-written. | 1532 // for real until captions have been re-written. |
1491 // FIXME: This code assumes (like all our other caption code) that only top/bo
ttom are | 1533 // FIXME: This code assumes (like all our other caption code) that only |
1492 // supported. When we actually support left/right and stop mapping them to to
p/bottom, | 1534 // top/bottom are supported. When we actually support left/right and stop |
1493 // we might have to hack this code first (depending on what order we do these
bug fixes in). | 1535 // mapping them to top/bottom, we might have to hack this code first |
| 1536 // (depending on what order we do these bug fixes in). |
1494 if (!m_captions.isEmpty()) { | 1537 if (!m_captions.isEmpty()) { |
1495 if (style()->isHorizontalWritingMode()) { | 1538 if (style()->isHorizontalWritingMode()) { |
1496 rect.setHeight(size().height()); | 1539 rect.setHeight(size().height()); |
1497 rect.setY(location.y()); | 1540 rect.setY(location.y()); |
1498 } else { | 1541 } else { |
1499 rect.setWidth(size().width()); | 1542 rect.setWidth(size().width()); |
1500 rect.setX(location.x()); | 1543 rect.setX(location.x()); |
1501 } | 1544 } |
1502 } | 1545 } |
1503 | 1546 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1617 } | 1660 } |
1618 | 1661 |
1619 LayoutUnit LayoutTable::paddingRight() const { | 1662 LayoutUnit LayoutTable::paddingRight() const { |
1620 if (collapseBorders()) | 1663 if (collapseBorders()) |
1621 return LayoutUnit(); | 1664 return LayoutUnit(); |
1622 | 1665 |
1623 return LayoutBlock::paddingRight(); | 1666 return LayoutBlock::paddingRight(); |
1624 } | 1667 } |
1625 | 1668 |
1626 } // namespace blink | 1669 } // namespace blink |
OLD | NEW |