Flutter Engine
The Flutter Engine
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 648 of file SkGradientBaseShader.cpp.

◆ PremulColorProc

Definition at line 649 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 320 of file SkGradientBaseShader.cpp.

320 {
321 add_stop_color(ctx, stop, {0, 0, 0, 0}, color);
322}
static void add_stop_color(SkRasterPipeline_GradientCtx *ctx, size_t stop, SkPMColor4f Fs, SkPMColor4f Bs)
DlColor color

◆ add_stop_color()

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

Definition at line 305 of file SkGradientBaseShader.cpp.

308 {
309 (ctx->fs[0])[stop] = Fs.fR;
310 (ctx->fs[1])[stop] = Fs.fG;
311 (ctx->fs[2])[stop] = Fs.fB;
312 (ctx->fs[3])[stop] = Fs.fA;
313
314 (ctx->bs[0])[stop] = Bs.fR;
315 (ctx->bs[1])[stop] = Bs.fG;
316 (ctx->bs[2])[stop] = Bs.fB;
317 (ctx->bs[3])[stop] = Bs.fA;
318}
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 1020 of file SkGradientBaseShader.cpp.

1022 {
1023 // The gradient is a piecewise linear interpolation between colors. For a given interval,
1024 // the integral between the two endpoints is 0.5 * (ci + cj) * (pj - pi), which provides that
1025 // intervals average color. The overall average color is thus the sum of each piece. The thing
1026 // to keep in mind is that the provided gradient definition may implicitly use p=0 and p=1.
1027 skvx::float4 blend(0.0f);
1028 for (int i = 0; i < colorCount - 1; ++i) {
1029 // Calculate the average color for the interval between pos(i) and pos(i+1)
1030 auto c0 = skvx::float4::Load(&colors[i]);
1031 auto c1 = skvx::float4::Load(&colors[i + 1]);
1032
1033 // when pos == null, there are colorCount uniformly distributed stops, going from 0 to 1,
1034 // so pos[i + 1] - pos[i] = 1/(colorCount-1)
1035 SkScalar w;
1036 if (pos) {
1037 // Match position fixing in SkGradientShader's constructor, clamping positions outside
1038 // [0, 1] and forcing the sequence to be monotonic
1039 SkScalar p0 = SkTPin(pos[i], 0.f, 1.f);
1040 SkScalar p1 = SkTPin(pos[i + 1], p0, 1.f);
1041 w = p1 - p0;
1042
1043 // And account for any implicit intervals at the start or end of the positions
1044 if (i == 0) {
1045 if (p0 > 0.0f) {
1046 // The first color is fixed between p = 0 to pos[0], so 0.5*(ci + cj)*(pj - pi)
1047 // becomes 0.5*(c + c)*(pj - 0) = c * pj
1048 auto c = skvx::float4::Load(&colors[0]);
1049 blend += p0 * c;
1050 }
1051 }
1052 if (i == colorCount - 2) {
1053 if (p1 < 1.f) {
1054 // The last color is fixed between pos[n-1] to p = 1, so 0.5*(ci + cj)*(pj - pi)
1055 // becomes 0.5*(c + c)*(1 - pi) = c * (1 - pi)
1056 auto c = skvx::float4::Load(&colors[colorCount - 1]);
1057 blend += (1.f - p1) * c;
1058 }
1059 }
1060 } else {
1061 w = 1.f / (colorCount - 1);
1062 }
1063
1064 blend += 0.5f * w * (c1 + c0);
1065 }
1066
1067 SkColor4f avg;
1068 blend.store(&avg);
1069 return avg;
1070}
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
PODArray< SkColor > colors
Definition: SkRecords.h:276
SkScalar w
Definition: SkVx.h:83
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 747 of file SkGradientBaseShader.cpp.

747 {
749 switch (cs) {
750 case ColorSpace::kLCH:
751 case ColorSpace::kOKLCH:
752 case ColorSpace::kHSL:
753 case ColorSpace::kHWB:
754 return true;
755 default:
756 return false;
757 }
758}
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 326 of file SkGradientBaseShader.cpp.

