2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller ( mueller@kde.org )
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "platform/Length.h"
28 #include "platform/CalculationValue.h"
29 #include "platform/animation/AnimationUtilities.h"
30 #include "wtf/ASCIICType.h"
31 #include "wtf/text/StringBuffer.h"
32 #include "wtf/text/WTFString.h"
38 template<typename CharType>
39 static unsigned splitLength(const CharType* data, unsigned length, unsigned& intLength, unsigned& doubleLength)
44 while (i < length && isSpaceOrNewline(data[i]))
46 if (i < length && (data[i] == '+' || data[i] == '-'))
48 while (i < length && isASCIIDigit(data[i]))
51 while (i < length && (isASCIIDigit(data[i]) || data[i] == '.'))
55 // IE quirk: Skip whitespace between the number and the % character (20 % => 20%).
56 while (i < length && isSpaceOrNewline(data[i]))
62 template<typename CharType>
63 static Length parseHTMLAreaCoordinate(const CharType* data, unsigned length)
66 unsigned doubleLength;
67 splitLength(data, length, intLength, doubleLength);
70 int r = charactersToIntStrict(data, intLength, &ok);
72 return Length(r, Fixed);
73 return Length(0, Fixed);
76 // FIXME: Per HTML5, this should follow the "rules for parsing a list of integers".
77 Vector<Length> parseHTMLAreaElementCoords(const String& string)
79 unsigned length = string.length();
80 StringBuffer<LChar> spacified(length);
81 for (unsigned i = 0; i < length; i++) {
83 if (cc > '9' || (cc < '0' && cc != '-' && cc != '.'))
88 RefPtr<StringImpl> str = spacified.release();
89 str = str->simplifyWhiteSpace();
90 ASSERT(str->is8Bit());
93 return Vector<Length>();
95 unsigned len = str->count(' ') + 1;
96 Vector<Length> r(len);
102 while ((pos2 = str->find(' ', pos)) != kNotFound) {
103 r[i++] = parseHTMLAreaCoordinate(str->characters8() + pos, pos2 - pos);
106 r[i] = parseHTMLAreaCoordinate(str->characters8() + pos, str->length() - pos);
108 ASSERT(i == len - 1);
113 class CalculationValueHandleMap {
114 WTF_MAKE_FAST_ALLOCATED;
116 CalculationValueHandleMap()
121 int insert(PassRefPtr<CalculationValue> calcValue)
124 // FIXME calc(): https://bugs.webkit.org/show_bug.cgi?id=80489
125 // This monotonically increasing handle generation scheme is potentially wasteful
126 // of the handle space. Consider reusing empty handles.
127 while (m_map.contains(m_index))
130 m_map.set(m_index, calcValue);
135 void remove(int index)
137 ASSERT(m_map.contains(index));
141 CalculationValue& get(int index)
143 ASSERT(m_map.contains(index));
144 return *m_map.get(index);
147 void decrementRef(int index)
149 ASSERT(m_map.contains(index));
150 CalculationValue* value = m_map.get(index);
151 if (value->hasOneRef()) {
152 // Force the CalculationValue destructor early to avoid a potential recursive call inside HashMap remove().
153 m_map.set(index, nullptr);
162 HashMap<int, RefPtr<CalculationValue> > m_map;
165 static CalculationValueHandleMap& calcHandles()
167 DEFINE_STATIC_LOCAL(CalculationValueHandleMap, handleMap, ());
171 Length::Length(PassRefPtr<CalculationValue> calc)
176 m_intValue = calcHandles().insert(calc);
179 Length Length::blendMixedTypes(const Length& from, double progress, ValueRange range) const
181 ASSERT(from.isSpecified());
182 ASSERT(isSpecified());
183 PixelsAndPercent fromPixelsAndPercent = from.pixelsAndPercent();
184 PixelsAndPercent toPixelsAndPercent = pixelsAndPercent();
185 const float pixels = WebCore::blend(fromPixelsAndPercent.pixels, toPixelsAndPercent.pixels, progress);
186 const float percent = WebCore::blend(fromPixelsAndPercent.percent, toPixelsAndPercent.percent, progress);
187 return Length(CalculationValue::create(PixelsAndPercent(pixels, percent), range));
190 PixelsAndPercent Length::pixelsAndPercent() const
194 return PixelsAndPercent(value(), 0);
196 return PixelsAndPercent(0, value());
198 return calculationValue().pixelsAndPercent();
200 ASSERT_NOT_REACHED();
201 return PixelsAndPercent(0, 0);
205 Length Length::subtractFromOneHundredPercent() const
207 PixelsAndPercent result = pixelsAndPercent();
208 result.pixels = -result.pixels;
209 result.percent = 100 - result.percent;
210 if (result.pixels && result.percent)
211 return Length(CalculationValue::create(result, ValueRangeAll));
213 return Length(result.percent, Percent);
214 return Length(result.pixels, Fixed);
217 CalculationValue& Length::calculationValue() const
219 ASSERT(isCalculated());
220 return calcHandles().get(calculationHandle());
223 void Length::incrementCalculatedRef() const
225 ASSERT(isCalculated());
226 calculationValue().ref();
229 void Length::decrementCalculatedRef() const
231 ASSERT(isCalculated());
232 calcHandles().decrementRef(calculationHandle());
235 float Length::nonNanCalculatedValue(int maxValue) const
237 ASSERT(isCalculated());
238 float result = calculationValue().evaluate(maxValue);
239 if (std::isnan(result))
244 bool Length::isCalculatedEqual(const Length& o) const
246 return isCalculated() && (&calculationValue() == &o.calculationValue() || calculationValue() == o.calculationValue());
249 struct SameSizeAsLength {
253 COMPILE_ASSERT(sizeof(Length) == sizeof(SameSizeAsLength), length_should_stay_small);
255 } // namespace WebCore