Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Typedefs | Enumerations | Functions
SkGradientBaseShader.cpp File Reference
#include "src/shaders/gradients/SkGradientBaseShader.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkShader.h"
#include "include/core/SkTileMode.h"
#include "include/private/SkColorData.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkArenaAlloc.h"
#include "src/base/SkFloatBits.h"
#include "src/base/SkVx.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkEffectPriv.h"
#include "src/core/SkPicturePriv.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkRasterPipelineOpContexts.h"
#include "src/core/SkRasterPipelineOpList.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"
#include <algorithm>
#include <cmath>
#include <optional>
#include <utility>

Go to the source code of this file.

Typedefs

using ConvertColorProc = SkPMColor4f(*)(SkPMColor4f, bool *)
 
using PremulColorProc = SkPMColor4f(*)(SkPMColor4f)
 

Enumerations

enum  GradientSerializationFlags {
  kHasPosition_GSF = 0x80000000 , kHasLegacyLocalMatrix_GSF = 0x40000000 , kHasColorSpace_GSF = 0x20000000 , kTileModeShift_GSF = 8 ,
  kTileModeMask_GSF = 0xF , kInterpolationColorSpaceShift_GSF = 4 , kInterpolationColorSpaceMask_GSF = 0xF , kInterpolationHueMethodShift_GSF = 1 ,
  kInterpolationHueMethodMask_GSF = 0x7 , kInterpolationInPremul_GSF = 0x1
}
 

Functions

template<int N, typename T , bool MEM_MOVE>
static bool validate_array (SkReadBuffer &buffer, size_t count, STArray< N, T, MEM_MOVE > *array)
 
static void add_stop_color (SkRasterPipeline_GradientCtx *ctx, size_t stop, SkPMColor4f Fs, SkPMColor4f Bs)
 
static void add_const_color (SkRasterPipeline_GradientCtx *ctx, size_t stop, SkPMColor4f color)
 
static void init_stop_evenly (SkRasterPipeline_GradientCtx *ctx, float gapCount, size_t stop, SkPMColor4f c_l, SkPMColor4f c_r)
 
static void init_stop_pos (SkRasterPipeline_GradientCtx *ctx, size_t stop, float t_l, float c_scale, SkPMColor4f c_l, SkPMColor4f c_r)
 
static sk_sp< SkColorSpaceintermediate_color_space (SkGradientShader::Interpolation::ColorSpace cs, SkColorSpace *dst)
 
static SkPMColor4f srgb_to_hsl (SkPMColor4f rgb, bool *hueIsPowerless)
 
static SkPMColor4f srgb_to_hwb (SkPMColor4f rgb, bool *hueIsPowerless)
 
static SkPMColor4f xyzd50_to_lab (SkPMColor4f xyz, bool *)
 
static SkPMColor4f xyzd50_to_hcl (SkPMColor4f xyz, bool *hueIsPowerless)
 
static SkPMColor4f lin_srgb_to_oklab (SkPMColor4f rgb, bool *)
 
static SkPMColor4f lin_srgb_to_okhcl (SkPMColor4f rgb, bool *hueIsPowerless)
 
static SkPMColor4f premul_polar (SkPMColor4f hsl)
 
static SkPMColor4f premul_rgb (SkPMColor4f rgb)
 
static bool color_space_is_polar (SkGradientShader::Interpolation::ColorSpace cs)
 
static SkColor4f average_gradient_color (const SkColor4f colors[], const SkScalar pos[], int colorCount)
 

Typedef Documentation

◆ ConvertColorProc

Definition at line 600 of file SkGradientBaseShader.cpp.

◆ PremulColorProc

Definition at line 601 of file SkGradientBaseShader.cpp.

Enumeration Type Documentation

◆ GradientSerializationFlags

Enumerator
kHasPosition_GSF 
kHasLegacyLocalMatrix_GSF 
kHasColorSpace_GSF 
kTileModeShift_GSF 
kTileModeMask_GSF 
kInterpolationColorSpaceShift_GSF 
kInterpolationColorSpaceMask_GSF 
kInterpolationHueMethodShift_GSF 
kInterpolationHueMethodMask_GSF 
kInterpolationInPremul_GSF 

Definition at line 45 of file SkGradientBaseShader.cpp.

