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