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
6 * reserved.
7 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 */
25
26 #include "third_party/blink/renderer/platform/geometry/length.h"
27
28 #include "base/macros.h"
29 #include "third_party/blink/renderer/platform/geometry/blend.h"
30 #include "third_party/blink/renderer/platform/geometry/calculation_value.h"
31 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
32 #include "third_party/blink/renderer/platform/wtf/size_assertions.h"
33
34 namespace blink {
35
36 class CalculationValueHandleMap {
37 USING_FAST_MALLOC(CalculationValueHandleMap);
38
39 public:
CalculationValueHandleMap()40 CalculationValueHandleMap() : index_(1) {}
41
insert(scoped_refptr<CalculationValue> calc_value)42 int insert(scoped_refptr<CalculationValue> calc_value) {
43 DCHECK(index_);
44 // FIXME calc(): https://bugs.webkit.org/show_bug.cgi?id=80489
45 // This monotonically increasing handle generation scheme is potentially
46 // wasteful of the handle space. Consider reusing empty handles.
47 while (map_.Contains(index_))
48 index_++;
49
50 map_.Set(index_, std::move(calc_value));
51
52 return index_;
53 }
54
Remove(int index)55 void Remove(int index) {
56 DCHECK(map_.Contains(index));
57 map_.erase(index);
58 }
59
Get(int index)60 CalculationValue& Get(int index) {
61 DCHECK(map_.Contains(index));
62 return *map_.at(index);
63 }
64
DecrementRef(int index)65 void DecrementRef(int index) {
66 DCHECK(map_.Contains(index));
67 CalculationValue* value = map_.at(index);
68 if (value->HasOneRef()) {
69 // Force the CalculationValue destructor early to avoid a potential
70 // recursive call inside HashMap remove().
71 map_.Set(index, nullptr);
72 map_.erase(index);
73 } else {
74 value->Release();
75 }
76 }
77
78 private:
79 int index_;
80 HashMap<int, scoped_refptr<CalculationValue>> map_;
81
82 DISALLOW_COPY_AND_ASSIGN(CalculationValueHandleMap);
83 };
84
CalcHandles()85 static CalculationValueHandleMap& CalcHandles() {
86 DEFINE_STATIC_LOCAL(CalculationValueHandleMap, handle_map, ());
87 return handle_map;
88 }
89
Length(scoped_refptr<CalculationValue> calc)90 Length::Length(scoped_refptr<CalculationValue> calc)
91 : quirk_(false), type_(kCalculated), is_float_(false) {
92 int_value_ = CalcHandles().insert(std::move(calc));
93 }
94
BlendMixedTypes(const Length & from,double progress,ValueRange range) const95 Length Length::BlendMixedTypes(const Length& from,
96 double progress,
97 ValueRange range) const {
98 DCHECK(from.IsSpecified());
99 DCHECK(IsSpecified());
100 return Length(
101 AsCalculationValue()->Blend(*from.AsCalculationValue(), progress, range));
102 }
103
BlendSameTypes(const Length & from,double progress,ValueRange range) const104 Length Length::BlendSameTypes(const Length& from,
105 double progress,
106 ValueRange range) const {
107 Length::Type result_type = GetType();
108 if (IsZero())
109 result_type = from.GetType();
110
111 float blended_value = blink::Blend(from.Value(), Value(), progress);
112 if (range == kValueRangeNonNegative)
113 blended_value = clampTo<float>(blended_value, 0);
114 return Length(blended_value, result_type);
115 }
116
GetPixelsAndPercent() const117 PixelsAndPercent Length::GetPixelsAndPercent() const {
118 switch (GetType()) {
119 case kFixed:
120 return PixelsAndPercent(Value(), 0);
121 case kPercent:
122 return PixelsAndPercent(0, Value());
123 case kCalculated:
124 return GetCalculationValue().GetPixelsAndPercent();
125 default:
126 NOTREACHED();
127 return PixelsAndPercent(0, 0);
128 }
129 }
130
AsCalculationValue() const131 scoped_refptr<CalculationValue> Length::AsCalculationValue() const {
132 if (IsCalculated())
133 return &GetCalculationValue();
134 return CalculationValue::Create(GetPixelsAndPercent(), kValueRangeAll);
135 }
136
SubtractFromOneHundredPercent() const137 Length Length::SubtractFromOneHundredPercent() const {
138 if (IsPercent())
139 return Length::Percent(100 - Value());
140 DCHECK(IsSpecified());
141 scoped_refptr<CalculationValue> result =
142 AsCalculationValue()->SubtractFromOneHundredPercent();
143 if (result->IsExpression() ||
144 (result->Pixels() != 0 && result->Percent() != 0)) {
145 return Length(std::move(result));
146 }
147 if (result->Percent())
148 return Length::Percent(result->Percent());
149 return Length::Fixed(result->Pixels());
150 }
151
Zoom(double factor) const152 Length Length::Zoom(double factor) const {
153 switch (GetType()) {
154 case kFixed:
155 return Length::Fixed(GetFloatValue() * factor);
156 case kCalculated:
157 return Length(GetCalculationValue().Zoom(factor));
158 default:
159 return *this;
160 }
161 }
162
GetCalculationValue() const163 CalculationValue& Length::GetCalculationValue() const {
164 DCHECK(IsCalculated());
165 return CalcHandles().Get(CalculationHandle());
166 }
167
IncrementCalculatedRef() const168 void Length::IncrementCalculatedRef() const {
169 DCHECK(IsCalculated());
170 GetCalculationValue().AddRef();
171 }
172
DecrementCalculatedRef() const173 void Length::DecrementCalculatedRef() const {
174 DCHECK(IsCalculated());
175 CalcHandles().DecrementRef(CalculationHandle());
176 }
177
NonNanCalculatedValue(LayoutUnit max_value) const178 float Length::NonNanCalculatedValue(LayoutUnit max_value) const {
179 DCHECK(IsCalculated());
180 float result = GetCalculationValue().Evaluate(max_value.ToFloat());
181 if (std::isnan(result))
182 return 0;
183 return result;
184 }
185
IsCalculatedEqual(const Length & o) const186 bool Length::IsCalculatedEqual(const Length& o) const {
187 return IsCalculated() &&
188 (&GetCalculationValue() == &o.GetCalculationValue() ||
189 GetCalculationValue() == o.GetCalculationValue());
190 }
191
192 struct SameSizeAsLength {
193 int32_t value;
194 int32_t meta_data;
195 };
196 ASSERT_SIZE(Length, SameSizeAsLength);
197
198 } // namespace blink
199