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