| 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 "core/paint/BoxPainter.h" | 5 #include "core/paint/BoxPainter.h" |
| 6 | 6 |
| 7 #include "core/HTMLNames.h" | 7 #include "core/HTMLNames.h" |
| 8 #include "core/frame/Settings.h" | 8 #include "core/frame/Settings.h" |
| 9 #include "core/html/HTMLFrameOwnerElement.h" | 9 #include "core/html/HTMLFrameOwnerElement.h" |
| 10 #include "core/layout/ImageQualityController.h" | 10 #include "core/layout/ImageQualityController.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 child = child->nextSibling()) | 58 child = child->nextSibling()) |
| 59 child->paint(childInfo, adjustedPaintOffset); | 59 child->paint(childInfo, adjustedPaintOffset); |
| 60 } | 60 } |
| 61 | 61 |
| 62 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, | 62 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, |
| 63 const LayoutPoint& paintOffset) { | 63 const LayoutPoint& paintOffset) { |
| 64 LayoutRect paintRect; | 64 LayoutRect paintRect; |
| 65 Optional<ScrollRecorder> scrollRecorder; | 65 Optional<ScrollRecorder> scrollRecorder; |
| 66 if (isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( | 66 if (isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( |
| 67 &m_layoutBox, paintInfo)) { | 67 &m_layoutBox, paintInfo)) { |
| 68 // For the case where we are painting the background into the scrolling cont
ents layer | 68 // For the case where we are painting the background into the scrolling |
| 69 // of a composited scroller we need to include the entire overflow rect. | 69 // contents layer of a composited scroller we need to include the entire |
| 70 // overflow rect. |
| 70 paintRect = m_layoutBox.layoutOverflowRect(); | 71 paintRect = m_layoutBox.layoutOverflowRect(); |
| 71 scrollRecorder.emplace(paintInfo.context, m_layoutBox, paintInfo.phase, | 72 scrollRecorder.emplace(paintInfo.context, m_layoutBox, paintInfo.phase, |
| 72 m_layoutBox.scrolledContentOffset()); | 73 m_layoutBox.scrolledContentOffset()); |
| 73 | 74 |
| 74 // The background painting code assumes that the borders are part of the pai
ntRect so we | 75 // The background painting code assumes that the borders are part of the |
| 75 // expand the paintRect by the border size when painting the background into
the | 76 // paintRect so we expand the paintRect by the border size when painting the |
| 76 // scrolling contents layer. | 77 // background into the scrolling contents layer. |
| 77 paintRect.expandEdges(LayoutUnit(m_layoutBox.borderTop()), | 78 paintRect.expandEdges(LayoutUnit(m_layoutBox.borderTop()), |
| 78 LayoutUnit(m_layoutBox.borderRight()), | 79 LayoutUnit(m_layoutBox.borderRight()), |
| 79 LayoutUnit(m_layoutBox.borderBottom()), | 80 LayoutUnit(m_layoutBox.borderBottom()), |
| 80 LayoutUnit(m_layoutBox.borderLeft())); | 81 LayoutUnit(m_layoutBox.borderLeft())); |
| 81 } else { | 82 } else { |
| 82 paintRect = m_layoutBox.borderBoxRect(); | 83 paintRect = m_layoutBox.borderBoxRect(); |
| 83 } | 84 } |
| 84 | 85 |
| 85 paintRect.moveBy(paintOffset); | 86 paintRect.moveBy(paintOffset); |
| 86 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); | 87 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 110 void BoxPainter::paintBoxDecorationBackgroundWithRect( | 111 void BoxPainter::paintBoxDecorationBackgroundWithRect( |
| 111 const PaintInfo& paintInfo, | 112 const PaintInfo& paintInfo, |
| 112 const LayoutPoint& paintOffset, | 113 const LayoutPoint& paintOffset, |
| 113 const LayoutRect& paintRect) { | 114 const LayoutRect& paintRect) { |
| 114 bool paintingOverflowContents = | 115 bool paintingOverflowContents = |
| 115 isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( | 116 isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( |
| 116 &m_layoutBox, paintInfo); | 117 &m_layoutBox, paintInfo); |
| 117 const ComputedStyle& style = m_layoutBox.styleRef(); | 118 const ComputedStyle& style = m_layoutBox.styleRef(); |
| 118 | 119 |
| 119 Optional<DisplayItemCacheSkipper> cacheSkipper; | 120 Optional<DisplayItemCacheSkipper> cacheSkipper; |
| 120 // Disable cache in under-invalidation checking mode for MediaSliderPart becau
se we always paint using the | 121 // Disable cache in under-invalidation checking mode for MediaSliderPart |
| 121 // latest data (buffered ranges, current time and duration) which may be diffe
rent from the cached data. | 122 // because we always paint using the latest data (buffered ranges, current |
| 123 // time and duration) which may be different from the cached data. |
| 122 if ((RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && | 124 if ((RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled() && |
| 123 style.appearance() == MediaSliderPart) | 125 style.appearance() == MediaSliderPart) |
| 124 // We may paint a delayed-invalidation object before it's actually invalid
ated. Note this would be handled for | 126 // We may paint a delayed-invalidation object before it's actually |
| 125 // us by LayoutObjectDrawingRecorder but we have to use DrawingRecorder as
we may use the scrolling contents | 127 // invalidated. Note this would be handled for us by |
| 126 // layer as DisplayItemClient below. | 128 // LayoutObjectDrawingRecorder but we have to use DrawingRecorder as we |
| 129 // may use the scrolling contents layer as DisplayItemClient below. |
| 127 || | 130 || |
| 128 m_layoutBox.fullPaintInvalidationReason() == | 131 m_layoutBox.fullPaintInvalidationReason() == |
| 129 PaintInvalidationDelayedFull) { | 132 PaintInvalidationDelayedFull) { |
| 130 cacheSkipper.emplace(paintInfo.context); | 133 cacheSkipper.emplace(paintInfo.context); |
| 131 } | 134 } |
| 132 | 135 |
| 133 const DisplayItemClient& displayItemClient = | 136 const DisplayItemClient& displayItemClient = |
| 134 paintingOverflowContents ? static_cast<const DisplayItemClient&>( | 137 paintingOverflowContents ? static_cast<const DisplayItemClient&>( |
| 135 *m_layoutBox.layer() | 138 *m_layoutBox.layer() |
| 136 ->compositedLayerMapping() | 139 ->compositedLayerMapping() |
| 137 ->scrollingContentsLayer()) | 140 ->scrollingContentsLayer()) |
| 138 : m_layoutBox; | 141 : m_layoutBox; |
| 139 if (DrawingRecorder::useCachedDrawingIfPossible( | 142 if (DrawingRecorder::useCachedDrawingIfPossible( |
| 140 paintInfo.context, displayItemClient, | 143 paintInfo.context, displayItemClient, |
| 141 DisplayItem::kBoxDecorationBackground)) | 144 DisplayItem::kBoxDecorationBackground)) |
| 142 return; | 145 return; |
| 143 | 146 |
| 144 DrawingRecorder recorder( | 147 DrawingRecorder recorder( |
| 145 paintInfo.context, displayItemClient, | 148 paintInfo.context, displayItemClient, |
| 146 DisplayItem::kBoxDecorationBackground, | 149 DisplayItem::kBoxDecorationBackground, |
| 147 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset))); | 150 FloatRect(boundsForDrawingRecorder(paintInfo, paintOffset))); |
| 148 BoxDecorationData boxDecorationData(m_layoutBox); | 151 BoxDecorationData boxDecorationData(m_layoutBox); |
| 149 GraphicsContextStateSaver stateSaver(paintInfo.context, false); | 152 GraphicsContextStateSaver stateSaver(paintInfo.context, false); |
| 150 | 153 |
| 151 if (!paintingOverflowContents) { | 154 if (!paintingOverflowContents) { |
| 152 // FIXME: Should eventually give the theme control over whether the box shad
ow should paint, since controls could have | 155 // FIXME: Should eventually give the theme control over whether the box |
| 153 // custom shadows of their own. | 156 // shadow should paint, since controls could have custom shadows of their |
| 157 // own. |
| 154 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground( | 158 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground( |
| 155 boxDecorationData.bleedAvoidance)) { | 159 boxDecorationData.bleedAvoidance)) { |
| 156 paintBoxShadow(paintInfo, paintRect, style, Normal); | 160 paintBoxShadow(paintInfo, paintRect, style, Normal); |
| 157 } | 161 } |
| 158 | 162 |
| 159 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) { | 163 if (bleedAvoidanceIsClipping(boxDecorationData.bleedAvoidance)) { |
| 160 stateSaver.save(); | 164 stateSaver.save(); |
| 161 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); | 165 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); |
| 162 paintInfo.context.clipRoundedRect(border); | 166 paintInfo.context.clipRoundedRect(border); |
| 163 | 167 |
| 164 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer) | 168 if (boxDecorationData.bleedAvoidance == BackgroundBleedClipLayer) |
| 165 paintInfo.context.beginLayer(); | 169 paintInfo.context.beginLayer(); |
| 166 } | 170 } |
| 167 } | 171 } |
| 168 | 172 |
| 169 // If we have a native theme appearance, paint that before painting our backgr
ound. | 173 // If we have a native theme appearance, paint that before painting our |
| 170 // The theme will tell us whether or not we should also paint the CSS backgrou
nd. | 174 // background. The theme will tell us whether or not we should also paint the |
| 175 // CSS background. |
| 171 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); | 176 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); |
| 172 ThemePainter& themePainter = LayoutTheme::theme().painter(); | 177 ThemePainter& themePainter = LayoutTheme::theme().painter(); |
| 173 bool themePainted = | 178 bool themePainted = |
| 174 boxDecorationData.hasAppearance && | 179 boxDecorationData.hasAppearance && |
| 175 !themePainter.paint(m_layoutBox, paintInfo, snappedPaintRect); | 180 !themePainter.paint(m_layoutBox, paintInfo, snappedPaintRect); |
| 176 bool shouldPaintBackground = | 181 bool shouldPaintBackground = |
| 177 !themePainted && (!paintInfo.skipRootBackground() || | 182 !themePainted && (!paintInfo.skipRootBackground() || |
| 178 paintInfo.paintContainer() != &m_layoutBox); | 183 paintInfo.paintContainer() != &m_layoutBox); |
| 179 if (shouldPaintBackground) { | 184 if (shouldPaintBackground) { |
| 180 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor, | 185 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor, |
| 181 boxDecorationData.bleedAvoidance); | 186 boxDecorationData.bleedAvoidance); |
| 182 | 187 |
| 183 if (boxDecorationData.hasAppearance) | 188 if (boxDecorationData.hasAppearance) |
| 184 themePainter.paintDecorations(m_layoutBox, paintInfo, snappedPaintRect); | 189 themePainter.paintDecorations(m_layoutBox, paintInfo, snappedPaintRect); |
| 185 } | 190 } |
| 186 | 191 |
| 187 if (!paintingOverflowContents) { | 192 if (!paintingOverflowContents) { |
| 188 paintBoxShadow(paintInfo, paintRect, style, Inset); | 193 paintBoxShadow(paintInfo, paintRect, style, Inset); |
| 189 | 194 |
| 190 // The theme will tell us whether or not we should also paint the CSS border
. | 195 // The theme will tell us whether or not we should also paint the CSS |
| 196 // border. |
| 191 if (boxDecorationData.hasBorderDecoration && | 197 if (boxDecorationData.hasBorderDecoration && |
| 192 (!boxDecorationData.hasAppearance || | 198 (!boxDecorationData.hasAppearance || |
| 193 (!themePainted && | 199 (!themePainted && |
| 194 LayoutTheme::theme().painter().paintBorderOnly(m_layoutBox, paintInfo, | 200 LayoutTheme::theme().painter().paintBorderOnly(m_layoutBox, paintInfo, |
| 195 snappedPaintRect))) && | 201 snappedPaintRect))) && |
| 196 !(m_layoutBox.isTable() && | 202 !(m_layoutBox.isTable() && |
| 197 toLayoutTable(&m_layoutBox)->collapseBorders())) { | 203 toLayoutTable(&m_layoutBox)->collapseBorders())) { |
| 198 paintBorder(m_layoutBox, paintInfo, paintRect, style, | 204 paintBorder(m_layoutBox, paintInfo, paintRect, style, |
| 199 boxDecorationData.bleedAvoidance); | 205 boxDecorationData.bleedAvoidance); |
| 200 } | 206 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 220 } | 226 } |
| 221 | 227 |
| 222 bool BoxPainter::calculateFillLayerOcclusionCulling( | 228 bool BoxPainter::calculateFillLayerOcclusionCulling( |
| 223 FillLayerOcclusionOutputList& reversedPaintList, | 229 FillLayerOcclusionOutputList& reversedPaintList, |
| 224 const FillLayer& fillLayer) { | 230 const FillLayer& fillLayer) { |
| 225 bool isNonAssociative = false; | 231 bool isNonAssociative = false; |
| 226 for (auto currentLayer = &fillLayer; currentLayer; | 232 for (auto currentLayer = &fillLayer; currentLayer; |
| 227 currentLayer = currentLayer->next()) { | 233 currentLayer = currentLayer->next()) { |
| 228 reversedPaintList.append(currentLayer); | 234 reversedPaintList.append(currentLayer); |
| 229 // Stop traversal when an opaque layer is encountered. | 235 // Stop traversal when an opaque layer is encountered. |
| 230 // FIXME : It would be possible for the following occlusion culling test to
be more aggressive | 236 // FIXME : It would be possible for the following occlusion culling test to |
| 231 // on layers with no repeat by testing whether the image covers the layout r
ect. | 237 // be more aggressive on layers with no repeat by testing whether the image |
| 232 // Testing that here would imply duplicating a lot of calculations that are
currently done in | 238 // covers the layout rect. Testing that here would imply duplicating a lot |
| 233 // LayoutBoxModelObject::paintFillLayer. A more efficient solution might be
to move the layer | 239 // of calculations that are currently done in |
| 234 // recursion into paintFillLayer, or to compute the layer geometry here and
pass it down. | 240 // LayoutBoxModelObject::paintFillLayer. A more efficient solution might be |
| 241 // to move the layer recursion into paintFillLayer, or to compute the layer |
| 242 // geometry here and pass it down. |
| 235 | 243 |
| 236 // TODO(trchen): Need to check compositing mode as well. | 244 // TODO(trchen): Need to check compositing mode as well. |
| 237 if (currentLayer->blendMode() != WebBlendModeNormal) | 245 if (currentLayer->blendMode() != WebBlendModeNormal) |
| 238 isNonAssociative = true; | 246 isNonAssociative = true; |
| 239 | 247 |
| 240 // TODO(trchen): A fill layer cannot paint if the calculated tile size is em
pty. | 248 // TODO(trchen): A fill layer cannot paint if the calculated tile size is |
| 241 // This occlusion check can be wrong. | 249 // empty. This occlusion check can be wrong. |
| 242 if (currentLayer->clipOccludesNextLayers() && | 250 if (currentLayer->clipOccludesNextLayers() && |
| 243 currentLayer->imageOccludesNextLayers(m_layoutBox)) { | 251 currentLayer->imageOccludesNextLayers(m_layoutBox)) { |
| 244 if (currentLayer->clip() == BorderFillBox) | 252 if (currentLayer->clip() == BorderFillBox) |
| 245 isNonAssociative = false; | 253 isNonAssociative = false; |
| 246 break; | 254 break; |
| 247 } | 255 } |
| 248 } | 256 } |
| 249 return isNonAssociative; | 257 return isNonAssociative; |
| 250 } | 258 } |
| 251 | 259 |
| 252 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, | 260 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, |
| 253 const Color& c, | 261 const Color& c, |
| 254 const FillLayer& fillLayer, | 262 const FillLayer& fillLayer, |
| 255 const LayoutRect& rect, | 263 const LayoutRect& rect, |
| 256 BackgroundBleedAvoidance bleedAvoidance, | 264 BackgroundBleedAvoidance bleedAvoidance, |
| 257 SkXfermode::Mode op, | 265 SkXfermode::Mode op, |
| 258 const LayoutObject* backgroundObject) { | 266 const LayoutObject* backgroundObject) { |
| 259 // TODO(trchen): Box shadow optimization and background color are concepts tha
t only | 267 // TODO(trchen): Box shadow optimization and background color are concepts |
| 260 // apply to background layers. Ideally we should refactor those out of paintFi
llLayer. | 268 // that only apply to background layers. Ideally we should refactor those out |
| 269 // of paintFillLayer. |
| 261 FillLayerOcclusionOutputList reversedPaintList; | 270 FillLayerOcclusionOutputList reversedPaintList; |
| 262 bool shouldDrawBackgroundInSeparateBuffer = false; | 271 bool shouldDrawBackgroundInSeparateBuffer = false; |
| 263 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) { | 272 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)) { |
| 264 shouldDrawBackgroundInSeparateBuffer = | 273 shouldDrawBackgroundInSeparateBuffer = |
| 265 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer); | 274 calculateFillLayerOcclusionCulling(reversedPaintList, fillLayer); |
| 266 } else { | 275 } else { |
| 267 // If we are responsible for painting box shadow, don't perform fill layer c
ulling. | 276 // If we are responsible for painting box shadow, don't perform fill layer |
| 268 // TODO(trchen): In theory we only need to make sure the last layer has bord
er box clipping | 277 // culling. |
| 269 // and make it paint the box shadow. Investigate optimization opportunity la
ter. | 278 // TODO(trchen): In theory we only need to make sure the last layer has |
| 279 // border box clipping and make it paint the box shadow. Investigate |
| 280 // optimization opportunity later. |
| 270 for (auto currentLayer = &fillLayer; currentLayer; | 281 for (auto currentLayer = &fillLayer; currentLayer; |
| 271 currentLayer = currentLayer->next()) { | 282 currentLayer = currentLayer->next()) { |
| 272 reversedPaintList.append(currentLayer); | 283 reversedPaintList.append(currentLayer); |
| 273 if (currentLayer->composite() != CompositeSourceOver || | 284 if (currentLayer->composite() != CompositeSourceOver || |
| 274 currentLayer->blendMode() != WebBlendModeNormal) | 285 currentLayer->blendMode() != WebBlendModeNormal) |
| 275 shouldDrawBackgroundInSeparateBuffer = true; | 286 shouldDrawBackgroundInSeparateBuffer = true; |
| 276 } | 287 } |
| 277 } | 288 } |
| 278 | 289 |
| 279 // TODO(trchen): We can optimize out isolation group if we have a non-transpar
ent | 290 // TODO(trchen): We can optimize out isolation group if we have a |
| 280 // background color and the bottom layer encloses all other layers. | 291 // non-transparent background color and the bottom layer encloses all other |
| 292 // layers. |
| 281 | 293 |
| 282 GraphicsContext& context = paintInfo.context; | 294 GraphicsContext& context = paintInfo.context; |
| 283 | 295 |
| 284 if (shouldDrawBackgroundInSeparateBuffer) | 296 if (shouldDrawBackgroundInSeparateBuffer) |
| 285 context.beginLayer(); | 297 context.beginLayer(); |
| 286 | 298 |
| 287 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); | 299 for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); |
| 288 ++it) | 300 ++it) |
| 289 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0, | 301 paintFillLayer(m_layoutBox, paintInfo, c, **it, rect, bleedAvoidance, 0, |
| 290 LayoutSize(), op, backgroundObject); | 302 LayoutSize(), op, backgroundObject); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 | 359 |
| 348 FloatRoundedRect backgroundRoundedRectAdjustedForBleedAvoidance( | 360 FloatRoundedRect backgroundRoundedRectAdjustedForBleedAvoidance( |
| 349 const LayoutObject& obj, | 361 const LayoutObject& obj, |
| 350 const LayoutRect& borderRect, | 362 const LayoutRect& borderRect, |
| 351 BackgroundBleedAvoidance bleedAvoidance, | 363 BackgroundBleedAvoidance bleedAvoidance, |
| 352 const InlineFlowBox* box, | 364 const InlineFlowBox* box, |
| 353 const LayoutSize& boxSize, | 365 const LayoutSize& boxSize, |
| 354 bool includeLogicalLeftEdge, | 366 bool includeLogicalLeftEdge, |
| 355 bool includeLogicalRightEdge) { | 367 bool includeLogicalRightEdge) { |
| 356 if (bleedAvoidance == BackgroundBleedShrinkBackground) { | 368 if (bleedAvoidance == BackgroundBleedShrinkBackground) { |
| 357 // Inset the background rect by a "safe" amount: 1/2 border-width for opaque
border styles, | 369 // Inset the background rect by a "safe" amount: 1/2 border-width for opaque |
| 358 // 1/6 border-width for double borders. | 370 // border styles, 1/6 border-width for double borders. |
| 359 | 371 |
| 360 // TODO(fmalita): we should be able to fold these parameters into BoxBorderI
nfo or | 372 // TODO(fmalita): we should be able to fold these parameters into |
| 361 // BoxDecorationData and avoid calling getBorderEdgeInfo redundantly here. | 373 // BoxBorderInfo or BoxDecorationData and avoid calling getBorderEdgeInfo |
| 374 // redundantly here. |
| 362 BorderEdge edges[4]; | 375 BorderEdge edges[4]; |
| 363 obj.style()->getBorderEdgeInfo(edges, includeLogicalLeftEdge, | 376 obj.style()->getBorderEdgeInfo(edges, includeLogicalLeftEdge, |
| 364 includeLogicalRightEdge); | 377 includeLogicalRightEdge); |
| 365 | 378 |
| 366 // Use the most conservative inset to avoid mixed-style corner issues. | 379 // Use the most conservative inset to avoid mixed-style corner issues. |
| 367 float fractionalInset = 1.0f / 2; | 380 float fractionalInset = 1.0f / 2; |
| 368 for (auto& edge : edges) { | 381 for (auto& edge : edges) { |
| 369 if (edge.borderStyle() == BorderStyleDouble) { | 382 if (edge.borderStyle() == BorderStyleDouble) { |
| 370 fractionalInset = 1.0f / 6; | 383 fractionalInset = 1.0f / 6; |
| 371 break; | 384 break; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 color(bgColor), | 418 color(bgColor), |
| 406 includeLeftEdge(box ? box->includeLogicalLeftEdge() : true), | 419 includeLeftEdge(box ? box->includeLogicalLeftEdge() : true), |
| 407 includeRightEdge(box ? box->includeLogicalRightEdge() : true), | 420 includeRightEdge(box ? box->includeLogicalRightEdge() : true), |
| 408 isBottomLayer(!layer.next()), | 421 isBottomLayer(!layer.next()), |
| 409 isBorderFill(layer.clip() == BorderFillBox), | 422 isBorderFill(layer.clip() == BorderFillBox), |
| 410 isClippedWithLocalScrolling(obj.hasOverflowClip() && | 423 isClippedWithLocalScrolling(obj.hasOverflowClip() && |
| 411 layer.attachment() == | 424 layer.attachment() == |
| 412 LocalBackgroundAttachment) { | 425 LocalBackgroundAttachment) { |
| 413 // When printing backgrounds is disabled or using economy mode, | 426 // When printing backgrounds is disabled or using economy mode, |
| 414 // change existing background colors and images to a solid white background. | 427 // change existing background colors and images to a solid white background. |
| 415 // If there's no bg color or image, leave it untouched to avoid affecting tr
ansparency. | 428 // If there's no bg color or image, leave it untouched to avoid affecting |
| 416 // We don't try to avoid loading the background images, because this style f
lag is only set | 429 // transparency. We don't try to avoid loading the background images, |
| 417 // when printing, and at that point we've already loaded the background imag
es anyway. (To avoid | 430 // because this style flag is only set when printing, and at that point |
| 418 // loading the background images we'd have to do this check when applying st
yles rather than | 431 // we've already loaded the background images anyway. (To avoid loading the |
| 419 // while layout.) | 432 // background images we'd have to do this check when applying styles rather |
| 433 // than while layout.) |
| 420 if (BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(obj.styleRef(), | 434 if (BoxPainter::shouldForceWhiteBackgroundForPrintEconomy(obj.styleRef(), |
| 421 obj.document())) { | 435 obj.document())) { |
| 422 // Note that we can't reuse this variable below because the bgColor might
be changed | 436 // Note that we can't reuse this variable below because the bgColor might |
| 437 // be changed. |
| 423 bool shouldPaintBackgroundColor = isBottomLayer && color.alpha(); | 438 bool shouldPaintBackgroundColor = isBottomLayer && color.alpha(); |
| 424 if (image || shouldPaintBackgroundColor) { | 439 if (image || shouldPaintBackgroundColor) { |
| 425 color = Color::white; | 440 color = Color::white; |
| 426 image = nullptr; | 441 image = nullptr; |
| 427 } | 442 } |
| 428 } | 443 } |
| 429 | 444 |
| 430 const bool hasRoundedBorder = | 445 const bool hasRoundedBorder = |
| 431 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge); | 446 obj.style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge); |
| 432 // BorderFillBox radius clipping is taken care of by BackgroundBleedClip{Onl
y,Layer} | 447 // BorderFillBox radius clipping is taken care of by |
| 448 // BackgroundBleedClip{Only,Layer} |
| 433 isRoundedFill = hasRoundedBorder && | 449 isRoundedFill = hasRoundedBorder && |
| 434 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance)); | 450 !(isBorderFill && bleedAvoidanceIsClipping(bleedAvoidance)); |
| 435 | 451 |
| 436 shouldPaintImage = image && image->canRender(); | 452 shouldPaintImage = image && image->canRender(); |
| 437 shouldPaintColor = | 453 shouldPaintColor = |
| 438 isBottomLayer && color.alpha() && | 454 isBottomLayer && color.alpha() && |
| 439 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj)); | 455 (!shouldPaintImage || !layer.imageOccludesNextLayers(obj)); |
| 440 shouldPaintShadow = | 456 shouldPaintShadow = |
| 441 shouldPaintColor && | 457 shouldPaintColor && |
| 442 obj.boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); | 458 obj.boxShadowShouldBeAppliedToBackground(bleedAvoidance, box); |
| 443 } | 459 } |
| 444 | 460 |
| 445 // FillLayerInfo is a temporary, stack-allocated container which cannot outliv
e the StyleImage. | 461 // FillLayerInfo is a temporary, stack-allocated container which cannot |
| 446 // This would normally be a raw pointer, if not for the Oilpan tooling complai
nts. | 462 // outlive the StyleImage. This would normally be a raw pointer, if not for |
| 463 // the Oilpan tooling complaints. |
| 447 Member<StyleImage> image; | 464 Member<StyleImage> image; |
| 448 Color color; | 465 Color color; |
| 449 | 466 |
| 450 bool includeLeftEdge; | 467 bool includeLeftEdge; |
| 451 bool includeRightEdge; | 468 bool includeRightEdge; |
| 452 bool isBottomLayer; | 469 bool isBottomLayer; |
| 453 bool isBorderFill; | 470 bool isBorderFill; |
| 454 bool isClippedWithLocalScrolling; | 471 bool isClippedWithLocalScrolling; |
| 455 bool isRoundedFill; | 472 bool isRoundedFill; |
| 456 | 473 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 Optional<BackgroundImageGeometry>& geometry) { | 539 Optional<BackgroundImageGeometry>& geometry) { |
| 523 // Complex cases not handled on the fast path. | 540 // Complex cases not handled on the fast path. |
| 524 if (!info.isBottomLayer || !info.isBorderFill || | 541 if (!info.isBottomLayer || !info.isBorderFill || |
| 525 info.isClippedWithLocalScrolling) | 542 info.isClippedWithLocalScrolling) |
| 526 return false; | 543 return false; |
| 527 | 544 |
| 528 // Transparent layer, nothing to paint. | 545 // Transparent layer, nothing to paint. |
| 529 if (!info.shouldPaintColor && !info.shouldPaintImage) | 546 if (!info.shouldPaintColor && !info.shouldPaintImage) |
| 530 return true; | 547 return true; |
| 531 | 548 |
| 532 // When the layer has an image, figure out whether it is covered by a single t
ile. | 549 // When the layer has an image, figure out whether it is covered by a single |
| 550 // tile. |
| 533 FloatRect imageTile; | 551 FloatRect imageTile; |
| 534 if (info.shouldPaintImage) { | 552 if (info.shouldPaintImage) { |
| 535 DCHECK(!geometry); | 553 DCHECK(!geometry); |
| 536 geometry.emplace(); | 554 geometry.emplace(); |
| 537 geometry->calculate(obj, paintInfo.paintContainer(), | 555 geometry->calculate(obj, paintInfo.paintContainer(), |
| 538 paintInfo.getGlobalPaintFlags(), layer, rect); | 556 paintInfo.getGlobalPaintFlags(), layer, rect); |
| 539 | 557 |
| 540 if (!geometry->destRect().isEmpty()) { | 558 if (!geometry->destRect().isEmpty()) { |
| 541 // The tile is too small. | 559 // The tile is too small. |
| 542 if (geometry->tileSize().width() < rect.width() || | 560 if (geometry->tileSize().width() < rect.width() || |
| 543 geometry->tileSize().height() < rect.height()) | 561 geometry->tileSize().height() < rect.height()) |
| 544 return false; | 562 return false; |
| 545 | 563 |
| 546 imageTile = Image::computeTileContaining( | 564 imageTile = Image::computeTileContaining( |
| 547 FloatPoint(geometry->destRect().location()), | 565 FloatPoint(geometry->destRect().location()), |
| 548 FloatSize(geometry->tileSize()), FloatPoint(geometry->phase()), | 566 FloatSize(geometry->tileSize()), FloatPoint(geometry->phase()), |
| 549 FloatSize(geometry->spaceSize())); | 567 FloatSize(geometry->spaceSize())); |
| 550 | 568 |
| 551 // The tile is misaligned. | 569 // The tile is misaligned. |
| 552 if (!imageTile.contains(FloatRect(rect))) | 570 if (!imageTile.contains(FloatRect(rect))) |
| 553 return false; | 571 return false; |
| 554 } | 572 } |
| 555 } | 573 } |
| 556 | 574 |
| 557 // At this point we're committed to the fast path: the destination (r)rect fit
s within a single | 575 // At this point we're committed to the fast path: the destination (r)rect |
| 558 // tile, and we can paint it using direct draw(R)Rect() calls. | 576 // fits within a single tile, and we can paint it using direct draw(R)Rect() |
| 577 // calls. |
| 559 GraphicsContext& context = paintInfo.context; | 578 GraphicsContext& context = paintInfo.context; |
| 560 FloatRoundedRect border = | 579 FloatRoundedRect border = |
| 561 info.isRoundedFill ? backgroundRoundedRectAdjustedForBleedAvoidance( | 580 info.isRoundedFill ? backgroundRoundedRectAdjustedForBleedAvoidance( |
| 562 obj, rect, bleedAvoidance, box, boxSize, | 581 obj, rect, bleedAvoidance, box, boxSize, |
| 563 info.includeLeftEdge, info.includeRightEdge) | 582 info.includeLeftEdge, info.includeRightEdge) |
| 564 : FloatRoundedRect(pixelSnappedIntRect(rect)); | 583 : FloatRoundedRect(pixelSnappedIntRect(rect)); |
| 565 | 584 |
| 566 Optional<RoundedInnerRectClipper> clipper; | 585 Optional<RoundedInnerRectClipper> clipper; |
| 567 if (info.isRoundedFill && !border.isRenderable()) { | 586 if (info.isRoundedFill && !border.isRenderable()) { |
| 568 // When the rrect is not renderable, we resort to clipping. | 587 // When the rrect is not renderable, we resort to clipping. |
| 569 // RoundedInnerRectClipper handles this case via discrete, corner-wise clipp
ing. | 588 // RoundedInnerRectClipper handles this case via discrete, corner-wise |
| 589 // clipping. |
| 570 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext); | 590 clipper.emplace(obj, paintInfo, rect, border, ApplyToContext); |
| 571 border.setRadii(FloatRoundedRect::Radii()); | 591 border.setRadii(FloatRoundedRect::Radii()); |
| 572 } | 592 } |
| 573 | 593 |
| 574 // Paint the color + shadow if needed. | 594 // Paint the color + shadow if needed. |
| 575 if (info.shouldPaintColor) { | 595 if (info.shouldPaintColor) { |
| 576 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); | 596 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); |
| 577 context.fillRoundedRect(border, info.color); | 597 context.fillRoundedRect(border, info.color); |
| 578 } | 598 } |
| 579 | 599 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 context, info.isClippedWithLocalScrolling); | 687 context, info.isClippedWithLocalScrolling); |
| 668 LayoutRect scrolledPaintRect = rect; | 688 LayoutRect scrolledPaintRect = rect; |
| 669 if (info.isClippedWithLocalScrolling && | 689 if (info.isClippedWithLocalScrolling && |
| 670 !isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( | 690 !isPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer( |
| 671 &obj, paintInfo)) { | 691 &obj, paintInfo)) { |
| 672 // Clip to the overflow area. | 692 // Clip to the overflow area. |
| 673 const LayoutBox& thisBox = toLayoutBox(obj); | 693 const LayoutBox& thisBox = toLayoutBox(obj); |
| 674 // TODO(chrishtr): this should be pixel-snapped. | 694 // TODO(chrishtr): this should be pixel-snapped. |
| 675 context.clip(FloatRect(thisBox.overflowClipRect(rect.location()))); | 695 context.clip(FloatRect(thisBox.overflowClipRect(rect.location()))); |
| 676 | 696 |
| 677 // Adjust the paint rect to reflect a scrolled content box with borders at t
he ends. | 697 // Adjust the paint rect to reflect a scrolled content box with borders at |
| 698 // the ends. |
| 678 IntSize offset = thisBox.scrolledContentOffset(); | 699 IntSize offset = thisBox.scrolledContentOffset(); |
| 679 scrolledPaintRect.move(-offset); | 700 scrolledPaintRect.move(-offset); |
| 680 scrolledPaintRect.setWidth(bLeft + thisBox.scrollWidth() + bRight); | 701 scrolledPaintRect.setWidth(bLeft + thisBox.scrollWidth() + bRight); |
| 681 scrolledPaintRect.setHeight(thisBox.borderTop() + thisBox.scrollHeight() + | 702 scrolledPaintRect.setHeight(thisBox.borderTop() + thisBox.scrollHeight() + |
| 682 thisBox.borderBottom()); | 703 thisBox.borderBottom()); |
| 683 } | 704 } |
| 684 | 705 |
| 685 GraphicsContextStateSaver backgroundClipStateSaver(context, false); | 706 GraphicsContextStateSaver backgroundClipStateSaver(context, false); |
| 686 IntRect maskRect; | 707 IntRect maskRect; |
| 687 | 708 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 703 scrolledPaintRect.height() - obj.borderTop() - obj.borderBottom() - | 724 scrolledPaintRect.height() - obj.borderTop() - obj.borderBottom() - |
| 704 (includePadding ? obj.paddingTop() + obj.paddingBottom() | 725 (includePadding ? obj.paddingTop() + obj.paddingBottom() |
| 705 : LayoutUnit())); | 726 : LayoutUnit())); |
| 706 backgroundClipStateSaver.save(); | 727 backgroundClipStateSaver.save(); |
| 707 // TODO(chrishtr): this should be pixel-snapped. | 728 // TODO(chrishtr): this should be pixel-snapped. |
| 708 context.clip(FloatRect(clipRect)); | 729 context.clip(FloatRect(clipRect)); |
| 709 | 730 |
| 710 break; | 731 break; |
| 711 } | 732 } |
| 712 case TextFillBox: { | 733 case TextFillBox: { |
| 713 // First figure out how big the mask has to be. It should be no bigger tha
n what we need | 734 // First figure out how big the mask has to be. It should be no bigger |
| 714 // to actually render, so we should intersect the dirty rect with the bord
er box of the background. | 735 // than what we need to actually render, so we should intersect the dirty |
| 736 // rect with the border box of the background. |
| 715 maskRect = pixelSnappedIntRect(rect); | 737 maskRect = pixelSnappedIntRect(rect); |
| 716 | 738 |
| 717 // We draw the background into a separate layer, to be later masked with y
et another layer | 739 // We draw the background into a separate layer, to be later masked with |
| 718 // holding the text content. | 740 // yet another layer holding the text content. |
| 719 backgroundClipStateSaver.save(); | 741 backgroundClipStateSaver.save(); |
| 720 context.clip(maskRect); | 742 context.clip(maskRect); |
| 721 context.beginLayer(); | 743 context.beginLayer(); |
| 722 | 744 |
| 723 break; | 745 break; |
| 724 } | 746 } |
| 725 case BorderFillBox: | 747 case BorderFillBox: |
| 726 break; | 748 break; |
| 727 default: | 749 default: |
| 728 ASSERT_NOT_REACHED(); | 750 ASSERT_NOT_REACHED(); |
| 729 break; | 751 break; |
| 730 } | 752 } |
| 731 | 753 |
| 732 // Paint the color first underneath all images, culled if background image occ
ludes it. | 754 // Paint the color first underneath all images, culled if background image |
| 733 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the cull
ing test | 755 // occludes it. |
| 734 // by verifying whether the background image covers the entire painting area. | 756 // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the |
| 757 // culling test by verifying whether the background image covers the entire |
| 758 // painting area. |
| 735 if (info.isBottomLayer && info.color.alpha()) { | 759 if (info.isBottomLayer && info.color.alpha()) { |
| 736 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); | 760 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); |
| 737 if (info.shouldPaintColor || info.shouldPaintShadow) { | 761 if (info.shouldPaintColor || info.shouldPaintShadow) { |
| 738 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); | 762 const ShadowContext shadowContext(context, obj, info.shouldPaintShadow); |
| 739 context.fillRect(backgroundRect, info.color); | 763 context.fillRect(backgroundRect, info.color); |
| 740 } | 764 } |
| 741 } | 765 } |
| 742 | 766 |
| 743 // no progressive loading of the background image | 767 // no progressive loading of the background image |
| 744 if (info.shouldPaintImage) { | 768 if (info.shouldPaintImage) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 763 imageContext.image(), FloatRect(geometry->destRect()), | 787 imageContext.image(), FloatRect(geometry->destRect()), |
| 764 FloatPoint(geometry->phase()), FloatSize(geometry->tileSize()), | 788 FloatPoint(geometry->phase()), FloatSize(geometry->tileSize()), |
| 765 imageContext.compositeOp(), FloatSize(geometry->spaceSize())); | 789 imageContext.compositeOp(), FloatSize(geometry->spaceSize())); |
| 766 } | 790 } |
| 767 } | 791 } |
| 768 | 792 |
| 769 if (bgLayer.clip() == TextFillBox) { | 793 if (bgLayer.clip() == TextFillBox) { |
| 770 // Create the text mask layer. | 794 // Create the text mask layer. |
| 771 context.beginLayer(1, SkXfermode::kDstIn_Mode); | 795 context.beginLayer(1, SkXfermode::kDstIn_Mode); |
| 772 | 796 |
| 773 // Now draw the text into the mask. We do this by painting using a special p
aint phase that signals to | 797 // Now draw the text into the mask. We do this by painting using a special |
| 798 // paint phase that signals to |
| 774 // InlineTextBoxes that they should just add their contents to the clip. | 799 // InlineTextBoxes that they should just add their contents to the clip. |
| 775 PaintInfo info(context, maskRect, PaintPhaseTextClip, | 800 PaintInfo info(context, maskRect, PaintPhaseTextClip, |
| 776 GlobalPaintNormalPhase, 0); | 801 GlobalPaintNormalPhase, 0); |
| 777 if (box) { | 802 if (box) { |
| 778 const RootInlineBox& root = box->root(); | 803 const RootInlineBox& root = box->root(); |
| 779 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), | 804 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), |
| 780 scrolledPaintRect.y() - box->y()), | 805 scrolledPaintRect.y() - box->y()), |
| 781 root.lineTop(), root.lineBottom()); | 806 root.lineTop(), root.lineBottom()); |
| 782 } else { | 807 } else { |
| 783 // FIXME: this should only have an effect for the line box list within |ob
j|. Change this to create a LineBoxListPainter directly. | 808 // FIXME: this should only have an effect for the line box list within |
| 809 // |obj|. Change this to create a LineBoxListPainter directly. |
| 784 LayoutSize localOffset = | 810 LayoutSize localOffset = |
| 785 obj.isBox() ? toLayoutBox(&obj)->locationOffset() : LayoutSize(); | 811 obj.isBox() ? toLayoutBox(&obj)->locationOffset() : LayoutSize(); |
| 786 obj.paint(info, scrolledPaintRect.location() - localOffset); | 812 obj.paint(info, scrolledPaintRect.location() - localOffset); |
| 787 } | 813 } |
| 788 | 814 |
| 789 context.endLayer(); | 815 context.endLayer(); |
| 790 context.endLayer(); | 816 context.endLayer(); |
| 791 } | 817 } |
| 792 } | 818 } |
| 793 | 819 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 819 bool flattenCompositingLayers = | 845 bool flattenCompositingLayers = |
| 820 paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers; | 846 paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers; |
| 821 | 847 |
| 822 bool allMaskImagesLoaded = true; | 848 bool allMaskImagesLoaded = true; |
| 823 | 849 |
| 824 if (!compositedMask || flattenCompositingLayers) { | 850 if (!compositedMask || flattenCompositingLayers) { |
| 825 pushTransparencyLayer = true; | 851 pushTransparencyLayer = true; |
| 826 StyleImage* maskBoxImage = m_layoutBox.style()->maskBoxImage().image(); | 852 StyleImage* maskBoxImage = m_layoutBox.style()->maskBoxImage().image(); |
| 827 const FillLayer& maskLayers = m_layoutBox.style()->maskLayers(); | 853 const FillLayer& maskLayers = m_layoutBox.style()->maskLayers(); |
| 828 | 854 |
| 829 // Don't render a masked element until all the mask images have loaded, to p
revent a flash of unmasked content. | 855 // Don't render a masked element until all the mask images have loaded, to |
| 856 // prevent a flash of unmasked content. |
| 830 if (maskBoxImage) | 857 if (maskBoxImage) |
| 831 allMaskImagesLoaded &= maskBoxImage->isLoaded(); | 858 allMaskImagesLoaded &= maskBoxImage->isLoaded(); |
| 832 | 859 |
| 833 allMaskImagesLoaded &= maskLayers.imagesAreLoaded(); | 860 allMaskImagesLoaded &= maskLayers.imagesAreLoaded(); |
| 834 | 861 |
| 835 paintInfo.context.beginLayer(1, SkXfermode::kDstIn_Mode); | 862 paintInfo.context.beginLayer(1, SkXfermode::kDstIn_Mode); |
| 836 } | 863 } |
| 837 | 864 |
| 838 if (allMaskImagesLoaded) { | 865 if (allMaskImagesLoaded) { |
| 839 paintFillLayers(paintInfo, Color::transparent, | 866 paintFillLayers(paintInfo, Color::transparent, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 includeLogicalRightEdge); | 932 includeLogicalRightEdge); |
| 906 borderPainter.paintBorder(info, rect); | 933 borderPainter.paintBorder(info, rect); |
| 907 } | 934 } |
| 908 | 935 |
| 909 void BoxPainter::paintBoxShadow(const PaintInfo& info, | 936 void BoxPainter::paintBoxShadow(const PaintInfo& info, |
| 910 const LayoutRect& paintRect, | 937 const LayoutRect& paintRect, |
| 911 const ComputedStyle& style, | 938 const ComputedStyle& style, |
| 912 ShadowStyle shadowStyle, | 939 ShadowStyle shadowStyle, |
| 913 bool includeLogicalLeftEdge, | 940 bool includeLogicalLeftEdge, |
| 914 bool includeLogicalRightEdge) { | 941 bool includeLogicalRightEdge) { |
| 915 // FIXME: Deal with border-image. Would be great to use border-image as a mask
. | 942 // FIXME: Deal with border-image. Would be great to use border-image as a |
| 943 // mask. |
| 916 GraphicsContext& context = info.context; | 944 GraphicsContext& context = info.context; |
| 917 if (!style.boxShadow()) | 945 if (!style.boxShadow()) |
| 918 return; | 946 return; |
| 919 FloatRoundedRect border = | 947 FloatRoundedRect border = |
| 920 (shadowStyle == Inset) | 948 (shadowStyle == Inset) |
| 921 ? style.getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, | 949 ? style.getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, |
| 922 includeLogicalRightEdge) | 950 includeLogicalRightEdge) |
| 923 : style.getRoundedBorderFor(paintRect, includeLogicalLeftEdge, | 951 : style.getRoundedBorderFor(paintRect, includeLogicalLeftEdge, |
| 924 includeLogicalRightEdge); | 952 includeLogicalRightEdge); |
| 925 | 953 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 956 shadowRect.inflate(shadowBlur + shadowSpread); | 984 shadowRect.inflate(shadowBlur + shadowSpread); |
| 957 shadowRect.move(shadowOffset); | 985 shadowRect.move(shadowOffset); |
| 958 | 986 |
| 959 // Save the state and clip, if not already done. | 987 // Save the state and clip, if not already done. |
| 960 // The clip does not depend on any shadow-specific properties. | 988 // The clip does not depend on any shadow-specific properties. |
| 961 if (!stateSaver.saved()) { | 989 if (!stateSaver.saved()) { |
| 962 stateSaver.save(); | 990 stateSaver.save(); |
| 963 if (hasBorderRadius) { | 991 if (hasBorderRadius) { |
| 964 FloatRoundedRect rectToClipOut = border; | 992 FloatRoundedRect rectToClipOut = border; |
| 965 | 993 |
| 966 // If the box is opaque, it is unnecessary to clip it out. However, do
ing so saves time | 994 // If the box is opaque, it is unnecessary to clip it out. However, |
| 967 // when painting the shadow. On the other hand, it introduces subpixel
gaps along the | 995 // doing so saves time when painting the shadow. On the other hand, it |
| 968 // corners. Those are avoided by insetting the clipping path by one CS
S pixel. | 996 // introduces subpixel gaps along the corners. Those are avoided by |
| 997 // insetting the clipping path by one CSS pixel. |
| 969 if (hasOpaqueBackground) | 998 if (hasOpaqueBackground) |
| 970 rectToClipOut.inflateWithRadii(-1); | 999 rectToClipOut.inflateWithRadii(-1); |
| 971 | 1000 |
| 972 if (!rectToClipOut.isEmpty()) | 1001 if (!rectToClipOut.isEmpty()) |
| 973 context.clipOutRoundedRect(rectToClipOut); | 1002 context.clipOutRoundedRect(rectToClipOut); |
| 974 } else { | 1003 } else { |
| 975 // This IntRect is correct even with fractional shadows, because it is
used for the rectangle | 1004 // This IntRect is correct even with fractional shadows, because it is |
| 976 // of the box itself, which is always pixel-aligned. | 1005 // used for the rectangle of the box itself, which is always |
| 1006 // pixel-aligned. |
| 977 FloatRect rectToClipOut = border.rect(); | 1007 FloatRect rectToClipOut = border.rect(); |
| 978 | 1008 |
| 979 // If the box is opaque, it is unnecessary to clip it out. However, do
ing so saves time | 1009 // If the box is opaque, it is unnecessary to clip it out. However, |
| 980 // when painting the shadow. On the other hand, it introduces subpixel
gaps along the | 1010 // doing so saves time when painting the shadow. On the other hand, it |
| 981 // edges if they are not pixel-aligned. Those are avoided by insetting
the clipping path | 1011 // introduces subpixel gaps along the edges if they are not |
| 982 // by one CSS pixel. | 1012 // pixel-aligned. Those are avoided by insetting the clipping path by |
| 1013 // one CSS pixel. |
| 983 if (hasOpaqueBackground) | 1014 if (hasOpaqueBackground) |
| 984 rectToClipOut.inflate(-1); | 1015 rectToClipOut.inflate(-1); |
| 985 | 1016 |
| 986 if (!rectToClipOut.isEmpty()) | 1017 if (!rectToClipOut.isEmpty()) |
| 987 context.clipOut(rectToClipOut); | 1018 context.clipOut(rectToClipOut); |
| 988 } | 1019 } |
| 989 } | 1020 } |
| 990 | 1021 |
| 991 // Draw only the shadow. | 1022 // Draw only the shadow. |
| 992 context.setShadow(shadowOffset, shadowBlur, shadowColor, | 1023 context.setShadow(shadowOffset, shadowBlur, shadowColor, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy( | 1071 bool BoxPainter::shouldForceWhiteBackgroundForPrintEconomy( |
| 1041 const ComputedStyle& style, | 1072 const ComputedStyle& style, |
| 1042 const Document& document) { | 1073 const Document& document) { |
| 1043 return document.printing() && | 1074 return document.printing() && |
| 1044 style.getPrintColorAdjust() == PrintColorAdjustEconomy && | 1075 style.getPrintColorAdjust() == PrintColorAdjustEconomy && |
| 1045 (!document.settings() || | 1076 (!document.settings() || |
| 1046 !document.settings()->shouldPrintBackgrounds()); | 1077 !document.settings()->shouldPrintBackgrounds()); |
| 1047 } | 1078 } |
| 1048 | 1079 |
| 1049 } // namespace blink | 1080 } // namespace blink |
| OLD | NEW |