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

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

Issue 2605333002: [SPInvalidation] Fix fixed-position printing (Closed)
Patch Set: Fix scrolled 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698