Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/paint/PaintLayerPainter.h" | 5 #include "core/paint/PaintLayerPainter.h" |
| 6 | 6 |
| 7 #include "core/frame/LocalFrame.h" | 7 #include "core/frame/LocalFrame.h" |
| 8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
| 9 #include "core/paint/ClipPathClipper.h" | 9 #include "core/paint/ClipPathClipper.h" |
| 10 #include "core/paint/FilterPainter.h" | 10 #include "core/paint/FilterPainter.h" |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 isSelfPaintingLayer && !isPaintingOverlayScrollbars; | 405 isSelfPaintingLayer && !isPaintingOverlayScrollbars; |
| 406 | 406 |
| 407 PaintLayerFragments layerFragments; | 407 PaintLayerFragments layerFragments; |
| 408 if (shouldPaintContent || shouldPaintSelfOutline || | 408 if (shouldPaintContent || shouldPaintSelfOutline || |
| 409 isPaintingOverlayScrollbars) { | 409 isPaintingOverlayScrollbars) { |
| 410 // Collect the fragments. This will compute the clip rectangles and paint | 410 // Collect the fragments. This will compute the clip rectangles and paint |
| 411 // offsets for each layer fragment. | 411 // offsets for each layer fragment. |
| 412 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) | 412 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
| 413 ? UncachedClipRects | 413 ? UncachedClipRects |
| 414 : PaintingClipRects; | 414 : PaintingClipRects; |
| 415 bool isFixedPositionObjectInPagedMedia = | |
| 416 fragmentPolicy != ForceSingleFragment && | |
| 417 this->isFixedPositionObjectInPagedMedia(); | |
| 415 // TODO(trchen): We haven't decided how to handle visual fragmentation with | 418 // TODO(trchen): We haven't decided how to handle visual fragmentation with |
| 416 // SPv2. Related thread | 419 // SPv2. Related thread |
| 417 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM | 420 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM |
| 418 if (fragmentPolicy == ForceSingleFragment || | 421 if (fragmentPolicy == ForceSingleFragment || |
| 422 isFixedPositionObjectInPagedMedia || | |
| 419 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 423 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 420 m_paintLayer.appendSingleFragmentIgnoringPagination( | 424 m_paintLayer.appendSingleFragmentIgnoringPagination( |
| 421 layerFragments, localPaintingInfo.rootLayer, | 425 layerFragments, localPaintingInfo.rootLayer, |
| 422 localPaintingInfo.paintDirtyRect, cacheSlot, | 426 localPaintingInfo.paintDirtyRect, cacheSlot, |
| 423 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, | 427 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
| 424 localPaintingInfo.subPixelAccumulation); | 428 localPaintingInfo.subPixelAccumulation); |
| 425 } else if (!collectPaintFragmentsForPaginatedFixedPosition( | 429 if (isFixedPositionObjectInPagedMedia) |
| 426 paintingInfo, layerFragments)) { | 430 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
| |
| 431 } else { | |
| 427 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, | 432 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
| 428 localPaintingInfo.paintDirtyRect, cacheSlot, | 433 localPaintingInfo.paintDirtyRect, cacheSlot, |
| 429 IgnoreOverlayScrollbarSize, | 434 IgnoreOverlayScrollbarSize, |
| 430 respectOverflowClip, &offsetFromRoot, | 435 respectOverflowClip, &offsetFromRoot, |
| 431 localPaintingInfo.subPixelAccumulation); | 436 localPaintingInfo.subPixelAccumulation); |
| 432 } | 437 } |
| 433 | 438 |
| 434 if (shouldPaintContent) { | 439 if (shouldPaintContent) { |
| 435 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar | 440 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar |
| 436 // optimization for slimming paint v2. | 441 // optimization for slimming paint v2. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 // fragment.layerBounds is set to the border box, not the bounding box, of | 584 // fragment.layerBounds is set to the border box, not the bounding box, of |
| 580 // the layer. | 585 // the layer. |
| 581 if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, | 586 if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, |
| 582 fragment.backgroundRect.rect(), | 587 fragment.backgroundRect.rect(), |
| 583 newOffsetFromRoot)) | 588 newOffsetFromRoot)) |
| 584 return true; | 589 return true; |
| 585 } | 590 } |
| 586 return false; | 591 return false; |
| 587 } | 592 } |
| 588 | 593 |
| 589 bool PaintLayerPainter::collectPaintFragmentsForPaginatedFixedPosition( | 594 inline bool PaintLayerPainter::isFixedPositionObjectInPagedMedia() { |
| 595 LayoutObject* object = m_paintLayer.layoutObject(); | |
| 596 LayoutView* view = object->view(); | |
| 597 return object->styleRef().position() == FixedPosition && | |
| 598 object->container() == view && view->pageLogicalHeight() && | |
| 599 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed | |
| 600 // position objects in paged media with vertical writing modes. | |
| 601 view->isHorizontalWritingMode(); | |
| 602 } | |
| 603 | |
| 604 // "For paged media, boxes with fixed positions are repeated on every page." | |
| 605 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning | |
| 606 void PaintLayerPainter::repeatFixedPositionObjectInPages( | |
| 590 const PaintLayerPaintingInfo& paintingInfo, | 607 const PaintLayerPaintingInfo& paintingInfo, |
| 591 PaintLayerFragments& layerFragments) { | 608 PaintLayerFragments& layerFragments) { |
| 592 LayoutObject* object = m_paintLayer.layoutObject(); | 609 DCHECK(isFixedPositionObjectInPagedMedia()); |
| 593 LayoutView* view = object->view(); | 610 DCHECK_EQ(1u, layerFragments.size()); |
| 594 bool isFixedPosObjectInPagedMedia = | |
| 595 object->style()->position() == FixedPosition && | |
| 596 object->container() == view && view->pageLogicalHeight(); | |
| 597 | 611 |
| 598 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position | 612 LayoutView* view = m_paintLayer.layoutObject()->view(); |
| 599 // objects in paged media with vertical writing modes. | |
| 600 if (!isFixedPosObjectInPagedMedia || !view->isHorizontalWritingMode()) | |
| 601 return false; | |
| 602 | |
| 603 // "For paged media, boxes with fixed positions are repeated on every page." | |
| 604 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning | |
| 605 unsigned pages = | 613 unsigned pages = |
| 606 ceilf(view->documentRect().height() / view->pageLogicalHeight()); | 614 ceilf(view->documentRect().height() / view->pageLogicalHeight()); |
| 607 LayoutPoint paginationOffset; | |
| 608 | 615 |
| 609 // The fixed position object is offset from the top of the page, so remove | 616 // The fixed position object is offset from the top of the page, so remove |
| 610 // any scroll offset. | 617 // any scroll offset. |
| 611 LayoutPoint offsetFromRoot; | 618 LayoutPoint offsetFromRoot; |
| 612 m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); | 619 m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
| 613 paginationOffset -= offsetFromRoot - m_paintLayer.location(); | 620 LayoutSize offsetAdjustment = m_paintLayer.location() - offsetFromRoot; |
| 621 layerFragments[0].paginationOffset += offsetAdjustment; | |
| 622 layerFragments[0].layerBounds.move(offsetAdjustment); | |
| 614 | 623 |
| 615 for (unsigned i = 0; i < pages; i++) { | 624 LayoutPoint pageOffset(LayoutUnit(), view->pageLogicalHeight()); |
| 616 PaintLayerFragment fragment; | 625 for (unsigned i = 1; i < pages; i++) { |
| 617 fragment.backgroundRect = paintingInfo.paintDirtyRect; | 626 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.
| |
| 618 fragment.paginationOffset = paginationOffset; | 627 fragment.paginationOffset += pageOffset; |
| 628 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.
| |
| 619 layerFragments.append(fragment); | 629 layerFragments.append(fragment); |
| 620 paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight()); | |
| 621 } | 630 } |
| 622 return true; | |
| 623 } | 631 } |
| 624 | 632 |
| 625 PaintResult PaintLayerPainter::paintLayerWithTransform( | 633 PaintResult PaintLayerPainter::paintLayerWithTransform( |
| 626 GraphicsContext& context, | 634 GraphicsContext& context, |
| 627 const PaintLayerPaintingInfo& paintingInfo, | 635 const PaintLayerPaintingInfo& paintingInfo, |
| 628 PaintLayerFlags paintFlags) { | 636 PaintLayerFlags paintFlags) { |
| 629 TransformationMatrix layerTransform = | 637 TransformationMatrix layerTransform = |
| 630 m_paintLayer.renderableTransform(paintingInfo.getGlobalPaintFlags()); | 638 m_paintLayer.renderableTransform(paintingInfo.getGlobalPaintFlags()); |
| 631 // If the transform can't be inverted, then don't paint anything. | 639 // If the transform can't be inverted, then don't paint anything. |
| 632 if (!layerTransform.isInvertible()) | 640 if (!layerTransform.isInvertible()) |
| 633 return FullyPainted; | 641 return FullyPainted; |
| 634 | 642 |
| 635 // FIXME: We should make sure that we don't walk past paintingInfo.rootLayer | 643 // FIXME: We should make sure that we don't walk past paintingInfo.rootLayer |
| 636 // here. m_paintLayer may be the "root", and then we should avoid looking at | 644 // here. m_paintLayer may be the "root", and then we should avoid looking at |
| 637 // its parent. | 645 // its parent. |
| 638 PaintLayer* parentLayer = m_paintLayer.parent(); | 646 PaintLayer* parentLayer = m_paintLayer.parent(); |
| 639 | 647 |
| 640 LayoutObject* object = m_paintLayer.layoutObject(); | |
| 641 LayoutView* view = object->view(); | |
| 642 bool isFixedPosObjectInPagedMedia = | |
| 643 object->style()->position() == FixedPosition && | |
| 644 object->container() == view && view->pageLogicalHeight(); | |
| 645 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); | 648 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); |
| 646 PaintLayerFragments layerFragments; | 649 PaintLayerFragments layerFragments; |
| 647 if (!collectPaintFragmentsForPaginatedFixedPosition(paintingInfo, | 650 bool isFixedPositionObjectInPagedMedia = |
| 648 layerFragments)) { | 651 this->isFixedPositionObjectInPagedMedia(); |
| 649 if (paginationLayer) { | 652 if (!paginationLayer || isFixedPositionObjectInPagedMedia) { |
| 650 // FIXME: This is a mess. Look closely at this code and the code in Layer | 653 // We don't need to collect any fragments in the regular way here. We have |
| 651 // and fix any issues in it & refactor to make it obvious from code | 654 // already calculated a clip rectangle for the ancestry if it was needed, |
| 652 // structure what it does and that it's correct. | 655 // and clipping this layer is something that can be done further down the |
| 653 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) | 656 // path, when the transform has been applied. |
| 654 ? UncachedClipRects | 657 PaintLayerFragment fragment; |
| 655 : PaintingClipRects; | 658 fragment.backgroundRect = paintingInfo.paintDirtyRect; |
| 656 ShouldRespectOverflowClipType respectOverflowClip = | 659 layerFragments.append(fragment); |
| 657 shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); | 660 if (isFixedPositionObjectInPagedMedia) |
| 658 // Calculate the transformed bounding box in the current coordinate space, | 661 repeatFixedPositionObjectInPages(paintingInfo, layerFragments); |
| 659 // to figure out which fragmentainers (e.g. columns) we need to visit. | 662 } else { |
| 660 LayoutRect transformedExtent = PaintLayer::transparencyClipBox( | 663 // FIXME: This is a mess. Look closely at this code and the code in Layer |
| 661 &m_paintLayer, paginationLayer, | 664 // and fix any issues in it & refactor to make it obvious from code |
| 662 PaintLayer::PaintingTransparencyClipBox, | 665 // structure what it does and that it's correct. |
| 663 PaintLayer::RootOfTransparencyClipBox, | 666 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
| 664 paintingInfo.subPixelAccumulation, | 667 ? UncachedClipRects |
| 665 paintingInfo.getGlobalPaintFlags()); | 668 : PaintingClipRects; |
| 666 // FIXME: we don't check if paginationLayer is within | 669 ShouldRespectOverflowClipType respectOverflowClip = |
| 667 // paintingInfo.rootLayer | 670 shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); |
| 668 // here. | 671 // Calculate the transformed bounding box in the current coordinate space, |
| 669 paginationLayer->collectFragments( | 672 // to figure out which fragmentainers (e.g. columns) we need to visit. |
| 670 layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, | 673 LayoutRect transformedExtent = PaintLayer::transparencyClipBox( |
| 671 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, | 674 &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox, |
| 672 paintingInfo.subPixelAccumulation, &transformedExtent); | 675 PaintLayer::RootOfTransparencyClipBox, |
| 673 } else { | 676 paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags()); |
| 674 // We don't need to collect any fragments in the regular way here. We have | 677 // FIXME: we don't check if paginationLayer is within |
| 675 // already calculated a clip rectangle for the ancestry if it was needed, | 678 // paintingInfo.rootLayer |
| 676 // and clipping this layer is something that can be done further down the | 679 // here. |
| 677 // path, when the transform has been applied. | 680 paginationLayer->collectFragments( |
| 678 PaintLayerFragment fragment; | 681 layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, |
| 679 fragment.backgroundRect = paintingInfo.paintDirtyRect; | 682 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, |
| 680 layerFragments.append(fragment); | 683 paintingInfo.subPixelAccumulation, &transformedExtent); |
| 681 } | |
| 682 } | 684 } |
| 683 | 685 |
| 684 Optional<DisplayItemCacheSkipper> cacheSkipper; | 686 Optional<DisplayItemCacheSkipper> cacheSkipper; |
| 685 if (layerFragments.size() > 1) | 687 if (layerFragments.size() > 1) |
| 686 cacheSkipper.emplace(context); | 688 cacheSkipper.emplace(context); |
| 687 | 689 |
| 688 ClipRect ancestorBackgroundClipRect; | 690 ClipRect ancestorBackgroundClipRect; |
| 689 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 691 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 690 if (parentLayer) { | 692 if (parentLayer) { |
| 691 // Calculate the clip rectangle that the ancestors establish. | 693 // Calculate the clip rectangle that the ancestors establish. |
| 692 ClipRectsContext clipRectsContext( | 694 ClipRectsContext clipRectsContext( |
| 693 paintingInfo.rootLayer, | 695 paintingInfo.rootLayer, |
| 694 (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects | 696 (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects |
| 695 : PaintingClipRects, | 697 : PaintingClipRects, |
| 696 IgnoreOverlayScrollbarSize); | 698 IgnoreOverlayScrollbarSize); |
| 697 if (shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()) == | 699 if (shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()) == |
| 698 IgnoreOverflowClip) | 700 IgnoreOverflowClip) |
| 699 clipRectsContext.setIgnoreOverflowClip(); | 701 clipRectsContext.setIgnoreOverflowClip(); |
| 700 ancestorBackgroundClipRect = | 702 ancestorBackgroundClipRect = |
| 701 m_paintLayer.clipper().backgroundClipRect(clipRectsContext); | 703 m_paintLayer.clipper().backgroundClipRect(clipRectsContext); |
| 702 } | 704 } |
| 703 } | 705 } |
| 704 | 706 |
| 705 PaintResult result = FullyPainted; | 707 PaintResult result = FullyPainted; |
| 706 for (const auto& fragment : layerFragments) { | 708 for (const auto& fragment : layerFragments) { |
| 707 Optional<LayerClipRecorder> clipRecorder; | 709 Optional<LayerClipRecorder> clipRecorder; |
| 708 if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 710 if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 709 ClipRect clipRectForFragment(ancestorBackgroundClipRect); | 711 ClipRect clipRectForFragment(ancestorBackgroundClipRect); |
| 710 // A fixed-position object is repeated on every page, but if it is clipped | 712 // A fixed-position object is repeated on every page instead of paginated, |
| 711 // by an ancestor layer then the repetitions are clipped out. | 713 // so we should apply the original ancestor clip rect. |
| 712 if (!isFixedPosObjectInPagedMedia) | 714 if (!isFixedPositionObjectInPagedMedia) |
| 713 clipRectForFragment.moveBy(fragment.paginationOffset); | 715 clipRectForFragment.moveBy(fragment.paginationOffset); |
| 714 clipRectForFragment.intersect(fragment.backgroundRect); | 716 clipRectForFragment.intersect(fragment.backgroundRect); |
| 715 if (clipRectForFragment.isEmpty()) | 717 if (clipRectForFragment.isEmpty()) |
| 716 continue; | 718 continue; |
| 717 if (needsToClip(paintingInfo, clipRectForFragment)) { | 719 if (needsToClip(paintingInfo, clipRectForFragment)) { |
| 718 clipRecorder.emplace(context, *parentLayer->layoutObject(), | 720 clipRecorder.emplace(context, *parentLayer->layoutObject(), |
| 719 DisplayItem::kClipLayerParent, clipRectForFragment, | 721 DisplayItem::kClipLayerParent, clipRectForFragment, |
| 720 &paintingInfo, fragment.paginationOffset, | 722 &paintingInfo, fragment.paginationOffset, |
| 721 paintFlags); | 723 paintFlags); |
| 722 } | 724 } |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 | 1121 |
| 1120 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, | 1122 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, |
| 1121 LayoutRect(enclosingIntRect(damageRect)), | 1123 LayoutRect(enclosingIntRect(damageRect)), |
| 1122 paintFlags, LayoutSize()); | 1124 paintFlags, LayoutSize()); |
| 1123 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); | 1125 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); |
| 1124 | 1126 |
| 1125 m_paintLayer.setContainsDirtyOverlayScrollbars(false); | 1127 m_paintLayer.setContainsDirtyOverlayScrollbars(false); |
| 1126 } | 1128 } |
| 1127 | 1129 |
| 1128 } // namespace blink | 1130 } // namespace blink |
| OLD | NEW |