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..3f64a82508a52d20cc64c595c30e133120451c7e 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,97 @@ void BackgroundImageGeometry::useFixedAttachment( |
setPhase(LayoutPoint(roundedIntPoint(m_phase))); |
} |
+enum ColumnGroupDirection { ColumnGroupStart, ColumnGroupEnd }; |
+ |
+static void expandToTableColumnGroup(const LayoutTableCell& cell, |
+ const LayoutTableCol& columnGroup, |
+ LayoutUnit& value, |
+ ColumnGroupDirection columnDirection) { |
+ auto siblingCell = columnDirection == ColumnGroupStart |
+ ? &LayoutTableCell::previousCell |
+ : &LayoutTableCell::nextCell; |
+ for (const auto* sibling = (cell.*siblingCell)(); sibling; |
+ sibling = (sibling->*siblingCell)()) { |
+ 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()); |
+ } |
+ |
+ 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()); |
+ |
+ DCHECK(positioningBox.isLayoutTableCol()); |
+ if (toLayoutTableCol(positioningBox).isTableColumn()) { |
+ return offsetInBackground - |
+ LayoutSize(LayoutUnit(), borderSpacing.height()); |
+ } |
+ |
+ DCHECK(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::getBackgroundObjectDimensions( |
+ 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()); |
+ } |
+ |
+ DCHECK(positioningBox.isLayoutTableCol()); |
+ LayoutRect sectionsRect(LayoutPoint(), cell.table()->size()); |
+ cell.table()->subtractCaptionRect(sectionsRect); |
+ LayoutUnit columnHeight = sectionsRect.height() - |
+ cell.table()->borderBefore() - |
+ borderSpacing.height() - borderSpacing.height(); |
+ if (toLayoutTableCol(positioningBox).isTableColumn()) |
+ return LayoutSize(cell.size().width(), columnHeight); |
+ |
+ DCHECK(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 +429,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) |
+ : cellUsingContainerBackground |
+ ? static_cast<const LayoutBoxModelObject&>(*backgroundObject) |
+ : obj; |
Xianzhu
2017/01/17 18:21:19
I found why toLayoutBoxModelObject for the first o
|
+ 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 +492,11 @@ void BackgroundImageGeometry::calculate( |
top -= paintRect.y(); |
} else { |
positioningAreaSize = |
- paintRect.size() - LayoutSize(left + right, top + bottom); |
+ (cellUsingContainerBackground |
+ ? getBackgroundObjectDimensions(toLayoutTableCell(obj), |
+ toLayoutBox(positioningBox)) |
+ : paintRect.size()) - |
+ LayoutSize(left + right, top + bottom); |
} |
} else { |
setHasNonLocalGeometry(); |
@@ -430,7 +542,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 +569,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 +596,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 +611,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 +632,8 @@ void BackgroundImageGeometry::calculate( |
? availableHeight - computedYPosition |
: computedYPosition; |
setNoRepeatY(top + yOffset); |
+ if (offsetInBackground.y() > tileSize().height()) |
+ setDestRect(LayoutRect()); |
} |
if (fixedAttachment) |