diff options
Diffstat (limited to 'WebCore/svg')
28 files changed, 476 insertions, 148 deletions
diff --git a/WebCore/svg/SVGClipPathElement.cpp b/WebCore/svg/SVGClipPathElement.cpp index c3a514e..5c23031 100644 --- a/WebCore/svg/SVGClipPathElement.cpp +++ b/WebCore/svg/SVGClipPathElement.cpp @@ -69,12 +69,16 @@ void SVGClipPathElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + RenderObject* object = renderer(); + if (!object) + return; + if (attrName == SVGNames::clipPathUnitsAttr || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledTransformableElement::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGClipPathElement::synchronizeProperty(const QualifiedName& attrName) @@ -97,8 +101,11 @@ void SVGClipPathElement::childrenChanged(bool changedByParser, Node* beforeChang { SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } RenderObject* SVGClipPathElement::createRenderer(RenderArena* arena, RenderStyle*) diff --git a/WebCore/svg/SVGClipPathElement.h b/WebCore/svg/SVGClipPathElement.h index eb74f72..11b07fb 100644 --- a/WebCore/svg/SVGClipPathElement.h +++ b/WebCore/svg/SVGClipPathElement.h @@ -39,6 +39,7 @@ public: virtual ~SVGClipPathElement(); virtual bool isValid() const { return SVGTests::isValid(); } + virtual bool needsPendingResourceHandling() const { return false; } virtual void parseMappedAttribute(Attribute*); virtual void svgAttributeChanged(const QualifiedName&); diff --git a/WebCore/svg/SVGElement.cpp b/WebCore/svg/SVGElement.cpp index b262e45..0497edf 100644 --- a/WebCore/svg/SVGElement.cpp +++ b/WebCore/svg/SVGElement.cpp @@ -278,20 +278,22 @@ bool SVGElement::childShouldCreateRenderer(Node* child) const void SVGElement::insertedIntoDocument() { StyledElement::insertedIntoDocument(); - SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); - String resourceId = getIdAttribute(); - if (extensions->isPendingResource(resourceId)) { - OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId)); - if (clients->isEmpty()) - return; + if (!needsPendingResourceHandling()) + return; - HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); - const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); + String resourceId = getIdAttribute(); + if (!extensions->isPendingResource(resourceId)) + return; + + OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId)); + if (clients->isEmpty()) + return; - for (; it != end; ++it) - (*it)->buildPendingResource(); - } + const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + for (HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); it != end; ++it) + (*it)->buildPendingResource(); } void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) diff --git a/WebCore/svg/SVGElement.h b/WebCore/svg/SVGElement.h index 64afe8e..eccf03e 100644 --- a/WebCore/svg/SVGElement.h +++ b/WebCore/svg/SVGElement.h @@ -97,6 +97,8 @@ namespace WebCore { virtual bool isSupported(StringImpl* feature, StringImpl* version) const; virtual ContainerNode* eventParentNode(); + + virtual bool needsPendingResourceHandling() const { return true; } virtual void buildPendingResource() { } void mapInstanceToElement(SVGElementInstance*); diff --git a/WebCore/svg/SVGFETurbulenceElement.cpp b/WebCore/svg/SVGFETurbulenceElement.cpp index e5b5419..e4987c5 100644 --- a/WebCore/svg/SVGFETurbulenceElement.cpp +++ b/WebCore/svg/SVGFETurbulenceElement.cpp @@ -99,6 +99,9 @@ void SVGFETurbulenceElement::synchronizeProperty(const QualifiedName& attrName) PassRefPtr<FilterEffect> SVGFETurbulenceElement::build(SVGFilterBuilder*) { + if (baseFrequencyX() < 0 || baseFrequencyY() < 0) + return 0; + return FETurbulence::create(static_cast<TurbulanceType>(type()), baseFrequencyX(), baseFrequencyY(), numOctaves(), seed(), stitchTiles() == SVG_STITCHTYPE_STITCH); } diff --git a/WebCore/svg/SVGFilterElement.cpp b/WebCore/svg/SVGFilterElement.cpp index 4387e71..0d55bb1 100644 --- a/WebCore/svg/SVGFilterElement.cpp +++ b/WebCore/svg/SVGFilterElement.cpp @@ -66,7 +66,9 @@ void SVGFilterElement::setFilterRes(unsigned long filterResX, unsigned long filt { setFilterResXBaseValue(filterResX); setFilterResYBaseValue(filterResY); - invalidateResourceClients(); + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } void SVGFilterElement::parseMappedAttribute(Attribute* attr) @@ -121,6 +123,10 @@ void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName) updateRelativeLengthsInformation(); } + RenderObject* object = renderer(); + if (!object) + return; + if (invalidateClients || attrName == SVGNames::filterUnitsAttr || attrName == SVGNames::primitiveUnitsAttr @@ -129,7 +135,7 @@ void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName) || SVGURIReference::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGFilterElement::synchronizeProperty(const QualifiedName& attrName) @@ -175,8 +181,11 @@ void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } FloatRect SVGFilterElement::filterBoundingBox(const FloatRect& objectBoundingBox) const diff --git a/WebCore/svg/SVGFilterElement.h b/WebCore/svg/SVGFilterElement.h index 7b0192c..cdb2297 100644 --- a/WebCore/svg/SVGFilterElement.h +++ b/WebCore/svg/SVGFilterElement.h @@ -43,6 +43,8 @@ public: SVGFilterElement(const QualifiedName&, Document*); virtual ~SVGFilterElement(); + virtual bool needsPendingResourceHandling() const { return false; } + void setFilterRes(unsigned long filterResX, unsigned long filterResY); FloatRect filterBoundingBox(const FloatRect&) const; diff --git a/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp b/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp index 8e284e6..042d93b 100644 --- a/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp +++ b/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp @@ -107,7 +107,7 @@ void SVGFilterPrimitiveStandardAttributes::childrenChanged(bool changedByParser, SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); if (!changedByParser) - invalidateResourceClients(); + invalidateFilter(); } void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(bool primitiveBoundingBoxMode, FilterEffect* filterEffect) const diff --git a/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h b/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h index 14784a5..19f6f3a 100644 --- a/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h +++ b/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h @@ -55,7 +55,8 @@ protected: { if (!inDocument() || !parentNode()->hasTagName(SVGNames::filterTag)) return; - static_cast<SVGFilterElement*>(parentNode())->invalidateResourceClients(); + if (RenderObject* object = parentNode()->renderer()) + object->setNeedsLayout(true); } private: diff --git a/WebCore/svg/SVGGradientElement.cpp b/WebCore/svg/SVGGradientElement.cpp index b314674..0d06955 100644 --- a/WebCore/svg/SVGGradientElement.cpp +++ b/WebCore/svg/SVGGradientElement.cpp @@ -85,13 +85,17 @@ void SVGGradientElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); + RenderObject* object = renderer(); + if (!object) + return; + if (attrName == SVGNames::gradientUnitsAttr || attrName == SVGNames::gradientTransformAttr || attrName == SVGNames::spreadMethodAttr || SVGURIReference::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -123,8 +127,11 @@ void SVGGradientElement::childrenChanged(bool changedByParser, Node* beforeChang { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } Vector<Gradient::ColorStop> SVGGradientElement::buildStops() diff --git a/WebCore/svg/SVGGradientElement.h b/WebCore/svg/SVGGradientElement.h index 2736ab3..11a13e4 100644 --- a/WebCore/svg/SVGGradientElement.h +++ b/WebCore/svg/SVGGradientElement.h @@ -37,6 +37,8 @@ namespace WebCore { SVGGradientElement(const QualifiedName&, Document*); virtual ~SVGGradientElement(); + virtual bool needsPendingResourceHandling() const { return false; } + virtual void parseMappedAttribute(Attribute*); virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); diff --git a/WebCore/svg/SVGLinearGradientElement.cpp b/WebCore/svg/SVGLinearGradientElement.cpp index d95c084..37f380b 100644 --- a/WebCore/svg/SVGLinearGradientElement.cpp +++ b/WebCore/svg/SVGLinearGradientElement.cpp @@ -76,7 +76,12 @@ void SVGLinearGradientElement::svgAttributeChanged(const QualifiedName& attrName || attrName == SVGNames::x2Attr || attrName == SVGNames::y2Attr) { updateRelativeLengthsInformation(); - invalidateResourceClients(); + + RenderObject* object = renderer(); + if (!object) + return; + + object->setNeedsLayout(true); } } @@ -155,8 +160,10 @@ LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() current = static_cast<SVGGradientElement*>(refNode); // Cycle detection - if (processedGradients.contains(current)) - return LinearGradientAttributes(); + if (processedGradients.contains(current)) { + current = 0; + break; + } isLinear = current->hasTagName(SVGNames::linearGradientTag); } else diff --git a/WebCore/svg/SVGMarkerElement.cpp b/WebCore/svg/SVGMarkerElement.cpp index 01faf21..195e91d 100644 --- a/WebCore/svg/SVGMarkerElement.cpp +++ b/WebCore/svg/SVGMarkerElement.cpp @@ -113,6 +113,10 @@ void SVGMarkerElement::svgAttributeChanged(const QualifiedName& attrName) updateRelativeLengthsInformation(); } + RenderObject* object = renderer(); + if (!object) + return; + if (invalidateClients || attrName == SVGNames::markerUnitsAttr || attrName == SVGNames::orientAttr @@ -120,7 +124,7 @@ void SVGMarkerElement::svgAttributeChanged(const QualifiedName& attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGFitToViewBox::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGMarkerElement::synchronizeProperty(const QualifiedName& attrName) @@ -166,8 +170,11 @@ void SVGMarkerElement::childrenChanged(bool changedByParser, Node* beforeChange, { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } void SVGMarkerElement::setOrientToAuto() @@ -175,7 +182,8 @@ void SVGMarkerElement::setOrientToAuto() setOrientTypeBaseValue(SVG_MARKER_ORIENT_AUTO); setOrientAngleBaseValue(SVGAngle()); - invalidateResourceClients(); + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } void SVGMarkerElement::setOrientToAngle(const SVGAngle& angle) @@ -183,7 +191,8 @@ void SVGMarkerElement::setOrientToAngle(const SVGAngle& angle) setOrientTypeBaseValue(SVG_MARKER_ORIENT_ANGLE); setOrientAngleBaseValue(angle); - invalidateResourceClients(); + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } RenderObject* SVGMarkerElement::createRenderer(RenderArena* arena, RenderStyle*) diff --git a/WebCore/svg/SVGMarkerElement.h b/WebCore/svg/SVGMarkerElement.h index 689a7e5..7b13d34 100644 --- a/WebCore/svg/SVGMarkerElement.h +++ b/WebCore/svg/SVGMarkerElement.h @@ -56,6 +56,8 @@ public: SVGMarkerElement(const QualifiedName&, Document*); virtual ~SVGMarkerElement(); + virtual bool needsPendingResourceHandling() const { return false; } + AffineTransform viewBoxToViewTransform(float viewWidth, float viewHeight) const; void setOrientToAuto(); diff --git a/WebCore/svg/SVGMaskElement.cpp b/WebCore/svg/SVGMaskElement.cpp index 5013e5c..a87c28e 100644 --- a/WebCore/svg/SVGMaskElement.cpp +++ b/WebCore/svg/SVGMaskElement.cpp @@ -102,6 +102,10 @@ void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) updateRelativeLengthsInformation(); } + RenderObject* object = renderer(); + if (!object) + return; + if (invalidateClients || attrName == SVGNames::maskUnitsAttr || attrName == SVGNames::maskContentUnitsAttr @@ -109,7 +113,7 @@ void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGMaskElement::synchronizeProperty(const QualifiedName& attrName) @@ -141,8 +145,11 @@ void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, N { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } FloatRect SVGMaskElement::maskBoundingBox(const FloatRect& objectBoundingBox) const diff --git a/WebCore/svg/SVGMaskElement.h b/WebCore/svg/SVGMaskElement.h index e941667..2df8f31 100644 --- a/WebCore/svg/SVGMaskElement.h +++ b/WebCore/svg/SVGMaskElement.h @@ -40,6 +40,7 @@ namespace WebCore { virtual ~SVGMaskElement(); virtual bool isValid() const { return SVGTests::isValid(); } + virtual bool needsPendingResourceHandling() const { return false; } FloatRect maskBoundingBox(const FloatRect&) const; virtual void parseMappedAttribute(Attribute*); diff --git a/WebCore/svg/SVGParserUtilities.cpp b/WebCore/svg/SVGParserUtilities.cpp index 14e3d58..b5e695b 100644 --- a/WebCore/svg/SVGParserUtilities.cpp +++ b/WebCore/svg/SVGParserUtilities.cpp @@ -40,8 +40,8 @@ namespace WebCore { */ template <typename FloatType> static bool _parseNumber(const UChar*& ptr, const UChar* end, FloatType& number, bool skip) { - int integer, exponent; - FloatType decimal, frac; + int exponent; + FloatType integer, decimal, frac; int sign, expsign; const UChar* start = ptr; @@ -64,9 +64,19 @@ template <typename FloatType> static bool _parseNumber(const UChar*& ptr, const // The first character of a number must be one of [0-9+-.] return false; - // read the integer part + // read the integer part, build right-to-left + const UChar* ptrStartIntPart = ptr; while (ptr < end && *ptr >= '0' && *ptr <= '9') - integer = (integer * 10) + *(ptr++) - '0'; + ++ptr; // Advance to first non-digit. + + if (ptr != ptrStartIntPart) { + const UChar* ptrScanIntPart = ptr - 1; + FloatType multiplier = 1; + while (ptrScanIntPart >= ptrStartIntPart) { + integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0'); + multiplier *= 10; + } + } if (ptr < end && *ptr == '.') { // read the decimals ptr++; diff --git a/WebCore/svg/SVGPatternElement.cpp b/WebCore/svg/SVGPatternElement.cpp index e258946..ee42118 100644 --- a/WebCore/svg/SVGPatternElement.cpp +++ b/WebCore/svg/SVGPatternElement.cpp @@ -129,6 +129,10 @@ void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName) updateRelativeLengthsInformation(); } + RenderObject* object = renderer(); + if (!object) + return; + if (invalidateClients || attrName == SVGNames::patternUnitsAttr || attrName == SVGNames::patternContentUnitsAttr @@ -139,7 +143,7 @@ void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGFitToViewBox::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateResourceClients(); + object->setNeedsLayout(true); } void SVGPatternElement::synchronizeProperty(const QualifiedName& attrName) @@ -188,8 +192,11 @@ void SVGPatternElement::childrenChanged(bool changedByParser, Node* beforeChange { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!changedByParser) - invalidateResourceClients(); + if (changedByParser) + return; + + if (RenderObject* object = renderer()) + object->setNeedsLayout(true); } RenderObject* SVGPatternElement::createRenderer(RenderArena* arena, RenderStyle*) @@ -236,8 +243,10 @@ PatternAttributes SVGPatternElement::collectPatternProperties() const current = static_cast<const SVGPatternElement*>(const_cast<const Node*>(refNode)); // Cycle detection - if (processedPatterns.contains(current)) - return PatternAttributes(); + if (processedPatterns.contains(current)) { + current = 0; + break; + } } else current = 0; } diff --git a/WebCore/svg/SVGPatternElement.h b/WebCore/svg/SVGPatternElement.h index 105b8e2..2a8a7fe 100644 --- a/WebCore/svg/SVGPatternElement.h +++ b/WebCore/svg/SVGPatternElement.h @@ -47,6 +47,7 @@ namespace WebCore { virtual ~SVGPatternElement(); virtual bool isValid() const { return SVGTests::isValid(); } + virtual bool needsPendingResourceHandling() const { return false; } virtual void parseMappedAttribute(Attribute*); virtual void svgAttributeChanged(const QualifiedName&); diff --git a/WebCore/svg/SVGRadialGradientElement.cpp b/WebCore/svg/SVGRadialGradientElement.cpp index 2a97b9d..a970817 100644 --- a/WebCore/svg/SVGRadialGradientElement.cpp +++ b/WebCore/svg/SVGRadialGradientElement.cpp @@ -83,7 +83,12 @@ void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName || attrName == SVGNames::fyAttr || attrName == SVGNames::rAttr) { updateRelativeLengthsInformation(); - invalidateResourceClients(); + + RenderObject* object = renderer(); + if (!object) + return; + + object->setNeedsLayout(true); } } @@ -168,8 +173,10 @@ RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() current = static_cast<SVGGradientElement*>(refNode); // Cycle detection - if (processedGradients.contains(current)) - return RadialGradientAttributes(); + if (processedGradients.contains(current)) { + current = 0; + break; + } isRadial = current->hasTagName(SVGNames::radialGradientTag); } else diff --git a/WebCore/svg/SVGScriptElement.cpp b/WebCore/svg/SVGScriptElement.cpp index abe77a9..ea4ac1f 100644 --- a/WebCore/svg/SVGScriptElement.cpp +++ b/WebCore/svg/SVGScriptElement.cpp @@ -242,6 +242,11 @@ void SVGScriptElement::dispatchErrorEvent() dispatchEvent(Event::create(eventNames().errorEvent, true, false)); } +bool SVGScriptElement::shouldExecuteAsJavaScript() const +{ + return m_data.shouldExecuteAsJavaScript(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGScriptElement.h b/WebCore/svg/SVGScriptElement.h index 770dc89..2d9cae8 100644 --- a/WebCore/svg/SVGScriptElement.h +++ b/WebCore/svg/SVGScriptElement.h @@ -56,7 +56,7 @@ namespace WebCore { virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; - virtual bool shouldExecuteAsJavaScript() const { return false; } + virtual bool shouldExecuteAsJavaScript() const; protected: virtual bool haveLoadedRequiredResources(); diff --git a/WebCore/svg/SVGStyleElement.cpp b/WebCore/svg/SVGStyleElement.cpp index 48fbe69..6050e84 100644 --- a/WebCore/svg/SVGStyleElement.cpp +++ b/WebCore/svg/SVGStyleElement.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org> + Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> Copyright (C) 2006 Apple Computer, Inc. Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> @@ -34,12 +34,10 @@ namespace WebCore { -using namespace SVGNames; - -SVGStyleElement::SVGStyleElement(const QualifiedName& tagName, Document* doc, bool createdByParser) - : SVGElement(tagName, doc) - , SVGLangSpace() - , m_createdByParser(createdByParser) +SVGStyleElement::SVGStyleElement(const QualifiedName& tagName, Document* document, bool createdByParser) + : SVGElement(tagName, document) + , SVGLangSpace() + , StyleElement(document, createdByParser) { } @@ -90,31 +88,26 @@ void SVGStyleElement::parseMappedAttribute(Attribute* attr) void SVGStyleElement::finishParsingChildren() { - StyleElement::sheet(this); - m_createdByParser = false; + StyleElement::finishParsingChildren(this); SVGElement::finishParsingChildren(); } void SVGStyleElement::insertedIntoDocument() { SVGElement::insertedIntoDocument(); - document()->addStyleSheetCandidateNode(this, m_createdByParser); - if (!m_createdByParser) - StyleElement::insertedIntoDocument(document(), this); + StyleElement::insertedIntoDocument(document(), this); } void SVGStyleElement::removedFromDocument() { SVGElement::removedFromDocument(); - if (document()->renderer()) - document()->removeStyleSheetCandidateNode(this); - StyleElement::removedFromDocument(document()); + StyleElement::removedFromDocument(document(), this); } void SVGStyleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { + StyleElement::childrenChanged(this); SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - StyleElement::process(this, 0); } StyleSheet* SVGStyleElement::sheet() @@ -122,13 +115,6 @@ StyleSheet* SVGStyleElement::sheet() return StyleElement::sheet(this); } -bool SVGStyleElement::sheetLoaded() -{ - document()->removePendingSheet(); - return true; -} - } -// vim:ts=4:noet #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGStyleElement.h b/WebCore/svg/SVGStyleElement.h index ae7ed57..fe11f9c 100644 --- a/WebCore/svg/SVGStyleElement.h +++ b/WebCore/svg/SVGStyleElement.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org> + Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> This library is free software; you can redistribute it and/or @@ -20,48 +20,43 @@ #ifndef SVGStyleElement_h #define SVGStyleElement_h -#if ENABLE(SVG) -#include <SVGElement.h> +#if ENABLE(SVG) +#include "SVGElement.h" #include "SVGLangSpace.h" #include "StyleElement.h" namespace WebCore { - class SVGStyleElement : public SVGElement, - public SVGLangSpace, - public StyleElement { - public: - SVGStyleElement(const QualifiedName&, Document*, bool createdByParser); +class SVGStyleElement : public SVGElement + , public SVGLangSpace + , public StyleElement { +public: + SVGStyleElement(const QualifiedName&, Document*, bool createdByParser); - // Derived from: 'Element' - virtual void parseMappedAttribute(Attribute*); - virtual void insertedIntoDocument(); - virtual void removedFromDocument(); - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - virtual void finishParsingChildren(); + virtual void finishParsingChildren(); - virtual bool sheetLoaded(); + virtual bool isLoading() const { return StyleElement::isLoading(); } + virtual bool sheetLoaded() { return StyleElement::sheetLoaded(document()); } - virtual const AtomicString& type() const; - void setType(const AtomicString&, ExceptionCode&); + virtual const AtomicString& type() const; + void setType(const AtomicString&, ExceptionCode&); - virtual const AtomicString& media() const; - void setMedia(const AtomicString&, ExceptionCode&); + virtual const AtomicString& media() const; + void setMedia(const AtomicString&, ExceptionCode&); - virtual String title() const; - void setTitle(const AtomicString&, ExceptionCode&); + virtual String title() const; + void setTitle(const AtomicString&, ExceptionCode&); - StyleSheet* sheet(); - - protected: - bool m_createdByParser; - }; + StyleSheet* sheet(); +}; } // namespace WebCore #endif // ENABLE(SVG) #endif // SVGStyleElement_h - -// vim:ts=4:noet diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index 6c2993c..09447c5 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -258,17 +258,12 @@ void SVGStyledElement::synchronizeProperty(const QualifiedName& attrName) synchronizeClassName(); } -void SVGStyledElement::invalidateResourceClients() +void SVGStyledElement::attach() { - if (document()->parsing()) - return; - - RenderObject* object = renderer(); - if (!object) - return; + SVGElement::attach(); - if (object->isSVGResourceContainer()) - object->toRenderSVGResourceContainer()->invalidateClients(); + if (RenderObject* object = renderer()) + object->updateFromElement(); } void SVGStyledElement::insertedIntoDocument() diff --git a/WebCore/svg/SVGStyledElement.h b/WebCore/svg/SVGStyledElement.h index 4982908..79ee0d5 100644 --- a/WebCore/svg/SVGStyledElement.h +++ b/WebCore/svg/SVGStyledElement.h @@ -57,6 +57,7 @@ namespace WebCore { virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); + virtual void attach(); virtual void insertedIntoDocument(); virtual void removedFromDocument(); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); @@ -64,8 +65,6 @@ namespace WebCore { // Centralized place to force a manual style resolution. Hacky but needed for now. PassRefPtr<RenderStyle> resolveStyle(RenderStyle* parentStyle); - void invalidateResourceClients(); - bool instanceUpdatesBlocked() const; void setInstanceUpdatesBlocked(bool); diff --git a/WebCore/svg/graphics/filters/SVGFETurbulence.cpp b/WebCore/svg/graphics/filters/SVGFETurbulence.cpp index db4b0bb..8042a47 100644 --- a/WebCore/svg/graphics/filters/SVGFETurbulence.cpp +++ b/WebCore/svg/graphics/filters/SVGFETurbulence.cpp @@ -2,6 +2,8 @@ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> + 2009 Dirk Schulze <krit@webkit.org> + 2010 Renata Hodovan <reni@inf.u-szeged.hu> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -23,13 +25,31 @@ #if ENABLE(SVG) && ENABLE(FILTERS) #include "SVGFETurbulence.h" -#include "SVGRenderTreeAsText.h" + +#include "CanvasPixelArray.h" #include "Filter.h" +#include "ImageData.h" +#include "SVGRenderTreeAsText.h" + +#include <wtf/MathExtras.h> namespace WebCore { -FETurbulence::FETurbulence(TurbulanceType type, const float& baseFrequencyX, const float& baseFrequencyY, - const int& numOctaves, const float& seed, bool stitchTiles) +/* + Produces results in the range [1, 2**31 - 2]. Algorithm is: + r = (a * r) mod m where a = randAmplitude = 16807 and + m = randMaximum = 2**31 - 1 = 2147483647, r = seed. + See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 + To test: the algorithm should produce the result 1043618065 + as the 10,000th generated number if the original seed is 1. +*/ +static const int s_perlinNoise = 4096; +static const long s_randMaximum = 2147483647; // 2**31 - 1 +static const int s_randAmplitude = 16807; // 7**5; primitive root of m +static const int s_randQ = 127773; // m / a +static const int s_randR = 2836; // m % a + +FETurbulence::FETurbulence(TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) : FilterEffect() , m_type(type) , m_baseFrequencyX(baseFrequencyX) @@ -40,8 +60,7 @@ FETurbulence::FETurbulence(TurbulanceType type, const float& baseFrequencyX, con { } -PassRefPtr<FETurbulence> FETurbulence::create(TurbulanceType type, const float& baseFrequencyX, const float& baseFrequencyY, - const int& numOctaves, const float& seed, bool stitchTiles) +PassRefPtr<FETurbulence> FETurbulence::create(TurbulanceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) { return adoptRef(new FETurbulence(type, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles)); } @@ -106,8 +125,226 @@ void FETurbulence::setStitchTiles(bool stitch) m_stitchTiles = stitch; } -void FETurbulence::apply(Filter*) +// The turbulence calculation code is an adapted version of what appears in the SVG 1.1 specification: +// http://www.w3.org/TR/SVG11/filters.html#feTurbulence + +FETurbulence::PaintingData::PaintingData(long paintingSeed, const IntSize& paintingSize) + : seed(paintingSeed) + , width(0) + , height(0) + , wrapX(0) + , wrapY(0) + , channel(0) + , filterSize(paintingSize) +{ +} + +// Compute pseudo random number. +inline long FETurbulence::PaintingData::random() +{ + long result = s_randAmplitude * (seed % s_randQ) - s_randR * (seed / s_randQ); + if (result <= 0) + result += s_randMaximum; + seed = result; + return result; +} + +inline float smoothCurve(float t) +{ + return t * t * (3 - 2 * t); +} + +inline float linearInterpolation(float t, float a, float b) +{ + return a + t * (b - a); +} + +inline void FETurbulence::initPaint(PaintingData& paintingData) { + float normalizationFactor; + + // The seed value clamp to the range [1, s_randMaximum - 1]. + if (paintingData.seed <= 0) + paintingData.seed = -(paintingData.seed % (s_randMaximum - 1)) + 1; + if (paintingData.seed > s_randMaximum - 1) + paintingData.seed = s_randMaximum - 1; + + float* gradient; + for (int channel = 0; channel < 4; ++channel) { + for (int i = 0; i < s_blockSize; ++i) { + paintingData.latticeSelector[i] = i; + gradient = paintingData.gradient[channel][i]; + gradient[0] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + gradient[1] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; + normalizationFactor = sqrtf(gradient[0] * gradient[0] + gradient[1] * gradient[1]); + gradient[0] /= normalizationFactor; + gradient[1] /= normalizationFactor; + } + } + for (int i = s_blockSize - 1; i >= 0; --i) { + int k = paintingData.latticeSelector[i]; + int j = paintingData.random() % s_blockSize; + ASSERT(j >= 0); + ASSERT(j < 2 * s_blockSize + 2); + paintingData.latticeSelector[i] = paintingData.latticeSelector[j]; + paintingData.latticeSelector[j] = k; + } + for (int i = 0; i < s_blockSize + 2; ++i) { + paintingData.latticeSelector[s_blockSize + i] = paintingData.latticeSelector[i]; + for (int channel = 0; channel < 4; ++channel) { + paintingData.gradient[channel][s_blockSize + i][0] = paintingData.gradient[channel][i][0]; + paintingData.gradient[channel][s_blockSize + i][1] = paintingData.gradient[channel][i][1]; + } + } +} + +inline void checkNoise(int& noiseValue, int limitValue, int newValue) +{ + if (noiseValue >= limitValue) + noiseValue -= newValue; + if (noiseValue >= limitValue - 1) + noiseValue -= newValue - 1; +} + +float FETurbulence::noise2D(PaintingData& paintingData, const FloatPoint& noiseVector) +{ + struct Noise { + int noisePositionIntegerValue; + float noisePositionFractionValue; + + Noise(float component) + { + float position = component + s_perlinNoise; + noisePositionIntegerValue = static_cast<int>(position); + noisePositionFractionValue = position - noisePositionIntegerValue; + } + }; + + Noise noiseX(noiseVector.x()); + Noise noiseY(noiseVector.y()); + float* q; + float sx, sy, a, b, u, v; + + // If stitching, adjust lattice points accordingly. + if (m_stitchTiles) { + checkNoise(noiseX.noisePositionIntegerValue, paintingData.wrapX, paintingData.width); + checkNoise(noiseY.noisePositionIntegerValue, paintingData.wrapY, paintingData.height); + } + + noiseX.noisePositionIntegerValue &= s_blockMask; + noiseY.noisePositionIntegerValue &= s_blockMask; + int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue]; + int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask]; + + sx = smoothCurve(noiseX.noisePositionFractionValue); + sy = smoothCurve(noiseY.noisePositionFractionValue); + + // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement. + int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1]; + a = linearInterpolation(sx, u, v); + temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1]; + q = paintingData.gradient[paintingData.channel][temp]; + v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; + b = linearInterpolation(sx, u, v); + return linearInterpolation(sy, a, b); +} + +unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paintingData, const FloatPoint& point) +{ + float tileWidth = paintingData.filterSize.width(); + ASSERT(tileWidth > 0); + float tileHeight = paintingData.filterSize.height(); + ASSERT(tileHeight > 0); + // Adjust the base frequencies if necessary for stitching. + if (m_stitchTiles) { + // When stitching tiled turbulence, the frequencies must be adjusted + // so that the tile borders will be continuous. + if (m_baseFrequencyX) { + float lowFrequency = floorf(tileWidth * m_baseFrequencyX) / tileWidth; + float highFrequency = ceilf(tileWidth * m_baseFrequencyX) / tileWidth; + // BaseFrequency should be non-negative according to the standard. + if (m_baseFrequencyX / lowFrequency < highFrequency / m_baseFrequencyX) + m_baseFrequencyX = lowFrequency; + else + m_baseFrequencyX = highFrequency; + } + if (m_baseFrequencyY) { + float lowFrequency = floorf(tileHeight * m_baseFrequencyY) / tileHeight; + float highFrequency = ceilf(tileHeight * m_baseFrequencyY) / tileHeight; + if (m_baseFrequencyY / lowFrequency < highFrequency / m_baseFrequencyY) + m_baseFrequencyY = lowFrequency; + else + m_baseFrequencyY = highFrequency; + } + // Set up TurbulenceInitial stitch values. + paintingData.width = roundf(tileWidth * m_baseFrequencyX); + paintingData.wrapX = s_perlinNoise + paintingData.width; + paintingData.height = roundf(tileHeight * m_baseFrequencyY); + paintingData.wrapY = s_perlinNoise + paintingData.height; + } + float turbulenceFunctionResult = 0; + FloatPoint noiseVector(point.x() * m_baseFrequencyX, point.y() * m_baseFrequencyY); + float ratio = 1; + for (int octave = 0; octave < m_numOctaves; ++octave) { + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + turbulenceFunctionResult += noise2D(paintingData, noiseVector) / ratio; + else + turbulenceFunctionResult += fabsf(noise2D(paintingData, noiseVector)) / ratio; + noiseVector.setX(noiseVector.x() * 2); + noiseVector.setY(noiseVector.y() * 2); + ratio *= 2; + if (m_stitchTiles) { + // Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and + // adding it afterward simplifies to subtracting it once. + paintingData.width *= 2; + paintingData.wrapX = 2 * paintingData.wrapX - s_perlinNoise; + paintingData.height *= 2; + paintingData.wrapY = 2 * paintingData.wrapY - s_perlinNoise; + } + } + + // Clamp result + turbulenceFunctionResult = std::max(std::min(turbulenceFunctionResult, 255.f), 0.f); + if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) + return static_cast<unsigned char>(turbulenceFunctionResult * 127.5f + 127.5f); // It comes form (turbulenceFunctionResult * 255 + 255) / 2 + return static_cast<unsigned char>(turbulenceFunctionResult * 255); +} + +void FETurbulence::apply(Filter* filter) +{ + if (!getEffectContext()) + return; + + IntRect imageRect(IntPoint(), resultImage()->size()); + if (!imageRect.size().width() || !imageRect.size().height()) + return; + + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + PaintingData paintingData(floorf(fabsf(m_seed)), imageRect.size()); + initPaint(paintingData); + + FloatRect filterRegion = filter->filterRegion(); + FloatPoint point; + point.setY(filterRegion.y()); + int indexOfPixelChannel = 0; + for (int y = 0; y < imageRect.height(); ++y) { + point.setY(point.y() + 1); + point.setX(filterRegion.x()); + for (int x = 0; x < imageRect.width(); ++x) { + point.setX(point.x() + 1); + for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel) + imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, point)); + } + } + resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint()); } void FETurbulence::dump() diff --git a/WebCore/svg/graphics/filters/SVGFETurbulence.h b/WebCore/svg/graphics/filters/SVGFETurbulence.h index bed0637..33e185e 100644 --- a/WebCore/svg/graphics/filters/SVGFETurbulence.h +++ b/WebCore/svg/graphics/filters/SVGFETurbulence.h @@ -2,6 +2,8 @@ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> + 2009 Dirk Schulze <krit@webkit.org> + 2010 Renata Hodovan <reni@inf.u-szeged.hu> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -28,51 +30,71 @@ namespace WebCore { - enum TurbulanceType { - FETURBULENCE_TYPE_UNKNOWN = 0, - FETURBULENCE_TYPE_FRACTALNOISE = 1, - FETURBULENCE_TYPE_TURBULENCE = 2 - }; +enum TurbulanceType { + FETURBULENCE_TYPE_UNKNOWN = 0, + FETURBULENCE_TYPE_FRACTALNOISE = 1, + FETURBULENCE_TYPE_TURBULENCE = 2 +}; + +class FETurbulence : public FilterEffect { +public: + static PassRefPtr<FETurbulence> create(TurbulanceType, float, float, int, float, bool); - class FETurbulence : public FilterEffect { - public: - static PassRefPtr<FETurbulence> create(TurbulanceType, const float&, const float&, const int&, const float&, - bool); + TurbulanceType type() const; + void setType(TurbulanceType); - TurbulanceType type() const; - void setType(TurbulanceType); + float baseFrequencyY() const; + void setBaseFrequencyY(float); - float baseFrequencyY() const; - void setBaseFrequencyY(float); + float baseFrequencyX() const; + void setBaseFrequencyX(float); - float baseFrequencyX() const; - void setBaseFrequencyX(float); + float seed() const; + void setSeed(float); - float seed() const; - void setSeed(float); + int numOctaves() const; + void setNumOctaves(bool); - int numOctaves() const; - void setNumOctaves(bool); + bool stitchTiles() const; + void setStitchTiles(bool); - bool stitchTiles() const; - void setStitchTiles(bool); + void apply(Filter*); + void dump(); + TextStream& externalRepresentation(TextStream&, int indent) const; - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; +private: + static const int s_blockSize = 256; + static const int s_blockMask = s_blockSize - 1; - private: - FETurbulence(TurbulanceType, const float&, const float&, const int&, const float&, - bool); + struct PaintingData { + long seed; + int latticeSelector[2 * s_blockSize + 2]; + float gradient[4][2 * s_blockSize + 2][2]; + int width; // How much to subtract to wrap for stitching. + int height; + int wrapX; // Minimum value to wrap. + int wrapY; + int channel; + IntSize filterSize; - TurbulanceType m_type; - float m_baseFrequencyX; - float m_baseFrequencyY; - int m_numOctaves; - float m_seed; - bool m_stitchTiles; + PaintingData(long paintingSeed, const IntSize& paintingSize); + inline long random(); }; + FETurbulence(TurbulanceType, float, float, int, float, bool); + + inline void initPaint(PaintingData&); + float noise2D(PaintingData&, const FloatPoint&); + unsigned char calculateTurbulenceValueForPoint(PaintingData&, const FloatPoint&); + + TurbulanceType m_type; + float m_baseFrequencyX; + float m_baseFrequencyY; + int m_numOctaves; + float m_seed; + bool m_stitchTiles; +}; + } // namespace WebCore #endif // ENABLE(SVG) && ENABLE(FILTERS) |