Index: third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
index 6e8ab3df4c7c88b64be532c30a0da0e428bb1ac9..ef264c495233ec02a464fe49399e6736fbc685c6 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
@@ -412,18 +412,23 @@ PaintResult PaintLayerPainter::paintLayerContents( |
ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
? UncachedClipRects |
: PaintingClipRects; |
+ bool isFixedPositionObjectInPagedMedia = |
+ fragmentPolicy != ForceSingleFragment && |
+ this->isFixedPositionObjectInPagedMedia(); |
// TODO(trchen): We haven't decided how to handle visual fragmentation with |
// SPv2. Related thread |
// https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuWFf-mxM |
if (fragmentPolicy == ForceSingleFragment || |
+ isFixedPositionObjectInPagedMedia || |
RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
m_paintLayer.appendSingleFragmentIgnoringPagination( |
layerFragments, localPaintingInfo.rootLayer, |
localPaintingInfo.paintDirtyRect, cacheSlot, |
IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
localPaintingInfo.subPixelAccumulation); |
- } else if (!collectPaintFragmentsForPaginatedFixedPosition( |
- paintingInfo, layerFragments)) { |
+ if (isFixedPositionObjectInPagedMedia) |
+ repeatFixedPositionObjectInPages(paintingInfo, layerFragments); |
chrishtr
2016/12/30 00:10:50
It's only possible in single-fragment mode?
Xianzhu
2016/12/30 00:52:41
Now isFixedPositionObjectInPageMedia and single-fr
|
+ } else { |
m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
localPaintingInfo.paintDirtyRect, cacheSlot, |
IgnoreOverlayScrollbarSize, |
@@ -586,40 +591,43 @@ bool PaintLayerPainter::atLeastOneFragmentIntersectsDamageRect( |
return false; |
} |
-bool PaintLayerPainter::collectPaintFragmentsForPaginatedFixedPosition( |
- const PaintLayerPaintingInfo& paintingInfo, |
- PaintLayerFragments& layerFragments) { |
+inline bool PaintLayerPainter::isFixedPositionObjectInPagedMedia() { |
LayoutObject* object = m_paintLayer.layoutObject(); |
LayoutView* view = object->view(); |
- bool isFixedPosObjectInPagedMedia = |
- object->style()->position() == FixedPosition && |
- object->container() == view && view->pageLogicalHeight(); |
+ return object->styleRef().position() == FixedPosition && |
+ object->container() == view && view->pageLogicalHeight() && |
+ // TODO(crbug.com/619094): Figure out the correct behaviour for fixed |
+ // position objects in paged media with vertical writing modes. |
+ view->isHorizontalWritingMode(); |
+} |
- // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position |
- // objects in paged media with vertical writing modes. |
- if (!isFixedPosObjectInPagedMedia || !view->isHorizontalWritingMode()) |
- return false; |
+// "For paged media, boxes with fixed positions are repeated on every page." |
+// https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning |
+void PaintLayerPainter::repeatFixedPositionObjectInPages( |
+ const PaintLayerPaintingInfo& paintingInfo, |
+ PaintLayerFragments& layerFragments) { |
+ DCHECK(isFixedPositionObjectInPagedMedia()); |
+ DCHECK_EQ(1u, layerFragments.size()); |
- // "For paged media, boxes with fixed positions are repeated on every page." |
- // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning |
+ LayoutView* view = m_paintLayer.layoutObject()->view(); |
unsigned pages = |
ceilf(view->documentRect().height() / view->pageLogicalHeight()); |
- LayoutPoint paginationOffset; |
// The fixed position object is offset from the top of the page, so remove |
// any scroll offset. |
LayoutPoint offsetFromRoot; |
m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
- paginationOffset -= offsetFromRoot - m_paintLayer.location(); |
- |
- for (unsigned i = 0; i < pages; i++) { |
- PaintLayerFragment fragment; |
- fragment.backgroundRect = paintingInfo.paintDirtyRect; |
- fragment.paginationOffset = paginationOffset; |
+ LayoutSize offsetAdjustment = m_paintLayer.location() - offsetFromRoot; |
+ layerFragments[0].paginationOffset += offsetAdjustment; |
+ layerFragments[0].layerBounds.move(offsetAdjustment); |
+ |
+ LayoutPoint pageOffset(LayoutUnit(), view->pageLogicalHeight()); |
+ for (unsigned i = 1; i < pages; i++) { |
+ PaintLayerFragment fragment = layerFragments[i - 1]; |
chrishtr
2017/01/03 18:25:09
What guarantees that |layerFragments| has exactly
chrishtr
2017/01/03 18:53:10
oh I see now, nm.
|
+ fragment.paginationOffset += pageOffset; |
+ fragment.layerBounds.moveBy(pageOffset); |
chrishtr
2016/12/30 00:10:50
This didn't used to get set in the transformed pat
Xianzhu
2016/12/30 00:52:41
No. layerBounds and foregroundRect of these fragme
chrishtr
2017/01/03 18:25:09
I'm not sure what you mean. layerBounds is used in
chrishtr
2017/01/03 18:53:10
Right ok, now I see.
|
layerFragments.append(fragment); |
- paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight()); |
} |
- return true; |
} |
PaintResult PaintLayerPainter::paintLayerWithTransform( |
@@ -637,48 +645,42 @@ PaintResult PaintLayerPainter::paintLayerWithTransform( |
// its parent. |
PaintLayer* parentLayer = m_paintLayer.parent(); |
- LayoutObject* object = m_paintLayer.layoutObject(); |
- LayoutView* view = object->view(); |
- bool isFixedPosObjectInPagedMedia = |
- object->style()->position() == FixedPosition && |
- object->container() == view && view->pageLogicalHeight(); |
PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); |
PaintLayerFragments layerFragments; |
- if (!collectPaintFragmentsForPaginatedFixedPosition(paintingInfo, |
- layerFragments)) { |
- if (paginationLayer) { |
- // FIXME: This is a mess. Look closely at this code and the code in Layer |
- // and fix any issues in it & refactor to make it obvious from code |
- // structure what it does and that it's correct. |
- ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
- ? UncachedClipRects |
- : PaintingClipRects; |
- ShouldRespectOverflowClipType respectOverflowClip = |
- shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); |
- // Calculate the transformed bounding box in the current coordinate space, |
- // to figure out which fragmentainers (e.g. columns) we need to visit. |
- LayoutRect transformedExtent = PaintLayer::transparencyClipBox( |
- &m_paintLayer, paginationLayer, |
- PaintLayer::PaintingTransparencyClipBox, |
- PaintLayer::RootOfTransparencyClipBox, |
- paintingInfo.subPixelAccumulation, |
- paintingInfo.getGlobalPaintFlags()); |
- // FIXME: we don't check if paginationLayer is within |
- // paintingInfo.rootLayer |
- // here. |
- paginationLayer->collectFragments( |
- layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, |
- cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, |
- paintingInfo.subPixelAccumulation, &transformedExtent); |
- } else { |
- // We don't need to collect any fragments in the regular way here. We have |
- // already calculated a clip rectangle for the ancestry if it was needed, |
- // and clipping this layer is something that can be done further down the |
- // path, when the transform has been applied. |
- PaintLayerFragment fragment; |
- fragment.backgroundRect = paintingInfo.paintDirtyRect; |
- layerFragments.append(fragment); |
- } |
+ bool isFixedPositionObjectInPagedMedia = |
+ this->isFixedPositionObjectInPagedMedia(); |
+ if (!paginationLayer || isFixedPositionObjectInPagedMedia) { |
+ // We don't need to collect any fragments in the regular way here. We have |
+ // already calculated a clip rectangle for the ancestry if it was needed, |
+ // and clipping this layer is something that can be done further down the |
+ // path, when the transform has been applied. |
+ PaintLayerFragment fragment; |
+ fragment.backgroundRect = paintingInfo.paintDirtyRect; |
+ layerFragments.append(fragment); |
+ if (isFixedPositionObjectInPagedMedia) |
+ repeatFixedPositionObjectInPages(paintingInfo, layerFragments); |
+ } else { |
+ // FIXME: This is a mess. Look closely at this code and the code in Layer |
+ // and fix any issues in it & refactor to make it obvious from code |
+ // structure what it does and that it's correct. |
+ ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
+ ? UncachedClipRects |
+ : PaintingClipRects; |
+ ShouldRespectOverflowClipType respectOverflowClip = |
+ shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); |
+ // Calculate the transformed bounding box in the current coordinate space, |
+ // to figure out which fragmentainers (e.g. columns) we need to visit. |
+ LayoutRect transformedExtent = PaintLayer::transparencyClipBox( |
+ &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox, |
+ PaintLayer::RootOfTransparencyClipBox, |
+ paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags()); |
+ // FIXME: we don't check if paginationLayer is within |
+ // paintingInfo.rootLayer |
+ // here. |
+ paginationLayer->collectFragments( |
+ layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, |
+ cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, |
+ paintingInfo.subPixelAccumulation, &transformedExtent); |
} |
Optional<DisplayItemCacheSkipper> cacheSkipper; |
@@ -707,9 +709,9 @@ PaintResult PaintLayerPainter::paintLayerWithTransform( |
Optional<LayerClipRecorder> clipRecorder; |
if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
ClipRect clipRectForFragment(ancestorBackgroundClipRect); |
- // A fixed-position object is repeated on every page, but if it is clipped |
- // by an ancestor layer then the repetitions are clipped out. |
- if (!isFixedPosObjectInPagedMedia) |
+ // A fixed-position object is repeated on every page instead of paginated, |
+ // so we should apply the original ancestor clip rect. |
+ if (!isFixedPositionObjectInPagedMedia) |
clipRectForFragment.moveBy(fragment.paginationOffset); |
clipRectForFragment.intersect(fragment.backgroundRect); |
if (clipRectForFragment.isEmpty()) |