2011-11-08 Nikolas Zimmermann <nzimmermann@rim.com>
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Nov 2011 14:14:35 +0000 (14:14 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Nov 2011 14:14:35 +0000 (14:14 +0000)
        Introduce SVGLengthContext, to allow to resolve relative units to arbitary viewports
        https://bugs.webkit.org/show_bug.cgi?id=71780

        Reviewed by Zoltan Herczeg.

        Introduce SVGLengthContext to cleanup SVGLength, by moving all conversion of relative units that depend on style or viewport
        out of SVGLength, into SVGLengthContext. Pass SVGLengthContext& to SVGLength::value/setValue/... functions instead of a pure
        "const SVGElement* context", which was previously used to determine the viewport when resolving percentage units.
        SVGLengthContext carries an additional FloatRect of the custom viewport, to which percentages are resolved, if specified.

        This allows us to kill several duplicates of the same code, which handles objectBoundingBox mode for gradients/patterns/masks/etc..
        A follow-up patch will convert filters to use the new SVGLengthContext::resolveRectangle code as well.

        This is a preparation for bug 10430, to fix feImage + objectBoundingBox support when rendering referenced elements, instead of files.

        Doesn't affect any tests yet.

        * CMakeLists.txt:
        * GNUmakefile.list.am:
        * Target.pri:
        * WebCore.gypi:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * rendering/svg/RenderSVGResourceGradient.cpp:
        (WebCore::RenderSVGResourceGradient::applyResource):
        * rendering/svg/RenderSVGResourceGradient.h:
        * rendering/svg/RenderSVGResourceLinearGradient.h:
        (WebCore::RenderSVGResourceLinearGradient::gradientUnits):
        * rendering/svg/RenderSVGResourcePattern.cpp:
        (WebCore::RenderSVGResourcePattern::applyResource):
        (WebCore::calculatePatternBoundaries):
        (WebCore::RenderSVGResourcePattern::buildTileImageTransform):
        (WebCore::RenderSVGResourcePattern::createTileImage):
        * rendering/svg/RenderSVGResourceRadialGradient.h:
        (WebCore::RenderSVGResourceRadialGradient::gradientUnits):
        * rendering/svg/SVGRenderTreeAsText.cpp:
        (WebCore::writeCommonGradientProperties):
        (WebCore::writeSVGResourceContainer):
        * svg/GradientAttributes.h:
        (WebCore::GradientAttributes::GradientAttributes):
        (WebCore::GradientAttributes::gradientUnits):
        (WebCore::GradientAttributes::setGradientUnits):
        (WebCore::GradientAttributes::hasGradientUnits):
        * svg/PatternAttributes.h:
        (WebCore::PatternAttributes::PatternAttributes):
        (WebCore::PatternAttributes::patternUnits):
        (WebCore::PatternAttributes::patternContentUnits):
        (WebCore::PatternAttributes::setPatternUnits):
        (WebCore::PatternAttributes::setPatternContentUnits):
        (WebCore::PatternAttributes::hasPatternUnits):
        (WebCore::PatternAttributes::hasPatternContentUnits):
        * svg/SVGAllInOne.cpp:
        * svg/SVGElement.h:
        (WebCore::SVGElement::operator SVGLengthContext):
        * svg/SVGFilterElement.cpp:
        (WebCore::SVGFilterElement::filterBoundingBox):
        * svg/SVGLength.cpp:
        (WebCore::SVGLength::SVGLength):
        (WebCore::SVGLength::unitMode):
        (WebCore::SVGLength::value):
        (WebCore::SVGLength::setValue):
        (WebCore::SVGLength::convertToSpecifiedUnits):
        * svg/SVGLength.h:
        (WebCore::SVGLength::blend):
        * svg/SVGLengthContext.cpp: Added.
        (WebCore::SVGLengthContext::SVGLengthContext):
        (WebCore::SVGLengthContext::resolveRectangle):
        (WebCore::SVGLengthContext::resolvePoint):
        (WebCore::SVGLengthContext::resolveLength):
        (WebCore::SVGLengthContext::convertValueToUserUnits):
        (WebCore::SVGLengthContext::convertValueFromUserUnits):
        (WebCore::SVGLengthContext::convertValueFromUserUnitsToPercentage):
        (WebCore::SVGLengthContext::convertValueFromPercentageToUserUnits):
        (WebCore::SVGLengthContext::convertValueFromUserUnitsToEMS):
        (WebCore::SVGLengthContext::convertValueFromEMSToUserUnits):
        (WebCore::SVGLengthContext::convertValueFromUserUnitsToEXS):
        (WebCore::SVGLengthContext::convertValueFromEXSToUserUnits):
        (WebCore::SVGLengthContext::determineViewport):
        * svg/SVGLengthContext.h: Added.
        (WebCore::SVGLengthContext::resolveRectangle):
        * svg/SVGLinearGradientElement.cpp:
        (WebCore::SVGLinearGradientElement::collectGradientAttributes):
        (WebCore::SVGLinearGradientElement::calculateStartEndPoints):
        * svg/SVGMaskElement.cpp:
        (WebCore::SVGMaskElement::maskBoundingBox):
        * svg/SVGPatternElement.cpp:
        (WebCore::SVGPatternElement::collectPatternAttributes):
        * svg/SVGRadialGradientElement.cpp:
        (WebCore::SVGRadialGradientElement::collectGradientAttributes):
        (WebCore::SVGRadialGradientElement::calculateFocalCenterPointsAndRadius):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@99561 268f45cc-cd09-0410-ab3c-d52691b4dbfc

26 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
Source/WebCore/svg/GradientAttributes.h
Source/WebCore/svg/PatternAttributes.h
Source/WebCore/svg/SVGAllInOne.cpp
Source/WebCore/svg/SVGElement.h
Source/WebCore/svg/SVGFilterElement.cpp
Source/WebCore/svg/SVGLength.cpp
Source/WebCore/svg/SVGLength.h
Source/WebCore/svg/SVGLengthContext.cpp [new file with mode: 0644]
Source/WebCore/svg/SVGLengthContext.h [new file with mode: 0644]
Source/WebCore/svg/SVGLinearGradientElement.cpp
Source/WebCore/svg/SVGMaskElement.cpp
Source/WebCore/svg/SVGPatternElement.cpp
Source/WebCore/svg/SVGRadialGradientElement.cpp

index f2267b7..7e15297 100644 (file)
@@ -1737,6 +1737,7 @@ IF (ENABLE_SVG)
         svg/SVGImageLoader.cpp
         svg/SVGLangSpace.cpp
         svg/SVGLength.cpp
+        svg/SVGLengthContext.cpp
         svg/SVGLengthList.cpp
         svg/SVGLineElement.cpp
         svg/SVGLinearGradientElement.cpp
index 7fd0ca7..38dc1d3 100644 (file)
@@ -1,3 +1,96 @@
+2011-11-08  Nikolas Zimmermann  <nzimmermann@rim.com>
+
+        Introduce SVGLengthContext, to allow to resolve relative units to arbitary viewports
+        https://bugs.webkit.org/show_bug.cgi?id=71780
+
+        Reviewed by Zoltan Herczeg.
+
+        Introduce SVGLengthContext to cleanup SVGLength, by moving all conversion of relative units that depend on style or viewport
+        out of SVGLength, into SVGLengthContext. Pass SVGLengthContext& to SVGLength::value/setValue/... functions instead of a pure
+        "const SVGElement* context", which was previously used to determine the viewport when resolving percentage units.
+        SVGLengthContext carries an additional FloatRect of the custom viewport, to which percentages are resolved, if specified.
+
+        This allows us to kill several duplicates of the same code, which handles objectBoundingBox mode for gradients/patterns/masks/etc..
+        A follow-up patch will convert filters to use the new SVGLengthContext::resolveRectangle code as well.
+
+        This is a preparation for bug 10430, to fix feImage + objectBoundingBox support when rendering referenced elements, instead of files.
+
+        Doesn't affect any tests yet.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/svg/RenderSVGResourceGradient.cpp:
+        (WebCore::RenderSVGResourceGradient::applyResource):
+        * rendering/svg/RenderSVGResourceGradient.h:
+        * rendering/svg/RenderSVGResourceLinearGradient.h:
+        (WebCore::RenderSVGResourceLinearGradient::gradientUnits):
+        * rendering/svg/RenderSVGResourcePattern.cpp:
+        (WebCore::RenderSVGResourcePattern::applyResource):
+        (WebCore::calculatePatternBoundaries):
+        (WebCore::RenderSVGResourcePattern::buildTileImageTransform):
+        (WebCore::RenderSVGResourcePattern::createTileImage):
+        * rendering/svg/RenderSVGResourceRadialGradient.h:
+        (WebCore::RenderSVGResourceRadialGradient::gradientUnits):
+        * rendering/svg/SVGRenderTreeAsText.cpp:
+        (WebCore::writeCommonGradientProperties):
+        (WebCore::writeSVGResourceContainer):
+        * svg/GradientAttributes.h:
+        (WebCore::GradientAttributes::GradientAttributes):
+        (WebCore::GradientAttributes::gradientUnits):
+        (WebCore::GradientAttributes::setGradientUnits):
+        (WebCore::GradientAttributes::hasGradientUnits):
+        * svg/PatternAttributes.h:
+        (WebCore::PatternAttributes::PatternAttributes):
+        (WebCore::PatternAttributes::patternUnits):
+        (WebCore::PatternAttributes::patternContentUnits):
+        (WebCore::PatternAttributes::setPatternUnits):
+        (WebCore::PatternAttributes::setPatternContentUnits):
+        (WebCore::PatternAttributes::hasPatternUnits):
+        (WebCore::PatternAttributes::hasPatternContentUnits):
+        * svg/SVGAllInOne.cpp:
+        * svg/SVGElement.h:
+        (WebCore::SVGElement::operator SVGLengthContext):
+        * svg/SVGFilterElement.cpp:
+        (WebCore::SVGFilterElement::filterBoundingBox):
+        * svg/SVGLength.cpp:
+        (WebCore::SVGLength::SVGLength):
+        (WebCore::SVGLength::unitMode):
+        (WebCore::SVGLength::value):
+        (WebCore::SVGLength::setValue):
+        (WebCore::SVGLength::convertToSpecifiedUnits):
+        * svg/SVGLength.h:
+        (WebCore::SVGLength::blend):
+        * svg/SVGLengthContext.cpp: Added.
+        (WebCore::SVGLengthContext::SVGLengthContext):
+        (WebCore::SVGLengthContext::resolveRectangle):
+        (WebCore::SVGLengthContext::resolvePoint):
+        (WebCore::SVGLengthContext::resolveLength):
+        (WebCore::SVGLengthContext::convertValueToUserUnits):
+        (WebCore::SVGLengthContext::convertValueFromUserUnits):
+        (WebCore::SVGLengthContext::convertValueFromUserUnitsToPercentage):
+        (WebCore::SVGLengthContext::convertValueFromPercentageToUserUnits):
+        (WebCore::SVGLengthContext::convertValueFromUserUnitsToEMS):
+        (WebCore::SVGLengthContext::convertValueFromEMSToUserUnits):
+        (WebCore::SVGLengthContext::convertValueFromUserUnitsToEXS):
+        (WebCore::SVGLengthContext::convertValueFromEXSToUserUnits):
+        (WebCore::SVGLengthContext::determineViewport):
+        * svg/SVGLengthContext.h: Added.
+        (WebCore::SVGLengthContext::resolveRectangle):
+        * svg/SVGLinearGradientElement.cpp:
+        (WebCore::SVGLinearGradientElement::collectGradientAttributes):
+        (WebCore::SVGLinearGradientElement::calculateStartEndPoints):
+        * svg/SVGMaskElement.cpp:
+        (WebCore::SVGMaskElement::maskBoundingBox):
+        * svg/SVGPatternElement.cpp:
+        (WebCore::SVGPatternElement::collectPatternAttributes):
+        * svg/SVGRadialGradientElement.cpp:
+        (WebCore::SVGRadialGradientElement::collectGradientAttributes):
+        (WebCore::SVGRadialGradientElement::calculateFocalCenterPointsAndRadius):
+
 2011-11-08  Andreas Kling  <kling@webkit.org>
 
         CSSValue: Devirtualize addSubresourceStyleURLs().
index 29fac81..1553442 100644 (file)
@@ -3743,6 +3743,8 @@ webcore_sources += \
        Source/WebCore/svg/SVGLangSpace.h \
        Source/WebCore/svg/SVGLength.cpp \
        Source/WebCore/svg/SVGLength.h \
+       Source/WebCore/svg/SVGLengthContext.cpp \
+       Source/WebCore/svg/SVGLengthContext.h \
        Source/WebCore/svg/SVGLengthList.cpp \
        Source/WebCore/svg/SVGLengthList.h \
        Source/WebCore/svg/SVGLinearGradientElement.cpp \
index 036f9e9..b05c31d 100644 (file)
@@ -2594,6 +2594,7 @@ HEADERS += \
     svg/SVGImageLoader.h \
     svg/SVGLangSpace.h \
     svg/SVGLength.h \
+    svg/SVGLengthContext.h \
     svg/SVGLengthList.h \
     svg/SVGLinearGradientElement.h \
     svg/SVGLineElement.h \
@@ -3463,6 +3464,7 @@ contains(DEFINES, ENABLE_SVG=1) {
               svg/SVGImageElement.cpp \
               svg/SVGLangSpace.cpp \
               svg/SVGLength.cpp \
+              svg/SVGLengthContext.cpp \
               svg/SVGLengthList.cpp \
               svg/SVGLinearGradientElement.cpp \
               svg/SVGLineElement.cpp \
index a2c5fa8..593ed59 100644 (file)
             'svg/SVGDocumentExtensions.h',
             'svg/SVGElement.h',
             'svg/SVGLength.h',
+            'svg/SVGLengthContext.h',
             'svg/SVGLengthList.h',
             'svg/SVGLocatable.h',
             'svg/SVGMatrix.h',
             'svg/SVGLangSpace.cpp',
             'svg/SVGLangSpace.h',
             'svg/SVGLength.cpp',
+            'svg/SVGLengthContext.cpp',
             'svg/SVGLengthList.cpp',
             'svg/SVGLineElement.cpp',
             'svg/SVGLineElement.h',
index d61a11c..89f4580 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\svg\SVGLengthContext.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\svg\SVGLengthList.h"
                                >
                        </File>
index 8e7cd6b..4ba9441 100644 (file)
                6EBF0E7712A9868800DB1709 /* JSOESTextureFloat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EBF0E7512A9868800DB1709 /* JSOESTextureFloat.h */; };
                6EE8A77210F803F3005A4A24 /* JSWebGLContextAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */; };
                6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */; };
