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

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: Now working on basic test cases Created 4 years, 1 month 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 paintLayer.previousScrollOffsetAccumulationForPainting()) { 222 paintLayer.previousScrollOffsetAccumulationForPainting()) {
223 needsRepaint = true; 223 needsRepaint = true;
224 shouldClearEmptyPaintPhaseFlags = true; 224 shouldClearEmptyPaintPhaseFlags = true;
225 } 225 }
226 paintLayer.setPreviousScrollOffsetAccumulationForPainting( 226 paintLayer.setPreviousScrollOffsetAccumulationForPainting(
227 paintingInfo.scrollOffsetAccumulation); 227 paintingInfo.scrollOffsetAccumulation);
228 228
229 return needsRepaint; 229 return needsRepaint;
230 } 230 }
231 231
232 LayoutPoint PaintLayerPainter::fragmentOffsetForAncestorClipMask(
233 const LayoutPoint& originalFragmentOffset) {
234 // The clipping container that will be used to define the clip and the
235 // child layer with respect to which the fragment offset is defined share
236 // a layer root. When the clip is recorded we will be using the clipping
237 // container's layer's offset to the root to position the clip. Hence we
238 // must convert the fragment offset into a corresponding offset in the
239 // clipping container's layer coordinates. To do that, we find the
240 // originalFragmentOffset's coordinate in the root layer, fragmentDelta.
241 // We also find the offset of the clipping container's origin in the root
242 // layer's coordinates, clippingDelta. clippingDelta - fragmentDelta gives
243 // the fragment's position in the root layer. But we need the position in
244 // the clipping layer coords, and we subtract clippingDelta to get that. The
245 // resulting offset is -fragmentDelta.
246 DCHECK_EQ(m_paintLayer.root(),
247 m_paintLayer.clippingContainer()->enclosingLayer()->root());
248 LayoutPoint fragmentDelta(originalFragmentOffset);
249 m_paintLayer.convertToLayerCoords(m_paintLayer.root(), fragmentDelta);
250 return LayoutPoint(-fragmentDelta.x(), -fragmentDelta.y());
251 }
252
232 PaintResult PaintLayerPainter::paintLayerContents( 253 PaintResult PaintLayerPainter::paintLayerContents(
233 GraphicsContext& context, 254 GraphicsContext& context,
234 const PaintLayerPaintingInfo& paintingInfoArg, 255 const PaintLayerPaintingInfo& paintingInfoArg,
235 PaintLayerFlags paintFlags, 256 PaintLayerFlags paintFlags,
236 FragmentPolicy fragmentPolicy) { 257 FragmentPolicy fragmentPolicy) {
237 Optional<ScopedPaintChunkProperties> scopedPaintChunkProperties; 258 Optional<ScopedPaintChunkProperties> scopedPaintChunkProperties;
238 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && 259 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() &&
239 RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 260 RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
240 m_paintLayer.layoutObject() && 261 m_paintLayer.layoutObject() &&
241 m_paintLayer.layoutObject()->isLayoutView()) { 262 m_paintLayer.layoutObject()->isLayoutView()) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 // These helpers output clip and compositing operations using a RAII pattern. 367 // These helpers output clip and compositing operations using a RAII pattern.
347 // Stack-allocated-varibles are destructed in the reverse order of 368 // Stack-allocated-varibles are destructed in the reverse order of
348 // construction, so they are nested properly. 369 // construction, so they are nested properly.
349 Optional<ClipPathClipper> clipPathClipper; 370 Optional<ClipPathClipper> clipPathClipper;
350 // 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
351 // composited-scrolling container. It must, however, still be applied to the 372 // composited-scrolling container. It must, however, still be applied to the
352 // mask layer, so that the compositor can properly mask the 373 // mask layer, so that the compositor can properly mask the
353 // scrolling contents and scrollbars. 374 // scrolling contents and scrollbars.
354 if (m_paintLayer.layoutObject()->hasClipPath() && 375 if (m_paintLayer.layoutObject()->hasClipPath() &&
355 (!m_paintLayer.needsCompositedScrolling() || 376 (!m_paintLayer.needsCompositedScrolling() ||
356 (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { 377 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
378 PaintLayerPaintingAncestorClippingMaskPhase)))) {
357 paintingInfo.ancestorHasClipPathClipping = true; 379 paintingInfo.ancestorHasClipPathClipping = true;
358 380
359 LayoutRect referenceBox(m_paintLayer.boxForClipPath()); 381 LayoutRect referenceBox(m_paintLayer.boxForClipPath());
360 // 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
361 // boundary. The reference box should be determined per-fragment, and hence 383 // boundary. The reference box should be determined per-fragment, and hence
362 // this ought to be performed after fragmentation. 384 // this ought to be performed after fragmentation.
363 if (m_paintLayer.enclosingPaginationLayer()) 385 if (m_paintLayer.enclosingPaginationLayer())
364 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor( 386 m_paintLayer.convertFromFlowThreadToVisualBoundingBoxInAncestor(
365 paintingInfo.rootLayer, referenceBox); 387 paintingInfo.rootLayer, referenceBox);
366 else 388 else
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 if (shouldPaintContent || shouldPaintSelfOutline || 424 if (shouldPaintContent || shouldPaintSelfOutline ||
403 isPaintingOverlayScrollbars) { 425 isPaintingOverlayScrollbars) {
404 // Collect the fragments. This will compute the clip rectangles and paint 426 // Collect the fragments. This will compute the clip rectangles and paint
405 // offsets for each layer fragment. 427 // offsets for each layer fragment.
406 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) 428 ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
407 ? UncachedClipRects 429 ? UncachedClipRects
408 : PaintingClipRects; 430 : PaintingClipRects;
409 // 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
410 // SPv2. Related thread 432 // SPv2. Related thread
411 // 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 LayoutPoint clippersOffsetToRoot;
443 paintLayerForFragmentsAndClip->convertToLayerCoords(m_paintLayer.root(),
444 clippersOffsetToRoot);
445 LayoutPoint thisOffsetToRoot;
446 m_paintLayer.convertToLayerCoords(m_paintLayer.root(), thisOffsetToRoot);
447 offsetFromRootForFragmentsAndClip =
448 LayoutPoint(clippersOffsetToRoot.x() - thisOffsetToRoot.x(),
449 clippersOffsetToRoot.y() - thisOffsetToRoot.y());
450 }
451
412 if (fragmentPolicy == ForceSingleFragment || 452 if (fragmentPolicy == ForceSingleFragment ||
413 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 453 RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
414 m_paintLayer.appendSingleFragmentIgnoringPagination( 454 paintLayerForFragmentsAndClip->appendSingleFragmentIgnoringPagination(
415 layerFragments, localPaintingInfo.rootLayer, 455 layerFragments, localPaintingInfo.rootLayer,
416 localPaintingInfo.paintDirtyRect, cacheSlot, 456 localPaintingInfo.paintDirtyRect, cacheSlot,
417 IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, 457 IgnoreOverlayScrollbarSize, respectOverflowClip,
458 &offsetFromRootForFragmentsAndClip,
418 localPaintingInfo.subPixelAccumulation); 459 localPaintingInfo.subPixelAccumulation);
419 else 460 } else {
420 m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, 461 paintLayerForFragmentsAndClip->collectFragments(
421 localPaintingInfo.paintDirtyRect, cacheSlot, 462 layerFragments, localPaintingInfo.rootLayer,
422 IgnoreOverlayScrollbarSize, 463 localPaintingInfo.paintDirtyRect, cacheSlot,
423 respectOverflowClip, &offsetFromRoot, 464 IgnoreOverlayScrollbarSize, respectOverflowClip,
424 localPaintingInfo.subPixelAccumulation); 465 &offsetFromRootForFragmentsAndClip,
466 localPaintingInfo.subPixelAccumulation);
467 }
468
469 // Reset the layerBounds because they were set using the clipper's layer
470 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
471 for (auto& fragment : layerFragments) {
472 fragment.layerBounds =
473 LayoutRect(offsetFromRoot, LayoutSize(m_paintLayer.size()));
474 }
475 }
425 476
426 if (shouldPaintContent) { 477 if (shouldPaintContent) {
427 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar 478 // TODO(wangxianzhu): This is for old slow scrolling. Implement similar
428 // optimization for slimming paint v2. 479 // optimization for slimming paint v2.
429 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect( 480 shouldPaintContent = atLeastOneFragmentIntersectsDamageRect(
430 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot); 481 layerFragments, localPaintingInfo, paintFlags, offsetFromRoot);
431 if (!shouldPaintContent) 482 if (!shouldPaintContent)
432 result = MayBeClippedByPaintDirtyRect; 483 result = MayBeClippedByPaintDirtyRect;
433 } 484 }
434 } 485 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 if (shouldPaintOverlayScrollbars) 569 if (shouldPaintOverlayScrollbars)
519 paintOverflowControlsForFragments(layerFragments, context, 570 paintOverflowControlsForFragments(layerFragments, context,
520 localPaintingInfo, paintFlags); 571 localPaintingInfo, paintFlags);
521 } // FilterPainter block 572 } // FilterPainter block
522 573
523 bool shouldPaintMask = 574 bool shouldPaintMask =
524 (paintFlags & PaintLayerPaintingCompositingMaskPhase) && 575 (paintFlags & PaintLayerPaintingCompositingMaskPhase) &&
525 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && 576 shouldPaintContent && m_paintLayer.layoutObject()->hasMask() &&
526 !selectionOnly; 577 !selectionOnly;
527 bool shouldPaintClippingMask = 578 bool shouldPaintClippingMask =
528 (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && 579 (paintFlags & (PaintLayerPaintingChildClippingMaskPhase |
580 PaintLayerPaintingAncestorClippingMaskPhase)) &&
529 shouldPaintContent && !selectionOnly; 581 shouldPaintContent && !selectionOnly;
530 582
531 if (shouldPaintMask) 583 if (shouldPaintMask)
532 paintMaskForFragments(layerFragments, context, localPaintingInfo, 584 paintMaskForFragments(layerFragments, context, localPaintingInfo,
533 paintFlags); 585 paintFlags);
534 if (shouldPaintClippingMask) { 586 if (shouldPaintClippingMask) {
535 // Paint the border radius mask for the fragments. 587 // Paint the border radius mask for the fragments.
536 paintChildClippingMaskForFragments(layerFragments, context, 588 paintChildClippingMaskForFragments(layerFragments, context,
537 localPaintingInfo, paintFlags); 589 localPaintingInfo, paintFlags);
538 } 590 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 // its parent. 649 // its parent.
598 PaintLayer* parentLayer = m_paintLayer.parent(); 650 PaintLayer* parentLayer = m_paintLayer.parent();
599 651
600 LayoutObject* object = m_paintLayer.layoutObject(); 652 LayoutObject* object = m_paintLayer.layoutObject();
601 LayoutView* view = object->view(); 653 LayoutView* view = object->view();
602 bool isFixedPosObjectInPagedMedia = 654 bool isFixedPosObjectInPagedMedia =
603 object->style()->position() == FixedPosition && 655 object->style()->position() == FixedPosition &&
604 object->container() == view && view->pageLogicalHeight(); 656 object->container() == view && view->pageLogicalHeight();
605 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); 657 PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer();
606 PaintLayerFragments fragments; 658 PaintLayerFragments fragments;
659
607 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position 660 // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position
608 // objects in paged media with vertical writing modes. 661 // objects in paged media with vertical writing modes.
609 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) { 662 if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) {
610 // "For paged media, boxes with fixed positions are repeated on every page." 663 // "For paged media, boxes with fixed positions are repeated on every page."
611 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng 664 // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioni ng
612 unsigned pages = 665 unsigned pages =
613 ceilf(view->documentRect().height() / view->pageLogicalHeight()); 666 ceilf(view->documentRect().height() / view->pageLogicalHeight());
614 LayoutPoint paginationOffset; 667 LayoutPoint paginationOffset;
615 668
616 // The fixed position object is offset from the top of the page, so remove 669 // The fixed position object is offset from the top of the page, so remove
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 // handle clipping to self. 934 // handle clipping to self.
882 case PaintPhaseSelfOutlineOnly: 935 case PaintPhaseSelfOutlineOnly:
883 case PaintPhaseMask: // Mask painting will handle clipping to self. 936 case PaintPhaseMask: // Mask painting will handle clipping to self.
884 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; 937 clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius;
885 break; 938 break;
886 default: 939 default:
887 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; 940 clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius;
888 break; 941 break;
889 } 942 }
890 943
891 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, 944 // When painting the clipping mask for a composited child, we pass
892 clipRect, &paintingInfo, fragment.paginationOffset, 945 // the clipping container object as the layoutObject to provide the clip.
893 paintFlags, clippingRule); 946 // The recorder assumes the fragment is positioned in that objects's
947 // layer coordinates, so we also convert that.
948 if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) {
949 clipRecorder.emplace(
950 context, *(toLayoutBoxModelObject(m_paintLayer.clippingContainer())),
951 clipType, clipRect, &paintingInfo,
952 fragmentOffsetForAncestorClipMask(fragment.paginationOffset),
953 paintFlags, clippingRule);
954 } else {
955 clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType,
956 clipRect, &paintingInfo, fragment.paginationOffset,
957 paintFlags, clippingRule);
958 }
894 } 959 }
895 960
896 LayoutRect newCullRect(clipRect.rect()); 961 LayoutRect newCullRect(clipRect.rect());
897 Optional<ScrollRecorder> scrollRecorder; 962 Optional<ScrollRecorder> scrollRecorder;
898 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation(); 963 LayoutPoint paintOffset = -m_paintLayer.layoutBoxLocation();
899 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 964 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
900 const auto* objectPaintProperties = 965 const auto* objectPaintProperties =
901 m_paintLayer.layoutObject()->paintProperties(); 966 m_paintLayer.layoutObject()->paintProperties();
902 DCHECK(objectPaintProperties && 967 DCHECK(objectPaintProperties &&
903 objectPaintProperties->localBorderBoxProperties()); 968 objectPaintProperties->localBorderBoxProperties());
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 1167
1103 PaintLayerPaintingInfo paintingInfo(&m_paintLayer, 1168 PaintLayerPaintingInfo paintingInfo(&m_paintLayer,
1104 LayoutRect(enclosingIntRect(damageRect)), 1169 LayoutRect(enclosingIntRect(damageRect)),
1105 paintFlags, LayoutSize()); 1170 paintFlags, LayoutSize());
1106 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars); 1171 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1107 1172
1108 m_paintLayer.setContainsDirtyOverlayScrollbars(false); 1173 m_paintLayer.setContainsDirtyOverlayScrollbars(false);
1109 } 1174 }
1110 1175
1111 } // namespace blink 1176 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698