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