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

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

Issue 10447082: Merge 117971 (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1132/
Patch Set: Created 8 years, 6 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 Nikolas Zimmermann <zimmermann@kde.org> 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org> 3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org>
4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org> 4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org>
5 * Copyright (C) 2009 Google, Inc. 5 * Copyright (C) 2009 Google, Inc.
6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com> 8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
10 * Copyright (C) 2011 University of Szeged 10 * Copyright (C) 2011 University of Szeged
(...skipping 22 matching lines...) Expand all
33 #include "FloatPoint.h" 33 #include "FloatPoint.h"
34 #include "FloatQuad.h" 34 #include "FloatQuad.h"
35 #include "GraphicsContext.h" 35 #include "GraphicsContext.h"
36 #include "HitTestRequest.h" 36 #include "HitTestRequest.h"
37 #include "LayoutRepainter.h" 37 #include "LayoutRepainter.h"
38 #include "PointerEventsHitRules.h" 38 #include "PointerEventsHitRules.h"
39 #include "RenderSVGContainer.h" 39 #include "RenderSVGContainer.h"
40 #include "RenderSVGResourceMarker.h" 40 #include "RenderSVGResourceMarker.h"
41 #include "RenderSVGResourceSolidColor.h" 41 #include "RenderSVGResourceSolidColor.h"
42 #include "SVGPathData.h" 42 #include "SVGPathData.h"
43 #include "SVGPathElement.h"
44 #include "SVGRenderingContext.h" 43 #include "SVGRenderingContext.h"
45 #include "SVGResources.h" 44 #include "SVGResources.h"
46 #include "SVGResourcesCache.h" 45 #include "SVGResourcesCache.h"
47 #include "SVGStyledTransformableElement.h" 46 #include "SVGStyledTransformableElement.h"
48 #include "SVGSubpathData.h" 47 #include "SVGSubpathData.h"
49 #include "SVGTransformList.h" 48 #include "SVGTransformList.h"
50 #include "SVGURIReference.h" 49 #include "SVGURIReference.h"
51 #include "StrokeStyleApplier.h" 50 #include "StrokeStyleApplier.h"
52 #include <wtf/MathExtras.h> 51 #include <wtf/MathExtras.h>
53 52
(...skipping 11 matching lines...) Expand all
65 RenderSVGShape::~RenderSVGShape() 64 RenderSVGShape::~RenderSVGShape()
66 { 65 {
67 } 66 }
68 67
69 void RenderSVGShape::createShape() 68 void RenderSVGShape::createShape()
70 { 69 {
71 ASSERT(!m_path); 70 ASSERT(!m_path);
72 m_path = adoptPtr(new Path); 71 m_path = adoptPtr(new Path);
73 ASSERT(isEmpty()); 72 ASSERT(isEmpty());
74 73
75 SVGPathElement* element = static_cast<SVGPathElement*>(node()); 74 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableE lement*>(node());
76 updatePathFromGraphicsElement(element, path()); 75 updatePathFromGraphicsElement(element, path());
77 processZeroLengthSubpaths(); 76 processZeroLengthSubpaths();
77 processMarkerPositions();
78 } 78 }
79 79
80 bool RenderSVGShape::isEmpty() const 80 bool RenderSVGShape::isEmpty() const
81 { 81 {
82 return m_path->isEmpty(); 82 return m_path->isEmpty();
83 } 83 }
84 84
85 void RenderSVGShape::fillShape(GraphicsContext* context) const 85 void RenderSVGShape::fillShape(GraphicsContext* context) const
86 { 86 {
87 context->fillPath(path()); 87 context->fillPath(path());
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 updateCachedBoundariesInParents = true; 170 updateCachedBoundariesInParents = true;
171 } 171 }
172 172
173 if (m_needsTransformUpdate) { 173 if (m_needsTransformUpdate) {
174 m_localTransform = element->animatedLocalTransform(); 174 m_localTransform = element->animatedLocalTransform();
175 m_needsTransformUpdate = false; 175 m_needsTransformUpdate = false;
176 updateCachedBoundariesInParents = true; 176 updateCachedBoundariesInParents = true;
177 } 177 }
178 178
179 // Invalidate all resources of this client if our layout changed. 179 // Invalidate all resources of this client if our layout changed.
180 if (everHadLayout() && selfNeedsLayout()) { 180 if (everHadLayout() && selfNeedsLayout())
181 SVGResourcesCache::clientLayoutChanged(this); 181 SVGResourcesCache::clientLayoutChanged(this);
182 m_markerLayoutInfo.clear();
183 }
184 182
185 // At this point LayoutRepainter already grabbed the old bounds, 183 // At this point LayoutRepainter already grabbed the old bounds,
186 // recalculate them now so repaintAfterLayout() uses the new bounds. 184 // recalculate them now so repaintAfterLayout() uses the new bounds.
187 if (needsShapeUpdate || m_needsBoundariesUpdate) { 185 if (needsShapeUpdate || m_needsBoundariesUpdate) {
188 updateCachedBoundaries(); 186 updateCachedBoundaries();
189 m_needsBoundariesUpdate = false; 187 m_needsBoundariesUpdate = false;
190 } 188 }
191 189
192 // If our bounds changed, notify the parents. 190 // If our bounds changed, notify the parents.
193 if (updateCachedBoundariesInParents) 191 if (updateCachedBoundariesInParents)
194 RenderSVGModelObject::setNeedsBoundariesUpdate(); 192 RenderSVGModelObject::setNeedsBoundariesUpdate();
195 193
196 repainter.repaintAfterLayout(); 194 repainter.repaintAfterLayout();
197 setNeedsLayout(false); 195 setNeedsLayout(false);
198 } 196 }
199 197
200 bool RenderSVGShape::shouldStrokeZeroLengthSubpath() const 198 bool RenderSVGShape::shouldStrokeZeroLengthSubpath() const
201 { 199 {
202 // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-l inecap" property has a value of butt 200 // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-l inecap" property has a value of butt
203 // but shall be stroked if the "stroke-linecap" property has a value of roun d or square 201 // but shall be stroked if the "stroke-linecap" property has a value of roun d or square
204 return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() ! = ButtCap; 202 return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() ! = ButtCap;
205 } 203 }
206 204
205 bool RenderSVGShape::shouldGenerateMarkerPositions() const
206 {
207 if (!style()->svgStyle()->hasMarkers())
208 return false;
209
210 SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableE lement*>(node());
211 if (!element->supportsMarkers())
212 return false;
213
214 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject( this);
215 if (!resources)
216 return false;
217
218 return resources->markerStart() || resources->markerMid() || resources->mark erEnd();
219 }
220
207 FloatRect RenderSVGShape::zeroLengthSubpathRect(const FloatPoint& linecapPositio n, float strokeWidth) const 221 FloatRect RenderSVGShape::zeroLengthSubpathRect(const FloatPoint& linecapPositio n, float strokeWidth) const
208 { 222 {
209 return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth); 223 return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth);
210 } 224 }
211 225
212 Path* RenderSVGShape::zeroLengthLinecapPath(const FloatPoint& linecapPosition) 226 Path* RenderSVGShape::zeroLengthLinecapPath(const FloatPoint& linecapPosition)
213 { 227 {
214 // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-l inecap" property has a value of butt 228 // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-l inecap" property has a value of butt
215 // but shall be stroked if the "stroke-linecap" property has a value of roun d or square 229 // but shall be stroked if the "stroke-linecap" property has a value of roun d or square
216 DEFINE_STATIC_LOCAL(Path, tempPath, ()); 230 DEFINE_STATIC_LOCAL(Path, tempPath, ());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 344
331 if (childPaintInfo.phase == PaintPhaseForeground) { 345 if (childPaintInfo.phase == PaintPhaseForeground) {
332 SVGRenderingContext renderingContext(this, childPaintInfo); 346 SVGRenderingContext renderingContext(this, childPaintInfo);
333 347
334 if (renderingContext.isRenderingPrepared()) { 348 if (renderingContext.isRenderingPrepared()) {
335 const SVGRenderStyle* svgStyle = style()->svgStyle(); 349 const SVGRenderStyle* svgStyle = style()->svgStyle();
336 if (svgStyle->shapeRendering() == SR_CRISPEDGES) 350 if (svgStyle->shapeRendering() == SR_CRISPEDGES)
337 childPaintInfo.context->setShouldAntialias(false); 351 childPaintInfo.context->setShouldAntialias(false);
338 352
339 fillAndStrokePath(childPaintInfo.context); 353 fillAndStrokePath(childPaintInfo.context);
340 354 if (!m_markerPositions.isEmpty())
341 if (svgStyle->hasMarkers()) 355 drawMarkers(childPaintInfo);
342 m_markerLayoutInfo.drawMarkers(childPaintInfo);
343 } 356 }
344 } 357 }
345 358
346 if (drawsOutline) 359 if (drawsOutline)
347 paintOutline(childPaintInfo.context, IntRect(boundingBox)); 360 paintOutline(childPaintInfo.context, IntRect(boundingBox));
348 } 361 }
349 } 362 }
350 363
351 // This method is called from inside paintOutline() since we call paintOutline() 364 // This method is called from inside paintOutline() since we call paintOutline()
352 // while transformed to our coord system, return local coords 365 // while transformed to our coord system, return local coords
(...skipping 24 matching lines...) Expand all
377 fillRule = svgStyle->clipRule(); 390 fillRule = svgStyle->clipRule();
378 if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requir eStroke) && strokeContains(localPoint, hitRules.requireStroke)) 391 if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requir eStroke) && strokeContains(localPoint, hitRules.requireStroke))
379 || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.require Fill) && fillContains(localPoint, hitRules.requireFill, fillRule))) { 392 || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.require Fill) && fillContains(localPoint, hitRules.requireFill, fillRule))) {
380 updateHitTestResult(result, roundedLayoutPoint(localPoint)); 393 updateHitTestResult(result, roundedLayoutPoint(localPoint));
381 return true; 394 return true;
382 } 395 }
383 } 396 }
384 return false; 397 return false;
385 } 398 }
386 399
387 FloatRect RenderSVGShape::calculateMarkerBoundsIfNeeded() 400 static inline RenderSVGResourceMarker* markerForType(SVGMarkerType type, RenderS VGResourceMarker* markerStart, RenderSVGResourceMarker* markerMid, RenderSVGReso urceMarker* markerEnd)
388 { 401 {
389 SVGElement* svgElement = static_cast<SVGElement*>(node()); 402 switch (type) {
390 ASSERT(svgElement && svgElement->document()); 403 case StartMarker:
391 if (!svgElement->isStyled()) 404 return markerStart;
392 return FloatRect(); 405 case MidMarker:
406 return markerMid;
407 case EndMarker:
408 return markerEnd;
409 }
393 410
394 SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement) ; 411 ASSERT_NOT_REACHED();
395 if (!styledElement->supportsMarkers()) 412 return 0;
396 return FloatRect(); 413 }
397 414
398 ASSERT(style()->svgStyle()->hasMarkers()); 415 FloatRect RenderSVGShape::markerRect(float strokeWidth) const
416 {
417 ASSERT(!m_markerPositions.isEmpty());
399 418
400 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject( this); 419 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject( this);
401 if (!resources) 420 ASSERT(resources);
402 return FloatRect();
403 421
404 RenderSVGResourceMarker* markerStart = resources->markerStart(); 422 RenderSVGResourceMarker* markerStart = resources->markerStart();
405 RenderSVGResourceMarker* markerMid = resources->markerMid(); 423 RenderSVGResourceMarker* markerMid = resources->markerMid();
406 RenderSVGResourceMarker* markerEnd = resources->markerEnd(); 424 RenderSVGResourceMarker* markerEnd = resources->markerEnd();
407 if (!markerStart && !markerMid && !markerEnd) 425 ASSERT(markerStart || markerMid || markerEnd);
408 return FloatRect();
409 426
410 return m_markerLayoutInfo.calculateBoundaries(markerStart, markerMid, marker End, strokeWidth(), path()); 427 FloatRect boundaries;
428 unsigned size = m_markerPositions.size();
429 for (unsigned i = 0; i < size; ++i) {
430 if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i] .type, markerStart, markerMid, markerEnd))
431 boundaries.unite(marker->markerBoundaries(marker->markerTransformati on(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth)));
432 }
433 return boundaries;
411 } 434 }
412 435
413 void RenderSVGShape::updateCachedBoundaries() 436 void RenderSVGShape::updateCachedBoundaries()
414 { 437 {
415 if (isEmpty()) { 438 if (isEmpty()) {
416 m_fillBoundingBox = FloatRect(); 439 m_fillBoundingBox = FloatRect();
417 m_strokeAndMarkerBoundingBox = FloatRect(); 440 m_strokeAndMarkerBoundingBox = FloatRect();
418 m_repaintBoundingBox = FloatRect(); 441 m_repaintBoundingBox = FloatRect();
419 return; 442 return;
420 } 443 }
(...skipping 18 matching lines...) Expand all
439 float RenderSVGShape::strokeWidth() const 462 float RenderSVGShape::strokeWidth() const
440 { 463 {
441 SVGElement* svgElement = static_cast<SVGElement*>(node()); 464 SVGElement* svgElement = static_cast<SVGElement*>(node());
442 SVGLengthContext lengthContext(svgElement); 465 SVGLengthContext lengthContext(svgElement);
443 return style()->svgStyle()->strokeWidth().value(lengthContext); 466 return style()->svgStyle()->strokeWidth().value(lengthContext);
444 } 467 }
445 468
446 void RenderSVGShape::inflateWithStrokeAndMarkerBounds() 469 void RenderSVGShape::inflateWithStrokeAndMarkerBounds()
447 { 470 {
448 const SVGRenderStyle* svgStyle = style()->svgStyle(); 471 const SVGRenderStyle* svgStyle = style()->svgStyle();
449 FloatRect strokeRect;
450 if (svgStyle->hasStroke()) { 472 if (svgStyle->hasStroke()) {
451 BoundingRectStrokeStyleApplier strokeStyle(this, style()); 473 BoundingRectStrokeStyleApplier strokeStyle(this, style());
452 m_strokeAndMarkerBoundingBox.unite(path().strokeBoundingRect(&strokeStyl e)); 474 m_strokeAndMarkerBoundingBox.unite(path().strokeBoundingRect(&strokeStyl e));
453 } 475 }
454 if (svgStyle->hasMarkers()) { 476 if (!m_markerPositions.isEmpty())
455 FloatRect markerBounds = calculateMarkerBoundsIfNeeded(); 477 m_strokeAndMarkerBoundingBox.unite(markerRect(strokeWidth()));
456 if (!markerBounds.isEmpty()) 478 }
457 m_strokeAndMarkerBoundingBox.unite(markerBounds); 479
480 void RenderSVGShape::drawMarkers(PaintInfo& paintInfo)
481 {
482 ASSERT(!m_markerPositions.isEmpty());
483
484 SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject( this);
485 if (!resources)
486 return;
487
488 RenderSVGResourceMarker* markerStart = resources->markerStart();
489 RenderSVGResourceMarker* markerMid = resources->markerMid();
490 RenderSVGResourceMarker* markerEnd = resources->markerEnd();
491 if (!markerStart && !markerMid && !markerEnd)
492 return;
493
494 float strokeWidth = this->strokeWidth();
495 unsigned size = m_markerPositions.size();
496 for (unsigned i = 0; i < size; ++i) {
497 if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i] .type, markerStart, markerMid, markerEnd))
498 marker->draw(paintInfo, marker->markerTransformation(m_markerPositio ns[i].origin, m_markerPositions[i].angle, strokeWidth));
458 } 499 }
459 } 500 }
460 501
461 void RenderSVGShape::processZeroLengthSubpaths() 502 void RenderSVGShape::processZeroLengthSubpaths()
462 { 503 {
463 m_zeroLengthLinecapLocations.clear(); 504 m_zeroLengthLinecapLocations.clear();
464 505
465 float strokeWidth = this->strokeWidth(); 506 float strokeWidth = this->strokeWidth();
466 if (!strokeWidth || !shouldStrokeZeroLengthSubpath()) 507 if (!strokeWidth || !shouldStrokeZeroLengthSubpath())
467 return; 508 return;
468 509
469 ASSERT(m_path); 510 ASSERT(m_path);
470 511
471 SVGSubpathData subpathData(m_zeroLengthLinecapLocations); 512 SVGSubpathData subpathData(m_zeroLengthLinecapLocations);
472 m_path->apply(&subpathData, SVGSubpathData::updateFromPathElement); 513 m_path->apply(&subpathData, SVGSubpathData::updateFromPathElement);
473 subpathData.pathIsDone(); 514 subpathData.pathIsDone();
474 } 515 }
475 516
517 void RenderSVGShape::processMarkerPositions()
518 {
519 m_markerPositions.clear();
520
521 if (!shouldGenerateMarkerPositions())
522 return;
523
524 ASSERT(m_path);
525
526 SVGMarkerData markerData(m_markerPositions);
527 m_path->apply(&markerData, SVGMarkerData::updateFromPathElement);
528 markerData.pathIsDone();
529 }
530
476 } 531 }
477 532
478 #endif // ENABLE(SVG) 533 #endif // ENABLE(SVG)
OLDNEW
« no previous file with comments | « Source/WebCore/rendering/svg/RenderSVGShape.h ('k') | Source/WebCore/rendering/svg/SVGMarkerData.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698