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#ifndef CalculationValue_h
32#define CalculationValue_h
33
34#include "Length.h"
35#include "LengthFunctions.h"
36#include <memory>
37#include <wtf/RefCounted.h>
38#include <wtf/Vector.h>
39
40namespace WebCore {
41
42enum CalcOperator {
43    CalcAdd = '+',
44    CalcSubtract = '-',
45    CalcMultiply = '*',
46    CalcDivide = '/'
47};
48
49enum CalculationPermittedValueRange {
50    CalculationRangeAll,
51    CalculationRangeNonNegative
52};
53
54enum CalcExpressionNodeType {
55    CalcExpressionNodeUndefined,
56    CalcExpressionNodeNumber,
57    CalcExpressionNodeLength,
58    CalcExpressionNodeBinaryOperation,
59    CalcExpressionNodeBlendLength,
60};
61
62class CalcExpressionNode {
63    WTF_MAKE_FAST_ALLOCATED;
64public:
65    explicit CalcExpressionNode(CalcExpressionNodeType = CalcExpressionNodeUndefined);
66    virtual ~CalcExpressionNode() { }
67
68    CalcExpressionNodeType type() const { return m_type; }
69
70    virtual float evaluate(float maxValue) const = 0;
71    virtual bool operator==(const CalcExpressionNode&) const = 0;
72
73private:
74    CalcExpressionNodeType m_type;
75};
76
77class CalcExpressionNumber final : public CalcExpressionNode {
78public:
79    explicit CalcExpressionNumber(float);
80
81    float value() const { return m_value; }
82
83private:
84    virtual float evaluate(float) const override;
85    virtual bool operator==(const CalcExpressionNode&) const override;
86
87    float m_value;
88};
89
90class CalcExpressionLength final : public CalcExpressionNode {
91public:
92    explicit CalcExpressionLength(Length);
93
94    const Length& length() const { return m_length; }
95
96private:
97    virtual float evaluate(float maxValue) const override;
98    virtual bool operator==(const CalcExpressionNode&) const override;
99
100    Length m_length;
101};
102
103class CalcExpressionBinaryOperation final : public CalcExpressionNode {
104public:
105    CalcExpressionBinaryOperation(std::unique_ptr<CalcExpressionNode> leftSide, std::unique_ptr<CalcExpressionNode> rightSide, CalcOperator);
106
107    const CalcExpressionNode& leftSide() const { return *m_leftSide; }
108    const CalcExpressionNode& rightSide() const { return *m_rightSide; }
109    CalcOperator getOperator() const { return m_operator; }
110
111private:
112    virtual float evaluate(float maxValue) const override;
113    virtual bool operator==(const CalcExpressionNode&) const override;
114
115    std::unique_ptr<CalcExpressionNode> m_leftSide;
116    std::unique_ptr<CalcExpressionNode> m_rightSide;
117    CalcOperator m_operator;
118};
119
120class CalcExpressionBlendLength final : public CalcExpressionNode {
121public:
122    CalcExpressionBlendLength(Length from, Length to, float progress);
123
124    const Length& from() const { return m_from; }
125    const Length& to() const { return m_to; }
126    float progress() const { return m_progress; }
127
128private:
129    virtual float evaluate(float maxValue) const override;
130    virtual bool operator==(const CalcExpressionNode&) const override;
131
132    Length m_from;
133    Length m_to;
134    float m_progress;
135};
136
137class CalculationValue : public RefCounted<CalculationValue> {
138public:
139    static PassRef<CalculationValue> create(std::unique_ptr<CalcExpressionNode>, CalculationPermittedValueRange);
140    float evaluate(float maxValue) const;
141
142    bool shouldClampToNonNegative() const { return m_shouldClampToNonNegative; }
143    const CalcExpressionNode& expression() const { return *m_expression; }
144
145private:
146    CalculationValue(std::unique_ptr<CalcExpressionNode>, CalculationPermittedValueRange);
147
148    std::unique_ptr<CalcExpressionNode> m_expression;
149    bool m_shouldClampToNonNegative;
150};
151
152inline CalcExpressionNode::CalcExpressionNode(CalcExpressionNodeType type)
153    : m_type(type)
154{
155}
156
157inline CalculationValue::CalculationValue(std::unique_ptr<CalcExpressionNode> expression, CalculationPermittedValueRange range)
158    : m_expression(WTF::move(expression))
159    , m_shouldClampToNonNegative(range == CalculationRangeNonNegative)
160{
161}
162
163inline bool operator==(const CalculationValue& a, const CalculationValue& b)
164{
165    return a.expression() == b.expression();
166}
167
168inline CalcExpressionNumber::CalcExpressionNumber(float value)
169    : CalcExpressionNode(CalcExpressionNodeNumber)
170    , m_value(value)
171{
172}
173
174inline bool operator==(const CalcExpressionNumber& a, const CalcExpressionNumber& b)
175{
176    return a.value() == b.value();
177}
178
179inline const CalcExpressionNumber& toCalcExpressionNumber(const CalcExpressionNode& value)
180{
181    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeNumber);
182    return static_cast<const CalcExpressionNumber&>(value);
183}
184
185inline CalcExpressionLength::CalcExpressionLength(Length length)
186    : CalcExpressionNode(CalcExpressionNodeLength)
187    , m_length(length)
188{
189}
190
191inline bool operator==(const CalcExpressionLength& a, const CalcExpressionLength& b)
192{
193    return a.length() == b.length();
194}
195
196inline const CalcExpressionLength& toCalcExpressionLength(const CalcExpressionNode& value)
197{
198    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeLength);
199    return static_cast<const CalcExpressionLength&>(value);
200}
201
202inline CalcExpressionBinaryOperation::CalcExpressionBinaryOperation(std::unique_ptr<CalcExpressionNode> leftSide, std::unique_ptr<CalcExpressionNode> rightSide, CalcOperator op)
203    : CalcExpressionNode(CalcExpressionNodeBinaryOperation)
204    , m_leftSide(WTF::move(leftSide))
205    , m_rightSide(WTF::move(rightSide))
206    , m_operator(op)
207{
208}
209
210inline bool operator==(const CalcExpressionBinaryOperation& a, const CalcExpressionBinaryOperation& b)
211{
212    return a.getOperator() == b.getOperator() && a.leftSide() == b.leftSide() && a.rightSide() == b.rightSide();
213}
214
215inline const CalcExpressionBinaryOperation& toCalcExpressionBinaryOperation(const CalcExpressionNode& value)
216{
217    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeBinaryOperation);
218    return static_cast<const CalcExpressionBinaryOperation&>(value);
219}
220
221inline CalcExpressionBlendLength::CalcExpressionBlendLength(Length from, Length to, float progress)
222    : CalcExpressionNode(CalcExpressionNodeBlendLength)
223    , m_from(from)
224    , m_to(to)
225    , m_progress(progress)
226{
227}
228
229inline bool operator==(const CalcExpressionBlendLength& a, const CalcExpressionBlendLength& b)
230{
231    return a.progress() == b.progress() && a.from() == b.from() && a.to() == b.to();
232}
233
234inline const CalcExpressionBlendLength& toCalcExpressionBlendLength(const CalcExpressionNode& value)
235{
236    ASSERT_WITH_SECURITY_IMPLICATION(value.type() == CalcExpressionNodeBlendLength);
237    return static_cast<const CalcExpressionBlendLength&>(value);
238}
239
240} // namespace WebCore
241
242#endif // CalculationValue_h
243