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