| 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 24 matching lines...) Expand all Loading... |
| 35 #include "third_party/skia/include/core/SkMatrix.h" | 35 #include "third_party/skia/include/core/SkMatrix.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 #include <algorithm> | 38 #include <algorithm> |
| 39 | 39 |
| 40 typedef Vector<SkScalar, 8> ColorStopOffsetVector; | 40 typedef Vector<SkScalar, 8> ColorStopOffsetVector; |
| 41 typedef Vector<SkColor, 8> ColorStopColorVector; | 41 typedef Vector<SkColor, 8> ColorStopColorVector; |
| 42 | 42 |
| 43 namespace blink { | 43 namespace blink { |
| 44 | 44 |
| 45 Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1) | 45 Gradient::Gradient(const FloatPoint& p0, |
| 46 const FloatPoint& p1, |
| 47 GradientSpreadMethod spreadMethod, |
| 48 ColorInterpolation interpolation) |
| 46 : m_p0(p0), | 49 : m_p0(p0), |
| 47 m_p1(p1), | 50 m_p1(p1), |
| 48 m_r0(0), | 51 m_r0(0), |
| 49 m_r1(0), | 52 m_r1(0), |
| 50 m_aspectRatio(1), | 53 m_aspectRatio(1), |
| 51 m_radial(false), | 54 m_radial(false), |
| 52 m_stopsSorted(false), | 55 m_stopsSorted(false), |
| 53 m_drawInPMColorSpace(false), | 56 m_spreadMethod(spreadMethod), |
| 54 m_spreadMethod(SpreadMethodPad) {} | 57 m_colorInterpolation(interpolation) {} |
| 55 | 58 |
| 56 Gradient::Gradient(const FloatPoint& p0, | 59 Gradient::Gradient(const FloatPoint& p0, |
| 57 float r0, | 60 float r0, |
| 58 const FloatPoint& p1, | 61 const FloatPoint& p1, |
| 59 float r1, | 62 float r1, |
| 60 float aspectRatio) | 63 float aspectRatio, |
| 64 GradientSpreadMethod spreadMethod, |
| 65 ColorInterpolation interpolation) |
| 61 : m_p0(p0), | 66 : m_p0(p0), |
| 62 m_p1(p1), | 67 m_p1(p1), |
| 63 m_r0(r0), | 68 m_r0(r0), |
| 64 m_r1(r1), | 69 m_r1(r1), |
| 65 m_aspectRatio(aspectRatio), | 70 m_aspectRatio(aspectRatio), |
| 66 m_radial(true), | 71 m_radial(true), |
| 67 m_stopsSorted(false), | 72 m_stopsSorted(false), |
| 68 m_drawInPMColorSpace(false), | 73 m_spreadMethod(spreadMethod), |
| 69 m_spreadMethod(SpreadMethodPad) {} | 74 m_colorInterpolation(interpolation) {} |
| 70 | 75 |
| 71 Gradient::~Gradient() {} | 76 Gradient::~Gradient() {} |
| 72 | 77 |
| 73 static inline bool compareStops(const Gradient::ColorStop& a, | 78 static inline bool compareStops(const Gradient::ColorStop& a, |
| 74 const Gradient::ColorStop& b) { | 79 const Gradient::ColorStop& b) { |
| 75 return a.stop < b.stop; | 80 return a.stop < b.stop; |
| 76 } | 81 } |
| 77 | 82 |
| 78 void Gradient::addColorStop(const Gradient::ColorStop& stop) { | 83 void Gradient::addColorStop(const Gradient::ColorStop& stop) { |
| 79 if (m_stops.isEmpty()) { | 84 if (m_stops.isEmpty()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 96 return; | 101 return; |
| 97 | 102 |
| 98 m_stopsSorted = true; | 103 m_stopsSorted = true; |
| 99 | 104 |
| 100 if (!m_stops.size()) | 105 if (!m_stops.size()) |
| 101 return; | 106 return; |
| 102 | 107 |
| 103 std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); | 108 std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); |
| 104 } | 109 } |
| 105 | 110 |
| 106 void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod) { | |
| 107 // FIXME: Should it become necessary, allow calls to this method after | |
| 108 // |m_gradient| has been set. | |
| 109 DCHECK(!m_cachedShader); | |
| 110 | |
| 111 if (m_spreadMethod == spreadMethod) | |
| 112 return; | |
| 113 | |
| 114 m_spreadMethod = spreadMethod; | |
| 115 } | |
| 116 | |
| 117 void Gradient::setDrawsInPMColorSpace(bool drawInPMColorSpace) { | |
| 118 if (drawInPMColorSpace == m_drawInPMColorSpace) | |
| 119 return; | |
| 120 | |
| 121 m_drawInPMColorSpace = drawInPMColorSpace; | |
| 122 m_cachedShader.reset(); | |
| 123 } | |
| 124 | |
| 125 // Determine the total number of stops needed, including pseudo-stops at the | 111 // Determine the total number of stops needed, including pseudo-stops at the |
| 126 // ends as necessary. | 112 // ends as necessary. |
| 127 static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, | 113 static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, |
| 128 size_t count) { | 114 size_t count) { |
| 129 // N.B.: The tests in this function should kept in sync with the ones in | 115 // N.B.: The tests in this function should kept in sync with the ones in |
| 130 // fillStops(), or badness happens. | 116 // fillStops(), or badness happens. |
| 131 const Gradient::ColorStop* stop = stopData; | 117 const Gradient::ColorStop* stop = stopData; |
| 132 size_t countUsed = count; | 118 size_t countUsed = count; |
| 133 if (count < 1 || stop->stop > 0.0) | 119 if (count < 1 || stop->stop > 0.0) |
| 134 countUsed++; | 120 countUsed++; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 break; | 187 break; |
| 202 case SpreadMethodRepeat: | 188 case SpreadMethodRepeat: |
| 203 tile = SkShader::kRepeat_TileMode; | 189 tile = SkShader::kRepeat_TileMode; |
| 204 break; | 190 break; |
| 205 case SpreadMethodPad: | 191 case SpreadMethodPad: |
| 206 tile = SkShader::kClamp_TileMode; | 192 tile = SkShader::kClamp_TileMode; |
| 207 break; | 193 break; |
| 208 } | 194 } |
| 209 | 195 |
| 210 sk_sp<SkShader> shader; | 196 sk_sp<SkShader> shader; |
| 211 uint32_t shouldDrawInPMColorSpace = | 197 uint32_t flags = m_colorInterpolation == ColorInterpolation::Premultiplied |
| 212 m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag | 198 ? SkGradientShader::kInterpolateColorsInPremul_Flag |
| 213 : 0; | 199 : 0; |
| 214 if (m_radial) { | 200 if (m_radial) { |
| 215 SkMatrix adjustedLocalMatrix = localMatrix; | 201 SkMatrix adjustedLocalMatrix = localMatrix; |
| 216 | 202 |
| 217 if (m_aspectRatio != 1) { | 203 if (m_aspectRatio != 1) { |
| 218 // CSS3 elliptical gradients: apply the elliptical scaling at the | 204 // CSS3 elliptical gradients: apply the elliptical scaling at the |
| 219 // gradient center point. | 205 // gradient center point. |
| 220 adjustedLocalMatrix.preTranslate(m_p0.x(), m_p0.y()); | 206 adjustedLocalMatrix.preTranslate(m_p0.x(), m_p0.y()); |
| 221 adjustedLocalMatrix.preScale(1, 1 / m_aspectRatio); | 207 adjustedLocalMatrix.preScale(1, 1 / m_aspectRatio); |
| 222 adjustedLocalMatrix.preTranslate(-m_p0.x(), -m_p0.y()); | 208 adjustedLocalMatrix.preTranslate(-m_p0.x(), -m_p0.y()); |
| 223 ASSERT(m_p0 == m_p1); | 209 ASSERT(m_p0 == m_p1); |
| 224 } | 210 } |
| 225 | 211 |
| 226 // Since the two-point radial gradient is slower than the plain radial, | 212 // Since the two-point radial gradient is slower than the plain radial, |
| 227 // only use it if we have to. | 213 // only use it if we have to. |
| 228 if (m_p0 == m_p1 && m_r0 <= 0.0f) { | 214 if (m_p0 == m_p1 && m_r0 <= 0.0f) { |
| 229 shader = SkGradientShader::MakeRadial( | 215 shader = SkGradientShader::MakeRadial( |
| 230 m_p1.data(), m_r1, colors.data(), pos.data(), | 216 m_p1.data(), m_r1, colors.data(), pos.data(), |
| 231 static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, | 217 static_cast<int>(countUsed), tile, flags, &adjustedLocalMatrix); |
| 232 &adjustedLocalMatrix); | |
| 233 } else { | 218 } else { |
| 234 // The radii we give to Skia must be positive. If we're given a | 219 // The radii we give to Skia must be positive. If we're given a |
| 235 // negative radius, ask for zero instead. | 220 // negative radius, ask for zero instead. |
| 236 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; | 221 SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0; |
| 237 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; | 222 SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0; |
| 238 shader = SkGradientShader::MakeTwoPointConical( | 223 shader = SkGradientShader::MakeTwoPointConical( |
| 239 m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), | 224 m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), |
| 240 static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, | 225 static_cast<int>(countUsed), tile, flags, &adjustedLocalMatrix); |
| 241 &adjustedLocalMatrix); | |
| 242 } | 226 } |
| 243 } else { | 227 } else { |
| 244 SkPoint pts[2] = {m_p0.data(), m_p1.data()}; | 228 SkPoint pts[2] = {m_p0.data(), m_p1.data()}; |
| 245 shader = SkGradientShader::MakeLinear( | 229 shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), |
| 246 pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile, | 230 static_cast<int>(countUsed), tile, |
| 247 shouldDrawInPMColorSpace, &localMatrix); | 231 flags, &localMatrix); |
| 248 } | 232 } |
| 249 | 233 |
| 250 if (!shader) { | 234 if (!shader) { |
| 251 // use last color, since our "geometry" was degenerate (e.g. radius==0) | 235 // use last color, since our "geometry" was degenerate (e.g. radius==0) |
| 252 shader = SkShader::MakeColorShader(colors[countUsed - 1]); | 236 shader = SkShader::MakeColorShader(colors[countUsed - 1]); |
| 253 } | 237 } |
| 254 | 238 |
| 255 return WrapSkShader(shader); | 239 return WrapSkShader(shader); |
| 256 } | 240 } |
| 257 | 241 |
| 258 void Gradient::applyToFlags(PaintFlags& flags, const SkMatrix& localMatrix) { | 242 void Gradient::applyToFlags(PaintFlags& flags, const SkMatrix& localMatrix) { |
| 259 if (!m_cachedShader || localMatrix != m_cachedShader->getLocalMatrix()) | 243 if (!m_cachedShader || localMatrix != m_cachedShader->getLocalMatrix()) |
| 260 m_cachedShader = createShader(localMatrix); | 244 m_cachedShader = createShader(localMatrix); |
| 261 | 245 |
| 262 flags.setShader(m_cachedShader); | 246 flags.setShader(m_cachedShader); |
| 263 | 247 |
| 264 // Legacy behavior: gradients are always dithered. | 248 // Legacy behavior: gradients are always dithered. |
| 265 flags.setDither(true); | 249 flags.setDither(true); |
| 266 } | 250 } |
| 267 | 251 |
| 268 } // namespace blink | 252 } // namespace blink |
| OLD | NEW |