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