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 129 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& repaintRect, GraphicsContext* context, ClipperContext& clip
perContext) | 150 const FloatRect& paintInvalidationRect, GraphicsContext* context, ClipperCon
text& clipperContext) |
151 { | 151 { |
152 ASSERT(target); | 152 ASSERT(target); |
153 ASSERT(context); | 153 ASSERT(context); |
154 ASSERT(clipperContext.state == ClipperContext::NotAppliedState); | 154 ASSERT(clipperContext.state == ClipperContext::NotAppliedState); |
155 ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout()); | 155 ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout()); |
156 | 156 |
157 if (repaintRect.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 clipperContext.state = ClipperContext::AppliedPathState; |
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 clipperContext.state = ClipperContext::AppliedMaskState; |
179 | 179 |
180 // Mask layer start | 180 // Mask layer start |
181 context->beginTransparencyLayer(1, &repaintRect); | 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 ClipperContext clipPathClipperContext; |
190 if (clipPathClipper && !clipPathClipper->applyClippingToContext(this, ta
rgetBoundingBox, repaintRect, context, clipPathClipperContext)) { | 190 if (clipPathClipper && !clipPathClipper->applyClippingToContext(this, ta
rgetBoundingBox, paintInvalidationRect, context, clipPathClipperContext)) { |
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
ipperContext); |
204 } | 204 } |
205 | 205 |
206 // Masked content layer start. | 206 // Masked content layer start. |
207 context->beginLayer(1, CompositeSourceIn, &repaintRect); | 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 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 renderer = childElement->renderer(); | 300 renderer = childElement->renderer(); |
301 | 301 |
302 SVGRenderingContext::renderSubtree(context, renderer, contentTransformat
ion); | 302 SVGRenderingContext::renderSubtree(context, renderer, contentTransformat
ion); |
303 } | 303 } |
304 | 304 |
305 frame()->view()->setPaintBehavior(oldBehavior); | 305 frame()->view()->setPaintBehavior(oldBehavior); |
306 | 306 |
307 return context->endRecording(); | 307 return context->endRecording(); |
308 } | 308 } |
309 | 309 |
310 void RenderSVGResourceClipper::calculateClipContentRepaintRect() | 310 void RenderSVGResourceClipper::calculateClipContentPaintInvalidationRect() |
311 { | 311 { |
312 // This is a rough heuristic to appraise the clip size and doesn't consider
clip on clip. | 312 // This is a rough heuristic to appraise the clip size and doesn't consider
clip on clip. |
313 for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()
); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement
)) { | 313 for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element()
); childElement; childElement = Traversal<SVGElement>::nextSibling(*childElement
)) { |
314 RenderObject* renderer = childElement->renderer(); | 314 RenderObject* renderer = childElement->renderer(); |
315 if (!renderer) | 315 if (!renderer) |
316 continue; | 316 continue; |
317 if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElemen
t(*childElement)) | 317 if (!renderer->isSVGShape() && !renderer->isSVGText() && !isSVGUseElemen
t(*childElement)) |
318 continue; | 318 continue; |
319 RenderStyle* style = renderer->style(); | 319 RenderStyle* style = renderer->style(); |
320 if (!style || style->display() == NONE || style->visibility() != VISIBLE
) | 320 if (!style || style->display() == NONE || style->visibility() != VISIBLE
) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 return false; | 359 return false; |
360 } | 360 } |
361 | 361 |
362 FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject* obje
ct) | 362 FloatRect RenderSVGResourceClipper::resourceBoundingBox(const RenderObject* obje
ct) |
363 { | 363 { |
364 // Resource was not layouted yet. Give back the boundingBox of the object. | 364 // Resource was not layouted yet. Give back the boundingBox of the object. |
365 if (selfNeedsLayout()) | 365 if (selfNeedsLayout()) |
366 return object->objectBoundingBox(); | 366 return object->objectBoundingBox(); |
367 | 367 |
368 if (m_clipBoundaries.isEmpty()) | 368 if (m_clipBoundaries.isEmpty()) |
369 calculateClipContentRepaintRect(); | 369 calculateClipContentPaintInvalidationRect(); |
370 | 370 |
371 if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumVa
lue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { | 371 if (toSVGClipPathElement(element())->clipPathUnits()->currentValue()->enumVa
lue() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { |
372 FloatRect objectBoundingBox = object->objectBoundingBox(); | 372 FloatRect objectBoundingBox = object->objectBoundingBox(); |
373 AffineTransform transform; | 373 AffineTransform transform; |
374 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); | 374 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); |
375 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h
eight()); | 375 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h
eight()); |
376 return transform.mapRect(m_clipBoundaries); | 376 return transform.mapRect(m_clipBoundaries); |
377 } | 377 } |
378 | 378 |
379 return m_clipBoundaries; | 379 return m_clipBoundaries; |
380 } | 380 } |
381 | 381 |
382 } | 382 } |
OLD | NEW |