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 |