Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 if (currentLayer->composite() != CompositeSourceOver || currentLayer->bl endMode() != WebBlendModeNormal) |
|
chrishtr
2015/06/09 21:07:53
Why condition on currentLayer->composite() != Comp
trchen
2015/06/09 23:36:08
Because anything other than src-over is non-associ
| |
| 207 shouldDrawBackgroundInSeparateBuffer = true; | 170 isNonAssociative = true; |
| 208 | 171 |
| 209 if (curLayer->clipOccludesNextLayers() | 172 // TODO(trchen): A fill layer cannot paint if the calculated tile size i s empty. |
| 210 && curLayer->hasOpaqueImage(&m_layoutBox) | 173 // This occlusion check can be wrong. |
| 211 && curLayer->image()->canRender(m_layoutBox, m_layoutBox.style()->ef fectiveZoom()) | 174 if (currentLayer->clipOccludesNextLayers() |
| 212 && curLayer->hasRepeatXY() | 175 && isFillLayerOpaque(*currentLayer, m_layoutBox)) { |
| 213 && curLayer->blendMode() == WebBlendModeNormal | 176 if (currentLayer->clip() == BorderFillBox) |
| 214 && !m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance) ) | 177 isNonAssociative = false; |
| 215 break; | 178 break; |
| 216 curLayer = curLayer->next(); | 179 } |
| 180 } | |
| 181 return isNonAssociative; | |
| 182 } | |
| 183 | |
| 184 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, con st FillLayer& fillLayer, const LayoutRect& rect, BackgroundBleedAvoidance bleedA voidance, SkXfermode::Mode op, LayoutObject* backgroundObject) | |
| 185 { | |
| 186 // TODO(trchen): Box shadow optimization and background color are concepts t hat only | |
| 187 // apply to background layers. Ideally we should refactor those out of paint FillLayer. | |
| 188 FillLayerOcclusionOutputList reversedPaintList; | |
| 189 bool shouldDrawBackgroundInSeparateBuffer = false; | |
| 190 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) { | |
| 191 shouldDrawBackgroundInSeparateBuffer = calculateFillLayerOcclusionCullin g(reversedPaintList, fillLayer); | |
| 192 } else { | |
| 193 // If we are responsible for painting box shadow, don't perform fill lay er culling. | |
| 194 // TODO(trchen): In theory we only need to make sure the last layer has border box clipping | |
| 195 // and make it paint the box shadow. Investigate optimization opportunit y later. | |
| 196 for (auto currentLayer = &fillLayer; currentLayer; currentLayer = curren tLayer->next()) { | |
| 197 reversedPaintList.append(currentLayer); | |
| 198 if (currentLayer->composite() != CompositeSourceOver || currentLayer ->blendMode() != WebBlendModeNormal) | |
| 199 shouldDrawBackgroundInSeparateBuffer = true; | |
| 200 } | |
| 217 } | 201 } |
| 218 | 202 |
| 219 if (layers.size() > 0 && (**layers.rbegin()).next()) | 203 // TODO(trchen): We can optimize out isolation group if we have a non-transp arent |
| 220 isBottomLayerOccluded = true; | 204 // background color and the bottom layer encloses all other layers. |
| 221 | 205 |
| 222 GraphicsContext* context = paintInfo.context; | 206 GraphicsContext* context = paintInfo.context; |
| 223 if (!context) | 207 if (!context) |
| 224 shouldDrawBackgroundInSeparateBuffer = false; | 208 shouldDrawBackgroundInSeparateBuffer = false; |
| 225 | 209 |
| 226 bool skipBaseColor = false; | 210 if (shouldDrawBackgroundInSeparateBuffer) |
| 227 if (shouldDrawBackgroundInSeparateBuffer) { | 211 context->beginLayer(); |
| 228 bool isBaseColorVisible = !isBottomLayerOccluded && c.hasAlpha(); | |
| 229 | 212 |
| 230 // Paint the document's base background color outside the transparency l ayer, | 213 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. | 214 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 | 215 |
| 243 if (shouldDrawBackgroundInSeparateBuffer) | 216 if (shouldDrawBackgroundInSeparateBuffer) |
| 244 context->endLayer(); | 217 context->endLayer(); |
| 245 } | 218 } |
| 246 | 219 |
| 247 void BoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, cons t FillLayer& fillLayer, const LayoutRect& rect, | 220 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) | 221 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject* backgroundObject) |
| 249 { | 222 { |
| 250 BoxPainter::paintFillLayerExtended(m_layoutBox, paintInfo, c, fillLayer, rec t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, skipBaseColor); | 223 BoxPainter::paintFillLayerExtended(m_layoutBox, paintInfo, c, fillLayer, rec t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject); |
| 251 } | 224 } |
| 252 | 225 |
| 253 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj ect& obj) | 226 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj ect& obj) |
| 254 { | 227 { |
| 255 const ShadowList* shadowList = obj.style()->boxShadow(); | 228 const ShadowList* shadowList = obj.style()->boxShadow(); |
| 256 ASSERT(shadowList); | 229 ASSERT(shadowList); |
| 257 for (size_t i = shadowList->shadows().size(); i--; ) { | 230 for (size_t i = shadowList->shadows().size(); i--; ) { |
| 258 const ShadowData& boxShadow = shadowList->shadows()[i]; | 231 const ShadowData& boxShadow = shadowList->shadows()[i]; |
| 259 if (boxShadow.style() != Normal) | 232 if (boxShadow.style() != Normal) |
| 260 continue; | 233 continue; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 FloatRoundedRect::Radii insetRadii(backgroundRoundedRect.radii()); | 287 FloatRoundedRect::Radii insetRadii(backgroundRoundedRect.radii()); |
| 315 insetRadii.shrink(-insets.top(), -insets.bottom(), -insets.left(), -inse ts.right()); | 288 insetRadii.shrink(-insets.top(), -insets.bottom(), -insets.left(), -inse ts.right()); |
| 316 return FloatRoundedRect(insetRect, insetRadii); | 289 return FloatRoundedRect(insetRect, insetRadii); |
| 317 } | 290 } |
| 318 if (bleedAvoidance == BackgroundBleedBackgroundOverBorder) | 291 if (bleedAvoidance == BackgroundBleedBackgroundOverBorder) |
| 319 return obj.style()->getRoundedInnerBorderFor(borderRect, includeLogicalL eftEdge, includeLogicalRightEdge); | 292 return obj.style()->getRoundedInnerBorderFor(borderRect, includeLogicalL eftEdge, includeLogicalRightEdge); |
| 320 | 293 |
| 321 return getBackgroundRoundedRect(obj, borderRect, box, boxSize.width(), boxSi ze.height(), includeLogicalLeftEdge, includeLogicalRightEdge); | 294 return getBackgroundRoundedRect(obj, borderRect, box, boxSize.width(), boxSi ze.height(), includeLogicalLeftEdge, includeLogicalRightEdge); |
| 322 } | 295 } |
| 323 | 296 |
| 324 void BoxPainter::paintFillLayerExtended(LayoutBoxModelObject& obj, const PaintIn fo& paintInfo, const Color& color, const FillLayer& bgLayer, const LayoutRect& r ect, | 297 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 { | 298 { |
| 327 GraphicsContext* context = paintInfo.context; | 299 GraphicsContext* context = paintInfo.context; |
| 328 if (rect.isEmpty()) | 300 if (rect.isEmpty()) |
| 329 return; | 301 return; |
| 330 | 302 |
| 331 bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true; | 303 bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true; |
| 332 bool includeRightEdge = box ? box->includeLogicalRightEdge() : true; | 304 bool includeRightEdge = box ? box->includeLogicalRightEdge() : true; |
| 333 | 305 |
| 334 bool hasRoundedBorder = obj.style()->hasBorderRadius() && (includeLeftEdge | | includeRightEdge); | 306 bool hasRoundedBorder = obj.style()->hasBorderRadius() && (includeLeftEdge | | includeRightEdge); |
| 335 bool clippedWithLocalScrolling = obj.hasOverflowClip() && bgLayer.attachment () == LocalBackgroundAttachment; | 307 bool clippedWithLocalScrolling = obj.hasOverflowClip() && bgLayer.attachment () == LocalBackgroundAttachment; |
| 336 bool isBorderFill = bgLayer.clip() == BorderFillBox; | 308 bool isBorderFill = bgLayer.clip() == BorderFillBox; |
| 337 bool isDocumentElementLayoutObject = obj.isDocumentElement(); | |
| 338 bool isBottomLayer = !bgLayer.next(); | 309 bool isBottomLayer = !bgLayer.next(); |
| 339 | 310 |
| 340 Color bgColor = color; | 311 Color bgColor = color; |
| 341 StyleImage* bgImage = bgLayer.image(); | 312 StyleImage* bgImage = bgLayer.image(); |
| 342 bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(obj, obj.sty le()->effectiveZoom()); | |
| 343 | 313 |
| 344 bool forceBackgroundToWhite = false; | 314 bool forceBackgroundToWhite = false; |
| 345 if (obj.document().printing()) { | 315 if (obj.document().printing()) { |
| 346 if (obj.style()->printColorAdjust() == PrintColorAdjustEconomy) | 316 if (obj.style()->printColorAdjust() == PrintColorAdjustEconomy) |
| 347 forceBackgroundToWhite = true; | 317 forceBackgroundToWhite = true; |
| 348 if (obj.document().settings() && obj.document().settings()->shouldPrintB ackgrounds()) | 318 if (obj.document().settings() && obj.document().settings()->shouldPrintB ackgrounds()) |
| 349 forceBackgroundToWhite = false; | 319 forceBackgroundToWhite = false; |
| 350 } | 320 } |
| 351 | 321 |
| 352 // When printing backgrounds is disabled or using economy mode, | 322 // When printing backgrounds is disabled or using economy mode, |
| 353 // change existing background colors and images to a solid white background. | 323 // 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. | 324 // 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 | 325 // 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 | 326 // 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 | 327 // loading the background images we'd have to do this check when applying st yles rather than |
| 358 // while layout.) | 328 // while layout.) |
| 359 if (forceBackgroundToWhite) { | 329 if (forceBackgroundToWhite) { |
| 360 // Note that we can't reuse this variable below because the bgColor migh t be changed | 330 // Note that we can't reuse this variable below because the bgColor migh t be changed |
| 361 bool shouldPaintBackgroundColor = isBottomLayer && bgColor.alpha(); | 331 bool shouldPaintBackgroundColor = isBottomLayer && bgColor.alpha(); |
| 362 if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) { | 332 if (bgImage || shouldPaintBackgroundColor) { |
|
chrishtr
2015/06/09 21:07:53
Was it a bug that we were checking bgImage->canRen
trchen
2015/06/09 23:36:07
Because we can't check that at this point. See rep
| |
| 363 bgColor = Color::white; | 333 bgColor = Color::white; |
| 364 shouldPaintBackgroundImage = false; | 334 bgImage = nullptr; |
| 365 } | 335 } |
| 366 } | 336 } |
| 367 | 337 |
| 368 bool colorVisible = bgColor.alpha(); | |
| 369 | |
| 370 // Fast path for drawing simple color backgrounds. | 338 // Fast path for drawing simple color backgrounds. |
| 371 if (!isDocumentElementLayoutObject && !clippedWithLocalScrolling && !shouldP aintBackgroundImage && isBorderFill && isBottomLayer) { | 339 if (!clippedWithLocalScrolling && !bgImage && isBorderFill && isBottomLayer) { |
|
chrishtr
2015/06/09 21:07:53
ditto
trchen
2015/06/09 23:36:08
See below.
| |
| 372 if (!colorVisible) | 340 if (!bgColor.alpha()) |
| 373 return; | 341 return; |
| 374 | 342 |
| 375 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); | 343 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); |
| 376 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAp pliedToBackground); | 344 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAp pliedToBackground); |
| 377 if (boxShadowShouldBeAppliedToBackground) | 345 if (boxShadowShouldBeAppliedToBackground) |
| 378 BoxPainter::applyBoxShadowForBackground(context, obj); | 346 BoxPainter::applyBoxShadowForBackground(context, obj); |
| 379 | 347 |
| 380 if (hasRoundedBorder && !bleedAvoidanceIsClipping(bleedAvoidance)) { | 348 if (hasRoundedBorder && !bleedAvoidanceIsClipping(bleedAvoidance)) { |
| 381 FloatRoundedRect border = backgroundRoundedRectAdjustedForBleedAvoid ance(obj, rect, | 349 FloatRoundedRect border = backgroundRoundedRectAdjustedForBleedAvoid ance(obj, rect, |
| 382 bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) ; | 350 bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) ; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 472 | 440 |
| 473 break; | 441 break; |
| 474 } | 442 } |
| 475 case BorderFillBox: | 443 case BorderFillBox: |
| 476 break; | 444 break; |
| 477 default: | 445 default: |
| 478 ASSERT_NOT_REACHED(); | 446 ASSERT_NOT_REACHED(); |
| 479 break; | 447 break; |
| 480 } | 448 } |
| 481 | 449 |
| 450 BackgroundImageGeometry geometry; | |
| 451 if (bgImage) | |
| 452 calculateBackgroundImageGeometry(obj, paintInfo.paintContainer(), bgLaye r, scrolledPaintRect, geometry, backgroundObject); | |
|
chrishtr
2015/06/09 21:07:53
What's the point of putting this call here rather
trchen
2015/06/09 23:36:08
calculateBackgroundImageGeometry() primes the imag
chrishtr
2015/06/10 01:03:39
I see. Why can't we move the call to calculateBack
trchen
2015/06/10 01:41:05
Because calculateBackgroundImageGeometry() needs s
| |
| 453 bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(obj, obj.sty le()->effectiveZoom()); | |
| 454 | |
| 482 // Paint the color first underneath all images, culled if background image o ccludes it. | 455 // 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 | 456 // 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. | 457 // by verifying whether the background image covers the entire painting area . |
| 485 if (isBottomLayer) { | 458 if (isBottomLayer) { |
| 486 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); | 459 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); |
| 487 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); | 460 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied ToBackground(bleedAvoidance, box); |
| 488 bool isOpaqueRoot = (isDocumentElementLayoutObject && !bgColor.hasAlpha( )) || isDocumentElementWithOpaqueBackground(obj); | 461 bool backgroundImageOccludesBackgroundColor = shouldPaintBackgroundImage && isFillLayerOpaque(bgLayer, obj); |
| 489 if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer.hasOpaqueImage(&obj) || !bgLayer.hasRepeatXY() || (isOpaqueRoot && ! toLayoutBox(&obj)->size().height())) { | 462 if (boxShadowShouldBeAppliedToBackground || !backgroundImageOccludesBack groundColor) { |
| 490 if (!RuntimeEnabledFeatures::slimmingPaintEnabled() && !boxShadowSho uldBeAppliedToBackground) | 463 if (!RuntimeEnabledFeatures::slimmingPaintEnabled() && !boxShadowSho uldBeAppliedToBackground) |
| 491 backgroundRect.intersect(paintInfo.rect); | 464 backgroundRect.intersect(paintInfo.rect); |
| 492 | 465 |
| 493 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould BeAppliedToBackground); | 466 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould BeAppliedToBackground); |
| 494 if (boxShadowShouldBeAppliedToBackground) | 467 if (boxShadowShouldBeAppliedToBackground) |
| 495 BoxPainter::applyBoxShadowForBackground(context, obj); | 468 BoxPainter::applyBoxShadowForBackground(context, obj); |
| 496 | 469 |
| 497 if (isOpaqueRoot && !skipBaseColor) { | 470 if (bgColor.alpha()) |
| 498 paintRootBackgroundColor(obj, paintInfo, rect, bgColor); | |
| 499 } else if (bgColor.alpha()) { | |
| 500 context->fillRect(backgroundRect, bgColor); | 471 context->fillRect(backgroundRect, bgColor); |
| 501 } | |
| 502 } | 472 } |
| 503 } | 473 } |
| 504 | 474 |
| 505 // no progressive loading of the background image | 475 // no progressive loading of the background image |
| 506 if (shouldPaintBackgroundImage) { | 476 if (shouldPaintBackgroundImage) { |
| 507 BackgroundImageGeometry geometry; | |
| 508 calculateBackgroundImageGeometry(obj, paintInfo.paintContainer(), bgLaye r, scrolledPaintRect, geometry, backgroundObject); | |
| 509 if (!geometry.destRect().isEmpty()) { | 477 if (!geometry.destRect().isEmpty()) { |
| 510 SkXfermode::Mode bgOp = WebCoreCompositeToSkiaComposite(bgLayer.comp osite(), bgLayer.blendMode()); | 478 SkXfermode::Mode bgOp = WebCoreCompositeToSkiaComposite(bgLayer.comp osite(), bgLayer.blendMode()); |
| 511 // if op != SkXfermode::kSrcOver_Mode, a mask is being painted. | 479 // if op != SkXfermode::kSrcOver_Mode, a mask is being painted. |
| 512 SkXfermode::Mode compositeOp = op == SkXfermode::kSrcOver_Mode ? bgO p : op; | 480 SkXfermode::Mode compositeOp = op == SkXfermode::kSrcOver_Mode ? bgO p : op; |
| 513 LayoutObject* clientForBackgroundImage = backgroundObject ? backgrou ndObject : &obj; | 481 LayoutObject* clientForBackgroundImage = backgroundObject ? backgrou ndObject : &obj; |
| 514 RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geome try.tileSize()); | 482 RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geome try.tileSize()); |
| 515 InterpolationQuality interpolationQuality = chooseInterpolationQuali ty(*clientForBackgroundImage, context, image.get(), &bgLayer, LayoutSize(geometr y.tileSize())); | 483 InterpolationQuality interpolationQuality = chooseInterpolationQuali ty(*clientForBackgroundImage, context, image.get(), &bgLayer, LayoutSize(geometr y.tileSize())); |
| 516 if (bgLayer.maskSourceType() == MaskLuminance) | 484 if (bgLayer.maskSourceType() == MaskLuminance) |
| 517 context->setColorFilter(ColorFilterLuminanceToAlpha); | 485 context->setColorFilter(ColorFilterLuminanceToAlpha); |
| 518 InterpolationQuality previousInterpolationQuality = context->imageIn terpolationQuality(); | 486 InterpolationQuality previousInterpolationQuality = context->imageIn terpolationQuality(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 return; | 568 return; |
| 601 | 569 |
| 602 IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset, m_layoutBox. size())); | 570 IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset, m_layoutBox. size())); |
| 603 LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutBox, paintInfo.phase, paintRect); | 571 LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutBox, paintInfo.phase, paintRect); |
| 604 if (drawingRecorder.canUseCachedDrawing()) | 572 if (drawingRecorder.canUseCachedDrawing()) |
| 605 return; | 573 return; |
| 606 | 574 |
| 607 paintInfo.context->fillRect(paintRect, Color::black); | 575 paintInfo.context->fillRect(paintRect, Color::black); |
| 608 } | 576 } |
| 609 | 577 |
| 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. | 578 // 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) | 579 static inline int getSpaceBetweenImageTiles(int areaSize, int tileSize) |
| 674 { | 580 { |
| 675 int numberOfTiles = areaSize / tileSize; | 581 int numberOfTiles = areaSize / tileSize; |
| 676 int space = -1; | 582 int space = -1; |
| 677 | 583 |
| 678 if (numberOfTiles > 1) { | 584 if (numberOfTiles > 1) { |
| 679 // Spec doesn't specify rounding, so use the same method as for backgrou nd-repeat: round. | 585 // 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)); | 586 space = lroundf((areaSize - numberOfTiles * tileSize) / (float)(numberOf Tiles - 1)); |
| 681 } | 587 } |
| 682 | 588 |
| 683 return space; | 589 return space; |
| 684 } | 590 } |
| 685 | 591 |
| 686 void BoxPainter::calculateBackgroundImageGeometry(LayoutBoxModelObject& obj, con st LayoutBoxModelObject* paintContainer, const FillLayer& fillLayer, const Layou tRect& paintRect, | 592 void BoxPainter::calculateBackgroundImageGeometry(LayoutBoxModelObject& obj, con st LayoutBoxModelObject* paintContainer, const FillLayer& fillLayer, const Layou tRect& paintRect, |
| 687 BackgroundImageGeometry& geometry, LayoutObject* backgroundObject) | 593 BackgroundImageGeometry& geometry, LayoutObject* backgroundObject) |
| 688 { | 594 { |
| 689 LayoutUnit left = 0; | 595 LayoutUnit left = 0; |
| 690 LayoutUnit top = 0; | 596 LayoutUnit top = 0; |
| 691 IntSize positioningAreaSize; | 597 IntSize positioningAreaSize; |
| 692 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect); | 598 IntRect snappedPaintRect = pixelSnappedIntRect(paintRect); |
| 599 bool isLayoutView = obj.isLayoutView(); | |
| 600 const LayoutBox* rootBox = nullptr; | |
| 601 if (isLayoutView) { | |
| 602 rootBox = toLayoutBox(obj.document().documentElement() ? obj.document(). documentElement()->layoutObject() : nullptr); | |
| 603 ASSERT(rootBox); | |
|
chrishtr
2015/06/09 21:07:53
You're asserting that something is non-null right
trchen
2015/06/09 23:36:08
It just means
ASSERT(obj.document().documentElemen
chrishtr
2015/06/10 01:03:39
Ok please add a brief comment explaining that next
trchen
2015/06/10 01:41:05
Done.
| |
| 604 } | |
| 605 const LayoutBoxModelObject& positioningBox = isLayoutView ? static_cast<cons t LayoutBoxModelObject&>(*rootBox) : obj; | |
| 693 | 606 |
| 694 // Determine the background positioning area and set destRect to the backgro und painting area. | 607 // 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. | 608 // 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. | 609 // FIXME: transforms spec says that fixed backgrounds behave like scroll ins ide transforms. |
| 697 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; | 610 bool fixedAttachment = fillLayer.attachment() == FixedBackgroundAttachment; |
| 698 | 611 |
| 699 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { | 612 if (RuntimeEnabledFeatures::fastMobileScrollingEnabled()) { |
| 700 // As a side effect of an optimization to blit on scroll, we do not hono r the CSS | 613 // 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 | 614 // 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 | 615 // artifacts. Note, these artifacts only appear if we are blitting on sc roll of |
| 703 // a page that has fixed background images. | 616 // a page that has fixed background images. |
| 704 fixedAttachment = false; | 617 fixedAttachment = false; |
| 705 } | 618 } |
| 706 | 619 |
| 707 if (!fixedAttachment) { | 620 if (!fixedAttachment) { |
| 708 geometry.setDestRect(snappedPaintRect); | 621 geometry.setDestRect(snappedPaintRect); |
| 709 | 622 |
| 710 LayoutUnit right = 0; | 623 LayoutUnit right = 0; |
| 711 LayoutUnit bottom = 0; | 624 LayoutUnit bottom = 0; |
| 712 // Scroll and Local. | 625 // Scroll and Local. |
| 713 if (fillLayer.origin() != BorderFillBox) { | 626 if (fillLayer.origin() != BorderFillBox) { |
| 714 left = obj.borderLeft(); | 627 left = positioningBox.borderLeft(); |
| 715 right = obj.borderRight(); | 628 right = positioningBox.borderRight(); |
| 716 top = obj.borderTop(); | 629 top = positioningBox.borderTop(); |
| 717 bottom = obj.borderBottom(); | 630 bottom = positioningBox.borderBottom(); |
| 718 if (fillLayer.origin() == ContentFillBox) { | 631 if (fillLayer.origin() == ContentFillBox) { |
| 719 left += obj.paddingLeft(); | 632 left += positioningBox.paddingLeft(); |
| 720 right += obj.paddingRight(); | 633 right += positioningBox.paddingRight(); |
| 721 top += obj.paddingTop(); | 634 top += positioningBox.paddingTop(); |
| 722 bottom += obj.paddingBottom(); | 635 bottom += positioningBox.paddingBottom(); |
| 723 } | 636 } |
| 724 } | 637 } |
| 725 | 638 |
| 726 // The background of the box generated by the root element covers the en tire canvas including | 639 if (isLayoutView) { |
| 727 // its margins. Since those were added in already, we have to factor the m out when computing | 640 // The background of the box generated by the root element covers th e entire canvas and will |
| 728 // the background positioning area. | 641 // be painted by the view object, but the we should still use the ro ot element box for |
| 729 if (obj.isDocumentElement()) { | 642 // positioning. |
| 730 positioningAreaSize = pixelSnappedIntSize(toLayoutBox(&obj)->size() - LayoutSize(left + right, top + bottom), toLayoutBox(&obj)->location()); | 643 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. | 644 // The input paint rect is specified in root element local coordinat e (i.e. a transform |
| 732 if (obj.style()->writingMode() == RightToLeftWritingMode) | 645 // is applied on the context for painting), and is expanded to cover the whole canvas. |
|
chrishtr
2015/06/09 21:07:53
Not needed to account for RTL?
trchen
2015/06/09 23:36:07
This is a hack to try to recover border box from p
| |
| 733 left = paintRect.width() - positioningAreaSize.width() - right - obj.marginRight(); | 646 // Since left/top is relative to the paint rect, we need to offset t hem back. |
| 734 else | 647 left -= paintRect.x(); |
|
chrishtr
2015/06/09 21:07:53
I don't get this part, can you explain? Also, why
trchen
2015/06/09 23:36:07
Yes, this is the tricky part. Line 620~652 compute
| |
| 735 left += obj.marginLeft(); | 648 top -= paintRect.y(); |
| 736 top += obj.marginTop(); | |
| 737 } else { | 649 } else { |
| 738 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location()); | 650 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS ize(left + right, top + bottom), paintRect.location()); |
| 739 } | 651 } |
| 740 } else { | 652 } else { |
| 741 geometry.setHasNonLocalGeometry(); | 653 geometry.setHasNonLocalGeometry(); |
| 742 | 654 |
| 743 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); | 655 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); |
| 744 if (fixedBackgroundPaintsInLocalCoordinates(obj)) | 656 if (fixedBackgroundPaintsInLocalCoordinates(obj)) |
| 745 viewportRect.setLocation(IntPoint()); | 657 viewportRect.setLocation(IntPoint()); |
| 746 else if (FrameView* frameView = obj.view()->frameView()) | 658 else if (FrameView* frameView = obj.view()->frameView()) |
| 747 viewportRect.setLocation(frameView->scrollPosition()); | 659 viewportRect.setLocation(frameView->scrollPosition()); |
| 748 | 660 |
| 749 if (paintContainer) { | 661 if (paintContainer) { |
| 750 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint())); | 662 IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->l ocalToAbsolute(FloatPoint())); |
| 751 viewportRect.moveBy(-absoluteContainerOffset); | 663 viewportRect.moveBy(-absoluteContainerOffset); |
| 752 } | 664 } |
| 753 | 665 |
| 754 geometry.setDestRect(viewportRect); | 666 geometry.setDestRect(viewportRect); |
| 755 positioningAreaSize = geometry.destRect().size(); | 667 positioningAreaSize = geometry.destRect().size(); |
| 756 } | 668 } |
| 757 | 669 |
| 758 const LayoutObject* clientForBackgroundImage = backgroundObject ? background Object : &obj; | 670 const LayoutObject* clientForBackgroundImage = backgroundObject ? background Object : &obj; |
| 759 IntSize fillTileSize = calculateFillTileSize(obj, fillLayer, positioningArea Size); | 671 IntSize fillTileSize = calculateFillTileSize(positioningBox, fillLayer, posi tioningAreaSize); |
| 760 fillLayer.image()->setContainerSizeForLayoutObject(clientForBackgroundImage, fillTileSize, obj.style()->effectiveZoom()); | 672 fillLayer.image()->setContainerSizeForLayoutObject(clientForBackgroundImage, fillTileSize, obj.style()->effectiveZoom()); |
| 761 geometry.setTileSize(fillTileSize); | 673 geometry.setTileSize(fillTileSize); |
| 762 | 674 |
| 763 EFillRepeat backgroundRepeatX = fillLayer.repeatX(); | 675 EFillRepeat backgroundRepeatX = fillLayer.repeatX(); |
| 764 EFillRepeat backgroundRepeatY = fillLayer.repeatY(); | 676 EFillRepeat backgroundRepeatY = fillLayer.repeatY(); |
| 765 int availableWidth = positioningAreaSize.width() - geometry.tileSize().width (); | 677 int availableWidth = positioningAreaSize.width() - geometry.tileSize().width (); |
| 766 int availableHeight = positioningAreaSize.height() - geometry.tileSize().hei ght(); | 678 int availableHeight = positioningAreaSize.height() - geometry.tileSize().hei ght(); |
| 767 | 679 |
| 768 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth); | 680 LayoutUnit computedXPosition = roundedMinimumValueForLength(fillLayer.xPosit ion(), availableWidth); |
| 769 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) { | 681 if (backgroundRepeatX == RoundFill && positioningAreaSize.width() > 0 && fil lTileSize.width() > 0) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 geometry.clip(snappedPaintRect); | 759 geometry.clip(snappedPaintRect); |
| 848 } | 760 } |
| 849 | 761 |
| 850 InterpolationQuality BoxPainter::chooseInterpolationQuality(LayoutObject& obj, G raphicsContext* context, Image* image, const void* layer, const LayoutSize& size ) | 762 InterpolationQuality BoxPainter::chooseInterpolationQuality(LayoutObject& obj, G raphicsContext* context, Image* image, const void* layer, const LayoutSize& size ) |
| 851 { | 763 { |
| 852 return ImageQualityController::imageQualityController()->chooseInterpolation Quality(context, &obj, image, layer, size); | 764 return ImageQualityController::imageQualityController()->chooseInterpolation Quality(context, &obj, image, layer, size); |
| 853 } | 765 } |
| 854 | 766 |
| 855 bool BoxPainter::fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj ) | 767 bool BoxPainter::fixedBackgroundPaintsInLocalCoordinates(const LayoutObject& obj ) |
| 856 { | 768 { |
| 857 if (!obj.isDocumentElement()) | 769 if (!obj.isLayoutView()) |
| 858 return false; | 770 return false; |
| 859 | 771 |
| 860 if (obj.view()->frameView() && obj.view()->frameView()->paintBehavior() & Pa intBehaviorFlattenCompositingLayers) | 772 const LayoutView& view = toLayoutView(obj); |
| 773 | |
| 774 if (view.frameView() && view.frameView()->paintBehavior() & PaintBehaviorFla ttenCompositingLayers) | |
| 861 return false; | 775 return false; |
| 862 | 776 |
| 863 DeprecatedPaintLayer* rootLayer = obj.view()->layer(); | 777 DeprecatedPaintLayer* rootLayer = view.layer(); |
| 864 if (!rootLayer || rootLayer->compositingState() == NotComposited) | 778 if (!rootLayer || rootLayer->compositingState() == NotComposited) |
| 865 return false; | 779 return false; |
| 866 | 780 |
| 867 return rootLayer->compositedDeprecatedPaintLayerMapping()->backgroundLayerPa intsFixedRootBackground(); | 781 return rootLayer->compositedDeprecatedPaintLayerMapping()->backgroundLayerPa intsFixedRootBackground(); |
| 868 } | 782 } |
| 869 | 783 |
| 870 static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize) | 784 static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize) |
| 871 { | 785 { |
| 872 tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tile Size.width().ceil() : tileSize.width().floor()); | 786 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()); | 787 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 Loading... | |
| 1123 else | 1037 else |
| 1124 clippedEdges |= GraphicsContext::BottomEdge; | 1038 clippedEdges |= GraphicsContext::BottomEdge; |
| 1125 } | 1039 } |
| 1126 // TODO: support non-integer shadows - crbug.com/334828 | 1040 // TODO: support non-integer shadows - crbug.com/334828 |
| 1127 context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowO ffset), shadowBlur, shadowSpread, clippedEdges); | 1041 context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowO ffset), shadowBlur, shadowSpread, clippedEdges); |
| 1128 } | 1042 } |
| 1129 } | 1043 } |
| 1130 } | 1044 } |
| 1131 | 1045 |
| 1132 } // namespace blink | 1046 } // namespace blink |
| OLD | NEW |