Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp

Issue 9235065: Merge 105978 - crash in WebCore::RenderSVGContainer::paint (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/963/
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 2 * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org>
4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
5 * Copyright (C) 2011 Dirk Schulze <krit@webkit.org> 5 * Copyright (C) 2011 Dirk Schulze <krit@webkit.org>
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 #include "SVGUnitTypes.h" 47 #include "SVGUnitTypes.h"
48 #include "SVGUseElement.h" 48 #include "SVGUseElement.h"
49 #include <wtf/UnusedParam.h> 49 #include <wtf/UnusedParam.h>
50 50
51 namespace WebCore { 51 namespace WebCore {
52 52
53 RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResource Type; 53 RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResource Type;
54 54
55 RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node) 55 RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node)
56 : RenderSVGResourceContainer(node) 56 : RenderSVGResourceContainer(node)
57 , m_invalidationBlocked(false)
58 { 57 {
59 } 58 }
60 59
61 RenderSVGResourceClipper::~RenderSVGResourceClipper() 60 RenderSVGResourceClipper::~RenderSVGResourceClipper()
62 { 61 {
63 if (m_clipper.isEmpty()) 62 if (m_clipper.isEmpty())
64 return; 63 return;
65 64
66 deleteAllValues(m_clipper); 65 deleteAllValues(m_clipper);
67 m_clipper.clear(); 66 m_clipper.clear();
68 } 67 }
69 68
70 void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidatio n) 69 void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidatio n)
71 { 70 {
72 if (m_invalidationBlocked)
73 return;
74
75 m_clipBoundaries = FloatRect(); 71 m_clipBoundaries = FloatRect();
76 if (!m_clipper.isEmpty()) { 72 if (!m_clipper.isEmpty()) {
77 deleteAllValues(m_clipper); 73 deleteAllValues(m_clipper);
78 m_clipper.clear(); 74 m_clipper.clear();
79 } 75 }
80 76
81 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation); 77 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation);
82 } 78 }
83 79
84 void RenderSVGResourceClipper::removeClientFromCache(RenderObject* client, bool markForInvalidation) 80 void RenderSVGResourceClipper::removeClientFromCache(RenderObject* client, bool markForInvalidation)
85 { 81 {
86 ASSERT(client); 82 ASSERT(client);
87 if (m_invalidationBlocked)
88 return;
89
90 if (m_clipper.contains(client)) 83 if (m_clipper.contains(client))
91 delete m_clipper.take(client); 84 delete m_clipper.take(client);
92 85
93 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation); 86 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation);
94 } 87 }
95 88
96 bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) 89 bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
97 { 90 {
98 ASSERT(object); 91 ASSERT(object);
99 ASSERT(context); 92 ASSERT(context);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 maskContext->concatCTM(absoluteTransform); 185 maskContext->concatCTM(absoluteTransform);
193 186
194 // clipPath can also be clipped by another clipPath. 187 // clipPath can also be clipped by another clipPath.
195 if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRende rObject(this)) { 188 if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRende rObject(this)) {
196 if (RenderSVGResourceClipper* clipper = resources->clipper()) { 189 if (RenderSVGResourceClipper* clipper = resources->clipper()) {
197 if (!clipper->applyClippingToContext(this, objectBoundingBox, re paintRect, maskContext)) 190 if (!clipper->applyClippingToContext(this, objectBoundingBox, re paintRect, maskContext))
198 return false; 191 return false;
199 } 192 }
200 } 193 }
201 194
202 drawContentIntoMaskImage(clipperData, objectBoundingBox); 195 if (!drawContentIntoMaskImage(clipperData, objectBoundingBox)) {
196 stateSaver.restore();
197 clipperData->clipMaskImage.clear();
198 }
203 } 199 }
204 200
205 if (!clipperData->clipMaskImage) 201 if (!clipperData->clipMaskImage)
206 return false; 202 return false;
207 203
208 SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAb soluteTargetRect, clipperData->clipMaskImage); 204 SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAb soluteTargetRect, clipperData->clipMaskImage);
209 return true; 205 return true;
210 } 206 }
211 207
212 bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData , const FloatRect& objectBoundingBox) 208 bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData , const FloatRect& objectBoundingBox)
213 { 209 {
210 ASSERT(frame());
214 ASSERT(clipperData); 211 ASSERT(clipperData);
215 ASSERT(clipperData->clipMaskImage); 212 ASSERT(clipperData->clipMaskImage);
216 213
217 GraphicsContext* maskContext = clipperData->clipMaskImage->context(); 214 GraphicsContext* maskContext = clipperData->clipMaskImage->context();
218 ASSERT(maskContext); 215 ASSERT(maskContext);
219 216
220 AffineTransform maskContentTransformation; 217 AffineTransform maskContentTransformation;
221 SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node()); 218 SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node());
222 if (clipPath->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGB OX) { 219 if (clipPath->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGB OX) {
223 maskContentTransformation.translate(objectBoundingBox.x(), objectBoundin gBox.y()); 220 maskContentTransformation.translate(objectBoundingBox.x(), objectBoundin gBox.y());
224 maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), obj ectBoundingBox.height()); 221 maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), obj ectBoundingBox.height());
225 maskContext->concatCTM(maskContentTransformation); 222 maskContext->concatCTM(maskContentTransformation);
226 } 223 }
227 224
225 // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:
226 // - fill-opacity/stroke-opacity/opacity set to 1
227 // - masker/filter not applied when rendering the children
228 // - fill is set to the initial fill paint server (solid, black)
229 // - stroke is set to the initial stroke paint server (none)
230 PaintBehavior oldBehavior = frame()->view()->paintBehavior();
231 frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMas k);
232
228 // Draw all clipPath children into a global mask. 233 // Draw all clipPath children into a global mask.
229 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) { 234 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) {
230 RenderObject* renderer = childNode->renderer(); 235 RenderObject* renderer = childNode->renderer();
231 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)-> isStyled() || !renderer) 236 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)-> isStyled() || !renderer)
232 continue; 237 continue;
238 if (renderer->needsLayout()) {
239 frame()->view()->setPaintBehavior(oldBehavior);
240 return false;
241 }
233 RenderStyle* style = renderer->style(); 242 RenderStyle* style = renderer->style();
234 if (!style || style->display() == NONE || style->visibility() != VISIBLE ) 243 if (!style || style->display() == NONE || style->visibility() != VISIBLE )
235 continue; 244 continue;
236 245
237 WindRule newClipRule = style->svgStyle()->clipRule(); 246 WindRule newClipRule = style->svgStyle()->clipRule();
238 bool isUseElement = renderer->isSVGShadowTreeRootContainer(); 247 bool isUseElement = renderer->isSVGShadowTreeRootContainer();
239 if (isUseElement) { 248 if (isUseElement) {
240 SVGUseElement* useElement = static_cast<SVGUseElement*>(childNode); 249 SVGUseElement* useElement = static_cast<SVGUseElement*>(childNode);
241 renderer = useElement->rendererClipChild(); 250 renderer = useElement->rendererClipChild();
242 if (!renderer) 251 if (!renderer)
243 continue; 252 continue;
244 if (!useElement->hasAttribute(SVGNames::clip_ruleAttr)) 253 if (!useElement->hasAttribute(SVGNames::clip_ruleAttr))
245 newClipRule = renderer->style()->svgStyle()->clipRule(); 254 newClipRule = renderer->style()->svgStyle()->clipRule();
246 } 255 }
247 256
248 // Only shapes, paths and texts are allowed for clipping. 257 // Only shapes, paths and texts are allowed for clipping.
249 if (!renderer->isSVGShape() && !renderer->isSVGText()) 258 if (!renderer->isSVGShape() && !renderer->isSVGText())
250 continue; 259 continue;
251 260
252 // Save the old RenderStyle of the current object for restoring after dr awing 261 maskContext->setFillRule(newClipRule);
253 // it to the MaskImage. The new intermediate RenderStyle needs to inheri t from
254 // the old one.
255 RefPtr<RenderStyle> oldRenderStyle = renderer->style();
256 RefPtr<RenderStyle> newRenderStyle = RenderStyle::clone(oldRenderStyle.g et());
257 SVGRenderStyle* svgStyle = newRenderStyle.get()->accessSVGStyle();
258 svgStyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRender Style::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri());
259 svgStyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRe nderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri());
260 svgStyle->setFillRule(newClipRule);
261 newRenderStyle.get()->setOpacity(1);
262 svgStyle->setFillOpacity(1);
263 svgStyle->setStrokeOpacity(1);
264 svgStyle->setFilterResource(String());
265 svgStyle->setMaskerResource(String());
266
267 // The setStyle() call results in a styleDidChange() call, which in turn invalidations the resources.
268 // As we're mutating the resource on purpose, block updates until we've resetted the style again.
269 m_invalidationBlocked = true;
270 renderer->setStyle(newRenderStyle.release());
271 262
272 // In the case of a <use> element, we obtained its renderere above, to r etrieve its clipRule. 263 // In the case of a <use> element, we obtained its renderere above, to r etrieve its clipRule.
273 // We have to pass the <use> renderer itself to renderSubtreeToImageBuff er() to apply it's x/y/transform/etc. values when rendering. 264 // We have to pass the <use> renderer itself to renderSubtreeToImageBuff er() to apply it's x/y/transform/etc. values when rendering.
274 // So if isUseElement is true, refetch the childNode->renderer(), as ren derer got overriden above. 265 // So if isUseElement is true, refetch the childNode->renderer(), as ren derer got overriden above.
275 SVGImageBufferTools::renderSubtreeToImageBuffer(clipperData->clipMaskIma ge.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransforma tion); 266 SVGImageBufferTools::renderSubtreeToImageBuffer(clipperData->clipMaskIma ge.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransforma tion);
276
277 renderer->setStyle(oldRenderStyle.release());
278 m_invalidationBlocked = false;
279 } 267 }
280 268
269 frame()->view()->setPaintBehavior(oldBehavior);
281 return true; 270 return true;
282 } 271 }
283 272
284 void RenderSVGResourceClipper::calculateClipContentRepaintRect() 273 void RenderSVGResourceClipper::calculateClipContentRepaintRect()
285 { 274 {
286 // This is a rough heuristic to appraise the clip size and doesn't consider clip on clip. 275 // This is a rough heuristic to appraise the clip size and doesn't consider clip on clip.
287 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) { 276 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) {
288 RenderObject* renderer = childNode->renderer(); 277 RenderObject* renderer = childNode->renderer();
289 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)-> isStyled() || !renderer) 278 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)-> isStyled() || !renderer)
290 continue; 279 continue;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h eight()); 334 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h eight());
346 return transform.mapRect(m_clipBoundaries); 335 return transform.mapRect(m_clipBoundaries);
347 } 336 }
348 337
349 return m_clipBoundaries; 338 return m_clipBoundaries;
350 } 339 }
351 340
352 } 341 }
353 342
354 #endif // ENABLE(SVG) 343 #endif // ENABLE(SVG)
OLDNEW
« no previous file with comments | « Source/WebCore/rendering/svg/RenderSVGResourceClipper.h ('k') | Source/WebCore/rendering/svg/RenderSVGResourceMasker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698