+               7134496D146941B300720312 /* SVGLengthContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7134496B146941B300720312 /* SVGLengthContext.cpp */; };
+               7134496E146941B300720312 /* SVGLengthContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 7134496C146941B300720312 /* SVGLengthContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
                71FB967B1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 71FB967A1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
                72626E020EF022FE00A07E20 /* FontFastPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 72626E010EF022FE00A07E20 /* FontFastPath.cpp */; };
                750D029311D0E7F300BD1B27 /* RenderInputSpeech.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 750D029111D0E7F300BD1B27 /* RenderInputSpeech.cpp */; };
                B2227AE20D00BF220071B782 /* SVGTRefElement.h in Headers */ = {isa = PBXBuildFile; fileRef = B222794C0D00BF210071B782 /* SVGTRefElement.h */; };
                B2227AE40D00BF220071B782 /* SVGTSpanElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B222794E0D00BF210071B782 /* SVGTSpanElement.cpp */; };
                B2227AE50D00BF220071B782 /* SVGTSpanElement.h in Headers */ = {isa = PBXBuildFile; fileRef = B222794F0D00BF210071B782 /* SVGTSpanElement.h */; };
-               B2227AE70D00BF220071B782 /* SVGUnitTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B22279510D00BF210071B782 /* SVGUnitTypes.h */; };
+               B2227AE70D00BF220071B782 /* SVGUnitTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B22279510D00BF210071B782 /* SVGUnitTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                B2227AE90D00BF220071B782 /* SVGURIReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B22279530D00BF210071B782 /* SVGURIReference.cpp */; };
                B2227AEA0D00BF220071B782 /* SVGURIReference.h in Headers */ = {isa = PBXBuildFile; fileRef = B22279540D00BF210071B782 /* SVGURIReference.h */; };
                B2227AEC0D00BF220071B782 /* SVGUseElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B22279560D00BF210071B782 /* SVGUseElement.cpp */; };
                6EBF0E7512A9868800DB1709 /* JSOESTextureFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSOESTextureFloat.h; sourceTree = "<group>"; };
                6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
                6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
+               7134496B146941B300720312 /* SVGLengthContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGLengthContext.cpp; sourceTree = "<group>"; };
+               7134496C146941B300720312 /* SVGLengthContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGLengthContext.h; sourceTree = "<group>"; };
                71FB967A1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedEnumerationPropertyTearOff.h; sourceTree = "<group>"; };
                72626E010EF022FE00A07E20 /* FontFastPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFastPath.cpp; sourceTree = "<group>"; };
                750D029111D0E7F300BD1B27 /* RenderInputSpeech.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderInputSpeech.cpp; sourceTree = "<group>"; };
                                B222789C0D00BF200071B782 /* SVGLength.cpp */,
                                B222789D0D00BF200071B782 /* SVGLength.h */,
                                B222789E0D00BF200071B782 /* SVGLength.idl */,
