OLD | NEW |
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati
on : ParentOnlyInvalidation); | 66 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati
on : ParentOnlyInvalidation); |
67 } | 67 } |
68 | 68 |
69 bool RenderSVGResourceClipper::applyResource(RenderObject*, RenderStyle*, Graphi
csContext*&, unsigned short) | 69 bool RenderSVGResourceClipper::applyResource(RenderObject*, RenderStyle*, Graphi
csContext*&, unsigned short) |
70 { | 70 { |
71 // Clippers are always applied using stateful methods. | 71 // Clippers are always applied using stateful methods. |
72 ASSERT_NOT_REACHED(); | 72 ASSERT_NOT_REACHED(); |
73 return false; | 73 return false; |
74 } | 74 } |
75 | 75 |
76 bool RenderSVGResourceClipper::applyStatefulResource(RenderObject* object, Graph
icsContext*& context, ClipperContext& clipperContext) | 76 bool RenderSVGResourceClipper::applyStatefulResource(RenderObject* object, Graph
icsContext*& context, ClipperState& clipperState) |
77 { | 77 { |
78 ASSERT(object); | 78 ASSERT(object); |
79 ASSERT(context); | 79 ASSERT(context); |
80 | 80 |
81 clearInvalidationMask(); | 81 clearInvalidationMask(); |
82 | 82 |
83 return applyClippingToContext(object, object->objectBoundingBox(), object->p
aintInvalidationRectInLocalCoordinates(), context, clipperContext); | 83 return applyClippingToContext(object, object->objectBoundingBox(), object->p
aintInvalidationRectInLocalCoordinates(), context, clipperState); |
84 } | 84 } |
85 | 85 |
86 bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context, | 86 bool RenderSVGResourceClipper::tryPathOnlyClipping(GraphicsContext* context, |
87 const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundi
ngBox) { | 87 const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundi
ngBox) { |
88 // If the current clip-path gets clipped itself, we have to fallback to mask
ing. | 88 // If the current clip-path gets clipped itself, we have to fallback to mask
ing. |
89 if (!style()->svgStyle().clipperResource().isEmpty()) | 89 if (!style()->svgStyle().clipperResource().isEmpty()) |
90 return false; | 90 return false; |
91 WindRule clipRule = RULE_NONZERO; | 91 WindRule clipRule = RULE_NONZERO; |
92 Path clipPath = Path(); | 92 Path clipPath = Path(); |
93 | 93 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 clipPath.transform(animatedLocalTransform); | 140 clipPath.transform(animatedLocalTransform); |
141 | 141 |
142 // The SVG specification wants us to clip everything, if clip-path doesn't h
ave a child. | 142 // The SVG specification wants us to clip everything, if clip-path doesn't h
ave a child. |
143 if (clipPath.isEmpty()) | 143 if (clipPath.isEmpty()) |
144 clipPath.addRect(FloatRect()); | 144 clipPath.addRect(FloatRect()); |
145 context->clipPath(clipPath, clipRule); | 145 context->clipPath(clipPath, clipRule); |
146 return true; | 146 return true; |
147 } | 147 } |
148 | 148 |
149 bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
t FloatRect& targetBoundingBox, | 149 bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* target, cons
t FloatRect& targetBoundingBox, |
150 const FloatRect& paintInvalidationRect, GraphicsContext* context, ClipperCon
text& clipperContext) | 150 const FloatRect& paintInvalidationRect, GraphicsContext* context, ClipperSta
te& clipperState) |
151 { | 151 { |
152 ASSERT(target); | 152 ASSERT(target); |
153 ASSERT(context); | 153 ASSERT(context); |
154 ASSERT(clipperContext.state == ClipperContext::NotAppliedState); | 154 ASSERT(clipperState == ClipperNotApplied); |
155 ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout()); | 155 ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout()); |
156 | 156 |
157 if (paintInvalidationRect.isEmpty() || m_inClipExpansion) | 157 if (paintInvalidationRect.isEmpty() || m_inClipExpansion) |
158 return false; | 158 return false; |
159 TemporaryChange<bool> inClipExpansionChange(m_inClipExpansion, true); | 159 TemporaryChange<bool> inClipExpansionChange(m_inClipExpansion, true); |
160 | 160 |
161 AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->an
imatedLocalTransform(); | 161 AffineTransform animatedLocalTransform = toSVGClipPathElement(element())->an
imatedLocalTransform(); |
162 // When drawing a clip for non-SVG elements, the CTM does not include the zo
om factor. | 162 // When drawing a clip for non-SVG elements, the CTM does not include the zo
om factor. |
163 // In this case, we need to apply the zoom scale explicitly - but only for c
lips with | 163 // In this case, we need to apply the zoom scale explicitly - but only for c
lips with |
164 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). | 164 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). |
165 if (!target->isSVG() | 165 if (!target->isSVG() |
166 && toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enu
mValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { | 166 && toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enu
mValue() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { |
167 ASSERT(style()); | 167 ASSERT(style()); |
168 animatedLocalTransform.scale(style()->effectiveZoom()); | 168 animatedLocalTransform.scale(style()->effectiveZoom()); |
169 } | 169 } |
170 | 170 |
171 // First, try to apply the clip as a clipPath. | 171 // First, try to apply the clip as a clipPath. |
172 if (tryPathOnlyClipping(context, animatedLocalTransform, targetBoundingBox))
{ | 172 if (tryPathOnlyClipping(context, animatedLocalTransform, targetBoundingBox))
{ |
173 clipperContext.state = ClipperContext::AppliedPathState; | 173 clipperState = ClipperAppliedPath; |
174 return true; | 174 return true; |
175 } | 175 } |
176 | 176 |
177 // Fall back to masking. | 177 // Fall back to masking. |
178 clipperContext.state = ClipperContext::AppliedMaskState; | 178 clipperState = ClipperAppliedMask; |
179 | 179 |
180 // Mask layer start | 180 // Mask layer start |
181 context->beginTransparencyLayer(1, &paintInvalidationRect); | 181 context->beginTransparencyLayer(1, &paintInvalidationRect); |
182 { | 182 { |
183 GraphicsContextStateSaver maskContentSaver(*context); | 183 GraphicsContextStateSaver maskContentSaver(*context); |
184 context->concatCTM(animatedLocalTransform); | 184 context->concatCTM(animatedLocalTransform); |
185 | 185 |
186 // clipPath can also be clipped by another clipPath. | 186 // clipPath can also be clipped by another clipPath. |
187 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObj
ect(this); | 187 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObj
ect(this); |
188 RenderSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : 0; | 188 RenderSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : 0; |
189 ClipperContext clipPathClipperContext; | 189 ClipperState clipPathClipperState = ClipperNotApplied; |
190 if (clipPathClipper && !clipPathClipper->applyClippingToContext(this, ta
rgetBoundingBox, paintInvalidationRect, context, clipPathClipperContext)) { | 190 if (clipPathClipper && !clipPathClipper->applyClippingToContext(this, ta
rgetBoundingBox, paintInvalidationRect, context, clipPathClipperState)) { |
191 // FIXME: Awkward state micro-management. Ideally, GraphicsContextSt
ateSaver should | 191 // FIXME: Awkward state micro-management. Ideally, GraphicsContextSt
ateSaver should |
192 // a) pop saveLayers also | 192 // a) pop saveLayers also |
193 // b) pop multiple states if needed (similarly to SkCanvas::restor
eToCount()) | 193 // b) pop multiple states if needed (similarly to SkCanvas::restor
eToCount()) |
194 // Then we should be able to replace this mess with a single, top-le
vel GCSS. | 194 // Then we should be able to replace this mess with a single, top-le
vel GCSS. |
195 maskContentSaver.restore(); | 195 maskContentSaver.restore(); |
196 context->restoreLayer(); | 196 context->restoreLayer(); |
197 return false; | 197 return false; |
198 } | 198 } |
199 | 199 |
200 drawClipMaskContent(context, targetBoundingBox); | 200 drawClipMaskContent(context, targetBoundingBox); |
201 | 201 |
202 if (clipPathClipper) | 202 if (clipPathClipper) |
203 clipPathClipper->postApplyStatefulResource(this, context, clipPathCl
ipperContext); | 203 clipPathClipper->postApplyStatefulResource(this, context, clipPathCl
ipperState); |
204 } | 204 } |
205 | 205 |
206 // Masked content layer start. | 206 // Masked content layer start. |
207 context->beginLayer(1, CompositeSourceIn, &paintInvalidationRect); | 207 context->beginLayer(1, CompositeSourceIn, &paintInvalidationRect); |
208 | 208 |
209 return true; | 209 return true; |
210 } | 210 } |
211 | 211 |
212 void RenderSVGResourceClipper::postApplyResource(RenderObject*, GraphicsContext*
&, unsigned short, | 212 void RenderSVGResourceClipper::postApplyResource(RenderObject*, GraphicsContext*
&, unsigned short, |
213 const Path*, const RenderSVGShape*) { | 213 const Path*, const RenderSVGShape*) { |
214 // Clippers are always applied using stateful methods. | 214 // Clippers are always applied using stateful methods. |
215 ASSERT_NOT_REACHED(); | 215 ASSERT_NOT_REACHED(); |
216 } | 216 } |
217 | 217 |
218 void RenderSVGResourceClipper::postApplyStatefulResource(RenderObject*, Graphics
Context*& context, ClipperContext& clipperContext) | 218 void RenderSVGResourceClipper::postApplyStatefulResource(RenderObject*, Graphics
Context*& context, ClipperState& clipperState) |
219 { | 219 { |
220 switch (clipperContext.state) { | 220 switch (clipperState) { |
221 case ClipperContext::AppliedPathState: | 221 case ClipperAppliedPath: |
222 // Path-only clipping, no layers to restore. | 222 // Path-only clipping, no layers to restore. |
223 break; | 223 break; |
224 case ClipperContext::AppliedMaskState: | 224 case ClipperAppliedMask: |
225 // Transfer content layer -> mask layer (SrcIn) | 225 // Transfer content layer -> mask layer (SrcIn) |
226 context->endLayer(); | 226 context->endLayer(); |
227 // Transfer mask layer -> bg layer (SrcOver) | 227 // Transfer mask layer -> bg layer (SrcOver) |
228 context->endLayer(); | 228 context->endLayer(); |
229 break; | 229 break; |
230 default: | 230 default: |
231 ASSERT_NOT_REACHED(); | 231 ASSERT_NOT_REACHED(); |
232 } | 232 } |
233 } | 233 } |
234 | 234 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 AffineTransform transform; | 374 AffineTransform transform; |
375 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); | 375 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); |
376 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h
eight()); | 376 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h
eight()); |
377 return transform.mapRect(m_clipBoundaries); | 377 return transform.mapRect(m_clipBoundaries); |
378 } | 378 } |
379 | 379 |
380 return m_clipBoundaries; | 380 return m_clipBoundaries; |
381 } | 381 } |
382 | 382 |
383 } | 383 } |
OLD | NEW |