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 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 isPaintingOverlayScrollbars) { | 414 isPaintingOverlayScrollbars) { |
415 // Collect the fragments. This will compute the clip rectangles and paint | 415 // Collect the fragments. This will compute the clip rectangles and paint |
416 // offsets for each layer fragment. | 416 // offsets for each layer fragment. |
417 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) | 417 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
418 ? UncachedClipRects | 418 ? UncachedClipRects |
419 : PaintingClipRects; | 419 : PaintingClipRects; |
420 // TODO(trchen): We haven't decided how to handle visual fragmentation with | 420 // TODO(trchen): We haven't decided how to handle visual fragmentation with |
421 // SPv2. Related thread | 421 // SPv2. Related thread |
422 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM | 422 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM |
423 if (fragmentPolicy == ForceSingleFragment || | 423 if (fragmentPolicy == ForceSingleFragment || |
424 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 424 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
425 m_paintLayer.appendSingleFragmentIgnoringPagination( | 425 m_paintLayer.appendSingleFragmentIgnoringPagination( |
426 layerFragments, localPaintingInfo.rootLayer, | 426 layerFragments, localPaintingInfo.rootLayer, |
427 localPaintingInfo.paintDirtyRect, cacheSlot, | 427 localPaintingInfo.paintDirtyRect, cacheSlot, |
428 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, | 428 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
429 localPaintingInfo.subPixelAccumulation); | 429 localPaintingInfo.subPixelAccumulation); |
430 else | 430 } else if (!collectPaintFragmentsForPaginatedFixedPosition( |
chrishtr
2016/12/28 21:52:22
This code is new.
| |
431 paintingInfo, layerFragments)) { | |
431 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, | 432 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
432 localPaintingInfo.paintDirtyRect, cacheSlot, | 433 localPaintingInfo.paintDirtyRect, cacheSlot, |
433 IgnoreOverlayScrollbarSize, | 434 IgnoreOverlayScrollbarSize, |
434 respectOverflowClip, &offsetFromRoot, | 435 respectOverflowClip, &offsetFromRoot, |
435 localPaintingInfo.subPixelAccumulation); | 436 localPaintingInfo.subPixelAccumulation); |
437 } | |
436 | 438 |
437 if (shouldPaintContent) { | 439 if (shouldPaintContent) { |
438 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar | 440 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar |
439 // optimization for slimming paint v2. | 441 // optimization for slimming paint v2. |
440 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( | 442 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( |
441 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); | 443 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); |
442 if (!shouldPaintContent) | 444 if (!shouldPaintContent) |
443 result = MayBeClippedByPaintDirtyRect; | 445 result = MayBeClippedByPaintDirtyRect; |
444 } | 446 } |
445 } | 447 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 // 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 |
583 // the layer. | 585 // the layer. |
584 if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, | 586 if (m_paintLayer.intersectsDamageRect(fragment.layerBounds, |
585 fragment.backgroundRect.rect(), | 587 fragment.backgroundRect.rect(), |
586 newOffsetFromRoot)) | 588 newOffsetFromRoot)) |
587 return true; | 589 return true; |
588 } | 590 } |
589 return false; | 591 return false; |
590 } | 592 } |
591 | 593 |
594 bool PaintLayerPainter::collectPaintFragmentsForPaginatedFixedPosition( | |
595 const PaintLayerPaintingInfo& paintingInfo, | |
596 PaintLayerFragments& layerFragments) { | |
597 LayoutObject* object = m_paintLayer.layoutObject(); | |
598 LayoutView* view = object->view(); | |
599 bool isFixedPosObjectInPagedMedia = | |
600 object->style()->position() == FixedPosition && | |
601 object->container() == view && view->pageLogicalHeight(); | |
602 | |
603 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position | |
604 // objects in paged media with vertical writing modes. | |
605 if (!isFixedPosObjectInPagedMedia || !view->isHorizontalWritingMode()) | |
606 return false; | |
607 LOG(ERROR) << "wtf"; | |
Xianzhu
2016/12/28 22:19:46
Remove.
chrishtr
2016/12/28 22:27:38
Oops, sorry. Removed.
| |
608 // "For paged media, boxes with fixed positions are repeated on every page." | |
609 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning | |
610 unsigned pages = | |
611 ceilf(view->documentRect().height() / view->pageLogicalHeight()); | |
612 LayoutPoint paginationOffset; | |
613 | |
614 // The fixed position object is offset from the top of the page, so remove | |
615 // any scroll offset. | |
616 LayoutPoint offsetFromRoot; | |
617 m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); | |
618 paginationOffset -= offsetFromRoot - m_paintLayer.location(); | |
619 | |
620 for (unsigned i = 0; i < pages; i++) { | |
621 PaintLayerFragment fragment; | |
622 fragment.backgroundRect = paintingInfo.paintDirtyRect; | |
623 fragment.paginationOffset = paginationOffset; | |
624 layerFragments.append(fragment); | |
625 paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight()); | |
626 } | |
627 return true; | |
628 } | |
629 | |
592 PaintResult PaintLayerPainter::paintLayerWithTransform( | 630 PaintResult PaintLayerPainter::paintLayerWithTransform( |
593 GraphicsContext& context, | 631 GraphicsContext& context, |
594 const PaintLayerPaintingInfo& paintingInfo, | 632 const PaintLayerPaintingInfo& paintingInfo, |
595 PaintLayerFlags paintFlags) { | 633 PaintLayerFlags paintFlags) { |
596 TransformationMatrix layerTransform = | 634 TransformationMatrix layerTransform = |
597 m_paintLayer.renderableTransform(paintingInfo.getGlobalPaintFlags()); | 635 m_paintLayer.renderableTransform(paintingInfo.getGlobalPaintFlags()); |
598 // If the transform can't be inverted, then don't paint anything. | 636 // If the transform can't be inverted, then don't paint anything. |
599 if (!layerTransform.isInvertible()) | 637 if (!layerTransform.isInvertible()) |
600 return FullyPainted; | 638 return FullyPainted; |
601 | 639 |
602 // FIXME: We should make sure that we don't walk past paintingInfo.rootLayer | 640 // FIXME: We should make sure that we don't walk past paintingInfo.rootLayer |
603 // here. m_paintLayer may be the "root", and then we should avoid looking at | 641 // here. m_paintLayer may be the "root", and then we should avoid looking at |
604 // its parent. | 642 // its parent. |
605 PaintLayer* parentLayer = m_paintLayer.parent(); | 643 PaintLayer* parentLayer = m_paintLayer.parent(); |
606 | 644 |
607 LayoutObject* object = m_paintLayer.layoutObject(); | 645 LayoutObject* object = m_paintLayer.layoutObject(); |
608 LayoutView* view = object->view(); | 646 LayoutView* view = object->view(); |
609 bool isFixedPosObjectInPagedMedia = | 647 bool isFixedPosObjectInPagedMedia = |
610 object->style()->position() == FixedPosition && | 648 object->style()->position() == FixedPosition && |
611 object->container() == view && view->pageLogicalHeight(); | 649 object->container() == view && view->pageLogicalHeight(); |
612 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); | 650 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); |
613 PaintLayerFragments fragments; | 651 PaintLayerFragments layerFragments; |
614 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position | 652 if (!collectPaintFragmentsForPaginatedFixedPosition(paintingInfo, |
615 // objects in paged media with vertical writing modes. | 653 layerFragments)) { |
616 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) { | 654 if (paginationLayer) { |
617 // "For paged media, boxes with fixed positions are repeated on every page." | 655 // FIXME: This is a mess. Look closely at this code and the code in Layer |
618 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng | 656 // and fix any issues in it & refactor to make it obvious from code |
619 unsigned pages = | 657 // structure what it does and that it's correct. |
620 ceilf(view->documentRect().height() / view->pageLogicalHeight()); | 658 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
621 LayoutPoint paginationOffset; | 659 ? UncachedClipRects |
622 | 660 : PaintingClipRects; |
623 // The fixed position object is offset from the top of the page, so remove | 661 ShouldRespectOverflowClipType respectOverflowClip = |
624 // any scroll offset. | 662 shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); |
625 LayoutPoint offsetFromRoot; | 663 // Calculate the transformed bounding box in the current coordinate space, |
626 m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); | 664 // to figure out which fragmentainers (e.g. columns) we need to visit. |
627 paginationOffset -= offsetFromRoot - m_paintLayer.location(); | 665 LayoutRect transformedExtent = PaintLayer::transparencyClipBox( |
628 | 666 &m_paintLayer, paginationLayer, |
629 for (unsigned i = 0; i < pages; i++) { | 667 PaintLayer::PaintingTransparencyClipBox, |
668 PaintLayer::RootOfTransparencyClipBox, | |
669 paintingInfo.subPixelAccumulation, | |
670 paintingInfo.getGlobalPaintFlags()); | |
671 // FIXME: we don't check if paginationLayer is within | |
672 // paintingInfo.rootLayer | |
673 // here. | |
674 paginationLayer->collectFragments( | |
675 layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, | |
676 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, | |
677 paintingInfo.subPixelAccumulation, &transformedExtent); | |
678 } else { | |
679 // We don't need to collect any fragments in the regular way here. We have | |
680 // already calculated a clip rectangle for the ancestry if it was needed, | |
681 // and clipping this layer is something that can be done further down the | |
682 // path, when the transform has been applied. | |
630 PaintLayerFragment fragment; | 683 PaintLayerFragment fragment; |
631 fragment.backgroundRect = paintingInfo.paintDirtyRect; | 684 fragment.backgroundRect = paintingInfo.paintDirtyRect; |
632 fragment.paginationOffset = paginationOffset; | 685 layerFragments.append(fragment); |
633 fragments.append(fragment); | |
634 paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight()); | |
635 } | 686 } |
636 } else if (paginationLayer) { | |
637 // FIXME: This is a mess. Look closely at this code and the code in Layer | |
638 // and fix any issues in it & refactor to make it obvious from code | |
639 // structure what it does and that it's correct. | |
640 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) | |
641 ? UncachedClipRects | |
642 : PaintingClipRects; | |
643 ShouldRespectOverflowClipType respectOverflowClip = | |
644 shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); | |
645 // Calculate the transformed bounding box in the current coordinate space, | |
646 // to figure out which fragmentainers (e.g. columns) we need to visit. | |
647 LayoutRect transformedExtent = PaintLayer::transparencyClipBox( | |
648 &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox, | |
649 PaintLayer::RootOfTransparencyClipBox, | |
650 paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags()); | |
651 // FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer | |
652 // here. | |
653 paginationLayer->collectFragments( | |
654 fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, | |
655 cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, | |
656 paintingInfo.subPixelAccumulation, &transformedExtent); | |
657 } else { | |
658 // We don't need to collect any fragments in the regular way here. We have | |
659 // already calculated a clip rectangle for the ancestry if it was needed, | |
660 // and clipping this layer is something that can be done further down the | |
661 // path, when the transform has been applied. | |
662 PaintLayerFragment fragment; | |
663 fragment.backgroundRect = paintingInfo.paintDirtyRect; | |
664 fragments.append(fragment); | |
665 } | 687 } |
666 | 688 |
667 Optional<DisplayItemCacheSkipper> cacheSkipper; | 689 Optional<DisplayItemCacheSkipper> cacheSkipper; |
668 if (fragments.size() > 1) | 690 if (layerFragments.size() > 1) |
669 cacheSkipper.emplace(context); | 691 cacheSkipper.emplace(context); |
670 | 692 |
671 ClipRect ancestorBackgroundClipRect; | 693 ClipRect ancestorBackgroundClipRect; |
672 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 694 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
673 if (parentLayer) { | 695 if (parentLayer) { |
674 // Calculate the clip rectangle that the ancestors establish. | 696 // Calculate the clip rectangle that the ancestors establish. |
675 ClipRectsContext clipRectsContext( | 697 ClipRectsContext clipRectsContext( |
676 paintingInfo.rootLayer, | 698 paintingInfo.rootLayer, |
677 (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects | 699 (paintFlags & PaintLayerUncachedClipRects) ? UncachedClipRects |
678 : PaintingClipRects, | 700 : PaintingClipRects, |
679 IgnoreOverlayScrollbarSize); | 701 IgnoreOverlayScrollbarSize); |
680 if (shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()) == | 702 if (shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()) == |
681 IgnoreOverflowClip) | 703 IgnoreOverflowClip) |
682 clipRectsContext.setIgnoreOverflowClip(); | 704 clipRectsContext.setIgnoreOverflowClip(); |
683 ancestorBackgroundClipRect = | 705 ancestorBackgroundClipRect = |
684 m_paintLayer.clipper().backgroundClipRect(clipRectsContext); | 706 m_paintLayer.clipper().backgroundClipRect(clipRectsContext); |
685 } | 707 } |
686 } | 708 } |
687 | 709 |
688 PaintResult result = FullyPainted; | 710 PaintResult result = FullyPainted; |
689 for (const auto& fragment : fragments) { | 711 for (const auto& fragment : layerFragments) { |
690 Optional<LayerClipRecorder> clipRecorder; | 712 Optional<LayerClipRecorder> clipRecorder; |
691 if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 713 if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
692 ClipRect clipRectForFragment(ancestorBackgroundClipRect); | 714 ClipRect clipRectForFragment(ancestorBackgroundClipRect); |
693 // A fixed-position object is repeated on every page, but if it is clipped | 715 // A fixed-position object is repeated on every page, but if it is clipped |
694 // by an ancestor layer then the repetitions are clipped out. | 716 // by an ancestor layer then the repetitions are clipped out. |
695 if (!isFixedPosObjectInPagedMedia) | 717 if (!isFixedPosObjectInPagedMedia) |
696 clipRectForFragment.moveBy(fragment.paginationOffset); | 718 clipRectForFragment.moveBy(fragment.paginationOffset); |
697 clipRectForFragment.intersect(fragment.backgroundRect); | 719 clipRectForFragment.intersect(fragment.backgroundRect); |
698 if (clipRectForFragment.isEmpty()) | 720 if (clipRectForFragment.isEmpty()) |
699 continue; | 721 continue; |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1109 | 1131 |
1110 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, | 1132 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, |
1111 LayoutRect(enclosingIntRect(damageRect)), | 1133 LayoutRect(enclosingIntRect(damageRect)), |
1112 paintFlags, LayoutSize()); | 1134 paintFlags, LayoutSize()); |
1113 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); | 1135 paint(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); |
1114 | 1136 |
1115 m_paintLayer.setContainsDirtyOverlayScrollbars(false); | 1137 m_paintLayer.setContainsDirtyOverlayScrollbars(false); |
1116 } | 1138 } |
1117 | 1139 |
1118 } // namespace blink | 1140 } // namespace blink |
OLD | NEW |