330 {
331 // Clankium's GCC 4.9 targeting ARMv7 is barfing when we use Sk4f math here, so go scalar...
332 SkPMColor4f Fs = {
333 (c_r.fR - c_l.fR) * gapCount,
334 (c_r.fG - c_l.fG) * gapCount,
335 (c_r.fB - c_l.fB) * gapCount,
336 (c_r.fA - c_l.fA) * gapCount,
337 };
338 SkPMColor4f Bs = {
339 c_l.fR - Fs.fR * (stop / gapCount),
340 c_l.fG - Fs.fG * (stop / gapCount),
341 c_l.fB - Fs.fB * (stop / gapCount),
342 c_l.fA - Fs.fA * (stop / gapCount),
343 };
344 add_stop_color(ctx, stop, Fs, Bs);
345}

◆ 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 349 of file SkGradientBaseShader.cpp.

354 {
355 // See note about Clankium's old compiler in init_stop_evenly().
356 SkPMColor4f Fs = {
357 (c_r.fR - c_l.fR) * c_scale,
358 (c_r.fG - c_l.fG) * c_scale,
359 (c_r.fB - c_l.fB) * c_scale,
360 (c_r.fA - c_l.fA) * c_scale,
361 };
362 SkPMColor4f Bs = {
363 c_l.fR - Fs.fR * t_l,
364 c_l.fG - Fs.fG * t_l,
365 c_l.fB - Fs.fB * t_l,
366 c_l.fA - Fs.fA * t_l,
367 };
368 ctx->ts[stop] = t_l;
369 add_stop_color(ctx, stop, Fs, Bs);
370}
float c_scale

◆ intermediate_color_space()

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

Definition at line 611 of file SkGradientBaseShader.cpp.

612 {
614 switch (cs) {
615 case ColorSpace::kDestination:
616 return sk_ref_sp(dst);
617
618 // css-color-4 allows XYZD50 and XYZD65. For gradients, those are redundant. Interpolating
619 // in any linear RGB space, (regardless of white point), gives the same answer.
620 case ColorSpace::kSRGBLinear:
622
623 case ColorSpace::kSRGB:
624 case ColorSpace::kHSL:
625 case ColorSpace::kHWB:
626 return SkColorSpace::MakeSRGB();
627
628 case ColorSpace::kLab:
629 case ColorSpace::kLCH:
630 // Conversion to Lab (and LCH) starts with XYZD50
632
633 case ColorSpace::kOKLab:
634 case ColorSpace::kOKLabGamutMap:
635 case ColorSpace::kOKLCH:
636 case ColorSpace::kOKLCHGamutMap:
637 // The "standard" conversion to these spaces starts with XYZD65. That requires extra
638 // effort to conjure. The author also has reference code for going directly from linear
639 // sRGB, so we use that.
640 // TODO(skia:13108): Even better would be to have an LMS color space, because the first
641 // part of the conversion is a matrix multiply, which could be absorbed into the
642 // color space xform.
644 }
646}
#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
Definition: SkColorSpace.h:99
static constexpr skcms_TransferFunction kLinear
Definition: SkColorSpace.h:51
dst
Definition: cp.py:12

◆ lin_srgb_to_okhcl()

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

Definition at line 727 of file SkGradientBaseShader.cpp.

727 {
728 SkPMColor4f OKLab = lin_srgb_to_oklab(rgb, hueIsPowerless);
729 float hue = sk_float_radians_to_degrees(atan2f(OKLab[2], OKLab[1]));
730 float chroma = sqrtf(OKLab[1] * OKLab[1] + OKLab[2] * OKLab[2]);
731 // The OKLCH math produces very small chroma values for achromatic colors:
732 constexpr float kMaxChromaForPowerlessHue = 1e-6f;
733 if (chroma <= kMaxChromaForPowerlessHue) {
734 *hueIsPowerless = true;
735 }
736 return {hue >= 0 ? hue : hue + 360, chroma, OKLab[0], rgb.fA};
737}
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 712 of file SkGradientBaseShader.cpp.

712 {
713 float l = 0.4122214708f * rgb.fR + 0.5363325363f * rgb.fG + 0.0514459929f * rgb.fB;
714 float m = 0.2119034982f * rgb.fR + 0.6806995451f * rgb.fG + 0.1073969566f * rgb.fB;
715 float s = 0.0883024619f * rgb.fR + 0.2817188376f * rgb.fG + 0.6299787005f * rgb.fB;
716 l = std::cbrtf(l);
717 m = std::cbrtf(m);
718 s = std::cbrtf(s);
719 return {0.2104542553f * l + 0.7936177850f * m - 0.0040720468f * s,
720 1.9779984951f * l - 2.4285922050f * m + 0.4505937099f * s,
721 0.0259040371f * l + 0.7827717662f * m - 0.8086757660f * s,
722 rgb.fA};
723}
struct MyStruct s

