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

Side by Side Diff: Source/core/paint/BoxPainter.cpp

Issue 1145993002: Refactor root element background painting (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase, adding back TestExpectation Created 5 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/paint/BoxPainter.h ('k') | Source/core/paint/DisplayItemListPaintTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "config.h" 5 #include "config.h"
6 #include "core/paint/BoxPainter.h" 6 #include "core/paint/BoxPainter.h"
7 7
8 #include "core/HTMLNames.h" 8 #include "core/HTMLNames.h"
9 #include "core/frame/Settings.h" 9 #include "core/frame/Settings.h"
10 #include "core/html/HTMLFrameOwnerElement.h" 10 #include "core/html/HTMLFrameOwnerElement.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 LayoutRect paintRect = m_layoutBox.borderBoxRect(); 54 LayoutRect paintRect = m_layoutBox.borderBoxRect();
55 paintRect.moveBy(paintOffset); 55 paintRect.moveBy(paintOffset);
56 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); 56 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
57 } 57 }
58 58
59 LayoutRect BoxPainter::boundsForDrawingRecorder(const LayoutPoint& paintOffset) 59 LayoutRect BoxPainter::boundsForDrawingRecorder(const LayoutPoint& paintOffset)
60 { 60 {
61 if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) 61 if (!RuntimeEnabledFeatures::slimmingPaintEnabled())
62 return LayoutRect(); 62 return LayoutRect();
63 63
64 // The document element is specified to paint its background infinitely.
65 if (m_layoutBox.isDocumentElement())
66 return rootBackgroundRect();
67
68 // Use the visual overflow rect here, because it will include overflow intro duced by the theme. 64 // Use the visual overflow rect here, because it will include overflow intro duced by the theme.
69 LayoutRect bounds = m_layoutBox.visualOverflowRect(); 65 LayoutRect bounds = m_layoutBox.visualOverflowRect();
70 bounds.moveBy(paintOffset); 66 bounds.moveBy(paintOffset);
71 return LayoutRect(pixelSnappedIntRect(bounds)); 67 return LayoutRect(pixelSnappedIntRect(bounds));
72 } 68 }
73 69
74 LayoutRect BoxPainter::rootBackgroundRect()
75 {
76 LayoutView* layoutView = m_layoutBox.view();
77 LayoutRect result = layoutView->backgroundRect(&m_layoutBox);
78 // In root-layer-scrolls mode, root background is painted in coordinates of the
79 // root scrolling contents layer, so don't need scroll offset adjustment.
80 if (layoutView->hasOverflowClip() && !layoutView->frame()->settings()->rootL ayerScrolls())
81 result.move(-layoutView->scrolledContentOffset());
82 return result;
83 }
84
85 namespace { 70 namespace {
86 71
87 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance) 72 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance)
88 { 73 {
89 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr oundBleedClipLayer; 74 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr oundBleedClipLayer;
90 } 75 }
91 76
92 } // anonymous namespace 77 } // anonymous namespace
93 78
94 void BoxPainter::paintBoxDecorationBackgroundWithRect(const PaintInfo& paintInfo , const LayoutPoint& paintOffset, const LayoutRect& paintRect) 79 void BoxPainter::paintBoxDecorationBackgroundWithRect(const PaintInfo& paintInfo , const LayoutPoint& paintOffset, const LayoutRect& paintRect)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 // The theme will tell us whether or not we should also paint the CSS border . 127 // The theme will tell us whether or not we should also paint the CSS border .
143 if (boxDecorationData.hasBorderDecoration && boxDecorationData.bleedAvoidanc e != BackgroundBleedBackgroundOverBorder 128 if (boxDecorationData.hasBorderDecoration && boxDecorationData.bleedAvoidanc e != BackgroundBleedBackgroundOverBorder
144 && (!boxDecorationData.hasAppearance || (!themePainted && LayoutTheme::t heme().painter().paintBorderOnly(&m_layoutBox, paintInfo, snappedPaintRect))) 129 && (!boxDecorationData.hasAppearance || (!themePainted && LayoutTheme::t heme().painter().paintBorderOnly(&m_layoutBox, paintInfo, snappedPaintRect)))
145 && !(m_layoutBox.isTable() && toLayoutTable(&m_layoutBox)->collapseBorde rs())) 130 && !(m_layoutBox.isTable() && toLayoutTable(&m_layoutBox)->collapseBorde rs()))
146 paintBorder(m_layoutBox, paintInfo, paintRect, style, boxDecorationData. bleedAvoidance); 131 paintBorder(m_layoutBox, paintInfo, paintRect, style, boxDecorationData. bleedAvoidance);
147 132
148 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer) 133 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer)
149 paintInfo.context->endLayer(); 134 paintInfo.context->endLayer();
150 } 135 }
151 136
152 static bool skipBodyBackground(const LayoutBox* bodyElementLayoutObject)
153 {
154 ASSERT(bodyElementLayoutObject->isBody());
155 // The <body> only paints its background if the root element has defined a b ackground independent of the body,
156 // or if the <body>'s parent is not the document element's layoutObject (e.g . inside SVG foreignObject).
157 LayoutObject* documentElementLayoutObject = bodyElementLayoutObject->documen t().documentElement()->layoutObject();
158 return documentElementLayoutObject
159 && !documentElementLayoutObject->hasBackground()
160 && (documentElementLayoutObject == bodyElementLayoutObject->parent());
161 }
162
163 void BoxPainter::paintBackground(const PaintInfo& paintInfo, const LayoutRect& p aintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance) 137 void BoxPainter::paintBackground(const PaintInfo& paintInfo, const LayoutRect& p aintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance)
164 { 138 {
165 if (m_layoutBox.isDocumentElement()) { 139 if (m_layoutBox.isDocumentElement())
166 paintRootBoxFillLayers(paintInfo);
167 return; 140 return;
168 } 141 if (m_layoutBox.backgroundStolenForBeingBody())
169 if (m_layoutBox.isBody() && skipBodyBackground(&m_layoutBox))
170 return; 142 return;
171 if (m_layoutBox.boxDecorationBackgroundIsKnownToBeObscured()) 143 if (m_layoutBox.boxDecorationBackgroundIsKnownToBeObscured())
172 return; 144 return;
173 paintFillLayers(paintInfo, backgroundColor, m_layoutBox.style()->backgroundL ayers(), paintRect, bleedAvoidance); 145 paintFillLayers(paintInfo, backgroundColor, m_layoutBox.style()->backgroundL ayers(), paintRect, bleedAvoidance);
174 } 146 }
175 147
176 void BoxPainter::paintRootBoxFillLayers(const PaintInfo& paintInfo) 148 static bool isFillLayerOpaque(const FillLayer& layer, const LayoutObject& imageC lient)
177 { 149 {
178 if (paintInfo.skipRootBackground()) 150 return layer.hasOpaqueImage(&imageClient)
179 return; 151 && layer.image()->canRender(imageClient, imageClient.style()->effectiveZ oom())
180 152 && !layer.image()->imageSize(&imageClient, imageClient.style()->effectiv eZoom()).isEmpty()
181 LayoutObject* rootBackgroundLayoutObject = m_layoutBox.layoutObjectForRootBa ckground(); 153 && layer.hasRepeatXY();
182
183 const FillLayer& bgLayer = rootBackgroundLayoutObject->style()->backgroundLa yers();
184 Color bgColor = rootBackgroundLayoutObject->resolveColor(CSSPropertyBackgrou ndColor);
185
186 paintFillLayers(paintInfo, bgColor, bgLayer, rootBackgroundRect(), Backgroun dBleedNone, SkXfermode::kSrcOver_Mode, rootBackgroundLayoutObject);
187 } 154 }
188 155
189 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, con st FillLayer& fillLayer, const LayoutRect& rect, 156 bool BoxPainter::calculateFillLayerOcclusionCulling(FillLayerOcclusionOutputList &reversedPaintList, const FillLayer& fillLayer)
190 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject* backgroundObject)
191 { 157 {
192 Vector<const FillLayer*, 8> layers; 158 bool isNonAssociative = false;
193 const FillLayer* curLayer = &fillLayer; 159 for (auto currentLayer = &fillLayer; currentLayer; currentLayer = currentLay er->next()) {
194 bool shouldDrawBackgroundInSeparateBuffer = false; 160 reversedPaintList.append(currentLayer);
195 bool isBottomLayerOccluded = false;
196 while (curLayer) {
197 layers.append(curLayer);
198 // Stop traversal when an opaque layer is encountered. 161 // Stop traversal when an opaque layer is encountered.
199 // FIXME : It would be possible for the following occlusion culling test to be more aggressive 162 // FIXME : It would be possible for the following occlusion culling test to be more aggressive
200 // on layers with no repeat by testing whether the image covers the layo ut rect. 163 // on layers with no repeat by testing whether the image covers the layo ut rect.
201 // Testing that here would imply duplicating a lot of calculations that are currently done in 164 // Testing that here would imply duplicating a lot of calculations that are currently done in
202 // LayoutBoxModelObject::paintFillLayerExtended. A more efficient soluti on might be to move 165 // LayoutBoxModelObject::paintFillLayerExtended. A more efficient soluti on might be to move
203 // the layer recursion into paintFillLayerExtended, or to compute the la yer geometry here 166 // the layer recursion into paintFillLayerExtended, or to compute the la yer geometry here
204 // and pass it down. 167 // and pass it down.
205 168
206 if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != We bBlendModeNormal) 169 // TODO(trchen): Need to check compositing mode as well.
207 shouldDrawBackgroundInSeparateBuffer = true; 170 if (currentLayer->blendMode() != WebBlendModeNormal)
171 isNonAssociative = true;
208 172
209 if (curLayer->clipOccludesNextLayers() 173 // TODO(trchen): A fill layer cannot paint if the calculated tile size i s empty.
210 && curLayer->hasOpaqueImage(&m_layoutBox) 174 // This occlusion check can be wrong.
211 && curLayer->image()->canRender(m_layoutBox, m_layoutBox.style()->ef fectiveZoom()) 175 if (currentLayer->clipOccludesNextLayers()
212 && curLayer->hasRepeatXY() 176 && isFillLayerOpaque(*currentLayer, m_layoutBox)) {
213 && curLayer->blendMode() == WebBlendModeNormal 177 if (currentLayer->clip() == BorderFillBox)
214 && !m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance) ) 178 isNonAssociative = false;
215 break; 179 break;
216 curLayer = curLayer->next(); 180 }
181 }
182 return isNonAssociative;
183 }
184
185 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, con st FillLayer& fillLayer, const LayoutRect& rect, BackgroundBleedAvoidance bleedA voidance, SkXfermode::Mode op, LayoutObject* backgroundObject)
186 {
187 // TODO(trchen): Box shadow optimization and background color are concepts t hat only
188 // apply to background layers. Ideally we should refactor those out of paint FillLayer.
189 FillLayerOcclusionOutputList reversedPaintList;
190 bool shouldDrawBackgroundInSeparateBuffer = false;
191 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) {
192 shouldDrawBackgroundInSeparateBuffer = calculateFillLayerOcclusionCullin g(reversedPaintList, fillLayer);
193 } else {
194 // If we are responsible for painting box shadow, don't perform fill lay er culling.
195 // TODO(trchen): In theory we only need to make sure the last layer has border box clipping
196 // and make it paint the box shadow. Investigate optimization opportunit y later.
197 for (auto currentLayer = &fillLayer; currentLayer; currentLayer = curren tLayer->next()) {
198 reversedPaintList.append(currentLayer);
199 if (currentLayer->composite() != CompositeSourceOver || currentLayer ->blendMode() != WebBlendModeNormal)
200 shouldDrawBackgroundInSeparateBuffer = true;
201 }
217 } 202 }
218 203
219 if (layers.size() > 0 && (**layers.rbegin()).next()) 204 // TODO(trchen): We can optimize out isolation group if we have a non-transp arent
220 isBottomLayerOccluded = true; 205 // background color and the bottom layer encloses all other layers.
221 206
222 GraphicsContext* context = paintInfo.context; 207 GraphicsContext* context = paintInfo.context;
223 if (!context) 208 if (!context)
224 shouldDrawBackgroundInSeparateBuffer = false; 209 shouldDrawBackgroundInSeparateBuffer = false;
225 210
226 bool skipBaseColor = false; 211 if (shouldDrawBackgroundInSeparateBuffer)
227 if (shouldDrawBackgroundInSeparateBuffer) { 212 context->beginLayer();
228 bool isBaseColorVisible = !isBottomLayerOccluded && c.hasAlpha();
229 213
230 // Paint the document's base background color outside the transparency l ayer, 214 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); + +it)
231 // so that the background images don't blend with this color: http://crb ug.com/389039. 215 paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundO bject);
232 if (isBaseColorVisible && isDocumentElementWithOpaqueBackground(m_layout Box)) {
233 paintRootBackgroundColor(m_layoutBox, paintInfo, rect, Color());
234 skipBaseColor = true;
235 }
236 context->beginLayer();
237 }
238
239 Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
240 for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
241 paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundO bject, skipBaseColor);
242 216
243 if (shouldDrawBackgroundInSeparateBuffer) 217 if (shouldDrawBackgroundInSeparateBuffer)
244 context->endLayer(); 218 context->endLayer();
245 } 219 }
246 220
247 void BoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, cons t FillLayer& fillLayer, const LayoutRect& rect, 221 void BoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, cons t FillLayer& fillLayer, const LayoutRect& rect,
248 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject* backgroundObject, bool skipBaseColor) 222 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject* backgroundObject)
249 { 223 {
250 BoxPainter::paintFillLayerExtended(m_layoutBox, paintInfo, c, fillLayer, rec t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, skipBaseColor); 224 BoxPainter::paintFillLayerExtended(m_layoutBox, paintInfo, c, fillLayer, rec t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
251 } 225 }
252 226
253 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj ect& obj) 227 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj ect& obj)
254 { 228 {
255 const ShadowList* shadowList = obj.style()->boxShadow(); 229 const ShadowList* shadowList = obj.style()->boxShadow();
256 ASSERT(shadowList); 230 ASSERT(shadowList);
257 for (size_t i = shadowList->shadows().size(); i--; ) { 231 for (size_t i = shadowList->shadows().size(); i--; ) {
258 const ShadowData& boxShadow = shadowList->shadows()[i]; 232 const ShadowData& boxShadow = shadowList->shadows()[i];
259 if (boxShadow.style() != Normal) 233 if (boxShadow.style() != Normal)
260 continue; 234 continue;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 FloatRoundedRect::Radii insetRadii(backgroundRoundedRect.radii()); 288 FloatRoundedRect::Radii insetRadii(backgroundRoundedRect.radii());
315 insetRadii.shrink(-insets.top(), -insets.bottom(), -insets.left(), -inse ts.right()); 289 insetRadii.shrink(-insets.top(), -insets.bottom(), -insets.left(), -inse ts.right());
316 return FloatRoundedRect(insetRect, insetRadii); 290 return FloatRoundedRect(insetRect, insetRadii);
317 } 291 }
318 if (bleedAvoidance == BackgroundBleedBackgroundOverBorder) 292 if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
319 return obj.style()->getRoundedInnerBorderFor(borderRect, includeLogicalL eftEdge, includeLogicalRightEdge); 293 return obj.style()->getRoundedInnerBorderFor(borderRect, includeLogicalL eftEdge, includeLogicalRightEdge);
320 294
321 return getBackgroundRoundedRect(obj, borderRect, box, boxSize.width(), boxSi ze.height(), includeLogicalLeftEdge, includeLogicalRightEdge); 295 return getBackgroundRoundedRect(obj, borderRect, box, boxSize.width(), boxSi ze.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
322 } 296 }
323 297
324 void BoxPainter::paintFillLayerExtended(LayoutBoxModelObject& obj, const PaintIn fo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& r ect, 298 void BoxPainter::paintFillLayerExtended(LayoutBoxModelObject& obj, const PaintIn fo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& r ect, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSi ze& boxSize, SkXfermode::Mode op, LayoutObject* backgroundObject)
325 BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSiz e& boxSize, SkXfermode::Mode op, LayoutObject* backgroundObject, bool skipBaseCo lor)
326 { 299 {
327 GraphicsContext* context = paintInfo.context; 300 GraphicsContext* context = paintInfo.context;
328 if (rect.isEmpty()) 301 if (rect.isEmpty())
329 return; 302 return;
330 303
331 bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true; 304 bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true;
332 bool includeRightEdge = box ? box->includeLogicalRightEdge() : true; 305 bool includeRightEdge = box ? box->includeLogicalRightEdge() : true;
333 306
334 bool hasRoundedBorder = obj.style()->hasBorderRadius() && (includeLeftEdge | | includeRightEdge); 307 bool hasRoundedBorder = obj.style()->hasBorderRadius() && (includeLeftEdge | | includeRightEdge);
335 bool clippedWithLocalScrolling = obj.hasOverflowClip() && bgLayer.attachment () == LocalBackgroundAttachment; 308 bool clippedWithLocalScrolling = obj.hasOverflowClip() && bgLayer.attachment () == LocalBackgroundAttachment;
336 bool isBorderFill = bgLayer.clip() == BorderFillBox; 309 bool isBorderFill = bgLayer.clip() == BorderFillBox;
337 bool isDocumentElementLayoutObject = obj.isDocumentElement();
338 bool isBottomLayer = !bgLayer.next(); 310 bool isBottomLayer = !bgLayer.next();
339 311
340 Color bgColor = color; 312 Color bgColor = color;
341 StyleImage* bgImage = bgLayer.image(); 313 StyleImage* bgImage = bgLayer.image();
342 bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(obj, obj.sty le()->effectiveZoom());
343 314
344 bool forceBackgroundToWhite = false; 315 bool forceBackgroundToWhite = false;
345 if (obj.document().printing()) { 316 if (obj.document().printing()) {
346 if (obj.style()->printColorAdjust() == PrintColorAdjustEconomy) 317 if (obj.style()->printColorAdjust() == PrintColorAdjustEconomy)
347 forceBackgroundToWhite = true; 318 forceBackgroundToWhite = true;
348 if (obj.document().settings() && obj.document().settings()->shouldPrintB ackgrounds()) 319 if (obj.document().settings() && obj.document().settings()->shouldPrintB ackgrounds())
349 forceBackgroundToWhite = false; 320 forceBackgroundToWhite = false;
350 } 321 }
351 322
352 // When printing backgrounds is disabled or using economy mode, 323 // When printing backgrounds is disabled or using economy mode,
353 // change existing background colors and images to a solid white background. 324 // change existing background colors and images to a solid white background.
354 // If there's no bg color or image, leave it untouched to avoid affecting tr ansparency. 325 // If there's no bg color or image, leave it untouched to avoid affecting tr ansparency.
355 // We don't try to avoid loading the background images, because this style f lag is only set 326 // We don't try to avoid loading the background images, because this style f lag is only set
356 // when printing, and at that point we've already loaded the background imag es anyway. (To avoid 327 // when printing, and at that point we've already loaded the background imag es anyway. (To avoid
357 // loading the background images we'd have to do this check when applying st yles rather than 328 // loading the background images we'd have to do this check when applying st yles rather than
358 // while layout.) 329 // while layout.)
359 if (forceBackgroundToWhite) { 330 if (forceBackgroundToWhite) {
360 // Note that we can't reuse this variable below because the bgColor migh t be changed 331 // Note that we can't reuse this variable below because the bgColor migh t be changed
361 bool shouldPaintBackgroundColor = isBottomLayer && bgColor.alpha(); 332 bool shouldPaintBackgroundColor = isBottomLayer && bgColor.alpha();
362 if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) { 333 if (bgImage || shouldPaintBackgroundColor) {
363 bgColor = Color::white; 334 bgColor = Color::white;
364 shouldPaintBackgroundImage = false; 335 bgImage = nullptr;
365 } 336 }
366 } 337 }
367 338
368 bool colorVisible = bgColor.alpha();
369
370 // Fast path for drawing simple color backgrounds. 339 // Fast path for drawing simple color backgrounds.
371 if (!isDocumentElementLayoutObject && !clippedWithLocalScrolling && !shouldP aintBackgroundImage && isBorderFill && isBottomLayer) { 340 if (!clippedWithLocalScrolling && !bgImage && isBorderFill && isBottomLayer) {
372 if (!colorVisible) 341 if (!bgColor.alpha())
373 return; 342 return;
374 343
375 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); 344 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box);
376 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAp pliedToBackground); 345 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAp pliedToBackground);
377 if (boxShadowShouldBeAppliedToBackground) 346 if (boxShadowShouldBeAppliedToBackground)
378 BoxPainter::applyBoxShadowForBackground(context, obj); 347 BoxPainter::applyBoxShadowForBackground(context, obj);
379 348
380 if (hasRoundedBorder && !bleedAvoidanceIsClipping(bleedAvoidance)) { 349 if (hasRoundedBorder && !bleedAvoidanceIsClipping(bleedAvoidance)) {
381 FloatRoundedRect border = backgroundRoundedRectAdjustedForBleedAvoid ance(obj, rect, 350 FloatRoundedRect border = backgroundRoundedRectAdjustedForBleedAvoid ance(obj, rect,
382 bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) ; 351 bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) ;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 441
473 break; 442 break;
474 } 443 }
475 case BorderFillBox: 444 case BorderFillBox:
476 break; 445 break;
477 default: 446 default:
478 ASSERT_NOT_REACHED(); 447 ASSERT_NOT_REACHED();
479 break; 448 break;
480 } 449 }
481 450
451 BackgroundImageGeometry geometry;
452 if (bgImage)
453 calculateBackgroundImageGeometry(obj, paintInfo.paintContainer(), bgLaye r, scrolledPaintRect, geometry, backgroundObject);
454 bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(obj, obj.sty le()->effectiveZoom());
455
482 // Paint the color first underneath all images, culled if background image o ccludes it. 456 // Paint the color first underneath all images, culled if background image o ccludes it.
483 // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culli ng test 457 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the cu lling test
484 // by verifying whether the background image covers the entire layout rect. 458 // by verifying whether the background image covers the entire painting area .
485 if (isBottomLayer) { 459 if (isBottomLayer) {
486 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); 460 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
487 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); 461 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box);
488 bool isOpaqueRoot = (isDocumentElementLayoutObject && !bgColor.hasAlpha( )) || isDocumentElementWithOpaqueBackground(obj); 462 bool backgroundImageOccludesBackgroundColor = shouldPaintBackgroundImage && isFillLayerOpaque(bgLayer, obj);
489 if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer.hasOpaqueImage(&obj) || !bgLayer.hasRepeatXY() || (isOpaqueRoot && ! toLayoutBox(&obj)->size().height())) { 463 if (boxShadowShouldBeAppliedToBackground || !backgroundImageOccludesBack groundColor) {
490 if (!RuntimeEnabledFeatures::slimmingPaintEnabled() && !boxShadowSho uldBeAppliedToBackground) 464 if (!RuntimeEnabledFeatures::slimmingPaintEnabled() && !boxShadowSho uldBeAppliedToBackground)
491 backgroundRect.intersect(paintInfo.rect); 465 backgroundRect.intersect(paintInfo.rect);
492 466
493 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould BeAppliedToBackground); 467 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould BeAppliedToBackground);
494 if (boxShadowShouldBeAppliedToBackground) 468 if (boxShadowShouldBeAppliedToBackground)
495 BoxPainter::applyBoxShadowForBackground(context, obj); 469 BoxPainter::applyBoxShadowForBackground(context, obj);
496 470
497 if (isOpaqueRoot && !skipBaseColor) { 471 if (bgColor.alpha())
498 paintRootBackgroundColor(obj, paintInfo, rect, bgColor);
499 } else if (bgColor.alpha()) {
500 context->fillRect(backgroundRect, bgColor); 472 context->fillRect(backgroundRect, bgColor);
501 }
502 } 473 }
503 } 474 }
504 475
505 // no progressive loading of the background image 476 // no progressive loading of the background image
506 if (shouldPaintBackgroundImage) { 477 if (shouldPaintBackgroundImage) {
507 BackgroundImageGeometry geometry;
508 calculateBackgroundImageGeometry(obj, paintInfo.paintContainer(), bgLaye r, scrolledPaintRect, geometry, backgroundObject);
509 if (!geometry.destRect().isEmpty()) { 478 if (!geometry.destRect().isEmpty()) {
510 SkXfermode::Mode bgOp = WebCoreCompositeToSkiaComposite(bgLayer.comp osite(), bgLayer.blendMode()); 479 SkXfermode::Mode bgOp = WebCoreCompositeToSkiaComposite(bgLayer.comp osite(), bgLayer.blendMode());
511 // if op != SkXfermode::kSrcOver_Mode, a mask is being painted. 480 // if op != SkXfermode::kSrcOver_Mode, a mask is being painted.
512 SkXfermode::Mode compositeOp = op == SkXfermode::kSrcOver_Mode ? bgO p : op; 481 SkXfermode::Mode compositeOp = op == SkXfermode::kSrcOver_Mode ? bgO p : op;
513 LayoutObject* clientForBackgroundImage = backgroundObject ? backgrou ndObject : &obj; 482 LayoutObject* clientForBackgroundImage = backgroundObject ? backgrou ndObject : &obj;
514 RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geome try.tileSize()); 483 RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geome try.tileSize());
515 InterpolationQuality interpolationQuality = chooseInterpolationQuali ty(*clientForBackgroundImage, context, image.get(), &bgLayer, LayoutSize(geometr y.tileSize())); 484 InterpolationQuality interpolationQuality = chooseInterpolationQuali ty(*clientForBackgroundImage, context, image.get(), &bgLayer, LayoutSize(geometr y.tileSize()));
516 if (bgLayer.maskSourceType() == MaskLuminance) 485 if (bgLayer.maskSourceType() == MaskLuminance)
517 context->setColorFilter(ColorFilterLuminanceToAlpha); 486 context->setColorFilter(ColorFilterLuminanceToAlpha);
518 InterpolationQuality previousInterpolationQuality = context->imageIn terpolationQuality(); 487 InterpolationQuality previousInterpolationQuality = context->imageIn terpolationQuality();
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return; 569 return;
601 570
602 IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset, m_layoutBox. size())); 571 IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset, m_layoutBox. size()));
603 LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutBox, paintInfo.phase, paintRect); 572 LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutBox, paintInfo.phase, paintRect);
604 if (drawingRecorder.canUseCachedDrawing()) 573 if (drawingRecorder.canUseCachedDrawing())
605 return; 574 return;
606 575
607 paintInfo.context->fillRect(paintRect, Color::black); 576 paintInfo.context->fillRect(paintRect, Color::black);
608 } 577 }
609 578
610 void BoxPainter::paintRootBackgroundColor(LayoutObject& obj, const PaintInfo& pa intInfo, const LayoutRect& rootBackgroundRect, const Color& bgColor)
611 {
612 if (rootBackgroundRect.isEmpty())
613 return;
614
615 ASSERT(obj.isDocumentElement());
616
617 IntRect backgroundRect(pixelSnappedIntRect(rootBackgroundRect));
618 if (!RuntimeEnabledFeatures::slimmingPaintEnabled())
619 backgroundRect.intersect(paintInfo.rect);
620
621 Color baseColor = obj.view()->frameView()->baseBackgroundColor();
622 bool shouldClearDocumentBackground = obj.document().settings() && obj.docume nt().settings()->shouldClearDocumentBackground();
623 SkXfermode::Mode operation = shouldClearDocumentBackground ?
624 SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode;
625
626 GraphicsContext* context = paintInfo.context;
627
628 // If we have an alpha go ahead and blend with the base background color.
629 if (baseColor.alpha()) {
630 if (bgColor.alpha())
631 baseColor = baseColor.blend(bgColor);
632 context->fillRect(backgroundRect, baseColor, operation);
633 } else if (bgColor.alpha()) {
634 context->fillRect(backgroundRect, bgColor, operation);
635 } else if (shouldClearDocumentBackground) {
636 context->clearRect(backgroundRect);
637 }
638 }
639
640 bool BoxPainter::isDocumentElementWithOpaqueBackground(LayoutObject& obj)
641 {
642 if (!obj.isDocumentElement())
643 return false;
644
645 // The background is opaque only if we're the root document, since iframes w ith
646 // no background in the child document should show the parent's background.
647 bool isOpaque = true;
648 Element* ownerElement = obj.document().ownerElement();
649 if (ownerElement) {
650 if (!isHTMLFrameElement(*ownerElement)) {
651 // Locate the <body> element using the DOM. This is easier than tryi ng
652 // to crawl around a layout tree with potential :before/:after conte nt and
653 // anonymous blocks created by inline <body> tags etc. We can locate the <body>
654 // layout object very easily via the DOM.
655 HTMLElement* body = obj.document().body();
656 if (body) {
657 // Can't scroll a frameset document anyway.
658 isOpaque = body->hasTagName(HTMLNames::framesetTag);
659 } else {
660 // FIXME: SVG specific behavior should be in the SVG code.
661 // SVG documents and XML documents with SVG root nodes are trans parent.
662 isOpaque = !obj.document().hasSVGRootNode();
663 }
664 }
665 } else if (obj.view()->frameView()) {
666 isOpaque = !obj.view()->frameView()->isTransparent();
667 }
668
669 return isOpaque;
670 }
671
672 // Return the amount of space to leave between image tiles for the background-re peat: space property. 579 // Return the amount of space to leave between image tiles for the background-re peat: space property.
673 static inline int getSpaceBetweenImageTiles(int areaSize, int tileSize) 580 static inline int getSpaceBetweenImageTiles(int areaSize, int tileSize)
674 { 581 {
675 int numberOfTiles = areaSize / tileSize; 582 int numberOfTiles = areaSize / tileSize;
676 int space = -1; 583 int space = -1;
677 584
678 if (numberOfTiles > 1) { 585 if (numberOfTiles > 1) {
679 // Spec doesn't specify rounding, so use the same method as for backgrou nd-repeat: round. 586 // Spec doesn't specify rounding, so use the same method as for backgrou nd-repeat: round.
680 space = lroundf((areaSize - numberOfTiles * tileSize) / (float)(numberOf Tiles - 1)); 587 space = lroundf((areaSize - numberOfTiles * tileSize) / (float)(numberOf Tiles - 1));
681 } 588 }
682 589
683 return space; 590 return space;
684 } 591 }
685 592
686 void BoxPainter::calculateBackgroundImageGeometry(LayoutBoxModelObject& obj, con st LayoutBoxModelObject* paintContainer, const FillLayer& fillLayer, const Layou tRect& paintRect, 593 void BoxPainter::calculateBackgroundImageGeometry(LayoutBoxModelObject& obj, con st LayoutBoxModelObject* paintContainer, const FillLayer& fillLayer, const Layou tRect& paintRect,
687 BackgroundImageGeometry& geometry, LayoutObject* backgroundObject) 594 BackgroundImageGeometry& geometry, LayoutObject* backgroundObject)
688 { 595 {
689 LayoutUnit left = 0; 596 LayoutUnit left = 0;
690 LayoutUnit top = 0; 597 LayoutUnit top = 0;
691 IntSize positioningAreaSize; 598 IntSize positioningAreaSize;
692 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect); 599 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect);
600 bool isLayoutView = obj.isLayoutView();
601 const LayoutBox* rootBox = nullptr;
602 if (isLayoutView) {
603 // It is only possible reach here when root element has a box.
604 Element* documentElement = obj.document().documentElement();
605 ASSERT(documentElement);
606 ASSERT(documentElement->layoutObject());
607 ASSERT(documentElement->layoutObject()->isBox());
608 rootBox = toLayoutBox(documentElement->layoutObject());
609 }
610 const LayoutBoxModelObject& positioningBox = isLayoutView ? static_cast<cons t LayoutBoxModelObject&>(*rootBox) : obj;
693 611
694 // Determine the background positioning area and set destRect to the backgro und painting area. 612 // Determine the background positioning area and set destRect to the backgro und painting area.
695 // destRect will be adjusted later if the background is non-repeating. 613 // destRect will be adjusted later if the background is non-repeating.
696 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms. 614 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms.
697 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; 615 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment;
698 616
699 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { 617 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) {
700 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS 618 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS
701 // property "background-attachment: fixed" because it may result in rend ering 619 // property "background-attachment: fixed" because it may result in rend ering
702 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of 620 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of
703 // a page that has fixed background images. 621 // a page that has fixed background images.
704 fixedAttachment = false; 622 fixedAttachment = false;
705 } 623 }
706 624
707 if (!fixedAttachment) { 625 if (!fixedAttachment) {
708 geometry.setDestRect(snappedPaintRect); 626 geometry.setDestRect(snappedPaintRect);
709 627
710 LayoutUnit right = 0; 628 LayoutUnit right = 0;
711 LayoutUnit bottom = 0; 629 LayoutUnit bottom = 0;
712 // Scroll and Local. 630 // Scroll and Local.
713 if (fillLayer.origin() != BorderFillBox) { 631 if (fillLayer.origin() != BorderFillBox) {
714 left = obj.borderLeft(); 632 left = positioningBox.borderLeft();
715 right = obj.borderRight(); 633 right = positioningBox.borderRight();
716 top = obj.borderTop(); 634 top = positioningBox.borderTop();
717 bottom = obj.borderBottom(); 635 bottom = positioningBox.borderBottom();
718 if (fillLayer.origin() == ContentFillBox) { 636 if (fillLayer.origin() == ContentFillBox) {
719 left += obj.paddingLeft(); 637 left += positioningBox.paddingLeft();
720 right += obj.paddingRight(); 638 right += positioningBox.paddingRight();
721 top += obj.paddingTop(); 639 top += positioningBox.paddingTop();
722 bottom += obj.paddingBottom(); 640 bottom += positioningBox.paddingBottom();
723 } 641 }
724 } 642 }
725 643
726 // The background of the box generated by the root element covers the en tire canvas including 644 if (isLayoutView) {
727 // its margins. Since those were added in already, we have to factor the m out when computing 645 // The background of the box generated by the root element covers th e entire canvas and will
728 // the background positioning area. 646 // be painted by the view object, but the we should still use the ro ot element box for
729 if (obj.isDocumentElement()) { 647 // positioning.
730 positioningAreaSize = pixelSnappedIntSize(toLayoutBox(&obj)->size() - LayoutSize(left + right, top + bottom), toLayoutBox(&obj)->location()); 648 positioningAreaSize = pixelSnappedIntSize(rootBox->size() - LayoutSi ze(left + right, top + bottom), rootBox->location());
731 // The positioning area is right aligned in paintRect if RightToLeft WritingMode, or left aligned otherwise. 649 // The input paint rect is specified in root element local coordinat e (i.e. a transform
732 if (obj.style()->writingMode() == RightToLeftWritingMode) 650 // is applied on the context for painting), and is expanded to cover the whole canvas.
733 left = paintRect.width() - positioningAreaSize.width() - right - obj.marginRight(); 651 // Since left/top is relative to the paint rect, we need to offset t hem back.
734 else 652 left -= paintRect.x();
735 left += obj.marginLeft(); 653 top -= paintRect.y();
736 top += obj.marginTop();
737 } else { 654 } else {
738 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location()); 655 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location());
739 } 656 }
740 } else { 657 } else {
741 geometry.setHasNonLocalGeometry(); 658 geometry.setHasNonLocalGeometry();
742 659
743 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); 660 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect());
744 if (fixedBackgroundPaintsInLocalCoordinates(obj)) 661 if (fixedBackgroundPaintsInLocalCoordinates(obj))
745 viewportRect.setLocation(IntPoint()); 662 viewportRect.setLocation(IntPoint());
746 else if (FrameView* frameView = obj.view()->frameView()) 663 else if (FrameView* frameView = obj.view()->frameView())
747 viewportRect.setLocation(frameView->scrollPosition()); 664 viewportRect.setLocation(frameView->scrollPosition());
748 665
749 if (paintContainer) { 666 if (paintContainer) {
750 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint())); 667 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint()));
751 viewportRect.moveBy(-absoluteContainerOffset); 668 viewportRect.moveBy(-absoluteContainerOffset);
752 } 669 }
753 670
754 geometry.setDestRect(viewportRect); 671 geometry.setDestRect(viewportRect);
755 positioningAreaSize = geometry.destRect().size(); 672 positioningAreaSize = geometry.destRect().size();
756 } 673 }
757 674
758 const LayoutObject* clientForBackgroundImage = backgroundObject ? background Object : &obj; 675 const LayoutObject* clientForBackgroundImage = backgroundObject ? background Object : &obj;
759 IntSize fillTileSize = calculateFillTileSize(obj, fillLayer, positioningArea Size); 676 IntSize fillTileSize = calculateFillTileSize(positioningBox, fillLayer, posi tioningAreaSize);
760 fillLayer.image()->setContainerSizeForLayoutObject(clientForBackgroundImage, fillTileSize, obj.style()->effectiveZoom()); 677 fillLayer.image()->setContainerSizeForLayoutObject(clientForBackgroundImage, fillTileSize, obj.style()->effectiveZoom());
761 geometry.setTileSize(fillTileSize); 678 geometry.setTileSize(fillTileSize);
762 679
763 EFillRepeat backgroundRepeatX = fillLayer.repeatX(); 680 EFillRepeat backgroundRepeatX = fillLayer.repeatX();
764 EFillRepeat backgroundRepeatY = fillLayer.repeatY(); 681 EFillRepeat backgroundRepeatY = fillLayer.repeatY();
765 int availableWidth = positioningAreaSize.width() - geometry.tileSize().width (); 682 int availableWidth = positioningAreaSize.width() - geometry.tileSize().width ();
766 int availableHeight = positioningAreaSize.height() - geometry.tileSize().hei ght(); 683 int availableHeight = positioningAreaSize.height() - geometry.tileSize().hei ght();
767 684
768 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth); 685 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth);
769 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) { 686 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 geometry.clip(snappedPaintRect); 764 geometry.clip(snappedPaintRect);
848 } 765 }
849 766
850 InterpolationQuality BoxPainter::chooseInterpolationQuality(LayoutObject& obj, G raphicsContext* context, Image* image, const void* layer, const LayoutSize& size ) 767 InterpolationQuality BoxPainter::chooseInterpolationQuality(LayoutObject& obj, G raphicsContext* context, Image* image, const void* layer, const LayoutSize& size )
851 { 768 {
852 return ImageQualityController::imageQualityController()->chooseInterpolation Quality(context, &obj, image, layer, size); 769 return ImageQualityController::imageQualityController()->chooseInterpolation Quality(context, &obj, image, layer, size);
853 } 770 }
854 771
855 bool BoxPainter::fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj ) 772 bool BoxPainter::fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj )
856 { 773 {
857 if (!obj.isDocumentElement()) 774 if (!obj.isLayoutView())
858 return false; 775 return false;
859 776
860 if (obj.view()->frameView() && obj.view()->frameView()->paintBehavior() & Pa intBehaviorFlattenCompositingLayers) 777 const LayoutView& view = toLayoutView(obj);
778
779 if (view.frameView() && view.frameView()->paintBehavior() & PaintBehaviorFla ttenCompositingLayers)
861 return false; 780 return false;
862 781
863 DeprecatedPaintLayer* rootLayer = obj.view()->layer(); 782 DeprecatedPaintLayer* rootLayer = view.layer();
864 if (!rootLayer || rootLayer->compositingState() == NotComposited) 783 if (!rootLayer || rootLayer->compositingState() == NotComposited)
865 return false; 784 return false;
866 785
867 return rootLayer->compositedDeprecatedPaintLayerMapping()->backgroundLayerPa intsFixedRootBackground(); 786 return rootLayer->compositedDeprecatedPaintLayerMapping()->backgroundLayerPa intsFixedRootBackground();
868 } 787 }
869 788
870 static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize) 789 static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize)
871 { 790 {
872 tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tile Size.width().ceil() : tileSize.width().floor()); 791 tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tile Size.width().ceil() : tileSize.width().floor());
873 tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? t ileSize.height().ceil() : tileSize.height().floor()); 792 tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? t ileSize.height().ceil() : tileSize.height().floor());
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 else 1042 else
1124 clippedEdges |= GraphicsContext::BottomEdge; 1043 clippedEdges |= GraphicsContext::BottomEdge;
1125 } 1044 }
1126 // TODO: support non-integer shadows - crbug.com/334828 1045 // TODO: support non-integer shadows - crbug.com/334828
1127 context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowO ffset), shadowBlur, shadowSpread, clippedEdges); 1046 context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowO ffset), shadowBlur, shadowSpread, clippedEdges);
1128 } 1047 }
1129 } 1048 }
1130 } 1049 }
1131 1050
1132 } // namespace blink 1051 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/paint/BoxPainter.h ('k') | Source/core/paint/DisplayItemListPaintTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698