+                               7134496B146941B300720312 /* SVGLengthContext.cpp */,
+                               7134496C146941B300720312 /* SVGLengthContext.h */,
                                B222789F0D00BF200071B782 /* SVGLengthList.cpp */,
                                B22278A00D00BF200071B782 /* SVGLengthList.h */,
                                B22278A10D00BF200071B782 /* SVGLengthList.idl */,
                                3169379C14609C6C00C01362 /* DragSession.h in Headers */,
                                CAE9F910146441F000C245B0 /* CSSAspectRatioValue.h in Headers */,
                                976F36EB14686225005E93B4 /* SecurityContext.h in Headers */,
+                               7134496E146941B300720312 /* SVGLengthContext.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                CDEA76341460B56F008B31F1 /* ClockGeneric.cpp in Sources */,
                                CDEA76351460B71A008B31F1 /* Clock.cpp in Sources */,
                                976F36EA14686225005E93B4 /* SecurityContext.cpp in Sources */,
+                               7134496D146941B300720312 /* SVGLengthContext.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 5e31b76..592abc5 100644 (file)
@@ -164,7 +164,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
     // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
     // then the given effect (e.g. a gradient or a filter) will be ignored.
     FloatRect objectBoundingBox = object->objectBoundingBox();
-    if (boundingBoxMode() && objectBoundingBox.isEmpty())
+    if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
         return false;
 
     if (!m_gradient.contains(object))
@@ -181,9 +181,9 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
         // resource, so don't apply it here. For non-CG platforms, we want the text bounding
         // box applied to the gradient space transform now, so the gradient shader can use it.
 #if USE(CG)
-        if (boundingBoxMode() && !objectBoundingBox.isEmpty() && !isPaintingText) {
+        if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty() && !isPaintingText) {
 #else
-        if (boundingBoxMode() && !objectBoundingBox.isEmpty()) {
+        if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty()) {
 #endif
             gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y());
             gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -250,7 +250,7 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
             calculateGradientTransform(gradientTransform);
 
             FloatRect targetRect;
-            gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, object, boundingBoxMode(), gradientTransform));
+            gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, object, gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, gradientTransform));
             context->setFillGradient(gradientData->gradient);
 
             context->fillRect(targetRect);
index df492e2..2acd95b 100644 (file)
@@ -56,7 +56,7 @@ public:
 protected:
     void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const;
 
-    virtual bool boundingBoxMode() const = 0;
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const = 0;
     virtual void calculateGradientTransform(AffineTransform&) = 0;
     virtual bool collectGradientAttributes(SVGGradientElement*) = 0;
     virtual void buildGradient(GradientData*, SVGGradientElement*) const = 0;
index 8c9bb1d..f501de9 100644 (file)
@@ -39,7 +39,7 @@ public:
     virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
     static RenderSVGResourceType s_resourceType;
 
-    virtual bool boundingBoxMode() const { return m_attributes.boundingBoxMode(); }
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
     virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
     virtual bool collectGradientAttributes(SVGGradientElement*);
     virtual void buildGradient(GradientData*, SVGGradientElement*) const;
index 8dce084..5dc15b6 100644 (file)
@@ -96,7 +96,7 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
     // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
     // then the given effect (e.g. a gradient or a filter) will be ignored.
     FloatRect objectBoundingBox = object->objectBoundingBox();
-    if (m_attributes.boundingBoxMode() && objectBoundingBox.isEmpty())
+    if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
         return false;
 
     if (!m_pattern.contains(object))
@@ -208,17 +208,7 @@ static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attr
                                                    const SVGPatternElement* patternElement)
 {
     ASSERT(patternElement);
-
-    if (attributes.boundingBoxMode())
-        return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(),
-                         attributes.y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(),
-                         attributes.width().valueAsPercentage() * objectBoundingBox.width(),
-                         attributes.height().valueAsPercentage() * objectBoundingBox.height());
-
-    return FloatRect(attributes.x().value(patternElement),
-                     attributes.y().value(patternElement),
-                     attributes.width().value(patternElement),
-                     attributes.height().value(patternElement));
+    return SVGLengthContext::resolveRectangle(patternElement, attributes.patternUnits(), objectBoundingBox, attributes.x(), attributes.y(), attributes.width(), attributes.height());
 }
 
 bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
@@ -240,7 +230,7 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
     // Apply viewBox/objectBoundingBox transformations.
     if (!viewBoxCTM.isIdentity())
         tileImageTransform = viewBoxCTM;
-    else if (attributes.boundingBoxModeContent())
+    else if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
         tileImageTransform.scale(objectBoundingBox.width(), objectBoundingBox.height());
 
     return true;
@@ -271,7 +261,7 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternA
         tileImageContext->concatCTM(tileImageTransform);
 
     AffineTransform contentTransformation;
-    if (attributes.boundingBoxModeContent())
+    if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
         contentTransformation = tileImageTransform;
 
     // Draw the content into the ImageBuffer.
index d30e4aa..c6933e9 100644 (file)
@@ -39,7 +39,7 @@ public:
     virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
     static RenderSVGResourceType s_resourceType;
 
-    virtual bool boundingBoxMode() const { return m_attributes.boundingBoxMode(); }
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
     virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
     virtual bool collectGradientAttributes(SVGGradientElement*);
     virtual void buildGradient(GradientData*, SVGGradientElement*) const;
index a162969..162f434 100644 (file)
@@ -495,14 +495,9 @@ static void writeChildren(TextStream& ts, const RenderObject& object, int indent
         write(ts, *child, indent + 1);
 }
 
-static inline String boundingBoxModeString(bool boundingBoxMode)
+static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, SVGUnitTypes::SVGUnitType gradientUnits)
 {
-    return boundingBoxMode ? "objectBoundingBox" : "userSpaceOnUse";
-}
-
-static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, bool boundingBoxMode)
-{
-    writeNameValuePair(ts, "gradientUnits", boundingBoxModeString(boundingBoxMode));
+    writeNameValuePair(ts, "gradientUnits", gradientUnits);
 
     if (spreadMethod != SVGSpreadMethodPad)
         ts << " [spreadMethod=" << spreadMethod << "]";
@@ -562,8 +557,8 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
         PatternAttributes attributes;
         static_cast<SVGPatternElement*>(pattern->node())->collectPatternAttributes(attributes);
 
-        writeNameValuePair(ts, "patternUnits", boundingBoxModeString(attributes.boundingBoxMode()));
-        writeNameValuePair(ts, "patternContentUnits", boundingBoxModeString(attributes.boundingBoxModeContent()));
+        writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
+        writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());
 
         AffineTransform transform = attributes.patternTransform();
         if (!transform.isIdentity())
@@ -578,7 +573,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
 
         LinearGradientAttributes attributes;
         linearGradientElement->collectGradientAttributes(attributes);
-        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode());
+        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
 
         FloatPoint startPoint;
         FloatPoint endPoint;
@@ -594,7 +589,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int i
 
         RadialGradientAttributes attributes;
         radialGradientElement->collectGradientAttributes(attributes);
-        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode());
+        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
 
         FloatPoint focalPoint;
         FloatPoint centerPoint;
index 17f55ce..b7cfe8a 100644 (file)
@@ -29,16 +29,16 @@ namespace WebCore {
 struct GradientAttributes {
     GradientAttributes()
         : m_spreadMethod(SVGSpreadMethodPad)
-        , m_boundingBoxMode(true)
+        , m_gradientUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
         , m_spreadMethodSet(false)
-        , m_boundingBoxModeSet(false)
+        , m_gradientUnitsSet(false)
         , m_gradientTransformSet(false)
         , m_stopsSet(false)
     {
     }
 
     SVGSpreadMethodType spreadMethod() const { return m_spreadMethod; }
-    bool boundingBoxMode() const { return m_boundingBoxMode; }
+    SVGUnitTypes::SVGUnitType gradientUnits() const { return m_gradientUnits; }
     AffineTransform gradientTransform() const { return m_gradientTransform; }
     const Vector<Gradient::ColorStop>& stops() const { return m_stops; }
 
@@ -48,10 +48,10 @@ struct GradientAttributes {
         m_spreadMethodSet = true;
     }
 
-    void setBoundingBoxMode(bool value)
+    void setGradientUnits(SVGUnitTypes::SVGUnitType unitType)
     {
-        m_boundingBoxMode = value;
-        m_boundingBoxModeSet = true;
+        m_gradientUnits = unitType;
+        m_gradientUnitsSet = true;
     }
 
     void setGradientTransform(const AffineTransform& value)
@@ -67,20 +67,20 @@ struct GradientAttributes {
     } 
 
     bool hasSpreadMethod() const { return m_spreadMethodSet; }
-    bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; }
+    bool hasGradientUnits() const { return m_gradientUnitsSet; }
     bool hasGradientTransform() const { return m_gradientTransformSet; }
     bool hasStops() const { return m_stopsSet; }
 
 private:
     // Properties
     SVGSpreadMethodType m_spreadMethod;
-    bool m_boundingBoxMode;
+    SVGUnitTypes::SVGUnitType m_gradientUnits;
     AffineTransform m_gradientTransform;
     Vector<Gradient::ColorStop> m_stops;
 
     // Property states
     bool m_spreadMethodSet : 1;
-    bool m_boundingBoxModeSet : 1;
+    bool m_gradientUnitsSet : 1;
     bool m_gradientTransformSet : 1;
     bool m_stopsSet : 1;
 };
index 28a29c4..3677b74 100644 (file)
@@ -36,8 +36,8 @@ struct PatternAttributes {
         , m_height()
         , m_viewBox()
         , m_preserveAspectRatio()
-        , m_boundingBoxMode(true)
-        , m_boundingBoxModeContent(false)
+        , m_patternUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
+        , m_patternContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
         , m_patternContentElement(0)
         , m_xSet(false)
         , m_ySet(false)
@@ -45,8 +45,8 @@ struct PatternAttributes {
         , m_heightSet(false)
         , m_viewBoxSet(false)
         , m_preserveAspectRatioSet(false)
-        , m_boundingBoxModeSet(false)
-        , m_boundingBoxModeContentSet(false)
+        , m_patternUnitsSet(false)
+        , m_patternContentUnitsSet(false)
         , m_patternTransformSet(false)
         , m_patternContentElementSet(false)
     {
@@ -58,8 +58,8 @@ struct PatternAttributes {
     SVGLength height() const { return m_height; }
     FloatRect viewBox() const { return m_viewBox; }
     SVGPreserveAspectRatio preserveAspectRatio() const { return m_preserveAspectRatio; }
-    bool boundingBoxMode() const { return m_boundingBoxMode; }
-    bool boundingBoxModeContent() const { return m_boundingBoxModeContent; }
+    SVGUnitTypes::SVGUnitType patternUnits() const { return m_patternUnits; }
+    SVGUnitTypes::SVGUnitType patternContentUnits() const { return m_patternContentUnits; }
     AffineTransform patternTransform() const { return m_patternTransform; }
     const SVGPatternElement* patternContentElement() const { return m_patternContentElement; }
 
@@ -99,16 +99,16 @@ struct PatternAttributes {
         m_preserveAspectRatioSet = true;
     }
 
-    void setBoundingBoxMode(bool value)
+    void setPatternUnits(SVGUnitTypes::SVGUnitType value)
     {
-        m_boundingBoxMode = value;
-        m_boundingBoxModeSet = true;
+        m_patternUnits = value;
+        m_patternUnitsSet = true;
     }
 
-    void setBoundingBoxModeContent(bool value)
+    void setPatternContentUnits(SVGUnitTypes::SVGUnitType value)
     {
-        m_boundingBoxModeContent = value;
-        m_boundingBoxModeContentSet = true;
+        m_patternContentUnits = value;
+        m_patternContentUnitsSet = true;
     }
 
     void setPatternTransform(const AffineTransform& value)
@@ -129,8 +129,8 @@ struct PatternAttributes {
     bool hasHeight() const { return m_heightSet; }
     bool hasViewBox() const { return m_viewBoxSet; }
     bool hasPreserveAspectRatio() const { return m_preserveAspectRatioSet; }
-    bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; }
-    bool hasBoundingBoxModeContent() const { return m_boundingBoxModeContentSet; }
+    bool hasPatternUnits() const { return m_patternUnitsSet; }
+    bool hasPatternContentUnits() const { return m_patternContentUnitsSet; }
     bool hasPatternTransform() const { return m_patternTransformSet; }
     bool hasPatternContentElement() const { return m_patternContentElementSet; }
 
@@ -142,8 +142,8 @@ private:
     SVGLength m_height;
     FloatRect m_viewBox;
     SVGPreserveAspectRatio m_preserveAspectRatio;
-    bool m_boundingBoxMode;
-    bool m_boundingBoxModeContent;
+    SVGUnitTypes::SVGUnitType m_patternUnits;
+    SVGUnitTypes::SVGUnitType m_patternContentUnits;
     AffineTransform m_patternTransform;
     const SVGPatternElement* m_patternContentElement;
 
@@ -154,8 +154,8 @@ private:
     bool m_heightSet : 1;
     bool m_viewBoxSet : 1;
     bool m_preserveAspectRatioSet : 1;
-    bool m_boundingBoxModeSet : 1;
-    bool m_boundingBoxModeContentSet : 1;
+    bool m_patternUnitsSet : 1;
+    bool m_patternContentUnitsSet : 1;
     bool m_patternTransformSet : 1;
     bool m_patternContentElementSet : 1;
 };
index 15a594e..e1a7417 100644 (file)
 #include "SVGImageLoader.cpp"
 #include "SVGLangSpace.cpp"
 #include "SVGLength.cpp"
+#include "SVGLengthContext.cpp"
 #include "SVGLengthList.cpp"
 #include "SVGLineElement.cpp"
 #include "SVGLinearGradientElement.cpp"
index e4872d8..f12f808 100644 (file)
@@ -23,6 +23,7 @@
 #define SVGElement_h
 
 #if ENABLE(SVG)
+#include "SVGLengthContext.h"
 #include "SVGLocatable.h"
 #include "SVGParsingError.h"
 #include "SVGPropertyInfo.h"
@@ -62,6 +63,10 @@ public:
     virtual bool isGradientStop() const { return false; }
     virtual bool isTextContent() const { return false; }
 
+    // FIXME: This is a temporary construct to aid reducing the impact of introducing SVGLengthContext.
+    // It will be removed once all code that uses x().value(this) is gone.
+    operator SVGLengthContext() const { return SVGLengthContext(this); }
+
     // For SVGTests
     virtual bool isValid() const { return true; }
 
index 97fe33c..6f28592 100644 (file)
@@ -190,6 +190,7 @@ void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange,
 
 FloatRect SVGFilterElement::filterBoundingBox(const FloatRect& objectBoundingBox) const
 {
+    // FIXME: A follow-up patch will make filters use SVGLengthContext::resolveRectangle.
     FloatRect filterBBox;
     if (filterUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
         filterBBox = FloatRect(x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(),
index d8b42af..2d97eec 100644 (file)
 #include "SVGLength.h"
 
 #include "CSSHelper.h"
+#include "CSSPrimitiveValue.h"
 #include "FloatConversion.h"
-#include "Frame.h"
-#include "FrameView.h"
-#include "RenderPart.h"
-#include "RenderSVGRoot.h"
-#include "RenderView.h"
-#include "SVGException.h"
 #include "SVGNames.h"
 #include "SVGParserUtilities.h"
-#include "SVGSVGElement.h"
 
 #include <wtf/MathExtras.h>
 #include <wtf/text/WTFString.h>
@@ -133,7 +127,7 @@ SVGLength::SVGLength(SVGLengthMode mode, const String& valueAsString)
     setValueAsString(valueAsString, ec);
 }
 
-SVGLength::SVGLength(const SVGElement* context, float value, SVGLengthMode mode, SVGLengthType unitType)
+SVGLength::SVGLength(const SVGLengthContext& context, float value, SVGLengthMode mode, SVGLengthType unitType)
     : m_valueInSpecifiedUnits(0)
     , m_unit(storeUnit(mode, unitType))
 {
@@ -186,96 +180,38 @@ SVGLengthType SVGLength::unitType() const
     return extractType(m_unit);
 }
 
-float SVGLength::value(const SVGElement* context) const
+SVGLengthMode SVGLength::unitMode() const
+{
+    return extractMode(m_unit);
+}
+
+float SVGLength::value(const SVGLengthContext& context) const
 {
     ExceptionCode ec = 0;
     return value(context, ec);
 }
 
-float SVGLength::value(const SVGElement* context, ExceptionCode& ec) const
+float SVGLength::value(const SVGLengthContext& context, ExceptionCode& ec) const
 {
-    return convertValueToUserUnits(m_valueInSpecifiedUnits, extractType(m_unit), context, ec);
+    return context.convertValueToUserUnits(m_valueInSpecifiedUnits, extractMode(m_unit), extractType(m_unit), ec);
 }
 
-void SVGLength::setValue(const SVGElement* context, float value, SVGLengthMode mode, SVGLengthType unitType, ExceptionCode& ec)
+void SVGLength::setValue(const SVGLengthContext& context, float value, SVGLengthMode mode, SVGLengthType unitType, ExceptionCode& ec)
 {
     m_unit = storeUnit(mode, unitType);
     setValue(value, context, ec);
 }
 
-void SVGLength::setValue(float value, const SVGElement* context, ExceptionCode& ec)
+void SVGLength::setValue(float value, const SVGLengthContext& context, ExceptionCode& ec)
 {
     // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
     if (extractType(m_unit) == LengthTypePercentage)
         value = value / 100;
 
-    float convertedValue = convertValueFromUserUnits(value, extractType(m_unit), context, ec);
+    float convertedValue = context.convertValueFromUserUnits(value, extractMode(m_unit), extractType(m_unit), ec);
     if (!ec)
         m_valueInSpecifiedUnits = convertedValue;
 }
-
-float SVGLength::convertValueToUserUnits(float value, SVGLengthType fromUnit, const SVGElement* context, ExceptionCode& ec) const
-{
-    switch (fromUnit) {
-    case LengthTypeUnknown:
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    case LengthTypeNumber:
-        return value;
-    case LengthTypePX:
-        return value;
-    case LengthTypePercentage:
-        return convertValueFromPercentageToUserUnits(value / 100, context, ec);
-    case LengthTypeEMS:
-        return convertValueFromEMSToUserUnits(value, context, ec);
-    case LengthTypeEXS:
-        return convertValueFromEXSToUserUnits(value, context, ec);
-    case LengthTypeCM:
-        return value * cssPixelsPerInch / 2.54f;
-    case LengthTypeMM:
-        return value * cssPixelsPerInch / 25.4f;
-    case LengthTypeIN:
-        return value * cssPixelsPerInch;
-    case LengthTypePT:
-        return value * cssPixelsPerInch / 72;
-    case LengthTypePC:
-        return value * cssPixelsPerInch / 6;
-    }
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-float SVGLength::convertValueFromUserUnits(float value, SVGLengthType toUnit, const SVGElement* context, ExceptionCode& ec) const
-{
-    switch (toUnit) {
-    case LengthTypeUnknown:
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    case LengthTypeNumber:
-        return value;
-    case LengthTypePercentage:
-        return convertValueFromUserUnitsToPercentage(value * 100, context, ec);
-    case LengthTypeEMS:
-        return convertValueFromUserUnitsToEMS(value, context, ec);
-    case LengthTypeEXS:
-        return convertValueFromUserUnitsToEXS(value, context, ec);
-    case LengthTypePX:
-        return value;
-    case LengthTypeCM:
-        return value * 2.54f / cssPixelsPerInch;
-    case LengthTypeMM:
-        return value * 25.4f / cssPixelsPerInch;
-    case LengthTypeIN:
-        return value / cssPixelsPerInch;
-    case LengthTypePT:
-        return value * 72 / cssPixelsPerInch;
-    case LengthTypePC:
-        return value * 6 / cssPixelsPerInch;
-    }
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
 float SVGLength::valueAsPercentage() const
 {
     // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
@@ -326,7 +262,7 @@ void SVGLength::newValueSpecifiedUnits(unsigned short type, float value, Excepti
     m_valueInSpecifiedUnits = value;
 }
 
-void SVGLength::convertToSpecifiedUnits(unsigned short type, const SVGElement* context, ExceptionCode& ec)
+void SVGLength::convertToSpecifiedUnits(unsigned short type, const SVGLengthContext& context, ExceptionCode& ec)
 {
     if (type == LengthTypeUnknown || type > LengthTypePC) {
         ec = NOT_SUPPORTED_ERR;
@@ -347,177 +283,6 @@ void SVGLength::convertToSpecifiedUnits(unsigned short type, const SVGElement* c
     m_unit = originalUnitAndType;
 }
 
-bool SVGLength::determineViewport(const SVGElement* context, float& width, float& height) const
-{
-    if (!context)
-        return false;
-
-    // Take size from outermost <svg> element.
-    Document* document = context->document();
-    if (document->documentElement() == context) {
-        if (context->isSVG()) {
-            Frame* frame = context->document() ? context->document()->frame() : 0;
-            if (!frame)
-                return false;
-
-            // SVGs embedded through <object> resolve percentage values against the owner renderer in the host document.
-            if (RenderPart* ownerRenderer = frame->ownerRenderer()) {
-                width = ownerRenderer->width();
-                height = ownerRenderer->height();
-                return true;
-            }
-        }
-
-        RenderView* view = toRenderView(document->renderer());
-        if (!view)
-            return false;
-
-        // Always resolve percentages against the unscaled viewport, as agreed across browsers.
-        float zoom = view->style()->effectiveZoom();
-        width = view->viewWidth();
-        height = view->viewHeight();
-        if (zoom != 1) {
-            width /= zoom;
-            height /= zoom;
-        }
-        return true;
-    }
-
-    // Take size from nearest viewport element (common case: inner <svg> elements)
-    SVGElement* viewportElement = context->viewportElement();
-    if (viewportElement && viewportElement->isSVG()) {
-        const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
-        FloatRect viewBox = svg->currentViewBoxRect();
-        if (viewBox.isEmpty()) {
-            width = svg->width().value(svg);
-            height = svg->height().value(svg);
-        } else {
-            width = viewBox.width();
-            height = viewBox.height();
-        }
-
-        return true;
-    }
-    
-    // Take size from enclosing non-SVG RenderBox (common case: inline SVG)
-    if (!context->parentNode() || context->parentNode()->isSVGElement())
-        return false;
-
-    RenderObject* renderer = context->renderer();
-    if (!renderer || !renderer->isBox())
-        return false;
-
-    RenderBox* box = toRenderBox(renderer);
-    width = box->width();
-    height = box->height();
-    return true;
-}
-
-float SVGLength::convertValueFromUserUnitsToPercentage(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    float width = 0;
-    float height = 0;
-    if (!determineViewport(context, width, height)) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    switch (extractMode(m_unit)) {
-    case LengthModeWidth:
-        return value / width * 100;
-    case LengthModeHeight:
-        return value / height * 100;
-    case LengthModeOther:
-        return value / (sqrtf((width * width + height * height) / 2)) * 100;
-    };
-
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-float SVGLength::convertValueFromPercentageToUserUnits(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    float width = 0;
-    float height = 0;
-    if (!determineViewport(context, width, height)) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    switch (extractMode(m_unit)) {
-    case LengthModeWidth:
-        return value * width;
-    case LengthModeHeight:
-        return value * height;
-    case LengthModeOther:
-        return value * sqrtf((width * width + height * height) / 2);
-    };
-
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-float SVGLength::convertValueFromUserUnitsToEMS(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    if (!context || !context->renderer() || !context->renderer()->style()) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    RenderStyle* style = context->renderer()->style();
-    float fontSize = style->fontSize();
-    if (!fontSize) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    return value / fontSize;
-}
-
-float SVGLength::convertValueFromEMSToUserUnits(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    if (!context || !context->renderer() || !context->renderer()->style()) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    RenderStyle* style = context->renderer()->style();
-    return value * style->fontSize();
-}
-
-float SVGLength::convertValueFromUserUnitsToEXS(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    if (!context || !context->renderer() || !context->renderer()->style()) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    RenderStyle* style = context->renderer()->style();
-
-    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
-    // if this causes problems in real world cases maybe it would be best to remove this
-    float xHeight = ceilf(style->fontMetrics().xHeight());
-    if (!xHeight) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    return value / xHeight;
-}
-
-float SVGLength::convertValueFromEXSToUserUnits(float value, const SVGElement* context, ExceptionCode& ec) const
-{
-    if (!context || !context->renderer() || !context->renderer()->style()) {
-        ec = NOT_SUPPORTED_ERR;
-        return 0;
-    }
-
-    RenderStyle* style = context->renderer()->style();
-    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
-    // if this causes problems in real world cases maybe it would be best to remove this
-    return value * ceilf(style->fontMetrics().xHeight());
-}
-
 SVGLength SVGLength::fromCSSPrimitiveValue(CSSPrimitiveValue* value)
 {
     ASSERT(value);
index f36cc15..1553030 100644 (file)
 #define SVGLength_h
 
 #if ENABLE(SVG)
-#include "ExceptionCode.h"
+#include "SVGLengthContext.h"
 #include "SVGParsingError.h"
 #include "SVGPropertyTraits.h"
 
 namespace WebCore {
 
 class CSSPrimitiveValue;
-
-enum SVGLengthType {
-    LengthTypeUnknown = 0,
-    LengthTypeNumber = 1,
-    LengthTypePercentage = 2,
-    LengthTypeEMS = 3,
-    LengthTypeEXS = 4,
-    LengthTypePX = 5,
-    LengthTypeCM = 6,
-    LengthTypeMM = 7,
-    LengthTypeIN = 8,
-    LengthTypePT = 9,
-    LengthTypePC = 10
-};
-
-enum SVGLengthMode {
-    LengthModeWidth = 0,
-    LengthModeHeight,
-    LengthModeOther
-};
+class QualifiedName;
 
 enum SVGLengthNegativeValuesMode {
     AllowNegativeLengths,
     ForbidNegativeLengths
 };
 
-class QualifiedName;
-class SVGElement;
-
 class SVGLength {
 public:
     // Forward declare these enums in the w3c naming scheme, for IDL generation
@@ -75,21 +53,22 @@ public:
         SVG_LENGTHTYPE_PC = LengthTypePC
     };
 
-    SVGLength(SVGLengthMode mode = LengthModeOther, const String& valueAsString = String());
-    SVGLength(const SVGElement*, float, SVGLengthMode mode = LengthModeOther, SVGLengthType type = LengthTypeNumber);
+    SVGLength(SVGLengthMode = LengthModeOther, const String& valueAsString = String());
+    SVGLength(const SVGLengthContext&, float, SVGLengthMode = LengthModeOther, SVGLengthType = LengthTypeNumber);
     SVGLength(const SVGLength&);
 
     SVGLengthType unitType() const;
+    SVGLengthMode unitMode() const;
 
     bool operator==(const SVGLength&) const;
     bool operator!=(const SVGLength&) const;
 
     static SVGLength construct(SVGLengthMode, const String&, SVGParsingError&, SVGLengthNegativeValuesMode = AllowNegativeLengths);
 
-    float value(const SVGElement* context) const;
-    float value(const SVGElement* context, ExceptionCode&) const;
-    void setValue(float, const SVGElement* context, ExceptionCode&);
-    void setValue(const SVGElement* context, float, SVGLengthMode, SVGLengthType, ExceptionCode&);
+    float value(const SVGLengthContext&) const;
+    float value(const SVGLengthContext&, ExceptionCode&) const;
+    void setValue(float, const SVGLengthContext&, ExceptionCode&);
+    void setValue(const SVGLengthContext&, float, SVGLengthMode, SVGLengthType, ExceptionCode&);
 
     float valueInSpecifiedUnits() const { return m_valueInSpecifiedUnits; }
     void setValueInSpecifiedUnits(float value) { m_valueInSpecifiedUnits = value; }
@@ -101,7 +80,7 @@ public:
     void setValueAsString(const String&, SVGLengthMode, ExceptionCode&);
     
     void newValueSpecifiedUnits(unsigned short, float valueInSpecifiedUnits, ExceptionCode&);
-    void convertToSpecifiedUnits(unsigned short, const SVGElement* context, ExceptionCode&);
+    void convertToSpecifiedUnits(unsigned short, const SVGLengthContext&, ExceptionCode&);
 
     // Helper functions
     inline bool isRelative() const
@@ -123,7 +102,6 @@ public:
     {
         SVGLengthType toType = unitType();
         SVGLengthType fromType = from.unitType();
-
         if ((from.isZero() && isZero())
             || fromType == LengthTypeUnknown
             || toType == LengthTypeUnknown
@@ -158,11 +136,13 @@ public:
 
         ASSERT(!isRelative());
         ASSERT(!from.isRelative());
-        float fromValueInUserUnits = convertValueToUserUnits(from.valueInSpecifiedUnits(), fromType, 0, ec);
+
+        SVGLengthContext nonRelativeLengthContext(0);
+        float fromValueInUserUnits = nonRelativeLengthContext.convertValueToUserUnits(from.valueInSpecifiedUnits(), from.unitMode(), fromType, ec);
         if (ec)
             return SVGLength();
 
-        float fromValue = convertValueFromUserUnits(fromValueInUserUnits, toType, 0, ec);
+        float fromValue = nonRelativeLengthContext.convertValueFromUserUnits(fromValueInUserUnits, unitMode(), toType, ec);
         if (ec)
             return SVGLength();
 
@@ -175,21 +155,6 @@ public:
     }
 
 private:
-    bool determineViewport(const SVGElement* context, float& width, float& height) const;
-
-    float convertValueToUserUnits(float value, SVGLengthType fromUnit, const SVGElement* context, ExceptionCode&) const;
-    float convertValueFromUserUnits(float value, SVGLengthType toUnit, const SVGElement* context, ExceptionCode&) const;
-
-    float convertValueFromPercentageToUserUnits(float value, const SVGElement* context, ExceptionCode&) const;
-    float convertValueFromUserUnitsToPercentage(float value, const SVGElement* context, ExceptionCode&) const;
-
-    float convertValueFromUserUnitsToEMS(float value, const SVGElement* context, ExceptionCode&) const;
-    float convertValueFromEMSToUserUnits(float value, const SVGElement* context, ExceptionCode&) const;
-
-    float convertValueFromUserUnitsToEXS(float value, const SVGElement* context, ExceptionCode&) const;
-    float convertValueFromEXSToUserUnits(float value, const SVGElement* context, ExceptionCode&) const;
-
-private:
     float m_valueInSpecifiedUnits;
     unsigned int m_unit;
 };
diff --git a/Source/WebCore/svg/SVGLengthContext.cpp b/Source/WebCore/svg/SVGLengthContext.cpp
new file mode 100644 (file)
index 0000000..af80bd8
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 "SVGLengthContext.h"
+
+#include "CSSHelper.h"
+#include "Frame.h"
+#include "RenderPart.h"
+#include "RenderView.h"
+#include "SVGNames.h"
+#include "SVGSVGElement.h"
+
+namespace WebCore {
+
+SVGLengthContext::SVGLengthContext(const SVGElement* context)
+    : m_context(context)
+{
+}
+
+SVGLengthContext::SVGLengthContext(const SVGElement* context, const FloatRect& viewport)
+    : m_context(context)
+    , m_overridenViewport(viewport)
+{
+}
+
+FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const FloatRect& viewport, const SVGLength& x, const SVGLength& y, const SVGLength& width, const SVGLength& height)
+{
+    ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN);
+    if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
+        SVGLengthContext lengthContext(context);
+        return FloatRect(x.value(lengthContext), y.value(lengthContext), width.value(lengthContext), height.value(lengthContext));
+    }
+
+    SVGLengthContext lengthContext(context, viewport);
+    return FloatRect(x.value(lengthContext) + viewport.x(),
+                     y.value(lengthContext) + viewport.y(),
+                     width.value(lengthContext),
+                     height.value(lengthContext));
+}
+
+FloatPoint SVGLengthContext::resolvePoint(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLength& x, const SVGLength& y)
+{
+    ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN);
+    if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
+        SVGLengthContext lengthContext(context);
+        return FloatPoint(x.value(lengthContext), y.value(lengthContext));
+    }
+
+    // FIXME: valueAsPercentage() won't be correct for eg. cm units. They need to be resolved in user space and then be considered in objectBoundingBox space.
+    return FloatPoint(x.valueAsPercentage(), y.valueAsPercentage());
+}
+
+float SVGLengthContext::resolveLength(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLength& x)
+{
+    ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN);
+    if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) {
+        SVGLengthContext lengthContext(context);
+        return x.value(lengthContext);
+    }
+
+    // FIXME: valueAsPercentage() won't be correct for eg. cm units. They need to be resolved in user space and then be considered in objectBoundingBox space.
+    return x.valueAsPercentage();
+}
+
+float SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, SVGLengthType fromUnit, ExceptionCode& ec) const
+{
+    // If the SVGLengthContext carries a custom viewport, force resolving against it.
+    if (!m_overridenViewport.isEmpty()) {
+        // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
+        if (fromUnit == LengthTypePercentage)
+            value /= 100;
+        return convertValueFromPercentageToUserUnits(value, mode, ec);
+    }
+
+    switch (fromUnit) {
+    case LengthTypeUnknown:
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    case LengthTypeNumber:
+        return value;
+    case LengthTypePX:
+        return value;
+    case LengthTypePercentage:
+        return convertValueFromPercentageToUserUnits(value / 100, mode, ec);
+    case LengthTypeEMS:
+        return convertValueFromEMSToUserUnits(value, ec);
+    case LengthTypeEXS:
+        return convertValueFromEXSToUserUnits(value, ec);
+    case LengthTypeCM:
+        return value * cssPixelsPerInch / 2.54f;
+    case LengthTypeMM:
+        return value * cssPixelsPerInch / 25.4f;
+    case LengthTypeIN:
+        return value * cssPixelsPerInch;
+    case LengthTypePT:
+        return value * cssPixelsPerInch / 72;
+    case LengthTypePC:
+        return value * cssPixelsPerInch / 6;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mode, SVGLengthType toUnit, ExceptionCode& ec) const
+{
+    switch (toUnit) {
+    case LengthTypeUnknown:
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    case LengthTypeNumber:
+        return value;
+    case LengthTypePercentage:
+        return convertValueFromUserUnitsToPercentage(value * 100, mode, ec);
+    case LengthTypeEMS:
+        return convertValueFromUserUnitsToEMS(value, ec);
+    case LengthTypeEXS:
+        return convertValueFromUserUnitsToEXS(value, ec);
+    case LengthTypePX:
+        return value;
+    case LengthTypeCM:
+        return value * 2.54f / cssPixelsPerInch;
+    case LengthTypeMM:
+        return value * 25.4f / cssPixelsPerInch;
+    case LengthTypeIN:
+        return value / cssPixelsPerInch;
+    case LengthTypePT:
+        return value * 72 / cssPixelsPerInch;
+    case LengthTypePC:
+        return value * 6 / cssPixelsPerInch;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+float SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode mode, ExceptionCode& ec) const
+{
+    float width = 0;
+    float height = 0;
+    if (!determineViewport(width, height)) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    switch (mode) {
+    case LengthModeWidth:
+        return value / width * 100;
+    case LengthModeHeight:
+        return value / height * 100;
+    case LengthModeOther:
+        return value / (sqrtf((width * width + height * height) / 2)) * 100;
+    };
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+float SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode, ExceptionCode& ec) const
+{
+    float width = 0;
+    float height = 0;
+    if (!determineViewport(width, height)) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    switch (mode) {
+    case LengthModeWidth:
+        return value * width;
+    case LengthModeHeight:
+        return value * height;
+    case LengthModeOther:
+        return value * sqrtf((width * width + height * height) / 2);
+    };
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+float SVGLengthContext::convertValueFromUserUnitsToEMS(float value, ExceptionCode& ec) const
+{
+    if (!m_context || !m_context->renderer() || !m_context->renderer()->style()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    RenderStyle* style = m_context->renderer()->style();
+    float fontSize = style->fontSize();
+    if (!fontSize) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    return value / fontSize;
+}
+
+float SVGLengthContext::convertValueFromEMSToUserUnits(float value, ExceptionCode& ec) const
+{
+    if (!m_context || !m_context->renderer() || !m_context->renderer()->style()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    RenderStyle* style = m_context->renderer()->style();
+    return value * style->fontSize();
+}
+
+float SVGLengthContext::convertValueFromUserUnitsToEXS(float value, ExceptionCode& ec) const
+{
+    if (!m_context || !m_context->renderer() || !m_context->renderer()->style()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    RenderStyle* style = m_context->renderer()->style();
+
+    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
+    // if this causes problems in real world cases maybe it would be best to remove this
+    float xHeight = ceilf(style->fontMetrics().xHeight());
+    if (!xHeight) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    return value / xHeight;
+}
+
+float SVGLengthContext::convertValueFromEXSToUserUnits(float value, ExceptionCode& ec) const
+{
+    if (!m_context || !m_context->renderer() || !m_context->renderer()->style()) {
+        ec = NOT_SUPPORTED_ERR;
+        return 0;
+    }
+
+    RenderStyle* style = m_context->renderer()->style();
+    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
+    // if this causes problems in real world cases maybe it would be best to remove this
+    return value * ceilf(style->fontMetrics().xHeight());
+}
+
+bool SVGLengthContext::determineViewport(float& width, float& height) const
+{
+    if (!m_context)
+        return false;
+
+    // If an overriden viewport is given, it has precedence.
+    if (!m_overridenViewport.isEmpty()) {
+        width = m_overridenViewport.width();
+        height = m_overridenViewport.height();
+        return true;
+    }
+
+    // Take size from outermost <svg> element.
+    Document* document = m_context->document();
+    if (document->documentElement() == m_context) {
+        if (m_context->isSVG()) {
+            Frame* frame = m_context->document() ? m_context->document()->frame() : 0;
+            if (!frame)
+                return false;
+
+            if (RenderPart* ownerRenderer = frame->ownerRenderer()) {
+                width = ownerRenderer->width();
+                height = ownerRenderer->height();
+                return true;
+            }
+        }
+
+        RenderView* view = toRenderView(document->renderer());
+        if (!view)
+            return false;
+
+        width = view->viewWidth();
+        height = view->viewHeight();
+        return true;
+    }
+
+    // Take size from nearest viewport element (common case: inner <svg> elements)
+    SVGElement* viewportElement = m_context->viewportElement();
+    if (viewportElement && viewportElement->isSVG()) {
+        const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
+        if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
+            width = svg->viewBox().width();
+            height = svg->viewBox().height();
+        } else {
+            width = svg->width().value(svg);
+            height = svg->height().value(svg);
+        }
+
+        return true;
+    }
+    
+    // Take size from enclosing non-SVG RenderBox (common case: inline SVG)
+    if (!m_context->parentNode() || m_context->parentNode()->isSVGElement())
+        return false;
+
+    RenderObject* renderer = m_context->renderer();
+    if (!renderer || !renderer->isBox())
+        return false;
+
+    RenderBox* box = toRenderBox(renderer);
+    width = box->width();
+    height = box->height();
+    return true;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/svg/SVGLengthContext.h b/Source/WebCore/svg/SVGLengthContext.h
new file mode 100644 (file)
index 0000000..f9d2c6e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 SVGLengthContext_h
+#define SVGLengthContext_h
+
+#if ENABLE(SVG)
+#include "ExceptionCode.h"
+#include "FloatRect.h"
+#include "SVGUnitTypes.h"
+
+namespace WebCore {
+
+class SVGElement;
+class SVGLength;
+
+enum SVGLengthType {
+    LengthTypeUnknown = 0,
+    LengthTypeNumber,
+    LengthTypePercentage,
+    LengthTypeEMS,
+    LengthTypeEXS,
+    LengthTypePX,
+    LengthTypeCM,
+    LengthTypeMM,
+    LengthTypeIN,
+    LengthTypePT,
+    LengthTypePC
+};
+
+enum SVGLengthMode {
+    LengthModeWidth = 0,
+    LengthModeHeight,
+    LengthModeOther
+};
+
+class SVGLengthContext {
+public:
+    SVGLengthContext(const SVGElement*);
+
+    template<typename T>
+    static FloatRect resolveRectangle(const T* context, SVGUnitTypes::SVGUnitType type, const FloatRect& viewport)
+    {
+        return SVGLengthContext::resolveRectangle(context, type, viewport, context->x(), context->y(), context->width(), context->height());
+    }
+
+    static FloatRect resolveRectangle(const SVGElement*, SVGUnitTypes::SVGUnitType, const FloatRect& viewport, const SVGLength& x, const SVGLength& y, const SVGLength& width, const SVGLength& height);
+    static FloatPoint resolvePoint(const SVGElement*, SVGUnitTypes::SVGUnitType, const SVGLength& x, const SVGLength& y);
+    static float resolveLength(const SVGElement*, SVGUnitTypes::SVGUnitType, const SVGLength&);
+
+    float convertValueToUserUnits(float, SVGLengthMode, SVGLengthType fromUnit, ExceptionCode&) const;
+    float convertValueFromUserUnits(float, SVGLengthMode, SVGLengthType toUnit, ExceptionCode&) const;
+
+private:
+    SVGLengthContext(const SVGElement*, const FloatRect& viewport);
+
+    float convertValueFromUserUnitsToPercentage(float value, SVGLengthMode, ExceptionCode&) const;
+    float convertValueFromPercentageToUserUnits(float value, SVGLengthMode, ExceptionCode&) const;
+
+    float convertValueFromUserUnitsToEMS(float value, ExceptionCode&) const;
+    float convertValueFromEMSToUserUnits(float value, ExceptionCode&) const;
+
+    float convertValueFromUserUnitsToEXS(float value, ExceptionCode&) const;
+    float convertValueFromEXSToUserUnits(float value, ExceptionCode&) const;
+
+    bool determineViewport(float& width, float& height) const;
+
+    const SVGElement* m_context;
+    FloatRect m_overridenViewport;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGLengthContext_h
index 7c8b340..6e77744 100644 (file)
@@ -137,8 +137,8 @@ bool SVGLinearGradientElement::collectGradientAttributes(LinearGradientAttribute
         if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr))
             attributes.setSpreadMethod(current->spreadMethod());
 
-        if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::gradientUnitsAttr))
-            attributes.setBoundingBoxMode(current->gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+        if (!attributes.hasGradientUnits() && current->hasAttribute(SVGNames::gradientUnitsAttr))
+            attributes.setGradientUnits(current->gradientUnits());
 
         if (!attributes.hasGradientTransform() && current->hasAttribute(SVGNames::gradientTransformAttr)) {
             AffineTransform transform;
@@ -191,14 +191,8 @@ bool SVGLinearGradientElement::collectGradientAttributes(LinearGradientAttribute
 
 void SVGLinearGradientElement::calculateStartEndPoints(const LinearGradientAttributes& attributes, FloatPoint& startPoint, FloatPoint& endPoint)
 {
-    // Determine gradient start/end points
-    if (attributes.boundingBoxMode()) {
-        startPoint = FloatPoint(attributes.x1().valueAsPercentage(), attributes.y1().valueAsPercentage());
-        endPoint = FloatPoint(attributes.x2().valueAsPercentage(), attributes.y2().valueAsPercentage());
-    } else {
-        startPoint = FloatPoint(attributes.x1().value(this), attributes.y1().value(this));
-        endPoint = FloatPoint(attributes.x2().value(this), attributes.y2().value(this));
-    }
+    startPoint = SVGLengthContext::resolvePoint(this, attributes.gradientUnits(), attributes.x1(), attributes.y1());
+    endPoint = SVGLengthContext::resolvePoint(this, attributes.gradientUnits(), attributes.x2(), attributes.y2());
 }
 
 bool SVGLinearGradientElement::selfHasRelativeLengths() const
index b65af11..64c3d10 100644 (file)
@@ -159,19 +159,7 @@ void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, N
 
 FloatRect SVGMaskElement::maskBoundingBox(const FloatRect& objectBoundingBox) const
 {
-    FloatRect maskBBox;
-    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
-        maskBBox = FloatRect(x().valueAsPercentage() * objectBoundingBox.width() + objectBoundingBox.x(),
-                             y().valueAsPercentage() * objectBoundingBox.height() + objectBoundingBox.y(),
-                             width().valueAsPercentage() * objectBoundingBox.width(),
-                             height().valueAsPercentage() * objectBoundingBox.height());
-    else
-        maskBBox = FloatRect(x().value(this),
-                             y().value(this),
-                             width().value(this),
-                             height().value(this));
-
-    return maskBBox;
+    return SVGLengthContext::resolveRectangle<SVGMaskElement>(this, maskUnits(), objectBoundingBox);
 }
 
 RenderObject* SVGMaskElement::createRenderer(RenderArena* arena, RenderStyle*)
index bed306f..e997c92 100644 (file)
@@ -211,11 +211,11 @@ void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes)
         if (!attributes.hasPreserveAspectRatio() && current->hasAttribute(SVGNames::preserveAspectRatioAttr))
             attributes.setPreserveAspectRatio(current->preserveAspectRatio());
 
-        if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::patternUnitsAttr))
-            attributes.setBoundingBoxMode(current->patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+        if (!attributes.hasPatternUnits() && current->hasAttribute(SVGNames::patternUnitsAttr))
+            attributes.setPatternUnits(current->patternUnits());
 
-        if (!attributes.hasBoundingBoxModeContent() && current->hasAttribute(SVGNames::patternContentUnitsAttr))
-            attributes.setBoundingBoxModeContent(current->patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+        if (!attributes.hasPatternContentUnits() && current->hasAttribute(SVGNames::patternContentUnitsAttr))
+            attributes.setPatternContentUnits(current->patternContentUnits());
 
         if (!attributes.hasPatternTransform() && current->hasAttribute(SVGNames::patternTransformAttr)) {
             AffineTransform transform;
index 565d39f..3424a29 100644 (file)
@@ -143,8 +143,8 @@ bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttribute
         if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr))
             attributes.setSpreadMethod(current->spreadMethod());
 
-        if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::gradientUnitsAttr))
-            attributes.setBoundingBoxMode(current->gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+        if (!attributes.hasGradientUnits() && current->hasAttribute(SVGNames::gradientUnitsAttr))
+            attributes.setGradientUnits(current->gradientUnits());
 
         if (!attributes.hasGradientTransform() && current->hasAttribute(SVGNames::gradientTransformAttr)) {
             AffineTransform transform;
@@ -208,15 +208,9 @@ bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttribute
 void SVGRadialGradientElement::calculateFocalCenterPointsAndRadius(const RadialGradientAttributes& attributes, FloatPoint& focalPoint, FloatPoint& centerPoint, float& radius)
 {
     // Determine gradient focal/center points and radius
-    if (attributes.boundingBoxMode()) {
-        focalPoint = FloatPoint(attributes.fx().valueAsPercentage(), attributes.fy().valueAsPercentage());
-        centerPoint = FloatPoint(attributes.cx().valueAsPercentage(), attributes.cy().valueAsPercentage());
-        radius = attributes.r().valueAsPercentage();
-    } else {
-        focalPoint = FloatPoint(attributes.fx().value(this), attributes.fy().value(this));
-        centerPoint = FloatPoint(attributes.cx().value(this), attributes.cy().value(this));
-        radius = attributes.r().value(this);
-    }
+    focalPoint = SVGLengthContext::resolvePoint(this, attributes.gradientUnits(), attributes.fx(), attributes.fy());
+    centerPoint = SVGLengthContext::resolvePoint(this, attributes.gradientUnits(), attributes.cx(), attributes.cy());
+    radius = SVGLengthContext::resolveLength(this, attributes.gradientUnits(), attributes.r());
 
     // Eventually adjust focal points, as described below
     float deltaX = focalPoint.x() - centerPoint.x();