45 {
46 // Bits 29:31 used for various boolean flags
47 kHasPosition_GSF = 0x80000000,
48 kHasLegacyLocalMatrix_GSF = 0x40000000,
49 kHasColorSpace_GSF = 0x20000000,
50
51 // Bits 12:28 unused
52
53 // Bits 8:11 for fTileMode
56
57 // Bits 4:7 for fInterpolation.fColorSpace
60
61 // Bits 1:3 for fInterpolation.fHueMethod
64
65 // Bit 0 for fInterpolation.fInPremul
67};
@ kHasColorSpace_GSF
@ kTileModeShift_GSF
@ kInterpolationColorSpaceMask_GSF
@ kHasLegacyLocalMatrix_GSF
@ kInterpolationColorSpaceShift_GSF
@ kInterpolationHueMethodShift_GSF
@ kHasPosition_GSF
@ kInterpolationInPremul_GSF
@ kInterpolationHueMethodMask_GSF
@ kTileModeMask_GSF

Function Documentation

◆ add_const_color()

static void add_const_color ( SkRasterPipeline_GradientCtx ctx,
size_t  stop,
SkPMColor4f  color 
)
static

Definition at line 272 of file SkGradientBaseShader.cpp.

272 {
273 add_stop_color(ctx, stop, {0, 0, 0, 0}, color);
274}
SkColor4f color
static void add_stop_color(SkRasterPipeline_GradientCtx *ctx, size_t stop, SkPMColor4f Fs, SkPMColor4f Bs)

◆ add_stop_color()

static void add_stop_color ( SkRasterPipeline_GradientCtx ctx,
size_t  stop,
SkPMColor4f  Fs,
SkPMColor4f  Bs 
)
static

Definition at line 257 of file SkGradientBaseShader.cpp.

260 {
261 (ctx->fs[0])[stop] = Fs.fR;
262 (ctx->fs[1])[stop] = Fs.fG;
263 (ctx->fs[2])[stop] = Fs.fB;
264 (ctx->fs[3])[stop] = Fs.fA;
265
266 (ctx->bs[0])[stop] = Bs.fR;
267 (ctx->bs[1])[stop] = Bs.fG;
268 (ctx->bs[2])[stop] = Bs.fB;
269 (ctx->bs[3])[stop] = Bs.fA;
270}
float fB
blue component
Definition SkColor.h:265
float fR
red component
Definition SkColor.h:263
float fG
green component
Definition SkColor.h:264
float fA
alpha component
Definition SkColor.h:266

◆ average_gradient_color()

static SkColor4f average_gradient_color ( const SkColor4f  colors[],
const SkScalar  pos[],
int  colorCount 
)
static

Definition at line 972 of file SkGradientBaseShader.cpp.

974 {
975 // The gradient is a piecewise linear interpolation between colors. For a given interval,
976 // the integral between the two endpoints is 0.5 * (ci + cj) * (pj - pi), which provides that
977 // intervals average color. The overall average color is thus the sum of each piece. The thing
978 // to keep in mind is that the provided gradient definition may implicitly use p=0 and p=1.
979 skvx::float4 blend(0.0f);
980 for (int i = 0; i < colorCount - 1; ++i) {
981 // Calculate the average color for the interval between pos(i) and pos(i+1)
982 auto c0 = skvx::float4::Load(&colors[i]);
983 auto c1 = skvx::float4::Load(&colors[i + 1]);
984
985 // when pos == null, there are colorCount uniformly distributed stops, going from 0 to 1,
986 // so pos[i + 1] - pos[i] = 1/(colorCount-1)
987 SkScalar w;
988 if (pos) {
989 // Match position fixing in SkGradientShader's constructor, clamping positions outside
990 // [0, 1] and forcing the sequence to be monotonic
991 SkScalar p0 = SkTPin(pos[i], 0.f, 1.f);
992 SkScalar p1 = SkTPin(pos[i + 1], p0, 1.f);
993 w = p1 - p0;
994
995 // And account for any implicit intervals at the start or end of the positions
996 if (i == 0) {
997 if (p0 > 0.0f) {
998 // The first color is fixed between p = 0 to pos[0], so 0.5*(ci + cj)*(pj - pi)
999 // becomes 0.5*(c + c)*(pj - 0) = c * pj
1000 auto c = skvx::float4::Load(&colors[0]);
1001 blend += p0 * c;
1002 }
1003 }
1004 if (i == colorCount - 2) {
1005 if (p1 < 1.f) {
1006 // The last color is fixed between pos[n-1] to p = 1, so 0.5*(ci + cj)*(pj - pi)
1007 // becomes 0.5*(c + c)*(1 - pi) = c * (1 - pi)
1008 auto c = skvx::float4::Load(&colors[colorCount - 1]);
1009 blend += (1.f - p1) * c;
1010 }
1011 }
1012 } else {
1013 w = 1.f / (colorCount - 1);
1014 }
1015
1016 blend += 0.5f * w * (c1 + c0);
1017 }
1018
1019 SkColor4f avg;
1020 blend.store(&avg);
1021 return avg;
1022}
SkPoint pos
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
float SkScalar
Definition extension.cpp:12
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
Definition hsl.cpp:142
SkScalar w
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition SkVx.h:109

