Replace PassRef with Ref/Ref&& across the board.
[WebKit-https.git] / Source / WebCore / svg / SVGLength.h
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifndef SVGLength_h
22 #define SVGLength_h
23
24 #include "AnimationUtilities.h"
25 #include "SVGLengthContext.h"
26 #include "SVGParsingError.h"
27 #include "SVGPropertyTraits.h"
28
29 namespace WebCore {
30
31 class CSSPrimitiveValue;
32 class QualifiedName;
33
34 typedef int ExceptionCode;
35
36 enum SVGLengthNegativeValuesMode {
37     AllowNegativeLengths,
38     ForbidNegativeLengths
39 };
40
41 class SVGLength {
42     WTF_MAKE_FAST_ALLOCATED;
43 public:
44     // Forward declare these enums in the w3c naming scheme, for IDL generation
45     enum {
46         SVG_LENGTHTYPE_UNKNOWN = LengthTypeUnknown,
47         SVG_LENGTHTYPE_NUMBER = LengthTypeNumber,
48         SVG_LENGTHTYPE_PERCENTAGE = LengthTypePercentage,
49         SVG_LENGTHTYPE_EMS = LengthTypeEMS,
50         SVG_LENGTHTYPE_EXS = LengthTypeEXS,
51         SVG_LENGTHTYPE_PX = LengthTypePX,
52         SVG_LENGTHTYPE_CM = LengthTypeCM,
53         SVG_LENGTHTYPE_MM = LengthTypeMM,
54         SVG_LENGTHTYPE_IN = LengthTypeIN,
55         SVG_LENGTHTYPE_PT = LengthTypePT,
56         SVG_LENGTHTYPE_PC = LengthTypePC
57     };
58
59     // FIXME: Once all SVGLength users use Length internally, we make this a wrapper for Length.
60     SVGLength(SVGLengthMode = LengthModeOther, const String& valueAsString = String());
61     SVGLength(const SVGLengthContext&, float, SVGLengthMode = LengthModeOther, SVGLengthType = LengthTypeNumber);
62     SVGLength(const SVGLength&);
63
64     SVGLengthType unitType() const;
65     SVGLengthMode unitMode() const;
66
67     bool operator==(const SVGLength&) const;
68     bool operator!=(const SVGLength&) const;
69
70     static SVGLength construct(SVGLengthMode, const String&, SVGParsingError&, SVGLengthNegativeValuesMode = AllowNegativeLengths);
71
72     float value(const SVGLengthContext&) const;
73     float value(const SVGLengthContext&, ExceptionCode&) const;
74     void setValue(float, const SVGLengthContext&, ExceptionCode&);
75     void setValue(const SVGLengthContext&, float, SVGLengthMode, SVGLengthType, ExceptionCode&);
76
77     float valueInSpecifiedUnits() const { return m_valueInSpecifiedUnits; }
78     void setValueInSpecifiedUnits(float value) { m_valueInSpecifiedUnits = value; }
79
80     float valueAsPercentage() const;
81
82     String valueAsString() const;
83     void setValueAsString(const String&, ExceptionCode&);
84     void setValueAsString(const String&, SVGLengthMode, ExceptionCode&);
85     
86     void newValueSpecifiedUnits(unsigned short, float valueInSpecifiedUnits, ExceptionCode&);
87     void convertToSpecifiedUnits(unsigned short, const SVGLengthContext&, ExceptionCode&);
88
89     // Helper functions
90     inline bool isRelative() const
91     {
92         SVGLengthType type = unitType();
93         return type == LengthTypePercentage || type == LengthTypeEMS || type == LengthTypeEXS;
94     }
95
96     bool isZero() const 
97     { 
98         return !m_valueInSpecifiedUnits;
99     }
100
101     static SVGLength fromCSSPrimitiveValue(CSSPrimitiveValue*);
102     static Ref<CSSPrimitiveValue> toCSSPrimitiveValue(const SVGLength&);
103     static SVGLengthMode lengthModeForAnimatedLengthAttribute(const QualifiedName&);
104
105     SVGLength blend(const SVGLength& from, float progress) const
106     {
107         SVGLengthType toType = unitType();
108         SVGLengthType fromType = from.unitType();
109         if ((from.isZero() && isZero())
110             || fromType == LengthTypeUnknown
111             || toType == LengthTypeUnknown
112             || (!from.isZero() && fromType != LengthTypePercentage && toType == LengthTypePercentage)
113             || (!isZero() && fromType == LengthTypePercentage && toType != LengthTypePercentage)
114             || (!from.isZero() && !isZero() && (fromType == LengthTypeEMS || fromType == LengthTypeEXS) && fromType != toType))
115             return *this;
116
117         SVGLength length;
118         ExceptionCode ec = 0;
119
120         if (fromType == LengthTypePercentage || toType == LengthTypePercentage) {
121             float fromPercent = from.valueAsPercentage() * 100;
122             float toPercent = valueAsPercentage() * 100;
123             length.newValueSpecifiedUnits(LengthTypePercentage, WebCore::blend(fromPercent, toPercent, progress), ec);
124             if (ec)
125                 return SVGLength();
126             return length;
127         }
128
129         if (fromType == toType || from.isZero() || isZero() || fromType == LengthTypeEMS || fromType == LengthTypeEXS) {
130             float fromValue = from.valueInSpecifiedUnits();
131             float toValue = valueInSpecifiedUnits();
132             if (isZero())
133                 length.newValueSpecifiedUnits(fromType, WebCore::blend(fromValue, toValue, progress), ec);
134             else
135                 length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), ec);
136             if (ec)
137                 return SVGLength();
138             return length;
139         }
140
141         ASSERT(!isRelative());
142         ASSERT(!from.isRelative());
143
144         SVGLengthContext nonRelativeLengthContext(0);
145         float fromValueInUserUnits = nonRelativeLengthContext.convertValueToUserUnits(from.valueInSpecifiedUnits(), from.unitMode(), fromType, ec);
146         if (ec)
147             return SVGLength();
148
149         float fromValue = nonRelativeLengthContext.convertValueFromUserUnits(fromValueInUserUnits, unitMode(), toType, ec);
150         if (ec)
151             return SVGLength();
152
153         float toValue = valueInSpecifiedUnits();
154         length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), ec);
155
156         if (ec)
157             return SVGLength();
158         return length;
159     }
160
161 private:
162     float m_valueInSpecifiedUnits;
163     unsigned int m_unit;
164 };
165
166 template<>
167 struct SVGPropertyTraits<SVGLength> {
168     static SVGLength initialValue() { return SVGLength(); }
169     static String toString(const SVGLength& type) { return type.valueAsString(); }
170 };
171
172
173 } // namespace WebCore
174
175 #endif // SVGLength_h