Home | History | Annotate | Download | only in svg
      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/platform/animation/AnimationUtilities.h"
     26 #include "core/svg/SVGLengthContext.h"
     27 #include "core/svg/SVGParsingError.h"
     28 #include "core/svg/properties/SVGPropertyTraits.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 es;
    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), es);
    123             if (es.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), es);
    133             else
    134                 length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), es);
    135             if (es.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, es);
    145         if (es.hadException())
    146             return SVGLength();
    147 
    148         float fromValue = nonRelativeLengthContext.convertValueFromUserUnits(fromValueInUserUnits, unitMode(), toType, es);
    149         if (es.hadException())
    150             return SVGLength();
    151 
    152         float toValue = valueInSpecifiedUnits();
    153         length.newValueSpecifiedUnits(toType, WebCore::blend(fromValue, toValue, progress), es);
    154 
    155         if (es.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