◆ color_space_is_polar()

static bool color_space_is_polar ( SkGradientShader::Interpolation::ColorSpace  cs)
static

Definition at line 699 of file SkGradientBaseShader.cpp.

699 {
701 switch (cs) {
702 case ColorSpace::kLCH:
703 case ColorSpace::kOKLCH:
704 case ColorSpace::kHSL:
705 case ColorSpace::kHWB:
706 return true;
707 default:
708 return false;
709 }
710}
ColorSpace
Definition image.h:16

◆ init_stop_evenly()

static void init_stop_evenly ( SkRasterPipeline_GradientCtx ctx,
float  gapCount,
size_t  stop,
SkPMColor4f  c_l,
SkPMColor4f  c_r 
)
static

Definition at line 278 of file SkGradientBaseShader.cpp.

282 {
283 // Clankium's GCC 4.9 targeting ARMv7 is barfing when we use Sk4f math here, so go scalar...
284 SkPMColor4f Fs = {
285 (c_r.fR - c_l.fR) * gapCount,
286 (c_r.fG - c_l.fG) * gapCount,
287 (c_r.fB - c_l.fB) * gapCount,
288 (c_r.fA - c_l.fA) * gapCount,
289 };
290 SkPMColor4f Bs = {
291 c_l.fR - Fs.fR * (stop / gapCount),
292 c_l.fG - Fs.fG * (stop / gapCount),
293 c_l.fB - Fs.fB * (stop / gapCount),
294 c_l.fA - Fs.fA * (stop / gapCount),
295 };
296 add_stop_color(ctx, stop, Fs, Bs);
297}

◆ init_stop_pos()

static void init_stop_pos ( SkRasterPipeline_GradientCtx ctx,
size_t  stop,
float  t_l,
float  c_scale,
SkPMColor4f  c_l,
SkPMColor4f  c_r 
)
static

Definition at line 301 of file SkGradientBaseShader.cpp.

306 {
307 // See note about Clankium's old compiler in init_stop_evenly().
308 SkPMColor4f Fs = {
309 (c_r.fR - c_l.fR) * c_scale,
310 (c_r.fG - c_l.fG) * c_scale,
311 (c_r.fB - c_l.fB) * c_scale,
312 (c_r.fA - c_l.fA) * c_scale,
313 };
314 SkPMColor4f Bs = {
315 c_l.fR - Fs.fR * t_l,
316 c_l.fG - Fs.fG * t_l,
317 c_l.fB - Fs.fB * t_l,
318 c_l.fA - Fs.fA * t_l,
319 };
320 ctx->ts[stop] = t_l;
321 add_stop_color(ctx, stop, Fs, Bs);
322}
float c_scale

◆ intermediate_color_space()

static sk_sp< SkColorSpace > intermediate_color_space ( SkGradientShader::Interpolation::ColorSpace  cs,
SkColorSpace dst 
)
static

Definition at line 563 of file SkGradientBaseShader.cpp.

