1/* 2 Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 4 Copyright (C) 2011 Rik Cabanier (cabanier@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 "AnimationUtilities.h" 27#include <string.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/PassOwnArrayPtr.h> 34 35namespace WebCore { 36 37enum LengthType { 38 Auto, Relative, Percent, Fixed, 39 Intrinsic, MinIntrinsic, 40 MinContent, MaxContent, FillAvailable, FitContent, 41 Calculated, 42 ViewportPercentageWidth, ViewportPercentageHeight, ViewportPercentageMin, ViewportPercentageMax, 43 Undefined 44}; 45 46class CalculationValue; 47 48struct Length { 49 WTF_MAKE_FAST_ALLOCATED; 50public: 51 Length() 52 : m_intValue(0), m_quirk(false), m_type(Auto), m_isFloat(false) 53 { 54 } 55 56 Length(LengthType t) 57 : m_intValue(0), m_quirk(false), m_type(t), m_isFloat(false) 58 { 59 ASSERT(t != Calculated); 60 } 61 62 Length(int v, LengthType t, bool q = false) 63 : m_intValue(v), m_quirk(q), m_type(t), m_isFloat(false) 64 { 65 ASSERT(t != Calculated); 66 } 67 68 Length(LayoutUnit v, LengthType t, bool q = false) 69 : m_floatValue(v.toFloat()), m_quirk(q), m_type(t), m_isFloat(true) 70 { 71 ASSERT(t != Calculated); 72 } 73 74 Length(float v, LengthType t, bool q = false) 75 : m_floatValue(v), m_quirk(q), m_type(t), m_isFloat(true) 76 { 77 ASSERT(t != Calculated); 78 } 79 80 Length(double v, LengthType t, bool q = false) 81 : m_quirk(q), m_type(t), m_isFloat(true) 82 { 83 m_floatValue = static_cast<float>(v); 84 } 85 86 explicit Length(PassRefPtr<CalculationValue>); 87 88 Length(const Length& length) 89 { 90 initFromLength(length); 91 } 92 93 Length& operator=(const Length& length) 94 { 95 initFromLength(length); 96 return *this; 97 } 98 99 ~Length() 100 { 101 if (isCalculated()) 102 decrementCalculatedRef(); 103 } 104 105 bool operator==(const Length& o) const { return (m_type == o.m_type) && (m_quirk == o.m_quirk) && (isUndefined() || (getFloatValue() == o.getFloatValue()) || isCalculatedEqual(o)); } 106 bool operator!=(const Length& o) const { return !(*this == o); } 107 108 const Length& operator*=(float v) 109 { 110 if (isCalculated()) { 111 ASSERT_NOT_REACHED(); 112 return *this; 113 } 114 115 if (m_isFloat) 116 m_floatValue = static_cast<float>(m_floatValue * v); 117 else 118 m_intValue = static_cast<int>(m_intValue * v); 119 120 return *this; 121 } 122 123 inline float value() const 124 { 125 return getFloatValue(); 126 } 127 128 int intValue() const 129 { 130 if (isCalculated()) { 131 ASSERT_NOT_REACHED(); 132 return 0; 133 } 134 return getIntValue(); 135 } 136 137 float percent() const 138 { 139 ASSERT(type() == Percent); 140 return getFloatValue(); 141 } 142 143 PassRefPtr<CalculationValue> calculationValue() const; 144 145 LengthType type() const { return static_cast<LengthType>(m_type); } 146 bool quirk() const { return m_quirk; } 147 148 void setQuirk(bool quirk) 149 { 150 m_quirk = quirk; 151 } 152 153 void setValue(LengthType t, int value) 154 { 155 m_type = t; 156 m_intValue = value; 157 m_isFloat = false; 158 } 159 160 void setValue(int value) 161 { 162 if (isCalculated()) { 163 ASSERT_NOT_REACHED(); 164 return; 165 } 166 setValue(Fixed, value); 167 } 168 169 void setValue(LengthType t, float value) 170 { 171 m_type = t; 172 m_floatValue = value; 173 m_isFloat = true; 174 } 175 176 void setValue(LengthType t, LayoutUnit value) 177 { 178 m_type = t; 179 m_floatValue = value; 180 m_isFloat = true; 181 } 182 183 void setValue(float value) 184 { 185 *this = Length(value, Fixed); 186 } 187 188 bool isUndefined() const { return type() == Undefined; } 189 190 // FIXME calc: https://bugs.webkit.org/show_bug.cgi?id=80357. A calculated Length 191 // always contains a percentage, and without a maxValue passed to these functions 192 // it's impossible to determine the sign or zero-ness. We assume all calc values 193 // are positive and non-zero for now. 194 bool isZero() const 195 { 196 ASSERT(!isUndefined()); 197 if (isCalculated()) 198 return false; 199 200 return m_isFloat ? !m_floatValue : !m_intValue; 201 } 202 bool isPositive() const 203 { 204 if (isUndefined()) 205 return false; 206 if (isCalculated()) 207 return true; 208 209 return getFloatValue() > 0; 210 } 211 bool isNegative() const 212 { 213 if (isUndefined() || isCalculated()) 214 return false; 215 216 return getFloatValue() < 0; 217 } 218 219 bool isAuto() const { return type() == Auto; } 220 bool isRelative() const { return type() == Relative; } 221 bool isPercent() const { return type() == Percent || type() == Calculated; } 222 bool isFixed() const { return type() == Fixed; } 223 bool isIntrinsicOrAuto() const { return type() == Auto || isLegacyIntrinsic() || isIntrinsic(); } 224 bool isLegacyIntrinsic() const { return type() == Intrinsic || type() == MinIntrinsic; } 225 bool isIntrinsic() const { return type() == MinContent || type() == MaxContent || type() == FillAvailable || type() == FitContent; } 226 bool isSpecified() const { return type() == Fixed || type() == Percent || type() == Calculated || isViewportPercentage(); } 227 bool isSpecifiedOrIntrinsic() const { return isSpecified() || isIntrinsic(); } 228 bool isCalculated() const { return type() == Calculated; } 229 bool isCalculatedEqual(const Length&) const; 230 bool isMinContent() const { return type() == MinContent; } 231 bool isMaxContent() const { return type() == MaxContent; } 232 233 Length blend(const Length& from, double progress) const 234 { 235 // Blend two lengths to produce a new length that is in between them. Used for animation. 236 if (from.type() == Calculated || type() == Calculated) 237 return blendMixedTypes(from, progress); 238 239 if (!from.isZero() && !isZero() && from.type() != type()) 240 return blendMixedTypes(from, progress); 241 242 if (from.isZero() && isZero()) 243 return *this; 244 245 LengthType resultType = type(); 246 if (isZero()) 247 resultType = from.type(); 248 249 if (resultType == Percent) { 250 float fromPercent = from.isZero() ? 0 : from.percent(); 251 float toPercent = isZero() ? 0 : percent(); 252 return Length(WebCore::blend(fromPercent, toPercent, progress), Percent); 253 } 254 255 float fromValue = from.isZero() ? 0 : from.value(); 256 float toValue = isZero() ? 0 : value(); 257 return Length(WebCore::blend(fromValue, toValue, progress), resultType); 258 } 259 260 float getFloatValue() const 261 { 262 ASSERT(!isUndefined()); 263 return m_isFloat ? m_floatValue : m_intValue; 264 } 265 float nonNanCalculatedValue(int maxValue) const; 266 267 bool isViewportPercentage() const 268 { 269 LengthType lengthType = type(); 270 return lengthType >= ViewportPercentageWidth && lengthType <= ViewportPercentageMax; 271 } 272 float viewportPercentageLength() const 273 { 274 ASSERT(isViewportPercentage()); 275 return getFloatValue(); 276 } 277private: 278 int getIntValue() const 279 { 280 ASSERT(!isUndefined()); 281 return m_isFloat ? static_cast<int>(m_floatValue) : m_intValue; 282 } 283 void initFromLength(const Length& length) 284 { 285 memcpy(this, &length, sizeof(Length)); 286 if (isCalculated()) 287 incrementCalculatedRef(); 288 } 289 290 Length blendMixedTypes(const Length& from, double progress) const; 291 292 int calculationHandle() const 293 { 294 ASSERT(isCalculated()); 295 return getIntValue(); 296 } 297 void incrementCalculatedRef() const; 298 void decrementCalculatedRef() const; 299 300 union { 301 int m_intValue; 302 float m_floatValue; 303 }; 304 bool m_quirk; 305 unsigned char m_type; 306 bool m_isFloat; 307}; 308 309PassOwnArrayPtr<Length> newCoordsArray(const String&, int& len); 310PassOwnArrayPtr<Length> newLengthArray(const String&, int& len); 311 312} // namespace WebCore 313 314#endif // Length_h 315