summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderPath.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/rendering/RenderPath.cpp
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/rendering/RenderPath.cpp')
-rw-r--r--WebCore/rendering/RenderPath.cpp129
1 files changed, 76 insertions, 53 deletions
diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp
index bcedd38..b1e2a8f 100644
--- a/WebCore/rendering/RenderPath.cpp
+++ b/WebCore/rendering/RenderPath.cpp
@@ -31,10 +31,11 @@
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "RenderSVGContainer.h"
+#include "RenderSVGResourceFilter.h"
+#include "RenderSVGResourceMarker.h"
#include "StrokeStyleApplier.h"
#include "SVGPaintServer.h"
#include "SVGRenderSupport.h"
-#include "SVGResourceMarker.h"
#include "SVGStyledTransformableElement.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
@@ -64,19 +65,12 @@ private:
RenderPath::RenderPath(SVGStyledTransformableElement* node)
: RenderSVGModelObject(node)
+ , m_needsBoundariesUpdate(false) // default is false, as this is only used when a RenderSVGResource tells us that the boundaries need to be recached
+ , m_needsPathUpdate(true) // default is true, so we grab a Path object once from SVGStyledTransformableElement
+ , m_needsTransformUpdate(true) // default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement
{
}
-const AffineTransform& RenderPath::localToParentTransform() const
-{
- return m_localTransform;
-}
-
-AffineTransform RenderPath::localTransform() const
-{
- return m_localTransform;
-}
-
bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const
{
if (m_path.isEmpty())
@@ -171,22 +165,34 @@ FloatRect RenderPath::repaintRectInLocalCoordinates() const
return m_cachedLocalRepaintRect;
}
-void RenderPath::setPath(const Path& newPath)
-{
- m_path = newPath;
- m_cachedLocalRepaintRect = FloatRect();
- m_cachedLocalStrokeBBox = FloatRect();
- m_cachedLocalFillBBox = FloatRect();
- m_cachedLocalMarkerBBox = FloatRect();
-}
-
void RenderPath::layout()
{
LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
-
SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
- m_localTransform = element->animatedLocalTransform();
- setPath(element->toPathData());
+
+ // We need to update the Path object whenever the underlying SVGStyledTransformableElement uses relative values
+ // as the viewport size may have changed. It would be nice to optimize this to detect these changes, and only
+ // update when needed, even when using relative values.
+ if (!m_needsPathUpdate && element->hasRelativeValues())
+ m_needsPathUpdate = true;
+
+ bool needsUpdate = m_needsPathUpdate || m_needsTransformUpdate || m_needsBoundariesUpdate;
+
+ if (m_needsBoundariesUpdate)
+ m_needsBoundariesUpdate = false;
+
+ if (m_needsPathUpdate) {
+ m_path = element->toPathData();
+ m_needsPathUpdate = false;
+ }
+
+ if (m_needsTransformUpdate) {
+ m_localTransform = element->animatedLocalTransform();
+ m_needsTransformUpdate = false;
+ }
+
+ if (needsUpdate)
+ invalidateCachedBoundaries();
repainter.repaintAfterLayout();
setNeedsLayout(false);
@@ -223,29 +229,32 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int)
return;
PaintInfo childPaintInfo(paintInfo);
- childPaintInfo.context->save();
- applyTransformToPaintInfo(childPaintInfo, m_localTransform);
- SVGResourceFilter* filter = 0;
-
- if (childPaintInfo.phase == PaintPhaseForeground) {
- PaintInfo savedInfo(childPaintInfo);
-
- if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) {
- if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
- childPaintInfo.context->setShouldAntialias(false);
- fillAndStrokePath(m_path, childPaintInfo.context, style(), this);
-
- if (static_cast<SVGStyledElement*>(node())->supportsMarkers())
- m_markerLayoutInfo.drawMarkers(childPaintInfo);
+ bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
+ if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
+ childPaintInfo.context->save();
+ applyTransformToPaintInfo(childPaintInfo, m_localTransform);
+ RenderSVGResourceFilter* filter = 0;
+
+ if (childPaintInfo.phase == PaintPhaseForeground) {
+ PaintInfo savedInfo(childPaintInfo);
+
+ if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) {
+ if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
+ childPaintInfo.context->setShouldAntialias(false);
+ fillAndStrokePath(m_path, childPaintInfo.context, style(), this);
+
+ if (static_cast<SVGStyledElement*>(node())->supportsMarkers())
+ m_markerLayoutInfo.drawMarkers(childPaintInfo);
+ }
+ finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context);
}
- finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context);
- }
- if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
- paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()),
- static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style());
-
- childPaintInfo.context->restore();
+ if (drawsOutline)
+ paintOutline(childPaintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()),
+ static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()));
+
+ childPaintInfo.context->restore();
+ }
}
// This method is called from inside paintOutline() since we call paintOutline()
@@ -293,28 +302,28 @@ void RenderPath::calculateMarkerBoundsIfNeeded() const
return;
const SVGRenderStyle* svgStyle = style()->svgStyle();
- AtomicString startMarkerId(svgStyle->startMarker());
- AtomicString midMarkerId(svgStyle->midMarker());
- AtomicString endMarkerId(svgStyle->endMarker());
+ AtomicString startMarkerId(svgStyle->markerStartResource());
+ AtomicString midMarkerId(svgStyle->markerMidResource());
+ AtomicString endMarkerId(svgStyle->markerEndResource());
- SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId, this);
- SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId, this);
- SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId, this);
+ RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, startMarkerId);
+ RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, midMarkerId);
+ RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(doc, endMarkerId);
if (!startMarker && !startMarkerId.isEmpty())
svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement);
else if (startMarker)
- startMarker->addClient(styledElement);
+ startMarker->addClient(this);
if (!midMarker && !midMarkerId.isEmpty())
svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement);
else if (midMarker)
- midMarker->addClient(styledElement);
+ midMarker->addClient(this);
if (!endMarker && !endMarkerId.isEmpty())
svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement);
else if (endMarker)
- endMarker->addClient(styledElement);
+ endMarker->addClient(this);
if (!startMarker && !midMarker && !endMarker)
return;
@@ -323,6 +332,20 @@ void RenderPath::calculateMarkerBoundsIfNeeded() const
m_cachedLocalMarkerBBox = m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path);
}
+void RenderPath::invalidateCachedBoundaries()
+{
+ m_cachedLocalRepaintRect = FloatRect();
+ m_cachedLocalStrokeBBox = FloatRect();
+ m_cachedLocalFillBBox = FloatRect();
+ m_cachedLocalMarkerBBox = FloatRect();
+}
+
+void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+ invalidateCachedBoundaries();
+ RenderSVGModelObject::styleWillChange(diff, newStyle);
+}
+
}
#endif // ENABLE(SVG)