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

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

Issue 2781863005: Account for filter bounds for backgroundRect during PaintLayer painting (Closed)
Patch Set: none Created 3 years, 8 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 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * 4 *
5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
6 * 6 *
7 * Other contributors: 7 * Other contributors:
8 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * Robert O'Callahan <roc+@cs.cmu.edu>
9 * David Baron <dbaron@fas.harvard.edu> 9 * David Baron <dbaron@fas.harvard.edu>
10 * Christian Biesinger <cbiesinger@web.de> 10 * Christian Biesinger <cbiesinger@web.de>
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 layer = layer->nextSibling()) 194 layer = layer->nextSibling())
195 layers.push(layer); 195 layers.push(layer);
196 } 196 }
197 } 197 }
198 198
199 LayoutRect PaintLayerClipper::localClipRect( 199 LayoutRect PaintLayerClipper::localClipRect(
200 const PaintLayer& clippingRootLayer) const { 200 const PaintLayer& clippingRootLayer) const {
201 ClipRectsContext context(&clippingRootLayer, PaintingClipRects); 201 ClipRectsContext context(&clippingRootLayer, PaintingClipRects);
202 if (m_geometryMapper) { 202 if (m_geometryMapper) {
203 ClipRect clipRect; 203 ClipRect clipRect;
204 calculateClipRectWithGeometryMapper(context, false, clipRect); 204 calculateBackgroundClipRectWithGeometryMapper(context, clipRect);
205 applyOverflowClipToBackgroundRectWithGeometryMapper(context, clipRect);
206 LayoutRect premappedRect = clipRect.rect(); 205 LayoutRect premappedRect = clipRect.rect();
207 206
208 // The rect now needs to be transformed to the local space of this 207 // The rect now needs to be transformed to the local space of this
209 // PaintLayer. 208 // PaintLayer.
210 premappedRect.moveBy(context.rootLayer->layoutObject().paintOffset()); 209 premappedRect.moveBy(context.rootLayer->layoutObject().paintOffset());
211 210
212 const auto* clipRootLayerTransform = clippingRootLayer.layoutObject() 211 const auto* clipRootLayerTransform = clippingRootLayer.layoutObject()
213 .paintProperties() 212 .paintProperties()
214 ->localBorderBoxProperties() 213 ->localBorderBoxProperties()
215 ->transform(); 214 ->transform();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 (expected.isEmpty() && actual.isEmpty()) || expected == actual; \ 249 (expected.isEmpty() && actual.isEmpty()) || expected == actual; \
251 if (!matches) { \ 250 if (!matches) { \
252 LOG(ERROR) << "Rects don't match for m_layer=" \ 251 LOG(ERROR) << "Rects don't match for m_layer=" \
253 << m_layer.layoutObject()->debugName() \ 252 << m_layer.layoutObject()->debugName() \
254 << " expected=" << expected.toString() \ 253 << " expected=" << expected.toString() \
255 << " actual=" << actual.toString(); \ 254 << " actual=" << actual.toString(); \
256 } \ 255 } \
257 } while (false); 256 } while (false);
258 #endif 257 #endif
259 258
260 void PaintLayerClipper::mapLocalToRootWithGeometryMapper(
261 const ClipRectsContext& context,
262 LayoutRect& rectToMap) const {
263 DCHECK(m_geometryMapper);
264
265 const auto* layerTransform = m_layer.layoutObject()
266 .paintProperties()
267 ->localBorderBoxProperties()
268 ->transform();
269 const auto* rootTransform = context.rootLayer->layoutObject()
270 .paintProperties()
271 ->localBorderBoxProperties()
272 ->transform();
273
274 FloatRect floatRect(rectToMap);
275 floatRect.moveBy(FloatPoint(m_layer.layoutObject().paintOffset()));
276 m_geometryMapper->sourceToDestinationRect(layerTransform, rootTransform,
277 floatRect);
278 rectToMap = LayoutRect(floatRect);
279 rectToMap.moveBy(-context.rootLayer->layoutObject().paintOffset());
280 rectToMap.move(context.subPixelAccumulation);
281 }
282
283 void PaintLayerClipper::calculateRectsWithGeometryMapper( 259 void PaintLayerClipper::calculateRectsWithGeometryMapper(
284 const ClipRectsContext& context, 260 const ClipRectsContext& context,
285 const LayoutRect& paintDirtyRect, 261 const LayoutRect& paintDirtyRect,
286 LayoutRect& layerBounds, 262 LayoutRect& layerBounds,
287 ClipRect& backgroundRect, 263 ClipRect& backgroundRect,
288 ClipRect& foregroundRect, 264 ClipRect& foregroundRect,
289 const LayoutPoint* offsetFromRoot) const { 265 const LayoutPoint* offsetFromRoot) const {
290 const auto* properties = m_layer.layoutObject().paintProperties(); 266 const auto* properties = m_layer.layoutObject().paintProperties();
291 // TODO(chrishtr): fix the underlying bug that causes this situation. 267 // TODO(chrishtr): fix the underlying bug that causes this situation.
292 if (!properties) { 268 if (!properties) {
293 backgroundRect = ClipRect(LayoutRect(LayoutRect::infiniteIntRect())); 269 backgroundRect = ClipRect(LayoutRect(LayoutRect::infiniteIntRect()));
294 foregroundRect = ClipRect(LayoutRect(LayoutRect::infiniteIntRect())); 270 foregroundRect = ClipRect(LayoutRect(LayoutRect::infiniteIntRect()));
295 } else { 271 } else {
296 calculateClipRectWithGeometryMapper(context, false, backgroundRect); 272 calculateBackgroundClipRectWithGeometryMapper(context, backgroundRect);
297
298 backgroundRect.move(context.subPixelAccumulation); 273 backgroundRect.move(context.subPixelAccumulation);
299 backgroundRect.intersect(paintDirtyRect); 274 backgroundRect.intersect(paintDirtyRect);
300 275
301 applyOverflowClipToBackgroundRectWithGeometryMapper(context, 276 calculateForegroundClipRectWithGeometryMapper(context, foregroundRect);
302 backgroundRect);
303
304 calculateClipRectWithGeometryMapper(context, true, foregroundRect);
305 foregroundRect.move(context.subPixelAccumulation); 277 foregroundRect.move(context.subPixelAccumulation);
306 foregroundRect.intersect(paintDirtyRect); 278 foregroundRect.intersect(paintDirtyRect);
307 } 279 }
308 LayoutPoint offset; 280 LayoutPoint offset;
309 if (offsetFromRoot) 281 if (offsetFromRoot)
310 offset = *offsetFromRoot; 282 offset = *offsetFromRoot;
311 else 283 else
312 m_layer.convertToLayerCoords(context.rootLayer, offset); 284 m_layer.convertToLayerCoords(context.rootLayer, offset);
313 layerBounds = LayoutRect(offset, LayoutSize(m_layer.size())); 285 layerBounds = LayoutRect(offset, LayoutSize(m_layer.size()));
314 286
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 LayoutRect overflowAndClipRect = 335 LayoutRect overflowAndClipRect =
364 toLayoutBox(layoutObject) 336 toLayoutBox(layoutObject)
365 .overflowClipRect(offset, context.overlayScrollbarClipBehavior); 337 .overflowClipRect(offset, context.overlayScrollbarClipBehavior);
366 foregroundRect.intersect(overflowAndClipRect); 338 foregroundRect.intersect(overflowAndClipRect);
367 if (layoutObject.styleRef().hasBorderRadius()) 339 if (layoutObject.styleRef().hasBorderRadius())
368 foregroundRect.setHasRadius(true); 340 foregroundRect.setHasRadius(true);
369 341
370 // FIXME: Does not do the right thing with columns yet, since we don't yet 342 // FIXME: Does not do the right thing with columns yet, since we don't yet
371 // factor in the individual column boxes as overflow. 343 // factor in the individual column boxes as overflow.
372 344
373 // The LayoutView is special since its overflow clipping rect may be larger 345 LayoutRect layerBoundsWithVisualOverflow = localVisualRect();
374 // than its box rect (crbug.com/492871).
375 LayoutRect layerBoundsWithVisualOverflow =
376 layoutObject.isLayoutView()
377 ? toLayoutView(layoutObject).viewRect()
378 : toLayoutBox(layoutObject).visualOverflowRect();
379 // PaintLayer are in physical coordinates, so the overflow has to be
380 // flipped.
381 toLayoutBox(layoutObject).flipForWritingMode(layerBoundsWithVisualOverflow);
382 layerBoundsWithVisualOverflow.moveBy(offset); 346 layerBoundsWithVisualOverflow.moveBy(offset);
383 backgroundRect.intersect(layerBoundsWithVisualOverflow); 347 backgroundRect.intersect(layerBoundsWithVisualOverflow);
384 } 348 }
385 349
386 // CSS clip (different than clipping due to overflow) can clip to any box, 350 // CSS clip (different than clipping due to overflow) can clip to any box,
387 // even if it falls outside of the border box. 351 // even if it falls outside of the border box.
388 if (layoutObject.hasClip()) { 352 if (layoutObject.hasClip()) {
389 // Clip applies to *us* as well, so go ahead and update the damageRect. 353 // Clip applies to *us* as well, so go ahead and update the damageRect.
390 LayoutRect newPosClip = toLayoutBox(layoutObject).clipRect(offset); 354 LayoutRect newPosClip = toLayoutBox(layoutObject).clipRect(offset);
391 backgroundRect.intersect(newPosClip); 355 backgroundRect.intersect(newPosClip);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 EPosition position) { 400 EPosition position) {
437 if (position == EPosition::kFixed) 401 if (position == EPosition::kFixed)
438 return parentRects.fixedClipRect(); 402 return parentRects.fixedClipRect();
439 403
440 if (position == EPosition::kAbsolute) 404 if (position == EPosition::kAbsolute)
441 return parentRects.posClipRect(); 405 return parentRects.posClipRect();
442 406
443 return parentRects.overflowClipRect(); 407 return parentRects.overflowClipRect();
444 } 408 }
445 409
446 void PaintLayerClipper::calculateClipRectWithGeometryMapper( 410 void PaintLayerClipper::calculateBackgroundClipRectWithGeometryMapper(
trchen 2017/03/30 18:46:40 This look a lot similar to calculateForegroundClip
chrishtr 2017/03/30 23:50:14 I went ahead and factored out some common code, si
447 const ClipRectsContext& context, 411 const ClipRectsContext& context,
448 bool isForeground,
449 ClipRect& output) const { 412 ClipRect& output) const {
450 DCHECK(m_geometryMapper); 413 DCHECK(m_geometryMapper);
451 const auto* properties = m_layer.layoutObject().paintProperties(); 414 const auto* properties = m_layer.layoutObject().paintProperties();
415 DCHECK(properties && properties->localBorderBoxProperties());
416
417 PropertyTreeState propertyTreeState = *properties->localBorderBoxProperties();
418 const auto* ancestorProperties =
419 context.rootLayer->layoutObject().paintProperties();
420 DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties());
421 PropertyTreeState destinationPropertyTreeState =
422 *ancestorProperties->localBorderBoxProperties();
423 // CSS clip of the root is always applied.
424 if (ancestorProperties->cssClip()) {
425 DCHECK(destinationPropertyTreeState.clip() ==
426 ancestorProperties->cssClip());
427 destinationPropertyTreeState.setClip(
428 ancestorProperties->cssClip()->parent());
429 }
430
431 if (&m_layer != context.rootLayer) {
432 // Set the clip of |destinationPropertyTreeState| to be inside the
433 // ancestor's overflow clip, so that that clip is not applied.
434 if (context.respectOverflowClip == IgnoreOverflowClip &&
435 ancestorProperties->overflowClip())
436 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip());
437 }
438
439 if (shouldClipOverflow(context)) {
440 FloatRect clipRect(localVisualRect());
trchen 2017/03/30 18:46:40 This part still puzzles me. It seems to me the fun
chrishtr 2017/03/30 23:50:14 The background phase also paints the visual overfl
441 clipRect.moveBy(FloatPoint(m_layer.layoutObject().paintOffset()));
442 m_geometryMapper->sourceToDestinationVisualRect(
443 propertyTreeState, destinationPropertyTreeState, clipRect);
444 output.setRect(FloatClipRect(clipRect));
445 } else {
446 const FloatClipRect& clippedRectInRootLayerSpace =
447 m_geometryMapper->sourceToDestinationClipRect(
448 propertyTreeState, destinationPropertyTreeState);
449 output.setRect(clippedRectInRootLayerSpace);
450 }
451
452 output.moveBy(-context.rootLayer->layoutObject().paintOffset());
453 }
454
455 void PaintLayerClipper::calculateForegroundClipRectWithGeometryMapper(
456 const ClipRectsContext& context,
457 ClipRect& output) const {
458 DCHECK(m_geometryMapper);
459 const auto* properties = m_layer.layoutObject().paintProperties();
452 DCHECK(properties && properties->localBorderBoxProperties()); 460 DCHECK(properties && properties->localBorderBoxProperties());
453 461
454 PropertyTreeState propertyTreeState = *properties->localBorderBoxProperties(); 462 PropertyTreeState propertyTreeState = *properties->localBorderBoxProperties();
455 const auto* ancestorProperties = 463 const auto* ancestorProperties =
456 context.rootLayer->layoutObject().paintProperties(); 464 context.rootLayer->layoutObject().paintProperties();
457 DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties()); 465 DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties());
458 PropertyTreeState destinationPropertyTreeState = 466 PropertyTreeState destinationPropertyTreeState =
459 *ancestorProperties->localBorderBoxProperties(); 467 *ancestorProperties->localBorderBoxProperties();
460 // CSS clip of the root is always applied. 468 // CSS clip of the root is always applied.
461 if (ancestorProperties->cssClip()) { 469 if (ancestorProperties->cssClip()) {
462 DCHECK(destinationPropertyTreeState.clip() == 470 DCHECK(destinationPropertyTreeState.clip() ==
463 ancestorProperties->cssClip()); 471 ancestorProperties->cssClip());
464 destinationPropertyTreeState.setClip( 472 destinationPropertyTreeState.setClip(
465 ancestorProperties->cssClip()->parent()); 473 ancestorProperties->cssClip()->parent());
466 } 474 }
467 475
468 if (&m_layer == context.rootLayer) { 476 if (&m_layer == context.rootLayer) {
trchen 2017/03/30 18:46:40 Not related to this CL. Just taking note to remind
chrishtr 2017/03/30 23:50:14 ack
469 // Set the overflow clip for |propertyTreeState| so that it differs from 477 // Set the overflow clip for |propertyTreeState| so that it differs from
470 // |destinationPropertyTreeState| in its clip. 478 // |destinationPropertyTreeState| in its clip.
471 if (isForeground && context.respectOverflowClip == RespectOverflowClip && 479 if (context.respectOverflowClip == RespectOverflowClip &&
472 properties->overflowClip()) 480 properties->overflowClip())
473 propertyTreeState.setClip(properties->overflowClip()); 481 propertyTreeState.setClip(properties->overflowClip());
474 } else { 482 } else {
475 // Set the clip of |destinationPropertyTreeState| to be inside the 483 // Set the clip of |destinationPropertyTreeState| to be inside the
476 // ancestor's overflow clip, so that that clip is not applied. 484 // ancestor's overflow clip, so that that clip is not applied.
477 if (context.respectOverflowClip == IgnoreOverflowClip && 485 if (context.respectOverflowClip == IgnoreOverflowClip &&
478 ancestorProperties->overflowClip()) 486 ancestorProperties->overflowClip())
479 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip()); 487 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip());
480 488
481 // Set the overflow clip for |propertyTreeState| so that it differs from 489 // Set the overflow clip for |propertyTreeState| so that it differs from
482 // destinationPropertyTreeState| in its clip. 490 // destinationPropertyTreeState| in its clip.
483 if (isForeground && properties->overflowClip()) 491 if (properties->overflowClip())
484 propertyTreeState.setClip(properties->overflowClip()); 492 propertyTreeState.setClip(properties->overflowClip());
485 } 493 }
486 494
487 const FloatClipRect& clippedRectInRootLayerSpace = 495 const FloatClipRect& clippedRectInRootLayerSpace =
488 m_geometryMapper->sourceToDestinationClipRect( 496 m_geometryMapper->sourceToDestinationClipRect(
489 propertyTreeState, destinationPropertyTreeState); 497 propertyTreeState, destinationPropertyTreeState);
490 output.setRect(clippedRectInRootLayerSpace); 498 output.setRect(clippedRectInRootLayerSpace);
491 499
492 output.moveBy(-context.rootLayer->layoutObject().paintOffset()); 500 output.moveBy(-context.rootLayer->layoutObject().paintOffset());
493 } 501 }
494 502
495 void PaintLayerClipper::applyOverflowClipToBackgroundRectWithGeometryMapper( 503 LayoutRect PaintLayerClipper::localVisualRect() const {
496 const ClipRectsContext& context,
497 ClipRect& clip) const {
498 const LayoutObject& layoutObject = m_layer.layoutObject(); 504 const LayoutObject& layoutObject = m_layer.layoutObject();
499 if (!shouldClipOverflow(context)) 505 // The LayoutView is special since its overflow clipping rect may be larger
500 return; 506 // than its box rect (crbug.com/492871).
501 LayoutRect layerBoundsWithVisualOverflow = 507 LayoutRect layerBoundsWithVisualOverflow =
502 layoutObject.isLayoutView() 508 layoutObject.isLayoutView()
503 ? toLayoutView(layoutObject).viewRect() 509 ? toLayoutView(layoutObject).viewRect()
504 : toLayoutBox(layoutObject).visualOverflowRect(); 510 : toLayoutBox(layoutObject).visualOverflowRect();
505 toLayoutBox(layoutObject) 511 toLayoutBox(layoutObject)
506 .flipForWritingMode( 512 .flipForWritingMode(
507 // PaintLayer are in physical coordinates, so the overflow has to be 513 // PaintLayer are in physical coordinates, so the overflow has to be
508 // flipped. 514 // flipped.
509 layerBoundsWithVisualOverflow); 515 layerBoundsWithVisualOverflow);
510 mapLocalToRootWithGeometryMapper(context, layerBoundsWithVisualOverflow); 516 if (m_layer.paintsWithFilters()) {
511 clip.intersect(layerBoundsWithVisualOverflow); 517 layerBoundsWithVisualOverflow =
518 m_layer.mapLayoutRectForFilter(layerBoundsWithVisualOverflow);
519 }
520 return layerBoundsWithVisualOverflow;
512 } 521 }
513 522
514 void PaintLayerClipper::calculateBackgroundClipRect( 523 void PaintLayerClipper::calculateBackgroundClipRect(
515 const ClipRectsContext& context, 524 const ClipRectsContext& context,
516 ClipRect& output) const { 525 ClipRect& output) const {
517 if (m_geometryMapper) { 526 if (m_geometryMapper) {
518 // TODO(chrishtr): fix the underlying bug that causes this situation. 527 // TODO(chrishtr): fix the underlying bug that causes this situation.
519 if (!m_layer.layoutObject().paintProperties()) { 528 if (!m_layer.layoutObject().paintProperties()) {
520 output.setRect(FloatClipRect()); 529 output.setRect(FloatClipRect());
521 return; 530 return;
522 } 531 }
523 532
524 calculateClipRectWithGeometryMapper(context, false, output); 533 calculateBackgroundClipRectWithGeometryMapper(context, output);
525 #ifdef CHECK_CLIP_RECTS 534 #ifdef CHECK_CLIP_RECTS
526 ClipRect testBackgroundClipRect = 535 ClipRect testBackgroundClipRect =
527 PaintLayerClipper(m_layer, nullptr).backgroundClipRect(context); 536 PaintLayerClipper(m_layer, nullptr).backgroundClipRect(context);
528 CHECK_RECTS_EQ(testBackgroundClipRect, output); 537 CHECK_RECTS_EQ(testBackgroundClipRect, output);
529 #endif 538 #endif
530 return; 539 return;
531 } 540 }
532 DCHECK(m_layer.parent()); 541 DCHECK(m_layer.parent());
533 LayoutView* layoutView = m_layer.layoutObject().view(); 542 LayoutView* layoutView = m_layer.layoutObject().view();
534 DCHECK(layoutView); 543 DCHECK(layoutView);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 DCHECK(!m_geometryMapper); 605 DCHECK(!m_geometryMapper);
597 ClipRectsContext context(rootLayer, PaintingClipRects, 606 ClipRectsContext context(rootLayer, PaintingClipRects,
598 IgnorePlatformOverlayScrollbarSize, 607 IgnorePlatformOverlayScrollbarSize,
599 subpixelAccumulation); 608 subpixelAccumulation);
600 if (respectOverflowClip == IgnoreOverflowClip) 609 if (respectOverflowClip == IgnoreOverflowClip)
601 context.setIgnoreOverflowClip(); 610 context.setIgnoreOverflowClip();
602 return getClipRects(context); 611 return getClipRects(context);
603 } 612 }
604 613
605 } // namespace blink 614 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698