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