564 {
566 switch (cs) {
567 case ColorSpace::kDestination:
568 return sk_ref_sp(dst);
569
570 // css-color-4 allows XYZD50 and XYZD65. For gradients, those are redundant. Interpolating
571 // in any linear RGB space, (regardless of white point), gives the same answer.
572 case ColorSpace::kSRGBLinear:
574
575 case ColorSpace::kSRGB:
576 case ColorSpace::kHSL:
577 case ColorSpace::kHWB:
578 return SkColorSpace::MakeSRGB();
579
580 case ColorSpace::kLab:
581 case ColorSpace::kLCH:
582 // Conversion to Lab (and LCH) starts with XYZD50
584
585 case ColorSpace::kOKLab:
586 case ColorSpace::kOKLabGamutMap:
587 case ColorSpace::kOKLCH:
588 case ColorSpace::kOKLCHGamutMap:
589 // The "standard" conversion to these spaces starts with XYZD65. That requires extra
590 // effort to conjure. The author also has reference code for going directly from linear
591 // sRGB, so we use that.
592 // TODO(skia:13108): Even better would be to have an LMS color space, because the first
593 // part of the conversion is a matrix multiply, which could be absorbed into the
594 // color space xform.
596 }
598}
#define SkUNREACHABLE
Definition SkAssert.h:135
sk_sp< T > sk_ref_sp(T *obj)
Definition SkRefCnt.h:381
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
static sk_sp< SkColorSpace > MakeSRGBLinear()
static constexpr skcms_Matrix3x3 kXYZ
static constexpr skcms_TransferFunction kLinear

◆ lin_srgb_to_okhcl()

static SkPMColor4f lin_srgb_to_okhcl ( SkPMColor4f  rgb,
bool *  hueIsPowerless 
)
static

Definition at line 679 of file SkGradientBaseShader.cpp.

679 {
680 SkPMColor4f OKLab = lin_srgb_to_oklab(rgb, hueIsPowerless);
681 float hue = sk_float_radians_to_degrees(atan2f(OKLab[2], OKLab[1]));
682 float chroma = sqrtf(OKLab[1] * OKLab[1] + OKLab[2] * OKLab[2]);
683 // The OKLCH math produces very small chroma values for achromatic colors:
684 constexpr float kMaxChromaForPowerlessHue = 1e-6f;
685 if (chroma <= kMaxChromaForPowerlessHue) {
686 *hueIsPowerless = true;
687 }
688 return {hue >= 0 ? hue : hue + 360, chroma, OKLab[0], rgb.fA};
689}
static constexpr float sk_float_radians_to_degrees(float radians)
static SkPMColor4f lin_srgb_to_oklab(SkPMColor4f rgb, bool *)
static void hue(float dr, float dg, float db, float *sr, float *sg, float *sb)
Definition hsl.cpp:92

◆ lin_srgb_to_oklab()

static SkPMColor4f lin_srgb_to_oklab ( SkPMColor4f  rgb,
bool *   
)
static

Definition at line 664 of file SkGradientBaseShader.cpp.

664 {
665 float l = 0.4122214708f * rgb.fR + 0.5363325363f * rgb.fG + 0.0514459929f * rgb.fB;
666 float m = 0.2119034982f * rgb.fR + 0.6806995451f * rgb.fG + 0.1073969566f * rgb.fB;
667 float s = 0.0883024619f * rgb.fR + 0.2817188376f * rgb.fG + 0.6299787005f * rgb.fB;
668 l = std::cbrtf(l);
669 m = std::cbrtf(m);
670 s = std::cbrtf(s);
671 return {0.2104542553f * l + 0.7936177850f * m - 0.0040720468f * s,
672 1.9779984951f * l - 2.4285922050f * m + 0.4505937099f * s,
673 0.0259040371f * l + 0.7827717662f * m - 0.8086757660f * s,
674 rgb.fA};
675}
struct MyStruct s

◆ premul_polar()

static SkPMColor4f premul_polar ( SkPMColor4f  hsl)
static

Definition at line 691 of file SkGradientBaseShader.cpp.

691 {
692 return {hsl.fR, hsl.fG * hsl.fA, hsl.fB * hsl.fA, hsl.fA};
693}

◆ premul_rgb()

static SkPMColor4f premul_rgb ( SkPMColor4f  rgb)
static

Definition at line 695 of file SkGradientBaseShader.cpp.

695 {
696 return {rgb.fR * rgb.fA, rgb.fG * rgb.fA, rgb.fB * rgb.fA, rgb.fA};
697}

◆ srgb_to_hsl()

static SkPMColor4f srgb_to_hsl ( SkPMColor4f  rgb,
bool *  hueIsPowerless 
)
static

