| /* |
| * Copyright 2025 Google LLC. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkGradient_DEFINED |
| #define SkGradient_DEFINED |
| |
| #include "include/core/SkColor.h" |
| #include "include/core/SkColorSpace.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkShader.h" |
| #include "include/core/SkSpan.h" |
| #include "include/core/SkTileMode.h" |
| #include "include/private/base/SkAPI.h" |
| |
| class SkMatrix; |
| |
| class SkGradient { |
| public: |
| struct Interpolation { |
| enum class InPremul : bool { kNo = false, kYes = true }; |
| |
| enum class ColorSpace : uint8_t { |
| // Default Skia behavior: interpolate in the color space of the destination surface |
| kDestination, |
| |
| // https://www.w3.org/TR/css-color-4/#interpolation-space |
| kSRGBLinear, |
| kLab, |
| kOKLab, |
| // This is the same as kOKLab, except it has a simplified version of the CSS gamut |
| // mapping algorithm (https://www.w3.org/TR/css-color-4/#css-gamut-mapping) |
| // into Rec2020 space applied to it. |
| // Warning: This space is experimental and should not be used in production. |
| kOKLabGamutMap, |
| kLCH, |
| kOKLCH, |
| // This is the same as kOKLCH, except it has the same gamut mapping applied to it |
| // as kOKLabGamutMap does. |
| // Warning: This space is experimental and should not be used in production. |
| kOKLCHGamutMap, |
| kSRGB, |
| kHSL, |
| kHWB, |
| |
| kDisplayP3, |
| kRec2020, |
| kProphotoRGB, |
| kA98RGB, |
| |
| kLastColorSpace = kA98RGB, |
| }; |
| static constexpr int kColorSpaceCount = static_cast<int>(ColorSpace::kLastColorSpace) + 1; |
| |
| enum class HueMethod : uint8_t { |
| // https://www.w3.org/TR/css-color-4/#hue-interpolation |
| kShorter, |
| kLonger, |
| kIncreasing, |
| kDecreasing, |
| |
| kLastHueMethod = kDecreasing, |
| }; |
| static constexpr int kHueMethodCount = static_cast<int>(HueMethod::kLastHueMethod) + 1; |
| |
| InPremul fInPremul = InPremul::kNo; |
| ColorSpace fColorSpace = ColorSpace::kDestination; |
| HueMethod fHueMethod = HueMethod::kShorter; // Only relevant for LCH, OKLCH, HSL, or HWB |
| |
| // legacy compatibility -- remove when we can |
| static Interpolation FromFlags(uint32_t flags) { |
| return {flags & 1 ? InPremul::kYes : InPremul::kNo, |
| ColorSpace::kDestination, |
| HueMethod::kShorter}; |
| } |
| }; |
| |
| /** |
| * Specification for the colors in a gradient. |
| * |
| * @param colors The span of colors for the gradient. |
| * @param pos Relative positions of each color across the gradient. If empty, |
| * the the colors are distributed evenly. If this is not null, the values |
| * must lie between 0.0 and 1.0, and be strictly increasing. If the first |
| * value is not 0.0, then an additional color stop is added at position 0.0, |
| * with the same color as colors[0]. If the the last value is less than 1.0, |
| * then an additional color stop is added at position 1.0, with the same color |
| * as colors[count - 1]. |
| * @param mode Tiling mode for the gradient. |
| * @param cs Optional colorspace associated with the span of colors. If this is null, |
| * the colors are treated as sRGB. |
| */ |
| class Colors { |
| public: |
| Colors() {} |
| Colors(SkSpan<const SkColor4f> colors, |
| SkSpan<const float> pos, |
| SkTileMode mode, |
| sk_sp<SkColorSpace> cs = nullptr) |
| : fColors(colors), fPos(pos), fColorSpace(std::move(cs)), fTileMode(mode) { |
| SkASSERT(fPos.size() == 0 || fPos.size() == fColors.size()); |
| |
| // throw away inconsistent inputs |
| if (fPos.size() != fColors.size()) { |
| fPos = {}; |
| } |
| } |
| |
| Colors(SkSpan<const SkColor4f> colors, SkTileMode tm, sk_sp<SkColorSpace> cs = nullptr) |
| : Colors(colors, {}, tm, std::move(cs)) {} |
| |
| SkSpan<const SkColor4f> colors() const { return fColors; } |
| SkSpan<const float> positions() const { return fPos; } |
| const sk_sp<SkColorSpace>& colorSpace() const { return fColorSpace; } |
| SkTileMode tileMode() const { return fTileMode; } |
| |
| private: |
| SkSpan<const SkColor4f> fColors; |
| SkSpan<const float> fPos; |
| sk_sp<SkColorSpace> fColorSpace; |
| SkTileMode fTileMode = SkTileMode::kClamp; |
| }; |
| |
| SkGradient() {} |
| SkGradient(const Colors& colors, const Interpolation& interp) |
| : fColors(colors), fInterpolation(interp) {} |
| |
| const Colors& colors() const { return fColors; } |
| const Interpolation& interpolation() const { return fInterpolation; } |
| |
| private: |
| Colors fColors; |
| Interpolation fInterpolation; |
| }; |
| |
| namespace SkShaders { |
| /** Returns a shader that generates a linear gradient between the two specified points. |
| * If the inputs are invalid, this will return nullptr. |
| * @param points Array of 2 points, the end-points of the line segment |
| * @param grad Description of the colors and interpolation method |
| * @param lm Optional local matrix, may be null |
| */ |
| SK_API sk_sp<SkShader> LinearGradient(const SkPoint pts[2], |
| const SkGradient&, |
| const SkMatrix* lm = nullptr); |
| |
| /** Returns a shader that generates a radial gradient given the center and radius. |
| * @param center The center of the circle for this gradient |
| * @param radius Must be positive. The radius of the circle for this gradient |
| * @param grad Description of the colors and interpolation method |
| * @param lm Optional local matrix, may be null |
| */ |
| SK_API sk_sp<SkShader> RadialGradient(SkPoint center, |
| float radius, |
| const SkGradient& grad, |
| const SkMatrix* lm = nullptr); |
| |
| /** Returns a shader that generates a conical gradient given two circles, or |
| * returns null if the inputs are invalid. The gradient interprets the |
| * two circles according to the following HTML spec. |
| * http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient |
| * @param start The center of the circle for this gradient |
| * @param startRadius Must be positive. The radius of the circle for this gradient |
| * @param end The center of the circle for this gradient |
| * @param startRadius Must be positive. The radius of the circle for this gradient |
| * @param grad Description of the colors and interpolation method |
| * @param lm Optional local matrix, may be null |
| */ |
| SK_API sk_sp<SkShader> TwoPointConicalGradient(SkPoint start, |
| float startRadius, |
| SkPoint end, |
| float endRadius, |
| const SkGradient& grad, |
| const SkMatrix* lm = nullptr); |
| |
| /** Returns a shader that generates a sweep gradient given a center. |
| * The shader accepts negative angles and angles larger than 360, draws |
| * between 0 and 360 degrees, similar to the CSS conic-gradient |
| * semantics. 0 degrees means horizontal positive x axis. The start angle |
| * must be less than the end angle, otherwise a null pointer is |
| * returned. If color stops do not contain 0 and 1 but are within this |
| * range, the respective outer color stop is repeated for 0 and 1. Color |
| * stops less than 0 are clamped to 0, and greater than 1 are clamped to 1. |
| * @param center The center of the sweep |
| * @param startAngle Start of the angular range, corresponding to pos == 0. |
| * @param endAngle End of the angular range, corresponding to pos == 1. |
| * @param grad Description of the colors and interpolation method |
| * @param lm Optional local matrix, may be null |
| */ |
| SK_API sk_sp<SkShader> SweepGradient(SkPoint center, |
| float startAngle, |
| float endAngle, |
| const SkGradient&, |
| const SkMatrix* lm = nullptr); |
| static inline sk_sp<SkShader> SweepGradient(SkPoint center, |
| const SkGradient& grad, |
| const SkMatrix* lm = nullptr) { |
| return SweepGradient(center, 0, 360, grad, lm); |
| } |
| |
| } // namespace SkShaders |
| |
| #endif |