OLD | NEW |
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 18 matching lines...) Expand all Loading... |
29 #include "platform/graphics/Gradient.h" | 29 #include "platform/graphics/Gradient.h" |
30 | 30 |
31 #include "platform/geometry/FloatRect.h" | 31 #include "platform/geometry/FloatRect.h" |
32 #include "platform/graphics/Color.h" | 32 #include "platform/graphics/Color.h" |
33 #include "platform/graphics/GraphicsContext.h" | 33 #include "platform/graphics/GraphicsContext.h" |
34 #include "platform/graphics/skia/SkiaUtils.h" | 34 #include "platform/graphics/skia/SkiaUtils.h" |
35 #include "third_party/skia/include/core/SkColorShader.h" | 35 #include "third_party/skia/include/core/SkColorShader.h" |
36 #include "third_party/skia/include/core/SkShader.h" | 36 #include "third_party/skia/include/core/SkShader.h" |
37 #include "third_party/skia/include/effects/SkGradientShader.h" | 37 #include "third_party/skia/include/effects/SkGradientShader.h" |
38 | 38 |
| 39 typedef Vector<SkScalar, 8> ColorStopOffsetVector; |
| 40 typedef Vector<SkColor, 8> ColorStopColorVector; |
| 41 |
39 namespace WebCore { | 42 namespace WebCore { |
40 | 43 |
41 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1) | 44 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1) |
42 : m_p0(p0) | 45 : m_p0(p0) |
43 , m_p1(p1) | 46 , m_p1(p1) |
44 , m_r0(0) | 47 , m_r0(0) |
45 , m_r1(0) | 48 , m_r1(0) |
46 , m_aspectRatio(1) | 49 , m_aspectRatio(1) |
47 , m_radial(false) | 50 , m_radial(false) |
48 , m_stopsSorted(false) | 51 , m_stopsSorted(false) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 if (count < 1 || stop->stop < 1.0) | 174 if (count < 1 || stop->stop < 1.0) |
172 countUsed++; | 175 countUsed++; |
173 return countUsed; | 176 return countUsed; |
174 } | 177 } |
175 | 178 |
176 // Collect sorted stop position and color information into the pos and colors | 179 // Collect sorted stop position and color information into the pos and colors |
177 // buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large | 180 // buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large |
178 // enough to hold information for all stops, including the new endpoints if | 181 // enough to hold information for all stops, including the new endpoints if |
179 // stops at 0.0 and 1.0 aren't already included. | 182 // stops at 0.0 and 1.0 aren't already included. |
180 static void fillStops(const Gradient::ColorStop* stopData, | 183 static void fillStops(const Gradient::ColorStop* stopData, |
181 size_t count, SkScalar* pos, SkColor* colors) | 184 size_t count, ColorStopOffsetVector& pos, ColorStopColorVector& colors) |
182 { | 185 { |
183 const Gradient::ColorStop* stop = stopData; | 186 const Gradient::ColorStop* stop = stopData; |
184 size_t start = 0; | 187 size_t start = 0; |
185 if (count < 1) { | 188 if (count < 1) { |
186 // A gradient with no stops must be transparent black. | 189 // A gradient with no stops must be transparent black. |
187 pos[0] = WebCoreFloatToSkScalar(0.0); | 190 pos[0] = WebCoreFloatToSkScalar(0.0); |
188 colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0); | 191 colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0); |
189 start = 1; | 192 start = 1; |
190 } else if (stop->stop > 0.0) { | 193 } else if (stop->stop > 0.0) { |
191 // Copy the first stop to 0.0. The first stop position may have a slight | 194 // Copy the first stop to 0.0. The first stop position may have a slight |
(...skipping 24 matching lines...) Expand all Loading... |
216 if (m_gradient) | 219 if (m_gradient) |
217 return m_gradient.get(); | 220 return m_gradient.get(); |
218 | 221 |
219 sortStopsIfNecessary(); | 222 sortStopsIfNecessary(); |
220 ASSERT(m_stopsSorted); | 223 ASSERT(m_stopsSorted); |
221 | 224 |
222 size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); | 225 size_t countUsed = totalStopsNeeded(m_stops.data(), m_stops.size()); |
223 ASSERT(countUsed >= 2); | 226 ASSERT(countUsed >= 2); |
224 ASSERT(countUsed >= m_stops.size()); | 227 ASSERT(countUsed >= m_stops.size()); |
225 | 228 |
226 // FIXME: Why is all this manual pointer math needed?! | 229 ColorStopOffsetVector pos(countUsed); |
227 SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar))); | 230 ColorStopColorVector colors(countUsed); |
228 SkColor* colors = (SkColor*)storage.get(); | |
229 SkScalar* pos = (SkScalar*)(colors + countUsed); | |
230 | |
231 fillStops(m_stops.data(), m_stops.size(), pos, colors); | 231 fillStops(m_stops.data(), m_stops.size(), pos, colors); |
232 | 232 |
233 SkShader::TileMode tile = SkShader::kClamp_TileMode; | 233 SkShader::TileMode tile = SkShader::kClamp_TileMode; |
234 switch (m_spreadMethod) { | 234 switch (m_spreadMethod) { |
235 case SpreadMethodReflect: | 235 case SpreadMethodReflect: |
236 tile = SkShader::kMirror_TileMode; | 236 tile = SkShader::kMirror_TileMode; |
237 break; | 237 break; |
238 case SpreadMethodRepeat: | 238 case SpreadMethodRepeat: |
239 tile = SkShader::kRepeat_TileMode; | 239 tile = SkShader::kRepeat_TileMode; |
240 break; | 240 break; |
241 case SpreadMethodPad: | 241 case SpreadMethodPad: |
242 tile = SkShader::kClamp_TileMode; | 242 tile = SkShader::kClamp_TileMode; |
243 break; | 243 break; |
244 } | 244 } |
245 | 245 |
246 uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader:
:kInterpolateColorsInPremul_Flag : 0; | 246 uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader:
:kInterpolateColorsInPremul_Flag : 0; |
247 if (m_radial) { | 247 if (m_radial) { |
248 // Since the two-point radial gradient is slower than the plain radial, | 248 // Since the two-point radial gradient is slower than the plain radial, |
249 // only use it if we have to. | 249 // only use it if we have to. |
250 if (m_p0 == m_p1 && m_r0 <= 0.0f) { | 250 if (m_p0 == m_p1 && m_r0 <= 0.0f) { |
251 m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, col
ors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); | 251 m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, col
ors.data(), pos.data(), static_cast<int>(countUsed), tile, 0, shouldDrawInPMColo
rSpace)); |
252 } else { | 252 } else { |
253 // The radii we give to Skia must be positive. If we're given a | 253 // The radii we give to Skia must be positive. If we're given a |
254 // negative radius, ask for zero instead. | 254 // negative radius, ask for zero instead. |
255 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; | 255 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; |
256 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; | 256 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; |
257 m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0,
radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile, 0, shoul
dDrawInPMColorSpace)); | 257 m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0,
radius0, m_p1, radius1, colors.data(), pos.data(), static_cast<int>(countUsed),
tile, 0, shouldDrawInPMColorSpace)); |
258 } | 258 } |
259 | 259 |
260 if (aspectRatio() != 1) { | 260 if (aspectRatio() != 1) { |
261 // CSS3 elliptical gradients: apply the elliptical scaling at the | 261 // CSS3 elliptical gradients: apply the elliptical scaling at the |
262 // gradient center point. | 262 // gradient center point. |
263 m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); | 263 m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y()); |
264 m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); | 264 m_gradientSpaceTransformation.scale(1, 1 / aspectRatio()); |
265 m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); | 265 m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y()); |
266 ASSERT(m_p0 == m_p1); | 266 ASSERT(m_p0 == m_p1); |
267 } | 267 } |
268 } else { | 268 } else { |
269 SkPoint pts[2] = { m_p0, m_p1 }; | 269 SkPoint pts[2] = { m_p0, m_p1 }; |
270 m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors, pos, s
tatic_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); | 270 m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors.data(),
pos.data(), static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace)); |
271 } | 271 } |
272 | 272 |
273 if (!m_gradient) { | 273 if (!m_gradient) { |
274 // use last color, since our "geometry" was degenerate (e.g. radius==0) | 274 // use last color, since our "geometry" was degenerate (e.g. radius==0) |
275 m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1])); | 275 m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1])); |
276 } else { | 276 } else { |
277 m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTran
sformation)); | 277 m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTran
sformation)); |
278 } | 278 } |
279 return m_gradient.get(); | 279 return m_gradient.get(); |
280 } | 280 } |
281 | 281 |
282 } //namespace | 282 } //namespace |
OLD | NEW |