diff options
Diffstat (limited to 'WebCore/svg')
50 files changed, 1233 insertions, 798 deletions
diff --git a/WebCore/svg/SVGAllInOne.cpp b/WebCore/svg/SVGAllInOne.cpp index c1bf281..0ad4932 100644 --- a/WebCore/svg/SVGAllInOne.cpp +++ b/WebCore/svg/SVGAllInOne.cpp @@ -107,7 +107,9 @@ #include "SVGNumberList.cpp" #include "SVGPaint.cpp" #include "SVGParserUtilities.cpp" +#include "SVGPathBuilder.cpp" #include "SVGPathElement.cpp" +#include "SVGPathParser.cpp" #include "SVGPathSegArc.cpp" #include "SVGPathSegClosePath.cpp" #include "SVGPathSegCurvetoCubic.cpp" @@ -118,6 +120,7 @@ #include "SVGPathSegLinetoHorizontal.cpp" #include "SVGPathSegLinetoVertical.cpp" #include "SVGPathSegList.cpp" +#include "SVGPathSegListBuilder.cpp" #include "SVGPathSegMoveto.cpp" #include "SVGPatternElement.cpp" #include "SVGPointList.cpp" diff --git a/WebCore/svg/SVGAnimateElement.cpp b/WebCore/svg/SVGAnimateElement.cpp index ff3317b..fa4a4cf 100644 --- a/WebCore/svg/SVGAnimateElement.cpp +++ b/WebCore/svg/SVGAnimateElement.cpp @@ -28,6 +28,7 @@ #include "SVGColor.h" #include "SVGParserUtilities.h" #include "SVGPathSegList.h" +#include "SVGPathSegListBuilder.h" #include "SVGPointList.h" #include <math.h> @@ -189,9 +190,11 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const } } else if (m_propertyType == PathProperty) { m_fromPath = SVGPathSegList::create(SVGNames::dAttr); - if (pathSegListFromSVGData(m_fromPath.get(), fromString)) { + SVGPathSegListBuilder fromParser(m_fromPath.get()); + if (fromParser.build(fromString, UnalteredParsing)) { m_toPath = SVGPathSegList::create(SVGNames::dAttr); - if (pathSegListFromSVGData(m_toPath.get(), toString)) + SVGPathSegListBuilder toParser(m_toPath.get()); + if (toParser.build(toString, UnalteredParsing)) return true; } m_fromPath.clear(); diff --git a/WebCore/svg/SVGAnimateMotionElement.cpp b/WebCore/svg/SVGAnimateMotionElement.cpp index 9a0da7f..a3f4ef9 100644 --- a/WebCore/svg/SVGAnimateMotionElement.cpp +++ b/WebCore/svg/SVGAnimateMotionElement.cpp @@ -28,9 +28,11 @@ #include "Attribute.h" #include "RenderObject.h" +#include "RenderSVGResource.h" #include "SVGElementInstance.h" #include "SVGMPathElement.h" #include "SVGParserUtilities.h" +#include "SVGPathBuilder.h" #include "SVGPathElement.h" #include "SVGTransformList.h" #include <math.h> @@ -87,7 +89,9 @@ void SVGAnimateMotionElement::parseMappedAttribute(Attribute* attr) { if (attr->name() == SVGNames::pathAttr) { m_path = Path(); - pathFromSVGData(m_path, attr->value()); + SVGPathBuilder builder(m_path); + // FIXME: We should analyse the returned value. + builder.build(attr->value()); } else SVGAnimationElement::parseMappedAttribute(attr); } @@ -214,9 +218,12 @@ void SVGAnimateMotionElement::applyResultsToTarget() { // We accumulate to the target element transform list so there is not much to do here. SVGElement* targetElement = this->targetElement(); - if (targetElement && targetElement->renderer()) - targetElement->renderer()->setNeedsLayout(true); - + if (!targetElement) + return; + + if (RenderObject* renderer = targetElement->renderer()) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); + // ...except in case where we have additional instances in <use> trees. const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); @@ -228,7 +235,7 @@ void SVGAnimateMotionElement::applyResultsToTarget() transform->setMatrix(t->a(), t->b(), t->c(), t->d(), t->e(), t->f()); if (RenderObject* renderer = shadowTreeElement->renderer()) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } } } @@ -248,5 +255,3 @@ float SVGAnimateMotionElement::calculateDistance(const String& fromString, const } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/svg/SVGAnimateTransformElement.cpp b/WebCore/svg/SVGAnimateTransformElement.cpp index 1a305bb..6ca9447 100644 --- a/WebCore/svg/SVGAnimateTransformElement.cpp +++ b/WebCore/svg/SVGAnimateTransformElement.cpp @@ -30,6 +30,7 @@ #include "AffineTransform.h" #include "Attribute.h" #include "RenderObject.h" +#include "RenderSVGResource.h" #include "SVGAngle.h" #include "SVGElementInstance.h" #include "SVGGradientElement.h" @@ -172,9 +173,12 @@ void SVGAnimateTransformElement::applyResultsToTarget() return; // We accumulate to the target element transform list so there is not much to do here. SVGElement* targetElement = this->targetElement(); + if (!targetElement) + return; + if (RenderObject* renderer = targetElement->renderer()) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } // ...except in case where we have additional instances in <use> trees. @@ -192,7 +196,7 @@ void SVGAnimateTransformElement::applyResultsToTarget() static_cast<SVGGradientElement*>(shadowTreeElement)->setGradientTransformBaseValue(transformList.get()); if (RenderObject* renderer = shadowTreeElement->renderer()) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } } } diff --git a/WebCore/svg/SVGCircleElement.cpp b/WebCore/svg/SVGCircleElement.cpp index c90b8e3..f8c9ccd 100644 --- a/WebCore/svg/SVGCircleElement.cpp +++ b/WebCore/svg/SVGCircleElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "FloatPoint.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" @@ -84,20 +85,20 @@ void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (isLengthAttribute) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGCircleElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGComponentTransferFunctionElement.idl b/WebCore/svg/SVGComponentTransferFunctionElement.idl index 950f77d..0a9e05d 100644 --- a/WebCore/svg/SVGComponentTransferFunctionElement.idl +++ b/WebCore/svg/SVGComponentTransferFunctionElement.idl @@ -25,7 +25,10 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGComponentTransferFunctionElement : SVGElement { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGComponentTransferFunctionElement : SVGElement { // Component Transfer Types const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; diff --git a/WebCore/svg/SVGEllipseElement.cpp b/WebCore/svg/SVGEllipseElement.cpp index 5509c2d..963b4b0 100644 --- a/WebCore/svg/SVGEllipseElement.cpp +++ b/WebCore/svg/SVGEllipseElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "FloatPoint.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" @@ -90,20 +91,20 @@ void SVGEllipseElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (isLengthAttribute) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGEllipseElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGException.idl b/WebCore/svg/SVGException.idl index db565ff..3f1f8ec 100644 --- a/WebCore/svg/SVGException.idl +++ b/WebCore/svg/SVGException.idl @@ -21,7 +21,8 @@ module svg { interface [ - Conditional=SVG + Conditional=SVG, + DontCheckEnums ] SVGException { readonly attribute unsigned short code; diff --git a/WebCore/svg/SVGFEBlendElement.idl b/WebCore/svg/SVGFEBlendElement.idl index bb6d86d..0c08603 100644 --- a/WebCore/svg/SVGFEBlendElement.idl +++ b/WebCore/svg/SVGFEBlendElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFEBlendElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFEBlendElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Blend Mode Types const unsigned short SVG_FEBLEND_MODE_UNKNOWN = 0; const unsigned short SVG_FEBLEND_MODE_NORMAL = 1; diff --git a/WebCore/svg/SVGFEColorMatrixElement.idl b/WebCore/svg/SVGFEColorMatrixElement.idl index d704906..61c5b4a 100644 --- a/WebCore/svg/SVGFEColorMatrixElement.idl +++ b/WebCore/svg/SVGFEColorMatrixElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFEColorMatrixElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFEColorMatrixElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Color Matrix Types const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0; const unsigned short SVG_FECOLORMATRIX_TYPE_MATRIX = 1; diff --git a/WebCore/svg/SVGFECompositeElement.idl b/WebCore/svg/SVGFECompositeElement.idl index d3adb25..af1d5cf 100644 --- a/WebCore/svg/SVGFECompositeElement.idl +++ b/WebCore/svg/SVGFECompositeElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFECompositeElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFECompositeElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Composite Operators const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0; const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1; diff --git a/WebCore/svg/SVGFEConvolveMatrixElement.idl b/WebCore/svg/SVGFEConvolveMatrixElement.idl index 5be4c33..afe859d 100644 --- a/WebCore/svg/SVGFEConvolveMatrixElement.idl +++ b/WebCore/svg/SVGFEConvolveMatrixElement.idl @@ -25,8 +25,12 @@ module svg { - interface [Conditional=SVG&FILTERS, GenerateConstructor] SVGFEConvolveMatrixElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + GenerateConstructor, + DontCheckEnums + ] SVGFEConvolveMatrixElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Edge Mode Values const unsigned short SVG_EDGEMODE_UNKNOWN = 0; const unsigned short SVG_EDGEMODE_DUPLICATE = 1; diff --git a/WebCore/svg/SVGFEDisplacementMapElement.idl b/WebCore/svg/SVGFEDisplacementMapElement.idl index b003e8f..1eb9440 100644 --- a/WebCore/svg/SVGFEDisplacementMapElement.idl +++ b/WebCore/svg/SVGFEDisplacementMapElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFEDisplacementMapElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFEDisplacementMapElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Channel Selectors const unsigned short SVG_CHANNEL_UNKNOWN = 0; const unsigned short SVG_CHANNEL_R = 1; diff --git a/WebCore/svg/SVGFEImageElement.cpp b/WebCore/svg/SVGFEImageElement.cpp index 84f8734..1f7164f 100644 --- a/WebCore/svg/SVGFEImageElement.cpp +++ b/WebCore/svg/SVGFEImageElement.cpp @@ -29,6 +29,7 @@ #include "DocLoader.h" #include "Document.h" #include "RenderObject.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" #include "SVGPreserveAspectRatio.h" @@ -107,7 +108,16 @@ void SVGFEImageElement::synchronizeProperty(const QualifiedName& attrName) void SVGFEImageElement::notifyFinished(CachedResource*) { - SVGStyledElement::invalidateResourcesInAncestorChain(); + if (!inDocument()) + return; + + Element* parent = parentElement(); + ASSERT(parent); + + if (!parent->hasTagName(SVGNames::filterTag) || !parent->renderer()) + return; + + RenderSVGResource::markForLayoutAndParentResourceInvalidation(parent->renderer()); } PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*) diff --git a/WebCore/svg/SVGFEMorphologyElement.idl b/WebCore/svg/SVGFEMorphologyElement.idl index ffd2289..64023e8 100644 --- a/WebCore/svg/SVGFEMorphologyElement.idl +++ b/WebCore/svg/SVGFEMorphologyElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFEMorphologyElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFEMorphologyElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Morphology Operators const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0; const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1; diff --git a/WebCore/svg/SVGFETurbulenceElement.idl b/WebCore/svg/SVGFETurbulenceElement.idl index 934eddf..f011d99 100644 --- a/WebCore/svg/SVGFETurbulenceElement.idl +++ b/WebCore/svg/SVGFETurbulenceElement.idl @@ -25,8 +25,11 @@ module svg { - interface [Conditional=SVG&FILTERS] SVGFETurbulenceElement : SVGElement, - SVGFilterPrimitiveStandardAttributes { + interface [ + Conditional=SVG&FILTERS, + DontCheckEnums + ] SVGFETurbulenceElement : SVGElement, + SVGFilterPrimitiveStandardAttributes { // Turbulence Types const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0; const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1; diff --git a/WebCore/svg/SVGFilterElement.cpp b/WebCore/svg/SVGFilterElement.cpp index b86b8c4..4387e71 100644 --- a/WebCore/svg/SVGFilterElement.cpp +++ b/WebCore/svg/SVGFilterElement.cpp @@ -62,8 +62,11 @@ SVGFilterElement::~SVGFilterElement() { } -void SVGFilterElement::setFilterRes(unsigned long, unsigned long) const +void SVGFilterElement::setFilterRes(unsigned long filterResX, unsigned long filterResY) { + setFilterResXBaseValue(filterResX); + setFilterResYBaseValue(filterResY); + invalidateResourceClients(); } void SVGFilterElement::parseMappedAttribute(Attribute* attr) @@ -122,10 +125,10 @@ void SVGFilterElement::svgAttributeChanged(const QualifiedName& attrName) || attrName == SVGNames::filterUnitsAttr || attrName == SVGNames::primitiveUnitsAttr || attrName == SVGNames::filterResAttr + || SVGStyledElement::isKnownAttribute(attrName) || SVGURIReference::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) - || SVGExternalResourcesRequired::isKnownAttribute(attrName) - || SVGStyledElement::isKnownAttribute(attrName)) + || SVGExternalResourcesRequired::isKnownAttribute(attrName)) invalidateResourceClients(); } @@ -168,6 +171,14 @@ void SVGFilterElement::synchronizeProperty(const QualifiedName& attrName) synchronizeHref(); } +void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +{ + SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); + + if (!changedByParser) + invalidateResourceClients(); +} + FloatRect SVGFilterElement::filterBoundingBox(const FloatRect& objectBoundingBox) const { FloatRect filterBBox; diff --git a/WebCore/svg/SVGFilterElement.h b/WebCore/svg/SVGFilterElement.h index 85679c7..7b0192c 100644 --- a/WebCore/svg/SVGFilterElement.h +++ b/WebCore/svg/SVGFilterElement.h @@ -43,12 +43,13 @@ public: SVGFilterElement(const QualifiedName&, Document*); virtual ~SVGFilterElement(); - void setFilterRes(unsigned long filterResX, unsigned long filterResY) const; + void setFilterRes(unsigned long filterResX, unsigned long filterResY); FloatRect filterBoundingBox(const FloatRect&) const; virtual void parseMappedAttribute(Attribute*); virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); diff --git a/WebCore/svg/SVGFont.cpp b/WebCore/svg/SVGFont.cpp index 5436688..6abea60 100644 --- a/WebCore/svg/SVGFont.cpp +++ b/WebCore/svg/SVGFont.cpp @@ -413,7 +413,7 @@ static float floatWidthOfSubStringUsingSVGFont(const Font* font, const TextRun& } SVGTextRunWalker<SVGTextRunWalkerMeasuredLengthData> runWalker(fontData, fontElement, data, floatWidthUsingSVGFontCallback, floatWidthMissingGlyphCallback); - runWalker.walk(run, isVerticalText, language, 0, run.length()); + runWalker.walk(run, isVerticalText, language, from, to); charsConsumed = data.charsConsumed; glyphName = data.glyphName; return data.length; diff --git a/WebCore/svg/SVGForeignObjectElement.cpp b/WebCore/svg/SVGForeignObjectElement.cpp index d6bf1cf..7ffe1c6 100644 --- a/WebCore/svg/SVGForeignObjectElement.cpp +++ b/WebCore/svg/SVGForeignObjectElement.cpp @@ -28,6 +28,7 @@ #include "Attribute.h" #include "CSSPropertyNames.h" #include "RenderForeignObject.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" #include <wtf/Assertions.h> @@ -90,7 +91,7 @@ void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } @@ -98,7 +99,7 @@ void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGForeignObjectElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGGElement.cpp b/WebCore/svg/SVGGElement.cpp index eceac41..a830096 100644 --- a/WebCore/svg/SVGGElement.cpp +++ b/WebCore/svg/SVGGElement.cpp @@ -24,6 +24,7 @@ #include "SVGGElement.h" #include "RenderSVGHiddenContainer.h" +#include "RenderSVGResource.h" #include "RenderSVGTransformableContainer.h" namespace WebCore { @@ -62,14 +63,14 @@ void SVGGElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGGElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGGlyphElement.cpp b/WebCore/svg/SVGGlyphElement.cpp index d5b7531..054db11 100644 --- a/WebCore/svg/SVGGlyphElement.cpp +++ b/WebCore/svg/SVGGlyphElement.cpp @@ -29,7 +29,7 @@ #include "SVGFontElement.h" #include "SVGFontFaceElement.h" #include "SVGNames.h" -#include "SVGParserUtilities.h" +#include "SVGPathBuilder.h" #include "SimpleFontData.h" #include "XMLNames.h" @@ -102,7 +102,9 @@ static inline SVGGlyphIdentifier::Orientation parseOrientation(const AtomicStrin static inline Path parsePathData(const AtomicString& value) { Path result; - pathFromSVGData(result, value); + SVGPathBuilder builder(result); + // FIXME: We should analyse the returned value. + builder.build(value); return result; } diff --git a/WebCore/svg/SVGGradientElement.idl b/WebCore/svg/SVGGradientElement.idl index 7485780..16ac636 100644 --- a/WebCore/svg/SVGGradientElement.idl +++ b/WebCore/svg/SVGGradientElement.idl @@ -25,11 +25,14 @@ module svg { - interface [Conditional=SVG] SVGGradientElement : SVGElement, - SVGURIReference, - SVGExternalResourcesRequired, - SVGStylable - /* SVGUnitTypes */ { + interface [ + Conditional=SVG, + DontCheckEnums + ] SVGGradientElement : SVGElement, + SVGURIReference, + SVGExternalResourcesRequired, + SVGStylable + /* SVGUnitTypes */ { // Spread Method Types const unsigned short SVG_SPREADMETHOD_UNKNOWN = 0; const unsigned short SVG_SPREADMETHOD_PAD = 1; diff --git a/WebCore/svg/SVGImageElement.cpp b/WebCore/svg/SVGImageElement.cpp index 711e9f3..75f05cf 100644 --- a/WebCore/svg/SVGImageElement.cpp +++ b/WebCore/svg/SVGImageElement.cpp @@ -27,6 +27,7 @@ #include "Attribute.h" #include "CSSPropertyNames.h" #include "RenderSVGImage.h" +#include "RenderSVGResource.h" #include "SVGDocument.h" #include "SVGLength.h" #include "SVGPreserveAspectRatio.h" @@ -105,7 +106,7 @@ void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } @@ -114,7 +115,7 @@ void SVGImageElement::svgAttributeChanged(const QualifiedName& attrName) || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGImageElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGLineElement.cpp b/WebCore/svg/SVGLineElement.cpp index c6e5e04..0898319 100644 --- a/WebCore/svg/SVGLineElement.cpp +++ b/WebCore/svg/SVGLineElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "FloatPoint.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" @@ -86,20 +87,20 @@ void SVGLineElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (isLengthAttribute) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGLineElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGPaint.cpp b/WebCore/svg/SVGPaint.cpp index 82a5fe4..6d60979 100644 --- a/WebCore/svg/SVGPaint.cpp +++ b/WebCore/svg/SVGPaint.cpp @@ -1,6 +1,7 @@ /* - 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) Research In Motion Limited 2010. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,8 +20,10 @@ */ #include "config.h" + #if ENABLE(SVG) #include "SVGPaint.h" +#include "SVGURIReference.h" namespace WebCore { @@ -108,8 +111,14 @@ String SVGPaint::cssText() const return SVGColor::cssText(); } +bool SVGPaint::matchesTargetURI(const String& referenceId) +{ + if (m_paintType != SVG_PAINTTYPE_URI && m_paintType != SVG_PAINTTYPE_URI_RGBCOLOR) + return false; + + return referenceId == SVGURIReference::getTarget(m_uri); +} + } -// vim:ts=4:noet #endif // ENABLE(SVG) - diff --git a/WebCore/svg/SVGPaint.h b/WebCore/svg/SVGPaint.h index 032f715..aa696d1 100644 --- a/WebCore/svg/SVGPaint.h +++ b/WebCore/svg/SVGPaint.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> Copyright (C) 2006 Samuel Weinig (sam.weinig@gmial.com) @@ -78,6 +78,8 @@ namespace WebCore { static SVGPaint* defaultFill(); static SVGPaint* defaultStroke(); + bool matchesTargetURI(const String& referenceId); + private: SVGPaint(); SVGPaint(const String& uri); @@ -96,5 +98,3 @@ namespace WebCore { #endif // ENABLE(SVG) #endif // SVGPaint_h - -// vim:ts=4:noet diff --git a/WebCore/svg/SVGParserUtilities.cpp b/WebCore/svg/SVGParserUtilities.cpp index c722232..14e3d58 100644 --- a/WebCore/svg/SVGParserUtilities.cpp +++ b/WebCore/svg/SVGParserUtilities.cpp @@ -21,31 +21,16 @@ */ #include "config.h" + #if ENABLE(SVG) #include "SVGParserUtilities.h" +#include "Document.h" #include "ExceptionCode.h" -#include "FloatConversion.h" #include "FloatPoint.h" -#include "Path.h" #include "PlatformString.h" -#include "SVGPathSegList.h" -#include "SVGPathSegArc.h" -#include "SVGPathSegClosePath.h" -#include "SVGPathSegCurvetoCubic.h" -#include "SVGPathSegCurvetoCubicSmooth.h" -#include "SVGPathSegCurvetoQuadratic.h" -#include "SVGPathSegCurvetoQuadraticSmooth.h" -#include "SVGPathSegLineto.h" -#include "SVGPathSegLinetoHorizontal.h" -#include "SVGPathSegLinetoVertical.h" -#include "SVGPathSegList.h" -#include "SVGPathSegMoveto.h" #include "SVGPointList.h" -#include "SVGPathElement.h" -#include <math.h> #include <wtf/ASCIICType.h> -#include <wtf/MathExtras.h> namespace WebCore { @@ -135,15 +120,9 @@ bool parseNumber(const UChar*& ptr, const UChar* end, float& number, bool skip) return _parseNumber(ptr, end, number, skip); } -// Only used for parsing Paths -static bool parseNumber(const UChar*& ptr, const UChar* end, double& number, bool skip = true) -{ - return _parseNumber(ptr, end, number, skip); -} - // only used to parse largeArcFlag and sweepFlag which must be a "0" or "1" // and might not have any whitespace/comma after it -static bool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag) +bool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag) { const UChar flagChar = *ptr++; if (flagChar == '0') @@ -210,637 +189,6 @@ bool pointsListFromSVGData(SVGPointList* pointsList, const String& points) return cur == end && !delimParsed; } - /** - * Parser for svg path data, contained in the d attribute. - * - * The parser delivers encountered commands and parameters by calling - * methods that correspond to those commands. Clients have to derive - * from this class and implement the abstract command methods. - * - * There are two operating modes. By default the parser just delivers unaltered - * svg path data commands and parameters. In the second mode, it will convert all - * relative coordinates to absolute ones, and convert all curves to cubic beziers. - */ - class SVGPathParser { - public: - virtual ~SVGPathParser() { } - bool parseSVG(const String& d, bool process = false); - - protected: - virtual void svgMoveTo(double x1, double y1, bool closed, bool abs = true) = 0; - virtual void svgLineTo(double x1, double y1, bool abs = true) = 0; - virtual void svgLineToHorizontal(double, bool /*abs*/ = true) { } - virtual void svgLineToVertical(double /*y*/, bool /*abs*/ = true) { } - virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true) = 0; - virtual void svgCurveToCubicSmooth(double /*x*/, double /*y*/, double /*x2*/, double /*y2*/, bool /*abs*/ = true) { } - virtual void svgCurveToQuadratic(double /*x*/, double /*y*/, double /*x1*/, double /*y1*/, bool /*abs*/ = true) { } - virtual void svgCurveToQuadraticSmooth(double /*x*/, double /*y*/, bool /*abs*/ = true) { } - virtual void svgArcTo(double /*x*/, double /*y*/, double /*r1*/, double /*r2*/, double /*angle*/, bool /*largeArcFlag*/, bool /*sweepFlag*/, bool /*abs*/ = true) { } - virtual void svgClosePath() = 0; - - private: - void calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag); - }; - -bool SVGPathParser::parseSVG(const String& s, bool process) -{ - const UChar* ptr = s.characters(); - const UChar* end = ptr + s.length(); - - double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc; - double px1, py1, px2, py2, px3, py3; - bool closed = true; - - if (!skipOptionalSpaces(ptr, end)) // skip any leading spaces - return false; - - char command = *(ptr++), lastCommand = ' '; - if (command != 'm' && command != 'M') // path must start with moveto - return false; - - subpathx = subpathy = curx = cury = contrlx = contrly = 0.0; - while (1) { - skipOptionalSpaces(ptr, end); // skip spaces between command and first coord - - bool relative = false; - - switch (command) - { - case 'm': - relative = true; - case 'M': - { - if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - if (process) { - subpathx = curx = relative ? curx + tox : tox; - subpathy = cury = relative ? cury + toy : toy; - - svgMoveTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury), closed); - } else - svgMoveTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), closed, !relative); - closed = false; - break; - } - case 'l': - relative = true; - case 'L': - { - if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - if (process) { - curx = relative ? curx + tox : tox; - cury = relative ? cury + toy : toy; - - svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury)); - } - else - svgLineTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative); - break; - } - case 'h': - { - if (!parseNumber(ptr, end, tox)) - return false; - if (process) { - curx = curx + tox; - svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury)); - } - else - svgLineToHorizontal(narrowPrecisionToFloat(tox), false); - break; - } - case 'H': - { - if (!parseNumber(ptr, end, tox)) - return false; - if (process) { - curx = tox; - svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury)); - } - else - svgLineToHorizontal(narrowPrecisionToFloat(tox)); - break; - } - case 'v': - { - if (!parseNumber(ptr, end, toy)) - return false; - if (process) { - cury = cury + toy; - svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury)); - } - else - svgLineToVertical(narrowPrecisionToFloat(toy), false); - break; - } - case 'V': - { - if (!parseNumber(ptr, end, toy)) - return false; - if (process) { - cury = toy; - svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury)); - } - else - svgLineToVertical(narrowPrecisionToFloat(toy)); - break; - } - case 'z': - case 'Z': - { - // reset curx, cury for next path - if (process) { - curx = subpathx; - cury = subpathy; - } - closed = true; - svgClosePath(); - break; - } - case 'c': - relative = true; - case 'C': - { - if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) || - !parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) || - !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - if (process) { - px1 = relative ? curx + x1 : x1; - py1 = relative ? cury + y1 : y1; - px2 = relative ? curx + x2 : x2; - py2 = relative ? cury + y2 : y2; - px3 = relative ? curx + tox : tox; - py3 = relative ? cury + toy : toy; - - svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2), - narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3)); - - contrlx = relative ? curx + x2 : x2; - contrly = relative ? cury + y2 : y2; - curx = relative ? curx + tox : tox; - cury = relative ? cury + toy : toy; - } - else - svgCurveToCubic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), narrowPrecisionToFloat(x2), - narrowPrecisionToFloat(y2), narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative); - - break; - } - case 's': - relative = true; - case 'S': - { - if (!parseNumber(ptr, end, x2) || !parseNumber(ptr, end, y2) || - !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - if (!(lastCommand == 'c' || lastCommand == 'C' || - lastCommand == 's' || lastCommand == 'S')) { - contrlx = curx; - contrly = cury; - } - - if (process) { - px1 = 2 * curx - contrlx; - py1 = 2 * cury - contrly; - px2 = relative ? curx + x2 : x2; - py2 = relative ? cury + y2 : y2; - px3 = relative ? curx + tox : tox; - py3 = relative ? cury + toy : toy; - - svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2), - narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3)); - - contrlx = relative ? curx + x2 : x2; - contrly = relative ? cury + y2 : y2; - curx = relative ? curx + tox : tox; - cury = relative ? cury + toy : toy; - } - else - svgCurveToCubicSmooth(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2), - narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative); - break; - } - case 'q': - relative = true; - case 'Q': - { - if (!parseNumber(ptr, end, x1) || !parseNumber(ptr, end, y1) || - !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - if (process) { - px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0); - py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0); - px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0); - py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0); - px3 = relative ? curx + tox : tox; - py3 = relative ? cury + toy : toy; - - svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2), - narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3)); - - contrlx = relative ? curx + x1 : x1; - contrly = relative ? cury + y1 : y1; - curx = relative ? curx + tox : tox; - cury = relative ? cury + toy : toy; - } - else - svgCurveToQuadratic(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), - narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative); - break; - } - case 't': - relative = true; - case 'T': - { - if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - if (!(lastCommand == 'q' || lastCommand == 'Q' || - lastCommand == 't' || lastCommand == 'T')) { - contrlx = curx; - contrly = cury; - } - - if (process) { - xc = 2 * curx - contrlx; - yc = 2 * cury - contrly; - - px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0); - py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0); - px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0); - py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0); - px3 = relative ? curx + tox : tox; - py3 = relative ? cury + toy : toy; - - svgCurveToCubic(narrowPrecisionToFloat(px1), narrowPrecisionToFloat(py1), narrowPrecisionToFloat(px2), - narrowPrecisionToFloat(py2), narrowPrecisionToFloat(px3), narrowPrecisionToFloat(py3)); - - contrlx = xc; - contrly = yc; - curx = relative ? curx + tox : tox; - cury = relative ? cury + toy : toy; - } - else - svgCurveToQuadraticSmooth(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative); - break; - } - case 'a': - relative = true; - case 'A': - { - bool largeArc, sweep; - double angle, rx, ry; - if (!parseNumber(ptr, end, rx) || !parseNumber(ptr, end, ry) - || !parseNumber(ptr, end, angle) - || !parseArcFlag(ptr, end, largeArc) || !parseArcFlag(ptr, end, sweep) - || !parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy)) - return false; - - // Spec: radii are nonnegative numbers - rx = fabs(rx); - ry = fabs(ry); - - if (process) - calculateArc(relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep); - else - svgArcTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), narrowPrecisionToFloat(rx), narrowPrecisionToFloat(ry), - narrowPrecisionToFloat(angle), largeArc, sweep, !relative); - break; - } - default: - // FIXME: An error should go to the JavaScript console, or the like. - return false; - } - lastCommand = command; - - if (ptr >= end) - return true; - - // Check for remaining coordinates in the current command. - if ((*ptr == '+' || *ptr == '-' || *ptr == '.' || (*ptr >= '0' && *ptr <= '9')) - && (command != 'z' && command != 'Z')) { - if (command == 'M') - command = 'L'; - else if (command == 'm') - command = 'l'; - } else - command = *(ptr++); - - if (lastCommand != 'C' && lastCommand != 'c' && - lastCommand != 'S' && lastCommand != 's' && - lastCommand != 'Q' && lastCommand != 'q' && - lastCommand != 'T' && lastCommand != 't') { - contrlx = curx; - contrly = cury; - } - } - - return false; -} - -// This works by converting the SVG arc to "simple" beziers. -// For each bezier found a svgToCurve call is done. -// Adapted from Niko's code in kdelibs/kdecore/svgicons. -// Maybe this can serve in some shared lib? (Rob) -void SVGPathParser::calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag) -{ - double sin_th, cos_th; - double a00, a01, a10, a11; - double x0, y0, x1, y1, xc, yc; - double d, sfactor, sfactor_sq; - double th0, th1, th_arc; - int i, n_segs; - - sin_th = sin(angle * (piDouble / 180.0)); - cos_th = cos(angle * (piDouble / 180.0)); - - double dx; - - if (!relative) - dx = (curx - x) / 2.0; - else - dx = -x / 2.0; - - double dy; - - if (!relative) - dy = (cury - y) / 2.0; - else - dy = -y / 2.0; - - double _x1 = cos_th * dx + sin_th * dy; - double _y1 = -sin_th * dx + cos_th * dy; - double Pr1 = r1 * r1; - double Pr2 = r2 * r2; - double Px = _x1 * _x1; - double Py = _y1 * _y1; - - // Spec : check if radii are large enough - double check = Px / Pr1 + Py / Pr2; - if (check > 1) { - r1 = r1 * sqrt(check); - r2 = r2 * sqrt(check); - } - - a00 = cos_th / r1; - a01 = sin_th / r1; - a10 = -sin_th / r2; - a11 = cos_th / r2; - - x0 = a00 * curx + a01 * cury; - y0 = a10 * curx + a11 * cury; - - if (!relative) - x1 = a00 * x + a01 * y; - else - x1 = a00 * (curx + x) + a01 * (cury + y); - - if (!relative) - y1 = a10 * x + a11 * y; - else - y1 = a10 * (curx + x) + a11 * (cury + y); - - /* (x0, y0) is current point in transformed coordinate space. - (x1, y1) is new point in transformed coordinate space. - - The arc fits a unit-radius circle in this space. - */ - - d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); - - sfactor_sq = 1.0 / d - 0.25; - - if (sfactor_sq < 0) - sfactor_sq = 0; - - sfactor = sqrt(sfactor_sq); - - if (sweepFlag == largeArcFlag) - sfactor = -sfactor; - - xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); - yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); - - /* (xc, yc) is center of the circle. */ - th0 = atan2(y0 - yc, x0 - xc); - th1 = atan2(y1 - yc, x1 - xc); - - th_arc = th1 - th0; - if (th_arc < 0 && sweepFlag) - th_arc += 2 * piDouble; - else if (th_arc > 0 && !sweepFlag) - th_arc -= 2 * piDouble; - - n_segs = (int) (int) ceil(fabs(th_arc / (piDouble * 0.5 + 0.001))); - - for (i = 0; i < n_segs; i++) { - double sin_th, cos_th; - double a00, a01, a10, a11; - double x1, y1, x2, y2, x3, y3; - double t; - double th_half; - - double _th0 = th0 + i * th_arc / n_segs; - double _th1 = th0 + (i + 1) * th_arc / n_segs; - - sin_th = sin(angle * (piDouble / 180.0)); - cos_th = cos(angle * (piDouble / 180.0)); - - /* inverse transform compared with rsvg_path_arc */ - a00 = cos_th * r1; - a01 = -sin_th * r2; - a10 = sin_th * r1; - a11 = cos_th * r2; - - th_half = 0.5 * (_th1 - _th0); - t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); - x1 = xc + cos(_th0) - t * sin(_th0); - y1 = yc + sin(_th0) + t * cos(_th0); - x3 = xc + cos(_th1); - y3 = yc + sin(_th1); - x2 = x3 + t * sin(_th1); - y2 = y3 - t * cos(_th1); - - svgCurveToCubic(narrowPrecisionToFloat(a00 * x1 + a01 * y1), narrowPrecisionToFloat(a10 * x1 + a11 * y1), - narrowPrecisionToFloat(a00 * x2 + a01 * y2), narrowPrecisionToFloat(a10 * x2 + a11 * y2), - narrowPrecisionToFloat(a00 * x3 + a01 * y3), narrowPrecisionToFloat(a10 * x3 + a11 * y3)); - } - - if (!relative) - curx = x; - else - curx += x; - - if (!relative) - cury = y; - else - cury += y; -} - -class PathBuilder : private SVGPathParser { -public: - bool build(Path* path, const String& d) - { - Path temporaryPath; - m_path = &temporaryPath; - if (!parseSVG(d, true)) - return false; - temporaryPath.swap(*path); - return true; - } - -private: - virtual void svgMoveTo(double x1, double y1, bool closed, bool abs = true) - { - current.setX(narrowPrecisionToFloat(abs ? x1 : current.x() + x1)); - current.setY(narrowPrecisionToFloat(abs ? y1 : current.y() + y1)); - if (closed) - m_path->closeSubpath(); - m_path->moveTo(current); - } - virtual void svgLineTo(double x1, double y1, bool abs = true) - { - current.setX(narrowPrecisionToFloat(abs ? x1 : current.x() + x1)); - current.setY(narrowPrecisionToFloat(abs ? y1 : current.y() + y1)); - m_path->addLineTo(current); - } - virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true) - { - if (!abs) { - x1 += current.x(); - y1 += current.y(); - x2 += current.x(); - y2 += current.y(); - } - current.setX(narrowPrecisionToFloat(abs ? x : current.x() + x)); - current.setY(narrowPrecisionToFloat(abs ? y : current.y() + y)); - m_path->addBezierCurveTo(FloatPoint::narrowPrecision(x1, y1), FloatPoint::narrowPrecision(x2, y2), current); - } - virtual void svgClosePath() - { - m_path->closeSubpath(); - } - - Path* m_path; - FloatPoint current; -}; - -bool pathFromSVGData(Path& path, const String& d) -{ - PathBuilder builder; - return builder.build(&path, d); -} - -class SVGPathSegListBuilder : private SVGPathParser { -public: - bool build(SVGPathSegList* segList, const String& d, bool process) - { - bool result = parseSVG(d, process); - size_t size = m_vector.size(); - for (size_t i = 0; i < size; ++i) { - ExceptionCode ec; - segList->appendItem(m_vector[i].release(), ec); - } - m_vector.clear(); - return result; - } - -private: - virtual void svgMoveTo(double x1, double y1, bool, bool abs = true) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegMovetoAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1))); - else - m_vector.append(SVGPathElement::createSVGPathSegMovetoRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1))); - } - virtual void svgLineTo(double x1, double y1, bool abs = true) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegLinetoAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1))); - else - m_vector.append(SVGPathElement::createSVGPathSegLinetoRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1))); - } - virtual void svgLineToHorizontal(double x, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegLinetoHorizontalAbs(narrowPrecisionToFloat(x))); - else - m_vector.append(SVGPathElement::createSVGPathSegLinetoHorizontalRel(narrowPrecisionToFloat(x))); - } - virtual void svgLineToVertical(double y, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegLinetoVerticalAbs(narrowPrecisionToFloat(y))); - else - m_vector.append(SVGPathElement::createSVGPathSegLinetoVerticalRel(narrowPrecisionToFloat(y))); - } - virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegCurvetoCubicAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), - narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), - narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2))); - else - m_vector.append(SVGPathElement::createSVGPathSegCurvetoCubicRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), - narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), - narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2))); - } - virtual void svgCurveToCubicSmooth(double x, double y, double x2, double y2, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2), - narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - else - m_vector.append(SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2), - narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - } - virtual void svgCurveToQuadratic(double x, double y, double x1, double y1, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), - narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - else - m_vector.append(SVGPathElement::createSVGPathSegCurvetoQuadraticRel(narrowPrecisionToFloat(x1), narrowPrecisionToFloat(y1), - narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - } - virtual void svgCurveToQuadraticSmooth(double x, double y, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - else - m_vector.append(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y))); - } - virtual void svgArcTo(double x, double y, double r1, double r2, double angle, bool largeArcFlag, bool sweepFlag, bool abs) - { - if (abs) - m_vector.append(SVGPathElement::createSVGPathSegArcAbs(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), - narrowPrecisionToFloat(r1), narrowPrecisionToFloat(r2), - narrowPrecisionToFloat(angle), largeArcFlag, sweepFlag)); - else - m_vector.append(SVGPathElement::createSVGPathSegArcRel(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), - narrowPrecisionToFloat(r1), narrowPrecisionToFloat(r2), - narrowPrecisionToFloat(angle), largeArcFlag, sweepFlag)); - } - virtual void svgClosePath() - { - m_vector.append(SVGPathElement::createSVGPathSegClosePath()); - } - - Vector<RefPtr<SVGPathSeg> > m_vector; -}; - -bool pathSegListFromSVGData(SVGPathSegList* path, const String& d, bool process) -{ - SVGPathSegListBuilder builder; - return builder.build(path, d, process); -} - bool parseGlyphName(const String& input, HashSet<String>& values) { // FIXME: Parsing error detection is missing. diff --git a/WebCore/svg/SVGParserUtilities.h b/WebCore/svg/SVGParserUtilities.h index cd6cbbe..69d6b12 100644 --- a/WebCore/svg/SVGParserUtilities.h +++ b/WebCore/svg/SVGParserUtilities.h @@ -30,12 +30,11 @@ typedef Vector<UnicodeRange> UnicodeRanges; namespace WebCore { - class Path; class SVGPointList; - class SVGPathSegList; bool parseNumber(const UChar*& ptr, const UChar* end, float& number, bool skip = true); bool parseNumberOptionalNumber(const String& s, float& h, float& v); + bool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag); // SVG allows several different whitespace characters: // http://www.w3.org/TR/SVG/paths.html#PathDataBNF @@ -65,8 +64,6 @@ namespace WebCore { } bool pointsListFromSVGData(SVGPointList* pointsList, const String& points); - bool pathFromSVGData(Path& path, const String& d); - bool pathSegListFromSVGData(SVGPathSegList* pathSegList, const String& d, bool process = false); Vector<String> parseDelimitedString(const String& input, const char seperator); bool parseKerningUnicodeString(const String& input, UnicodeRanges&, HashSet<String>& stringList); bool parseGlyphName(const String& input, HashSet<String>& values); diff --git a/WebCore/svg/SVGPathBuilder.cpp b/WebCore/svg/SVGPathBuilder.cpp new file mode 100644 index 0000000..916c7d0 --- /dev/null +++ b/WebCore/svg/SVGPathBuilder.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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) +#include "SVGPathBuilder.h" + +#include "SVGPathParser.h" + +namespace WebCore { + +SVGPathBuilder::SVGPathBuilder(Path& path) + : m_path(path) +{ +} + +bool SVGPathBuilder::build(const String& d) +{ + SVGPathParser parser(this); + return parser.parsePathDataString(d, true); +} + +void SVGPathBuilder::moveTo(const FloatPoint& point, bool closed, PathCoordinateMode mode) +{ + m_current = mode == AbsoluteCoordinates ? point : m_current + point; + if (closed) + m_path.closeSubpath(); + m_path.moveTo(m_current); +} + +void SVGPathBuilder::lineTo(const FloatPoint& point, PathCoordinateMode mode) +{ + m_current = mode == AbsoluteCoordinates ? point : m_current + point; + m_path.addLineTo(m_current); +} + +void SVGPathBuilder::curveToCubic(const FloatPoint& point1, const FloatPoint& point2, const FloatPoint& point, PathCoordinateMode mode) +{ + if (mode == RelativeCoordinates) { + m_path.addBezierCurveTo(m_current + point1, m_current + point2, m_current + point); + m_current += point; + } else { + m_current = point; + m_path.addBezierCurveTo(point1, point2, m_current); + } +} + +void SVGPathBuilder::closePath() +{ + m_path.closeSubpath(); +} + +} + +#endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGPathBuilder.h b/WebCore/svg/SVGPathBuilder.h new file mode 100644 index 0000000..c47e69d --- /dev/null +++ b/WebCore/svg/SVGPathBuilder.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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 SVGPathBuilder_h +#define SVGPathBuilder_h + +#if ENABLE(SVG) +#include "FloatPoint.h" +#include "Path.h" +#include "SVGPathConsumer.h" + +namespace WebCore { + +class SVGPathBuilder : private SVGPathConsumer { +public: + SVGPathBuilder(Path&); + bool build(const String&); + +private: + // Used in UnalteredParisng/NormalizedParsing modes. + virtual void moveTo(const FloatPoint&, bool closed, PathCoordinateMode); + virtual void lineTo(const FloatPoint&, PathCoordinateMode); + virtual void curveToCubic(const FloatPoint&, const FloatPoint&, const FloatPoint&, PathCoordinateMode); + virtual void closePath(); + +private: + // Only used in UnalteredParsing mode. + virtual void lineToHorizontal(float, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + virtual void lineToVertical(float, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + virtual void curveToCubicSmooth(const FloatPoint&, const FloatPoint&, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + virtual void curveToQuadratic(const FloatPoint&, const FloatPoint&, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + virtual void curveToQuadraticSmooth(const FloatPoint&, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + virtual void arcTo(const FloatPoint&, float, float, float, bool, bool, PathCoordinateMode) { ASSERT_NOT_REACHED(); } + + Path& m_path; + FloatPoint m_current; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGPathBuilder_h diff --git a/WebCore/svg/SVGPathConsumer.h b/WebCore/svg/SVGPathConsumer.h new file mode 100644 index 0000000..7f2fb39 --- /dev/null +++ b/WebCore/svg/SVGPathConsumer.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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 SVGPathConsumer_h +#define SVGPathConsumer_h + +#if ENABLE(SVG) +#include "FloatPoint.h" + +namespace WebCore { + +enum PathCoordinateMode { + AbsoluteCoordinates, + RelativeCoordinates +}; + +enum PathParsingMode { + NormalizedParsing, + UnalteredParsing +}; + +class SVGPathConsumer { +public: + // Used in UnalteredParisng/NormalizedParsing modes. + virtual void moveTo(const FloatPoint&, bool closed, PathCoordinateMode) = 0; + virtual void lineTo(const FloatPoint&, PathCoordinateMode) = 0; + virtual void curveToCubic(const FloatPoint&, const FloatPoint&, const FloatPoint&, PathCoordinateMode) = 0; + virtual void closePath() = 0; + +public: + // Only used in UnalteredParsing mode. + virtual void lineToHorizontal(float, PathCoordinateMode) = 0; + virtual void lineToVertical(float, PathCoordinateMode) = 0; + virtual void curveToCubicSmooth(const FloatPoint&, const FloatPoint&, PathCoordinateMode) = 0; + virtual void curveToQuadratic(const FloatPoint&, const FloatPoint&, PathCoordinateMode) = 0; + virtual void curveToQuadraticSmooth(const FloatPoint&, PathCoordinateMode) = 0; + virtual void arcTo(const FloatPoint&, float, float, float, bool largeArcFlag, bool sweepFlag, PathCoordinateMode) = 0; + +protected: + SVGPathConsumer() { } + virtual ~SVGPathConsumer() { } +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGPathConsumer_h diff --git a/WebCore/svg/SVGPathElement.cpp b/WebCore/svg/SVGPathElement.cpp index 40996d1..803ce14 100644 --- a/WebCore/svg/SVGPathElement.cpp +++ b/WebCore/svg/SVGPathElement.cpp @@ -25,8 +25,8 @@ #include "Attribute.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGNames.h" -#include "SVGParserUtilities.h" #include "SVGPathSegArc.h" #include "SVGPathSegClosePath.h" #include "SVGPathSegCurvetoCubic.h" @@ -37,6 +37,7 @@ #include "SVGPathSegLinetoHorizontal.h" #include "SVGPathSegLinetoVertical.h" #include "SVGPathSegList.h" +#include "SVGPathSegListBuilder.h" #include "SVGPathSegMoveto.h" #include "SVGSVGElement.h" @@ -172,7 +173,8 @@ void SVGPathElement::parseMappedAttribute(Attribute* attr) if (attr->name() == SVGNames::dAttr) { ExceptionCode ec; pathSegList()->clear(ec); - if (!pathSegListFromSVGData(pathSegList(), attr->value(), true)) + SVGPathSegListBuilder parser(pathSegList()); + if (!parser.build(attr->value(), NormalizedParsing)) document()->accessSVGExtensions()->reportError("Problem parsing d=\"" + attr->value() + "\""); } else if (attr->name() == SVGNames::pathLengthAttr) { setPathLengthBaseValue(attr->value().toFloat()); @@ -199,13 +201,13 @@ void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName) if (attrName == SVGNames::dAttr) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } @@ -213,7 +215,7 @@ void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName) || SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGPathElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGPathParser.cpp b/WebCore/svg/SVGPathParser.cpp new file mode 100644 index 0000000..3d937c0 --- /dev/null +++ b/WebCore/svg/SVGPathParser.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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) +#include "SVGPathParser.h" + +#include "AffineTransform.h" +#include "SVGParserUtilities.h" +#include <wtf/MathExtras.h> + +static const float gOneOverThree = 1 / 3.f; + +namespace WebCore { + +SVGPathParser::SVGPathParser(SVGPathConsumer* consumer) + : m_consumer(consumer) +{ +} + +SVGPathParser::~SVGPathParser() +{ +} + +void SVGPathParser::parseClosePathSegment() +{ + // Reset m_currentPoint for the next path. + if (m_normalized) + m_currentPoint = m_subPathPoint; + m_pathClosed = true; + m_consumer->closePath(); +} + +bool SVGPathParser::parseMoveToSegment() +{ + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, toX) || !parseNumber(m_ptr, m_end, toY)) + return false; + + FloatPoint toPoint(toX, toY); + if (m_normalized) { + if (m_mode == RelativeCoordinates) + m_currentPoint += toPoint; + else + m_currentPoint = toPoint; + m_subPathPoint = m_currentPoint; + m_consumer->moveTo(m_currentPoint, m_pathClosed, AbsoluteCoordinates); + } else + m_consumer->moveTo(toPoint, m_pathClosed, m_mode); + m_pathClosed = false; + return true; +} + +bool SVGPathParser::parseLineToSegment() +{ + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, toX) || !parseNumber(m_ptr, m_end, toY)) + return false; + + FloatPoint toPoint(toX, toY); + if (m_normalized) { + if (m_mode == RelativeCoordinates) + m_currentPoint += toPoint; + else + m_currentPoint = toPoint; + m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); + } else + m_consumer->lineTo(toPoint, m_mode); + return true; +} + +bool SVGPathParser::parseLineToHorizontalSegment() +{ + float toX; + if (!parseNumber(m_ptr, m_end, toX)) + return false; + + if (m_normalized) { + if (m_mode == RelativeCoordinates) + m_currentPoint.move(toX, 0); + else + m_currentPoint.setX(toX); + m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); + } else + m_consumer->lineToHorizontal(toX, m_mode); + return true; +} + +bool SVGPathParser::parseLineToVerticalSegment() +{ + float toY; + if (!parseNumber(m_ptr, m_end, toY)) + return false; + + if (m_normalized) { + if (m_mode == RelativeCoordinates) + m_currentPoint.move(0, toY); + else + m_currentPoint.setY(toY); + m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); + } else + m_consumer->lineToVertical(toY, m_mode); + return true; +} + +bool SVGPathParser::parseCurveToCubicSegment() +{ + float x1; + float y1; + float x2; + float y2; + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, x1) + || !parseNumber(m_ptr, m_end, y1) + || !parseNumber(m_ptr, m_end, x2) + || !parseNumber(m_ptr, m_end, y2) + || !parseNumber(m_ptr, m_end, toX) + || !parseNumber(m_ptr, m_end, toY)) + return false; + + FloatPoint point1(x1, y1); + FloatPoint point2(x2, y2); + FloatPoint point3(toX, toY); + if (m_normalized) { + if (m_mode == RelativeCoordinates) { + point1 += m_currentPoint; + point2 += m_currentPoint; + point3 += m_currentPoint; + } + m_consumer->curveToCubic(point1, point2, point3, AbsoluteCoordinates); + + m_controlPoint = point2; + m_currentPoint = point3; + } else + m_consumer->curveToCubic(point1, point2, point3, m_mode); + return true; +} + +bool SVGPathParser::parseCurveToCubicSmoothSegment() +{ + float x2; + float y2; + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, x2) + || !parseNumber(m_ptr, m_end, y2) + || !parseNumber(m_ptr, m_end, toX) + || !parseNumber(m_ptr, m_end, toY)) + return false; + + if (m_lastCommand != 'c' + && m_lastCommand != 'C' + && m_lastCommand != 's' + && m_lastCommand != 'S') + m_controlPoint = m_currentPoint; + + FloatPoint point2(x2, y2); + FloatPoint point3(toX, toY); + if (m_normalized) { + FloatPoint point1 = m_currentPoint; + point1.scale(2, 2); + point1.move(-m_controlPoint.x(), -m_controlPoint.y()); + if (m_mode == RelativeCoordinates) { + point2 += m_currentPoint; + point3 += m_currentPoint; + } + + m_consumer->curveToCubic(point1, point2, point3, AbsoluteCoordinates); + + m_controlPoint = point2; + m_currentPoint = point3; + } else + m_consumer->curveToCubicSmooth(point2, point3, m_mode); + return true; +} + +bool SVGPathParser::parseCurveToQuadraticSegment() +{ + float x1; + float y1; + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, x1) + || !parseNumber(m_ptr, m_end, y1) + || !parseNumber(m_ptr, m_end, toX) + || !parseNumber(m_ptr, m_end, toY)) + return false; + + FloatPoint point3(toX, toY); + if (m_normalized) { + FloatPoint point1 = m_currentPoint; + point1.move(2 * x1, 2 * y1); + FloatPoint point2(toX + 2 * x1, toY + 2 * y1); + if (m_mode == RelativeCoordinates) { + point1.move(2 * m_currentPoint.x(), 2 * m_currentPoint.y()); + point2.move(3 * m_currentPoint.x(), 3 * m_currentPoint.y()); + point3 += m_currentPoint; + } + point1.scale(gOneOverThree, gOneOverThree); + point2.scale(gOneOverThree, gOneOverThree); + + m_consumer->curveToCubic(point1, point2, point3, AbsoluteCoordinates); + + m_controlPoint = FloatPoint(x1, y1); + if (m_mode == RelativeCoordinates) + m_controlPoint += m_currentPoint; + m_currentPoint = point3; + } else + m_consumer->curveToQuadratic(FloatPoint(x1, y1), point3, m_mode); + return true; +} + +bool SVGPathParser::parseCurveToQuadraticSmoothSegment() +{ + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, toX) || !parseNumber(m_ptr, m_end, toY)) + return false; + if (m_lastCommand != 'q' + && m_lastCommand != 'Q' + && m_lastCommand != 't' + && m_lastCommand != 'T') + m_controlPoint = m_currentPoint; + + if (m_normalized) { + FloatPoint cubicPoint = m_currentPoint; + cubicPoint.scale(2, 2); + cubicPoint.move(-m_controlPoint.x(), -m_controlPoint.y()); + FloatPoint point1(m_currentPoint.x() + 2 * cubicPoint.x(), m_currentPoint.y() + 2 * cubicPoint.y()); + FloatPoint point2(toX + 2 * cubicPoint.x(), toY + 2 * cubicPoint.y()); + FloatPoint point3(toX, toY); + if (m_mode == RelativeCoordinates) { + point2 += m_currentPoint; + point3 += m_currentPoint; + } + point1.scale(gOneOverThree, gOneOverThree); + point2.scale(gOneOverThree, gOneOverThree); + + m_consumer->curveToCubic(point1, point2, point3, AbsoluteCoordinates); + + m_controlPoint = cubicPoint; + m_currentPoint = point3; + } else + m_consumer->curveToQuadraticSmooth(FloatPoint(toX, toY), m_mode); + return true; +} + +bool SVGPathParser::parseArcToSegment() +{ + bool largeArc; + bool sweep; + float angle; + float rx; + float ry; + float toX; + float toY; + if (!parseNumber(m_ptr, m_end, rx) + || !parseNumber(m_ptr, m_end, ry) + || !parseNumber(m_ptr, m_end, angle) + || !parseArcFlag(m_ptr, m_end, largeArc) + || !parseArcFlag(m_ptr, m_end, sweep) + || !parseNumber(m_ptr, m_end, toX) + || !parseNumber(m_ptr, m_end, toY)) + return false; + + FloatPoint point2 = FloatPoint(toX, toY); + // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") joining the endpoints. + // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters + rx = fabsf(rx); + ry = fabsf(ry); + if (!rx || !ry) { + if (m_normalized) { + if (m_mode == RelativeCoordinates) + m_currentPoint += point2; + else + m_currentPoint = point2; + m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); + } else + m_consumer->lineTo(point2, m_mode); + return true; + } + + if (m_normalized) { + FloatPoint point1 = m_currentPoint; + if (m_mode == RelativeCoordinates) + point2 += m_currentPoint; + m_currentPoint = point2; + return decomposeArcToCubic(angle, rx, ry, point1, point2, largeArc, sweep); + } + m_consumer->arcTo(point2, rx, ry, angle, largeArc, sweep, m_mode); + return true; +} + +bool SVGPathParser::parsePathDataString(const String& s, bool normalized) +{ + m_ptr = s.characters(); + m_end = m_ptr + s.length(); + m_normalized = normalized; + + m_controlPoint = FloatPoint(); + m_currentPoint = FloatPoint(); + m_subPathPoint = FloatPoint(); + m_pathClosed = true; + + // Skip any leading spaces. + if (!skipOptionalSpaces(m_ptr, m_end)) + return false; + + char command = *(m_ptr++); + m_lastCommand = ' '; + // Path must start with moveto. + if (command != 'm' && command != 'M') + return false; + + while (true) { + // Skip spaces between command and first coordinate. + skipOptionalSpaces(m_ptr, m_end); + m_mode = command >= 'a' && command <= 'z' ? RelativeCoordinates : AbsoluteCoordinates; + switch (command) { + case 'm': + case 'M': + if (!parseMoveToSegment()) + return false; + break; + case 'l': + case 'L': + if (!parseLineToSegment()) + return false; + break; + case 'h': + case 'H': + if (!parseLineToHorizontalSegment()) + return false; + break; + case 'v': + case 'V': + if (!parseLineToVerticalSegment()) + return false; + break; + case 'z': + case 'Z': + parseClosePathSegment(); + break; + case 'c': + case 'C': + if (!parseCurveToCubicSegment()) + return false; + break; + case 's': + case 'S': + if (!parseCurveToCubicSmoothSegment()) + return false; + break; + case 'q': + case 'Q': + if (!parseCurveToQuadraticSegment()) + return false; + break; + case 't': + case 'T': + if (!parseCurveToQuadraticSmoothSegment()) + return false; + break; + case 'a': + case 'A': + if (!parseArcToSegment()) + return false; + break; + default: + return false; + } + m_lastCommand = command; + + if (m_ptr >= m_end) + return true; + + // Check for remaining coordinates in the current command. + if ((*m_ptr == '+' || *m_ptr == '-' || *m_ptr == '.' || (*m_ptr >= '0' && *m_ptr <= '9')) + && command != 'z' && command != 'Z') { + if (command == 'M') + command = 'L'; + else if (command == 'm') + command = 'l'; + } else + command = *(m_ptr++); + + if (m_lastCommand != 'C' && m_lastCommand != 'c' + && m_lastCommand != 'S' && m_lastCommand != 's' + && m_lastCommand != 'Q' && m_lastCommand != 'q' + && m_lastCommand != 'T' && m_lastCommand != 't') + m_controlPoint = m_currentPoint; + } + + return false; +} + +// This works by converting the SVG arc to "simple" beziers. +// Partly adapted from Niko's code in kdelibs/kdecore/svgicons. +// See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter +bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, FloatPoint& point1, FloatPoint& point2, bool largeArcFlag, bool sweepFlag) +{ + FloatSize midPointDistance = point1 - point2; + midPointDistance.scale(0.5f); + + AffineTransform pointTransform; + pointTransform.rotate(-angle); + + FloatPoint transformedMidPoint = pointTransform.mapPoint(FloatPoint(midPointDistance.width(), midPointDistance.height())); + float squareRx = rx * rx; + float squareRy = ry * ry; + float squareX = transformedMidPoint.x() * transformedMidPoint.x(); + float squareY = transformedMidPoint.y() * transformedMidPoint.y(); + + // Check if the radii are big enough to draw the arc, scale radii if not. + // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii + float radiiScale = squareX / squareRx + squareY / squareRy; + if (radiiScale > 1) { + rx *= sqrtf(radiiScale); + ry *= sqrtf(radiiScale); + } + + pointTransform.makeIdentity(); + pointTransform.scale(1 / rx, 1 / ry); + pointTransform.rotate(-angle); + + point1 = pointTransform.mapPoint(point1); + point2 = pointTransform.mapPoint(point2); + FloatSize delta = point2 - point1; + + float d = delta.width() * delta.width() + delta.height() * delta.height(); + float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f); + + float scaleFactor = sqrtf(scaleFactorSquared); + if (sweepFlag == largeArcFlag) + scaleFactor = -scaleFactor; + + delta.scale(scaleFactor); + FloatPoint centerPoint = FloatPoint(0.5f * (point1.x() + point2.x()) - delta.height(), + 0.5f * (point1.y() + point2.y()) + delta.width()); + + float theta1 = atan2f(point1.y() - centerPoint.y(), point1.x() - centerPoint.x()); + float theta2 = atan2f(point2.y() - centerPoint.y(), point2.x() - centerPoint.x()); + + float thetaArc = theta2 - theta1; + if (thetaArc < 0 && sweepFlag) + thetaArc += 2 * piFloat; + else if (thetaArc > 0 && !sweepFlag) + thetaArc -= 2 * piFloat; + + pointTransform.makeIdentity(); + pointTransform.rotate(angle); + pointTransform.scale(rx, ry); + + // Some results of atan2 on some platform implementations are not exact enough. So that we get more + // cubic curves than expected here. Adding 0.001f reduces the count of sgements to the correct count. + int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f))); + for (int i = 0; i < segments; ++i) { + float startTheta = theta1 + i * thetaArc / segments; + float endTheta = theta1 + (i + 1) * thetaArc / segments; + + float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta)); + if (!isfinite(t)) + return false; + float sinStartTheta = sinf(startTheta); + float cosStartTheta = cosf(startTheta); + float sinEndTheta = sinf(endTheta); + float cosEndTheta = cosf(endTheta); + + point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta); + point1.move(centerPoint.x(), centerPoint.y()); + FloatPoint point3 = FloatPoint(cosEndTheta, sinEndTheta); + point3.move(centerPoint.x(), centerPoint.y()); + point2 = point3; + point2.move(t * sinEndTheta, -t * cosEndTheta); + + m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform.mapPoint(point2), + pointTransform.mapPoint(point3), AbsoluteCoordinates); + } + return true; +} + +} + +#endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGPathParser.h b/WebCore/svg/SVGPathParser.h new file mode 100644 index 0000000..f39094b --- /dev/null +++ b/WebCore/svg/SVGPathParser.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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 SVGPathParser_h +#define SVGPathParser_h + +#if ENABLE(SVG) +#include "PlatformString.h" +#include "SVGPathConsumer.h" + +namespace WebCore { + +class SVGPathParser { +public: + SVGPathParser(SVGPathConsumer*); + ~SVGPathParser(); + + bool parsePathDataString(const String&, bool normalized = false); + +private: + bool decomposeArcToCubic(float, float, float, FloatPoint&, FloatPoint&, bool largeArcFlag, bool sweepFlag); + void parseClosePathSegment(); + bool parseMoveToSegment(); + bool parseLineToSegment(); + bool parseLineToHorizontalSegment(); + bool parseLineToVerticalSegment(); + bool parseCurveToCubicSegment(); + bool parseCurveToCubicSmoothSegment(); + bool parseCurveToQuadraticSegment(); + bool parseCurveToQuadraticSmoothSegment(); + bool parseArcToSegment(); + + SVGPathConsumer* m_consumer; + PathCoordinateMode m_mode; + const UChar* m_ptr; + const UChar* m_end; + char m_lastCommand; + bool m_normalized; + bool m_pathClosed; + FloatPoint m_controlPoint; + FloatPoint m_currentPoint; + FloatPoint m_subPathPoint; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGPathParser_h diff --git a/WebCore/svg/SVGPathSegListBuilder.cpp b/WebCore/svg/SVGPathSegListBuilder.cpp new file mode 100644 index 0000000..4434c2e --- /dev/null +++ b/WebCore/svg/SVGPathSegListBuilder.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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) +#include "SVGPathSegListBuilder.h" + +#include "ExceptionCode.h" +#include "SVGPathElement.h" +#include "SVGPathParser.h" +#include "SVGPathSegArc.h" +#include "SVGPathSegClosePath.h" +#include "SVGPathSegCurvetoCubic.h" +#include "SVGPathSegCurvetoCubicSmooth.h" +#include "SVGPathSegCurvetoQuadratic.h" +#include "SVGPathSegCurvetoQuadraticSmooth.h" +#include "SVGPathSegLineto.h" +#include "SVGPathSegLinetoHorizontal.h" +#include "SVGPathSegLinetoVertical.h" +#include "SVGPathSegList.h" +#include "SVGPathSegMoveto.h" + +namespace WebCore { + +SVGPathSegListBuilder::SVGPathSegListBuilder(SVGPathSegList* segList) + : m_pathSegList(segList) +{ +} + +bool SVGPathSegListBuilder::build(const String& d, PathParsingMode parsingMode) +{ + if (!m_pathSegList) + return false; + + SVGPathParser parser(this); + return parser.parsePathDataString(d, parsingMode == NormalizedParsing); +} + +void SVGPathSegListBuilder::moveTo(const FloatPoint& point, bool, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegMovetoAbs(point.x(), point.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegMovetoRel(point.x(), point.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::lineTo(const FloatPoint& point, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoAbs(point.x(), point.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoRel(point.x(), point.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::lineToHorizontal(float x, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalAbs(x), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoHorizontalRel(x), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::lineToVertical(float y, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalAbs(y), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegLinetoVerticalRel(y), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::curveToCubic(const FloatPoint& point1, const FloatPoint& point2, const FloatPoint& point, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicAbs(point.x(), point.y(), point1.x(), point1.y(), point2.x(), point2.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicRel(point.x(), point.y(), point1.x(), point1.y(), point2.x(), point2.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::curveToCubicSmooth(const FloatPoint& point, const FloatPoint& point2, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(point2.x(), point2.y(), point.x(), point.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(point2.x(), point2.y(), point.x(), point.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::curveToQuadratic(const FloatPoint& point, const FloatPoint& point1, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(point1.x(), point1.y(), point.x(), point.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticRel(point1.x(), point1.y(), point.x(), point.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::curveToQuadraticSmooth(const FloatPoint& point, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(point.x(), point.y()), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(point.x(), point.y()), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::arcTo(const FloatPoint& point, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag, PathCoordinateMode mode) +{ + ExceptionCode ec = 0; + if (mode == AbsoluteCoordinates) + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegArcAbs(point.x(), point.y(), r1, r2, angle, largeArcFlag, sweepFlag), ec); + else + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegArcRel(point.x(), point.y(), r1, r2, angle, largeArcFlag, sweepFlag), ec); + ASSERT(!ec); +} + +void SVGPathSegListBuilder::closePath() +{ + ExceptionCode ec = 0; + m_pathSegList->appendItem(SVGPathElement::createSVGPathSegClosePath(), ec); + ASSERT(!ec); +} + +} + +#endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGPathSegListBuilder.h b/WebCore/svg/SVGPathSegListBuilder.h new file mode 100644 index 0000000..71d0dde --- /dev/null +++ b/WebCore/svg/SVGPathSegListBuilder.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002, 2003 The Karbon Developers + * 2006 Alexander Kellett <lypanov@kde.org> + * 2006, 2007 Rob Buis <buis@kde.org> + * Copyrigth (C) 2007, 2009 Apple, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * 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 SVGPathSegListBuilder_h +#define SVGPathSegListBuilder_h + +#if ENABLE(SVG) +#include "FloatPoint.h" +#include "SVGPathConsumer.h" +#include "SVGPathSegList.h" + +namespace WebCore { + +class SVGPathSegListBuilder : private SVGPathConsumer { +public: + SVGPathSegListBuilder(SVGPathSegList*); + bool build(const String&, PathParsingMode); + +private: + // Used in UnalteredParisng/NormalizedParsing modes. + virtual void moveTo(const FloatPoint&, bool closed, PathCoordinateMode); + virtual void lineTo(const FloatPoint&, PathCoordinateMode); + virtual void curveToCubic(const FloatPoint&, const FloatPoint&, const FloatPoint&, PathCoordinateMode); + virtual void closePath(); + +private: + // Only used in UnalteredParsing mode. + virtual void lineToHorizontal(float, PathCoordinateMode); + virtual void lineToVertical(float, PathCoordinateMode); + virtual void curveToCubicSmooth(const FloatPoint&, const FloatPoint&, PathCoordinateMode); + virtual void curveToQuadratic(const FloatPoint&, const FloatPoint&, PathCoordinateMode); + virtual void curveToQuadraticSmooth(const FloatPoint&, PathCoordinateMode); + virtual void arcTo(const FloatPoint&, float, float, float, bool largeArcFlag, bool sweepFlag, PathCoordinateMode); + + SVGPathSegList* m_pathSegList; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGPathSegListBuilder_h diff --git a/WebCore/svg/SVGPolyElement.cpp b/WebCore/svg/SVGPolyElement.cpp index 6f88b22..2996dd7 100644 --- a/WebCore/svg/SVGPolyElement.cpp +++ b/WebCore/svg/SVGPolyElement.cpp @@ -27,6 +27,7 @@ #include "Document.h" #include "FloatPoint.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGNames.h" #include "SVGParserUtilities.h" #include "SVGPointList.h" @@ -94,20 +95,20 @@ void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (attrName == SVGNames::pointsAttr) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGPolyElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGRectElement.cpp b/WebCore/svg/SVGRectElement.cpp index 3e559ed..a848246 100644 --- a/WebCore/svg/SVGRectElement.cpp +++ b/WebCore/svg/SVGRectElement.cpp @@ -25,6 +25,7 @@ #include "Attribute.h" #include "RenderPath.h" +#include "RenderSVGResource.h" #include "SVGLength.h" #include "SVGNames.h" @@ -101,20 +102,20 @@ void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (isLengthAttribute) { renderer->setNeedsPathUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); return; } if (SVGTests::isKnownAttribute(attrName) || SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName)) - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } void SVGRectElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGSVGElement.cpp b/WebCore/svg/SVGSVGElement.cpp index 6d88c37..c513b98 100644 --- a/WebCore/svg/SVGSVGElement.cpp +++ b/WebCore/svg/SVGSVGElement.cpp @@ -35,6 +35,7 @@ #include "FloatRect.h" #include "FrameView.h" #include "HTMLNames.h" +#include "RenderSVGResource.h" #include "RenderSVGRoot.h" #include "RenderSVGViewportContainer.h" #include "SMILTimeContainer.h" @@ -204,8 +205,8 @@ void SVGSVGElement::setCurrentScale(float scale) } m_scale = scale; - if (renderer()) - renderer()->setNeedsLayout(true); + if (RenderObject* object = renderer()) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(object); } FloatPoint SVGSVGElement::currentTranslate() const @@ -320,7 +321,7 @@ void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGZoomAndPan::isKnownAttribute(attrName) || SVGStyledLocatableElement::isKnownAttribute(attrName)) - renderer()->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer()); } void SVGSVGElement::synchronizeProperty(const QualifiedName& attrName) @@ -579,7 +580,9 @@ void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement) if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr)) currentView()->setZoomAndPan(viewElement->zoomAndPan()); - renderer()->setNeedsLayout(true); + + if (RenderObject* object = renderer()) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(object); } void SVGSVGElement::documentWillBecomeInactive() diff --git a/WebCore/svg/SVGStopElement.cpp b/WebCore/svg/SVGStopElement.cpp index 672b082..36d4338 100644 --- a/WebCore/svg/SVGStopElement.cpp +++ b/WebCore/svg/SVGStopElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "Document.h" #include "RenderSVGGradientStop.h" +#include "RenderSVGResource.h" #include "SVGGradientElement.h" #include "SVGNames.h" @@ -33,7 +34,7 @@ namespace WebCore { SVGStopElement::SVGStopElement(const QualifiedName& tagName, Document* doc) : SVGStyledElement(tagName, doc) - , m_offset(0.0f) + , m_offset(0) { } @@ -53,6 +54,17 @@ void SVGStopElement::parseMappedAttribute(Attribute* attr) SVGStyledElement::parseMappedAttribute(attr); } +void SVGStopElement::svgAttributeChanged(const QualifiedName& attrName) +{ + SVGStyledElement::svgAttributeChanged(attrName); + + if (!renderer()) + return; + + if (attrName == SVGNames::offsetAttr) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer()); +} + void SVGStopElement::synchronizeProperty(const QualifiedName& attrName) { SVGStyledElement::synchronizeProperty(attrName); diff --git a/WebCore/svg/SVGStopElement.h b/WebCore/svg/SVGStopElement.h index db5eff0..96c3294 100644 --- a/WebCore/svg/SVGStopElement.h +++ b/WebCore/svg/SVGStopElement.h @@ -33,6 +33,7 @@ namespace WebCore { virtual ~SVGStopElement(); virtual void parseMappedAttribute(Attribute*); + virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); Color stopColorIncludingOpacity() const; diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index 6b55683..6c2993c 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -246,14 +246,6 @@ void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName) object->toRenderSVGResourceContainer()->idChanged(); } - if (!document()->parsing() && object) { - // If we're the child of a resource element, tell the resource (and eventually its resources) that we've changed. - invalidateResourcesInAncestorChain(); - - // If we're referencing resources, tell them we've changed. - RenderSVGResource::invalidateAllResourcesOfRenderer(object); - } - // Invalidate all SVGElementInstances associated with us SVGElementInstance::invalidateAllInstancesOfElement(this); } @@ -266,27 +258,11 @@ void SVGStyledElement::synchronizeProperty(const QualifiedName& attrName) synchronizeClassName(); } -void SVGStyledElement::invalidateResourcesInAncestorChain() const -{ - Node* node = parentNode(); - while (node) { - if (!node->isSVGElement()) - break; - - SVGElement* element = static_cast<SVGElement*>(node); - if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) { - styledElement->invalidateResourceClients(); - - // If we found the first resource in the ancestor chain, immediately stop. - break; - } - - node = node->parentNode(); - } -} - void SVGStyledElement::invalidateResourceClients() { + if (document()->parsing()) + return; + RenderObject* object = renderer(); if (!object) return; diff --git a/WebCore/svg/SVGStyledElement.h b/WebCore/svg/SVGStyledElement.h index dcfc96a..4982908 100644 --- a/WebCore/svg/SVGStyledElement.h +++ b/WebCore/svg/SVGStyledElement.h @@ -65,7 +65,6 @@ namespace WebCore { PassRefPtr<RenderStyle> resolveStyle(RenderStyle* parentStyle); void invalidateResourceClients(); - void invalidateResourcesInAncestorChain() const; bool instanceUpdatesBlocked() const; void setInstanceUpdatesBlocked(bool); diff --git a/WebCore/svg/SVGTRefElement.cpp b/WebCore/svg/SVGTRefElement.cpp index 4faa633..4c593ca 100644 --- a/WebCore/svg/SVGTRefElement.cpp +++ b/WebCore/svg/SVGTRefElement.cpp @@ -24,6 +24,7 @@ #include "SVGTRefElement.h" #include "RenderSVGInline.h" +#include "RenderSVGResource.h" #include "SVGDocument.h" #include "SVGNames.h" #include "Text.h" @@ -69,7 +70,7 @@ void SVGTRefElement::svgAttributeChanged(const QualifiedName& attrName) return; if (SVGURIReference::isKnownAttribute(attrName)) - renderer()->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer()); } void SVGTRefElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGTextElement.cpp b/WebCore/svg/SVGTextElement.cpp index 0aba04b..7269adf 100644 --- a/WebCore/svg/SVGTextElement.cpp +++ b/WebCore/svg/SVGTextElement.cpp @@ -26,6 +26,7 @@ #include "AffineTransform.h" #include "Attribute.h" #include "FloatRect.h" +#include "RenderSVGResource.h" #include "RenderSVGText.h" #include "SVGLengthList.h" #include "SVGRenderStyle.h" @@ -120,7 +121,7 @@ void SVGTextElement::svgAttributeChanged(const QualifiedName& attrName) if (SVGTransformable::isKnownAttribute(attrName)) { renderer->setNeedsTransformUpdate(); - renderer->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer); } } diff --git a/WebCore/svg/SVGTextPathElement.cpp b/WebCore/svg/SVGTextPathElement.cpp index 288edfd..732185d 100644 --- a/WebCore/svg/SVGTextPathElement.cpp +++ b/WebCore/svg/SVGTextPathElement.cpp @@ -25,6 +25,7 @@ #include "AffineTransform.h" #include "Attribute.h" #include "FloatRect.h" +#include "RenderSVGResource.h" #include "RenderSVGTextPath.h" #include "SVGLengthList.h" #include "SVGPathElement.h" @@ -82,7 +83,7 @@ void SVGTextPathElement::svgAttributeChanged(const QualifiedName& attrName) if (attrName == SVGNames::startOffsetAttr || SVGTextContentElement::isKnownAttribute(attrName) || SVGURIReference::isKnownAttribute(attrName)) - renderer()->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer()); } void SVGTextPathElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGTextPositioningElement.cpp b/WebCore/svg/SVGTextPositioningElement.cpp index ef47322..19f1fbc 100644 --- a/WebCore/svg/SVGTextPositioningElement.cpp +++ b/WebCore/svg/SVGTextPositioningElement.cpp @@ -25,6 +25,7 @@ #include "Attribute.h" #include "RenderObject.h" +#include "RenderSVGResource.h" #include "SVGLengthList.h" #include "SVGNames.h" #include "SVGNumberList.h" @@ -75,7 +76,7 @@ void SVGTextPositioningElement::svgAttributeChanged(const QualifiedName& attrNam return; if (isKnownAttribute(attrName)) - renderer()->setNeedsLayout(true); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer()); } void SVGTextPositioningElement::synchronizeProperty(const QualifiedName& attrName) diff --git a/WebCore/svg/SVGUseElement.cpp b/WebCore/svg/SVGUseElement.cpp index 5ca560a..e42a794 100644 --- a/WebCore/svg/SVGUseElement.cpp +++ b/WebCore/svg/SVGUseElement.cpp @@ -32,6 +32,7 @@ #include "HTMLNames.h" #include "NodeRenderStyle.h" #include "RegisteredEventListener.h" +#include "RenderSVGResource.h" #include "RenderSVGShadowTreeRootContainer.h" #include "SVGElementInstance.h" #include "SVGElementInstanceList.h" @@ -142,7 +143,8 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) if (isXYAttribute || isWidthHeightAttribute) updateRelativeLengthsInformation(); - if (!renderer()) + RenderObject* object = renderer(); + if (!object) return; if (SVGURIReference::isKnownAttribute(attrName)) { @@ -173,8 +175,8 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) } if (SVGStyledTransformableElement::isKnownAttribute(attrName)) { - renderer()->setNeedsTransformUpdate(); - renderer()->setNeedsLayout(true); + object->setNeedsTransformUpdate(); + RenderSVGResource::markForLayoutAndParentResourceInvalidation(object); return; } @@ -256,8 +258,8 @@ void SVGUseElement::updateContainerSizes() // Update whole subtree, scanning for shadow container elements, that correspond to <svg>/<symbol> tags updateContainerSize(this, m_targetElementInstance.get()); - if (renderer()) - renderer()->setNeedsLayout(true); + if (RenderObject* object = renderer()) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(object); } static void updateContainerOffset(SVGElementInstance* targetInstance) @@ -308,8 +310,8 @@ void SVGUseElement::updateContainerOffsets() // Update whole subtree, scanning for shadow container elements, marking a cloned use subtree updateContainerOffset(m_targetElementInstance.get()); - if (renderer()) - renderer()->setNeedsLayout(true); + if (RenderObject* object = renderer()) + RenderSVGResource::markForLayoutAndParentResourceInvalidation(object); } void SVGUseElement::recalcStyle(StyleChange change) diff --git a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp index 39b3e57..ddd4928 100644 --- a/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp +++ b/WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp @@ -194,13 +194,27 @@ void FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha) and would make it really hard to understand. */ -static ALWAYS_INLINE unsigned char clampRGBAValue(float rgba) +static ALWAYS_INLINE unsigned char clampRGBAValue(float channel, unsigned char max = 255) { - if (rgba <= 0) + if (channel <= 0) return 0; - if (rgba >= 255) - return 255; - return rgba; + if (channel >= max) + return max; + return channel; +} + +template<bool preserveAlphaValues> +ALWAYS_INLINE void setDestinationPixels(CanvasPixelArray* image, int& pixel, float* totals, float divisor, float bias, CanvasPixelArray* src) +{ + unsigned char maxAlpha = preserveAlphaValues ? 255 : clampRGBAValue(totals[3] / divisor + bias); + for (int i = 0; i < 3; ++i) + image->set(pixel++, clampRGBAValue(totals[i] / divisor + bias, maxAlpha)); + + if (preserveAlphaValues) { + image->set(pixel, src->get(pixel)); + ++pixel; + } else + image->set(pixel++, maxAlpha); } // Only for region C @@ -244,15 +258,7 @@ ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintin } } - 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; - } + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); startKernelPixel += 4; } pixel += xIncrease; @@ -337,15 +343,7 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in } } - 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; - } + setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); ++startKernelPixelX; } pixel += xIncrease; |