1/*
2 * Copyright (C) 2008 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef CSSGradientValue_h
27#define CSSGradientValue_h
28
29#include "CSSImageGeneratorValue.h"
30#include "CSSPrimitiveValue.h"
31#include <wtf/RefPtr.h>
32#include <wtf/Vector.h>
33
34namespace WebCore {
35
36class FloatPoint;
37class Gradient;
38
39enum CSSGradientType {
40    CSSDeprecatedLinearGradient,
41    CSSDeprecatedRadialGradient,
42    CSSPrefixedLinearGradient,
43    CSSPrefixedRadialGradient,
44    CSSLinearGradient,
45    CSSRadialGradient
46};
47enum CSSGradientRepeat { NonRepeating, Repeating };
48
49struct CSSGradientColorStop {
50    CSSGradientColorStop() : m_colorIsDerivedFromElement(false) { };
51    RefPtr<CSSPrimitiveValue> m_position; // percentage or length
52    RefPtr<CSSPrimitiveValue> m_color;
53    Color m_resolvedColor;
54    bool m_colorIsDerivedFromElement;
55    bool operator==(const CSSGradientColorStop& other) const
56    {
57        return compareCSSValuePtr(m_color, other.m_color)
58            && compareCSSValuePtr(m_position, other.m_position);
59    }
60};
61
62class CSSGradientValue : public CSSImageGeneratorValue {
63public:
64    PassRefPtr<Image> image(RenderObject*, const IntSize&);
65
66    void setFirstX(PassRefPtr<CSSPrimitiveValue> val) { m_firstX = val; }
67    void setFirstY(PassRefPtr<CSSPrimitiveValue> val) { m_firstY = val; }
68    void setSecondX(PassRefPtr<CSSPrimitiveValue> val) { m_secondX = val; }
69    void setSecondY(PassRefPtr<CSSPrimitiveValue> val) { m_secondY = val; }
70
71    void addStop(const CSSGradientColorStop& stop) { m_stops.append(stop); }
72
73    unsigned stopCount() const { return m_stops.size(); }
74
75    void sortStopsIfNeeded();
76
77    bool isLinearGradient() const { return classType() == LinearGradientClass; }
78    bool isRadialGradient() const { return classType() == RadialGradientClass; }
79
80    bool isRepeating() const { return m_repeating; }
81
82    CSSGradientType gradientType() const { return m_gradientType; }
83
84    bool isFixedSize() const { return false; }
85    IntSize fixedSize(const RenderObject*) const { return IntSize(); }
86
87    bool isPending() const { return false; }
88    bool knownToBeOpaque(const RenderObject*) const;
89
90    void loadSubimages(CachedResourceLoader*) { }
91    PassRefPtr<CSSGradientValue> gradientWithStylesResolved(StyleResolver*);
92
93protected:
94    CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, CSSGradientType gradientType)
95        : CSSImageGeneratorValue(classType)
96        , m_stopsSorted(false)
97        , m_gradientType(gradientType)
98        , m_repeating(repeat == Repeating)
99    {
100    }
101
102    CSSGradientValue(const CSSGradientValue& other, ClassType classType, CSSGradientType gradientType)
103        : CSSImageGeneratorValue(classType)
104        , m_firstX(other.m_firstX)
105        , m_firstY(other.m_firstY)
106        , m_secondX(other.m_secondX)
107        , m_secondY(other.m_secondY)
108        , m_stops(other.m_stops)
109        , m_stopsSorted(other.m_stopsSorted)
110        , m_gradientType(gradientType)
111        , m_repeating(other.isRepeating() ? Repeating : NonRepeating)
112    {
113    }
114
115    void addStops(Gradient*, RenderObject*, RenderStyle* rootStyle, float maxLengthForRepeat = 0);
116
117    // Resolve points/radii to front end values.
118    FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, const IntSize&);
119
120    bool isCacheable() const;
121
122    // Points. Some of these may be null.
123    RefPtr<CSSPrimitiveValue> m_firstX;
124    RefPtr<CSSPrimitiveValue> m_firstY;
125
126    RefPtr<CSSPrimitiveValue> m_secondX;
127    RefPtr<CSSPrimitiveValue> m_secondY;
128
129    // Stops
130    Vector<CSSGradientColorStop, 2> m_stops;
131    bool m_stopsSorted;
132    CSSGradientType m_gradientType;
133    bool m_repeating;
134};
135
136
137class CSSLinearGradientValue : public CSSGradientValue {
138public:
139
140    static PassRefPtr<CSSLinearGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient)
141    {
142        return adoptRef(new CSSLinearGradientValue(repeat, gradientType));
143    }
144
145    void setAngle(PassRefPtr<CSSPrimitiveValue> val) { m_angle = val; }
146
147    String customCssText() const;
148
149    // Create the gradient for a given size.
150    PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
151
152    PassRefPtr<CSSLinearGradientValue> clone() const
153    {
154        return adoptRef(new CSSLinearGradientValue(*this));
155    }
156
157    bool equals(const CSSLinearGradientValue&) const;
158
159private:
160    CSSLinearGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient)
161        : CSSGradientValue(LinearGradientClass, repeat, gradientType)
162    {
163    }
164
165    CSSLinearGradientValue(const CSSLinearGradientValue& other)
166        : CSSGradientValue(other, LinearGradientClass, other.gradientType())
167        , m_angle(other.m_angle)
168    {
169    }
170
171    RefPtr<CSSPrimitiveValue> m_angle; // may be null.
172};
173
174class CSSRadialGradientValue : public CSSGradientValue {
175public:
176    static PassRefPtr<CSSRadialGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient)
177    {
178        return adoptRef(new CSSRadialGradientValue(repeat, gradientType));
179    }
180
181    PassRefPtr<CSSRadialGradientValue> clone() const
182    {
183        return adoptRef(new CSSRadialGradientValue(*this));
184    }
185
186    String customCssText() const;
187
188    void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
189    void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
190
191    void setShape(PassRefPtr<CSSPrimitiveValue> val) { m_shape = val; }
192    void setSizingBehavior(PassRefPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; }
193
194    void setEndHorizontalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; }
195    void setEndVerticalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; }
196
197    // Create the gradient for a given size.
198    PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
199
200    bool equals(const CSSRadialGradientValue&) const;
201
202private:
203    CSSRadialGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient)
204        : CSSGradientValue(RadialGradientClass, repeat, gradientType)
205    {
206    }
207
208    CSSRadialGradientValue(const CSSRadialGradientValue& other)
209        : CSSGradientValue(other, RadialGradientClass, other.gradientType())
210        , m_firstRadius(other.m_firstRadius)
211        , m_secondRadius(other.m_secondRadius)
212        , m_shape(other.m_shape)
213        , m_sizingBehavior(other.m_sizingBehavior)
214        , m_endHorizontalSize(other.m_endHorizontalSize)
215        , m_endVerticalSize(other.m_endVerticalSize)
216    {
217    }
218
219
220    // Resolve points/radii to front end values.
221    float resolveRadius(CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, float* widthOrHeight = 0);
222
223    // These may be null for non-deprecated gradients.
224    RefPtr<CSSPrimitiveValue> m_firstRadius;
225    RefPtr<CSSPrimitiveValue> m_secondRadius;
226
227    // The below are only used for non-deprecated gradients. Any of them may be null.
228    RefPtr<CSSPrimitiveValue> m_shape;
229    RefPtr<CSSPrimitiveValue> m_sizingBehavior;
230
231    RefPtr<CSSPrimitiveValue> m_endHorizontalSize;
232    RefPtr<CSSPrimitiveValue> m_endVerticalSize;
233};
234
235} // namespace WebCore
236
237#endif // CSSGradientValue_h
238