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

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(
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);
414 PropertyTreeState sourcePropertyTreeState(nullptr, nullptr, nullptr);
415 PropertyTreeState destinationPropertyTreeState(nullptr, nullptr, nullptr);
416 initializeCommonClipRectState(context, sourcePropertyTreeState,
417 destinationPropertyTreeState);
418 const auto* ancestorProperties =
419 context.rootLayer->layoutObject().paintProperties();
420
421 if (&m_layer != context.rootLayer) {
422 // Set the clip of |destinationPropertyTreeState| to be inside the
423 // ancestor's overflow clip, so that that clip is not applied.
424 if (context.respectOverflowClip == IgnoreOverflowClip &&
425 ancestorProperties->overflowClip())
426 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip());
427 }
428
429 // The background rect applies all clips *above* m_layer, but not the overflow
430 // clip of m_layer. It also applies a clip to the total painting bounds
431 // of m_layer, because nothing in m_layer or its children within the clip can
432 // paint outside of those bounds.
433 // The total painting bounds includes any visual overflow (such as shadow) and
434 // filter bounds.
435 if (shouldClipOverflow(context)) {
436 FloatRect clipRect(localVisualRect());
437 clipRect.moveBy(FloatPoint(m_layer.layoutObject().paintOffset()));
438 m_geometryMapper->sourceToDestinationVisualRect(
439 sourcePropertyTreeState, destinationPropertyTreeState, clipRect);
440 output.setRect(FloatClipRect(clipRect));
441 } else {
442 const FloatClipRect& clippedRectInRootLayerSpace =
443 m_geometryMapper->sourceToDestinationClipRect(
444 sourcePropertyTreeState, destinationPropertyTreeState);
445 output.setRect(clippedRectInRootLayerSpace);
446 }
447
448 output.moveBy(-context.rootLayer->layoutObject().paintOffset());
449 }
450
451 void PaintLayerClipper::initializeCommonClipRectState(
452 const ClipRectsContext& context,
453 PropertyTreeState& sourcePropertyTreeState,
454 PropertyTreeState& destinationPropertyTreeState) const {
455 DCHECK(m_geometryMapper);
451 const auto* properties = m_layer.layoutObject().paintProperties(); 456 const auto* properties = m_layer.layoutObject().paintProperties();
452 DCHECK(properties && properties->localBorderBoxProperties()); 457 DCHECK(properties && properties->localBorderBoxProperties());
453 458
454 PropertyTreeState propertyTreeState = *properties->localBorderBoxProperties(); 459 sourcePropertyTreeState = *properties->localBorderBoxProperties();
455 const auto* ancestorProperties = 460 const auto* ancestorProperties =
456 context.rootLayer->layoutObject().paintProperties(); 461 context.rootLayer->layoutObject().paintProperties();
457 DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties()); 462 DCHECK(ancestorProperties && ancestorProperties->localBorderBoxProperties());
458 PropertyTreeState destinationPropertyTreeState = 463 destinationPropertyTreeState =
459 *ancestorProperties->localBorderBoxProperties(); 464 *ancestorProperties->localBorderBoxProperties();
460 // CSS clip of the root is always applied. 465 // CSS clip of the root is always applied.
461 if (ancestorProperties->cssClip()) { 466 if (ancestorProperties->cssClip()) {
462 DCHECK(destinationPropertyTreeState.clip() == 467 DCHECK(destinationPropertyTreeState.clip() ==
463 ancestorProperties->cssClip()); 468 ancestorProperties->cssClip());
464 destinationPropertyTreeState.setClip( 469 destinationPropertyTreeState.setClip(
465 ancestorProperties->cssClip()->parent()); 470 ancestorProperties->cssClip()->parent());
466 } 471 }
472 }
473
474 void PaintLayerClipper::calculateForegroundClipRectWithGeometryMapper(
475 const ClipRectsContext& context,
476 ClipRect& output) const {
477 DCHECK(m_geometryMapper);
478 PropertyTreeState sourcePropertyTreeState(nullptr, nullptr, nullptr);
479 PropertyTreeState destinationPropertyTreeState(nullptr, nullptr, nullptr);
480 initializeCommonClipRectState(context, sourcePropertyTreeState,
481 destinationPropertyTreeState);
482 const auto* properties = m_layer.layoutObject().paintProperties();
483 const auto* ancestorProperties =
484 context.rootLayer->layoutObject().paintProperties();
467 485
468 if (&m_layer == context.rootLayer) { 486 if (&m_layer == context.rootLayer) {
469 // Set the overflow clip for |propertyTreeState| so that it differs from 487 // Set the overflow clip for |sourcePropertyTreeState| so that it differs
470 // |destinationPropertyTreeState| in its clip. 488 // from |destinationPropertyTreeState| in its clip.
471 if (isForeground && context.respectOverflowClip == RespectOverflowClip && 489 if (context.respectOverflowClip == RespectOverflowClip &&
472 properties->overflowClip()) 490 properties->overflowClip())
473 propertyTreeState.setClip(properties->overflowClip()); 491 sourcePropertyTreeState.setClip(properties->overflowClip());
474 } else { 492 } else {
475 // Set the clip of |destinationPropertyTreeState| to be inside the 493 // Set the clip of |destinationPropertyTreeState| to be inside the
476 // ancestor's overflow clip, so that that clip is not applied. 494 // ancestor's overflow clip, so that that clip is not applied.
477 if (context.respectOverflowClip == IgnoreOverflowClip && 495 if (context.respectOverflowClip == IgnoreOverflowClip &&
478 ancestorProperties->overflowClip()) 496 ancestorProperties->overflowClip())
479 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip()); 497 destinationPropertyTreeState.setClip(ancestorProperties->overflowClip());
480 498
481 // Set the overflow clip for |propertyTreeState| so that it differs from 499 // Set the overflow clip for |sourcePropertyTreeState| so that it differs
482 // destinationPropertyTreeState| in its clip. 500 // from destinationPropertyTreeState| in its clip.
483 if (isForeground && properties->overflowClip()) 501 if (properties->overflowClip())
484 propertyTreeState.setClip(properties->overflowClip()); 502 sourcePropertyTreeState.setClip(properties->overflowClip());
485 } 503 }
486 504
487 const FloatClipRect& clippedRectInRootLayerSpace = 505 const FloatClipRect& clippedRectInRootLayerSpace =
488 m_geometryMapper->sourceToDestinationClipRect( 506 m_geometryMapper->sourceToDestinationClipRect(
489 propertyTreeState, destinationPropertyTreeState); 507 sourcePropertyTreeState, destinationPropertyTreeState);
490 output.setRect(clippedRectInRootLayerSpace); 508 output.setRect(clippedRectInRootLayerSpace);
491 509
492 output.moveBy(-context.rootLayer->layoutObject().paintOffset()); 510 output.moveBy(-context.rootLayer->layoutObject().paintOffset());
493 } 511 }
494 512
495 void PaintLayerClipper::applyOverflowClipToBackgroundRectWithGeometryMapper( 513 LayoutRect PaintLayerClipper::localVisualRect() const {
496 const ClipRectsContext& context,
497 ClipRect& clip) const {
498 const LayoutObject& layoutObject = m_layer.layoutObject(); 514 const LayoutObject& layoutObject = m_layer.layoutObject();
499 if (!shouldClipOverflow(context)) 515 // The LayoutView is special since its overflow clipping rect may be larger
500 return; 516 // than its box rect (crbug.com/492871).
501 LayoutRect layerBoundsWithVisualOverflow = 517 LayoutRect layerBoundsWithVisualOverflow =
502 layoutObject.isLayoutView() 518 layoutObject.isLayoutView()
503 ? toLayoutView(layoutObject).viewRect() 519 ? toLayoutView(layoutObject).viewRect()
504 : toLayoutBox(layoutObject).visualOverflowRect(); 520 : toLayoutBox(layoutObject).visualOverflowRect();
505 toLayoutBox(layoutObject) 521 toLayoutBox(layoutObject)
506 .flipForWritingMode( 522 .flipForWritingMode(
507 // PaintLayer are in physical coordinates, so the overflow has to be 523 // PaintLayer are in physical coordinates, so the overflow has to be
508 // flipped. 524 // flipped.
509 layerBoundsWithVisualOverflow); 525 layerBoundsWithVisualOverflow);
510 mapLocalToRootWithGeometryMapper(context, layerBoundsWithVisualOverflow); 526 if (m_layer.paintsWithFilters()) {
511 clip.intersect(layerBoundsWithVisualOverflow); 527 layerBoundsWithVisualOverflow =
528 m_layer.mapLayoutRectForFilter(layerBoundsWithVisualOverflow);
529 }
530 return layerBoundsWithVisualOverflow;
512 } 531 }
513 532
514 void PaintLayerClipper::calculateBackgroundClipRect( 533 void PaintLayerClipper::calculateBackgroundClipRect(
515 const ClipRectsContext& context, 534 const ClipRectsContext& context,
516 ClipRect& output) const { 535 ClipRect& output) const {
517 if (m_geometryMapper) { 536 if (m_geometryMapper) {
518 // TODO(chrishtr): fix the underlying bug that causes this situation. 537 // TODO(chrishtr): fix the underlying bug that causes this situation.
519 if (!m_layer.layoutObject().paintProperties()) { 538 if (!m_layer.layoutObject().paintProperties()) {
520 output.setRect(FloatClipRect()); 539 output.setRect(FloatClipRect());
521 return; 540 return;
522 } 541 }
523 542
524 calculateClipRectWithGeometryMapper(context, false, output); 543 calculateBackgroundClipRectWithGeometryMapper(context, output);
525 #ifdef CHECK_CLIP_RECTS 544 #ifdef CHECK_CLIP_RECTS
526 ClipRect testBackgroundClipRect = 545 ClipRect testBackgroundClipRect =
527 PaintLayerClipper(m_layer, nullptr).backgroundClipRect(context); 546 PaintLayerClipper(m_layer, nullptr).backgroundClipRect(context);
528 CHECK_RECTS_EQ(testBackgroundClipRect, output); 547 CHECK_RECTS_EQ(testBackgroundClipRect, output);
529 #endif 548 #endif
530 return; 549 return;
531 } 550 }
532 DCHECK(m_layer.parent()); 551 DCHECK(m_layer.parent());
533 LayoutView* layoutView = m_layer.layoutObject().view(); 552 LayoutView* layoutView = m_layer.layoutObject().view();
534 DCHECK(layoutView); 553 DCHECK(layoutView);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 DCHECK(!m_geometryMapper); 615 DCHECK(!m_geometryMapper);
597 ClipRectsContext context(rootLayer, PaintingClipRects, 616 ClipRectsContext context(rootLayer, PaintingClipRects,
598 IgnorePlatformOverlayScrollbarSize, 617 IgnorePlatformOverlayScrollbarSize,
599 subpixelAccumulation); 618 subpixelAccumulation);
600 if (respectOverflowClip == IgnoreOverflowClip) 619 if (respectOverflowClip == IgnoreOverflowClip)
601 context.setIgnoreOverflowClip(); 620 context.setIgnoreOverflowClip();
602 return getClipRects(context); 621 return getClipRects(context);
603 } 622 }
604 623
605 } // namespace blink 624 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698