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 
      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 Length_h
     22 #define Length_h
     23 
     24 #include <wtf/Assertions.h>
     25 #include <wtf/FastAllocBase.h>
     26 #include <wtf/MathExtras.h>
     27 
     28 namespace WebCore {
     29 
     30 class String;
     31 
     32 const int undefinedLength = -1;
     33 const int percentScaleFactor = 128;
     34 
     35 enum LengthType { Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };
     36 
     37 struct Length : FastAllocBase {
     38     Length()
     39         : m_value(0)
     40     {
     41     }
     42 
     43     Length(LengthType t)
     44         : m_value(t)
     45     {
     46     }
     47 
     48     Length(int v, LengthType t, bool q = false)
     49         : m_value((v * 16) | (q << 3) | t) // FIXME: Doesn't work if the passed-in value is very large!
     50     {
     51         ASSERT(t != Percent);
     52     }
     53 
     54     Length(double v, LengthType t, bool q = false)
     55         : m_value(static_cast<int>(v * percentScaleFactor) * 16 | (q << 3) | t)
     56     {
     57         ASSERT(t == Percent);
     58     }
     59 
     60     bool operator==(const Length& o) const { return m_value == o.m_value; }
     61     bool operator!=(const Length& o) const { return m_value != o.m_value; }
     62 
     63     int value() const {
     64         ASSERT(type() != Percent);
     65         return rawValue();
     66     }
     67 
     68     int rawValue() const { return (m_value & ~0xF) / 16; }
     69 
     70     double percent() const
     71     {
     72         ASSERT(type() == Percent);
     73         return static_cast<double>(rawValue()) / percentScaleFactor;
     74     }
     75 
     76     LengthType type() const { return static_cast<LengthType>(m_value & 7); }
     77     bool quirk() const { return (m_value >> 3) & 1; }
     78 
     79     void setValue(LengthType t, int value)
     80     {
     81         ASSERT(t != Percent);
     82         setRawValue(t, value);
     83     }
     84 
     85     void setRawValue(LengthType t, int value) { m_value = value * 16 | (m_value & 0x8) | t; }
     86 
     87     void setValue(int value)
     88     {
     89         ASSERT(!value || type() != Percent);
     90         setRawValue(value);
     91     }
     92 
     93     void setRawValue(int value) { m_value = value * 16 | (m_value & 0xF); }
     94 
     95     void setValue(LengthType t, double value)
     96     {
     97         ASSERT(t == Percent);
     98         m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0x8) | t;
     99     }
    100 
    101     void setValue(double value)
    102     {
    103         ASSERT(type() == Percent);
    104         m_value = static_cast<int>(value * percentScaleFactor) * 16 | (m_value & 0xF);
    105     }
    106 
    107     // note: works only for certain types, returns undefinedLength otherwise
    108     int calcValue(int maxValue, bool roundPercentages = false) const
    109     {
    110         switch (type()) {
    111             case Fixed:
    112                 return value();
    113             case Percent:
    114                 if (roundPercentages)
    115                     return static_cast<int>(round(maxValue * percent() / 100.0));
    116                 return maxValue * rawValue() / (100 * percentScaleFactor);
    117             case Auto:
    118                 return maxValue;
    119             default:
    120                 return undefinedLength;
    121         }
    122     }
    123 
    124     int calcMinValue(int maxValue, bool roundPercentages = false) const
    125     {
    126         switch (type()) {
    127             case Fixed:
    128                 return value();
    129             case Percent:
    130                 if (roundPercentages)
    131                     return static_cast<int>(round(maxValue * percent() / 100.0));
    132                 return maxValue * rawValue() / (100 * percentScaleFactor);
    133             case Auto:
    134             default:
    135                 return 0;
    136         }
    137     }
    138 
    139     float calcFloatValue(int maxValue) const
    140     {
    141         switch (type()) {
    142             case Fixed:
    143                 return static_cast<float>(value());
    144             case Percent:
    145                 return static_cast<float>(maxValue * percent() / 100.0);
    146             case Auto:
    147                 return static_cast<float>(maxValue);
    148             default:
    149                 return static_cast<float>(undefinedLength);
    150         }
    151     }
    152 
    153     bool isUndefined() const { return rawValue() == undefinedLength; }
    154     bool isZero() const { return !(m_value & ~0xF); }
    155     bool isPositive() const { return rawValue() > 0; }
    156     bool isNegative() const { return rawValue() < 0; }
    157 
    158     bool isAuto() const { return type() == Auto; }
    159     bool isRelative() const { return type() == Relative; }
    160     bool isPercent() const { return type() == Percent; }
    161     bool isFixed() const { return type() == Fixed; }
    162     bool isStatic() const { return type() == Static; }
    163     bool isIntrinsicOrAuto() const { return type() == Auto || type() == MinIntrinsic || type() == Intrinsic; }
    164 
    165     Length blend(const Length& from, double progress) const
    166     {
    167         // Blend two lengths to produce a new length that is in between them.  Used for animation.
    168         if (!from.isZero() && !isZero() && from.type() != type())
    169             return *this;
    170 
    171         if (from.isZero() && isZero())
    172             return *this;
    173 
    174         LengthType resultType = type();
    175         if (isZero())
    176             resultType = from.type();
    177 
    178         if (resultType == Percent) {
    179             double fromPercent = from.isZero() ? 0. : from.percent();
    180             double toPercent = isZero() ? 0. : percent();
    181             return Length(fromPercent + (toPercent - fromPercent) * progress, Percent);
    182         }
    183 
    184         int fromValue = from.isZero() ? 0 : from.value();
    185         int toValue = isZero() ? 0 : value();
    186         return Length(int(fromValue + (toValue - fromValue) * progress), resultType);
    187     }
    188 
    189 private:
    190     int m_value;
    191 };
    192 
    193 Length* newCoordsArray(const String&, int& len);
    194 Length* newLengthArray(const String&, int& len);
    195 
    196 } // namespace WebCore
    197 
    198 #endif // Length_h
    199