Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / Length.cpp
blobce86077350e677fb9bd5d58a1348afde6cbdf522
1 /*
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.
25 #include "config.h"
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"
34 using namespace WTF;
36 namespace blink {
38 template<typename CharType>
39 static unsigned splitLength(const CharType* data, unsigned length, unsigned& intLength, unsigned& doubleLength)
41 ASSERT(length);
43 unsigned i = 0;
44 while (i < length && isSpaceOrNewline(data[i]))
45 ++i;
46 if (i < length && (data[i] == '+' || data[i] == '-'))
47 ++i;
48 while (i < length && isASCIIDigit(data[i]))
49 ++i;
50 intLength = i;
51 while (i < length && (isASCIIDigit(data[i]) || data[i] == '.'))
52 ++i;
53 doubleLength = i;
55 // IE quirk: Skip whitespace between the number and the % character (20 % => 20%).
56 while (i < length && isSpaceOrNewline(data[i]))
57 ++i;
59 return i;
62 template<typename CharType>
63 static Length parseHTMLAreaCoordinate(const CharType* data, unsigned length)
65 unsigned intLength;
66 unsigned doubleLength;
67 splitLength(data, length, intLength, doubleLength);
69 return Length(charactersToIntStrict(data, intLength), Fixed);
72 // FIXME: Per HTML5, this should follow the "rules for parsing a list of integers".
73 Vector<Length> parseHTMLAreaElementCoords(const String& string)
75 unsigned length = string.length();
76 StringBuffer<LChar> spacified(length);
77 for (unsigned i = 0; i < length; i++) {
78 UChar cc = string[i];
79 if (cc > '9' || (cc < '0' && cc != '-' && cc != '.'))
80 spacified[i] = ' ';
81 else
82 spacified[i] = cc;
84 RefPtr<StringImpl> str = spacified.release();
85 str = str->simplifyWhiteSpace();
86 ASSERT(str->is8Bit());
88 if (!str->length())
89 return Vector<Length>();
91 unsigned len = str->count(' ') + 1;
92 Vector<Length> r(len);
94 unsigned i = 0;
95 unsigned pos = 0;
96 size_t pos2;
98 while ((pos2 = str->find(' ', pos)) != kNotFound) {
99 r[i++] = parseHTMLAreaCoordinate(str->characters8() + pos, pos2 - pos);
100 pos = pos2 + 1;
102 r[i] = parseHTMLAreaCoordinate(str->characters8() + pos, str->length() - pos);
104 ASSERT(i == len - 1);
106 return r;
109 class CalculationValueHandleMap {
110 WTF_MAKE_FAST_ALLOCATED(CalculationValueHandleMap);
111 public:
112 CalculationValueHandleMap()
113 : m_index(1)
117 int insert(PassRefPtr<CalculationValue> calcValue)
119 ASSERT(m_index);
120 // FIXME calc(): https://bugs.webkit.org/show_bug.cgi?id=80489
121 // This monotonically increasing handle generation scheme is potentially wasteful
122 // of the handle space. Consider reusing empty handles.
123 while (m_map.contains(m_index))
124 m_index++;
126 m_map.set(m_index, calcValue);
128 return m_index;
131 void remove(int index)
133 ASSERT(m_map.contains(index));
134 m_map.remove(index);
137 CalculationValue& get(int index)
139 ASSERT(m_map.contains(index));
140 return *m_map.get(index);
143 void decrementRef(int index)
145 ASSERT(m_map.contains(index));
146 CalculationValue* value = m_map.get(index);
147 if (value->hasOneRef()) {
148 // Force the CalculationValue destructor early to avoid a potential recursive call inside HashMap remove().
149 m_map.set(index, nullptr);
150 m_map.remove(index);
151 } else {
152 value->deref();
156 private:
157 int m_index;
158 HashMap<int, RefPtr<CalculationValue>> m_map;
161 static CalculationValueHandleMap& calcHandles()
163 DEFINE_STATIC_LOCAL(CalculationValueHandleMap, handleMap, ());
164 return handleMap;
167 Length::Length(PassRefPtr<CalculationValue> calc)
168 : m_quirk(false)
169 , m_type(Calculated)
170 , m_isFloat(false)
172 m_intValue = calcHandles().insert(calc);
175 Length Length::blendMixedTypes(const Length& from, double progress, ValueRange range) const
177 ASSERT(from.isSpecified());
178 ASSERT(isSpecified());
179 PixelsAndPercent fromPixelsAndPercent = from.pixelsAndPercent();
180 PixelsAndPercent toPixelsAndPercent = pixelsAndPercent();
181 const float pixels = blink::blend(fromPixelsAndPercent.pixels, toPixelsAndPercent.pixels, progress);
182 const float percent = blink::blend(fromPixelsAndPercent.percent, toPixelsAndPercent.percent, progress);
183 return Length(CalculationValue::create(PixelsAndPercent(pixels, percent), range));
186 PixelsAndPercent Length::pixelsAndPercent() const
188 switch (type()) {
189 case Fixed:
190 return PixelsAndPercent(value(), 0);
191 case Percent:
192 return PixelsAndPercent(0, value());
193 case Calculated:
194 return calculationValue().pixelsAndPercent();
195 default:
196 ASSERT_NOT_REACHED();
197 return PixelsAndPercent(0, 0);
201 Length Length::subtractFromOneHundredPercent() const
203 PixelsAndPercent result = pixelsAndPercent();
204 result.pixels = -result.pixels;
205 result.percent = 100 - result.percent;
206 if (result.pixels && result.percent)
207 return Length(CalculationValue::create(result, ValueRangeAll));
208 if (result.percent)
209 return Length(result.percent, Percent);
210 return Length(result.pixels, Fixed);
213 Length Length::zoom(double factor) const
215 switch (type()) {
216 case Fixed:
217 return Length(getFloatValue() * factor, Fixed);
218 case Calculated: {
219 PixelsAndPercent result = pixelsAndPercent();
220 result.pixels *= factor;
221 return Length(CalculationValue::create(result, calculationValue().valueRange()));
223 default:
224 return *this;
228 CalculationValue& Length::calculationValue() const
230 ASSERT(isCalculated());
231 return calcHandles().get(calculationHandle());
234 void Length::incrementCalculatedRef() const
236 ASSERT(isCalculated());
237 calculationValue().ref();
240 void Length::decrementCalculatedRef() const
242 ASSERT(isCalculated());
243 calcHandles().decrementRef(calculationHandle());
246 float Length::nonNanCalculatedValue(LayoutUnit maxValue) const
248 ASSERT(isCalculated());
249 float result = calculationValue().evaluate(maxValue.toFloat());
250 if (std::isnan(result))
251 return 0;
252 return result;
255 bool Length::isCalculatedEqual(const Length& o) const
257 return isCalculated() && (&calculationValue() == &o.calculationValue() || calculationValue() == o.calculationValue());
260 struct SameSizeAsLength {
261 int32_t value;
262 int32_t metaData;
264 static_assert(sizeof(Length) == sizeof(SameSizeAsLength), "length should stay small");
266 } // namespace blink