| 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" |
| 11 #include "core/layout/ImageQualityController.h" | 11 #include "core/layout/ImageQualityController.h" |
| 12 #include "core/layout/Layer.h" | 12 #include "core/layout/Layer.h" |
| 13 #include "core/layout/LayoutBox.h" |
| 13 #include "core/layout/LayoutBoxModelObject.h" | 14 #include "core/layout/LayoutBoxModelObject.h" |
| 14 #include "core/layout/LayoutObject.h" | 15 #include "core/layout/LayoutObject.h" |
| 15 #include "core/layout/LayoutTable.h" | 16 #include "core/layout/LayoutTable.h" |
| 16 #include "core/layout/LayoutTheme.h" | 17 #include "core/layout/LayoutTheme.h" |
| 17 #include "core/layout/PaintInfo.h" | 18 #include "core/layout/PaintInfo.h" |
| 18 #include "core/layout/compositing/CompositedLayerMapping.h" | 19 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 19 #include "core/layout/style/BorderEdge.h" | 20 #include "core/layout/style/BorderEdge.h" |
| 20 #include "core/layout/style/ShadowList.h" | 21 #include "core/layout/style/ShadowList.h" |
| 21 #include "core/paint/BackgroundImageGeometry.h" | 22 #include "core/paint/BackgroundImageGeometry.h" |
| 22 #include "core/paint/BoxDecorationData.h" | 23 #include "core/paint/BoxDecorationData.h" |
| 23 #include "core/paint/RenderDrawingRecorder.h" | 24 #include "core/paint/RenderDrawingRecorder.h" |
| 24 #include "core/paint/RoundedInnerRectClipper.h" | 25 #include "core/paint/RoundedInnerRectClipper.h" |
| 25 #include "core/rendering/RenderBox.h" | |
| 26 #include "core/rendering/RenderView.h" | 26 #include "core/rendering/RenderView.h" |
| 27 #include "platform/LengthFunctions.h" | 27 #include "platform/LengthFunctions.h" |
| 28 #include "platform/geometry/LayoutPoint.h" | 28 #include "platform/geometry/LayoutPoint.h" |
| 29 #include "platform/graphics/GraphicsContextStateSaver.h" | 29 #include "platform/graphics/GraphicsContextStateSaver.h" |
| 30 #include "platform/graphics/paint/CompositingDisplayItem.h" | 30 #include "platform/graphics/paint/CompositingDisplayItem.h" |
| 31 | 31 |
| 32 namespace blink { | 32 namespace blink { |
| 33 | 33 |
| 34 void BoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffse
t) | 34 void BoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffse
t) |
| 35 { | 35 { |
| 36 LayoutPoint adjustedPaintOffset = paintOffset + m_renderBox.location(); | 36 LayoutPoint adjustedPaintOffset = paintOffset + m_layoutBox.location(); |
| 37 // default implementation. Just pass paint through to the children | 37 // default implementation. Just pass paint through to the children |
| 38 PaintInfo childInfo(paintInfo); | 38 PaintInfo childInfo(paintInfo); |
| 39 childInfo.updatePaintingRootForChildren(&m_renderBox); | 39 childInfo.updatePaintingRootForChildren(&m_layoutBox); |
| 40 for (LayoutObject* child = m_renderBox.slowFirstChild(); child; child = chil
d->nextSibling()) | 40 for (LayoutObject* child = m_layoutBox.slowFirstChild(); child; child = chil
d->nextSibling()) |
| 41 child->paint(childInfo, adjustedPaintOffset); | 41 child->paint(childInfo, adjustedPaintOffset); |
| 42 } | 42 } |
| 43 | 43 |
| 44 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const
LayoutPoint& paintOffset) | 44 void BoxPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo, const
LayoutPoint& paintOffset) |
| 45 { | 45 { |
| 46 if (!paintInfo.shouldPaintWithinRoot(&m_renderBox)) | 46 if (!paintInfo.shouldPaintWithinRoot(&m_layoutBox)) |
| 47 return; | 47 return; |
| 48 | 48 |
| 49 LayoutRect paintRect = m_renderBox.borderBoxRect(); | 49 LayoutRect paintRect = m_layoutBox.borderBoxRect(); |
| 50 paintRect.moveBy(paintOffset); | 50 paintRect.moveBy(paintOffset); |
| 51 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); | 51 paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect); |
| 52 } | 52 } |
| 53 | 53 |
| 54 LayoutRect BoxPainter::boundsForDrawingRecorder(const LayoutPoint& paintOffset) | 54 LayoutRect BoxPainter::boundsForDrawingRecorder(const LayoutPoint& paintOffset) |
| 55 { | 55 { |
| 56 if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) | 56 if (!RuntimeEnabledFeatures::slimmingPaintEnabled()) |
| 57 return LayoutRect(); | 57 return LayoutRect(); |
| 58 | 58 |
| 59 // The document element is specified to paint its background infinitely. | 59 // The document element is specified to paint its background infinitely. |
| 60 if (m_renderBox.isDocumentElement()) | 60 if (m_layoutBox.isDocumentElement()) |
| 61 return scrolledBackgroundRect(); | 61 return scrolledBackgroundRect(); |
| 62 | 62 |
| 63 // Use the visual overflow rect here, because it will include overflow intro
duced by the theme. | 63 // Use the visual overflow rect here, because it will include overflow intro
duced by the theme. |
| 64 LayoutRect bounds = m_renderBox.visualOverflowRect(); | 64 LayoutRect bounds = m_layoutBox.visualOverflowRect(); |
| 65 bounds.moveBy(paintOffset); | 65 bounds.moveBy(paintOffset); |
| 66 return pixelSnappedIntRect(bounds); | 66 return pixelSnappedIntRect(bounds); |
| 67 } | 67 } |
| 68 | 68 |
| 69 LayoutRect BoxPainter::scrolledBackgroundRect() | 69 LayoutRect BoxPainter::scrolledBackgroundRect() |
| 70 { | 70 { |
| 71 RenderView* renderView = m_renderBox.view(); | 71 RenderView* renderView = m_layoutBox.view(); |
| 72 LayoutRect result = renderView->backgroundRect(&m_renderBox); | 72 LayoutRect result = renderView->backgroundRect(&m_layoutBox); |
| 73 if (renderView->hasOverflowClip()) | 73 if (renderView->hasOverflowClip()) |
| 74 result.move(-renderView->scrolledContentOffset()); | 74 result.move(-renderView->scrolledContentOffset()); |
| 75 return result; | 75 return result; |
| 76 } | 76 } |
| 77 | 77 |
| 78 void BoxPainter::paintBoxDecorationBackgroundWithRect(const PaintInfo& paintInfo
, const LayoutPoint& paintOffset, const LayoutRect& paintRect) | 78 void BoxPainter::paintBoxDecorationBackgroundWithRect(const PaintInfo& paintInfo
, const LayoutPoint& paintOffset, const LayoutRect& paintRect) |
| 79 { | 79 { |
| 80 RenderDrawingRecorder recorder(paintInfo.context, m_renderBox, DisplayItem::
BoxDecorationBackground, boundsForDrawingRecorder(paintOffset)); | 80 RenderDrawingRecorder recorder(paintInfo.context, m_layoutBox, DisplayItem::
BoxDecorationBackground, boundsForDrawingRecorder(paintOffset)); |
| 81 if (recorder.canUseCachedDrawing()) | 81 if (recorder.canUseCachedDrawing()) |
| 82 return; | 82 return; |
| 83 | 83 |
| 84 const LayoutStyle& style = m_renderBox.styleRef(); | 84 const LayoutStyle& style = m_layoutBox.styleRef(); |
| 85 BoxDecorationData boxDecorationData(m_renderBox, paintInfo.context); | 85 BoxDecorationData boxDecorationData(m_layoutBox, paintInfo.context); |
| 86 | 86 |
| 87 // FIXME: Should eventually give the theme control over whether the box shad
ow should paint, since controls could have | 87 // FIXME: Should eventually give the theme control over whether the box shad
ow should paint, since controls could have |
| 88 // custom shadows of their own. | 88 // custom shadows of their own. |
| 89 if (!m_renderBox.boxShadowShouldBeAppliedToBackground(boxDecorationData.blee
dAvoidance())) | 89 if (!m_layoutBox.boxShadowShouldBeAppliedToBackground(boxDecorationData.blee
dAvoidance())) |
| 90 paintBoxShadow(paintInfo, paintRect, style, Normal); | 90 paintBoxShadow(paintInfo, paintRect, style, Normal); |
| 91 | 91 |
| 92 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); | 92 GraphicsContextStateSaver stateSaver(*paintInfo.context, false); |
| 93 if (boxDecorationData.bleedAvoidance() == BackgroundBleedClipBackground) { | 93 if (boxDecorationData.bleedAvoidance() == BackgroundBleedClipBackground) { |
| 94 stateSaver.save(); | 94 stateSaver.save(); |
| 95 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); | 95 FloatRoundedRect border = style.getRoundedBorderFor(paintRect); |
| 96 paintInfo.context->clipRoundedRect(border); | 96 paintInfo.context->clipRoundedRect(border); |
| 97 } | 97 } |
| 98 | 98 |
| 99 // If we have a native theme appearance, paint that before painting our back
ground. | 99 // If we have a native theme appearance, paint that before painting our back
ground. |
| 100 // The theme will tell us whether or not we should also paint the CSS backgr
ound. | 100 // The theme will tell us whether or not we should also paint the CSS backgr
ound. |
| 101 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); | 101 IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); |
| 102 bool themePainted = boxDecorationData.hasAppearance && !LayoutTheme::theme()
.paint(&m_renderBox, paintInfo, snappedPaintRect); | 102 bool themePainted = boxDecorationData.hasAppearance && !LayoutTheme::theme()
.paint(&m_layoutBox, paintInfo, snappedPaintRect); |
| 103 if (!themePainted) { | 103 if (!themePainted) { |
| 104 if (boxDecorationData.bleedAvoidance() == BackgroundBleedBackgroundOverB
order) | 104 if (boxDecorationData.bleedAvoidance() == BackgroundBleedBackgroundOverB
order) |
| 105 paintBorder(m_renderBox, paintInfo, paintRect, style, boxDecorationD
ata.bleedAvoidance()); | 105 paintBorder(m_layoutBox, paintInfo, paintRect, style, boxDecorationD
ata.bleedAvoidance()); |
| 106 | 106 |
| 107 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor,
boxDecorationData.bleedAvoidance()); | 107 paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor,
boxDecorationData.bleedAvoidance()); |
| 108 | 108 |
| 109 if (boxDecorationData.hasAppearance) | 109 if (boxDecorationData.hasAppearance) |
| 110 LayoutTheme::theme().paintDecorations(&m_renderBox, paintInfo, snapp
edPaintRect); | 110 LayoutTheme::theme().paintDecorations(&m_layoutBox, paintInfo, snapp
edPaintRect); |
| 111 } | 111 } |
| 112 paintBoxShadow(paintInfo, paintRect, style, Inset); | 112 paintBoxShadow(paintInfo, paintRect, style, Inset); |
| 113 | 113 |
| 114 // The theme will tell us whether or not we should also paint the CSS border
. | 114 // The theme will tell us whether or not we should also paint the CSS border
. |
| 115 if (boxDecorationData.hasBorder && boxDecorationData.bleedAvoidance() != Bac
kgroundBleedBackgroundOverBorder | 115 if (boxDecorationData.hasBorder && boxDecorationData.bleedAvoidance() != Bac
kgroundBleedBackgroundOverBorder |
| 116 && (!boxDecorationData.hasAppearance || (!themePainted && LayoutTheme::t
heme().paintBorderOnly(&m_renderBox, paintInfo, snappedPaintRect))) | 116 && (!boxDecorationData.hasAppearance || (!themePainted && LayoutTheme::t
heme().paintBorderOnly(&m_layoutBox, paintInfo, snappedPaintRect))) |
| 117 && !(m_renderBox.isTable() && toLayoutTable(&m_renderBox)->collapseBorde
rs())) | 117 && !(m_layoutBox.isTable() && toLayoutTable(&m_layoutBox)->collapseBorde
rs())) |
| 118 paintBorder(m_renderBox, paintInfo, paintRect, style, boxDecorationData.
bleedAvoidance()); | 118 paintBorder(m_layoutBox, paintInfo, paintRect, style, boxDecorationData.
bleedAvoidance()); |
| 119 } | 119 } |
| 120 | 120 |
| 121 static bool skipBodyBackground(const RenderBox* bodyElementRenderer) | 121 static bool skipBodyBackground(const LayoutBox* bodyElementRenderer) |
| 122 { | 122 { |
| 123 ASSERT(bodyElementRenderer->isBody()); | 123 ASSERT(bodyElementRenderer->isBody()); |
| 124 // The <body> only paints its background if the root element has defined a b
ackground independent of the body, | 124 // The <body> only paints its background if the root element has defined a b
ackground independent of the body, |
| 125 // or if the <body>'s parent is not the document element's renderer (e.g. in
side SVG foreignObject). | 125 // or if the <body>'s parent is not the document element's renderer (e.g. in
side SVG foreignObject). |
| 126 LayoutObject* documentElementRenderer = bodyElementRenderer->document().docu
mentElement()->renderer(); | 126 LayoutObject* documentElementRenderer = bodyElementRenderer->document().docu
mentElement()->renderer(); |
| 127 return documentElementRenderer | 127 return documentElementRenderer |
| 128 && !documentElementRenderer->hasBackground() | 128 && !documentElementRenderer->hasBackground() |
| 129 && (documentElementRenderer == bodyElementRenderer->parent()); | 129 && (documentElementRenderer == bodyElementRenderer->parent()); |
| 130 } | 130 } |
| 131 | 131 |
| 132 void BoxPainter::paintBackground(const PaintInfo& paintInfo, const LayoutRect& p
aintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance) | 132 void BoxPainter::paintBackground(const PaintInfo& paintInfo, const LayoutRect& p
aintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance) |
| 133 { | 133 { |
| 134 if (m_renderBox.isDocumentElement()) { | 134 if (m_layoutBox.isDocumentElement()) { |
| 135 paintRootBoxFillLayers(paintInfo); | 135 paintRootBoxFillLayers(paintInfo); |
| 136 return; | 136 return; |
| 137 } | 137 } |
| 138 if (m_renderBox.isBody() && skipBodyBackground(&m_renderBox)) | 138 if (m_layoutBox.isBody() && skipBodyBackground(&m_layoutBox)) |
| 139 return; | 139 return; |
| 140 if (m_renderBox.boxDecorationBackgroundIsKnownToBeObscured()) | 140 if (m_layoutBox.boxDecorationBackgroundIsKnownToBeObscured()) |
| 141 return; | 141 return; |
| 142 paintFillLayers(paintInfo, backgroundColor, m_renderBox.style()->backgroundL
ayers(), paintRect, bleedAvoidance); | 142 paintFillLayers(paintInfo, backgroundColor, m_layoutBox.style()->backgroundL
ayers(), paintRect, bleedAvoidance); |
| 143 } | 143 } |
| 144 | 144 |
| 145 void BoxPainter::paintRootBoxFillLayers(const PaintInfo& paintInfo) | 145 void BoxPainter::paintRootBoxFillLayers(const PaintInfo& paintInfo) |
| 146 { | 146 { |
| 147 if (paintInfo.skipRootBackground()) | 147 if (paintInfo.skipRootBackground()) |
| 148 return; | 148 return; |
| 149 | 149 |
| 150 LayoutObject* rootBackgroundRenderer = m_renderBox.rendererForRootBackground
(); | 150 LayoutObject* rootBackgroundRenderer = m_layoutBox.rendererForRootBackground
(); |
| 151 | 151 |
| 152 const FillLayer& bgLayer = rootBackgroundRenderer->style()->backgroundLayers
(); | 152 const FillLayer& bgLayer = rootBackgroundRenderer->style()->backgroundLayers
(); |
| 153 Color bgColor = rootBackgroundRenderer->resolveColor(CSSPropertyBackgroundCo
lor); | 153 Color bgColor = rootBackgroundRenderer->resolveColor(CSSPropertyBackgroundCo
lor); |
| 154 | 154 |
| 155 paintFillLayers(paintInfo, bgColor, bgLayer, scrolledBackgroundRect(), Backg
roundBleedNone, SkXfermode::kSrcOver_Mode, rootBackgroundRenderer); | 155 paintFillLayers(paintInfo, bgColor, bgLayer, scrolledBackgroundRect(), Backg
roundBleedNone, SkXfermode::kSrcOver_Mode, rootBackgroundRenderer); |
| 156 } | 156 } |
| 157 | 157 |
| 158 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, con
st FillLayer& fillLayer, const LayoutRect& rect, | 158 void BoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, con
st FillLayer& fillLayer, const LayoutRect& rect, |
| 159 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject*
backgroundObject) | 159 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject*
backgroundObject) |
| 160 { | 160 { |
| 161 Vector<const FillLayer*, 8> layers; | 161 Vector<const FillLayer*, 8> layers; |
| 162 const FillLayer* curLayer = &fillLayer; | 162 const FillLayer* curLayer = &fillLayer; |
| 163 bool shouldDrawBackgroundInSeparateBuffer = false; | 163 bool shouldDrawBackgroundInSeparateBuffer = false; |
| 164 bool isBottomLayerOccluded = false; | 164 bool isBottomLayerOccluded = false; |
| 165 while (curLayer) { | 165 while (curLayer) { |
| 166 layers.append(curLayer); | 166 layers.append(curLayer); |
| 167 // Stop traversal when an opaque layer is encountered. | 167 // Stop traversal when an opaque layer is encountered. |
| 168 // FIXME : It would be possible for the following occlusion culling test
to be more aggressive | 168 // FIXME : It would be possible for the following occlusion culling test
to be more aggressive |
| 169 // on layers with no repeat by testing whether the image covers the layo
ut rect. | 169 // on layers with no repeat by testing whether the image covers the layo
ut rect. |
| 170 // Testing that here would imply duplicating a lot of calculations that
are currently done in | 170 // Testing that here would imply duplicating a lot of calculations that
are currently done in |
| 171 // LayoutBoxModelObject::paintFillLayerExtended. A more efficient soluti
on might be to move | 171 // LayoutBoxModelObject::paintFillLayerExtended. A more efficient soluti
on might be to move |
| 172 // the layer recursion into paintFillLayerExtended, or to compute the la
yer geometry here | 172 // the layer recursion into paintFillLayerExtended, or to compute the la
yer geometry here |
| 173 // and pass it down. | 173 // and pass it down. |
| 174 | 174 |
| 175 if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != We
bBlendModeNormal) | 175 if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != We
bBlendModeNormal) |
| 176 shouldDrawBackgroundInSeparateBuffer = true; | 176 shouldDrawBackgroundInSeparateBuffer = true; |
| 177 | 177 |
| 178 // The clipOccludesNextLayers condition must be evaluated first to avoid
short-circuiting. | 178 // The clipOccludesNextLayers condition must be evaluated first to avoid
short-circuiting. |
| 179 if (curLayer->clipOccludesNextLayers(curLayer == &fillLayer) | 179 if (curLayer->clipOccludesNextLayers(curLayer == &fillLayer) |
| 180 && curLayer->hasOpaqueImage(&m_renderBox) | 180 && curLayer->hasOpaqueImage(&m_layoutBox) |
| 181 && curLayer->image()->canRender(m_renderBox, m_renderBox.style()->ef
fectiveZoom()) | 181 && curLayer->image()->canRender(m_layoutBox, m_layoutBox.style()->ef
fectiveZoom()) |
| 182 && curLayer->hasRepeatXY() | 182 && curLayer->hasRepeatXY() |
| 183 && curLayer->blendMode() == WebBlendModeNormal | 183 && curLayer->blendMode() == WebBlendModeNormal |
| 184 && !m_renderBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)
) | 184 && !m_layoutBox.boxShadowShouldBeAppliedToBackground(bleedAvoidance)
) |
| 185 break; | 185 break; |
| 186 curLayer = curLayer->next(); | 186 curLayer = curLayer->next(); |
| 187 } | 187 } |
| 188 | 188 |
| 189 if (layers.size() > 0 && (**layers.rbegin()).next()) | 189 if (layers.size() > 0 && (**layers.rbegin()).next()) |
| 190 isBottomLayerOccluded = true; | 190 isBottomLayerOccluded = true; |
| 191 | 191 |
| 192 GraphicsContext* context = paintInfo.context; | 192 GraphicsContext* context = paintInfo.context; |
| 193 if (!context) | 193 if (!context) |
| 194 shouldDrawBackgroundInSeparateBuffer = false; | 194 shouldDrawBackgroundInSeparateBuffer = false; |
| 195 | 195 |
| 196 bool skipBaseColor = false; | 196 bool skipBaseColor = false; |
| 197 if (shouldDrawBackgroundInSeparateBuffer) { | 197 if (shouldDrawBackgroundInSeparateBuffer) { |
| 198 bool isBaseColorVisible = !isBottomLayerOccluded && c.hasAlpha(); | 198 bool isBaseColorVisible = !isBottomLayerOccluded && c.hasAlpha(); |
| 199 | 199 |
| 200 // Paint the document's base background color outside the transparency l
ayer, | 200 // Paint the document's base background color outside the transparency l
ayer, |
| 201 // so that the background images don't blend with this color: http://crb
ug.com/389039. | 201 // so that the background images don't blend with this color: http://crb
ug.com/389039. |
| 202 if (isBaseColorVisible && isDocumentElementWithOpaqueBackground(m_render
Box)) { | 202 if (isBaseColorVisible && isDocumentElementWithOpaqueBackground(m_layout
Box)) { |
| 203 paintRootBackgroundColor(m_renderBox, paintInfo, rect, Color()); | 203 paintRootBackgroundColor(m_layoutBox, paintInfo, rect, Color()); |
| 204 skipBaseColor = true; | 204 skipBaseColor = true; |
| 205 } | 205 } |
| 206 context->beginTransparencyLayer(1); | 206 context->beginTransparencyLayer(1); |
| 207 } | 207 } |
| 208 | 208 |
| 209 Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend(); | 209 Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend(); |
| 210 for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin();
it != topLayer; ++it) | 210 for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin();
it != topLayer; ++it) |
| 211 paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundO
bject, skipBaseColor); | 211 paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundO
bject, skipBaseColor); |
| 212 | 212 |
| 213 if (shouldDrawBackgroundInSeparateBuffer) | 213 if (shouldDrawBackgroundInSeparateBuffer) |
| 214 context->endLayer(); | 214 context->endLayer(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 void BoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, cons
t FillLayer& fillLayer, const LayoutRect& rect, | 217 void BoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, cons
t FillLayer& fillLayer, const LayoutRect& rect, |
| 218 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject*
backgroundObject, bool skipBaseColor) | 218 BackgroundBleedAvoidance bleedAvoidance, SkXfermode::Mode op, LayoutObject*
backgroundObject, bool skipBaseColor) |
| 219 { | 219 { |
| 220 BoxPainter::paintFillLayerExtended(m_renderBox, paintInfo, c, fillLayer, rec
t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, skipBaseColor); | 220 BoxPainter::paintFillLayerExtended(m_layoutBox, paintInfo, c, fillLayer, rec
t, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, skipBaseColor); |
| 221 } | 221 } |
| 222 | 222 |
| 223 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj
ect& obj) | 223 void BoxPainter::applyBoxShadowForBackground(GraphicsContext* context, LayoutObj
ect& obj) |
| 224 { | 224 { |
| 225 const ShadowList* shadowList = obj.style()->boxShadow(); | 225 const ShadowList* shadowList = obj.style()->boxShadow(); |
| 226 ASSERT(shadowList); | 226 ASSERT(shadowList); |
| 227 for (size_t i = shadowList->shadows().size(); i--; ) { | 227 for (size_t i = shadowList->shadows().size(); i--; ) { |
| 228 const ShadowData& boxShadow = shadowList->shadows()[i]; | 228 const ShadowData& boxShadow = shadowList->shadows()[i]; |
| 229 if (boxShadow.style() != Normal) | 229 if (boxShadow.style() != Normal) |
| 230 continue; | 230 continue; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 362 |
| 363 int bLeft = includeLeftEdge ? obj.borderLeft() : 0; | 363 int bLeft = includeLeftEdge ? obj.borderLeft() : 0; |
| 364 int bRight = includeRightEdge ? obj.borderRight() : 0; | 364 int bRight = includeRightEdge ? obj.borderRight() : 0; |
| 365 LayoutUnit pLeft = includeLeftEdge ? obj.paddingLeft() : LayoutUnit(); | 365 LayoutUnit pLeft = includeLeftEdge ? obj.paddingLeft() : LayoutUnit(); |
| 366 LayoutUnit pRight = includeRightEdge ? obj.paddingRight() : LayoutUnit(); | 366 LayoutUnit pRight = includeRightEdge ? obj.paddingRight() : LayoutUnit(); |
| 367 | 367 |
| 368 GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithL
ocalScrolling); | 368 GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithL
ocalScrolling); |
| 369 LayoutRect scrolledPaintRect = rect; | 369 LayoutRect scrolledPaintRect = rect; |
| 370 if (clippedWithLocalScrolling) { | 370 if (clippedWithLocalScrolling) { |
| 371 // Clip to the overflow area. | 371 // Clip to the overflow area. |
| 372 RenderBox* thisBox = toRenderBox(&obj); | 372 LayoutBox* thisBox = toLayoutBox(&obj); |
| 373 context->clip(thisBox->overflowClipRect(rect.location())); | 373 context->clip(thisBox->overflowClipRect(rect.location())); |
| 374 | 374 |
| 375 // Adjust the paint rect to reflect a scrolled content box with borders
at the ends. | 375 // Adjust the paint rect to reflect a scrolled content box with borders
at the ends. |
| 376 IntSize offset = thisBox->scrolledContentOffset(); | 376 IntSize offset = thisBox->scrolledContentOffset(); |
| 377 scrolledPaintRect.move(-offset); | 377 scrolledPaintRect.move(-offset); |
| 378 scrolledPaintRect.setWidth(bLeft + thisBox->scrollWidth() + bRight); | 378 scrolledPaintRect.setWidth(bLeft + thisBox->scrollWidth() + bRight); |
| 379 scrolledPaintRect.setHeight(thisBox->borderTop() + thisBox->scrollHeight
() + thisBox->borderBottom()); | 379 scrolledPaintRect.setHeight(thisBox->borderTop() + thisBox->scrollHeight
() + thisBox->borderBottom()); |
| 380 } | 380 } |
| 381 | 381 |
| 382 GraphicsContextStateSaver backgroundClipStateSaver(*context, false); | 382 GraphicsContextStateSaver backgroundClipStateSaver(*context, false); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 break; | 420 break; |
| 421 } | 421 } |
| 422 | 422 |
| 423 // Paint the color first underneath all images, culled if background image o
ccludes it. | 423 // Paint the color first underneath all images, culled if background image o
ccludes it. |
| 424 // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culli
ng test | 424 // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culli
ng test |
| 425 // by verifying whether the background image covers the entire layout rect. | 425 // by verifying whether the background image covers the entire layout rect. |
| 426 if (isBottomLayer) { | 426 if (isBottomLayer) { |
| 427 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); | 427 IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect)); |
| 428 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied
ToBackground(bleedAvoidance, box); | 428 bool boxShadowShouldBeAppliedToBackground = obj.boxShadowShouldBeApplied
ToBackground(bleedAvoidance, box); |
| 429 bool isOpaqueRoot = (isDocumentElementRenderer && !bgColor.hasAlpha()) |
| isDocumentElementWithOpaqueBackground(obj); | 429 bool isOpaqueRoot = (isDocumentElementRenderer && !bgColor.hasAlpha()) |
| isDocumentElementWithOpaqueBackground(obj); |
| 430 if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage
|| !bgLayer.hasOpaqueImage(&obj) || !bgLayer.hasRepeatXY() || (isOpaqueRoot && !
toRenderBox(&obj)->size().height())) { | 430 if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage
|| !bgLayer.hasOpaqueImage(&obj) || !bgLayer.hasRepeatXY() || (isOpaqueRoot && !
toLayoutBox(&obj)->size().height())) { |
| 431 if (!boxShadowShouldBeAppliedToBackground) | 431 if (!boxShadowShouldBeAppliedToBackground) |
| 432 backgroundRect.intersect(paintInfo.rect); | 432 backgroundRect.intersect(paintInfo.rect); |
| 433 | 433 |
| 434 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould
BeAppliedToBackground); | 434 GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShould
BeAppliedToBackground); |
| 435 if (boxShadowShouldBeAppliedToBackground) | 435 if (boxShadowShouldBeAppliedToBackground) |
| 436 BoxPainter::applyBoxShadowForBackground(context, obj); | 436 BoxPainter::applyBoxShadowForBackground(context, obj); |
| 437 | 437 |
| 438 if (isOpaqueRoot && !skipBaseColor) { | 438 if (isOpaqueRoot && !skipBaseColor) { |
| 439 paintRootBackgroundColor(obj, paintInfo, rect, bgColor); | 439 paintRootBackgroundColor(obj, paintInfo, rect, bgColor); |
| 440 } else if (bgColor.alpha()) { | 440 } else if (bgColor.alpha()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 | 475 |
| 476 // Now draw the text into the mask. We do this by painting using a speci
al paint phase that signals to | 476 // Now draw the text into the mask. We do this by painting using a speci
al paint phase that signals to |
| 477 // InlineTextBoxes that they should just add their contents to the clip. | 477 // InlineTextBoxes that they should just add their contents to the clip. |
| 478 PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForce
BlackText, 0); | 478 PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForce
BlackText, 0); |
| 479 context->setCompositeOperation(SkXfermode::kSrcOver_Mode); | 479 context->setCompositeOperation(SkXfermode::kSrcOver_Mode); |
| 480 if (box) { | 480 if (box) { |
| 481 RootInlineBox& root = box->root(); | 481 RootInlineBox& root = box->root(); |
| 482 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrol
ledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom()); | 482 box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrol
ledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom()); |
| 483 } else { | 483 } else { |
| 484 // FIXME: this should only have an effect for the line box list with
in |obj|. Change this to create a LineBoxListPainter directly. | 484 // FIXME: this should only have an effect for the line box list with
in |obj|. Change this to create a LineBoxListPainter directly. |
| 485 LayoutSize localOffset = obj.isBox() ? toRenderBox(&obj)->locationOf
fset() : LayoutSize(); | 485 LayoutSize localOffset = obj.isBox() ? toLayoutBox(&obj)->locationOf
fset() : LayoutSize(); |
| 486 obj.paint(info, scrolledPaintRect.location() - localOffset); | 486 obj.paint(info, scrolledPaintRect.location() - localOffset); |
| 487 } | 487 } |
| 488 | 488 |
| 489 context->endLayer(); | 489 context->endLayer(); |
| 490 context->endLayer(); | 490 context->endLayer(); |
| 491 } | 491 } |
| 492 } | 492 } |
| 493 | 493 |
| 494 void BoxPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintO
ffset) | 494 void BoxPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintO
ffset) |
| 495 { | 495 { |
| 496 if (!paintInfo.shouldPaintWithinRoot(&m_renderBox) || m_renderBox.style()->v
isibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) | 496 if (!paintInfo.shouldPaintWithinRoot(&m_layoutBox) || m_layoutBox.style()->v
isibility() != VISIBLE || paintInfo.phase != PaintPhaseMask) |
| 497 return; | 497 return; |
| 498 | 498 |
| 499 LayoutRect paintRect = LayoutRect(paintOffset, m_renderBox.size()); | 499 LayoutRect paintRect = LayoutRect(paintOffset, m_layoutBox.size()); |
| 500 paintMaskImages(paintInfo, paintRect); | 500 paintMaskImages(paintInfo, paintRect); |
| 501 } | 501 } |
| 502 | 502 |
| 503 void BoxPainter::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& p
aintRect) | 503 void BoxPainter::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& p
aintRect) |
| 504 { | 504 { |
| 505 // Figure out if we need to push a transparency layer to render our mask. | 505 // Figure out if we need to push a transparency layer to render our mask. |
| 506 bool pushTransparencyLayer = false; | 506 bool pushTransparencyLayer = false; |
| 507 bool compositedMask = m_renderBox.hasLayer() && m_renderBox.layer()->hasComp
ositedMask(); | 507 bool compositedMask = m_layoutBox.hasLayer() && m_layoutBox.layer()->hasComp
ositedMask(); |
| 508 bool flattenCompositingLayers = m_renderBox.view()->frameView() && m_renderB
ox.view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers; | 508 bool flattenCompositingLayers = m_layoutBox.view()->frameView() && m_layoutB
ox.view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers; |
| 509 | 509 |
| 510 bool allMaskImagesLoaded = true; | 510 bool allMaskImagesLoaded = true; |
| 511 | 511 |
| 512 SkXfermode::Mode previousCompositeOperation = paintInfo.context->compositeOp
eration(); | 512 SkXfermode::Mode previousCompositeOperation = paintInfo.context->compositeOp
eration(); |
| 513 | 513 |
| 514 if (!compositedMask || flattenCompositingLayers) { | 514 if (!compositedMask || flattenCompositingLayers) { |
| 515 pushTransparencyLayer = true; | 515 pushTransparencyLayer = true; |
| 516 StyleImage* maskBoxImage = m_renderBox.style()->maskBoxImage().image(); | 516 StyleImage* maskBoxImage = m_layoutBox.style()->maskBoxImage().image(); |
| 517 const FillLayer& maskLayers = m_renderBox.style()->maskLayers(); | 517 const FillLayer& maskLayers = m_layoutBox.style()->maskLayers(); |
| 518 | 518 |
| 519 // Don't render a masked element until all the mask images have loaded,
to prevent a flash of unmasked content. | 519 // Don't render a masked element until all the mask images have loaded,
to prevent a flash of unmasked content. |
| 520 if (maskBoxImage) | 520 if (maskBoxImage) |
| 521 allMaskImagesLoaded &= maskBoxImage->isLoaded(); | 521 allMaskImagesLoaded &= maskBoxImage->isLoaded(); |
| 522 | 522 |
| 523 allMaskImagesLoaded &= maskLayers.imagesAreLoaded(); | 523 allMaskImagesLoaded &= maskLayers.imagesAreLoaded(); |
| 524 | 524 |
| 525 paintInfo.context->setCompositeOperation(SkXfermode::kDstIn_Mode); | 525 paintInfo.context->setCompositeOperation(SkXfermode::kDstIn_Mode); |
| 526 paintInfo.context->beginTransparencyLayer(1); | 526 paintInfo.context->beginTransparencyLayer(1); |
| 527 } | 527 } |
| 528 | 528 |
| 529 if (allMaskImagesLoaded) { | 529 if (allMaskImagesLoaded) { |
| 530 paintFillLayers(paintInfo, Color::transparent, m_renderBox.style()->mask
Layers(), paintRect, BackgroundBleedNone, SkXfermode::kSrcOver_Mode); | 530 paintFillLayers(paintInfo, Color::transparent, m_layoutBox.style()->mask
Layers(), paintRect, BackgroundBleedNone, SkXfermode::kSrcOver_Mode); |
| 531 paintNinePieceImage(m_renderBox, paintInfo.context, paintRect, m_renderB
ox.styleRef(), m_renderBox.style()->maskBoxImage(), SkXfermode::kSrcOver_Mode); | 531 paintNinePieceImage(m_layoutBox, paintInfo.context, paintRect, m_layoutB
ox.styleRef(), m_layoutBox.style()->maskBoxImage(), SkXfermode::kSrcOver_Mode); |
| 532 } | 532 } |
| 533 | 533 |
| 534 if (pushTransparencyLayer) { | 534 if (pushTransparencyLayer) { |
| 535 paintInfo.context->endLayer(); | 535 paintInfo.context->endLayer(); |
| 536 paintInfo.context->setCompositeOperation(previousCompositeOperation); | 536 paintInfo.context->setCompositeOperation(previousCompositeOperation); |
| 537 } | 537 } |
| 538 } | 538 } |
| 539 | 539 |
| 540 void BoxPainter::paintClippingMask(const PaintInfo& paintInfo, const LayoutPoint
& paintOffset) | 540 void BoxPainter::paintClippingMask(const PaintInfo& paintInfo, const LayoutPoint
& paintOffset) |
| 541 { | 541 { |
| 542 if (!paintInfo.shouldPaintWithinRoot(&m_renderBox) || m_renderBox.style()->v
isibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask) | 542 if (!paintInfo.shouldPaintWithinRoot(&m_layoutBox) || m_layoutBox.style()->v
isibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask) |
| 543 return; | 543 return; |
| 544 | 544 |
| 545 if (!m_renderBox.layer() || m_renderBox.layer()->compositingState() != Paint
sIntoOwnBacking) | 545 if (!m_layoutBox.layer() || m_layoutBox.layer()->compositingState() != Paint
sIntoOwnBacking) |
| 546 return; | 546 return; |
| 547 | 547 |
| 548 LayoutRect paintRect = LayoutRect(paintOffset, m_renderBox.size()); | 548 LayoutRect paintRect = LayoutRect(paintOffset, m_layoutBox.size()); |
| 549 paintInfo.context->fillRect(pixelSnappedIntRect(paintRect), Color::black); | 549 paintInfo.context->fillRect(pixelSnappedIntRect(paintRect), Color::black); |
| 550 } | 550 } |
| 551 | 551 |
| 552 void BoxPainter::paintRootBackgroundColor(LayoutObject& obj, const PaintInfo& pa
intInfo, const LayoutRect& rect, const Color& bgColor) | 552 void BoxPainter::paintRootBackgroundColor(LayoutObject& obj, const PaintInfo& pa
intInfo, const LayoutRect& rect, const Color& bgColor) |
| 553 { | 553 { |
| 554 GraphicsContext* context = paintInfo.context; | 554 GraphicsContext* context = paintInfo.context; |
| 555 if (rect.isEmpty()) | 555 if (rect.isEmpty()) |
| 556 return; | 556 return; |
| 557 | 557 |
| 558 ASSERT(obj.isDocumentElement()); | 558 ASSERT(obj.isDocumentElement()); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 right += obj.paddingRight(); | 659 right += obj.paddingRight(); |
| 660 top += obj.paddingTop(); | 660 top += obj.paddingTop(); |
| 661 bottom += obj.paddingBottom(); | 661 bottom += obj.paddingBottom(); |
| 662 } | 662 } |
| 663 } | 663 } |
| 664 | 664 |
| 665 // The background of the box generated by the root element covers the en
tire canvas including | 665 // The background of the box generated by the root element covers the en
tire canvas including |
| 666 // its margins. Since those were added in already, we have to factor the
m out when computing | 666 // its margins. Since those were added in already, we have to factor the
m out when computing |
| 667 // the background positioning area. | 667 // the background positioning area. |
| 668 if (obj.isDocumentElement()) { | 668 if (obj.isDocumentElement()) { |
| 669 positioningAreaSize = pixelSnappedIntSize(toRenderBox(&obj)->size()
- LayoutSize(left + right, top + bottom), toRenderBox(&obj)->location()); | 669 positioningAreaSize = pixelSnappedIntSize(toLayoutBox(&obj)->size()
- LayoutSize(left + right, top + bottom), toLayoutBox(&obj)->location()); |
| 670 left += obj.marginLeft(); | 670 left += obj.marginLeft(); |
| 671 top += obj.marginTop(); | 671 top += obj.marginTop(); |
| 672 } else { | 672 } else { |
| 673 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS
ize(left + right, top + bottom), paintRect.location()); | 673 positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutS
ize(left + right, top + bottom), paintRect.location()); |
| 674 } | 674 } |
| 675 } else { | 675 } else { |
| 676 geometry.setHasNonLocalGeometry(); | 676 geometry.setHasNonLocalGeometry(); |
| 677 | 677 |
| 678 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); | 678 IntRect viewportRect = pixelSnappedIntRect(obj.viewRect()); |
| 679 if (fixedBackgroundPaintsInLocalCoordinates(obj)) | 679 if (fixedBackgroundPaintsInLocalCoordinates(obj)) |
| (...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 | 2191 |
| 2192 FloatPoint secondQuad[4]; | 2192 FloatPoint secondQuad[4]; |
| 2193 secondQuad[0] = quad[0]; | 2193 secondQuad[0] = quad[0]; |
| 2194 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); | 2194 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); |
| 2195 secondQuad[2] = quad[2]; | 2195 secondQuad[2] = quad[2]; |
| 2196 secondQuad[3] = quad[3]; | 2196 secondQuad[3] = quad[3]; |
| 2197 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches); | 2197 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches); |
| 2198 } | 2198 } |
| 2199 | 2199 |
| 2200 } // namespace blink | 2200 } // namespace blink |
| OLD | NEW |