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

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

Issue 2194273002: Fix border radius on composited children. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Switch to using the layer's offsetFromLayoutObject Created 4 years 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 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 // These helpers output clip and compositing operations using a RAII pattern. 367 // These helpers output clip and compositing operations using a RAII pattern.
368 // Stack-allocated-varibles are destructed in the reverse order of 368 // Stack-allocated-varibles are destructed in the reverse order of
369 // construction, so they are nested properly. 369 // construction, so they are nested properly.
370 Optional<ClipPathClipper> clipPathClipper; 370 Optional<ClipPathClipper> clipPathClipper;
371 // Clip-path, like border radius, must not be applied to the contents of a 371 // Clip-path, like border radius, must not be applied to the contents of a
372 // composited-scrolling container. It must, however, still be applied to the 372 // composited-scrolling container. It must, however, still be applied to the
373 // mask layer, so that the compositor can properly mask the 373 // mask layer, so that the compositor can properly mask the
374 // scrolling contents and scrollbars. 374 // scrolling contents and scrollbars.
375 if (m_paintLayer.layoutObject()->hasClipPath() && 375 if (m_paintLayer.layoutObject()->hasClipPath() &&
376 (!m_paintLayer.needsCompositedScrolling() || 376 (!m_paintLayer.needsCompositedScrolling() ||
377 (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { 377 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
378 PaintLayerPaintingAncestorClippingMaskPhase)))) {
378 paintingInfo.ancestorHasClipPathClipping = true; 379 paintingInfo.ancestorHasClipPathClipping = true;
379 380
380 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); 381 LayoutRect referenceBox(m_paintLayer.boxForClipPath());
381 // Note that this isn't going to work correctly if crossing a column 382 // Note that this isn't going to work correctly if crossing a column
382 // boundary. The reference box should be determined per-fragment, and hence 383 // boundary. The reference box should be determined per-fragment, and hence
383 // this ought to be performed after fragmentation. 384 // this ought to be performed after fragmentation.
384 if (m_paintLayer.enclosingPaginationLayer()) 385 if (m_paintLayer.enclosingPaginationLayer())
385 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( 386 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor(
386 paintingInfo.rootLayer, referenceBox); 387 paintingInfo.rootLayer, referenceBox);
387 else 388 else
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 localPaintingInfo.subPixelAccumulation = subpixelAccumulation; 421 localPaintingInfo.subPixelAccumulation = subpixelAccumulation;
421 422
422 PaintLayerFragments layerFragments; 423 PaintLayerFragments layerFragments;
423 if (shouldPaintContent || shouldPaintSelfOutline || 424 if (shouldPaintContent || shouldPaintSelfOutline ||
424 isPaintingOverlayScrollbars) { 425 isPaintingOverlayScrollbars) {
425 // Collect the fragments. This will compute the clip rectangles and paint 426 // Collect the fragments. This will compute the clip rectangles and paint
426 // offsets for each layer fragment. 427 // offsets for each layer fragment.
427 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) 428 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
428 ? UncachedClipRects 429 ? UncachedClipRects
429 : PaintingClipRects; 430 : PaintingClipRects;
430 // TODO(trchen): We haven't decided how to handle visual fragmentation with 431 // TODO(trchen): We haven't decided how to handle visual fragmentation with
chrishtr 2016/12/02 19:21:47 This comment belongs down by line 446.
Stephen Chennney 2016/12/07 21:39:38 Done.
431 // SPv2. Related thread 432 // SPv2. Related thread
432 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM 433 // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuW Ff-mxM
434 PaintLayer* paintLayerForFragmentsAndClip = &m_paintLayer;
435 LayoutPoint offsetFromRootForFragmentsAndClip = offsetFromRoot;
436 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
437 // Compute fragments and their clips with respect to the clipping
438 // container, and then convert them back to this layer's space.
439 // We need a new offset from root.
440 paintLayerForFragmentsAndClip =
441 m_paintLayer.clippingContainer()->enclosingLayer();
442 paintLayerForFragmentsAndClip->convertToLayerCoords(
chrishtr 2016/12/02 19:21:47 You can't map from an ancestor to a descendant Pai
Stephen Chennney 2016/12/07 21:39:38 Done.
443 m_paintLayer.root(), offsetFromRootForFragmentsAndClip);
444 }
445
433 if (fragmentPolicy == ForceSingleFragment || 446 if (fragmentPolicy == ForceSingleFragment ||
434 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 447 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
435 m_paintLayer.appendSingleFragmentIgnoringPagination( 448 paintLayerForFragmentsAndClip->appendSingleFragmentIgnoringPagination(
436 layerFragments, localPaintingInfo.rootLayer, 449 layerFragments, localPaintingInfo.rootLayer,
437 localPaintingInfo.paintDirtyRect, cacheSlot, 450 localPaintingInfo.paintDirtyRect, cacheSlot,
438 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 451 IgnoreOverlayScrollbarSize, respectOverflowClip,
452 &offsetFromRootForFragmentsAndClip,
439 localPaintingInfo.subPixelAccumulation); 453 localPaintingInfo.subPixelAccumulation);
440 else 454 } else {
441 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, 455 paintLayerForFragmentsAndClip->collectFragments(
442 localPaintingInfo.paintDirtyRect, cacheSlot, 456 layerFragments, localPaintingInfo.rootLayer,
443 IgnoreOverlayScrollbarSize, 457 localPaintingInfo.paintDirtyRect, cacheSlot,
444 respectOverflowClip, &offsetFromRoot, 458 IgnoreOverlayScrollbarSize, respectOverflowClip,
445 localPaintingInfo.subPixelAccumulation); 459 &offsetFromRootForFragmentsAndClip,
460 localPaintingInfo.subPixelAccumulation);
461 }
446 462
447 if (shouldPaintContent) { 463 if (shouldPaintContent) {
448 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar 464 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
449 // optimization for slimming paint v2. 465 // optimization for slimming paint v2.
450 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( 466 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(
451 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); 467 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
452 if (!shouldPaintContent) 468 if (!shouldPaintContent)
453 result = MayBeClippedByPaintDirtyRect; 469 result = MayBeClippedByPaintDirtyRect;
454 } 470 }
455 } 471 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 if (shouldPaintOverlayScrollbars) 555 if (shouldPaintOverlayScrollbars)
540 paintOverflowControlsForFragments(layerFragments, context, 556 paintOverflowControlsForFragments(layerFragments, context,
541 localPaintingInfo, paintFlags); 557 localPaintingInfo, paintFlags);
542 } // FilterPainter block 558 } // FilterPainter block
543 559
544 bool shouldPaintMask = 560 bool shouldPaintMask =
545 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && 561 (paintFlags & PaintLayerPaintingCompositingMaskPhase) &&
546 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && 562 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
547 !selectionOnly; 563 !selectionOnly;
548 bool shouldPaintClippingMask = 564 bool shouldPaintClippingMask =
549 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && 565 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
566 PaintLayerPaintingAncestorClippingMaskPhase)) &&
550 shouldPaintContent && !selectionOnly; 567 shouldPaintContent && !selectionOnly;
551 568
552 if (shouldPaintMask) 569 if (shouldPaintMask)
553 paintMaskForFragments(layerFragments, context, localPaintingInfo, 570 paintMaskForFragments(layerFragments, context, localPaintingInfo,
554 paintFlags); 571 paintFlags);
555 if (shouldPaintClippingMask) { 572 if (shouldPaintClippingMask) {
556 // Paint the border radius mask for the fragments. 573 // Paint the border radius mask for the fragments.
557 paintChildClippingMaskForFragments(layerFragments, context, 574 paintChildClippingMaskForFragments(layerFragments, context,
558 localPaintingInfo, paintFlags); 575 localPaintingInfo, paintFlags);
559 } 576 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 // its parent. 635 // its parent.
619 PaintLayer* parentLayer = m_paintLayer.parent(); 636 PaintLayer* parentLayer = m_paintLayer.parent();
620 637
621 LayoutObject* object = m_paintLayer.layoutObject(); 638 LayoutObject* object = m_paintLayer.layoutObject();
622 LayoutView* view = object->view(); 639 LayoutView* view = object->view();
623 bool isFixedPosObjectInPagedMedia = 640 bool isFixedPosObjectInPagedMedia =
624 object->style()->position() == FixedPosition && 641 object->style()->position() == FixedPosition &&
625 object->container() == view && view->pageLogicalHeight(); 642 object->container() == view && view->pageLogicalHeight();
626 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); 643 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer();
627 PaintLayerFragments fragments; 644 PaintLayerFragments fragments;
645
chrishtr 2016/12/02 19:21:47 Super nit: spurious.
Stephen Chennney 2016/12/07 21:39:38 Done.
628 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position 646 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position
629 // objects in paged media with vertical writing modes. 647 // objects in paged media with vertical writing modes.
630 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) { 648 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) {
631 // "For paged media, boxes with fixed positions are repeated on every page." 649 // "For paged media, boxes with fixed positions are repeated on every page."
632 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng 650 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng
633 unsigned pages = 651 unsigned pages =
634 ceilf(view->documentRect().height() / view->pageLogicalHeight()); 652 ceilf(view->documentRect().height() / view->pageLogicalHeight());
635 LayoutPoint paginationOffset; 653 LayoutPoint paginationOffset;
636 654
637 // The fixed position object is offset from the top of the page, so remove 655 // The fixed position object is offset from the top of the page, so remove
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 892
875 // We pass IntPoint() as the paint offset here, because 893 // We pass IntPoint() as the paint offset here, because
876 // ScrollableArea::paintOverflowControls just ignores it and uses the 894 // ScrollableArea::paintOverflowControls just ignores it and uses the
877 // offset found in a previous pass. 895 // offset found in a previous pass.
878 CullRect snappedCullRect(pixelSnappedIntRect(cullRect)); 896 CullRect snappedCullRect(pixelSnappedIntRect(cullRect));
879 ScrollableAreaPainter(*scrollableArea) 897 ScrollableAreaPainter(*scrollableArea)
880 .paintOverflowControls(context, IntPoint(), snappedCullRect, true); 898 .paintOverflowControls(context, IntPoint(), snappedCullRect, true);
881 } 899 }
882 } 900 }
883 901
902 void adjustPaintOffsetForAncestorClippingMask(
903 PaintLayer& layer, LayoutPoint& paintOffset)
904 {
905 // Adjust the paint offset to reflect the fact that the fragment is
906 // positioned for the clipping container object.
907 LayoutPoint clippersOffsetToRoot;
908 PaintLayer* paintLayerForMask =
909 layer.clippingContainer()->enclosingLayer();
910 paintLayerForMask->convertToLayerCoords(layer.root(),
chrishtr 2016/12/02 19:21:47 This duplicates line 442 I think?
911 clippersOffsetToRoot);
912 LayoutPoint paintersOffsetToRoot;
913 layer.convertToLayerCoords(layer.root(), paintersOffsetToRoot);
914
915 paintOffset.move(paintersOffsetToRoot - clippersOffsetToRoot);
916 }
917
884 void PaintLayerPainter::paintFragmentWithPhase( 918 void PaintLayerPainter::paintFragmentWithPhase(
885 PaintPhase phase, 919 PaintPhase phase,
886 const PaintLayerFragment& fragment, 920 const PaintLayerFragment& fragment,
887 GraphicsContext& context, 921 GraphicsContext& context,
888 const ClipRect& clipRect, 922 const ClipRect& clipRect,
889 const PaintLayerPaintingInfo& paintingInfo, 923 const PaintLayerPaintingInfo& paintingInfo,
890 PaintLayerFlags paintFlags, 924 PaintLayerFlags paintFlags,
891 ClipState clipState) { 925 ClipState clipState) {
892 DCHECK(m_paintLayer.isSelfPaintingLayer()); 926 DCHECK(m_paintLayer.isSelfPaintingLayer());
893 927
894 Optional<LayerClipRecorder> clipRecorder; 928 Optional<LayerClipRecorder> clipRecorder;
895 if (clipState != HasClipped && paintingInfo.clipToDirtyRect && 929 if (clipState != HasClipped && paintingInfo.clipToDirtyRect &&
896 needsToClip(paintingInfo, clipRect)) { 930 needsToClip(paintingInfo, clipRect)) {
897 DisplayItem::Type clipType = 931 DisplayItem::Type clipType =
898 DisplayItem::paintPhaseToClipLayerFragmentType(phase); 932 DisplayItem::paintPhaseToClipLayerFragmentType(phase);
899 LayerClipRecorder::BorderRadiusClippingRule clippingRule; 933 LayerClipRecorder::BorderRadiusClippingRule clippingRule;
900 switch (phase) { 934 switch (phase) {
901 case PaintPhaseSelfBlockBackgroundOnly: // Background painting will 935 case PaintPhaseSelfBlockBackgroundOnly: // Background painting will
902 // handle clipping to self. 936 // handle clipping to self.
903 case PaintPhaseSelfOutlineOnly: 937 case PaintPhaseSelfOutlineOnly:
904 case PaintPhaseMask: // Mask painting will handle clipping to self. 938 case PaintPhaseMask: // Mask painting will handle clipping to self.
905 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; 939 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
906 break; 940 break;
907 default: 941 default:
908 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; 942 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
909 break; 943 break;
910 } 944 }
911 945
912 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, 946 // When painting the clipping mask for a composited child, we pass
913 clipRect, &paintingInfo, fragment.paginationOffset, 947 // the clipping container object as the layoutObject to provide the clip.
914 paintFlags, clippingRule); 948 // The recorder assumes the fragment is positioned in that objects's
949 // layer coordinates, so we also convert that.
950 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
951 clipRecorder.emplace(
952 context, *(toLayoutBoxModelObject(m_paintLayer.clippingContainer())),
chrishtr 2016/12/02 19:21:47 Might be easier to read if you make a local variab
953 clipType, clipRect, &paintingInfo,
954 fragment.paginationOffset,
955 paintFlags, clippingRule);
956 } else {
957 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
958 clipRect, &paintingInfo, fragment.paginationOffset,
959 paintFlags, clippingRule);
960 }
915 } 961 }
916 962
917 LayoutRect newCullRect(clipRect.rect()); 963 LayoutRect newCullRect(clipRect.rect());
918 Optional<ScrollRecorder> scrollRecorder; 964 Optional<ScrollRecorder> scrollRecorder;
919 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); 965 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation();
920 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 966 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
921 const auto* objectPaintProperties = 967 const auto* objectPaintProperties =
922 m_paintLayer.layoutObject()->paintProperties(); 968 m_paintLayer.layoutObject()->paintProperties();
923 DCHECK(objectPaintProperties && 969 DCHECK(objectPaintProperties &&
924 objectPaintProperties->localBorderBoxProperties()); 970 objectPaintProperties->localBorderBoxProperties());
(...skipping 13 matching lines...) Expand all
938 984
939 newCullRect.move(paintingInfo.scrollOffsetAccumulation); 985 newCullRect.move(paintingInfo.scrollOffsetAccumulation);
940 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase, 986 scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase,
941 paintingInfo.scrollOffsetAccumulation); 987 paintingInfo.scrollOffsetAccumulation);
942 } 988 }
943 } 989 }
944 PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase, 990 PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase,
945 paintingInfo.getGlobalPaintFlags(), paintFlags, 991 paintingInfo.getGlobalPaintFlags(), paintFlags,
946 paintingInfo.rootLayer->layoutObject()); 992 paintingInfo.rootLayer->layoutObject());
947 993
994 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase)
995 adjustPaintOffsetForAncestorClippingMask(m_paintLayer, paintOffset);
996
948 m_paintLayer.layoutObject()->paint(paintInfo, paintOffset); 997 m_paintLayer.layoutObject()->paint(paintInfo, paintOffset);
949 } 998 }
950 999
951 void PaintLayerPainter::paintBackgroundForFragments( 1000 void PaintLayerPainter::paintBackgroundForFragments(
952 const PaintLayerFragments& layerFragments, 1001 const PaintLayerFragments& layerFragments,
953 GraphicsContext& context, 1002 GraphicsContext& context,
954 const LayoutRect& transparencyPaintDirtyRect, 1003 const LayoutRect& transparencyPaintDirtyRect,
955 const PaintLayerPaintingInfo& localPaintingInfo, 1004 const PaintLayerPaintingInfo& localPaintingInfo,
956 PaintLayerFlags paintFlags) { 1005 PaintLayerFlags paintFlags) {
957 Optional<DisplayItemCacheSkipper> cacheSkipper; 1006 Optional<DisplayItemCacheSkipper> cacheSkipper;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 1172
1124 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, 1173 PaintLayerPaintingInfo paintingInfo(&m_paintLayer,
1125 LayoutRect(enclosingIntRect(damageRect)), 1174 LayoutRect(enclosingIntRect(damageRect)),
1126 paintFlags, LayoutSize()); 1175 paintFlags, LayoutSize());
1127 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1176 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1128 1177
1129 m_paintLayer.setContainsDirtyOverlayScrollbars(false); 1178 m_paintLayer.setContainsDirtyOverlayScrollbars(false);
1130 } 1179 }
1131 1180
1132 } // namespace blink 1181 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698