Definition at line 603 of file SkGradientBaseShader.cpp.

603 {
604 float mx = std::max({rgb.fR, rgb.fG, rgb.fB});
605 float mn = std::min({rgb.fR, rgb.fG, rgb.fB});
606 float hue = 0, sat = 0, light = (mn + mx) / 2;
607 float d = mx - mn;
608
609 if (d != 0) {
610 sat = (light == 0 || light == 1) ? 0 : (mx - light) / std::min(light, 1 - light);
611 if (mx == rgb.fR) {
612 hue = (rgb.fG - rgb.fB) / d + (rgb.fG < rgb.fB ? 6 : 0);
613 } else if (mx == rgb.fG) {
614 hue = (rgb.fB - rgb.fR) / d + 2;
615 } else {
616 hue = (rgb.fR - rgb.fG) / d + 4;
617 }
618
619 hue *= 60;
620 }
621 if (sat == 0) {
622 *hueIsPowerless = true;
623 }
624 return {hue, sat * 100, light * 100, rgb.fA};
625}
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static float sat(float r, float g, float b)
Definition hsl.cpp:51
static float min(float r, float g, float b)
Definition hsl.cpp:48
Definition ref_ptr.h:256

◆ srgb_to_hwb()

static SkPMColor4f srgb_to_hwb ( SkPMColor4f  rgb,
bool *  hueIsPowerless 
)
static

Definition at line 627 of file SkGradientBaseShader.cpp.

627 {
628 SkPMColor4f hsl = srgb_to_hsl(rgb, hueIsPowerless);
629 float white = std::min({rgb.fR, rgb.fG, rgb.fB});
630 float black = 1 - std::max({rgb.fR, rgb.fG, rgb.fB});
631 return {hsl.fR, white * 100, black * 100, rgb.fA};
632}
static SkPMColor4f srgb_to_hsl(SkPMColor4f rgb, bool *hueIsPowerless)

◆ validate_array()

template<int N, typename T , bool MEM_MOVE>
static bool validate_array ( SkReadBuffer buffer,
size_t  count,
STArray< N, T, MEM_MOVE > *  array 
)
static

Definition at line 121 of file SkGradientBaseShader.cpp.

121 {
122 if (!buffer.validateCanReadN<T>(count)) {
123 return false;
124 }
125
126 array->resize_back(count);
127 return true;
128}
int count
void resize_back(int newCount)
Definition SkTArray.h:338
static const uint8_t buffer[]

◆ xyzd50_to_hcl()

static SkPMColor4f xyzd50_to_hcl ( SkPMColor4f  xyz,
bool *  hueIsPowerless 
)
static

Definition at line 651 of file SkGradientBaseShader.cpp.

651 {
652 SkPMColor4f Lab = xyzd50_to_lab(xyz, hueIsPowerless);
653 float hue = sk_float_radians_to_degrees(atan2f(Lab[2], Lab[1]));
654 float chroma = sqrtf(Lab[1] * Lab[1] + Lab[2] * Lab[2]);
655 // The LCH math produces small-ish (but not tiny) chroma values for achromatic colors:
656 constexpr float kMaxChromaForPowerlessHue = 1e-2f;
657 if (chroma <= kMaxChromaForPowerlessHue) {
658 *hueIsPowerless = true;
659 }
660 return {hue >= 0 ? hue : hue + 360, chroma, Lab[0], xyz.fA};
661}
static SkPMColor4f xyzd50_to_lab(SkPMColor4f xyz, bool *)

◆ xyzd50_to_lab()

static SkPMColor4f xyzd50_to_lab ( SkPMColor4f  xyz,
bool *   
)
static

Definition at line 634 of file SkGradientBaseShader.cpp.

634 {
635 constexpr float D50[3] = {0.3457f / 0.3585f, 1.0f, (1.0f - 0.3457f - 0.3585f) / 0.3585f};
636
637 constexpr float e = 216.0f / 24389;
638 constexpr float k = 24389.0f / 27;
639
641 for (int i = 0; i < 3; ++i) {
642 float v = xyz[i] / D50[i];
643 f[i] = (v > e) ? std::cbrtf(v) : (k * v + 16) / 116;
644 }
645
646 return {(116 * f[1]) - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2]), xyz.fA};
647}