1 /* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) 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 "bindings/v8/ExceptionState.h" 25 #include "core/svg/SVGLengthContext.h" 26 #include "core/svg/SVGParsingError.h" 27 #include "core/svg/properties/SVGPropertyTraits.h" 28 #include "platform/animation/AnimationUtilities.h" 29 30 namespace WebCore { 31 32 class CSSPrimitiveValue; 33 class ExceptionState; 34 class QualifiedName; 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 SVGLength(SVGLengthMode = LengthModeOther, const String& valueAsString = String()); 60 SVGLength(const SVGLengthContext&, float, SVGLengthMode = LengthModeOther, SVGLengthType = LengthTypeNumber); 61 SVGLength(const SVGLength&); 62 63 SVGLengthType unitType() const; 64 SVGLengthMode unitMode() const; 65 66 bool operator==(const SVGLength&) const; 67 bool operator!=(const SVGLength&) const; 68 69 static SVGLength construct(SVGLengthMode, const String&, SVGParsingError&, SVGLengthNegativeValuesMode = AllowNegativeLengths); 70 71 float value(const SVGLengthContext&) const; 72 float value(const SVGLengthContext&, ExceptionState&) const; 73 void setValue(float, const SVGLengthContext&, ExceptionState&); 74 void setValue(const SVGLengthContext&, float, SVGLengthMode, SVGLengthType, ExceptionState&); 75 76 float valueInSpecifiedUnits() const { return m_valueInSpecifiedUnits; } 77 void setValueInSpecifiedUnits(float value) { m_valueInSpecifiedUnits = value; } 78 79 float valueAsPercentage() const; 80 81 String valueAsString() const; 82 void setValueAsString(const String&, ExceptionState&); 83 void setValueAsString(const String&, SVGLengthMode, ExceptionState&); 84 85 void newValueSpecifiedUnits(unsigned short, float valueInSpecifiedUnits, ExceptionState&); 86 void convertToSpecifiedUnits(unsigned short, const SVGLengthContext&, ExceptionState&); 87 88 // Helper functions 89 inline bool isRelative() const 90 { 91 SVGLengthType type = unitType(); 92 return type == LengthTypePercentage || type == LengthTypeEMS || type == LengthTypeEXS; 93 } 94 95 bool isZero() const 96 { 97 return !m_valueInSpecifiedUnits; 98 } 99 100 static SVGLength fromCSSPrimitiveValue(CSSPrimitiveValue*); 101 static PassRefPtr<CSSPrimitiveValue> toCSSPrimitiveValue(const SVGLength&); 102 static SVGLengthMode lengthModeForAnimatedLengthAttribute(const QualifiedName&); 103 104 SVGLength blend(const SVGLength& from, float progress) const 105 { 106 SVGLengthType toType = unitType(); 107 SVGLengthType fromType = from.unitType(); 108 if ((from.isZero() && isZero()) 109 || fromType == LengthTypeUnknown 110 || toType == LengthTypeUnknown 111 || (!from.isZero() && fromType != LengthTypePercentage && toType == LengthTypePercentage) 112 || (!isZero() && fromType == LengthTypePercentage && toType != LengthTypePercentage) 113 || (!from.isZero() && !isZero() && (fromType == LengthTypeEMS || fromType == LengthTypeEXS) && fromType != toType)) 114 return *this; 115 116 SVGLength length; 117 TrackExceptionState exceptionState; 118 119 if (fromType == LengthTypePercentage || toType == LengthTypePercentage) { 120 float fromPercent = from.valueAsPercentage() * 100; 121 float toPercent = valueAsPercentage() * 100; 122 length.newValueSpecifiedUnits(LengthTypePercentage, WebCore::blend(fromPercent, toPercent, progress), exceptionState); 123 if (exceptionState.hadException()) 124 return SVGLength(); 125 return length; 126 } 127 128 if (fromType == toType || from.isZero() || isZero() || fromType == LengthTypeEMS || fromType == LengthTypeEXS) { 129 float fromValue = from.valueInSpecifiedUnits(); 130 float toValue = valueInSpecifiedUnits(); 131 if (isZero()) 132 length.newValueSpecifiedUnits(fromType, WebCore::blend(fromValue, toValue, progress), exceptionState); 133 else 134 length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), exceptionState); 135 if (exceptionState.hadException()) 136 return SVGLength(); 137 return length; 138 } 139 140 ASSERT(!isRelative()); 141 ASSERT(!from.isRelative()); 142 143 SVGLengthContext nonRelativeLengthContext(0); 144 float fromValueInUserUnits = nonRelativeLengthContext.convertValueToUserUnits(from.valueInSpecifiedUnits(), from.unitMode(), fromType, exceptionState); 145 if (exceptionState.hadException()) 146 return SVGLength(); 147 148 float fromValue = nonRelativeLengthContext.convertValueFromUserUnits(fromValueInUserUnits, unitMode(), toType, exceptionState); 149 if (exceptionState.hadException()) 150 return SVGLength(); 151 152 float toValue = valueInSpecifiedUnits(); 153 length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), exceptionState); 154 155 if (exceptionState.hadException()) 156 return SVGLength(); 157 return length; 158 } 159 160 private: 161 float m_valueInSpecifiedUnits; 162 unsigned int m_unit; 163 }; 164 165 template<> 166 struct SVGPropertyTraits<SVGLength> { 167 static SVGLength initialValue() { return SVGLength(); } 168 static String toString(const SVGLength& type) { return type.valueAsString(); } 169 }; 170 171 172 } // namespace WebCore 173 174 #endif // SVGLength_h 175