diff options
| author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
| commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
| tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/svg | |
| parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
| download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz | |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/rendering/svg')
72 files changed, 508 insertions, 340 deletions
diff --git a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp index a6bcd0296..234e7ce6c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGAllInOne.cpp @@ -77,3 +77,4 @@ #include "SVGTextMetrics.cpp" #include "SVGTextMetricsBuilder.cpp" #include "SVGTextQuery.cpp" + diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp index 9f39357c1..f120b9946 100644 --- a/Source/WebCore/rendering/svg/RenderSVGBlock.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGBlock.cpp @@ -31,8 +31,8 @@ namespace WebCore { -RenderSVGBlock::RenderSVGBlock(SVGElement* node) - : RenderBlock(node) +RenderSVGBlock::RenderSVGBlock(SVGElement* element) + : RenderBlock(element) { } diff --git a/Source/WebCore/rendering/svg/RenderSVGBlock.h b/Source/WebCore/rendering/svg/RenderSVGBlock.h index 222d5ee20..0bd300c1c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGBlock.h +++ b/Source/WebCore/rendering/svg/RenderSVGBlock.h @@ -41,6 +41,8 @@ private: virtual void setStyle(PassRefPtr<RenderStyle>); virtual void updateFromStyle() OVERRIDE; + virtual bool isRenderSVGBlock() const OVERRIDE { return true; }; + virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp index 5069f41aa..9305dc6b3 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.cpp @@ -35,6 +35,7 @@ #include "SVGResources.h" #include "SVGResourcesCache.h" #include "SVGStyledElement.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -137,7 +138,7 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&) } if (continueRendering) { - childPaintInfo.updatePaintingRootForChildren(this); + childPaintInfo.updateSubtreePaintRootForChildren(this); for (RenderObject* child = firstChild(); child; child = child->nextSibling()) child->paint(childPaintInfo, IntPoint()); } @@ -150,12 +151,12 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&) // We should instead disable our clip during PaintPhaseOutline if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect)); - paintOutline(paintInfo.context, paintRectInParent); + paintOutline(paintInfo, paintRectInParent); } } // addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call -void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&) +void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); if (!paintRectInParent.isEmpty()) @@ -186,6 +187,12 @@ bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTest } } + // Accessibility wants to return SVG containers, if appropriate. + if (request.type() & HitTestRequest::AccessibilityHitTest && m_objectBoundingBox.contains(localPoint)) { + updateHitTestResult(result, roundedLayoutPoint(localPoint)); + return true; + } + // Spec: Only graphical elements can be targeted by the mouse, period. // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched." return false; diff --git a/Source/WebCore/rendering/svg/RenderSVGContainer.h b/Source/WebCore/rendering/svg/RenderSVGContainer.h index 3c0fa9814..70e1ec8d5 100644 --- a/Source/WebCore/rendering/svg/RenderSVGContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGContainer.h @@ -44,6 +44,7 @@ public: virtual void paint(PaintInfo&, const LayoutPoint&); virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } + virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; } virtual bool didTransformToRootUpdate() { return false; } bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; } @@ -58,7 +59,7 @@ protected: virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE; virtual void removeChild(RenderObject*) OVERRIDE; - virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&); + virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE; virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; } virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; } @@ -90,13 +91,13 @@ private: inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object) { - ASSERT(!object || object->isSVGContainer()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGContainer()); return static_cast<RenderSVGContainer*>(object); } inline const RenderSVGContainer* toRenderSVGContainer(const RenderObject* object) { - ASSERT(!object || object->isSVGContainer()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGContainer()); return static_cast<const RenderSVGContainer*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp index b4a76531e..8c1df2da4 100644 --- a/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp @@ -31,12 +31,12 @@ #include "SVGCircleElement.h" #include "SVGEllipseElement.h" +#include "SVGGraphicsElement.h" #include "SVGNames.h" -#include "SVGStyledTransformableElement.h" namespace WebCore { -RenderSVGEllipse::RenderSVGEllipse(SVGStyledTransformableElement* node) +RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement* node) : RenderSVGShape(node) , m_usePathFallback(false) { diff --git a/Source/WebCore/rendering/svg/RenderSVGEllipse.h b/Source/WebCore/rendering/svg/RenderSVGEllipse.h index f5129df90..a5af34bc4 100644 --- a/Source/WebCore/rendering/svg/RenderSVGEllipse.h +++ b/Source/WebCore/rendering/svg/RenderSVGEllipse.h @@ -29,13 +29,13 @@ #if ENABLE(SVG) #include "RenderSVGShape.h" -#include "SVGStyledTransformableElement.h" +#include "SVGGraphicsElement.h" namespace WebCore { class RenderSVGEllipse : public RenderSVGShape { public: - explicit RenderSVGEllipse(SVGStyledTransformableElement*); + explicit RenderSVGEllipse(SVGGraphicsElement*); virtual ~RenderSVGEllipse(); private: diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp index 408d887f0..9bd4672ed 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp @@ -35,6 +35,7 @@ #include "SVGResourcesCache.h" #include "SVGSVGElement.h" #include "TransformState.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -193,9 +194,9 @@ bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, return false; } -void RenderSVGForeignObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const +void RenderSVGForeignObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, mode & SnapOffsetForTransforms, wasFixed); + SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const diff --git a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h index 00979de61..02c29cc05 100644 --- a/Source/WebCore/rendering/svg/RenderSVGForeignObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGForeignObject.h @@ -54,7 +54,7 @@ public: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE; virtual bool isSVGForeignObject() const { return true; } - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE; + virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp index 31d5da5ca..9b41ae319 100644 --- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp @@ -27,6 +27,7 @@ #include "SVGNames.h" #include "SVGResourcesCache.h" #include "SVGStopElement.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -72,7 +73,7 @@ SVGGradientElement* RenderSVGGradientStop::gradientElement() const { ContainerNode* parentNode = node()->parentNode(); if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag)) - return static_cast<SVGGradientElement*>(parentNode); + return toSVGGradientElement(parentNode); return 0; } diff --git a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h index 1c0e4033b..ac8b97ac9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGGradientStop.h +++ b/Source/WebCore/rendering/svg/RenderSVGGradientStop.h @@ -47,6 +47,7 @@ public: virtual FloatRect objectBoundingBox() const { return FloatRect(); } virtual FloatRect strokeBoundingBox() const { return FloatRect(); } virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction) OVERRIDE { return false; } protected: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); @@ -57,7 +58,7 @@ private: inline const RenderSVGGradientStop* toRenderSVGGradientStop(const RenderObject* object) { - ASSERT(!object || object->isSVGGradientStop()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGGradientStop()); return static_cast<const RenderSVGGradientStop*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp index 4d37e13d7..2a015a5c0 100644 --- a/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp @@ -24,6 +24,7 @@ #include "RenderSVGPath.h" #include "SVGStyledElement.h" +#include <wtf/StackStats.h> namespace WebCore { diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.cpp b/Source/WebCore/rendering/svg/RenderSVGImage.cpp index 45db954df..76d7c5c2e 100644 --- a/Source/WebCore/rendering/svg/RenderSVGImage.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGImage.cpp @@ -44,6 +44,7 @@ #include "SVGRenderingContext.h" #include "SVGResources.h" #include "SVGResourcesCache.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -63,7 +64,7 @@ RenderSVGImage::~RenderSVGImage() bool RenderSVGImage::updateImageViewport() { - SVGImageElement* image = static_cast<SVGImageElement*>(node()); + SVGImageElement* image = toSVGImageElement(node()); FloatRect oldBoundaries = m_objectBoundingBox; SVGLengthContext lengthContext(image); @@ -87,7 +88,7 @@ void RenderSVGImage::layout() bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundariesUpdate; if (m_needsTransformUpdate) { - m_localTransform = static_cast<SVGImageElement*>(node())->animatedLocalTransform(); + m_localTransform = toSVGImageElement(node())->animatedLocalTransform(); m_needsTransformUpdate = false; } @@ -132,22 +133,35 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&) SVGRenderingContext renderingContext(this, childPaintInfo); if (renderingContext.isRenderingPrepared()) { - RefPtr<Image> image = m_imageResource->image(); - FloatRect destRect = m_objectBoundingBox; - FloatRect srcRect(0, 0, image->width(), image->height()); + if (style()->svgStyle()->bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_bufferedForeground)) + return; - SVGImageElement* imageElement = static_cast<SVGImageElement*>(node()); - imageElement->preserveAspectRatio().transformRect(destRect, srcRect); - - childPaintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect); + paintForeground(childPaintInfo); } } if (drawsOutline) - paintOutline(childPaintInfo.context, IntRect(boundingBox)); + paintOutline(childPaintInfo, IntRect(boundingBox)); } } +void RenderSVGImage::paintForeground(PaintInfo& paintInfo) +{ + RefPtr<Image> image = m_imageResource->image(); + FloatRect destRect = m_objectBoundingBox; + FloatRect srcRect(0, 0, image->width(), image->height()); + + SVGImageElement* imageElement = toSVGImageElement(node()); + imageElement->preserveAspectRatio().transformRect(destRect, srcRect); + + paintInfo.context->drawImage(image.get(), ColorSpaceDeviceRGB, destRect, srcRect); +} + +void RenderSVGImage::invalidateBufferedForeground() +{ + m_bufferedForeground.clear(); +} + bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. @@ -188,10 +202,12 @@ void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*) m_objectBoundingBox = FloatRect(); updateImageViewport(); + invalidateBufferedForeground(); + repaint(); } -void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&) +void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { // this is called from paint() after the localTransform has already been applied IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates()); diff --git a/Source/WebCore/rendering/svg/RenderSVGImage.h b/Source/WebCore/rendering/svg/RenderSVGImage.h index 905a8d37d..af85b895b 100644 --- a/Source/WebCore/rendering/svg/RenderSVGImage.h +++ b/Source/WebCore/rendering/svg/RenderSVGImage.h @@ -43,14 +43,18 @@ public: bool updateImageViewport(); virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } + virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; } virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } RenderImageResource* imageResource() { return m_imageResource.get(); } const RenderImageResource* imageResource() const { return m_imageResource.get(); } + // Note: Assumes the PaintInfo context has had all local transforms applied. + void paintForeground(PaintInfo&); + private: virtual const char* renderName() const { return "RenderSVGImage"; } - virtual bool isSVGImage() const { return true; } + virtual bool isSVGImage() const OVERRIDE { return true; } virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } @@ -59,13 +63,15 @@ private: virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; } virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const OVERRIDE { return m_repaintBoundingBoxExcludingShadow; } - virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&); + virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE; virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); virtual void layout(); virtual void paint(PaintInfo&, const LayoutPoint&); + void invalidateBufferedForeground(); + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); virtual AffineTransform localTransform() const { return m_localTransform; } @@ -78,17 +84,19 @@ private: FloatRect m_repaintBoundingBox; FloatRect m_repaintBoundingBoxExcludingShadow; OwnPtr<RenderImageResource> m_imageResource; + + OwnPtr<ImageBuffer> m_bufferedForeground; }; inline RenderSVGImage* toRenderSVGImage(RenderObject* object) { - ASSERT(!object || object->isSVGImage()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGImage()); return static_cast<RenderSVGImage*>(object); } inline const RenderSVGImage* toRenderSVGImage(const RenderObject* object) { - ASSERT(!object || object->isSVGImage()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGImage()); return static_cast<const RenderSVGImage*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp index 9252c54f3..e8dfe03e4 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp @@ -32,8 +32,8 @@ namespace WebCore { -RenderSVGInline::RenderSVGInline(Node* n) - : RenderInline(n) +RenderSVGInline::RenderSVGInline(Element* element) + : RenderInline(element) { setAlwaysCreateLineBoxes(); } @@ -79,9 +79,9 @@ void RenderSVGInline::computeFloatRectForRepaint(const RenderLayerModelObject* r SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const +void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, mode & SnapOffsetForTransforms, wasFixed); + SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.h b/Source/WebCore/rendering/svg/RenderSVGInline.h index 50dec2ddd..dbeb0d3ed 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInline.h +++ b/Source/WebCore/rendering/svg/RenderSVGInline.h @@ -30,7 +30,7 @@ namespace WebCore { class RenderSVGInline : public RenderInline { public: - explicit RenderSVGInline(Node*); + explicit RenderSVGInline(Element*); virtual const char* renderName() const { return "RenderSVGInline"; } virtual bool requiresLayer() const { return false; } @@ -47,7 +47,7 @@ public: virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE; virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE; + virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp index 2371d1abf..4bf0ec595 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp @@ -185,7 +185,7 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point) if (!box->isSVGInlineTextBox()) continue; - SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); + SVGInlineTextBox* textBox = toSVGInlineTextBox(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); @@ -228,8 +228,7 @@ void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, c Document* document = renderer->document(); ASSERT(document); - StyleResolver* styleResolver = document->styleResolver(); - ASSERT(styleResolver); + StyleResolver* styleResolver = document->ensureStyleResolver(); // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer); diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.h b/Source/WebCore/rendering/svg/RenderSVGInlineText.h index 7643cf1ab..b6fc83008 100644 --- a/Source/WebCore/rendering/svg/RenderSVGInlineText.h +++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.h @@ -69,13 +69,13 @@ private: inline RenderSVGInlineText* toRenderSVGInlineText(RenderObject* object) { - ASSERT(!object || object->isSVGInlineText()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGInlineText()); return static_cast<RenderSVGInlineText*>(object); } inline const RenderSVGInlineText* toRenderSVGInlineText(const RenderObject* object) { - ASSERT(!object || object->isSVGInlineText()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGInlineText()); return static_cast<const RenderSVGInlineText*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp index 019204e4e..6733a2e05 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.cpp @@ -57,9 +57,9 @@ void RenderSVGModelObject::computeFloatRectForRepaint(const RenderLayerModelObje SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const +void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, mode & SnapOffsetForTransforms, wasFixed); + SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const @@ -131,8 +131,8 @@ static void getElementCTM(SVGElement* element, AffineTransform& transform) Node* current = element; while (current && current->isSVGElement()) { - SVGElement* currentElement = static_cast<SVGElement*>(current); - if (currentElement->isStyled()) { + SVGElement* currentElement = toSVGElement(current); + if (currentElement->isSVGStyledElement()) { localTransform = currentElement->renderer()->localToParentTransform(); transform = localTransform.multiply(transform); } @@ -140,7 +140,7 @@ static void getElementCTM(SVGElement* element, AffineTransform& transform) if (currentElement == stopAtElement) break; - current = current->parentOrHostNode(); + current = current->parentOrShadowHostNode(); } } @@ -180,7 +180,7 @@ bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const Float if (!isGraphicsElement(renderer)) return false; AffineTransform ctm; - SVGElement* svgElement = static_cast<SVGElement*>(renderer->node()); + SVGElement* svgElement = toSVGElement(renderer->node()); getElementCTM(svgElement, ctm); ASSERT(svgElement->renderer()); return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates())); @@ -193,7 +193,7 @@ bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const FloatRec if (!isGraphicsElement(renderer)) return false; AffineTransform ctm; - SVGElement* svgElement = static_cast<SVGElement*>(renderer->node()); + SVGElement* svgElement = toSVGElement(renderer->node()); getElementCTM(svgElement, ctm); ASSERT(svgElement->renderer()); return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates())); diff --git a/Source/WebCore/rendering/svg/RenderSVGModelObject.h b/Source/WebCore/rendering/svg/RenderSVGModelObject.h index dc2d5da39..0511f2772 100644 --- a/Source/WebCore/rendering/svg/RenderSVGModelObject.h +++ b/Source/WebCore/rendering/svg/RenderSVGModelObject.h @@ -58,7 +58,7 @@ public: virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE; + virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.cpp b/Source/WebCore/rendering/svg/RenderSVGPath.cpp index cf658359d..97f713012 100644 --- a/Source/WebCore/rendering/svg/RenderSVGPath.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGPath.cpp @@ -30,13 +30,13 @@ #if ENABLE(SVG) #include "RenderSVGPath.h" +#include "SVGGraphicsElement.h" #include "SVGPathElement.h" -#include "SVGStyledTransformableElement.h" #include "SVGSubpathData.h" namespace WebCore { -RenderSVGPath::RenderSVGPath(SVGStyledTransformableElement* node) +RenderSVGPath::RenderSVGPath(SVGGraphicsElement* node) : RenderSVGShape(node) { } diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.h b/Source/WebCore/rendering/svg/RenderSVGPath.h index ab1cf1c0b..674289564 100644 --- a/Source/WebCore/rendering/svg/RenderSVGPath.h +++ b/Source/WebCore/rendering/svg/RenderSVGPath.h @@ -33,11 +33,11 @@ namespace WebCore { class RenderSVGPath : public RenderSVGShape { public: - explicit RenderSVGPath(SVGStyledTransformableElement*); + explicit RenderSVGPath(SVGGraphicsElement*); virtual ~RenderSVGPath(); private: - virtual bool isSVGPath() const { return true; } + virtual bool isSVGPath() const OVERRIDE { return true; } virtual const char* renderName() const { return "RenderSVGPath"; } virtual void updateShapeFromElement() OVERRIDE; @@ -54,6 +54,12 @@ private: Vector<FloatPoint> m_zeroLengthLinecapLocations; }; +inline RenderSVGPath* toRenderSVGPath(RenderObject* object) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGPath()); + return static_cast<RenderSVGPath*>(object); +} + } #endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGRect.cpp b/Source/WebCore/rendering/svg/RenderSVGRect.cpp index c7f9c5b7b..1fa46a4a1 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRect.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRect.cpp @@ -32,7 +32,6 @@ #include "SVGNames.h" #include "SVGRectElement.h" -#include <wtf/Platform.h> namespace WebCore { diff --git a/Source/WebCore/rendering/svg/RenderSVGResource.cpp b/Source/WebCore/rendering/svg/RenderSVGResource.cpp index fd16ef29d..6ced1c79c 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResource.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResource.cpp @@ -180,7 +180,7 @@ static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object if (!object->node() || !object->node()->isSVGElement()) return; - HashSet<SVGElement*>* dependencies = object->document()->accessSVGExtensions()->setOfElementsReferencingTarget(static_cast<SVGElement*>(object->node())); + HashSet<SVGElement*>* dependencies = object->document()->accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object->node())); if (!dependencies) return; HashSet<SVGElement*>::iterator end = dependencies->end(); diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp index 7339e2859..9967d70ed 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp @@ -39,16 +39,15 @@ #include "RenderStyle.h" #include "SVGClipPathElement.h" #include "SVGElement.h" +#include "SVGGraphicsElement.h" #include "SVGNames.h" #include "SVGRenderSupport.h" #include "SVGRenderingContext.h" #include "SVGResources.h" #include "SVGResourcesCache.h" #include "SVGStyledElement.h" -#include "SVGStyledTransformableElement.h" #include "SVGUnitTypes.h" #include "SVGUseElement.h" -#include <wtf/UnusedParam.h> namespace WebCore { @@ -117,9 +116,9 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const // Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts. if (renderer->isSVGText()) return false; - if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyledTransformable()) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGGraphicsElement()) continue; - SVGStyledTransformableElement* styled = static_cast<SVGStyledTransformableElement*>(childNode); + SVGGraphicsElement* styled = toSVGGraphicsElement(childNode); RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) continue; @@ -169,7 +168,7 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons } AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform); if (shouldCreateClipData && !repaintRect.isEmpty()) { if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated)) @@ -234,7 +233,7 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData // Draw all clipPath children into a global mask. for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); - if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer) continue; if (renderer->needsLayout()) { frame()->view()->setPaintBehavior(oldBehavior); @@ -247,7 +246,7 @@ bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData WindRule newClipRule = style->svgStyle()->clipRule(); bool isUseElement = childNode->hasTagName(SVGNames::useTag); if (isUseElement) { - SVGUseElement* useElement = static_cast<SVGUseElement*>(childNode); + SVGUseElement* useElement = toSVGUseElement(childNode); renderer = useElement->rendererClipChild(); if (!renderer) continue; @@ -276,7 +275,7 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect() // This is a rough heuristic to appraise the clip size and doesn't consider clip on clip. for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); - if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer) continue; if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag)) continue; @@ -306,13 +305,13 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); - if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer) continue; if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag)) continue; IntPoint hitPoint; HitTestResult result(hitPoint); - if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent), result, point, HitTestForeground)) + if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowShadowContent), result, point, HitTestForeground)) return true; } diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp index e311c1c21..38bd67a63 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp @@ -25,9 +25,10 @@ #include "RenderLayer.h" #include "RenderSVGRoot.h" #include "RenderView.h" +#include "SVGGraphicsElement.h" #include "SVGRenderingContext.h" #include "SVGResourcesCache.h" -#include "SVGStyledTransformableElement.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -86,7 +87,7 @@ void RenderSVGResourceContainer::idChanged() // Remove old id, that is guaranteed to be present in cache. SVGDocumentExtensions* extensions = svgExtensionsFromNode(node()); extensions->removeResource(m_id); - m_id = static_cast<Element*>(node())->getIdAttribute(); + m_id = toElement(node())->getIdAttribute(); registerResource(); } @@ -114,13 +115,18 @@ void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout); } + markAllClientLayersForInvalidation(); + + m_isInvalidating = false; +} + +void RenderSVGResourceContainer::markAllClientLayersForInvalidation() +{ #if ENABLE(CSS_FILTERS) HashSet<RenderLayer*>::iterator layerEnd = m_clientLayers.end(); for (HashSet<RenderLayer*>::iterator it = m_clientLayers.begin(); it != layerEnd; ++it) (*it)->filterNeedsRepaint(); #endif - - m_isInvalidating = false; } void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, InvalidationMode mode) @@ -184,7 +190,7 @@ void RenderSVGResourceContainer::registerResource() const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end(); for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) { ASSERT((*it)->hasPendingResources()); - (*it)->clearHasPendingResourcesIfPossible(); + extensions->clearHasPendingResourcesIfPossible(*it); RenderObject* renderer = (*it)->renderer(); if (!renderer) continue; @@ -220,7 +226,7 @@ AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderOb if (!object->isSVGShape()) return resourceTransform; - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); + SVGGraphicsElement* element = toSVGGraphicsElement(object->node()); AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate); transform *= resourceTransform; return transform; diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h index 0f074863b..0f425cd45 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceContainer.h @@ -57,6 +57,7 @@ protected: // Used from the invalidateClient/invalidateClients methods from classes, inheriting from us. void markAllClientsForInvalidation(InvalidationMode); + void markAllClientLayersForInvalidation(); void markClientForInvalidation(RenderObject*, InvalidationMode); private: diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp index 7d4eedfc9..c5e6bbb26 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp @@ -49,8 +49,6 @@ #include "Settings.h" #include "SourceAlpha.h" #include "SourceGraphic.h" - -#include <wtf/UnusedParam.h> #include <wtf/Vector.h> using namespace std; @@ -99,7 +97,7 @@ void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool m PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter) { - SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); + SVGFilterElement* filterElement = toSVGFilterElement(node()); FloatRect targetBoundingBox = filter->targetBoundingBox(); // Add effects to the builder @@ -108,7 +106,7 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* if (!node->isSVGElement()) continue; - SVGElement* element = static_cast<SVGElement*>(node); + SVGElement* element = toSVGElement(node); if (!element->isFilterEffect()) continue; @@ -121,8 +119,8 @@ PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* builder->appendEffectToEffectReferences(effect, effectElement->renderer()); effectElement->setStandardAttributes(effect.get()); effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), targetBoundingBox)); - effect->setColorSpace(effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB - ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); + effect->setOperatingColorSpace( + effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB); builder->add(effectElement->result(), effect); } return builder.release(); @@ -159,14 +157,14 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, OwnPtr<FilterData> filterData(adoptPtr(new FilterData)); FloatRect targetBoundingBox = object->objectBoundingBox(); - SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node()); + SVGFilterElement* filterElement = toSVGFilterElement(node()); filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits(), targetBoundingBox); if (filterData->boundaries.isEmpty()) return false; // Determine absolute transformation matrix for filter. AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform); if (!absoluteTransform.isInvertible()) return false; @@ -175,9 +173,9 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, // Determine absolute boundaries of the filter and the drawing region. FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries); - FloatRect drawingRegion = object->strokeBoundingBox(); - drawingRegion.intersect(filterData->boundaries); - FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion); + filterData->drawingRegion = object->strokeBoundingBox(); + filterData->drawingRegion.intersect(filterData->boundaries); + FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion); // Create the SVGFilter object. bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; @@ -222,7 +220,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, // If the drawingRegion is empty, we have something like <g filter=".."/>. // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource. - if (drawingRegion.isEmpty()) { + if (filterData->drawingRegion.isEmpty()) { ASSERT(!m_filter.contains(object)); filterData->savedContext = context; m_filter.set(object, filterData.leakPtr()); @@ -236,7 +234,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, OwnPtr<ImageBuffer> sourceGraphic; RenderingMode renderingMode = object->document()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated; - if (!SVGRenderingContext::createImageBuffer(drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) { + if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) { ASSERT(!m_filter.contains(object)); filterData->savedContext = context; m_filter.set(object, filterData.leakPtr()); @@ -309,13 +307,9 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo // Always true if filterData is just built (filterData->state == FilterData::Built). if (!lastEffect->hasResult()) { filterData->state = FilterData::Applying; - lastEffect->apply(); + lastEffect->applyAll(); lastEffect->correctFilterResultIfNeeded(); -#if !USE(CG) - ImageBuffer* resultImage = lastEffect->asImageBuffer(); - if (resultImage) - resultImage->transformColorSpace(lastEffect->colorSpace(), ColorSpaceDeviceRGB); -#endif + lastEffect->transformResultColorSpace(ColorSpaceDeviceRGB); } filterData->state = FilterData::Built; @@ -335,7 +329,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo FloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object) { - if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node())) + if (SVGFilterElement* element = toSVGFilterElement(node())) return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits(), object->objectBoundingBox()); return FloatRect(); @@ -365,6 +359,13 @@ void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, co // Repaint the image on the screen. markClientForInvalidation(it->key, RepaintInvalidation); } + markAllClientLayersForInvalidation(); +} + +FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const +{ + FilterData* filterData = m_filter.get(object); + return filterData ? filterData->drawingRegion : FloatRect(); } } diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h index db422c17e..4ad9ad037 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h @@ -56,6 +56,7 @@ public: GraphicsContext* savedContext; AffineTransform shearFreeAbsoluteTransform; FloatRect boundaries; + FloatRect drawingRegion; FloatSize scale; FilterDataState state; }; @@ -68,7 +69,7 @@ public: virtual ~RenderSVGResourceFilter(); virtual const char* renderName() const { return "RenderSVGResourceFilter"; } - virtual bool isSVGResourceFilter() const { return true; } + virtual bool isSVGResourceFilter() const OVERRIDE { return true; } virtual void removeAllClientsFromCache(bool markForInvalidation = true); virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); @@ -80,20 +81,27 @@ public: PassRefPtr<SVGFilterBuilder> buildPrimitives(SVGFilter*); - SVGUnitTypes::SVGUnitType filterUnits() const { return static_cast<SVGFilterElement*>(node())->filterUnits(); } - SVGUnitTypes::SVGUnitType primitiveUnits() const { return static_cast<SVGFilterElement*>(node())->primitiveUnits(); } + SVGUnitTypes::SVGUnitType filterUnits() const { return toSVGFilterElement(node())->filterUnits(); } + SVGUnitTypes::SVGUnitType primitiveUnits() const { return toSVGFilterElement(node())->primitiveUnits(); } void primitiveAttributeChanged(RenderObject*, const QualifiedName&); virtual RenderSVGResourceType resourceType() const { return s_resourceType; } static RenderSVGResourceType s_resourceType; + FloatRect drawingRegion(RenderObject*) const; private: bool fitsInMaximumImageSize(const FloatSize&, FloatSize&); HashMap<RenderObject*, FilterData*> m_filter; }; +inline RenderSVGResourceFilter* toRenderSVGFilter(RenderObject* object) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGResourceFilter()); + return static_cast<RenderSVGResourceFilter*>(object); +} + } #endif diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp index f3da929ef..b5177fad9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp @@ -53,12 +53,12 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons const SVGRenderStyle* newStyle = this->style()->svgStyle(); if (node()->hasTagName(SVGNames::feFloodTag)) { if (newStyle->floodColor() != oldStyle->svgStyle()->floodColor()) - static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr); + toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr); if (newStyle->floodOpacity() != oldStyle->svgStyle()->floodOpacity()) - static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr); + toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr); } else if (node()->hasTagName(SVGNames::feDiffuseLightingTag) || node()->hasTagName(SVGNames::feSpecularLightingTag)) { if (newStyle->lightingColor() != oldStyle->svgStyle()->lightingColor()) - static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr); + toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr); } } diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp index 30ce1b8cb..25a61239f 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp @@ -31,7 +31,6 @@ #include "RenderSVGText.h" #include "SVGRenderSupport.h" #include "SVGRenderingContext.h" -#include <wtf/UnusedParam.h> namespace WebCore { @@ -68,7 +67,7 @@ static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con ASSERT(textRootBlock); AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform); FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates(); OwnPtr<ImageBuffer> maskImage; @@ -95,7 +94,7 @@ static inline AffineTransform clipToTextMask(GraphicsContext* context, ASSERT(textRootBlock); AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(textRootBlock, absoluteTransform); targetRect = textRootBlock->repaintRectInLocalCoordinates(); SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false); @@ -122,12 +121,12 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash. - SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node()); + SVGGradientElement* gradientElement = toSVGGradientElement(node()); if (!gradientElement) return false; if (m_shouldCollectGradientAttributes) { - gradientElement->updateAnimatedSVGAttribute(anyQName()); + gradientElement->synchronizeAnimatedSVGAttribute(anyQName()); if (!collectGradientAttributes(gradientElement)) return false; diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp index 7aaef0e9e..bcf517aef 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp @@ -28,10 +28,11 @@ #include "RenderSVGContainer.h" #include "RenderSVGRoot.h" #include "SVGElement.h" +#include "SVGGraphicsElement.h" #include "SVGMarkerElement.h" #include "SVGRenderSupport.h" #include "SVGStyledElement.h" -#include "SVGStyledTransformableElement.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -96,7 +97,7 @@ const AffineTransform& RenderSVGResourceMarker::localToParentTransform() const FloatPoint RenderSVGResourceMarker::referencePoint() const { - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + SVGMarkerElement* marker = toSVGMarkerElement(node()); ASSERT(marker); SVGLengthContext lengthContext(marker); @@ -105,7 +106,7 @@ FloatPoint RenderSVGResourceMarker::referencePoint() const float RenderSVGResourceMarker::angle() const { - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + SVGMarkerElement* marker = toSVGMarkerElement(node()); ASSERT(marker); float angle = -1; @@ -117,7 +118,7 @@ float RenderSVGResourceMarker::angle() const AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& origin, float autoAngle, float strokeWidth) const { - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + SVGMarkerElement* marker = toSVGMarkerElement(node()); ASSERT(marker); float markerAngle = angle(); @@ -132,6 +133,12 @@ AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform& transform) { + // An empty viewBox disables rendering. + SVGMarkerElement* marker = toSVGMarkerElement(toSVGElement(node())); + ASSERT(marker); + if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBoxIsValid() && marker->viewBox().isEmpty()) + return; + PaintInfo info(paintInfo); GraphicsContextStateSaver stateSaver(*info.context); info.applyTransform(transform); @@ -153,7 +160,7 @@ AffineTransform RenderSVGResourceMarker::markerContentTransformation(const Affin AffineTransform RenderSVGResourceMarker::viewportTransform() const { - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + SVGMarkerElement* marker = toSVGMarkerElement(node()); ASSERT(marker); return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); @@ -164,7 +171,7 @@ void RenderSVGResourceMarker::calcViewport() if (!selfNeedsLayout()) return; - SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node()); + SVGMarkerElement* marker = toSVGMarkerElement(node()); ASSERT(marker); SVGLengthContext lengthContext(marker); diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h index 26fbc6f93..1838450cf 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMarker.h @@ -60,7 +60,7 @@ public: FloatPoint referencePoint() const; float angle() const; - SVGMarkerUnitsType markerUnits() const { return static_cast<SVGMarkerElement*>(node())->markerUnits(); } + SVGMarkerUnitsType markerUnits() const { return toSVGMarkerElement(node())->markerUnits(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } static RenderSVGResourceType s_resourceType; diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp index 1f501a88b..fa66dfa7b 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp @@ -36,8 +36,6 @@ #include "SVGRenderingContext.h" #include "SVGStyledElement.h" #include "SVGUnitTypes.h" - -#include <wtf/UnusedParam.h> #include <wtf/Vector.h> namespace WebCore { @@ -92,7 +90,7 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, MaskerData* maskerData = m_masker.get(object); AffineTransform absoluteTransform; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform); FloatRect repaintRect = object->repaintRectInLocalCoordinates(); @@ -137,7 +135,7 @@ bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, C // Draw the content into the ImageBuffer. for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) { RenderObject* renderer = node->renderer(); - if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer) + if (!node->isSVGElement() || !toSVGElement(node)->isSVGStyledElement() || !renderer) continue; if (renderer->needsLayout()) return false; @@ -166,7 +164,7 @@ void RenderSVGResourceMasker::calculateMaskContentRepaintRect() { for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { RenderObject* renderer = childNode->renderer(); - if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) + if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer) continue; RenderStyle* style = renderer->style(); if (!style || style->display() == NONE || style->visibility() != VISIBLE) diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp index 55dbb8319..4df4c22a9 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp @@ -66,7 +66,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign return 0; if (m_shouldCollectPatternAttributes) { - patternElement->updateAnimatedSVGAttribute(anyQName()); + patternElement->synchronizeAnimatedSVGAttribute(anyQName()); m_attributes = PatternAttributes(); patternElement->collectPatternAttributes(m_attributes); @@ -77,6 +77,10 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign if (!m_attributes.patternContentElement()) return 0; + // An empty viewBox disables rendering. + if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty()) + return 0; + // Compute all necessary transformations to build the tile image & the pattern. FloatRect tileBoundaries; AffineTransform tileImageTransform; @@ -84,7 +88,7 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsign return 0; AffineTransform absoluteTransformIgnoringRotation; - SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransformIgnoringRotation); + SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation); // Ignore 2D rotation, as it doesn't affect the size of the tile. SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation); @@ -269,7 +273,7 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA // Draw the content into the ImageBuffer. for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { - if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) + if (!node->isSVGElement() || !toSVGElement(node)->isSVGStyledElement() || !node->renderer()) continue; if (node->renderer()->needsLayout()) return nullptr; diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp index a81c3698d..ca5cad4c5 100644 --- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp @@ -29,10 +29,6 @@ #include "RenderStyle.h" #include "SVGRenderSupport.h" -#if USE(SKIA) -#include "PlatformContextSkia.h" -#endif - namespace WebCore { RenderSVGResourceType RenderSVGResourceSolidColor::s_resourceType = SolidColorResourceType; diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp index 048c4f604..c3d159734 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.cpp @@ -46,6 +46,7 @@ #include "SVGStyledElement.h" #include "SVGViewSpec.h" #include "TransformState.h" +#include <wtf/StackStats.h> #if ENABLE(FILTERS) #include "RenderSVGResourceFilter.h" @@ -77,7 +78,8 @@ void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, d // the same as the CSS width and height properties. Specifically, percentage values do not provide an intrinsic width or height, // and do not indicate a percentage of the containing block. Rather, once the viewport is established, they indicate the portion // of the viewport that is actually covered by image data. - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); + ASSERT(svg); Length intrinsicWidthAttribute = svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties); Length intrinsicHeightAttribute = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties); @@ -128,10 +130,10 @@ bool RenderSVGRoot::isEmbeddedThroughSVGImage() const return false; // Test whether we're embedded through an img. - if (!frame->page() || !frame->page()->chrome()) + if (!frame->page()) return false; - ChromeClient* chromeClient = frame->page()->chrome()->client(); + ChromeClient* chromeClient = frame->page()->chrome().client(); if (!chromeClient || !chromeClient->isSVGImageChromeClient()) return false; @@ -159,9 +161,9 @@ static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, floa return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1)); } -LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) const +LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. @@ -169,7 +171,7 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) cons return m_containerSize.width(); if (style()->logicalWidth().isSpecified() || style()->logicalMaxWidth().isSpecified()) - return RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth); + return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); if (svg->widthAttributeEstablishesViewport()) return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth(), view()); @@ -179,12 +181,12 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(bool includeMaxWidth) cons return document()->frame()->ownerRenderer()->availableLogicalWidth(); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. - return RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth); + return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); } LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. @@ -206,12 +208,12 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const } else RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this)); - return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(), view()); + return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), view()); } // SVG embedded through object/embed/iframe. if (isEmbeddedThroughFrameContainingSVGDocument()) - return document()->frame()->ownerRenderer()->availableLogicalHeight(); + return document()->frame()->ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalHeight(); @@ -235,7 +237,8 @@ void RenderSVGRoot::layout() updateLogicalHeight(); buildLocalToBorderBoxTransform(); - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); + ASSERT(svg); m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size()); SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this)); @@ -256,6 +259,8 @@ void RenderSVGRoot::layout() m_needsBoundariesOrTransformUpdate = false; } + updateLayerTransform(); + repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -267,10 +272,17 @@ void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paint if (pixelSnappedBorderBoxRect().isEmpty()) return; - // Don't paint, if the context explicitely disabled it. + // Don't paint, if the context explicitly disabled it. if (paintInfo.context->paintingDisabled()) return; + // An empty viewBox also disables rendering. + // (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute) + SVGSVGElement* svg = toSVGSVGElement(node()); + ASSERT(svg); + if (svg->hasEmptyViewBox()) + return; + Page* page = 0; if (Frame* frame = this->frame()) page = frame->page(); @@ -354,12 +366,13 @@ void RenderSVGRoot::removeChild(RenderObject* child) // relative to our borderBox origin. This method gives us exactly that. void RenderSVGRoot::buildLocalToBorderBoxTransform() { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); + ASSERT(svg); float scale = style()->effectiveZoom(); - FloatPoint translate = svg->currentTranslate(); + SVGPoint translate = svg->currentTranslate(); LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop()); m_localToBorderBoxTransform = svg->viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale); - if (borderAndPadding.isEmpty() && scale == 1 && translate == FloatPoint::zero()) + if (borderAndPadding.isEmpty() && scale == 1 && translate == SVGPoint::zero()) return; m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform; } @@ -463,15 +476,22 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re bool RenderSVGRoot::hasRelativeDimensions() const { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent(); } +bool RenderSVGRoot::hasRelativeIntrinsicLogicalWidth() const +{ + SVGSVGElement* svg = toSVGSVGElement(node()); + ASSERT(svg); + return svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent(); +} + bool RenderSVGRoot::hasRelativeLogicalHeight() const { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); ASSERT(svg); return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent(); @@ -484,7 +504,7 @@ void RenderSVGRoot::addResourceForClientInvalidation(RenderSVGResourceContainer* svgRoot = svgRoot->parent(); if (!svgRoot) return; - static_cast<RenderSVGRoot*>(svgRoot)->m_resourcesNeedingToInvalidateClients.add(resource); + toRenderSVGRoot(svgRoot)->m_resourcesNeedingToInvalidateClients.add(resource); } } diff --git a/Source/WebCore/rendering/svg/RenderSVGRoot.h b/Source/WebCore/rendering/svg/RenderSVGRoot.h index 38e89179e..e218e291e 100644 --- a/Source/WebCore/rendering/svg/RenderSVGRoot.h +++ b/Source/WebCore/rendering/svg/RenderSVGRoot.h @@ -52,13 +52,15 @@ public: bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; } virtual void setNeedsBoundariesUpdate() { m_needsBoundariesOrTransformUpdate = true; } + virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesOrTransformUpdate; } virtual void setNeedsTransformUpdate() { m_needsBoundariesOrTransformUpdate = true; } IntSize containerSize() const { return m_containerSize; } void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; } - virtual bool hasRelativeDimensions() const; - virtual bool hasRelativeLogicalHeight() const; + virtual bool hasRelativeDimensions() const OVERRIDE; + virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE; + virtual bool hasRelativeLogicalHeight() const OVERRIDE; // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates. const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; } @@ -77,7 +79,7 @@ private: virtual bool isSVGRoot() const { return true; } virtual const char* renderName() const { return "RenderSVGRoot"; } - virtual LayoutUnit computeReplacedLogicalWidth(bool includeMaxWidth = true) const; + virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred = ComputeActual) const OVERRIDE; virtual LayoutUnit computeReplacedLogicalHeight() const; virtual void layout(); virtual void paintReplaced(PaintInfo&, const LayoutPoint&); @@ -103,7 +105,7 @@ private: virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE; virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const OVERRIDE; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE; + virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; virtual bool canBeSelectionLeaf() const { return false; } @@ -129,13 +131,13 @@ private: inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object) { - ASSERT(!object || object->isSVGRoot()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGRoot()); return static_cast<RenderSVGRoot*>(object); } inline const RenderSVGRoot* toRenderSVGRoot(const RenderObject* object) { - ASSERT(!object || object->isSVGRoot()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGRoot()); return static_cast<const RenderSVGRoot*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.cpp b/Source/WebCore/rendering/svg/RenderSVGShape.cpp index 7e329b2b7..8070a392a 100644 --- a/Source/WebCore/rendering/svg/RenderSVGShape.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGShape.cpp @@ -39,23 +39,24 @@ #include "RenderSVGContainer.h" #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceSolidColor.h" +#include "SVGGraphicsElement.h" #include "SVGPathData.h" #include "SVGRenderingContext.h" #include "SVGResources.h" #include "SVGResourcesCache.h" -#include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" #include "SVGURIReference.h" #include "StrokeStyleApplier.h" #include <wtf/MathExtras.h> +#include <wtf/StackStats.h> namespace WebCore { -RenderSVGShape::RenderSVGShape(SVGStyledTransformableElement* node) +RenderSVGShape::RenderSVGShape(SVGGraphicsElement* node) : RenderSVGModelObject(node) , m_needsBoundariesUpdate(false) // Default is false, the cached rects are empty from the beginning. - , m_needsShapeUpdate(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. + , m_needsShapeUpdate(true) // Default is true, so we grab a Path object once from SVGGraphicsElement. + , m_needsTransformUpdate(true) // Default is true, so we grab a AffineTransform object once from SVGGraphicsElement. { } @@ -69,7 +70,7 @@ void RenderSVGShape::updateShapeFromElement() m_path = adoptPtr(new Path); ASSERT(RenderSVGShape::isEmpty()); - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + SVGGraphicsElement* element = toSVGGraphicsElement(node()); updatePathFromGraphicsElement(element, path()); processMarkerPositions(); @@ -146,7 +147,7 @@ void RenderSVGShape::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout()); - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + SVGGraphicsElement* element = toSVGGraphicsElement(node()); bool updateCachedBoundariesInParents = false; @@ -198,7 +199,7 @@ bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransfo AffineTransform RenderSVGShape::nonScalingStrokeTransform() const { - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + SVGGraphicsElement* element = toSVGGraphicsElement(node()); return element->getScreenCTM(SVGLocatable::DisallowStyleUpdate); } @@ -207,7 +208,7 @@ bool RenderSVGShape::shouldGenerateMarkerPositions() const if (!style()->svgStyle()->hasMarkers()) return false; - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + SVGGraphicsElement* element = toSVGGraphicsElement(node()); if (!element->supportsMarkers()) return false; @@ -258,7 +259,6 @@ void RenderSVGShape::fillAndStrokeShape(GraphicsContext* context) return; GraphicsContextStateSaver stateSaver(*context, false); - AffineTransform nonScalingTransform; if (hasNonScalingStroke()) { AffineTransform nonScalingTransform = nonScalingStrokeTransform(); @@ -298,13 +298,13 @@ void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&) } if (drawsOutline) - paintOutline(childPaintInfo.context, IntRect(boundingBox)); + paintOutline(childPaintInfo, IntRect(boundingBox)); } } // This method is called from inside paintOutline() since we call paintOutline() // while transformed to our coord system, return local coords -void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&) +void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*) { IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates()); if (!rect.isEmpty()) @@ -416,7 +416,7 @@ void RenderSVGShape::updateRepaintBoundingBox() float RenderSVGShape::strokeWidth() const { - SVGElement* svgElement = static_cast<SVGElement*>(node()); + SVGElement* svgElement = toSVGElement(node()); SVGLengthContext lengthContext(svgElement); return style()->svgStyle()->strokeWidth().value(lengthContext); } diff --git a/Source/WebCore/rendering/svg/RenderSVGShape.h b/Source/WebCore/rendering/svg/RenderSVGShape.h index 60a2daeb4..289369698 100644 --- a/Source/WebCore/rendering/svg/RenderSVGShape.h +++ b/Source/WebCore/rendering/svg/RenderSVGShape.h @@ -42,7 +42,7 @@ class GraphicsContextStateSaver; class RenderSVGContainer; class RenderSVGPath; class RenderSVGResource; -class SVGStyledTransformableElement; +class SVGGraphicsElement; class BoundingRectStrokeStyleApplier : public StrokeStyleApplier { public: @@ -66,16 +66,18 @@ private: class RenderSVGShape : public RenderSVGModelObject { public: - explicit RenderSVGShape(SVGStyledTransformableElement*); - RenderSVGShape(SVGStyledTransformableElement*, Path*, bool); + explicit RenderSVGShape(SVGGraphicsElement*); + RenderSVGShape(SVGGraphicsElement*, Path*, bool); virtual ~RenderSVGShape(); void setNeedsShapeUpdate() { m_needsShapeUpdate = true; } virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } + virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; } virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } virtual void fillShape(GraphicsContext*) const; virtual void strokeShape(GraphicsContext*) const; + bool hasPath() const { return m_path.get(); } Path& path() const { ASSERT(m_path); @@ -88,7 +90,6 @@ protected: virtual bool shapeDependentStrokeContains(const FloatPoint&); virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const; float strokeWidth() const; - bool hasPath() const { return m_path.get(); } bool hasSmoothStroke() const; bool hasNonScalingStroke() const { return style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; } @@ -113,7 +114,7 @@ private: virtual void layout(); virtual void paint(PaintInfo&, const LayoutPoint&); - virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&); + virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE; virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); @@ -148,13 +149,13 @@ private: inline RenderSVGShape* toRenderSVGShape(RenderObject* object) { - ASSERT(!object || object->isSVGShape()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGShape()); return static_cast<RenderSVGShape*>(object); } inline const RenderSVGShape* toRenderSVGShape(const RenderObject* object) { - ASSERT(!object || object->isSVGShape()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGShape()); return static_cast<const RenderSVGShape*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGTSpan.cpp b/Source/WebCore/rendering/svg/RenderSVGTSpan.cpp index 872d07642..0831b2409 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTSpan.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTSpan.cpp @@ -27,8 +27,8 @@ namespace WebCore { -RenderSVGTSpan::RenderSVGTSpan(Node* n) - : RenderSVGInline(n) +RenderSVGTSpan::RenderSVGTSpan(Element* element) + : RenderSVGInline(element) { } diff --git a/Source/WebCore/rendering/svg/RenderSVGTSpan.h b/Source/WebCore/rendering/svg/RenderSVGTSpan.h index d5e2ed768..bd9ce9abe 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTSpan.h +++ b/Source/WebCore/rendering/svg/RenderSVGTSpan.h @@ -28,7 +28,7 @@ namespace WebCore { class RenderSVGTSpan : public RenderSVGInline { public: - explicit RenderSVGTSpan(Node*); + explicit RenderSVGTSpan(Element*); virtual const char* renderName() const { return "RenderSVGTSpan"; } }; } diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp index fd49f9b46..a65a3e498 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp @@ -52,6 +52,7 @@ #include "SimpleFontData.h" #include "TransformState.h" #include "VisiblePosition.h" +#include <wtf/StackStats.h> namespace WebCore { @@ -111,9 +112,9 @@ void RenderSVGText::computeFloatRectForRepaint(const RenderLayerModelObject* rep SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const +void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const { - SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, mode & SnapOffsetForTransforms, wasFixed); + SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed); } const RenderObject* RenderSVGText::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const @@ -472,7 +473,7 @@ VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInConten if (!rootBox) return createVisiblePosition(0, DOWNSTREAM); - ASSERT(rootBox->isSVGRootInlineBox()); + ASSERT_WITH_SECURITY_IMPLICATION(rootBox->isSVGRootInlineBox()); ASSERT(!rootBox->nextRootBox()); ASSERT(childrenInline()); @@ -513,7 +514,7 @@ FloatRect RenderSVGText::strokeBoundingBox() const ASSERT(node()); ASSERT(node()->isSVGElement()); - SVGLengthContext lengthContext(static_cast<SVGElement*>(node())); + SVGLengthContext lengthContext(toSVGElement(node())); strokeBoundaries.inflate(svgStyle->strokeWidth().value(lengthContext)); return strokeBoundaries; } diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h index cae5ba721..4d4f4ae3d 100644 --- a/Source/WebCore/rendering/svg/RenderSVGText.h +++ b/Source/WebCore/rendering/svg/RenderSVGText.h @@ -75,7 +75,7 @@ private: virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE; virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE; - virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip | SnapOffsetForTransforms, bool* wasFixed = 0) const OVERRIDE; + virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE; virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE; virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject*) OVERRIDE; @@ -104,13 +104,13 @@ private: inline RenderSVGText* toRenderSVGText(RenderObject* object) { - ASSERT(!object || object->isSVGText()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGText()); return static_cast<RenderSVGText*>(object); } inline const RenderSVGText* toRenderSVGText(const RenderObject* object) { - ASSERT(!object || object->isSVGText()); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGText()); return static_cast<const RenderSVGText*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp index 15b48f590..e816f9e47 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.cpp @@ -34,8 +34,8 @@ namespace WebCore { -RenderSVGTextPath::RenderSVGTextPath(Node* n) - : RenderSVGInline(n) +RenderSVGTextPath::RenderSVGTextPath(Element* element) + : RenderSVGInline(element) { } @@ -46,7 +46,7 @@ Path RenderSVGTextPath::layoutPath() const if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag)) return Path(); - SVGPathElement* pathElement = static_cast<SVGPathElement*>(targetElement); + SVGPathElement* pathElement = toSVGPathElement(targetElement); Path pathData; updatePathFromGraphicsElement(pathElement, pathData); diff --git a/Source/WebCore/rendering/svg/RenderSVGTextPath.h b/Source/WebCore/rendering/svg/RenderSVGTextPath.h index 2758a0692..f1c872138 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTextPath.h +++ b/Source/WebCore/rendering/svg/RenderSVGTextPath.h @@ -28,7 +28,7 @@ namespace WebCore { class RenderSVGTextPath : public RenderSVGInline { public: - RenderSVGTextPath(Node*); + RenderSVGTextPath(Element*); Path layoutPath() const; float startOffset() const; @@ -45,7 +45,7 @@ private: inline RenderSVGTextPath* toRenderSVGTextPath(RenderObject* object) { - ASSERT(!object || !strcmp(object->renderName(), "RenderSVGTextPath")); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGTextPath()); return static_cast<RenderSVGTextPath*>(object); } diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp index ee4d74e24..06df24dc6 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.cpp @@ -24,14 +24,14 @@ #if ENABLE(SVG) #include "RenderSVGTransformableContainer.h" +#include "SVGGraphicsElement.h" #include "SVGNames.h" #include "SVGRenderSupport.h" -#include "SVGStyledTransformableElement.h" #include "SVGUseElement.h" namespace WebCore { -RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransformableElement* node) +RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGGraphicsElement* node) : RenderSVGContainer(node) , m_needsTransformUpdate(true) , m_didTransformToRootUpdate(false) @@ -40,18 +40,18 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransf bool RenderSVGTransformableContainer::calculateLocalTransform() { - SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); + SVGGraphicsElement* element = toSVGGraphicsElement(node()); // If we're either the renderer for a <use> element, or for any <g> element inside the shadow // tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers // need to respect the translations induced by their corresponding use elements x/y attributes. SVGUseElement* useElement = 0; if (element->hasTagName(SVGNames::useTag)) - useElement = static_cast<SVGUseElement*>(element); + useElement = toSVGUseElement(element); else if (element->isInShadowTree() && element->hasTagName(SVGNames::gTag)) { SVGElement* correspondingElement = element->correspondingElement(); if (correspondingElement && correspondingElement->hasTagName(SVGNames::useTag)) - useElement = static_cast<SVGUseElement*>(correspondingElement); + useElement = toSVGUseElement(correspondingElement); } if (useElement) { diff --git a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h index c10a08dc2..b59327efd 100644 --- a/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGTransformableContainer.h @@ -26,10 +26,10 @@ namespace WebCore { -class SVGStyledTransformableElement; +class SVGGraphicsElement; class RenderSVGTransformableContainer : public RenderSVGContainer { public: - explicit RenderSVGTransformableContainer(SVGStyledTransformableElement*); + explicit RenderSVGTransformableContainer(SVGGraphicsElement*); virtual bool isSVGTransformableContainer() const { return true; } virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp index 27a319f28..834452d20 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.cpp @@ -47,7 +47,7 @@ void RenderSVGViewportContainer::determineIfLayoutSizeChanged() if (!node()->hasTagName(SVGNames::svgTag)) return; - m_isLayoutSizeChanged = static_cast<SVGSVGElement*>(node())->hasRelativeLengths() && selfNeedsLayout(); + m_isLayoutSizeChanged = toSVGSVGElement(node())->hasRelativeLengths() && selfNeedsLayout(); } void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo) @@ -58,10 +58,10 @@ void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo) void RenderSVGViewportContainer::calcViewport() { - SVGElement* element = static_cast<SVGElement*>(node()); + SVGElement* element = toSVGElement(node()); if (!element->hasTagName(SVGNames::svgTag)) return; - SVGSVGElement* svg = static_cast<SVGSVGElement*>(element); + SVGSVGElement* svg = toSVGSVGElement(element); FloatRect oldViewport = m_viewport; SVGLengthContext lengthContext(element); @@ -133,7 +133,7 @@ bool RenderSVGViewportContainer::calculateLocalTransform() AffineTransform RenderSVGViewportContainer::viewportTransform() const { if (node()->hasTagName(SVGNames::svgTag)) { - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + SVGSVGElement* svg = toSVGSVGElement(node()); return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height()); } @@ -149,6 +149,17 @@ bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& poi return m_viewport.contains(pointInParent); } +void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) +{ + // An empty viewBox disables rendering. + if (node()->hasTagName(SVGNames::svgTag)) { + if (toSVGSVGElement(node())->hasEmptyViewBox()) + return; + } + + RenderSVGContainer::paint(paintInfo, paintOffset); +} + } #endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h index eb7041a30..427e423da 100644 --- a/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h +++ b/Source/WebCore/rendering/svg/RenderSVGViewportContainer.h @@ -41,6 +41,8 @@ public: virtual void determineIfLayoutSizeChanged(); virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } + virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE; + private: virtual bool isSVGViewportContainer() const { return true; } virtual const char* renderName() const { return "RenderSVGViewportContainer"; } @@ -63,13 +65,13 @@ private: inline RenderSVGViewportContainer* toRenderSVGViewportContainer(RenderObject* object) { - ASSERT(!object || !strcmp(object->renderName(), "RenderSVGViewportContainer")); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGViewportContainer()); return static_cast<RenderSVGViewportContainer*>(object); } inline const RenderSVGViewportContainer* toRenderSVGViewportContainer(const RenderObject* object) { - ASSERT(!object || !strcmp(object->renderName(), "RenderSVGViewportContainer")); + ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGViewportContainer()); return static_cast<const RenderSVGViewportContainer*>(object); } diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp index 21a909224..3e97b6722 100644 --- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp +++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp @@ -43,9 +43,9 @@ void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo) PaintInfo childPaintInfo(paintInfo); for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (child->isSVGInlineTextBox()) - static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo); + toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo); else if (child->isSVGInlineFlowBox()) - static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo); + toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo); } } @@ -61,7 +61,7 @@ void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni if (renderingContext.isRenderingPrepared()) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (child->isSVGInlineTextBox()) - computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer())); + computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer())); child->paint(paintInfo, LayoutPoint(), 0, 0); } @@ -107,7 +107,7 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText if (!box->isSVGInlineTextBox()) continue; - SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); + SVGInlineTextBox* textBox = toSVGInlineTextBox(box); int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0); int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len()); diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h index bc44c7e55..18b8a527f 100644 --- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h +++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h @@ -28,7 +28,7 @@ namespace WebCore { class RenderSVGInlineText; -class SVGInlineFlowBox : public InlineFlowBox { +class SVGInlineFlowBox FINAL : public InlineFlowBox { public: SVGInlineFlowBox(RenderObject* obj) : InlineFlowBox(obj) @@ -51,6 +51,12 @@ private: float m_logicalHeight; }; +inline SVGInlineFlowBox* toSVGInlineFlowBox(InlineBox* box) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!box || box->isSVGInlineFlowBox()); + return static_cast<SVGInlineFlowBox*>(box); +} + } // namespace WebCore #endif // ENABLE(SVG) diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp index 7864d4ee8..08a9e14c7 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -318,10 +318,10 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations. int decorations = style->textDecorationsInEffect(); - if (decorations & UNDERLINE) - paintDecoration(paintInfo.context, UNDERLINE, fragment); - if (decorations & OVERLINE) - paintDecoration(paintInfo.context, OVERLINE, fragment); + if (decorations & TextDecorationUnderline) + paintDecoration(paintInfo.context, TextDecorationUnderline, fragment); + if (decorations & TextDecorationOverline) + paintDecoration(paintInfo.context, TextDecorationOverline, fragment); // Fill text if (hasFill) { @@ -336,8 +336,8 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni } // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text. - if (decorations & LINE_THROUGH) - paintDecoration(paintInfo.context, LINE_THROUGH, fragment); + if (decorations & TextDecorationLineThrough) + paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment); m_paintingResourceMode = ApplyToDefaultMode; } @@ -478,22 +478,22 @@ bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGText return true; } -static inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness) +static inline float positionOffsetForDecoration(TextDecoration decoration, const FontMetrics& fontMetrics, float thickness) { // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified. // Compatible with Batik/Opera. - if (decoration == UNDERLINE) + if (decoration == TextDecorationUnderline) return fontMetrics.floatAscent() + thickness * 1.5f; - if (decoration == OVERLINE) + if (decoration == TextDecorationOverline) return thickness; - if (decoration == LINE_THROUGH) + if (decoration == TextDecorationLineThrough) return fontMetrics.floatAscent() * 5 / 8.0f; ASSERT_NOT_REACHED(); return 0.0f; } -static inline float thicknessForDecoration(ETextDecoration, const Font& font) +static inline float thicknessForDecoration(TextDecoration, const Font& font) { // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified. // Compatible with Batik/Opera @@ -507,7 +507,7 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB while (parentBox) { renderer = parentBox->renderer(); - if (renderer->style() && renderer->style()->textDecoration() != TDNONE) + if (renderer->style() && renderer->style()->textDecoration() != TextDecorationNone) break; parentBox = parentBox->parent(); @@ -517,9 +517,9 @@ static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowB return renderer; } -void SVGInlineTextBox::paintDecoration(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment) +void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment) { - if (textRenderer()->style()->textDecorationsInEffect() == TDNONE) + if (textRenderer()->style()->textDecorationsInEffect() == TextDecorationNone) return; // Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours. @@ -547,7 +547,7 @@ void SVGInlineTextBox::paintDecoration(GraphicsContext* context, ETextDecoration } } -void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer) +void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer) { ASSERT(!m_paintingResource); ASSERT(m_paintingResourceMode != ApplyToDefaultMode); diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.h b/Source/WebCore/rendering/svg/SVGInlineTextBox.h index ef399c724..6fea28db3 100644 --- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h +++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h @@ -31,7 +31,7 @@ namespace WebCore { class RenderSVGResource; class SVGRootInlineBox; -class SVGInlineTextBox : public InlineTextBox { +class SVGInlineTextBox FINAL : public InlineTextBox { public: SVGInlineTextBox(RenderObject*); @@ -57,7 +57,7 @@ public: Vector<SVGTextFragment>& textFragments() { return m_textFragments; } const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; } - void dirtyLineBoxes() OVERRIDE; + virtual void dirtyLineBoxes() OVERRIDE; bool startsNewTextChunk() const { return m_startsNewTextChunk; } void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; } @@ -74,8 +74,8 @@ private: bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&, RenderStyle*); void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&); - void paintDecoration(GraphicsContext*, ETextDecoration, const SVGTextFragment&); - void paintDecorationWithStyle(GraphicsContext*, ETextDecoration, const SVGTextFragment&, RenderObject* decorationRenderer); + void paintDecoration(GraphicsContext*, TextDecoration, const SVGTextFragment&); + void paintDecorationWithStyle(GraphicsContext*, TextDecoration, const SVGTextFragment&, RenderObject* decorationRenderer); void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition); void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly); @@ -89,6 +89,12 @@ private: Vector<SVGTextFragment> m_textFragments; }; +inline SVGInlineTextBox* toSVGInlineTextBox(InlineBox* box) +{ + ASSERT_WITH_SECURITY_IMPLICATION(!box || box->isSVGInlineTextBox()); + return static_cast<SVGInlineTextBox*>(box); +} + } // namespace WebCore #endif diff --git a/Source/WebCore/rendering/svg/SVGMarkerData.h b/Source/WebCore/rendering/svg/SVGMarkerData.h index 7e2ce0edc..6c70f4297 100644 --- a/Source/WebCore/rendering/svg/SVGMarkerData.h +++ b/Source/WebCore/rendering/svg/SVGMarkerData.h @@ -82,19 +82,23 @@ public: private: float currentAngle(SVGMarkerType type) const { - FloatSize inslopeChange = m_inslopePoints[1] - m_inslopePoints[0]; - FloatSize outslopeChange = m_outslopePoints[1] - m_outslopePoints[0]; + // For details of this calculation, see: http://www.w3.org/TR/SVG/single-page.html#painting-MarkerElement + FloatPoint inSlope(m_inslopePoints[1] - m_inslopePoints[0]); + FloatPoint outSlope(m_outslopePoints[1] - m_outslopePoints[0]); - double inslope = rad2deg(atan2(inslopeChange.height(), inslopeChange.width())); - double outslope = rad2deg(atan2(outslopeChange.height(), outslopeChange.width())); + double inAngle = rad2deg(inSlope.slopeAngleRadians()); + double outAngle = rad2deg(outSlope.slopeAngleRadians()); switch (type) { case StartMarker: - return narrowPrecisionToFloat(outslope); + return narrowPrecisionToFloat(outAngle); case MidMarker: - return narrowPrecisionToFloat((inslope + outslope) / 2); + // WK193015: Prevent bugs due to angles being non-continuous. + if (fabs(inAngle - outAngle) > 180) + inAngle += 360; + return narrowPrecisionToFloat((inAngle + outAngle) / 2); case EndMarker: - return narrowPrecisionToFloat(inslope); + return narrowPrecisionToFloat(inAngle); } ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/rendering/svg/SVGPathData.cpp b/Source/WebCore/rendering/svg/SVGPathData.cpp index 98c80b22f..234122510 100644 --- a/Source/WebCore/rendering/svg/SVGPathData.cpp +++ b/Source/WebCore/rendering/svg/SVGPathData.cpp @@ -73,8 +73,7 @@ static void updatePathFromLineElement(SVGElement* element, Path& path) static void updatePathFromPathElement(SVGElement* element, Path& path) { - ASSERT(element->hasTagName(SVGNames::pathTag)); - buildPathFromByteStream(static_cast<SVGPathElement*>(element)->pathByteStream(), path); + buildPathFromByteStream(toSVGPathElement(element)->pathByteStream(), path); } static void updatePathFromPolygonElement(SVGElement* element, Path& path) diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp index c75015d57..4fba77407 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.cpp @@ -42,7 +42,6 @@ #include "SVGResourcesCache.h" #include "SVGStyledElement.h" #include "TransformState.h" -#include <wtf/UnusedParam.h> namespace WebCore { @@ -50,6 +49,7 @@ FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVG { // FIXME: Add support for RenderSVGBlock. + // FIXME: This should use a safer cast such as toRenderSVGModelObject(). if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer()) return static_cast<const RenderSVGModelObject*>(object)->repaintRectInLocalCoordinatesExcludingSVGShadow(); @@ -84,7 +84,7 @@ void SVGRenderSupport::computeFloatRectForRepaint(const RenderObject* object, co object->parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed); } -void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool snapOffsetForTransforms, bool* wasFixed) +void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) { transformState.applyTransform(object->localToParentTransform()); @@ -97,8 +97,6 @@ void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const Ren transformState.applyTransform(toRenderSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; - if (snapOffsetForTransforms) - mode |= SnapOffsetForTransforms; parent->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); } @@ -231,12 +229,21 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) { bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start); bool transformChanged = transformToRootChanged(start); + bool hasSVGShadow = rendererHasSVGShadow(start); + bool needsBoundariesUpdate = start->needsBoundariesUpdate(); HashSet<RenderObject*> notlayoutedObjects; for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { bool needsLayout = selfNeedsLayout; bool childEverHadLayout = child->everHadLayout(); + if (needsBoundariesUpdate && hasSVGShadow) { + // If we have a shadow, our shadow is baked into our children's cached boundaries, + // so they need to update. + child->setNeedsBoundariesUpdate(); + needsLayout = true; + } + if (transformChanged) { // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true). if (child->isSVGText()) @@ -246,8 +253,8 @@ void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout) if (layoutSizeChanged) { // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths - if (SVGElement* element = child->node()->isSVGElement() ? static_cast<SVGElement*>(child->node()) : 0) { - if (element->isStyled() && static_cast<SVGStyledElement*>(element)->hasRelativeLengths()) { + if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) { + if (element->isSVGStyledElement() && toSVGStyledElement(element)->hasRelativeLengths()) { // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object if (child->isSVGShape()) toRenderSVGShape(child)->setNeedsShapeUpdate(); @@ -307,11 +314,12 @@ bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject* object) { // FIXME: Add support for RenderSVGBlock. + // FIXME: This should use a safer cast such as toRenderSVGModelObject(). if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer()) return static_cast<const RenderSVGModelObject*>(object)->hasSVGShadow(); if (object->isSVGRoot()) - return static_cast<const RenderSVGRoot*>(object)->hasSVGShadow(); + return toRenderSVGRoot(object)->hasSVGShadow(); return false; } @@ -320,6 +328,7 @@ void SVGRenderSupport::setRendererHasSVGShadow(RenderObject* object, bool hasSha { // FIXME: Add support for RenderSVGBlock. + // FIXME: This should use a safer cast such as toRenderSVGModelObject(). if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer()) return static_cast<RenderSVGModelObject*>(object)->setHasSVGShadow(hasShadow); @@ -424,7 +433,7 @@ void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const const SVGRenderStyle* svgStyle = style->svgStyle(); ASSERT(svgStyle); - SVGLengthContext lengthContext(static_cast<SVGElement*>(object->node())); + SVGLengthContext lengthContext(toSVGElement(object->node())); context->setStrokeThickness(svgStyle->strokeWidth().value(lengthContext)); context->setLineCap(svgStyle->capStyle()); context->setLineJoin(svgStyle->joinStyle()); diff --git a/Source/WebCore/rendering/svg/SVGRenderSupport.h b/Source/WebCore/rendering/svg/SVGRenderSupport.h index f7375e43b..0b1871617 100644 --- a/Source/WebCore/rendering/svg/SVGRenderSupport.h +++ b/Source/WebCore/rendering/svg/SVGRenderSupport.h @@ -68,7 +68,7 @@ public: static FloatRect repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(const RenderObject*); static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer); static void computeFloatRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed); - static void mapLocalToContainer(const RenderObject*, const RenderLayerModelObject* repaintContainer, TransformState&, bool snapOffsetForTransforms = true, bool* wasFixed = 0); + static void mapLocalToContainer(const RenderObject*, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed = 0); static const RenderObject* pushMappingToContainer(const RenderObject*, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&); static bool checkForSVGRepaintDuringLayout(RenderObject*); diff --git a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp index 12352ae72..532db27c6 100644 --- a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp @@ -262,7 +262,7 @@ static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource else if (resource->resourceType() == RadialGradientResourceType) ts << "[type=RADIAL-GRADIENT]"; - ts << " [id=\"" << static_cast<SVGElement*>(node)->getIdAttribute() << "\"]"; + ts << " [id=\"" << toSVGElement(node)->getIdAttribute() << "\"]"; } static void writeStyle(TextStream& ts, const RenderObject& object) @@ -285,7 +285,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object) ts << " [stroke={" << s; writeSVGPaintingResource(ts, strokePaintingResource); - SVGLengthContext lengthContext(static_cast<SVGElement*>(shape.node())); + SVGLengthContext lengthContext(toSVGElement(shape.node())); double dashOffset = svgStyle->strokeDashOffset().value(lengthContext); double strokeWidth = svgStyle->strokeWidth().value(lengthContext); const Vector<SVGLength>& dashes = svgStyle->strokeDashArray(); @@ -336,7 +336,7 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape) writePositionAndStyle(ts, shape); ASSERT(shape.node()->isSVGElement()); - SVGElement* svgElement = static_cast<SVGElement*>(shape.node()); + SVGElement* svgElement = toSVGElement(shape.node()); SVGLengthContext lengthContext(svgElement); if (svgElement->hasTagName(SVGNames::rectTag)) { @@ -366,7 +366,7 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape) SVGPolyElement* element = static_cast<SVGPolyElement*>(svgElement); writeNameAndQuotedValue(ts, "points", element->pointList().valueAsString()); } else if (svgElement->hasTagName(SVGNames::pathTag)) { - SVGPathElement* element = static_cast<SVGPathElement*>(svgElement); + SVGPathElement* element = toSVGPathElement(svgElement); String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing); @@ -459,7 +459,7 @@ static inline void writeSVGInlineTextBoxes(TextStream& ts, const RenderText& tex if (!box->isSVGInlineTextBox()) continue; - writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent); + writeSVGInlineTextBox(ts, toSVGInlineTextBox(box), indent); } } @@ -493,7 +493,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i { writeStandardPrefix(ts, object, indent); - Element* element = static_cast<Element*>(object.node()); + Element* element = toElement(object.node()); const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp index 041aed418..a65d39fe6 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.cpp @@ -30,6 +30,8 @@ #include "BasicShapes.h" #include "Frame.h" #include "FrameView.h" +#include "RenderLayer.h" +#include "RenderSVGImage.h" #include "RenderSVGResource.h" #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" @@ -59,8 +61,9 @@ SVGRenderingContext::~SVGRenderingContext() #if ENABLE(FILTERS) if (m_renderingFlags & EndFilterLayer) { ASSERT(m_filter); - m_filter->postApplyResource(static_cast<RenderSVGShape*>(m_object), m_paintInfo->context, ApplyToDefaultMode, 0, 0); + m_filter->postApplyResource(m_object, m_paintInfo->context, ApplyToDefaultMode, 0, 0); m_paintInfo->context = m_savedContext; + m_paintInfo->rect = m_savedPaintRect; } #endif @@ -117,7 +120,7 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI if (shadow) { m_paintInfo->context->clip(repaintRect); - m_paintInfo->context->setShadow(IntSize(roundToInt(shadow->x()), roundToInt(shadow->y())), shadow->blur(), shadow->color(), style->colorSpace()); + m_paintInfo->context->setShadow(IntSize(roundToInt(shadow->x()), roundToInt(shadow->y())), shadow->radius(), shadow->color(), style->colorSpace()); m_paintInfo->context->beginTransparencyLayer(1); m_renderingFlags |= EndShadowLayer; } @@ -157,11 +160,18 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI m_filter = resources->filter(); if (m_filter) { m_savedContext = m_paintInfo->context; + m_savedPaintRect = m_paintInfo->rect; // Return with false here may mean that we don't need to draw the content // (because it was either drawn before or empty) but we still need to apply the filter. m_renderingFlags |= EndFilterLayer; if (!m_filter->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode)) return; + + // Since we're caching the resulting bitmap and do not invalidate it on repaint rect + // changes, we need to paint the whole filter region. Otherwise, elements not visible + // at the time of the initial paint (due to scrolling, window size, etc.) will never + // be drawn. + m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_object)); } } #endif @@ -180,21 +190,34 @@ float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObje ASSERT(renderer); AffineTransform ctm; - calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm); + calculateTransformationToOutermostCoordinateSystem(renderer, ctm); return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); } -void SVGRenderingContext::calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform) +void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform) { - const RenderObject* current = renderer; - ASSERT(current); - + ASSERT(renderer); absoluteTransform = currentContentTransformation(); - while (current) { - absoluteTransform = current->localToParentTransform() * absoluteTransform; - if (current->isSVGRoot()) + + // Walk up the render tree, accumulating SVG transforms. + while (renderer) { + absoluteTransform = renderer->localToParentTransform() * absoluteTransform; + if (renderer->isSVGRoot()) break; - current = current->parent(); + renderer = renderer->parent(); + } + + // Continue walking up the layer tree, accumulating CSS transforms. + RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0; + while (layer) { + if (TransformationMatrix* layerTransform = layer->transform()) + absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform; + + // We can stop at compositing layers, to match the backing resolution. + if (layer->isComposited()) + break; + + layer = layer->parent(); } } @@ -251,7 +274,7 @@ void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderO ASSERT(image); ASSERT(image->context()); - PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0, 0); + PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal); AffineTransform& contentTransformation = currentContentTransformation(); AffineTransform savedContentTransformation = contentTransformation; @@ -302,6 +325,37 @@ void SVGRenderingContext::clear2DRotation(AffineTransform& transform) transform.recompose(decomposition); } +bool SVGRenderingContext::bufferForeground(OwnPtr<ImageBuffer>& imageBuffer) +{ + ASSERT(m_paintInfo); + ASSERT(m_object->isSVGImage()); + FloatRect boundingBox = m_object->objectBoundingBox(); + + // Invalidate an existing buffer if the scale is not correct. + if (imageBuffer) { + AffineTransform transform = m_paintInfo->context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale); + IntSize expandedBoundingBox = expandedIntSize(boundingBox.size()); + IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale()))); + if (bufferSize != imageBuffer->internalSize()) + imageBuffer.clear(); + } + + // Create a new buffer and paint the foreground into it. + if (!imageBuffer) { + if ((imageBuffer = m_paintInfo->context->createCompatibleBuffer(expandedIntSize(boundingBox.size()), true))) { + GraphicsContext* bufferedRenderingContext = imageBuffer->context(); + bufferedRenderingContext->translate(-boundingBox.x(), -boundingBox.y()); + PaintInfo bufferedInfo(*m_paintInfo); + bufferedInfo.context = bufferedRenderingContext; + toRenderSVGImage(m_object)->paintForeground(bufferedInfo); + } else + return false; + } + + m_paintInfo->context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, boundingBox); + return true; +} + } #endif diff --git a/Source/WebCore/rendering/svg/SVGRenderingContext.h b/Source/WebCore/rendering/svg/SVGRenderingContext.h index c88168968..1fc3f1a2e 100644 --- a/Source/WebCore/rendering/svg/SVGRenderingContext.h +++ b/Source/WebCore/rendering/svg/SVGRenderingContext.h @@ -83,7 +83,7 @@ public: static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>&, bool safeToClear); static float calculateScreenFontSizeScalingFactor(const RenderObject*); - static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform); + static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform); static IntSize clampedAbsoluteSize(const IntSize&); static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect); static void clear2DRotation(AffineTransform&); @@ -93,6 +93,9 @@ public: return enclosingIntRect(absoluteTransform.mapRect(targetRect)); } + // Support for the buffered-rendering hint. + bool bufferForeground(OwnPtr<ImageBuffer>&); + private: // To properly revert partially successful initializtions in the destructor, we record all successful steps. enum RenderingFlags { @@ -111,6 +114,7 @@ private: RenderObject* m_object; PaintInfo* m_paintInfo; GraphicsContext* m_savedContext; + IntRect m_savedPaintRect; #if ENABLE(FILTERS) RenderSVGResourceFilter* m_filter; #endif diff --git a/Source/WebCore/rendering/svg/SVGResources.cpp b/Source/WebCore/rendering/svg/SVGResources.cpp index d9097409d..015190d27 100644 --- a/Source/WebCore/rendering/svg/SVGResources.cpp +++ b/Source/WebCore/rendering/svg/SVGResources.cpp @@ -146,10 +146,10 @@ static inline String targetReferenceFromResource(SVGElement* element) if (element->hasTagName(SVGNames::patternTag)) target = static_cast<SVGPatternElement*>(element)->href(); else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag)) - target = static_cast<SVGGradientElement*>(element)->href(); + target = toSVGGradientElement(element)->href(); #if ENABLE(FILTERS) else if (element->hasTagName(SVGNames::filterTag)) - target = static_cast<SVGFilterElement*>(element)->href(); + target = toSVGFilterElement(element)->href(); #endif else ASSERT_NOT_REACHED(); @@ -179,8 +179,8 @@ static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element) { ASSERT(element); - ASSERT(element->isStyled()); - extensions->addPendingResource(id, static_cast<SVGStyledElement*>(element)); + ASSERT_WITH_SECURITY_IMPLICATION(element->isSVGStyledElement()); + extensions->addPendingResource(id, toSVGStyledElement(element)); } bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style) @@ -190,9 +190,9 @@ bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRen Node* node = object->node(); ASSERT(node); - ASSERT(node->isSVGElement()); + ASSERT_WITH_SECURITY_IMPLICATION(node->isSVGElement()); - SVGElement* element = static_cast<SVGElement*>(node); + SVGElement* element = toSVGElement(node); if (!element) return false; diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp index 8b48cf53e..3f6e7dee1 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp +++ b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp @@ -36,7 +36,6 @@ SVGResourcesCache::SVGResourcesCache() SVGResourcesCache::~SVGResourcesCache() { - deleteAllValues(m_cache); } void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style) @@ -49,14 +48,12 @@ void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const ASSERT(svgStyle); // Build a list of all resources associated with the passed RenderObject - SVGResources* resources = new SVGResources; - if (!resources->buildCachedResources(object, svgStyle)) { - delete resources; + OwnPtr<SVGResources> newResources = adoptPtr(new SVGResources); + if (!newResources->buildCachedResources(object, svgStyle)) return; - } // Put object in cache. - m_cache.set(object, resources); + SVGResources* resources = m_cache.set(object, newResources.release()).iterator->value.get(); // Run cycle-detection _afterwards_, so self-references can be caught as well. SVGResourcesCycleSolver solver(object, resources); @@ -76,7 +73,7 @@ void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object) if (!m_cache.contains(object)) return; - SVGResources* resources = m_cache.get(object); + OwnPtr<SVGResources> resources = m_cache.take(object); // Walk resources and register the render object at each resources. HashSet<RenderSVGResourceContainer*> resourceSet; @@ -85,8 +82,6 @@ void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object) HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end(); for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) (*it)->removeClient(object); - - delete m_cache.take(object); } static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObject* renderer) @@ -106,11 +101,7 @@ static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObje SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(const RenderObject* renderer) { ASSERT(renderer); - SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); - if (!cache->m_cache.contains(renderer)) - return 0; - - return cache->m_cache.get(renderer); + return resourcesCacheFromRenderObject(renderer)->m_cache.get(renderer); } void SVGResourcesCache::clientLayoutChanged(RenderObject* object) @@ -125,6 +116,12 @@ void SVGResourcesCache::clientLayoutChanged(RenderObject* object) resources->removeClientFromCache(object); } +static inline bool rendererCanHaveResources(RenderObject* renderer) +{ + ASSERT(renderer); + return renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGInlineText(); +} + void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle) { ASSERT(renderer); @@ -132,24 +129,22 @@ void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifferen return; // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint. - if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint) + if (renderer->isSVGResourceFilterPrimitive() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintIfText)) return; // Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a renderer. // FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed // to be able to selectively rebuild individual resources, instead of all of them. - SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); - cache->removeResourcesFromRenderObject(renderer); - cache->addResourcesFromRenderObject(renderer, newStyle); + if (rendererCanHaveResources(renderer)) { + SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); + cache->removeResourcesFromRenderObject(renderer); + cache->addResourcesFromRenderObject(renderer, newStyle); + } RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false); -} -static inline bool rendererCanHaveResources(RenderObject* renderer) -{ - ASSERT(renderer); - ASSERT(renderer->parent()); - return renderer->node() && !renderer->isSVGInlineText(); + if (renderer->node() && !renderer->node()->isSVGElement()) + renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); } void SVGResourcesCache::clientWasAddedToTree(RenderObject* renderer, const RenderStyle* newStyle) @@ -196,13 +191,13 @@ void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource) // The resource itself may have clients, that need to be notified. cache->removeResourcesFromRenderObject(resource); - HashMap<const RenderObject*, SVGResources*>::iterator end = cache->m_cache.end(); - for (HashMap<const RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) { + CacheMap::iterator end = cache->m_cache.end(); + for (CacheMap::iterator it = cache->m_cache.begin(); it != end; ++it) { it->value->resourceDestroyed(resource); // Mark users of destroyed resources as pending resolution based on the id of the old resource. Element* resourceElement = toElement(resource->node()); - SVGStyledElement* clientElement = toSVGStyledElement(it->key->node()); + Element* clientElement = toElement(it->key->node()); SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions(); extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement); diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.h b/Source/WebCore/rendering/svg/SVGResourcesCache.h index 633fcd73d..67a01059c 100644 --- a/Source/WebCore/rendering/svg/SVGResourcesCache.h +++ b/Source/WebCore/rendering/svg/SVGResourcesCache.h @@ -23,6 +23,7 @@ #if ENABLE(SVG) #include "RenderStyleConstants.h" #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> namespace WebCore { @@ -61,7 +62,8 @@ private: void addResourcesFromRenderObject(RenderObject*, const RenderStyle*); void removeResourcesFromRenderObject(RenderObject*); - HashMap<const RenderObject*, SVGResources*> m_cache; + typedef HashMap<const RenderObject*, OwnPtr<SVGResources> > CacheMap; + CacheMap m_cache; }; } diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp index 546fec26c..d2df3f16d 100644 --- a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp +++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp @@ -51,9 +51,9 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni if (hasSelection) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (child->isSVGInlineTextBox()) - static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo); + toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo); else if (child->isSVGInlineFlowBox()) - static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo); + toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo); } } @@ -61,7 +61,7 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUni if (renderingContext.isRenderingPrepared()) { for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { if (child->isSVGInlineTextBox()) - SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer())); + SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(toSVGInlineTextBox(child)->textRenderer())); child->paint(paintInfo, LayoutPoint(), 0, 0); } @@ -101,7 +101,7 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText ASSERT(child->renderer()); ASSERT(child->renderer()->isSVGInlineText()); - SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child); + SVGInlineTextBox* textBox = toSVGInlineTextBox(child); characterLayout.layoutInlineTextBox(textBox); } else { // Skip generated content. @@ -109,9 +109,9 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText if (!node) continue; - ASSERT(child->isInlineFlowBox()); + ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox()); - SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child); + SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); bool isTextPath = node->hasTagName(SVGNames::textPathTag); if (isTextPath) { // Build text chunks for all <textPath> children, using the line layout algorithm. @@ -138,7 +138,7 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe ASSERT(child->renderer()); ASSERT(child->renderer()->isSVGInlineText()); - SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child); + SVGInlineTextBox* textBox = toSVGInlineTextBox(child); boxRect = textBox->calculateBoundaries(); textBox->setX(boxRect.x()); textBox->setY(boxRect.y()); @@ -149,9 +149,9 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRe if (!child->renderer()->node()) continue; - ASSERT(child->isInlineFlowBox()); + ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox()); - SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child); + SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child); layoutChildBoxes(flowBox); boxRect = flowBox->calculateBoundaries(); @@ -171,9 +171,9 @@ void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect) ASSERT(parentBlock); // Finally, assign the root block position, now that all content is laid out. - IntRect roundedChildRect = enclosingIntRect(childRect); - parentBlock->setLocation(roundedChildRect.location()); - parentBlock->setSize(roundedChildRect.size()); + LayoutRect boundingRect = enclosingLayoutRect(childRect); + parentBlock->setLocation(boundingRect.location()); + parentBlock->setSize(boundingRect.size()); // Position all children relative to the parent block. for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) { @@ -188,7 +188,7 @@ void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect) setY(0); setLogicalWidth(childRect.width()); setLogicalHeight(childRect.height()); - setLineTopBottomPositions(0, roundedChildRect.height(), 0, roundedChildRect.height()); + setLineTopBottomPositions(0, boundingRect.height(), 0, boundingRect.height()); } InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& point) @@ -278,8 +278,8 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve continue; } - SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first); - SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last); + SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first); + SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last); // Reordering is only necessary for BiDi text that is _absolutely_ positioned. if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) { diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.h b/Source/WebCore/rendering/svg/SVGRootInlineBox.h index 7aec8d888..5bab4f784 100644 --- a/Source/WebCore/rendering/svg/SVGRootInlineBox.h +++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.h @@ -32,7 +32,7 @@ namespace WebCore { class SVGInlineTextBox; -class SVGRootInlineBox : public RootInlineBox { +class SVGRootInlineBox FINAL : public RootInlineBox { public: SVGRootInlineBox(RenderBlock* block) : RootInlineBox(block) diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp index ba2b7639d..e31104575 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp @@ -171,6 +171,8 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou RenderSVGTextPath* textPath = toRenderSVGTextPath(object); m_textPath = textPath->layoutPath(); + if (m_textPath.isEmpty()) + return; m_textPathStartOffset = textPath->startOffset(); m_textPathLength = m_textPath.length(); if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1) @@ -423,7 +425,10 @@ void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& vis void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style) { - SVGElement* lengthContext = static_cast<SVGElement*>(text->parent()->node()); + if (m_inPathLayout && m_textPath.isEmpty()) + return; + + SVGElement* lengthContext = toSVGElement(text->parent()->node()); RenderObject* textParent = text->parent(); bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false; @@ -578,20 +583,9 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend y += m_dy; } - // Determine wheter we have to start a new fragment. - bool shouldStartNewFragment = false; - - if (m_dx || m_dy) - shouldStartNewFragment = true; - - if (!shouldStartNewFragment && (m_isVerticalText || m_inPathLayout)) - shouldStartNewFragment = true; - - if (!shouldStartNewFragment && (angle || angle != lastAngle || orientationAngle)) - shouldStartNewFragment = true; - - if (!shouldStartNewFragment && (kerning || applySpacingToNextCharacter || definesTextLength)) - shouldStartNewFragment = true; + // Determine whether we have to start a new fragment. + bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPathLayout || angle || angle != lastAngle + || orientationAngle || kerning || applySpacingToNextCharacter || definesTextLength; // If we already started a fragment, close it now. if (didStartTextFragment && shouldStartNewFragment) { diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp index 074a8ea66..f0107c4ab 100644 --- a/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp +++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngineSpacing.cpp @@ -30,8 +30,6 @@ #include "SVGFontData.h" #include "SVGFontElement.h" #include "SVGFontFaceElement.h" -#else -#include <wtf/UnusedParam.h> #endif namespace WebCore { diff --git a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp index dfeebb2f8..901ec8179 100644 --- a/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp +++ b/Source/WebCore/rendering/svg/SVGTextMetricsBuilder.cpp @@ -65,9 +65,6 @@ void SVGTextMetricsBuilder::advanceSimpleText() return; } - if (currentCharacterStartsSurrogatePair()) - ASSERT(metricsLength == 2); - float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.cpp b/Source/WebCore/rendering/svg/SVGTextQuery.cpp index a7ee787c4..bcc8d87ba 100644 --- a/Source/WebCore/rendering/svg/SVGTextQuery.cpp +++ b/Source/WebCore/rendering/svg/SVGTextQuery.cpp @@ -101,7 +101,7 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox) } if (child->isSVGInlineTextBox()) - m_textBoxes.append(static_cast<SVGInlineTextBox*>(child)); + m_textBoxes.append(toSVGInlineTextBox(child)); } } @@ -352,10 +352,10 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe return true; } -FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const +SVGPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const { if (m_textBoxes.isEmpty()) - return FloatPoint(); + return SVGPoint(); StartPositionOfCharacterData data(position); executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); @@ -399,10 +399,10 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText return true; } -FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const +SVGPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const { if (m_textBoxes.isEmpty()) - return FloatPoint(); + return SVGPoint(); EndPositionOfCharacterData data(position); executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); @@ -543,7 +543,7 @@ bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT return false; } -int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const +int SVGTextQuery::characterNumberAtPosition(const SVGPoint& position) const { if (m_textBoxes.isEmpty()) return -1; diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.h b/Source/WebCore/rendering/svg/SVGTextQuery.h index 331dd945c..bf60a6da6 100644 --- a/Source/WebCore/rendering/svg/SVGTextQuery.h +++ b/Source/WebCore/rendering/svg/SVGTextQuery.h @@ -22,6 +22,7 @@ #if ENABLE(SVG) #include "FloatRect.h" +#include "SVGPoint.h" #include "SVGTextFragment.h" #include <wtf/Vector.h> @@ -38,11 +39,11 @@ public: unsigned numberOfCharacters() const; float textLength() const; float subStringLength(unsigned startPosition, unsigned length) const; - FloatPoint startPositionOfCharacter(unsigned position) const; - FloatPoint endPositionOfCharacter(unsigned position) const; + SVGPoint startPositionOfCharacter(unsigned position) const; + SVGPoint endPositionOfCharacter(unsigned position) const; float rotationOfCharacter(unsigned position) const; FloatRect extentOfCharacter(unsigned position) const; - int characterNumberAtPosition(const FloatPoint&) const; + int characterNumberAtPosition(const SVGPoint&) const; // Public helper struct. Private classes in SVGTextQuery inherit from it. struct Data; diff --git a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp index 7dd60d49e..f94b283e6 100644 --- a/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp +++ b/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp @@ -126,7 +126,7 @@ void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const T if (!glyph) continue; - float advance = glyphBuffer.advanceAt(from + i); + float advance = glyphBuffer.advanceAt(from + i).width(); SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph); ASSERT(!svgGlyph.isPartOfLigature); ASSERT(svgGlyph.tableEntry == glyph); @@ -174,7 +174,7 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co const SimpleFontData* primaryFont = font.primaryFont(); ASSERT(primaryFont); - pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(character, mirror); + pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(character, mirror, AutoVariant); GlyphData glyphData = pair.first; // Check if we have the missing glyph data, in which case we can just return. @@ -186,9 +186,9 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co // Save data fromt he font fallback list because we may modify it later. Do this before the // potential change to glyphData.fontData below. - FontFallbackList* fontList = font.fontList(); - ASSERT(fontList); - FontFallbackList::GlyphPagesStateSaver glyphPagesSaver(*fontList); + FontGlyphs* glyph = font.glyphs(); + ASSERT(glyph); + FontGlyphs::GlyphPagesStateSaver glyphPagesSaver(*glyph); // Characters enclosed by an <altGlyph> element, may not be registered in the GlyphPage. const SimpleFontData* originalFontData = glyphData.fontData; @@ -230,7 +230,7 @@ GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, co // No suitable glyph found that is compatible with the requirments (same language, arabic-form, orientation etc.) // Even though our GlyphPage contains an entry for eg. glyph "a", it's not compatible. So we have to temporarily // remove the glyph data information from the GlyphPage, and retry the lookup, which handles font fallbacks correctly. - page->setGlyphDataForCharacter(character, glyphData.glyph, 0); + page->setGlyphDataForCharacter(character, 0, 0); // Assure that the font fallback glyph selection worked, aka. the fallbackGlyphData font data is not the same as before. GlyphData fallbackGlyphData = font.glyphDataForCharacter(character, mirror); |
