| 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 |