Chromium Code Reviews| Index: third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp |
| diff --git a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp |
| index 47910c1ad54de667a3421a97a92af6158a3d3f0c..9514999942f33bdc9178730ca6983c3b4be52a9e 100644 |
| --- a/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp |
| +++ b/third_party/WebKit/Source/core/paint/BackgroundImageGeometry.cpp |
| @@ -7,6 +7,8 @@ |
| #include "core/frame/FrameView.h" |
| #include "core/layout/LayoutBox.h" |
| #include "core/layout/LayoutBoxModelObject.h" |
| +#include "core/layout/LayoutTableCell.h" |
| +#include "core/layout/LayoutTableCol.h" |
| #include "core/layout/LayoutView.h" |
| #include "core/layout/compositing/CompositedLayerMapping.h" |
| #include "core/paint/PaintLayer.h" |
| @@ -213,13 +215,16 @@ void BackgroundImageGeometry::setRepeatX(const FillLayer& fillLayer, |
| LayoutUnit unsnappedTileWidth, |
| LayoutUnit snappedAvailableWidth, |
| LayoutUnit unsnappedAvailableWidth, |
| - LayoutUnit extraOffset) { |
| + LayoutUnit extraOffset, |
| + LayoutUnit offsetForCell) { |
| // We would like to identify the phase as a fraction of the image size in the |
| // absence of snapping, then re-apply it to the snapped values. This is to |
| // handle large positions. |
| if (unsnappedTileWidth) { |
| - LayoutUnit computedXPosition = roundedMinimumValueForLength( |
| - fillLayer.xPosition(), unsnappedAvailableWidth); |
| + LayoutUnit computedXPosition = |
| + roundedMinimumValueForLength(fillLayer.xPosition(), |
| + unsnappedAvailableWidth) - |
| + offsetForCell; |
| if (fillLayer.backgroundXOrigin() == RightEdge) { |
| float numberOfTilesInPosition = |
| (snappedAvailableWidth - computedXPosition + extraOffset).toFloat() / |
| @@ -247,13 +252,16 @@ void BackgroundImageGeometry::setRepeatY(const FillLayer& fillLayer, |
| LayoutUnit unsnappedTileHeight, |
| LayoutUnit snappedAvailableHeight, |
| LayoutUnit unsnappedAvailableHeight, |
| - LayoutUnit extraOffset) { |
| + LayoutUnit extraOffset, |
| + LayoutUnit offsetForCell) { |
| // We would like to identify the phase as a fraction of the image size in the |
| // absence of snapping, then re-apply it to the snapped values. This is to |
| // handle large positions. |
| if (unsnappedTileHeight) { |
| - LayoutUnit computedYPosition = roundedMinimumValueForLength( |
| - fillLayer.yPosition(), unsnappedAvailableHeight); |
| + LayoutUnit computedYPosition = |
| + roundedMinimumValueForLength(fillLayer.yPosition(), |
| + unsnappedAvailableHeight) - |
| + offsetForCell; |
| if (fillLayer.backgroundYOrigin() == BottomEdge) { |
| float numberOfTilesInPosition = |
| (snappedAvailableHeight - computedYPosition + extraOffset).toFloat() / |
| @@ -313,8 +321,99 @@ void BackgroundImageGeometry::useFixedAttachment( |
| setPhase(LayoutPoint(roundedIntPoint(m_phase))); |
| } |
| +enum ColumnGroupDirection { ColumnGroupStart, ColumnGroupEnd }; |
| + |
| +static void expandToTableColumnGroup(const LayoutTableCell* cell, |
|
Xianzhu
2017/01/15 20:45:58
s/*/&/
|
| + const LayoutTableCol& columnGroup, |
| + LayoutUnit& value, |
| + ColumnGroupDirection columnDirection) { |
| + std::function<LayoutTableCell*(LayoutTableCell*)> siblingCell = |
| + columnDirection == ColumnGroupStart ? &LayoutTableCell::previousCell |
| + : &LayoutTableCell::nextCell; |
|
Xianzhu
2017/01/15 20:45:57
Wdyt using the following:
auto siblingCell = ..
|
| + for (LayoutTableCell* sibling = |
| + siblingCell(const_cast<LayoutTableCell*>(cell)); |
| + sibling; sibling = siblingCell(sibling)) { |
| + if (cell->table() |
| + ->colElementAtAbsoluteColumn(sibling->absoluteColumnIndex()) |
| + .innermostColOrColGroup() |
| + ->enclosingColumnGroup() != columnGroup) |
| + break; |
| + value += sibling->size().width(); |
| + } |
| +} |
| + |
| +LayoutPoint BackgroundImageGeometry::getOffsetForCell( |
| + const LayoutTableCell& cell, |
| + const LayoutBox& positioningBox) { |
| + LayoutSize borderSpacing = LayoutSize(cell.table()->hBorderSpacing(), |
| + cell.table()->vBorderSpacing()); |
| + if (positioningBox.isTableSection()) |
| + return cell.location() - borderSpacing; |
| + if (positioningBox.isTableRow()) { |
| + return LayoutPoint(cell.location().x(), LayoutUnit()) - |
| + LayoutSize(borderSpacing.width(), LayoutUnit()); |
| + } |
| + |
|
Xianzhu
2017/01/15 20:45:58
DCHECK(positioningBox.isLayoutTableCol());
|
| + LayoutRect sectionsRect(LayoutPoint(), cell.table()->size()); |
| + cell.table()->subtractCaptionRect(sectionsRect); |
| + LayoutUnit heightOfCaptions = |
| + cell.table()->size().height() - sectionsRect.height(); |
| + LayoutPoint offsetInBackground = LayoutPoint( |
| + LayoutUnit(), (cell.section()->location().y() - |
| + cell.table()->borderBefore() - heightOfCaptions) + |
| + cell.location().y()); |
| + if (positioningBox.isLayoutTableCol() && |
|
Xianzhu
2017/01/15 20:45:58
Remove 'positioningBox.isLayoutTableCol() &&'.
|
| + toLayoutTableCol(positioningBox).isTableColumn()) { |
| + return offsetInBackground - |
| + LayoutSize(LayoutUnit(), borderSpacing.height()); |
| + } |
| + |
| + DCHECK(positioningBox.isLayoutTableCol() && |
|
Xianzhu
2017/01/15 20:45:57
Remove 'positioningBox.isLayoutTableCol() &&'.
|
| + toLayoutTableCol(positioningBox).isTableColumnGroup()); |
| + LayoutUnit offset = offsetInBackground.x(); |
| + expandToTableColumnGroup(&cell, toLayoutTableCol(positioningBox), offset, |
| + ColumnGroupStart); |
| + offsetInBackground.move(offset, LayoutUnit()); |
| + return offsetInBackground - LayoutSize(LayoutUnit(), borderSpacing.height()); |
| +} |
| + |
| +LayoutSize BackgroundImageGeometry::getPositioningAreaSizeForCell( |
| + const LayoutTableCell& cell, |
| + const LayoutBox& positioningBox) { |
| + LayoutSize borderSpacing = LayoutSize(cell.table()->hBorderSpacing(), |
| + cell.table()->vBorderSpacing()); |
| + if (positioningBox.isTableSection()) |
| + return positioningBox.size() - borderSpacing - borderSpacing; |
| + |
| + if (positioningBox.isTableRow()) { |
| + return positioningBox.size() - |
| + LayoutSize(borderSpacing.width(), LayoutUnit()) - |
| + LayoutSize(borderSpacing.width(), LayoutUnit()); |
| + } |
| + |
|
Xianzhu
2017/01/15 20:45:57
Ditto comments as in getOffsetForCell().
|
| + LayoutRect sectionsRect(LayoutPoint(), cell.table()->size()); |
| + cell.table()->subtractCaptionRect(sectionsRect); |
| + LayoutUnit columnHeight = sectionsRect.height() - |
| + cell.table()->borderBefore() - |
| + borderSpacing.height() - borderSpacing.height(); |
| + if (positioningBox.isLayoutTableCol() && |
| + toLayoutTableCol(positioningBox).isTableColumn()) |
| + return LayoutSize(cell.size().width(), columnHeight); |
| + |
| + DCHECK(positioningBox.isLayoutTableCol() && |
| + toLayoutTableCol(positioningBox).isTableColumnGroup()); |
| + LayoutUnit width = cell.size().width(); |
| + expandToTableColumnGroup(&cell, toLayoutTableCol(positioningBox), width, |
| + ColumnGroupStart); |
| + expandToTableColumnGroup(&cell, toLayoutTableCol(positioningBox), width, |
| + ColumnGroupEnd); |
| + |
| + return LayoutSize(width, columnHeight); |
| +} |
| + |
| void BackgroundImageGeometry::calculate( |
| const LayoutBoxModelObject& obj, |
| + const LayoutObject* backgroundObject, |
| const LayoutBoxModelObject* paintContainer, |
| const GlobalPaintFlags globalPaintFlags, |
| const FillLayer& fillLayer, |
| @@ -332,9 +431,20 @@ void BackgroundImageGeometry::calculate( |
| DCHECK(documentElement->layoutObject()->isBox()); |
| rootBox = toLayoutBox(documentElement->layoutObject()); |
| } |
| - const LayoutBoxModelObject& positioningBox = |
| - isLayoutView ? static_cast<const LayoutBoxModelObject&>(*rootBox) : obj; |
| + bool cellUsingContainerBackground = |
| + obj.isTableCell() && backgroundObject && !backgroundObject->isTableCell(); |
| + const LayoutBoxModelObject& positioningBox = |
| + isLayoutView |
| + ? static_cast<const LayoutBoxModelObject&>(*rootBox) |
|
Xianzhu
2017/01/15 20:45:58
s/static_cast<const LayoutBoxModelObject&>(...)/to
|
| + : cellUsingContainerBackground |
| + ? static_cast<const LayoutBoxModelObject&>(*backgroundObject) |
|
Xianzhu
2017/01/15 20:45:57
Ditto.
|
| + : obj; |
| + LayoutPoint offsetInBackground = |
| + cellUsingContainerBackground |
| + ? getOffsetForCell(toLayoutTableCell(obj), |
| + toLayoutBox(positioningBox)) |
| + : LayoutPoint(); |
| // Determine the background positioning area and set destRect to the |
| // background painting area. destRect will be adjusted later if the |
| // background is non-repeating. |
| @@ -384,7 +494,11 @@ void BackgroundImageGeometry::calculate( |
| top -= paintRect.y(); |
| } else { |
| positioningAreaSize = |
| - paintRect.size() - LayoutSize(left + right, top + bottom); |
| + (cellUsingContainerBackground |
| + ? getPositioningAreaSizeForCell(toLayoutTableCell(obj), |
| + toLayoutBox(positioningBox)) |
| + : paintRect.size()) - |
|
Xianzhu
2017/01/15 20:45:58
I doubt if the name getPositionAreaSizeForCell() i
|
| + LayoutSize(left + right, top + bottom); |
| } |
| } else { |
| setHasNonLocalGeometry(); |
| @@ -430,7 +544,8 @@ void BackgroundImageGeometry::calculate( |
| positioningAreaSize.height() - tileSize().height(); |
| LayoutUnit computedXPosition = |
| - roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth); |
| + roundedMinimumValueForLength(fillLayer.xPosition(), availableWidth) - |
| + offsetInBackground.x(); |
| if (backgroundRepeatX == RoundFill && |
| positioningAreaSize.width() > LayoutUnit() && |
| fillTileSize.width() > LayoutUnit()) { |
| @@ -456,7 +571,8 @@ void BackgroundImageGeometry::calculate( |
| } |
| LayoutUnit computedYPosition = |
| - roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight); |
| + roundedMinimumValueForLength(fillLayer.yPosition(), availableHeight) - |
| + offsetInBackground.y(); |
| if (backgroundRepeatY == RoundFill && |
| positioningAreaSize.height() > LayoutUnit() && |
| fillTileSize.height() > LayoutUnit()) { |
| @@ -482,7 +598,7 @@ void BackgroundImageGeometry::calculate( |
| if (backgroundRepeatX == RepeatFill) { |
| setRepeatX(fillLayer, fillTileSize.width(), availableWidth, |
| - unsnappedAvailableWidth, left); |
| + unsnappedAvailableWidth, left, offsetInBackground.x()); |
| } else if (backgroundRepeatX == SpaceFill && |
| tileSize().width() > LayoutUnit()) { |
| LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.width(), |
| @@ -497,11 +613,13 @@ void BackgroundImageGeometry::calculate( |
| ? availableWidth - computedXPosition |
| : computedXPosition; |
| setNoRepeatX(left + xOffset); |
| + if (offsetInBackground.x() > tileSize().width()) |
| + setDestRect(LayoutRect()); |
| } |
| if (backgroundRepeatY == RepeatFill) { |
| setRepeatY(fillLayer, fillTileSize.height(), availableHeight, |
| - unsnappedAvailableHeight, top); |
| + unsnappedAvailableHeight, top, offsetInBackground.y()); |
| } else if (backgroundRepeatY == SpaceFill && |
| tileSize().height() > LayoutUnit()) { |
| LayoutUnit space = getSpaceBetweenImageTiles(positioningAreaSize.height(), |
| @@ -516,6 +634,8 @@ void BackgroundImageGeometry::calculate( |
| ? availableHeight - computedYPosition |
| : computedYPosition; |
| setNoRepeatY(top + yOffset); |
| + if (offsetInBackground.y() > tileSize().height()) |
| + setDestRect(LayoutRect()); |
| } |
| if (fixedAttachment) |