Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp

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

Powered by Google App Engine
This is Rietveld 408576698