[WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
[WebKit-https.git] / Source / WebCore / platform / graphics / Gradient.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "Gradient.h"
29
30 #include "Color.h"
31 #include "FloatRect.h"
32 #include <wtf/HashFunctions.h>
33 #include <wtf/Hasher.h>
34
35 using WTF::pairIntHash;
36
37 namespace WebCore {
38
39 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1)
40     : m_radial(false)
41     , m_p0(p0)
42     , m_p1(p1)
43     , m_r0(0)
44     , m_r1(0)
45     , m_aspectRatio(1)
46     , m_stopsSorted(false)
47     , m_spreadMethod(SpreadMethodPad)
48     , m_cachedHash(0)
49 {
50     platformInit();
51 }
52
53 Gradient::Gradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1, float aspectRatio)
54     : m_radial(true)
55     , m_p0(p0)
56     , m_p1(p1)
57     , m_r0(r0)
58     , m_r1(r1)
59     , m_aspectRatio(aspectRatio)
60     , m_stopsSorted(false)
61     , m_spreadMethod(SpreadMethodPad)
62     , m_cachedHash(0)
63 {
64     platformInit();
65 }
66
67 Gradient::~Gradient()
68 {
69     platformDestroy();
70 }
71
72 void Gradient::adjustParametersForTiledDrawing(FloatSize& size, FloatRect& srcRect, const FloatSize& spacing)
73 {
74     if (m_radial)
75         return;
76
77     if (srcRect.isEmpty())
78         return;
79
80     if (!spacing.isZero())
81         return;
82
83     if (m_p0.x() == m_p1.x()) {
84         size.setWidth(1);
85         srcRect.setWidth(1);
86         srcRect.setX(0);
87         return;
88     }
89     if (m_p0.y() != m_p1.y())
90         return;
91
92     size.setHeight(1);
93     srcRect.setHeight(1);
94     srcRect.setY(0);
95 }
96
97 void Gradient::addColorStop(float value, const Color& color)
98 {
99     // FIXME: ExtendedColor - update this to support colors with color spaces.
100     float r;
101     float g;
102     float b;
103     float a;
104     color.getRGBA(r, g, b, a);
105     m_stops.append(ColorStop(value, r, g, b, a));
106
107     m_stopsSorted = false;
108     platformDestroy();
109
110     invalidateHash();
111 }
112
113 void Gradient::addColorStop(const Gradient::ColorStop& stop)
114 {
115     m_stops.append(stop);
116
117     m_stopsSorted = false;
118     platformDestroy();
119
120     invalidateHash();
121 }
122
123 static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
124 {
125     return a.stop < b.stop;
126 }
127
128 void Gradient::sortStopsIfNecessary()
129 {
130     if (m_stopsSorted)
131         return;
132
133     m_stopsSorted = true;
134
135     if (!m_stops.size())
136         return;
137
138     std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
139
140     invalidateHash();
141 }
142
143 bool Gradient::hasAlpha() const
144 {
145     for (size_t i = 0; i < m_stops.size(); i++) {
146         if (m_stops[i].alpha < 1)
147             return true;
148     }
149
150     return false;
151 }
152
153 void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod)
154 {
155     // FIXME: Should it become necessary, allow calls to this method after m_gradient has been set.
156     ASSERT(m_gradient == 0);
157
158     if (m_spreadMethod == spreadMethod)
159         return;
160
161     m_spreadMethod = spreadMethod;
162
163     invalidateHash();
164 }
165
166 void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation)
167 {
168     if (m_gradientSpaceTransformation == gradientSpaceTransformation)
169         return;
170
171     m_gradientSpaceTransformation = gradientSpaceTransformation;
172     setPlatformGradientSpaceTransform(gradientSpaceTransformation);
173
174     invalidateHash();
175 }
176
177 #if !USE(CAIRO)
178 void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&)
179 {
180 }
181 #endif
182
183 unsigned Gradient::hash() const
184 {
185     if (m_cachedHash)
186         return m_cachedHash;
187
188     struct {
189         AffineTransform gradientSpaceTransformation;
190         FloatPoint p0;
191         FloatPoint p1;
192         float r0;
193         float r1;
194         float aspectRatio;
195         GradientSpreadMethod spreadMethod;
196         bool radial;
197     } parameters;
198
199     // StringHasher requires that the memory it hashes be a multiple of two in size.
200     COMPILE_ASSERT(!(sizeof(parameters) % 2), Gradient_parameters_size_should_be_multiple_of_two);
201     COMPILE_ASSERT(!(sizeof(ColorStop) % 2), Color_stop_size_should_be_multiple_of_two);
202     
203     // Ensure that any padding in the struct is zero-filled, so it will not affect the hash value.
204     memset(&parameters, 0, sizeof(parameters));
205     
206     parameters.gradientSpaceTransformation = m_gradientSpaceTransformation;
207     parameters.p0 = m_p0;
208     parameters.p1 = m_p1;
209     parameters.r0 = m_r0;
210     parameters.r1 = m_r1;
211     parameters.aspectRatio = m_aspectRatio;
212     parameters.spreadMethod = m_spreadMethod;
213     parameters.radial = m_radial;
214
215     unsigned parametersHash = StringHasher::hashMemory(&parameters, sizeof(parameters));
216     unsigned stopHash = StringHasher::hashMemory(m_stops.data(), m_stops.size() * sizeof(ColorStop));
217
218     m_cachedHash = pairIntHash(parametersHash, stopHash);
219
220     return m_cachedHash;
221 }
222
223 } //namespace