diff options
Diffstat (limited to 'WebCore/svg')
51 files changed, 1091 insertions, 171 deletions
diff --git a/WebCore/svg/SVGAllInOne.cpp b/WebCore/svg/SVGAllInOne.cpp index e9008dc..c1bf281 100644 --- a/WebCore/svg/SVGAllInOne.cpp +++ b/WebCore/svg/SVGAllInOne.cpp @@ -54,6 +54,7 @@ #include "SVGFEColorMatrixElement.cpp" #include "SVGFEComponentTransferElement.cpp" #include "SVGFECompositeElement.cpp" +#include "SVGFEConvolveMatrixElement.cpp" #include "SVGFEDiffuseLightingElement.cpp" #include "SVGFEDisplacementMapElement.cpp" #include "SVGFEDistantLightElement.cpp" diff --git a/WebCore/svg/SVGCircleElement.cpp b/WebCore/svg/SVGCircleElement.cpp index 135a96f..c90b8e3 100644 --- a/WebCore/svg/SVGCircleElement.cpp +++ b/WebCore/svg/SVGCircleElement.cpp @@ -71,6 +71,13 @@ void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isLengthAttribute = attrName == SVGNames::cxAttr + || attrName == SVGNames::cyAttr + || attrName == SVGNames::rAttr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderPath* renderer = static_cast<RenderPath*>(this->renderer()); if (!renderer) return; @@ -81,9 +88,7 @@ void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::cxAttr - || attrName == SVGNames::cyAttr - || attrName == SVGNames::rAttr) { + if (isLengthAttribute) { renderer->setNeedsPathUpdate(); renderer->setNeedsLayout(true); return; @@ -122,9 +127,11 @@ Path SVGCircleElement::toPathData() const return Path::createCircle(FloatPoint(cx().value(this), cy().value(this)), r().value(this)); } -bool SVGCircleElement::hasRelativeValues() const +bool SVGCircleElement::selfHasRelativeLengths() const { - return (cx().isRelative() || cy().isRelative() || r().isRelative()); + return cx().isRelative() + || cy().isRelative() + || r().isRelative(); } } diff --git a/WebCore/svg/SVGCircleElement.h b/WebCore/svg/SVGCircleElement.h index eb2714c..0ffb934 100644 --- a/WebCore/svg/SVGCircleElement.h +++ b/WebCore/svg/SVGCircleElement.h @@ -45,10 +45,9 @@ namespace WebCore { virtual Path toPathData() const; - protected: - virtual bool hasRelativeValues() const; - private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::cxAttr, SVGLength, Cx, cx) DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::cyAttr, SVGLength, Cy, cy) DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::rAttr, SVGLength, R, r) diff --git a/WebCore/svg/SVGDocumentExtensions.cpp b/WebCore/svg/SVGDocumentExtensions.cpp index 7b285eb..fc31551 100644 --- a/WebCore/svg/SVGDocumentExtensions.cpp +++ b/WebCore/svg/SVGDocumentExtensions.cpp @@ -37,7 +37,7 @@ #include "SVGSMILElement.h" #include "SVGSVGElement.h" #include "SMILTimeContainer.h" -#include "XMLDocumentParser.h" +#include "ScriptableDocumentParser.h" #include "ScriptController.h" namespace WebCore { @@ -125,16 +125,29 @@ bool SVGDocumentExtensions::sampleAnimationAtTime(const String& elementId, SVGSM return true; } +// FIXME: Callers should probably use ScriptController::eventHandlerLineNumber() +static int parserLineNumber(Document* document) +{ + ScriptableDocumentParser* parser = document->scriptableDocumentParser(); + if (!parser) + return 1; + return parser->lineNumber(); +} + +static void reportMessage(Document* document, MessageLevel level, const String& message) +{ + if (Frame* frame = document->frame()) + frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, level, message, parserLineNumber(document), String()); +} + void SVGDocumentExtensions::reportWarning(const String& message) { - if (Frame* frame = m_doc->frame()) - frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Warning: " + message, m_doc->parser() ? m_doc->parser()->lineNumber() : 1, String()); + reportMessage(m_doc, WarningMessageLevel, "Warning: " + message); } void SVGDocumentExtensions::reportError(const String& message) { - if (Frame* frame = m_doc->frame()) - frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Error: " + message, m_doc->parser() ? m_doc->parser()->lineNumber() : 1, String()); + reportMessage(m_doc, ErrorMessageLevel, "Error: " + message); } void SVGDocumentExtensions::addPendingResource(const AtomicString& id, SVGStyledElement* obj) diff --git a/WebCore/svg/SVGElement.cpp b/WebCore/svg/SVGElement.cpp index 293e4d6..b262e45 100644 --- a/WebCore/svg/SVGElement.cpp +++ b/WebCore/svg/SVGElement.cpp @@ -301,6 +301,15 @@ void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) return; StyledElement::attributeChanged(attr, preserveDecls); + + // When an animated SVG property changes through SVG DOM, svgAttributeChanged() is called, not attributeChanged(). + // Next time someone tries to access the XML attributes, the synchronization code starts. During that synchronization + // SVGAnimatedPropertySynchronizer may call NamedNodeMap::removeAttribute(), which in turn calls attributeChanged(). + // At this point we're not allowed to call svgAttributeChanged() again - it may lead to extra work being done, or crashes + // see bug https://bugs.webkit.org/show_bug.cgi?id=40994. + if (isSynchronizingSVGAttributes()) + return; + svgAttributeChanged(attr->name()); } diff --git a/WebCore/svg/SVGEllipseElement.cpp b/WebCore/svg/SVGEllipseElement.cpp index d811b56..5509c2d 100644 --- a/WebCore/svg/SVGEllipseElement.cpp +++ b/WebCore/svg/SVGEllipseElement.cpp @@ -76,6 +76,14 @@ void SVGEllipseElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isLengthAttribute = attrName == SVGNames::cxAttr + || attrName == SVGNames::cyAttr + || attrName == SVGNames::rxAttr + || attrName == SVGNames::ryAttr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderPath* renderer = static_cast<RenderPath*>(this->renderer()); if (!renderer) return; @@ -86,10 +94,7 @@ void SVGEllipseElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::cxAttr - || attrName == SVGNames::cyAttr - || attrName == SVGNames::rxAttr - || attrName == SVGNames::ryAttr) { + if (isLengthAttribute) { renderer->setNeedsPathUpdate(); renderer->setNeedsLayout(true); return; @@ -132,10 +137,12 @@ Path SVGEllipseElement::toPathData() const rx().value(this), ry().value(this)); } -bool SVGEllipseElement::hasRelativeValues() const +bool SVGEllipseElement::selfHasRelativeLengths() const { - return (cx().isRelative() || cy().isRelative() || - rx().isRelative() || ry().isRelative()); + return cx().isRelative() + || cy().isRelative() + || rx().isRelative() + || ry().isRelative(); } } diff --git a/WebCore/svg/SVGEllipseElement.h b/WebCore/svg/SVGEllipseElement.h index 4b2c38d..5a5060e 100644 --- a/WebCore/svg/SVGEllipseElement.h +++ b/WebCore/svg/SVGEllipseElement.h @@ -45,10 +45,9 @@ namespace WebCore { virtual Path toPathData() const; - protected: - virtual bool hasRelativeValues() const; - private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::cxAttr, SVGLength, Cx, cx) DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::cyAttr, SVGLength, Cy, cy) DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::rxAttr, SVGLength, Rx, rx) diff --git a/WebCore/svg/SVGFEConvolveMatrixElement.cpp b/WebCore/svg/SVGFEConvolveMatrixElement.cpp new file mode 100644 index 0000000..63d1365 --- /dev/null +++ b/WebCore/svg/SVGFEConvolveMatrixElement.cpp @@ -0,0 +1,161 @@ +/* + Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "SVGFEConvolveMatrixElement.h" + +#include "Attr.h" +#include "FloatPoint.h" +#include "FloatSize.h" +#include "IntPoint.h" +#include "IntSize.h" +#include "SVGNames.h" +#include "SVGNumberList.h" +#include "SVGParserUtilities.h" + +#include <math.h> + +namespace WebCore { + +char SVGKernelUnitLengthXAttrIdentifier[] = "SVGKernelUnitLengthXAttr"; +char SVGKernelUnitLengthYAttrIdentifier[] = "SVGKernelUnitLengthYAttr"; + +SVGFEConvolveMatrixElement::SVGFEConvolveMatrixElement(const QualifiedName& tagName, Document* doc) + : SVGFilterPrimitiveStandardAttributes(tagName, doc) + , m_kernelMatrix(SVGNumberList::create(SVGNames::kernelMatrixAttr)) + , m_edgeMode(EDGEMODE_DUPLICATE) +{ +} + +SVGFEConvolveMatrixElement::~SVGFEConvolveMatrixElement() +{ +} + +void SVGFEConvolveMatrixElement::parseMappedAttribute(Attribute* attr) +{ + const String& value = attr->value(); + if (attr->name() == SVGNames::inAttr) + setIn1BaseValue(value); + else if (attr->name() == SVGNames::orderAttr) { + float x, y; + if (parseNumberOptionalNumber(value, x, y)) { + setOrderXBaseValue(x); + setOrderYBaseValue(y); + } + } else if (attr->name() == SVGNames::edgeModeAttr) { + if (value == "duplicate") + setEdgeModeBaseValue(EDGEMODE_DUPLICATE); + else if (value == "wrap") + setEdgeModeBaseValue(EDGEMODE_WRAP); + else if (value == "none") + setEdgeModeBaseValue(EDGEMODE_NONE); + } else if (attr->name() == SVGNames::kernelMatrixAttr) + kernelMatrixBaseValue()->parse(value); + else if (attr->name() == SVGNames::divisorAttr) + setDivisorBaseValue(value.toFloat()); + else if (attr->name() == SVGNames::biasAttr) + setBiasBaseValue(value.toFloat()); + else if (attr->name() == SVGNames::targetXAttr) + setTargetXBaseValue(value.toUIntStrict()); + else if (attr->name() == SVGNames::targetYAttr) + setTargetYBaseValue(value.toUIntStrict()); + else if (attr->name() == SVGNames::kernelUnitLengthAttr) { + float x, y; + if (parseNumberOptionalNumber(value, x, y)) { + setKernelUnitLengthXBaseValue(x); + setKernelUnitLengthYBaseValue(y); + } + } else if (attr->name() == SVGNames::preserveAlphaAttr) { + if (value == "true") + setPreserveAlphaBaseValue(true); + else if (value == "false") + setPreserveAlphaBaseValue(false); + } else + SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr); +} + +void SVGFEConvolveMatrixElement::setOrder(float, float) +{ + // FIXME: Needs an implementation. +} + +void SVGFEConvolveMatrixElement::setKernelUnitLength(float, float) +{ + // FIXME: Needs an implementation. +} + +PassRefPtr<FilterEffect> SVGFEConvolveMatrixElement::build(SVGFilterBuilder* filterBuilder) +{ + FilterEffect* input1 = filterBuilder->getEffectById(in1()); + + if (!input1) + return 0; + + Vector<float> kernelMatrixValues; + SVGNumberList* numbers = kernelMatrix(); + + ExceptionCode ec = 0; + int numberOfItems = numbers->numberOfItems(); + for (int i = 0; i < numberOfItems; ++i) + kernelMatrixValues.append(numbers->getItem(i, ec)); + + int orderXValue = orderX(); + int orderYValue = orderY(); + if (!hasAttribute(SVGNames::orderAttr)) { + orderXValue = 3; + orderYValue = 3; + } + // The spec says this is a requirement, and should bail out if fails + if (orderXValue * orderYValue != numberOfItems) + return 0; + + int targetXValue = targetX(); + int targetYValue = targetY(); + if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue)) + return 0; + // The spec says the default value is: targetX = floor ( orderX / 2 )) + if (!hasAttribute(SVGNames::targetXAttr)) + targetXValue = static_cast<int>(floorf(orderXValue / 2)); + if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue)) + return 0; + // The spec says the default value is: targetY = floor ( orderY / 2 )) + if (!hasAttribute(SVGNames::targetYAttr)) + targetYValue = static_cast<int>(floorf(orderYValue / 2)); + + float divisorValue = divisor(); + if (hasAttribute(SVGNames::divisorAttr) && !divisorValue) + return 0; + if (!hasAttribute(SVGNames::divisorAttr)) { + for (int i = 0; i < numberOfItems; ++i) + divisorValue += kernelMatrixValues[i]; + if (!divisorValue) + divisorValue = 1; + } + + return FEConvolveMatrix::create( + input1, IntSize(orderXValue, orderYValue), divisorValue, + bias(), IntPoint(targetXValue, targetYValue), static_cast<EdgeModeType>(edgeMode()), + FloatPoint(kernelUnitLengthX(), kernelUnitLengthX()), preserveAlpha(), kernelMatrixValues); +} + +} // namespace WebCore + +#endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGFEConvolveMatrixElement.h b/WebCore/svg/SVGFEConvolveMatrixElement.h new file mode 100644 index 0000000..56ae788 --- /dev/null +++ b/WebCore/svg/SVGFEConvolveMatrixElement.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SVGFEConvolveMatrixElement_h +#define SVGFEConvolveMatrixElement_h + +#if ENABLE(SVG) && ENABLE(FILTERS) +#include "SVGFEConvolveMatrix.h" +#include "SVGFilterPrimitiveStandardAttributes.h" +#include "SVGNumberList.h" + +namespace WebCore { + +class SVGFEConvolveMatrixElement : public SVGFilterPrimitiveStandardAttributes { +public: + SVGFEConvolveMatrixElement(const QualifiedName&, Document*); + virtual ~SVGFEConvolveMatrixElement(); + + void setOrder(float orderX, float orderY); + void setKernelUnitLength(float kernelUnitLengthX, float kernelUnitLengthY); + + virtual void parseMappedAttribute(Attribute*); + virtual PassRefPtr<FilterEffect> build(SVGFilterBuilder*); + +private: + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::inAttr, String, In1, in1) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::orderXAttr, long, OrderX, orderX) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::orderYAttr, long, OrderY, orderY) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::kernelMatrixAttr, SVGNumberList*, KernelMatrix, kernelMatrix) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::divisorAttr, float, Divisor, divisor) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::biasAttr, float, Bias, bias) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::targetXAttr, long, TargetX, targetX) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::targetYAttr, long, TargetY, targetY) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::operatorAttr, int, EdgeMode, edgeMode) + DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, SVGKernelUnitLengthXIdentifier, float, KernelUnitLengthX, kernelUnitLengthX) + DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGFEConvolveMatrixElement, SVGNames::kernelUnitLengthAttr, SVGKernelUnitLengthYIdentifier, float, KernelUnitLengthY, kernelUnitLengthY) + DECLARE_ANIMATED_PROPERTY(SVGFEConvolveMatrixElement, SVGNames::preserveAlphaAttr, bool, PreserveAlpha, preserveAlpha) +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif diff --git a/WebCore/svg/SVGFEConvolveMatrixElement.idl b/WebCore/svg/SVGFEConvolveMatrixElement.idl new file mode 100644 index 0000000..5be4c33 --- /dev/null +++ b/WebCore/svg/SVGFEConvolveMatrixElement.idl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module svg { + + interface [Conditional=SVG&FILTERS, GenerateConstructor] SVGFEConvolveMatrixElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { + // Edge Mode Values + const unsigned short SVG_EDGEMODE_UNKNOWN = 0; + const unsigned short SVG_EDGEMODE_DUPLICATE = 1; + const unsigned short SVG_EDGEMODE_WRAP = 2; + const unsigned short SVG_EDGEMODE_NONE = 3; + + readonly attribute SVGAnimatedString in1; + readonly attribute SVGAnimatedInteger orderX; + readonly attribute SVGAnimatedInteger orderY; + readonly attribute SVGAnimatedNumberList kernelMatrix; + readonly attribute SVGAnimatedNumber divisor; + readonly attribute SVGAnimatedNumber bias; + readonly attribute SVGAnimatedInteger targetX; + readonly attribute SVGAnimatedInteger targetY; + readonly attribute SVGAnimatedEnumeration edgeMode; + readonly attribute SVGAnimatedNumber kernelUnitLengthX; + readonly attribute SVGAnimatedNumber kernelUnitLengthY; + readonly attribute SVGAnimatedBoolean preserveAlpha; + }; + +} diff --git a/WebCore/svg/SVGFEDiffuseLightingElement.cpp b/WebCore/svg/SVGFEDiffuseLightingElement.cpp index efe4d5e..fdb3b52 100644 --- a/WebCore/svg/SVGFEDiffuseLightingElement.cpp +++ b/WebCore/svg/SVGFEDiffuseLightingElement.cpp @@ -55,7 +55,7 @@ void SVGFEDiffuseLightingElement::parseMappedAttribute(Attribute* attr) else if (attr->name() == SVGNames::surfaceScaleAttr) setSurfaceScaleBaseValue(value.toFloat()); else if (attr->name() == SVGNames::diffuseConstantAttr) - setDiffuseConstantBaseValue(value.toInt()); + setDiffuseConstantBaseValue(value.toFloat()); else if (attr->name() == SVGNames::kernelUnitLengthAttr) { float x, y; if (parseNumberOptionalNumber(value, x, y)) { diff --git a/WebCore/svg/SVGFEImageElement.cpp b/WebCore/svg/SVGFEImageElement.cpp index 7fa4c51..84f8734 100644 --- a/WebCore/svg/SVGFEImageElement.cpp +++ b/WebCore/svg/SVGFEImageElement.cpp @@ -28,6 +28,7 @@ #include "CachedImage.h" #include "DocLoader.h" #include "Document.h" +#include "RenderObject.h" #include "SVGLength.h" #include "SVGNames.h" #include "SVGPreserveAspectRatio.h" @@ -123,7 +124,7 @@ PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*) IntRect targetRect = enclosingIntRect(renderer->objectBoundingBox()); m_targetImage = ImageBuffer::create(targetRect.size(), LinearRGB); - renderSubtreeToImage(m_targetImage.get(), renderer); + SVGRenderSupport::renderSubtreeToImage(m_targetImage.get(), renderer); } return FEImage::create(m_targetImage ? m_targetImage->image() : m_cachedImage->image(), preserveAspectRatio()); diff --git a/WebCore/svg/SVGFilterElement.cpp b/WebCore/svg/SVGFilterElement.cpp index f3ed90c..b86b8c4 100644 --- a/WebCore/svg/SVGFilterElement.cpp +++ b/WebCore/svg/SVGFilterElement.cpp @@ -105,6 +105,30 @@ void SVGFilterElement::parseMappedAttribute(Attribute* attr) } } +void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName) +{ + SVGStyledElement::svgAttributeChanged(attrName); + + bool invalidateClients = false; + if (attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr) { + invalidateClients = true; + updateRelativeLengthsInformation(); + } + + if (invalidateClients + || attrName == SVGNames::filterUnitsAttr + || attrName == SVGNames::primitiveUnitsAttr + || attrName == SVGNames::filterResAttr + || SVGURIReference::isKnownAttribute(attrName) + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGStyledElement::isKnownAttribute(attrName)) + invalidateResourceClients(); +} + void SVGFilterElement::synchronizeProperty(const QualifiedName& attrName) { SVGStyledElement::synchronizeProperty(attrName); @@ -165,6 +189,15 @@ RenderObject* SVGFilterElement::createRenderer(RenderArena* arena, RenderStyle*) { return new (arena) RenderSVGResourceFilter(this); } + +bool SVGFilterElement::selfHasRelativeLengths() const +{ + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative(); +} + } #endif diff --git a/WebCore/svg/SVGFilterElement.h b/WebCore/svg/SVGFilterElement.h index 3dad97f..85679c7 100644 --- a/WebCore/svg/SVGFilterElement.h +++ b/WebCore/svg/SVGFilterElement.h @@ -47,11 +47,14 @@ public: FloatRect filterBoundingBox(const FloatRect&) const; virtual void parseMappedAttribute(Attribute*); + virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::filterUnitsAttr, int, FilterUnits, filterUnits) DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::primitiveUnitsAttr, int, PrimitiveUnits, primitiveUnits) DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::xAttr, SVGLength, X, x) diff --git a/WebCore/svg/SVGForeignObjectElement.cpp b/WebCore/svg/SVGForeignObjectElement.cpp index e3e8fab..d6bf1cf 100644 --- a/WebCore/svg/SVGForeignObjectElement.cpp +++ b/WebCore/svg/SVGForeignObjectElement.cpp @@ -76,6 +76,14 @@ void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isLengthAttribute = attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderObject* renderer = this->renderer(); if (!renderer) return; @@ -86,10 +94,7 @@ void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::xAttr - || attrName == SVGNames::yAttr - || attrName == SVGNames::widthAttr - || attrName == SVGNames::heightAttr + if (isLengthAttribute || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) @@ -139,6 +144,14 @@ bool SVGForeignObjectElement::childShouldCreateRenderer(Node* child) const return StyledElement::childShouldCreateRenderer(child); } +bool SVGForeignObjectElement::selfHasRelativeLengths() const +{ + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative(); +} + } #endif diff --git a/WebCore/svg/SVGForeignObjectElement.h b/WebCore/svg/SVGForeignObjectElement.h index 2cd60a4..86edc08 100644 --- a/WebCore/svg/SVGForeignObjectElement.h +++ b/WebCore/svg/SVGForeignObjectElement.h @@ -48,6 +48,8 @@ namespace WebCore { virtual RenderObject* createRenderer(RenderArena* arena, RenderStyle* style); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::xAttr, SVGLength, X, x) DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::yAttr, SVGLength, Y, y) DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::widthAttr, SVGLength, Width, width) diff --git a/WebCore/svg/SVGImageElement.cpp b/WebCore/svg/SVGImageElement.cpp index e67c337..711e9f3 100644 --- a/WebCore/svg/SVGImageElement.cpp +++ b/WebCore/svg/SVGImageElement.cpp @@ -91,6 +91,14 @@ void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGURIReference::isKnownAttribute(attrName)) m_imageLoader.updateFromElementIgnoringPreviousError(); + bool isLengthAttribute = attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderObject* renderer = this->renderer(); if (!renderer) return; @@ -101,10 +109,7 @@ void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::xAttr - || attrName == SVGNames::yAttr - || attrName == SVGNames::widthAttr - || attrName == SVGNames::heightAttr + if (isLengthAttribute || attrName == SVGNames::preserveAspectRatioAttr || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) @@ -143,10 +148,12 @@ void SVGImageElement::synchronizeProperty(const QualifiedName& attrName) synchronizeHref(); } -bool SVGImageElement::hasRelativeValues() const +bool SVGImageElement::selfHasRelativeLengths() const { - return (x().isRelative() || width().isRelative() || - y().isRelative() || height().isRelative()); + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative(); } RenderObject* SVGImageElement::createRenderer(RenderArena* arena, RenderStyle*) diff --git a/WebCore/svg/SVGImageElement.h b/WebCore/svg/SVGImageElement.h index 06e3bdb..da3800a 100644 --- a/WebCore/svg/SVGImageElement.h +++ b/WebCore/svg/SVGImageElement.h @@ -59,9 +59,9 @@ namespace WebCore { protected: virtual bool haveLoadedRequiredResources(); - virtual bool hasRelativeValues() const; private: + virtual bool selfHasRelativeLengths() const; virtual void willMoveToNewOwnerDocument(); DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::xAttr, SVGLength, X, x) diff --git a/WebCore/svg/SVGLineElement.cpp b/WebCore/svg/SVGLineElement.cpp index a840858..c6e5e04 100644 --- a/WebCore/svg/SVGLineElement.cpp +++ b/WebCore/svg/SVGLineElement.cpp @@ -72,6 +72,14 @@ void SVGLineElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isLengthAttribute = attrName == SVGNames::x1Attr + || attrName == SVGNames::y1Attr + || attrName == SVGNames::x2Attr + || attrName == SVGNames::y2Attr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderPath* renderer = static_cast<RenderPath*>(this->renderer()); if (!renderer) return; @@ -82,10 +90,7 @@ void SVGLineElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::x1Attr - || attrName == SVGNames::y1Attr - || attrName == SVGNames::x2Attr - || attrName == SVGNames::y2Attr) { + if (isLengthAttribute) { renderer->setNeedsPathUpdate(); renderer->setNeedsLayout(true); return; @@ -128,10 +133,12 @@ Path SVGLineElement::toPathData() const FloatPoint(x2().value(this), y2().value(this))); } -bool SVGLineElement::hasRelativeValues() const +bool SVGLineElement::selfHasRelativeLengths() const { - return (x1().isRelative() || y1().isRelative() || - x2().isRelative() || y2().isRelative()); + return x1().isRelative() + || y1().isRelative() + || x2().isRelative() + || y2().isRelative(); } } diff --git a/WebCore/svg/SVGLineElement.h b/WebCore/svg/SVGLineElement.h index 1fbe421..d07ee6d 100644 --- a/WebCore/svg/SVGLineElement.h +++ b/WebCore/svg/SVGLineElement.h @@ -49,10 +49,9 @@ namespace WebCore { virtual bool supportsMarkers() const { return true; } - protected: - virtual bool hasRelativeValues() const; - private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::x1Attr, SVGLength, X1, x1) DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::y1Attr, SVGLength, Y1, y1) DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::x2Attr, SVGLength, X2, x2) diff --git a/WebCore/svg/SVGLinearGradientElement.cpp b/WebCore/svg/SVGLinearGradientElement.cpp index 29ee85e..d95c084 100644 --- a/WebCore/svg/SVGLinearGradientElement.cpp +++ b/WebCore/svg/SVGLinearGradientElement.cpp @@ -74,8 +74,10 @@ void SVGLinearGradientElement::svgAttributeChanged(const QualifiedName& attrName if (attrName == SVGNames::x1Attr || attrName == SVGNames::y1Attr || attrName == SVGNames::x2Attr - || attrName == SVGNames::y2Attr) + || attrName == SVGNames::y2Attr) { + updateRelativeLengthsInformation(); invalidateResourceClients(); + } } void SVGLinearGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -176,6 +178,14 @@ void SVGLinearGradientElement::calculateStartEndPoints(const LinearGradientAttri } } +bool SVGLinearGradientElement::selfHasRelativeLengths() const +{ + return x1().isRelative() + || y1().isRelative() + || x2().isRelative() + || y2().isRelative(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGLinearGradientElement.h b/WebCore/svg/SVGLinearGradientElement.h index b248c48..62b972f 100644 --- a/WebCore/svg/SVGLinearGradientElement.h +++ b/WebCore/svg/SVGLinearGradientElement.h @@ -44,6 +44,8 @@ namespace WebCore { void calculateStartEndPoints(const LinearGradientAttributes&, FloatPoint& startPoint, FloatPoint& endPoint); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::x1Attr, SVGLength, X1, x1) DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::y1Attr, SVGLength, Y1, y1) DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::x2Attr, SVGLength, X2, x2) diff --git a/WebCore/svg/SVGMarkerElement.cpp b/WebCore/svg/SVGMarkerElement.cpp index 9ffbd8d..01faf21 100644 --- a/WebCore/svg/SVGMarkerElement.cpp +++ b/WebCore/svg/SVGMarkerElement.cpp @@ -104,13 +104,22 @@ void SVGMarkerElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); - if (attrName == SVGNames::markerUnitsAttr || attrName == SVGNames::refXAttr || - attrName == SVGNames::refYAttr || attrName == SVGNames::markerWidthAttr || - attrName == SVGNames::markerHeightAttr || attrName == SVGNames::orientAttr || - SVGLangSpace::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGFitToViewBox::isKnownAttribute(attrName) || - SVGStyledElement::isKnownAttribute(attrName)) + bool invalidateClients = false; + if (attrName == SVGNames::refXAttr + || attrName == SVGNames::refYAttr + || attrName == SVGNames::markerWidthAttr + || attrName == SVGNames::markerHeightAttr) { + invalidateClients = true; + updateRelativeLengthsInformation(); + } + + if (invalidateClients + || attrName == SVGNames::markerUnitsAttr + || attrName == SVGNames::orientAttr + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGFitToViewBox::isKnownAttribute(attrName) + || SVGStyledElement::isKnownAttribute(attrName)) invalidateResourceClients(); } @@ -182,6 +191,14 @@ RenderObject* SVGMarkerElement::createRenderer(RenderArena* arena, RenderStyle*) return new (arena) RenderSVGResourceMarker(this); } +bool SVGMarkerElement::selfHasRelativeLengths() const +{ + return refX().isRelative() + || refY().isRelative() + || markerWidth().isRelative() + || markerHeight().isRelative(); +} + } #endif diff --git a/WebCore/svg/SVGMarkerElement.h b/WebCore/svg/SVGMarkerElement.h index bd397b5..689a7e5 100644 --- a/WebCore/svg/SVGMarkerElement.h +++ b/WebCore/svg/SVGMarkerElement.h @@ -69,6 +69,8 @@ public: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::refXAttr, SVGLength, RefX, refX) DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::refYAttr, SVGLength, RefY, refY) DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::markerWidthAttr, SVGLength, MarkerWidth, markerWidth) diff --git a/WebCore/svg/SVGMaskElement.cpp b/WebCore/svg/SVGMaskElement.cpp index 07afe08..1376480 100644 --- a/WebCore/svg/SVGMaskElement.cpp +++ b/WebCore/svg/SVGMaskElement.cpp @@ -96,14 +96,23 @@ void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); - if (attrName == SVGNames::maskUnitsAttr || attrName == SVGNames::maskContentUnitsAttr || - attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || - attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr || - SVGURIReference::isKnownAttribute(attrName) || - SVGTests::isKnownAttribute(attrName) || - SVGLangSpace::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGStyledElement::isKnownAttribute(attrName)) + bool invalidateClients = false; + if (attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr) { + invalidateClients = true; + updateRelativeLengthsInformation(); + } + + if (invalidateClients + || attrName == SVGNames::maskUnitsAttr + || attrName == SVGNames::maskContentUnitsAttr + || SVGURIReference::isKnownAttribute(attrName) + || SVGTests::isKnownAttribute(attrName) + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGStyledElement::isKnownAttribute(attrName)) invalidateResourceClients(); } @@ -165,6 +174,14 @@ RenderObject* SVGMaskElement::createRenderer(RenderArena* arena, RenderStyle*) return new (arena) RenderSVGResourceMasker(this); } +bool SVGMaskElement::selfHasRelativeLengths() const +{ + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGMaskElement.h b/WebCore/svg/SVGMaskElement.h index 79e0bf0..467128d 100644 --- a/WebCore/svg/SVGMaskElement.h +++ b/WebCore/svg/SVGMaskElement.h @@ -51,6 +51,8 @@ namespace WebCore { virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::maskUnitsAttr, int, MaskUnits, maskUnits) DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::maskContentUnitsAttr, int, MaskContentUnits, maskContentUnits) DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::xAttr, SVGLength, X, x) diff --git a/WebCore/svg/SVGPatternElement.cpp b/WebCore/svg/SVGPatternElement.cpp index fe889e3..e258946 100644 --- a/WebCore/svg/SVGPatternElement.cpp +++ b/WebCore/svg/SVGPatternElement.cpp @@ -120,13 +120,19 @@ void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); - if (attrName == SVGNames::patternUnitsAttr - || attrName == SVGNames::patternContentUnitsAttr - || attrName == SVGNames::patternTransformAttr - || attrName == SVGNames::xAttr + bool invalidateClients = false; + if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || attrName == SVGNames::widthAttr - || attrName == SVGNames::heightAttr + || attrName == SVGNames::heightAttr) { + invalidateClients = true; + updateRelativeLengthsInformation(); + } + + if (invalidateClients + || attrName == SVGNames::patternUnitsAttr + || attrName == SVGNames::patternContentUnitsAttr + || attrName == SVGNames::patternTransformAttr || SVGURIReference::isKnownAttribute(attrName) || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) @@ -239,6 +245,14 @@ PatternAttributes SVGPatternElement::collectPatternProperties() const return attributes; } +bool SVGPatternElement::selfHasRelativeLengths() const +{ + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGPatternElement.h b/WebCore/svg/SVGPatternElement.h index 56f7238..105b8e2 100644 --- a/WebCore/svg/SVGPatternElement.h +++ b/WebCore/svg/SVGPatternElement.h @@ -58,6 +58,8 @@ namespace WebCore { PatternAttributes collectPatternProperties() const; private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::xAttr, SVGLength, X, x) DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::yAttr, SVGLength, Y, y) DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::widthAttr, SVGLength, Width, width) diff --git a/WebCore/svg/SVGPolyElement.cpp b/WebCore/svg/SVGPolyElement.cpp index 053b700..6f88b22 100644 --- a/WebCore/svg/SVGPolyElement.cpp +++ b/WebCore/svg/SVGPolyElement.cpp @@ -67,10 +67,8 @@ void SVGPolyElement::parseMappedAttribute(Attribute* attr) ExceptionCode ec = 0; points()->clear(ec); - if (!pointsListFromSVGData(points(), value)) { - points()->clear(ec); + if (!pointsListFromSVGData(points(), value)) document()->accessSVGExtensions()->reportError("Problem parsing points=\"" + value + "\""); - } } else { if (SVGTests::parseMappedAttribute(attr)) return; diff --git a/WebCore/svg/SVGRadialGradientElement.cpp b/WebCore/svg/SVGRadialGradientElement.cpp index 14e0163..2a97b9d 100644 --- a/WebCore/svg/SVGRadialGradientElement.cpp +++ b/WebCore/svg/SVGRadialGradientElement.cpp @@ -81,8 +81,10 @@ void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName || attrName == SVGNames::cyAttr || attrName == SVGNames::fxAttr || attrName == SVGNames::fyAttr - || attrName == SVGNames::rAttr) + || attrName == SVGNames::rAttr) { + updateRelativeLengthsInformation(); invalidateResourceClients(); + } } void SVGRadialGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -214,6 +216,15 @@ void SVGRadialGradientElement::calculateFocalCenterPointsAndRadius(const RadialG } } +bool SVGRadialGradientElement::selfHasRelativeLengths() const +{ + return cy().isRelative() + || cy().isRelative() + || r().isRelative() + || fx().isRelative() + || fy().isRelative(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGRadialGradientElement.h b/WebCore/svg/SVGRadialGradientElement.h index 0db08a3..8debc9c 100644 --- a/WebCore/svg/SVGRadialGradientElement.h +++ b/WebCore/svg/SVGRadialGradientElement.h @@ -44,6 +44,8 @@ namespace WebCore { void calculateFocalCenterPointsAndRadius(const RadialGradientAttributes&, FloatPoint& focalPoint, FloatPoint& centerPoint, float& radius); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::cxAttr, SVGLength, Cx, cx) DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::cyAttr, SVGLength, Cy, cy) DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::rAttr, SVGLength, R, r) diff --git a/WebCore/svg/SVGRectElement.cpp b/WebCore/svg/SVGRectElement.cpp index b4dc624..3e559ed 100644 --- a/WebCore/svg/SVGRectElement.cpp +++ b/WebCore/svg/SVGRectElement.cpp @@ -85,6 +85,16 @@ void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isLengthAttribute = attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr + || attrName == SVGNames::rxAttr + || attrName == SVGNames::ryAttr; + + if (isLengthAttribute) + updateRelativeLengthsInformation(); + RenderPath* renderer = static_cast<RenderPath*>(this->renderer()); if (!renderer) return; @@ -95,12 +105,7 @@ void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::xAttr - || attrName == SVGNames::yAttr - || attrName == SVGNames::widthAttr - || attrName == SVGNames::heightAttr - || attrName == SVGNames::rxAttr - || attrName == SVGNames::ryAttr) { + if (isLengthAttribute) { renderer->setNeedsPathUpdate(); renderer->setNeedsLayout(true); return; @@ -158,11 +163,14 @@ Path SVGRectElement::toPathData() const return Path::createRectangle(rect); } -bool SVGRectElement::hasRelativeValues() const +bool SVGRectElement::selfHasRelativeLengths() const { - return (x().isRelative() || width().isRelative() || - y().isRelative() || height().isRelative() || - rx().isRelative() || ry().isRelative()); + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative() + || rx().isRelative() + || ry().isRelative(); } } diff --git a/WebCore/svg/SVGRectElement.h b/WebCore/svg/SVGRectElement.h index 16f8408..4aafc13 100644 --- a/WebCore/svg/SVGRectElement.h +++ b/WebCore/svg/SVGRectElement.h @@ -45,10 +45,9 @@ namespace WebCore { virtual Path toPathData() const; - protected: - virtual bool hasRelativeValues() const; - private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::xAttr, SVGLength, X, x) DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::yAttr, SVGLength, Y, y) DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::widthAttr, SVGLength, Width, width) diff --git a/WebCore/svg/SVGSVGElement.cpp b/WebCore/svg/SVGSVGElement.cpp index 154ad7a..a719323 100644 --- a/WebCore/svg/SVGSVGElement.cpp +++ b/WebCore/svg/SVGSVGElement.cpp @@ -294,21 +294,32 @@ void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName) // Thus the CSS length value for width is not updated, and width() calcWidth() // calculations on RenderSVGRoot will be wrong. // https://bugs.webkit.org/show_bug.cgi?id=25387 - if (attrName == SVGNames::widthAttr) + bool updateRelativeLengths = false; + if (attrName == SVGNames::widthAttr) { updateCSSForAttribute(this, attrName, CSSPropertyWidth, widthBaseValue()); - else if (attrName == SVGNames::heightAttr) + updateRelativeLengths = true; + } else if (attrName == SVGNames::heightAttr) { updateCSSForAttribute(this, attrName, CSSPropertyHeight, heightBaseValue()); + updateRelativeLengths = true; + } + + if (updateRelativeLengths + || attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || SVGFitToViewBox::isKnownAttribute(attrName)) { + updateRelativeLengths = true; + updateRelativeLengthsInformation(); + } if (!renderer()) return; - if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || - SVGTests::isKnownAttribute(attrName) || - SVGLangSpace::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGFitToViewBox::isKnownAttribute(attrName) || - SVGZoomAndPan::isKnownAttribute(attrName) || - SVGStyledLocatableElement::isKnownAttribute(attrName)) + if (updateRelativeLengths + || SVGTests::isKnownAttribute(attrName) + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGZoomAndPan::isKnownAttribute(attrName) + || SVGStyledLocatableElement::isKnownAttribute(attrName)) renderer()->setNeedsLayout(true); } @@ -430,7 +441,7 @@ FloatRect SVGSVGElement::createSVGRect() SVGTransform SVGSVGElement::createSVGTransform() { - return SVGTransform(); + return SVGTransform(SVGTransform::SVG_TRANSFORM_MATRIX); } SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const AffineTransform& matrix) @@ -510,10 +521,13 @@ void SVGSVGElement::setCurrentTime(float /* seconds */) // FIXME: Implement me, bug 12073 } -bool SVGSVGElement::hasRelativeValues() const +bool SVGSVGElement::selfHasRelativeLengths() const { - return (x().isRelative() || width().isRelative() || - y().isRelative() || height().isRelative()); + return x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative() + || hasAttribute(SVGNames::viewBoxAttr); } bool SVGSVGElement::isOutermostSVG() const @@ -522,9 +536,11 @@ bool SVGSVGElement::isOutermostSVG() const if (!parentNode()) return true; +#if ENABLE(SVG_FOREIGN_OBJECT) // We act like an outermost SVG element, if we're a direct child of a <foreignObject> element. if (parentNode()->hasTagName(SVGNames::foreignObjectTag)) return true; +#endif // This is true whenever this is the outermost SVG, even if there are HTML elements outside it return !parentNode()->isSVGElement(); @@ -579,5 +595,3 @@ void SVGSVGElement::documentDidBecomeActive() } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/svg/SVGSVGElement.h b/WebCore/svg/SVGSVGElement.h index e941034..88ce958 100644 --- a/WebCore/svg/SVGSVGElement.h +++ b/WebCore/svg/SVGSVGElement.h @@ -128,9 +128,10 @@ namespace WebCore { void inheritViewAttributes(SVGViewElement*); bool isOutermostSVG() const; - virtual bool hasRelativeValues() const; private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::xAttr, SVGLength, X, x) DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::yAttr, SVGLength, Y, y) DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::widthAttr, SVGLength, Width, width) diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index 10cc793..1d7e4ec 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -251,7 +251,7 @@ void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName) invalidateResourcesInAncestorChain(); // If we're referencing resources, tell them we've changed. - deregisterFromResources(object); + RenderSVGResource::invalidateAllResourcesOfRenderer(object); } // Invalidate all SVGElementInstances associated with us @@ -295,6 +295,18 @@ void SVGStyledElement::invalidateResourceClients() object->toRenderSVGResourceContainer()->invalidateClients(); } +void SVGStyledElement::insertedIntoDocument() +{ + SVGElement::insertedIntoDocument(); + updateRelativeLengthsInformation(); +} + +void SVGStyledElement::removedFromDocument() +{ + updateRelativeLengthsInformation(false, this); + SVGElement::removedFromDocument(); +} + void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); @@ -354,6 +366,12 @@ AffineTransform SVGStyledElement::localCoordinateSpaceTransform(SVGLocatable::CT return AffineTransform(); } +void SVGStyledElement::updateRelativeLengthsInformation(bool, SVGStyledElement*) +{ + // FIXME: The actual code will land in a follow-up patch. + // See https://bugs.webkit.org/show_bug.cgi?id=41566 +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGStyledElement.h b/WebCore/svg/SVGStyledElement.h index cf78050..d0b52db 100644 --- a/WebCore/svg/SVGStyledElement.h +++ b/WebCore/svg/SVGStyledElement.h @@ -26,6 +26,7 @@ #include "SVGElement.h" #include "SVGLocatable.h" #include "SVGStylable.h" +#include <wtf/HashSet.h> namespace WebCore { @@ -39,7 +40,9 @@ namespace WebCore { virtual String title() const; - virtual bool hasRelativeValues() const { return false; } + // FIXME: The actual code will land in a follow-up patch. + bool hasRelativeLengths() const { return selfHasRelativeLengths(); } + virtual bool isStyled() const { return true; } virtual bool supportsMarkers() const { return false; } @@ -55,6 +58,8 @@ namespace WebCore { virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); // Centralized place to force a manual style resolution. Hacky but needed for now. @@ -70,6 +75,10 @@ namespace WebCore { protected: static int cssPropertyIdForSVGAttributeName(const QualifiedName&); + void updateRelativeLengthsInformation() { updateRelativeLengthsInformation(selfHasRelativeLengths(), this); } + void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGStyledElement*); + + virtual bool selfHasRelativeLengths() const { return false; } private: DECLARE_ANIMATED_PROPERTY(SVGStyledElement, HTMLNames::classAttr, String, ClassName, className) diff --git a/WebCore/svg/SVGSymbolElement.cpp b/WebCore/svg/SVGSymbolElement.cpp index 40dab91..2ee21f6 100644 --- a/WebCore/svg/SVGSymbolElement.cpp +++ b/WebCore/svg/SVGSymbolElement.cpp @@ -51,6 +51,14 @@ void SVGSymbolElement::parseMappedAttribute(Attribute* attr) SVGStyledElement::parseMappedAttribute(attr); } +void SVGSymbolElement::svgAttributeChanged(const QualifiedName& attrName) +{ + SVGStyledElement::svgAttributeChanged(attrName); + + if (attrName == SVGNames::viewBoxAttr) + updateRelativeLengthsInformation(); +} + void SVGSymbolElement::synchronizeProperty(const QualifiedName& attrName) { SVGStyledElement::synchronizeProperty(attrName); @@ -76,6 +84,11 @@ void SVGSymbolElement::synchronizeProperty(const QualifiedName& attrName) } } +bool SVGSymbolElement::selfHasRelativeLengths() const +{ + return hasAttribute(SVGNames::viewBoxAttr); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGSymbolElement.h b/WebCore/svg/SVGSymbolElement.h index 9db81c4..7a7ef87 100644 --- a/WebCore/svg/SVGSymbolElement.h +++ b/WebCore/svg/SVGSymbolElement.h @@ -38,10 +38,13 @@ namespace WebCore { virtual ~SVGSymbolElement(); virtual void parseMappedAttribute(Attribute*); + virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); virtual bool rendererIsNeeded(RenderStyle*) { return false; } private: + virtual bool selfHasRelativeLengths() const; + // SVGExternalResourcesRequired DECLARE_ANIMATED_PROPERTY(SVGSymbolElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired) diff --git a/WebCore/svg/SVGTextContentElement.cpp b/WebCore/svg/SVGTextContentElement.cpp index 12b9b31..234c03a 100644 --- a/WebCore/svg/SVGTextContentElement.cpp +++ b/WebCore/svg/SVGTextContentElement.cpp @@ -217,6 +217,11 @@ bool SVGTextContentElement::isKnownAttribute(const QualifiedName& attrName) SVGStyledElement::isKnownAttribute(attrName)); } +bool SVGTextContentElement::selfHasRelativeLengths() const +{ + return textLength().isRelative(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGTextContentElement.h b/WebCore/svg/SVGTextContentElement.h index f73d5e4..44220b9 100644 --- a/WebCore/svg/SVGTextContentElement.h +++ b/WebCore/svg/SVGTextContentElement.h @@ -63,6 +63,9 @@ namespace WebCore { bool isKnownAttribute(const QualifiedName&); + protected: + virtual bool selfHasRelativeLengths() const; + private: DECLARE_ANIMATED_PROPERTY(SVGTextContentElement, SVGNames::textLengthAttr, SVGLength, TextLength, textLength) DECLARE_ANIMATED_PROPERTY(SVGTextContentElement, SVGNames::lengthAdjustAttr, int, LengthAdjust, lengthAdjust) diff --git a/WebCore/svg/SVGTextPathElement.cpp b/WebCore/svg/SVGTextPathElement.cpp index 4a2cea5..288edfd 100644 --- a/WebCore/svg/SVGTextPathElement.cpp +++ b/WebCore/svg/SVGTextPathElement.cpp @@ -69,6 +69,22 @@ void SVGTextPathElement::parseMappedAttribute(Attribute* attr) } } +void SVGTextPathElement::svgAttributeChanged(const QualifiedName& attrName) +{ + SVGTextContentElement::svgAttributeChanged(attrName); + + if (attrName == SVGNames::startOffsetAttr) + updateRelativeLengthsInformation(); + + if (!renderer()) + return; + + if (attrName == SVGNames::startOffsetAttr + || SVGTextContentElement::isKnownAttribute(attrName) + || SVGURIReference::isKnownAttribute(attrName)) + renderer()->setNeedsLayout(true); +} + void SVGTextPathElement::synchronizeProperty(const QualifiedName& attrName) { SVGTextContentElement::synchronizeProperty(attrName); @@ -110,7 +126,7 @@ bool SVGTextPathElement::childShouldCreateRenderer(Node* child) const void SVGTextPathElement::insertedIntoDocument() { - SVGElement::insertedIntoDocument(); + SVGTextContentElement::insertedIntoDocument(); String id = SVGURIReference::getTarget(href()); Element* targetElement = ownerDocument()->getElementById(id); @@ -120,6 +136,12 @@ void SVGTextPathElement::insertedIntoDocument() } } +bool SVGTextPathElement::selfHasRelativeLengths() const +{ + return startOffset().isRelative() + || SVGTextContentElement::selfHasRelativeLengths(); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGTextPathElement.h b/WebCore/svg/SVGTextPathElement.h index 943d795..4e7f914 100644 --- a/WebCore/svg/SVGTextPathElement.h +++ b/WebCore/svg/SVGTextPathElement.h @@ -57,12 +57,15 @@ namespace WebCore { virtual void insertedIntoDocument(); virtual void parseMappedAttribute(Attribute*); + virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); bool childShouldCreateRenderer(Node*) const; private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::startOffsetAttr, SVGLength, StartOffset, startOffset) DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::methodAttr, int, Method, method) DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::spacingAttr, int, Spacing, spacing) diff --git a/WebCore/svg/SVGTextPositioningElement.cpp b/WebCore/svg/SVGTextPositioningElement.cpp index 12b1975..ef47322 100644 --- a/WebCore/svg/SVGTextPositioningElement.cpp +++ b/WebCore/svg/SVGTextPositioningElement.cpp @@ -65,6 +65,12 @@ void SVGTextPositioningElement::svgAttributeChanged(const QualifiedName& attrNam { SVGTextContentElement::svgAttributeChanged(attrName); + if (attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::dxAttr + || attrName == SVGNames::dyAttr) + updateRelativeLengthsInformation(); + if (!renderer()) return; @@ -107,6 +113,39 @@ bool SVGTextPositioningElement::isKnownAttribute(const QualifiedName& attrName) SVGTextContentElement::isKnownAttribute(attrName)); } +static inline bool listContainsRelativeValue(SVGLengthList* list) +{ + if (!list) + return false; + + ExceptionCode ec = 0; + int length = list->numberOfItems(); + for (int i = 0; i < length; ++i) { + SVGLength length(list->getItem(i, ec)); + ASSERT(!ec); + + if (length.isRelative()) + return true; + } + + return false; +} + +bool SVGTextPositioningElement::selfHasRelativeLengths() const +{ + if (SVGTextContentElement::selfHasRelativeLengths()) + return true; + if (listContainsRelativeValue(x())) + return true; + if (listContainsRelativeValue(y())) + return true; + if (listContainsRelativeValue(dx())) + return true; + if (listContainsRelativeValue(dy())) + return true; + return false; +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGTextPositioningElement.h b/WebCore/svg/SVGTextPositioningElement.h index f3e11bc..985ced4 100644 --- a/WebCore/svg/SVGTextPositioningElement.h +++ b/WebCore/svg/SVGTextPositioningElement.h @@ -40,6 +40,8 @@ namespace WebCore { bool isKnownAttribute(const QualifiedName&); private: + virtual bool selfHasRelativeLengths() const; + DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::xAttr, SVGLengthList*, X, x) DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::yAttr, SVGLengthList*, Y, y) DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::dxAttr, SVGLengthList*, Dx, dx) diff --git a/WebCore/svg/SVGUseElement.cpp b/WebCore/svg/SVGUseElement.cpp index 17b4212..b90bd53 100644 --- a/WebCore/svg/SVGUseElement.cpp +++ b/WebCore/svg/SVGUseElement.cpp @@ -120,7 +120,7 @@ void SVGUseElement::parseMappedAttribute(Attribute* attr) void SVGUseElement::insertedIntoDocument() { // This functions exists to assure assumptions made in the code regarding SVGElementInstance creation/destruction are satisfied. - SVGElement::insertedIntoDocument(); + SVGStyledTransformableElement::insertedIntoDocument(); ASSERT(!m_targetElementInstance); ASSERT(!m_isPendingResource); } @@ -128,13 +128,19 @@ void SVGUseElement::insertedIntoDocument() void SVGUseElement::removedFromDocument() { m_targetElementInstance = 0; - SVGElement::removedFromDocument(); + SVGStyledTransformableElement::removedFromDocument(); } void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); + bool isXYAttribute = attrName == SVGNames::xAttr || attrName == SVGNames::yAttr; + bool isWidthHeightAttribute = attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr; + + if (isXYAttribute || isWidthHeightAttribute) + updateRelativeLengthsInformation(); + if (!renderer()) return; @@ -149,12 +155,12 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) return; } - if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr) { + if (isXYAttribute) { updateContainerOffsets(); return; } - if (attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr) { + if (isWidthHeightAttribute) { updateContainerSizes(); return; } @@ -552,6 +558,9 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR // Update container offset/size updateContainerOffsets(); updateContainerSizes(); + + // Update relative length information + updateRelativeLengthsInformation(); } RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*) @@ -979,9 +988,22 @@ void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVG ASSERT(!ec); } -bool SVGUseElement::hasRelativeValues() const +bool SVGUseElement::selfHasRelativeLengths() const { - return x().isRelative() || y().isRelative() || width().isRelative() || height().isRelative(); + if (x().isRelative() + || y().isRelative() + || width().isRelative() + || height().isRelative()) + return true; + + if (!m_targetElementInstance) + return false; + + SVGElement* element = m_targetElementInstance->correspondingElement(); + if (!element || !element->isStyled()) + return false; + + return static_cast<SVGStyledElement*>(element)->hasRelativeLengths(); } } diff --git a/WebCore/svg/SVGUseElement.h b/WebCore/svg/SVGUseElement.h index 01a193b..bfda95e 100644 --- a/WebCore/svg/SVGUseElement.h +++ b/WebCore/svg/SVGUseElement.h @@ -74,7 +74,7 @@ namespace WebCore { void buildShadowAndInstanceTree(SVGShadowTreeRootElement*); private: - virtual bool hasRelativeValues() const; + virtual bool selfHasRelativeLengths() const; DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::xAttr, SVGLength, X, x) DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::yAttr, SVGLength, Y, y) diff --git a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp index 916b2f9..39b3e57 100644 --- a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp +++ b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.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 Zoltan Herczeg <zherczeg@webkit.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -23,17 +25,19 @@ #if ENABLE(SVG) && ENABLE(FILTERS) #include "SVGFEConvolveMatrix.h" + +#include "CanvasPixelArray.h" #include "Filter.h" +#include "ImageData.h" #include "SVGRenderTreeAsText.h" namespace WebCore { -FEConvolveMatrix::FEConvolveMatrix(FilterEffect* in, FilterEffect* in2, const FloatSize& kernelSize, - const float& divisor, const float& bias, const FloatSize& targetOffset, EdgeModeType edgeMode, +FEConvolveMatrix::FEConvolveMatrix(FilterEffect* in, const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) : FilterEffect() , m_in(in) - , m_in2(in2) , m_kernelSize(kernelSize) , m_divisor(divisor) , m_bias(bias) @@ -45,21 +49,21 @@ FEConvolveMatrix::FEConvolveMatrix(FilterEffect* in, FilterEffect* in2, const Fl { } -PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(FilterEffect* in, FilterEffect* in2, const FloatSize& kernelSize, - const float& divisor, const float& bias, const FloatSize& targetOffset, EdgeModeType edgeMode, +PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(FilterEffect* in, const IntSize& kernelSize, + float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) { - return adoptRef(new FEConvolveMatrix(in, in2, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength, + return adoptRef(new FEConvolveMatrix(in, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength, preserveAlpha, kernelMatrix)); } -FloatSize FEConvolveMatrix::kernelSize() const +IntSize FEConvolveMatrix::kernelSize() const { return m_kernelSize; } -void FEConvolveMatrix::setKernelSize(FloatSize kernelSize) +void FEConvolveMatrix::setKernelSize(IntSize kernelSize) { m_kernelSize = kernelSize; } @@ -94,12 +98,12 @@ void FEConvolveMatrix::setBias(float bias) m_bias = bias; } -FloatSize FEConvolveMatrix::targetOffset() const +IntPoint FEConvolveMatrix::targetOffset() const { return m_targetOffset; } -void FEConvolveMatrix::setTargetOffset(FloatSize targetOffset) +void FEConvolveMatrix::setTargetOffset(IntPoint targetOffset) { m_targetOffset = targetOffset; } @@ -134,8 +138,295 @@ void FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha) m_preserveAlpha = preserveAlpha; } -void FEConvolveMatrix::apply(Filter*) +/* + ----------------------------------- + ConvolveMatrix implementation + ----------------------------------- + + The image rectangle is split in the following way: + + +---------------------+ + | A | + +---------------------+ + | | | | + | B | C | D | + | | | | + +---------------------+ + | E | + +---------------------+ + + Where region C contains those pixels, whose values + can be calculated without crossing the edge of the rectangle. + + Example: + Image size: width: 10, height: 10 + + Order (kernel matrix size): width: 3, height 4 + Target: x:1, y:3 + + The following figure shows the target inside the kernel matrix: + + ... + ... + ... + .X. + + The regions in this case are the following: + Note: (x1, y1) top-left and (x2, y2) is the bottom-right corner + Note: row x2 and column y2 is not part of the region + only those (x, y) pixels, where x1 <= x < x2 and y1 <= y < y2 + + Region A: x1: 0, y1: 0, x2: 10, y2: 3 + Region B: x1: 0, y1: 3, x2: 1, y2: 10 + Region C: x1: 1, y1: 3, x2: 9, y2: 10 + Region D: x1: 9, y1: 3, x2: 10, y2: 10 + Region E: x1: 0, y1: 10, x2: 10, y2: 10 (empty region) + + Since region C (often) contains most of the pixels, we implemented + a fast algoritm to calculate these values, called fastSetInteriorPixels. + For other regions, fastSetOuterPixels is used, which calls getPixelValue, + to handle pixels outside of the image. In a rare situations, when + kernel matrix is bigger than the image, all pixels are calculated by this + function. + + Although these two functions have lot in common, I decided not to make + common a template for them, since there are key differences as well, + and would make it really hard to understand. +*/ + +static ALWAYS_INLINE unsigned char clampRGBAValue(float rgba) +{ + if (rgba <= 0) + return 0; + if (rgba >= 255) + return 255; + return rgba; +} + +// Only for region C +template<bool preserveAlphaValues> +ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) { + // edge mode does not affect these pixels + int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4; + int startKernelPixel = 0; + int kernelIncrease = clipRight * 4; + int xIncrease = (m_kernelSize.width() - 1) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = clipBottom + 1; y > 0; --y) { + for (int x = clipRight + 1; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixel = startKernelPixel; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel++)); + if (!preserveAlphaValues) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(kernelPixel)); + ++kernelPixel; + --kernelValue; + if (!--width) { + kernelPixel += kernelIncrease; + width = m_kernelSize.width(); + } + } + + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[0] / m_divisor + paintingData.bias)); + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[1] / m_divisor + paintingData.bias)); + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[2] / m_divisor + paintingData.bias)); + if (!preserveAlphaValues) + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[3] / m_divisor + paintingData.bias)); + else { + paintingData.dstPixelArray->set(pixel, paintingData.srcPixelArray->get(pixel)); + ++pixel; + } + startKernelPixel += 4; + } + pixel += xIncrease; + startKernelPixel += xIncrease; + } +} + +ALWAYS_INLINE int FEConvolveMatrix::getPixelValue(PaintingData& paintingData, int x, int y) +{ + if (x >= 0 && x < paintingData.width && x >= 0 && y < paintingData.height) + return (y * paintingData.width + x) << 2; + + switch (m_edgeMode) { + default: // EDGEMODE_NONE + return -1; + case EDGEMODE_DUPLICATE: + if (x < 0) + x = 0; + else if (x >= paintingData.width) + x = paintingData.width - 1; + if (y < 0) + y = 0; + else if (y >= paintingData.height) + y = paintingData.height - 1; + return (y * paintingData.width + x) << 2; + case EDGEMODE_WRAP: + while (x < 0) + x += paintingData.width; + x %= paintingData.width; + while (y < 0) + y += paintingData.height; + y %= paintingData.height; + return (y * paintingData.width + x) << 2; + } +} + +// For other regions than C +template<bool preserveAlphaValues> +void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + int pixel = (y1 * paintingData.width + x1) * 4; + int height = y2 - y1; + int width = x2 - x1; + int beginKernelPixelX = x1 - m_targetOffset.x(); + int startKernelPixelX = beginKernelPixelX; + int startKernelPixelY = y1 - m_targetOffset.y(); + int xIncrease = (paintingData.width - width) * 4; + // Contains the sum of rgb(a) components + float totals[3 + (preserveAlphaValues ? 0 : 1)]; + + // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this + ASSERT(m_divisor); + + for (int y = height; y > 0; --y) { + for (int x = width; x > 0; --x) { + int kernelValue = m_kernelMatrix.size() - 1; + int kernelPixelX = startKernelPixelX; + int kernelPixelY = startKernelPixelY; + int width = m_kernelSize.width(); + + totals[0] = 0; + totals[1] = 0; + totals[2] = 0; + if (!preserveAlphaValues) + totals[3] = 0; + + while (kernelValue >= 0) { + int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY); + if (pixelIndex >= 0) { + totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex)); + totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 1)); + totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 2)); + } + if (!preserveAlphaValues && pixelIndex >= 0) + totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->get(pixelIndex + 3)); + ++kernelPixelX; + --kernelValue; + if (!--width) { + kernelPixelX = startKernelPixelX; + ++kernelPixelY; + width = m_kernelSize.width(); + } + } + + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[0] / m_divisor + paintingData.bias)); + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[1] / m_divisor + paintingData.bias)); + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[2] / m_divisor + paintingData.bias)); + if (!preserveAlphaValues) + paintingData.dstPixelArray->set(pixel++, clampRGBAValue(totals[3] / m_divisor + paintingData.bias)); + else { + paintingData.dstPixelArray->set(pixel, paintingData.srcPixelArray->get(pixel)); + ++pixel; + } + ++startKernelPixelX; + } + pixel += xIncrease; + startKernelPixelX = beginKernelPixelX; + ++startKernelPixelY; + } +} + +ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom) +{ + // Must be implemented here, since it refers another ALWAYS_INLINE + // function, which defined in this C++ source file as well + if (m_preserveAlpha) + fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom); + else + fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom); +} + +ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) +{ + // Although this function can be moved to the header, it is implemented here + // because setInteriorPixels is also implemented here + if (m_preserveAlpha) + fastSetOuterPixels<true>(paintingData, x1, y1, x2, y2); + else + fastSetOuterPixels<false>(paintingData, x1, y1, x2, y2); +} + +void FEConvolveMatrix::apply(Filter* filter) +{ + m_in->apply(filter); + if (!m_in->resultImage()) + return; + + if (!getEffectContext()) + return; + + IntRect imageRect(IntPoint(), resultImage()->size()); + IntRect effectDrawingRect = calculateDrawingIntRect(m_in->subRegion()); + + RefPtr<CanvasPixelArray> srcPixelArray; + if (m_preserveAlpha) + srcPixelArray = m_in->resultImage()->getUnmultipliedImageData(effectDrawingRect)->data(); + else + srcPixelArray = m_in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data(); + + RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height()); + + PaintingData paintingData; + paintingData.srcPixelArray = srcPixelArray.get(); + paintingData.dstPixelArray = imageData->data(); + paintingData.width = imageRect.width(); + paintingData.height = imageRect.height(); + paintingData.bias = m_bias * 255; + + // Drawing fully covered pixels + int clipRight = imageRect.width() - m_kernelSize.width(); + int clipBottom = imageRect.height() - m_kernelSize.height(); + + if (clipRight >= 0 && clipBottom >= 0) { + setInteriorPixels(paintingData, clipRight, clipBottom); + + clipRight += m_targetOffset.x() + 1; + clipBottom += m_targetOffset.y() + 1; + if (m_targetOffset.y() > 0) + setOuterPixels(paintingData, 0, 0, imageRect.width(), m_targetOffset.y()); + if (clipBottom < imageRect.height()) + setOuterPixels(paintingData, 0, clipBottom, imageRect.width(), imageRect.height()); + if (m_targetOffset.x() > 0) + setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); + if (clipRight < imageRect.width()) + setOuterPixels(paintingData, clipRight, m_targetOffset.y(), imageRect.width(), clipBottom); + } else { + // Rare situation, not optimizied for speed + setOuterPixels(paintingData, 0, 0, imageRect.width(), imageRect.height()); + } + + if (m_preserveAlpha) + resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint()); + else + resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint()); } void FEConvolveMatrix::dump() @@ -144,8 +435,7 @@ void FEConvolveMatrix::dump() static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) { - switch (type) - { + switch (type) { case EDGEMODE_UNKNOWN: ts << "UNKNOWN"; break; @@ -176,7 +466,6 @@ TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) << "kernelUnitLength=\"" << m_kernelUnitLength << "\" " << "preserveAlpha=\"" << m_preserveAlpha << "\"]\n"; m_in->externalRepresentation(ts, indent + 1); - m_in2->externalRepresentation(ts, indent + 1); return ts; } diff --git a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h index 8e3a9bd..7b8da0b 100644 --- a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h +++ b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h @@ -2,6 +2,7 @@ Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> + 2010 Zoltan Herczeg <zherczeg@webkit.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -27,68 +28,90 @@ #include "FloatPoint.h" #include "FloatSize.h" #include "Filter.h" +#include <wtf/AlwaysInline.h> #include <wtf/Vector.h> namespace WebCore { - enum EdgeModeType { - EDGEMODE_UNKNOWN = 0, - EDGEMODE_DUPLICATE = 1, - EDGEMODE_WRAP = 2, - EDGEMODE_NONE = 3 - }; +enum EdgeModeType { + EDGEMODE_UNKNOWN = 0, + EDGEMODE_DUPLICATE = 1, + EDGEMODE_WRAP = 2, + EDGEMODE_NONE = 3 +}; + +class CanvasPixelArray; - class FEConvolveMatrix : public FilterEffect { - public: - static PassRefPtr<FEConvolveMatrix> create(FilterEffect*, FilterEffect*, const FloatSize&, - const float&, const float&, const FloatSize&, EdgeModeType, const FloatPoint&, - bool, const Vector<float>&); +class FEConvolveMatrix : public FilterEffect { +public: + static PassRefPtr<FEConvolveMatrix> create(FilterEffect*, const IntSize&, + float, float, const IntPoint&, EdgeModeType, const FloatPoint&, + bool, const Vector<float>&); - FloatSize kernelSize() const; - void setKernelSize(FloatSize); + IntSize kernelSize() const; + void setKernelSize(IntSize); - const Vector<float>& kernel() const; - void setKernel(const Vector<float>&); + const Vector<float>& kernel() const; + void setKernel(const Vector<float>&); - float divisor() const; - void setDivisor(float); + float divisor() const; + void setDivisor(float); - float bias() const; - void setBias(float); + float bias() const; + void setBias(float); - FloatSize targetOffset() const; - void setTargetOffset(FloatSize); + IntPoint targetOffset() const; + void setTargetOffset(IntPoint); - EdgeModeType edgeMode() const; - void setEdgeMode(EdgeModeType); + EdgeModeType edgeMode() const; + void setEdgeMode(EdgeModeType); - FloatPoint kernelUnitLength() const; - void setKernelUnitLength(FloatPoint); + FloatPoint kernelUnitLength() const; + void setKernelUnitLength(FloatPoint); - bool preserveAlpha() const; - void setPreserveAlpha(bool); + bool preserveAlpha() const; + void setPreserveAlpha(bool); - virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get(), m_in2.get()); } - void apply(Filter*); - void dump(); - TextStream& externalRepresentation(TextStream&, int indent) const; + virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return calculateUnionOfChildEffectSubregions(filter, m_in.get()); } + void apply(Filter*); + void dump(); + TextStream& externalRepresentation(TextStream&, int indent) const; - private: - FEConvolveMatrix(FilterEffect*, FilterEffect*, const FloatSize&, const float&, const float&, - const FloatSize&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&); +private: + FEConvolveMatrix(FilterEffect*, const IntSize&, float, float, + const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&); - RefPtr<FilterEffect> m_in; - RefPtr<FilterEffect> m_in2; - FloatSize m_kernelSize; - float m_divisor; - float m_bias; - FloatSize m_targetOffset; - EdgeModeType m_edgeMode; - FloatPoint m_kernelUnitLength; - bool m_preserveAlpha; - Vector<float> m_kernelMatrix; + struct PaintingData { + CanvasPixelArray* srcPixelArray; + CanvasPixelArray* dstPixelArray; + int width; + int height; + float bias; }; + template<bool preserveAlphaValues> + ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom); + + ALWAYS_INLINE int getPixelValue(PaintingData&, int x, int y); + + template<bool preserveAlphaValues> + void fastSetOuterPixels(PaintingData&, int x1, int y1, int x2, int y2); + + // Wrapper functions + ALWAYS_INLINE void setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom); + ALWAYS_INLINE void setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2); + + RefPtr<FilterEffect> m_in; + IntSize m_kernelSize; + float m_divisor; + float m_bias; + IntPoint m_targetOffset; + EdgeModeType m_edgeMode; + FloatPoint m_kernelUnitLength; + bool m_preserveAlpha; + Vector<float> m_kernelMatrix; +}; + } // namespace WebCore #endif // ENABLE(SVG) && ENABLE(FILTERS) diff --git a/WebCore/svg/svgattrs.in b/WebCore/svg/svgattrs.in index dbe7663..fe48c8a 100644 --- a/WebCore/svg/svgattrs.in +++ b/WebCore/svg/svgattrs.in @@ -141,6 +141,8 @@ onzoom opacity operator order +orderX +orderY orient orientation origin diff --git a/WebCore/svg/svgtags.in b/WebCore/svg/svgtags.in index 5d44e03..adf0b24 100644 --- a/WebCore/svg/svgtags.in +++ b/WebCore/svg/svgtags.in @@ -31,9 +31,7 @@ feBlend createWithNew feColorMatrix createWithNew feComponentTransfer createWithNew feComposite createWithNew -#if 0 feConvolveMatrix createWithNew -#endif feDiffuseLighting createWithNew feDisplacementMap createWithNew feDistantLight createWithNew |