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/LayerPainter.h" | 6 #include "core/paint/LayerPainter.h" |
7 | 7 |
8 #include "core/frame/Settings.h" | 8 #include "core/frame/Settings.h" |
9 #include "core/page/Page.h" | 9 #include "core/page/Page.h" |
10 #include "core/paint/FilterPainter.h" | 10 #include "core/paint/FilterPainter.h" |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform)
; | 151 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform)
; |
152 | 152 |
153 // Paint the reflection first if we have one. | 153 // Paint the reflection first if we have one. |
154 if (m_renderLayer.reflectionInfo()) | 154 if (m_renderLayer.reflectionInfo()) |
155 m_renderLayer.reflectionInfo()->paint(context, paintingInfo, localPaintF
lags | PaintLayerPaintingReflection); | 155 m_renderLayer.reflectionInfo()->paint(context, paintingInfo, localPaintF
lags | PaintLayerPaintingReflection); |
156 | 156 |
157 localPaintFlags |= PaintLayerPaintingCompositingAllPhases; | 157 localPaintFlags |= PaintLayerPaintingCompositingAllPhases; |
158 paintLayerContents(context, paintingInfo, localPaintFlags); | 158 paintLayerContents(context, paintingInfo, localPaintFlags); |
159 } | 159 } |
160 | 160 |
| 161 class ClipPathHelper { |
| 162 public: |
| 163 ClipPathHelper(GraphicsContext* context, const RenderLayer& renderLayer, con
st LayerPaintingInfo& paintingInfo, LayoutRect& rootRelativeBounds, bool& rootRe
lativeBoundsComputed, |
| 164 const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags) |
| 165 : m_resourceClipper(0), m_clipStateSaver(*context, false), m_renderLayer
(renderLayer), m_context(context) |
| 166 { |
| 167 RenderStyle* style = renderLayer.renderer()->style(); |
| 168 |
| 169 // Clip-path, like border radius, must not be applied to the contents of
a composited-scrolling container. |
| 170 // It must, however, still be applied to the mask layer, so that the com
positor can properly mask the |
| 171 // scrolling contents and scrollbars. |
| 172 if (!renderLayer.renderer()->hasClipPath() || !style || (renderLayer.nee
dsCompositedScrolling() && !(paintFlags & PaintLayerPaintingChildClippingMaskPha
se))) |
| 173 return; |
| 174 |
| 175 m_clipperState = RenderSVGResourceClipper::ClipperNotApplied; |
| 176 |
| 177 ASSERT(style->clipPath()); |
| 178 if (style->clipPath()->type() == ClipPathOperation::SHAPE) { |
| 179 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->c
lipPath()); |
| 180 if (clipPath->isValid()) { |
| 181 m_clipStateSaver.save(); |
| 182 |
| 183 if (!rootRelativeBoundsComputed) { |
| 184 rootRelativeBounds = renderLayer.physicalBoundingBoxIncludin
gReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); |
| 185 rootRelativeBoundsComputed = true; |
| 186 } |
| 187 |
| 188 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->
windRule()); |
| 189 } |
| 190 } else if (style->clipPath()->type() == ClipPathOperation::REFERENCE) { |
| 191 ReferenceClipPathOperation* referenceClipPathOperation = toReference
ClipPathOperation(style->clipPath()); |
| 192 Document& document = renderLayer.renderer()->document(); |
| 193 // FIXME: It doesn't work with forward or external SVG references (h
ttps://bugs.webkit.org/show_bug.cgi?id=90405) |
| 194 Element* element = document.getElementById(referenceClipPathOperatio
n->fragment()); |
| 195 if (isSVGClipPathElement(element) && element->renderer()) { |
| 196 // FIXME: Saving at this point is not required in the 'mask'- |
| 197 // case, or if the clip ends up empty. |
| 198 m_clipStateSaver.save(); |
| 199 if (!rootRelativeBoundsComputed) { |
| 200 rootRelativeBounds = renderLayer.physicalBoundingBoxIncludin
gReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); |
| 201 rootRelativeBoundsComputed = true; |
| 202 } |
| 203 |
| 204 m_resourceClipper = toRenderSVGResourceClipper(toRenderSVGResour
ceContainer(element->renderer())); |
| 205 if (!m_resourceClipper->applyClippingToContext(renderLayer.rende
rer(), rootRelativeBounds, |
| 206 paintingInfo.paintDirtyRect, context, m_clipperState)) { |
| 207 // No need to post-apply the clipper if this failed. |
| 208 m_resourceClipper = 0; |
| 209 } |
| 210 } |
| 211 } |
| 212 } |
| 213 |
| 214 ~ClipPathHelper() |
| 215 { |
| 216 if (m_resourceClipper) |
| 217 m_resourceClipper->postApplyStatefulResource(m_renderLayer.renderer(
), m_context, m_clipperState); |
| 218 } |
| 219 private: |
| 220 RenderSVGResourceClipper* m_resourceClipper; |
| 221 GraphicsContextStateSaver m_clipStateSaver; |
| 222 RenderSVGResourceClipper::ClipperState m_clipperState; |
| 223 const RenderLayer& m_renderLayer; |
| 224 GraphicsContext* m_context; |
| 225 }; |
| 226 |
161 void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
ingInfo& paintingInfo, PaintLayerFlags paintFlags) | 227 void LayerPainter::paintLayerContents(GraphicsContext* context, const LayerPaint
ingInfo& paintingInfo, PaintLayerFlags paintFlags) |
162 { | 228 { |
163 ASSERT(m_renderLayer.isSelfPaintingLayer() || m_renderLayer.hasSelfPaintingL
ayerDescendant()); | 229 ASSERT(m_renderLayer.isSelfPaintingLayer() || m_renderLayer.hasSelfPaintingL
ayerDescendant()); |
164 ASSERT(!(paintFlags & PaintLayerAppliedTransform)); | 230 ASSERT(!(paintFlags & PaintLayerAppliedTransform)); |
165 | 231 |
166 bool haveTransparency = paintFlags & PaintLayerHaveTransparency; | 232 bool haveTransparency = paintFlags & PaintLayerHaveTransparency; |
167 bool isSelfPaintingLayer = m_renderLayer.isSelfPaintingLayer(); | 233 bool isSelfPaintingLayer = m_renderLayer.isSelfPaintingLayer(); |
168 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScr
ollbars; | 234 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScr
ollbars; |
169 bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositing
ScrollingPhase; | 235 bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositing
ScrollingPhase; |
170 bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingComposi
tingForegroundPhase; | 236 bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingComposi
tingForegroundPhase; |
(...skipping 21 matching lines...) Expand all Loading... |
192 | 258 |
193 LayoutPoint offsetFromRoot; | 259 LayoutPoint offsetFromRoot; |
194 m_renderLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); | 260 m_renderLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); |
195 | 261 |
196 if (m_renderLayer.compositingState() == PaintsIntoOwnBacking) | 262 if (m_renderLayer.compositingState() == PaintsIntoOwnBacking) |
197 offsetFromRoot.move(m_renderLayer.subpixelAccumulation()); | 263 offsetFromRoot.move(m_renderLayer.subpixelAccumulation()); |
198 | 264 |
199 LayoutRect rootRelativeBounds; | 265 LayoutRect rootRelativeBounds; |
200 bool rootRelativeBoundsComputed = false; | 266 bool rootRelativeBoundsComputed = false; |
201 | 267 |
202 // Apply clip-path to context. | 268 ClipPathHelper clipPathHelper(context, m_renderLayer, paintingInfo, rootRela
tiveBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags); |
203 GraphicsContextStateSaver clipStateSaver(*context, false); | |
204 RenderStyle* style = m_renderLayer.renderer()->style(); | |
205 RenderSVGResourceClipper* resourceClipper = 0; | |
206 RenderSVGResourceClipper::ClipperState clipperState = RenderSVGResourceClipp
er::ClipperNotApplied; | |
207 | |
208 // Clip-path, like border radius, must not be applied to the contents of a c
omposited-scrolling container. | |
209 // It must, however, still be applied to the mask layer, so that the composi
tor can properly mask the | |
210 // scrolling contents and scrollbars. | |
211 if (m_renderLayer.renderer()->hasClipPath() && style && (!m_renderLayer.need
sCompositedScrolling() || paintFlags & PaintLayerPaintingChildClippingMaskPhase)
) { | |
212 ASSERT(style->clipPath()); | |
213 if (style->clipPath()->type() == ClipPathOperation::SHAPE) { | |
214 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->c
lipPath()); | |
215 if (clipPath->isValid()) { | |
216 clipStateSaver.save(); | |
217 | |
218 if (!rootRelativeBoundsComputed) { | |
219 rootRelativeBounds = m_renderLayer.physicalBoundingBoxInclud
ingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); | |
220 rootRelativeBoundsComputed = true; | |
221 } | |
222 | |
223 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->
windRule()); | |
224 } | |
225 } else if (style->clipPath()->type() == ClipPathOperation::REFERENCE) { | |
226 ReferenceClipPathOperation* referenceClipPathOperation = toReference
ClipPathOperation(style->clipPath()); | |
227 Document& document = m_renderLayer.renderer()->document(); | |
228 // FIXME: It doesn't work with forward or external SVG references (h
ttps://bugs.webkit.org/show_bug.cgi?id=90405) | |
229 Element* element = document.getElementById(referenceClipPathOperatio
n->fragment()); | |
230 if (isSVGClipPathElement(element) && element->renderer()) { | |
231 // FIXME: Saving at this point is not required in the 'mask'- | |
232 // case, or if the clip ends up empty. | |
233 clipStateSaver.save(); | |
234 if (!rootRelativeBoundsComputed) { | |
235 rootRelativeBounds = m_renderLayer.physicalBoundingBoxInclud
ingReflectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot); | |
236 rootRelativeBoundsComputed = true; | |
237 } | |
238 | |
239 resourceClipper = toRenderSVGResourceClipper(toRenderSVGResource
Container(element->renderer())); | |
240 if (!resourceClipper->applyClippingToContext(m_renderLayer.rende
rer(), rootRelativeBounds, | |
241 paintingInfo.paintDirtyRect, context, clipperState)) { | |
242 // No need to post-apply the clipper if this failed. | |
243 resourceClipper = 0; | |
244 } | |
245 } | |
246 } | |
247 } | |
248 | 269 |
249 // Blending operations must be performed only with the nearest ancestor stac
king context. | 270 // Blending operations must be performed only with the nearest ancestor stac
king context. |
250 // Note that there is no need to create a transparency layer if we're painti
ng the root. | 271 // Note that there is no need to create a transparency layer if we're painti
ng the root. |
251 bool createTransparencyLayerForBlendMode = !m_renderLayer.renderer()->isDocu
mentElement() && m_renderLayer.stackingNode()->isStackingContext() && m_renderLa
yer.hasNonIsolatedDescendantWithBlendMode(); | 272 bool createTransparencyLayerForBlendMode = !m_renderLayer.renderer()->isDocu
mentElement() && m_renderLayer.stackingNode()->isStackingContext() && m_renderLa
yer.hasNonIsolatedDescendantWithBlendMode(); |
252 | 273 |
253 if (createTransparencyLayerForBlendMode) | 274 if (createTransparencyLayerForBlendMode) |
254 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.pa
intDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); | 275 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.pa
intDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.paintBehavior); |
255 | 276 |
256 LayerPaintingInfo localPaintingInfo(paintingInfo); | 277 LayerPaintingInfo localPaintingInfo(paintingInfo); |
257 | 278 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 paintChildClippingMaskForFragments(layerFragments, context, localPaintin
gInfo, paintingRootForRenderer, paintFlags); | 368 paintChildClippingMaskForFragments(layerFragments, context, localPaintin
gInfo, paintingRootForRenderer, paintFlags); |
348 } | 369 } |
349 | 370 |
350 // End our transparency layer | 371 // End our transparency layer |
351 if ((haveTransparency || createTransparencyLayerForBlendMode) && m_renderLay
er.usedTransparency() | 372 if ((haveTransparency || createTransparencyLayerForBlendMode) && m_renderLay
er.usedTransparency() |
352 && !(m_renderLayer.reflectionInfo() && m_renderLayer.reflectionInfo()->i
sPaintingInsideReflection())) { | 373 && !(m_renderLayer.reflectionInfo() && m_renderLayer.reflectionInfo()->i
sPaintingInsideReflection())) { |
353 context->endLayer(); | 374 context->endLayer(); |
354 context->restore(); | 375 context->restore(); |
355 m_renderLayer.setUsedTransparency(false); | 376 m_renderLayer.setUsedTransparency(false); |
356 } | 377 } |
357 | |
358 if (resourceClipper) | |
359 resourceClipper->postApplyStatefulResource(m_renderLayer.renderer(), con
text, clipperState); | |
360 } | 378 } |
361 | 379 |
362 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
r) | 380 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
r) |
363 { | 381 { |
364 if (startLayer == endLayer) | 382 if (startLayer == endLayer) |
365 return true; | 383 return true; |
366 | 384 |
367 RenderView* view = startLayer->renderer()->view(); | 385 RenderView* view = startLayer->renderer()->view(); |
368 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock();
currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo
ck()) { | 386 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock();
currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo
ck()) { |
369 if (currentBlock->layer() == endLayer) | 387 if (currentBlock->layer() == endLayer) |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 | 846 |
829 OwnPtr<ClipRecorder> clipRecorder; | 847 OwnPtr<ClipRecorder> clipRecorder; |
830 if (needsToClip(paintingInfo, clipRect)) | 848 if (needsToClip(paintingInfo, clipRect)) |
831 clipRecorder = adoptPtr(new ClipRecorder(m_renderLayer.parent(), con
text, DisplayItem::ClipLayerFragmentParent, clipRect)); | 849 clipRecorder = adoptPtr(new ClipRecorder(m_renderLayer.parent(), con
text, DisplayItem::ClipLayerFragmentParent, clipRect)); |
832 | 850 |
833 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragmen
t.paginationOffset); | 851 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragmen
t.paginationOffset); |
834 } | 852 } |
835 } | 853 } |
836 | 854 |
837 } // namespace blink | 855 } // namespace blink |
OLD | NEW |