OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |