Home | History | Annotate | Download | only in platform
      1 /*
      2     Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3     Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
      4     Copyright (C) 2011 Rik Cabanier (cabanier (at) adobe.com)
      5 
      6     This library is free software; you can redistribute it and/or
      7     modify it under the terms of the GNU Library General Public
      8     License as published by the Free Software Foundation; either
      9     version 2 of the License, or (at your option) any later version.
     10 
     11     This library is distributed in the hope that it will be useful,
     12     but WITHOUT ANY WARRANTY; without even the implied warranty of
     13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14     Library General Public License for more details.
     15 
     16     You should have received a copy of the GNU Library General Public License
     17     along with this library; see the file COPYING.LIB.  If not, write to
     18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19     Boston, MA 02110-1301, USA.
     20 */
     21 
     22 #ifndef Length_h
     23 #define Length_h
     24 
     25 #include <wtf/Assertions.h>
     26 #include <wtf/FastAllocBase.h>
     27 #include <wtf/Forward.h>
     28 #include <wtf/MathExtras.h>
     29 #include <wtf/PassOwnArrayPtr.h>
     30 
     31 namespace WebCore {
     32 
     33 const int undefinedLength = -1;
     34 const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int
     35 const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int
     36 
     37 enum LengthType { Auto, Relative, Percent, Fixed, Intrinsic, MinIntrinsic };
     38 
     39 struct Length {
     40     WTF_MAKE_FAST_ALLOCATED;
     41 public:
     42     Length()
     43         :  m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
     44     {
     45     }
     46 
     47     Length(LengthType t)
     48         : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
     49     {
     50     }
     51 
     52     Length(int v, LengthType t, bool q = false)
     53         : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
     54     {
     55     }
     56 
     57     Length(float v, LengthType t, bool q = false)
     58     : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
     59     {
     60     }
     61 
     62     Length(double v, LengthType t, bool q = false)
     63         : m_quirk(q), m_type(t), m_isFloat(true)
     64     {
     65         m_floatValue = static_cast<float>(v);
     66     }
     67 
     68     bool operator==(const Length& o) const { return (getFloatValue() == o.getFloatValue()) && (m_type == o.m_type) && (m_quirk == o.m_quirk); }
     69     bool operator!=(const Length& o) const { return (getFloatValue() != o.getFloatValue()) || (m_type != o.m_type) || (m_quirk != o.m_quirk); }
     70 
     71     const Length& operator*=(float v)
     72     {
     73         if (m_isFloat)
     74             m_floatValue = static_cast<float>(m_floatValue * v);
     75         else
     76             m_intValue = static_cast<int>(m_intValue * v);
     77 
     78         return *this;
     79     }
     80 
     81     int value() const {
     82         return getIntValue();
     83     }
     84 
     85     float percent() const
     86     {
     87         ASSERT(type() == Percent);
     88         return getFloatValue();
     89     }
     90 
     91     LengthType type() const { return static_cast<LengthType>(m_type); }
     92     bool quirk() const { return m_quirk; }
     93 
     94     void setValue(LengthType t, int value)
     95     {
     96         m_type = t;
     97         m_intValue = value;
     98         m_isFloat = false;
     99     }
    100 
    101     void setValue(int value)
    102     {
    103         setValue(Fixed, value);
    104     }
    105 
    106     void setValue(LengthType t, float value)
    107     {
    108         m_type = t;
    109         m_floatValue = value;
    110         m_isFloat = true;
    111     }
    112 
    113     void setValue(float value)
    114     {
    115         *this = Length(value, Fixed);
    116     }
    117 
    118     // note: works only for certain types, returns undefinedLength otherwise
    119     int calcValue(int maxValue, bool roundPercentages = false) const
    120     {
    121         switch (type()) {
    122             case Fixed:
    123             case Percent:
    124                 return calcMinValue(maxValue, roundPercentages);
    125             case Auto:
    126                 return maxValue;
    127             default:
    128                 return undefinedLength;
    129         }
    130     }
    131 
    132     int calcMinValue(int maxValue, bool roundPercentages = false) const
    133     {
    134         switch (type()) {
    135             case Fixed:
    136                 return value();
    137             case Percent:
    138                 if (roundPercentages)
    139                     return static_cast<int>(round(maxValue * percent() / 100.0f));
    140                 // Don't remove the extra cast to float. It is needed for rounding on 32-bit Intel machines that use the FPU stack.
    141                 return static_cast<int>(static_cast<float>(maxValue * percent() / 100.0f));
    142             case Auto:
    143             default:
    144                 return 0;
    145         }
    146     }
    147 
    148     float calcFloatValue(int maxValue) const
    149     {
    150         switch (type()) {
    151             case Fixed:
    152                 return getFloatValue();
    153             case Percent:
    154                 return static_cast<float>(maxValue * percent() / 100.0f);
    155             case Auto:
    156                 return static_cast<float>(maxValue);
    157             default:
    158                 return static_cast<float>(undefinedLength);
    159         }
    160     }
    161 
    162     bool isUndefined() const { return value() == undefinedLength; }
    163     bool isZero() const
    164     {
    165         return m_isFloat ? !m_floatValue : !m_intValue;
    166     }
    167 
    168     bool isPositive() const { return getFloatValue() > 0; }
    169     bool isNegative() const { return getFloatValue() < 0; }
    170 
    171     bool isAuto() const { return type() == Auto; }
    172     bool isRelative() const { return type() == Relative; }
    173     bool isPercent() const { return type() == Percent; }
    174     bool isFixed() const { return type() == Fixed; }
    175     bool isIntrinsicOrAuto() const { return type() == Auto || type() == MinIntrinsic || type() == Intrinsic; }
    176 
    177     Length blend(const Length& from, float progress) const
    178     {
    179         // Blend two lengths to produce a new length that is in between them.  Used for animation.
    180         if (!from.isZero() && !isZero() && from.type() != type())
    181             return *this;
    182 
    183         if (from.isZero() && isZero())
    184             return *this;
    185 
    186         LengthType resultType = type();
    187         if (isZero())
    188             resultType = from.type();
    189 
    190         if (resultType == Percent) {
    191             float fromPercent = from.isZero() ? 0 : from.percent();
    192             float toPercent = isZero() ? 0 : percent();
    193             return Length(fromPercent + (toPercent - fromPercent) * progress, Percent);
    194         }
    195 
    196         float fromValue = from.isZero() ? 0 : from.value();
    197         float toValue = isZero() ? 0 : value();
    198         return Length(fromValue + (toValue - fromValue) * progress, resultType);
    199     }
    200 
    201 private:
    202     int getIntValue() const
    203     {
    204         return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
    205     }
    206 
    207     float getFloatValue() const
    208     {
    209         return m_isFloat ? m_floatValue : m_intValue;
    210     }
    211 
    212     union {
    213         int m_intValue;
    214         float m_floatValue;
    215     };
    216     bool m_quirk;
    217     unsigned char m_type;
    218     bool m_isFloat;
    219 };
    220 
    221 PassOwnArrayPtr<Length> newCoordsArray(const String&, int& len);
    222 PassOwnArrayPtr<Length> newLengthArray(const String&, int& len);
    223 
    224 } // namespace WebCore
    225 
    226 #endif // Length_h
    227