Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/Gradient.cpp

Issue 2007553002: Retire setGradientSpaceTransform, setPatternSpaceTransform (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fmalita discovers SkMatrix::I() Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4 * Copyright (C) 2013 Google Inc. All rights reserved. 4 * Copyright (C) 2013 Google Inc. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 13 matching lines...) Expand all
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "platform/graphics/Gradient.h" 28 #include "platform/graphics/Gradient.h"
29 29
30 #include "platform/geometry/FloatRect.h" 30 #include "platform/geometry/FloatRect.h"
31 #include "platform/graphics/GraphicsContext.h" 31 #include "platform/graphics/GraphicsContext.h"
32 #include "platform/graphics/skia/SkiaUtils.h" 32 #include "platform/graphics/skia/SkiaUtils.h"
33 #include "third_party/skia/include/core/SkColor.h" 33 #include "third_party/skia/include/core/SkColor.h"
34 #include "third_party/skia/include/core/SkMatrix.h"
34 #include "third_party/skia/include/core/SkShader.h" 35 #include "third_party/skia/include/core/SkShader.h"
35 #include "third_party/skia/include/effects/SkGradientShader.h" 36 #include "third_party/skia/include/effects/SkGradientShader.h"
36 #include <algorithm> 37 #include <algorithm>
37 38
38 typedef Vector<SkScalar, 8> ColorStopOffsetVector; 39 typedef Vector<SkScalar, 8> ColorStopOffsetVector;
39 typedef Vector<SkColor, 8> ColorStopColorVector; 40 typedef Vector<SkColor, 8> ColorStopColorVector;
40 41
41 namespace blink { 42 namespace blink {
42 43
43 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1) 44 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 78
78 void Gradient::addColorStop(const Gradient::ColorStop& stop) 79 void Gradient::addColorStop(const Gradient::ColorStop& stop)
79 { 80 {
80 if (m_stops.isEmpty()) { 81 if (m_stops.isEmpty()) {
81 m_stopsSorted = true; 82 m_stopsSorted = true;
82 } else { 83 } else {
83 m_stopsSorted = m_stopsSorted && compareStops(m_stops.last(), stop); 84 m_stopsSorted = m_stopsSorted && compareStops(m_stops.last(), stop);
84 } 85 }
85 86
86 m_stops.append(stop); 87 m_stops.append(stop);
87 m_gradient.reset(); 88 m_cachedShader.reset();
88 } 89 }
89 90
90 void Gradient::sortStopsIfNecessary() 91 void Gradient::sortStopsIfNecessary()
91 { 92 {
92 if (m_stopsSorted) 93 if (m_stopsSorted)
93 return; 94 return;
94 95
95 m_stopsSorted = true; 96 m_stopsSorted = true;
96 97
97 if (!m_stops.size()) 98 if (!m_stops.size())
98 return; 99 return;
99 100
100 std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); 101 std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
101 } 102 }
102 103
103 void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod) 104 void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod)
104 { 105 {
105 // FIXME: Should it become necessary, allow calls to this method after m_gra dient has been set. 106 // FIXME: Should it become necessary, allow calls to this method after m_gra dient has been set.
106 ASSERT(!m_gradient); 107 DCHECK(!m_cachedShader);
107 108
108 if (m_spreadMethod == spreadMethod) 109 if (m_spreadMethod == spreadMethod)
109 return; 110 return;
110 111
111 m_spreadMethod = spreadMethod; 112 m_spreadMethod = spreadMethod;
112 } 113 }
113 114
114 void Gradient::setDrawsInPMColorSpace(bool drawInPMColorSpace) 115 void Gradient::setDrawsInPMColorSpace(bool drawInPMColorSpace)
115 { 116 {
116 if (drawInPMColorSpace == m_drawInPMColorSpace) 117 if (drawInPMColorSpace == m_drawInPMColorSpace)
117 return; 118 return;
118 119
119 m_drawInPMColorSpace = drawInPMColorSpace; 120 m_drawInPMColorSpace = drawInPMColorSpace;
120 m_gradient.reset(); 121 m_cachedShader.reset();
121 }
122
123 void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra nsformation)
124 {
125 if (m_gradientSpaceTransformation == gradientSpaceTransformation)
126 return;
127
128 m_gradientSpaceTransformation = gradientSpaceTransformation;
129 m_gradient.reset();
130 } 122 }
131 123
132 // Determine the total number of stops needed, including pseudo-stops at the 124 // Determine the total number of stops needed, including pseudo-stops at the
133 // ends as necessary. 125 // ends as necessary.
134 static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count ) 126 static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count )
135 { 127 {
136 // N.B.: The tests in this function should kept in sync with the ones in 128 // N.B.: The tests in this function should kept in sync with the ones in
137 // fillStops(), or badness happens. 129 // fillStops(), or badness happens.
138 const Gradient::ColorStop* stop = stopData; 130 const Gradient::ColorStop* stop = stopData;
139 size_t countUsed = count; 131 size_t countUsed = count;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 } 174 }
183 175
184 // Copy the last stop to 1.0 if needed. See comment above about this float 176 // Copy the last stop to 1.0 if needed. See comment above about this float
185 // comparison. 177 // comparison.
186 if (count < 1 || (--stop)->stop < 1.0) { 178 if (count < 1 || (--stop)->stop < 1.0) {
187 pos[start + count] = WebCoreFloatToSkScalar(1.0); 179 pos[start + count] = WebCoreFloatToSkScalar(1.0);
188 colors[start + count] = colors[start + count - 1]; 180 colors[start + count] = colors[start + count - 1];
189 } 181 }
190 } 182 }
191 183
192 sk_sp<SkShader> Gradient::createShader() 184 sk_sp<SkShader> Gradient::createShader(const SkMatrix& localMatrix)
193 { 185 {
194 sortStopsIfNecessary(); 186 sortStopsIfNecessary();
195 ASSERT(m_stopsSorted); 187 ASSERT(m_stopsSorted);
196 188
197 size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); 189 size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size());
198 ASSERT(countUsed >= 2); 190 ASSERT(countUsed >= 2);
199 ASSERT(countUsed >= m_stops.size()); 191 ASSERT(countUsed >= m_stops.size());
200 192
201 ColorStopOffsetVector pos(countUsed); 193 ColorStopOffsetVector pos(countUsed);
202 ColorStopColorVector colors(countUsed); 194 ColorStopColorVector colors(countUsed);
203 fillStops(m_stops.data(), m_stops.size(), pos, colors); 195 fillStops(m_stops.data(), m_stops.size(), pos, colors);
204 196
205 SkShader::TileMode tile = SkShader::kClamp_TileMode; 197 SkShader::TileMode tile = SkShader::kClamp_TileMode;
206 switch (m_spreadMethod) { 198 switch (m_spreadMethod) {
207 case SpreadMethodReflect: 199 case SpreadMethodReflect:
208 tile = SkShader::kMirror_TileMode; 200 tile = SkShader::kMirror_TileMode;
209 break; 201 break;
210 case SpreadMethodRepeat: 202 case SpreadMethodRepeat:
211 tile = SkShader::kRepeat_TileMode; 203 tile = SkShader::kRepeat_TileMode;
212 break; 204 break;
213 case SpreadMethodPad: 205 case SpreadMethodPad:
214 tile = SkShader::kClamp_TileMode; 206 tile = SkShader::kClamp_TileMode;
215 break; 207 break;
216 } 208 }
217 209
218 sk_sp<SkShader> shader; 210 sk_sp<SkShader> shader;
219 uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader: :kInterpolateColorsInPremul_Flag : 0; 211 uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader: :kInterpolateColorsInPremul_Flag : 0;
220 if (m_radial) { 212 if (m_radial) {
221 if (aspectRatio() != 1) { 213 SkMatrix adjustedLocalMatrix = localMatrix;
214
215 if (m_aspectRatio != 1) {
222 // CSS3 elliptical gradients: apply the elliptical scaling at the 216 // CSS3 elliptical gradients: apply the elliptical scaling at the
223 // gradient center point. 217 // gradient center point.
224 m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); 218 adjustedLocalMatrix.preTranslate(m_p0.x(), m_p0.y());
225 m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); 219 adjustedLocalMatrix.preScale(1, 1 / m_aspectRatio);
226 m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); 220 adjustedLocalMatrix.preTranslate(-m_p0.x(), -m_p0.y());
227 ASSERT(m_p0 == m_p1); 221 ASSERT(m_p0 == m_p1);
228 } 222 }
229 SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransfor mation);
230 223
231 // Since the two-point radial gradient is slower than the plain radial, 224 // Since the two-point radial gradient is slower than the plain radial,
232 // only use it if we have to. 225 // only use it if we have to.
233 if (m_p0 == m_p1 && m_r0 <= 0.0f) { 226 if (m_p0 == m_p1 && m_r0 <= 0.0f) {
234 shader = SkGradientShader::MakeRadial(m_p1.data(), m_r1, colors.data (), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &lo calMatrix); 227 shader = SkGradientShader::MakeRadial(m_p1.data(), m_r1, colors.data (), pos.data(),
228 static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &ad justedLocalMatrix);
235 } else { 229 } else {
236 // The radii we give to Skia must be positive. If we're given a 230 // The radii we give to Skia must be positive. If we're given a
237 // negative radius, ask for zero instead. 231 // negative radius, ask for zero instead.
238 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; 232 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
239 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; 233 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
240 shader = SkGradientShader::MakeTwoPointConical(m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), static_cast<int>(countUsed), t ile, shouldDrawInPMColorSpace, &localMatrix); 234 shader = SkGradientShader::MakeTwoPointConical(m_p0.data(), radius0, m_p1.data(),
235 radius1, colors.data(), pos.data(), static_cast<int>(countUsed), tile,
236 shouldDrawInPMColorSpace, &adjustedLocalMatrix);
241 } 237 }
242 } else { 238 } else {
243 SkPoint pts[2] = { m_p0.data(), m_p1.data() }; 239 SkPoint pts[2] = { m_p0.data(), m_p1.data() };
244 SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransfor mation); 240 shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
245 shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), st atic_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix); 241 static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localM atrix);
246 } 242 }
247 243
248 if (!shader) { 244 if (!shader) {
249 // use last color, since our "geometry" was degenerate (e.g. radius==0) 245 // use last color, since our "geometry" was degenerate (e.g. radius==0)
250 shader = SkShader::MakeColorShader(colors[countUsed - 1]); 246 shader = SkShader::MakeColorShader(colors[countUsed - 1]);
251 } 247 }
252 248
253 return shader; 249 return shader;
254 } 250 }
255 251
256 void Gradient::applyToPaint(SkPaint& paint) 252 void Gradient::applyToPaint(SkPaint& paint, const SkMatrix& localMatrix)
257 { 253 {
258 if (!m_gradient) 254 if (!m_cachedShader || localMatrix != m_cachedShader->getLocalMatrix())
259 m_gradient = createShader(); 255 m_cachedShader = createShader(localMatrix);
260 256
261 paint.setShader(m_gradient); 257 paint.setShader(m_cachedShader);
262 258
263 // Legacy behavior: gradients are always dithered. 259 // Legacy behavior: gradients are always dithered.
264 paint.setDither(true); 260 paint.setDither(true);
265 } 261 }
266 262
267 } // namespace blink 263 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698