1 | /* |
2 | * Copyright (C) 2011 Google Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are |
6 | * met: |
7 | * |
8 | * * Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * * Redistributions in binary form must reproduce the above |
11 | * copyright notice, this list of conditions and the following disclaimer |
12 | * in the documentation and/or other materials provided with the |
13 | * distribution. |
14 | * * Neither the name of Google Inc. nor the names of its |
15 | * contributors may be used to endorse or promote products derived from |
16 | * this software without specific prior written permission. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
30 | |
31 | #pragma once |
32 | |
33 | #include "Length.h" |
34 | #include <memory> |
35 | #include <wtf/Ref.h> |
36 | #include <wtf/RefCounted.h> |
37 | #include <wtf/Vector.h> |
38 | |
39 | namespace WTF { |
40 | class TextStream; |
41 | } |
42 | |
43 | namespace WebCore { |
44 | |
45 | // Don't change these values; parsing uses them. |
46 | enum class CalcOperator : uint8_t { |
47 | Add = '+', |
48 | Subtract = '-', |
49 | Multiply = '*', |
50 | Divide = '/', |
51 | Min = 0, |
52 | Max = 1, |
53 | }; |
54 | |
55 | enum class CalcExpressionNodeType : uint8_t { |
56 | Undefined, |
57 | Number, |
58 | Length, |
59 | Operation, |
60 | BlendLength, |
61 | }; |
62 | |
63 | class CalcExpressionNode { |
64 | WTF_MAKE_FAST_ALLOCATED; |
65 | public: |
66 | explicit CalcExpressionNode(CalcExpressionNodeType = CalcExpressionNodeType::Undefined); |
67 | virtual ~CalcExpressionNode() = default; |
68 | |
69 | CalcExpressionNodeType type() const { return m_type; } |
70 | |
71 | virtual float evaluate(float maxValue) const = 0; |
72 | virtual bool operator==(const CalcExpressionNode&) const = 0; |
73 | virtual void dump(WTF::TextStream&) const = 0; |
74 | |
75 | private: |
76 | CalcExpressionNodeType m_type; |
77 | }; |
78 | |
79 | class CalcExpressionNumber final : public CalcExpressionNode { |
80 | public: |
81 | explicit CalcExpressionNumber(float); |
82 | |
83 | float value() const { return m_value; } |
84 | |
85 | private: |
86 | float evaluate(float) const override; |
87 | bool operator==(const CalcExpressionNode&) const override; |
88 | void dump(WTF::TextStream&) const override; |
89 | |
90 | float m_value; |
91 | }; |
92 | |
93 | class CalcExpressionLength final : public CalcExpressionNode { |
94 | public: |
95 | explicit CalcExpressionLength(Length); |
96 | |
97 | const Length& length() const { return m_length; } |
98 | |
99 | private: |
100 | float evaluate(float maxValue) const override; |
101 | bool operator==(const CalcExpressionNode&) const override; |
102 | void dump(WTF::TextStream&) const override; |
103 | |
104 | Length m_length; |
105 | }; |
106 | |
107 | class CalcExpressionOperation final : public CalcExpressionNode { |
108 | public: |
109 | CalcExpressionOperation(Vector<std::unique_ptr<CalcExpressionNode>>&& children, CalcOperator); |
110 | |
111 | CalcOperator getOperator() const { return m_operator; } |
112 | |
113 | const Vector<std::unique_ptr<CalcExpressionNode>>& children() const { return m_children; } |
114 | |
115 | private: |
116 | float evaluate(float maxValue) const override; |
117 | bool operator==(const CalcExpressionNode&) const override; |
118 | void dump(WTF::TextStream&) const override; |
119 | |
120 | Vector<std::unique_ptr<CalcExpressionNode>> m_children; |
121 | CalcOperator m_operator; |
122 | }; |
123 | |
124 | class CalcExpressionBlendLength final : public CalcExpressionNode { |
125 | public: |
126 | CalcExpressionBlendLength(Length from, Length to, float progress); |
127 | |
128 | const Length& from() const { return m_from; } |
129 | const Length& to() const { return m_to; } |
130 | float progress() const { return m_progress; } |
131 | |
132 | private: |
133 | float evaluate(float maxValue) const override; |
134 | bool operator==(const CalcExpressionNode&) const override; |
135 | void dump(WTF::TextStream&) const override; |
136 | |
137 | Length m_from; |
138 | Length m_to; |
139 | float m_progress; |
140 | }; |
141 | |
142 | class CalculationValue : public RefCounted<CalculationValue> { |
143 | public: |
144 | WEBCORE_EXPORT static Ref<CalculationValue> create(std::unique_ptr<CalcExpressionNode>, ValueRange); |
145 | float evaluate(float maxValue) const; |
146 | |
147 | bool shouldClampToNonNegative() const { return m_shouldClampToNonNegative; } |
148 | const CalcExpressionNode& expression() const { return *m_expression; } |
149 | |
150 | private: |
151 | CalculationValue(std::unique_ptr<CalcExpressionNode>, ValueRange); |
152 | |
153 | std::unique_ptr<CalcExpressionNode> m_expression; |
154 | bool m_shouldClampToNonNegative; |
155 | }; |
156 | |
157 | inline CalcExpressionNode::CalcExpressionNode(CalcExpressionNodeType type) |
158 | : m_type(type) |
159 | { |
160 | } |
161 | |
162 | inline CalculationValue::CalculationValue(std::unique_ptr<CalcExpressionNode> expression, ValueRange range) |
163 | : m_expression(WTFMove(expression)) |
164 | , m_shouldClampToNonNegative(range == ValueRangeNonNegative) |
165 | { |
166 | } |
167 | |
168 | inline bool operator==(const CalculationValue& a, const CalculationValue& b) |
169 | { |
170 | return a.expression() == b.expression(); |
171 | } |
172 | |
173 | inline CalcExpressionNumber::CalcExpressionNumber(float value) |
174 | : CalcExpressionNode(CalcExpressionNodeType::Number) |
175 | , m_value(value) |
176 | { |
177 | } |
178 | |
179 | inline bool operator==(const CalcExpressionNumber& a, const CalcExpressionNumber& b) |
180 | { |
181 | return a.value() == b.value(); |
182 | } |
183 | |
184 | inline const CalcExpressionNumber& toCalcExpressionNumber(const CalcExpressionNode& value) |
185 | { |
186 | ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeType::Number); |
187 | return static_cast<const CalcExpressionNumber&>(value); |
188 | } |
189 | |
190 | inline CalcExpressionLength::CalcExpressionLength(Length length) |
191 | : CalcExpressionNode(CalcExpressionNodeType::Length) |
192 | , m_length(length) |
193 | { |
194 | } |
195 | |
196 | inline bool operator==(const CalcExpressionLength& a, const CalcExpressionLength& b) |
197 | { |
198 | return a.length() == b.length(); |
199 | } |
200 | |
201 | inline const CalcExpressionLength& toCalcExpressionLength(const CalcExpressionNode& value) |
202 | { |
203 | ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeType::Length); |
204 | return static_cast<const CalcExpressionLength&>(value); |
205 | } |
206 | |
207 | inline CalcExpressionOperation::CalcExpressionOperation(Vector<std::unique_ptr<CalcExpressionNode>>&& children, CalcOperator op) |
208 | : CalcExpressionNode(CalcExpressionNodeType::Operation) |
209 | , m_children(WTFMove(children)) |
210 | , m_operator(op) |
211 | { |
212 | } |
213 | |
214 | bool operator==(const CalcExpressionOperation&, const CalcExpressionOperation&); |
215 | |
216 | inline const CalcExpressionOperation& toCalcExpressionOperation(const CalcExpressionNode& value) |
217 | { |
218 | ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeType::Operation); |
219 | return static_cast<const CalcExpressionOperation&>(value); |
220 | } |
221 | |
222 | inline bool operator==(const CalcExpressionBlendLength& a, const CalcExpressionBlendLength& b) |
223 | { |
224 | return a.progress() == b.progress() && a.from() == b.from() && a.to() == b.to(); |
225 | } |
226 | |
227 | inline const CalcExpressionBlendLength& toCalcExpressionBlendLength(const CalcExpressionNode& value) |
228 | { |
229 | ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeType::BlendLength); |
230 | return static_cast<const CalcExpressionBlendLength&>(value); |
231 | } |
232 | |
233 | WTF::TextStream& operator<<(WTF::TextStream&, const CalculationValue&); |
234 | WTF::TextStream& operator<<(WTF::TextStream&, const CalcExpressionNode&); |
235 | WTF::TextStream& operator<<(WTF::TextStream&, CalcOperator); |
236 | |
237 | } // namespace WebCore |
238 | |