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     Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
      6 
      7     This library is free software; you can redistribute it and/or
      8     modify it under the terms of the GNU Library General Public
      9     License as published by the Free Software Foundation; either
     10     version 2 of the License, or (at your option) any later version.
     11 
     12     This library is distributed in the hope that it will be useful,
     13     but WITHOUT ANY WARRANTY; without even the implied warranty of
     14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15     Library General Public License for more details.
     16 
     17     You should have received a copy of the GNU Library General Public License
     18     along with this library; see the file COPYING.LIB.  If not, write to
     19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20     Boston, MA 02110-1301, USA.
     21 */
     22 
     23 #ifndef Length_h
     24 #define Length_h
     25 
     26 #include <cstring>
     27 #include "core/platform/animation/AnimationUtilities.h"
     28 #include "wtf/Assertions.h"
     29 #include "wtf/FastAllocBase.h"
     30 #include "wtf/Forward.h"
     31 #include "wtf/HashMap.h"
     32 #include "wtf/MathExtras.h"
     33 #include "wtf/Vector.h"
     34 
     35 namespace WebCore {
     36 
     37 enum LengthType {
     38     Auto, Relative, Percent, Fixed,
     39     Intrinsic, MinIntrinsic,
     40     MinContent, MaxContent, FillAvailable, FitContent,
     41     Calculated,
     42     ViewportPercentageWidth, ViewportPercentageHeight, ViewportPercentageMin, ViewportPercentageMax,
     43     ExtendToZoom,
     44     Undefined
     45 };
     46 
     47 class CalculationValue;
     48 
     49 struct Length {
     50     WTF_MAKE_FAST_ALLOCATED;
     51 public:
     52     Length()
     53         :  m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false)
     54     {
     55     }
     56 
     57     Length(LengthType t)
     58         : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false)
     59     {
     60         ASSERT(t != Calculated);
     61     }
     62 
     63     Length(int v, LengthType t, bool q = false)
     64         : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false)
     65     {
     66         ASSERT(t != Calculated);
     67     }
     68 
     69     Length(LayoutUnit v, LengthType t, bool q = false)
     70         : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true)
     71     {
     72         ASSERT(t != Calculated);
     73     }
     74 
     75     Length(float v, LengthType t, bool q = false)
     76         : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true)
     77     {
     78         ASSERT(t != Calculated);
     79     }
     80 
     81     Length(double v, LengthType t, bool q = false)
     82         : m_quirk(q), m_type(t), m_isFloat(true)
     83     {
     84         m_floatValue = static_cast<float>(v);
     85     }
     86 
     87     explicit Length(PassRefPtr<CalculationValue>);
     88 
     89     Length(const Length& length)
     90     {
     91         initFromLength(length);
     92     }
     93 
     94     Length& operator=(const Length& length)
     95     {
     96         initFromLength(length);
     97         return *this;
     98     }
     99 
    100     ~Length()
    101     {
    102         if (isCalculated())
    103             decrementCalculatedRef();
    104     }
    105 
    106     bool operator==(const Length& o) const { return (m_type == o.m_type) && (m_quirk == o.m_quirk) && (isUndefined() || (getFloatValue() == o.getFloatValue()) || isCalculatedEqual(o)); }
    107     bool operator!=(const Length& o) const { return !(*this == o); }
    108 
    109     const Length& operator*=(float v)
    110     {
    111         if (isCalculated()) {
    112             ASSERT_NOT_REACHED();
    113             return *this;
    114         }
    115 
    116         if (m_isFloat)
    117             m_floatValue = static_cast<float>(m_floatValue * v);
    118         else
    119             m_intValue = static_cast<int>(m_intValue * v);
    120 
    121         return *this;
    122     }
    123 
    124     inline float value() const
    125     {
    126         return getFloatValue();
    127     }
    128 
    129      int intValue() const
    130      {
    131         if (isCalculated()) {
    132             ASSERT_NOT_REACHED();
    133             return 0;
    134         }
    135         return getIntValue();
    136     }
    137 
    138     float percent() const
    139     {
    140         ASSERT(type() == Percent);
    141         return getFloatValue();
    142     }
    143 
    144     PassRefPtr<CalculationValue> calculationValue() const;
    145 
    146     LengthType type() const { return static_cast<LengthType>(m_type); }
    147     bool quirk() const { return m_quirk; }
    148 
    149     void setQuirk(bool quirk)
    150     {
    151         m_quirk = quirk;
    152     }
    153 
    154     void setValue(LengthType t, int value)
    155     {
    156         m_type = t;
    157         m_intValue = value;
    158         m_isFloat = false;
    159     }
    160 
    161     void setValue(int value)
    162     {
    163         if (isCalculated()) {
    164             ASSERT_NOT_REACHED();
    165             return;
    166         }
    167         setValue(Fixed, value);
    168     }
    169 
    170     void setValue(LengthType t, float value)
    171     {
    172         m_type = t;
    173         m_floatValue = value;
    174         m_isFloat = true;
    175     }
    176 
    177     void setValue(LengthType t, LayoutUnit value)
    178     {
    179         m_type = t;
    180         m_floatValue = value;
    181         m_isFloat = true;
    182     }
    183 
    184     void setValue(float value)
    185     {
    186         *this = Length(value, Fixed);
    187     }
    188 
    189     bool isUndefined() const { return type() == Undefined; }
    190 
    191     // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length
    192     // always contains a percentage, and without a maxValue passed to these functions
    193     // it's impossible to determine the sign or zero-ness. We assume all calc values
    194     // are positive and non-zero for now.
    195     bool isZero() const
    196     {
    197         ASSERT(!isUndefined());
    198         if (isCalculated())
    199             return false;
    200 
    201         return m_isFloat ? !m_floatValue : !m_intValue;
    202     }
    203     bool isPositive() const
    204     {
    205         if (isUndefined())
    206             return false;
    207         if (isCalculated())
    208             return true;
    209 
    210         return getFloatValue() > 0;
    211     }
    212     bool isNegative() const
    213     {
    214         if (isUndefined() || isCalculated())
    215             return false;
    216 
    217         return getFloatValue() < 0;
    218     }
    219 
    220     bool isAuto() const { return type() == Auto; }
    221     bool isRelative() const { return type() == Relative; }
    222     bool isPercent() const { return type() == Percent || type() == Calculated; }
    223     bool isFixed() const { return type() == Fixed; }
    224     bool isIntrinsicOrAuto() const { return type() == Auto || isLegacyIntrinsic() || isIntrinsic(); }
    225     bool isLegacyIntrinsic() const { return type() == Intrinsic || type() == MinIntrinsic; }
    226     bool isIntrinsic() const { return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent; }
    227     bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated || isViewportPercentage(); }
    228     bool isSpecifiedOrIntrinsic() const { return isSpecified() || isIntrinsic(); }
    229     bool isCalculated() const { return type() == Calculated; }
    230     bool isCalculatedEqual(const Length&) const;
    231     bool isMinContent() const { return type() == MinContent; }
    232     bool isMaxContent() const { return type() == MaxContent; }
    233     bool isFillAvailable() const { return type() == FillAvailable; }
    234     bool isFitContent() const { return type() == FitContent; }
    235 
    236     Length blend(const Length& from, double progress) const
    237     {
    238         if (isUndefined() || from.isUndefined())
    239             return *this;
    240 
    241         // Blend two lengths to produce a new length that is in between them.  Used for animation.
    242         if (from.type() == Calculated || type() == Calculated)
    243             return blendMixedTypes(from, progress);
    244 
    245         if (!from.isZero() && !isZero() && from.type() != type())
    246             return blendMixedTypes(from, progress);
    247 
    248         if (from.isZero() && isZero())
    249             return *this;
    250 
    251         LengthType resultType = type();
    252         if (isZero())
    253             resultType = from.type();
    254 
    255         if (resultType == Percent) {
    256             float fromPercent = from.isZero() ? 0 : from.percent();
    257             float toPercent = isZero() ? 0 : percent();
    258             return Length(WebCore::blend(fromPercent, toPercent, progress), Percent);
    259         }
    260 
    261         float fromValue = from.isZero() ? 0 : from.value();
    262         float toValue = isZero() ? 0 : value();
    263         return Length(WebCore::blend(fromValue, toValue, progress), resultType);
    264     }
    265 
    266     float getFloatValue() const
    267     {
    268         ASSERT(!isUndefined());
    269         return m_isFloat ? m_floatValue : m_intValue;
    270     }
    271     float nonNanCalculatedValue(int maxValue) const;
    272 
    273     bool isViewportPercentage() const
    274     {
    275         LengthType lengthType = type();
    276         return lengthType >= ViewportPercentageWidth && lengthType <= ViewportPercentageMax;
    277     }
    278     float viewportPercentageLength() const
    279     {
    280         ASSERT(isViewportPercentage());
    281         return getFloatValue();
    282     }
    283 private:
    284     int getIntValue() const
    285     {
    286         ASSERT(!isUndefined());
    287         return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue;
    288     }
    289     void initFromLength(const Length& length)
    290     {
    291         memcpy(this, &length, sizeof(Length));
    292 
    293         if (isCalculated())
    294             incrementCalculatedRef();
    295     }
    296 
    297     Length blendMixedTypes(const Length& from, double progress) const;
    298 
    299     int calculationHandle() const
    300     {
    301         ASSERT(isCalculated());
    302         return getIntValue();
    303     }
    304     void incrementCalculatedRef() const;
    305     void decrementCalculatedRef() const;
    306 
    307     union {
    308         int m_intValue;
    309         float m_floatValue;
    310     };
    311     bool m_quirk;
    312     unsigned char m_type;
    313     bool m_isFloat;
    314 };
    315 
    316 Vector<Length> parseHTMLAreaElementCoords(const String&);
    317 
    318 } // namespace WebCore
    319 
    320 #endif // Length_h
    321