◆ premul_polar()

static SkPMColor4f premul_polar ( SkPMColor4f  hsl)
static

Definition at line 739 of file SkGradientBaseShader.cpp.

739 {
740 return {hsl.fR, hsl.fG * hsl.fA, hsl.fB * hsl.fA, hsl.fA};
741}

◆ premul_rgb()

static SkPMColor4f premul_rgb ( SkPMColor4f  rgb)
static

Definition at line 743 of file SkGradientBaseShader.cpp.

743 {
744 return {rgb.fR * rgb.fA, rgb.fG * rgb.fA, rgb.fB * rgb.fA, rgb.fA};
745}

◆ srgb_to_hsl()

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

Definition at line 651 of file SkGradientBaseShader.cpp.

651 {
652 float mx = std::max({rgb.fR, rgb.fG, rgb.fB});
653 float mn = std::min({rgb.fR, rgb.fG, rgb.fB});
654 float hue = 0, sat = 0, light = (mn + mx) / 2;
655 float d = mx - mn;
656
657 if (d != 0) {
658 sat = (light == 0 || light == 1) ? 0 : (mx - light) / std::min(light, 1 - light);
659 if (mx == rgb.fR) {
660 hue = (rgb.fG - rgb.fB) / d + (rgb.fG < rgb.fB ? 6 : 0);
661 } else if (mx == rgb.fG) {
662 hue = (rgb.fB - rgb.fR) / d + 2;
663 } else {
664 hue = (rgb.fR - rgb.fG) / d + 4;
665 }
666
667 hue *= 60;
668 }
669 if (sat == 0) {
670 *hueIsPowerless = true;
671 }
672 return {hue, sat * 100, light * 100, rgb.fA};
673}
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 max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48

◆ srgb_to_hwb()

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

Definition at line 675 of file SkGradientBaseShader.cpp.

675 {
676 SkPMColor4f hsl = srgb_to_hsl(rgb, hueIsPowerless);
677 float white = std::min({rgb.fR, rgb.fG, rgb.fB});
678 float black = 1 - std::max({rgb.fR, rgb.fG, rgb.fB});
679 return {hsl.fR, white * 100, black * 100, rgb.fA};
680}
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
Definition: FontMgrTest.cpp:50
void resize_back(int newCount)
Definition: SkTArray.h:343
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define T
Definition: precompiler.cc:65

◆ xyzd50_to_hcl()

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

Definition at line 699 of file SkGradientBaseShader.cpp.

699 {
700 SkPMColor4f Lab = xyzd50_to_lab(xyz, hueIsPowerless);
701 float hue = sk_float_radians_to_degrees(atan2f(Lab[2], Lab[1]));
702 float chroma = sqrtf(Lab[1] * Lab[1] + Lab[2] * Lab[2]);
703 // The LCH math produces small-ish (but not tiny) chroma values for achromatic colors:
704 constexpr float kMaxChromaForPowerlessHue = 1e-2f;
705 if (chroma <= kMaxChromaForPowerlessHue) {
706 *hueIsPowerless = true;
707 }
708 return {hue >= 0 ? hue : hue + 360, chroma, Lab[0], xyz.fA};
709}
static SkPMColor4f xyzd50_to_lab(SkPMColor4f xyz, bool *)

◆ xyzd50_to_lab()

static SkPMColor4f xyzd50_to_lab ( SkPMColor4f  xyz,
bool *   
)
static

Definition at line 682 of file SkGradientBaseShader.cpp.

682 {
683 constexpr float D50[3] = {0.3457f / 0.3585f, 1.0f, (1.0f - 0.3457f - 0.3585f) / 0.3585f};
684
685 constexpr float e = 216.0f / 24389;
686 constexpr float k = 24389.0f / 27;
687
689 for (int i = 0; i < 3; ++i) {
690 float v = xyz[i] / D50[i];
691 f[i] = (v > e) ? std::cbrtf(v) : (k * v + 16) / 116;
692 }
693
694 return {(116 * f[1]) - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2]), xyz.fA};
695}