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/BoxPainter.cpp

Issue 2464053003: Always paint background and shadow separately (Closed)
Patch Set: Rebaseline-cl (invisible pixel changes along shadow edges) (The original Patch Set 2 was removed to get the try result in Patch Set 1) 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/BoxPainter.h" 5 #include "core/paint/BoxPainter.h"
6 6
7 #include "core/HTMLNames.h" 7 #include "core/HTMLNames.h"
8 #include "core/frame/Settings.h" 8 #include "core/frame/Settings.h"
9 #include "core/html/HTMLFrameOwnerElement.h" 9 #include "core/html/HTMLFrameOwnerElement.h"
10 #include "core/layout/ImageQualityController.h" 10 #include "core/layout/ImageQualityController.h"
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 paintInfo.context, displayItemClient, 185 paintInfo.context, displayItemClient,
186 DisplayItem::kBoxDecorationBackground, 186 DisplayItem::kBoxDecorationBackground,
187 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset))); 187 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset)));
188 BoxDecorationData boxDecorationData(m_layoutBox); 188 BoxDecorationData boxDecorationData(m_layoutBox);
189 GraphicsContextStateSaver stateSaver(paintInfo.context, false); 189 GraphicsContextStateSaver stateSaver(paintInfo.context, false);
190 190
191 if (!paintingOverflowContents) { 191 if (!paintingOverflowContents) {
192 // FIXME: Should eventually give the theme control over whether the box 192 // FIXME: Should eventually give the theme control over whether the box
193 // shadow should paint, since controls could have custom shadows of their 193 // shadow should paint, since controls could have custom shadows of their
194 // own. 194 // own.
195 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground( 195 paintBoxShadow(paintInfo, paintRect, style, Normal);
196 boxDecorationData.bleedAvoidance)) {
197 paintBoxShadow(paintInfo, paintRect, style, Normal);
198 }
199 196
200 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) { 197 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) {
201 stateSaver.save(); 198 stateSaver.save();
202 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); 199 FloatRoundedRect border = style.getRoundedBorderFor(paintRect);
203 paintInfo.context.clipRoundedRect(border); 200 paintInfo.context.clipRoundedRect(border);
204 201
205 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer) 202 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer)
206 paintInfo.context.beginLayer(); 203 paintInfo.context.beginLayer();
207 } 204 }
208 } 205 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 return isNonAssociative; 291 return isNonAssociative;
295 } 292 }
296 293
297 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, 294 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo,
298 const Color& c, 295 const Color& c,
299 const FillLayer& fillLayer, 296 const FillLayer& fillLayer,
300 const LayoutRect& rect, 297 const LayoutRect& rect,
301 BackgroundBleedAvoidance bleedAvoidance, 298 BackgroundBleedAvoidance bleedAvoidance,
302 SkBlendMode op, 299 SkBlendMode op,
303 const LayoutObject* backgroundObject) { 300 const LayoutObject* backgroundObject) {
304 // TODO(trchen): Box shadow optimization and background color are concepts
305 // that only apply to background layers. Ideally we should refactor those out
306 // of paintFillLayer.
307 FillLayerOcclusionOutputList reversedPaintList; 301 FillLayerOcclusionOutputList reversedPaintList;
308 bool shouldDrawBackgroundInSeparateBuffer = false; 302 bool shouldDrawBackgroundInSeparateBuffer =
309 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) { 303 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer);
310 shouldDrawBackgroundInSeparateBuffer =
311 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer);
312 } else {
313 // If we are responsible for painting box shadow, don't perform fill layer
314 // culling.
315 // TODO(trchen): In theory we only need to make sure the last layer has
316 // border box clipping and make it paint the box shadow. Investigate
317 // optimization opportunity later.
318 for (auto currentLayer = &fillLayer; currentLayer;
319 currentLayer = currentLayer->next()) {
320 reversedPaintList.append(currentLayer);
321 if (currentLayer->composite() != CompositeSourceOver ||
322 currentLayer->blendMode() != WebBlendModeNormal)
323 shouldDrawBackgroundInSeparateBuffer = true;
324 }
325 }
326 304
327 // TODO(trchen): We can optimize out isolation group if we have a 305 // TODO(trchen): We can optimize out isolation group if we have a
328 // non-transparent background color and the bottom layer encloses all other 306 // non-transparent background color and the bottom layer encloses all other
329 // layers. 307 // layers.
330 308
331 GraphicsContext& context = paintInfo.context; 309 GraphicsContext& context = paintInfo.context;
332 310
333 if (shouldDrawBackgroundInSeparateBuffer) 311 if (shouldDrawBackgroundInSeparateBuffer)
334 context.beginLayer(); 312 context.beginLayer();
335 313
336 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); 314 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend();
337 ++it) 315 ++it)
338 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0, 316 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0,
339 LayoutSize(), op, backgroundObject); 317 LayoutSize(), op, backgroundObject);
340 318
341 if (shouldDrawBackgroundInSeparateBuffer) 319 if (shouldDrawBackgroundInSeparateBuffer)
342 context.endLayer(); 320 context.endLayer();
343 } 321 }
344 322
345 namespace { 323 namespace {
346 324
347 // RAII shadow helper.
348 class ShadowContext {
349 STACK_ALLOCATED();
350
351 public:
352 ShadowContext(GraphicsContext& context,
353 const LayoutObject& obj,
354 bool applyShadow)
355 : m_saver(context, applyShadow) {
356 if (!applyShadow)
357 return;
358
359 const ShadowList* shadowList = obj.style()->boxShadow();
360 DCHECK(shadowList);
361 for (size_t i = shadowList->shadows().size(); i--;) {
362 const ShadowData& boxShadow = shadowList->shadows()[i];
363 if (boxShadow.style() != Normal)
364 continue;
365 FloatSize shadowOffset(boxShadow.x(), boxShadow.y());
366 context.setShadow(
367 shadowOffset, boxShadow.blur(),
368 boxShadow.color().resolve(obj.resolveColor(CSSPropertyColor)),
369 DrawLooperBuilder::ShadowRespectsTransforms,
370 DrawLooperBuilder::ShadowIgnoresAlpha);
371 break;
372 }
373 }
374
375 private:
376 GraphicsContextStateSaver m_saver;
377 };
378
379 FloatRoundedRect getBackgroundRoundedRect(const LayoutObject& obj, 325 FloatRoundedRect getBackgroundRoundedRect(const LayoutObject& obj,
380 const LayoutRect& borderRect, 326 const LayoutRect& borderRect,
381 const InlineFlowBox* box, 327 const InlineFlowBox* box,
382 LayoutUnit inlineBoxWidth, 328 LayoutUnit inlineBoxWidth,
383 LayoutUnit inlineBoxHeight, 329 LayoutUnit inlineBoxHeight,
384 bool includeLogicalLeftEdge, 330 bool includeLogicalLeftEdge,
385 bool includeLogicalRightEdge) { 331 bool includeLogicalRightEdge) {
386 FloatRoundedRect border = obj.style()->getRoundedBorderFor( 332 FloatRoundedRect border = obj.style()->getRoundedBorderFor(
387 borderRect, includeLogicalLeftEdge, includeLogicalRightEdge); 333 borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
388 if (box && (box->nextLineBox() || box->prevLineBox())) { 334 if (box && (box->nextLineBox() || box->prevLineBox())) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge); 429 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge);
484 // BorderFillBox radius clipping is taken care of by 430 // BorderFillBox radius clipping is taken care of by
485 // BackgroundBleedClip{Only,Layer} 431 // BackgroundBleedClip{Only,Layer}
486 isRoundedFill = hasRoundedBorder && 432 isRoundedFill = hasRoundedBorder &&
487 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance)); 433 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance));
488 434
489 shouldPaintImage = image && image->canRender(); 435 shouldPaintImage = image && image->canRender();
490 shouldPaintColor = 436 shouldPaintColor =
491 isBottomLayer && color.alpha() && 437 isBottomLayer && color.alpha() &&
492 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj)); 438 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj));
493 shouldPaintShadow =
494 shouldPaintColor &&
495 obj.boxShadowShouldBeAppliedToBackground(bleedAvoidance, box);
496 } 439 }
497 440
498 // FillLayerInfo is a temporary, stack-allocated container which cannot 441 // FillLayerInfo is a temporary, stack-allocated container which cannot
499 // outlive the StyleImage. This would normally be a raw pointer, if not for 442 // outlive the StyleImage. This would normally be a raw pointer, if not for
500 // the Oilpan tooling complaints. 443 // the Oilpan tooling complaints.
501 Member<StyleImage> image; 444 Member<StyleImage> image;
502 Color color; 445 Color color;
503 446
504 bool includeLeftEdge; 447 bool includeLeftEdge;
505 bool includeRightEdge; 448 bool includeRightEdge;
506 bool isBottomLayer; 449 bool isBottomLayer;
507 bool isBorderFill; 450 bool isBorderFill;
508 bool isClippedWithLocalScrolling; 451 bool isClippedWithLocalScrolling;
509 bool isRoundedFill; 452 bool isRoundedFill;
510 453
511 bool shouldPaintImage; 454 bool shouldPaintImage;
512 bool shouldPaintColor; 455 bool shouldPaintColor;
513 bool shouldPaintShadow;
514 }; 456 };
515 457
516 // RAII image paint helper. 458 // RAII image paint helper.
517 class ImagePaintContext { 459 class ImagePaintContext {
518 STACK_ALLOCATED(); 460 STACK_ALLOCATED();
519 461
520 public: 462 public:
521 ImagePaintContext(const LayoutBoxModelObject& obj, 463 ImagePaintContext(const LayoutBoxModelObject& obj,
522 GraphicsContext& context, 464 GraphicsContext& context,
523 const FillLayer& layer, 465 const FillLayer& layer,
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 563
622 Optional<RoundedInnerRectClipper> clipper; 564 Optional<RoundedInnerRectClipper> clipper;
623 if (info.isRoundedFill && !border.isRenderable()) { 565 if (info.isRoundedFill && !border.isRenderable()) {
624 // When the rrect is not renderable, we resort to clipping. 566 // When the rrect is not renderable, we resort to clipping.
625 // RoundedInnerRectClipper handles this case via discrete, corner-wise 567 // RoundedInnerRectClipper handles this case via discrete, corner-wise
626 // clipping. 568 // clipping.
627 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext); 569 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext);
628 border.setRadii(FloatRoundedRect::Radii()); 570 border.setRadii(FloatRoundedRect::Radii());
629 } 571 }
630 572
631 // Paint the color + shadow if needed. 573 // Paint the color if needed.
632 if (info.shouldPaintColor) { 574 if (info.shouldPaintColor)
633 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow);
634 context.fillRoundedRect(border, info.color); 575 context.fillRoundedRect(border, info.color);
635 }
636 576
637 // Paint the image + shadow if needed. 577 // Paint the image if needed.
638 if (!info.shouldPaintImage || imageTile.isEmpty()) 578 if (!info.shouldPaintImage || imageTile.isEmpty())
639 return true; 579 return true;
640 580
641 const ImagePaintContext imageContext(obj, context, layer, *info.image, op, 581 const ImagePaintContext imageContext(obj, context, layer, *info.image, op,
642 backgroundObject, geometry->tileSize()); 582 backgroundObject, geometry->tileSize());
643 if (!imageContext.image()) 583 if (!imageContext.image())
644 return true; 584 return true;
645 585
646 const FloatSize intrinsicTileSize = 586 const FloatSize intrinsicTileSize =
647 imageContext.image()->hasRelativeSize() 587 imageContext.image()->hasRelativeSize()
648 ? imageTile.size() 588 ? imageTile.size()
649 : FloatSize(imageContext.image()->size()); 589 : FloatSize(imageContext.image()->size());
650 const FloatRect srcRect = 590 const FloatRect srcRect =
651 Image::computeSubsetForTile(imageTile, border.rect(), intrinsicTileSize); 591 Image::computeSubsetForTile(imageTile, border.rect(), intrinsicTileSize);
652 592
653 // The shadow may have been applied with the color fill.
654 const ShadowContext shadowContext(
655 context, obj, info.shouldPaintShadow && !info.shouldPaintColor);
656 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", 593 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
657 "data", InspectorPaintImageEvent::data(obj, *info.image)); 594 "data", InspectorPaintImageEvent::data(obj, *info.image));
658 context.drawImageRRect(imageContext.image(), border, srcRect, 595 context.drawImageRRect(imageContext.image(), border, srcRect,
659 imageContext.compositeOp()); 596 imageContext.compositeOp());
660 597
661 updatePreferredRasterBoundsFromImage(srcRect, border.rect(), obj); 598 updatePreferredRasterBoundsFromImage(srcRect, border.rect(), obj);
662 599
663 return true; 600 return true;
664 } 601 }
665 602
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 default: 725 default:
789 ASSERT_NOT_REACHED(); 726 ASSERT_NOT_REACHED();
790 break; 727 break;
791 } 728 }
792 729
793 // Paint the color first underneath all images, culled if background image 730 // Paint the color first underneath all images, culled if background image
794 // occludes it. 731 // occludes it.
795 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the 732 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the
796 // culling test by verifying whether the background image covers the entire 733 // culling test by verifying whether the background image covers the entire
797 // painting area. 734 // painting area.
798 if (info.isBottomLayer && info.color.alpha()) { 735 if (info.isBottomLayer && info.color.alpha() && info.shouldPaintColor) {
799 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); 736 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
800 if (info.shouldPaintColor || info.shouldPaintShadow) { 737 context.fillRect(backgroundRect, info.color);
801 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow);
802 context.fillRect(backgroundRect, info.color);
803 }
804 } 738 }
805 739
806 // no progressive loading of the background image 740 // no progressive loading of the background image
807 if (info.shouldPaintImage) { 741 if (info.shouldPaintImage) {
808 if (!geometry) { 742 if (!geometry) {
809 geometry.emplace(); 743 geometry.emplace();
810 geometry->calculate(obj, paintInfo.paintContainer(), 744 geometry->calculate(obj, paintInfo.paintContainer(),
811 paintInfo.getGlobalPaintFlags(), bgLayer, 745 paintInfo.getGlobalPaintFlags(), bgLayer,
812 scrolledPaintRect); 746 scrolledPaintRect);
813 } else { 747 } else {
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy( 1044 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(
1111 const ComputedStyle& style, 1045 const ComputedStyle& style,
1112 const Document& document) { 1046 const Document& document) {
1113 return document.printing() && 1047 return document.printing() &&
1114 style.getPrintColorAdjust() == PrintColorAdjustEconomy && 1048 style.getPrintColorAdjust() == PrintColorAdjustEconomy &&
1115 (!document.settings() || 1049 (!document.settings() ||
1116 !document.settings()->shouldPrintBackgrounds()); 1050 !document.settings()->shouldPrintBackgrounds());
1117 } 1051 }
1118 1052
1119 } // namespace blink 1053 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698