207 lines
8.6 KiB
C++
207 lines
8.6 KiB
C++
/*
|
|
* 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
|