112 if (colorSpaceData) {
113 buffer.writeDataAsByteArray(colorSpaceData.
get());
116 buffer.writeScalarArray(positions, colorCount);
120template <
int N,
typename T,
bool MEM_MOVE>
150 fColors = fColorStorage.begin();
168 SkASSERT(
buffer.isVersionLT(SkPicturePriv::Version::kNoShaderLocalMatrix));
169 buffer.readMatrix(legacyLocalMatrix);
183 , fColorsAreOpaque(
true) {
206 if (
desc.fPositions) {
222 for (
int i = 0;
i <
desc.fColorCount; ++
i) {
224 fColorsAreOpaque = fColorsAreOpaque && (
desc.fColors[
i].fA == 1);
231 if (
desc.fPositions) {
239 bool uniformStops =
true;
241 for (
int i = startIndex;
i <
count;
i++) {
244 if (
i !=
desc.fColorCount) {
256 *positions++ =
prev = curr;
269 int dedupedColorCount = 0;
274 bool dupStop = j -
i > 1;
280 if (!ignoreLeftmost) {
290 if (dupStop && !ignoreRightmost) {
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;
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;
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,
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),
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,
378 if (
count == 2 && positions ==
nullptr) {
379 const SkPMColor4f c_l = pmColors[0], c_r = pmColors[1];
386 p->append(SkRasterPipelineOp::evenly_spaced_2_stop_gradient, ctx);
392 for (
int i = 0;
i < 4;
i++) {
398 if (positions ==
nullptr) {
401 size_t stopCount =
count;
402 float gapCount = stopCount - 1;
405 for (
size_t i = 0;
i < stopCount - 1;
i++) {
412 ctx->stopCount = stopCount;
413 p->append(SkRasterPipelineOp::evenly_spaced_gradient, ctx);
424 firstStop = pmColors[0] != pmColors[1] ? 0 : 1;
431 size_t stopCount = 0;
432 float t_l = positions[firstStop];
436 for (
int i = firstStop;
i < lastStop;
i++) {
437 float t_r = positions[
i + 1];
451 ctx->ts[stopCount] = t_l;
454 ctx->stopCount = stopCount;
455 p->append(SkRasterPipelineOp::gradient, ctx);
462 bool colorsAreOpaque,
467 bool colorIsPremul =
static_cast<bool>(interpolation.
fInPremul);
472 case ColorSpace::kLab:
473 case ColorSpace::kOKLab:
474 case ColorSpace::kOKLabGamutMap:
475 p->append(SkRasterPipelineOp::unpremul);
476 colorIsPremul =
false;
478 case ColorSpace::kLCH:
479 case ColorSpace::kOKLCH:
480 case ColorSpace::kOKLCHGamutMap:
481 case ColorSpace::kHSL:
482 case ColorSpace::kHWB:
483 p->append(SkRasterPipelineOp::unpremul_polar);
484 colorIsPremul =
false;
493 case ColorSpace::kLab:
p->append(SkRasterPipelineOp::css_lab_to_xyz);
break;
494 case ColorSpace::kOKLab:
p->append(SkRasterPipelineOp::css_oklab_to_linear_srgb);
break;
495 case ColorSpace::kOKLabGamutMap:
496 p->append(SkRasterPipelineOp::css_oklab_gamut_map_to_linear_srgb);
498 case ColorSpace::kLCH:
p->append(SkRasterPipelineOp::css_hcl_to_lab);
499 p->append(SkRasterPipelineOp::css_lab_to_xyz);
break;
500 case ColorSpace::kOKLCH:
p->append(SkRasterPipelineOp::css_hcl_to_lab);
501 p->append(SkRasterPipelineOp::css_oklab_to_linear_srgb);
break;
502 case ColorSpace::kOKLCHGamutMap:
503 p->append(SkRasterPipelineOp::css_hcl_to_lab);
504 p->append(SkRasterPipelineOp::css_oklab_gamut_map_to_linear_srgb);
506 case ColorSpace::kHSL:
p->append(SkRasterPipelineOp::css_hsl_to_srgb);
break;
507 case ColorSpace::kHWB:
p->append(SkRasterPipelineOp::css_hwb_to_srgb);
break;
513 if (!dstColorSpace) {
525 intermediateColorSpace, intermediateAlphaType, dstColorSpace, dstAlphaType)
535 std::optional<SkShaders::MatrixRec> newMRec = mRec.
apply(rec,
fPtsToUnit);
536 if (!newMRec.has_value()) {
546 p->append(SkRasterPipelineOp::mirror_x_1);
549 p->append(SkRasterPipelineOp::repeat_x_1);
555 p->append(SkRasterPipelineOp::decal_x, decal_ctx);
564 p->append(SkRasterPipelineOp::clamp_x_1);
579 p->append(SkRasterPipelineOp::check_decal_mask, decal_ctx);
582 p->extend(postPipeline);
615 case ColorSpace::kDestination:
620 case ColorSpace::kSRGBLinear:
623 case ColorSpace::kSRGB:
624 case ColorSpace::kHSL:
625 case ColorSpace::kHWB:
628 case ColorSpace::kLab:
629 case ColorSpace::kLCH:
633 case ColorSpace::kOKLab:
634 case ColorSpace::kOKLabGamutMap:
635 case ColorSpace::kOKLCH:
636 case ColorSpace::kOKLCHGamutMap:
654 float hue = 0,
sat = 0, light = (mn + mx) / 2;
658 sat = (light == 0 || light == 1) ? 0 : (mx - light) /
std::min(light, 1 - light);
660 hue = (rgb.
fG - rgb.
fB) /
d + (rgb.
fG < rgb.
fB ? 6 : 0);
661 }
else if (mx == rgb.
fG) {
670 *hueIsPowerless =
true;
672 return {
hue,
sat * 100, light * 100, rgb.
fA};
679 return {hsl.
fR, white * 100, black * 100, rgb.
fA};
683 constexpr float D50[3] = {0.3457f / 0.3585f, 1.0f, (1.0f - 0.3457f - 0.3585f) / 0.3585f};
685 constexpr float e = 216.0f / 24389;
686 constexpr float k = 24389.0f / 27;
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;
694 return {(116 *
f[1]) - 16, 500 * (
f[0] -
f[1]), 200 * (
f[1] -
f[2]), xyz.
fA};
702 float chroma = sqrtf(Lab[1] * Lab[1] + Lab[2] * Lab[2]);
704 constexpr float kMaxChromaForPowerlessHue = 1e-2f;
705 if (chroma <= kMaxChromaForPowerlessHue) {
706 *hueIsPowerless =
true;
708 return {
hue >= 0 ?
hue :
hue + 360, chroma, Lab[0], xyz.
fA};
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;
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,
730 float chroma = sqrtf(OKLab[1] * OKLab[1] + OKLab[2] * OKLab[2]);
732 constexpr float kMaxChromaForPowerlessHue = 1e-6f;
733 if (chroma <= kMaxChromaForPowerlessHue) {
734 *hueIsPowerless =
true;
736 return {
hue >= 0 ?
hue :
hue + 360, chroma, OKLab[0], rgb.
fA};
740 return {hsl.
fR, hsl.
fG * hsl.
fA, hsl.
fB * hsl.
fA, hsl.
fA};
744 return {rgb.
fR * rgb.
fA, rgb.
fG * rgb.
fA, rgb.
fB * rgb.
fA, rgb.
fA};
750 case ColorSpace::kLCH:
751 case ColorSpace::kOKLCH:
752 case ColorSpace::kHSL:
753 case ColorSpace::kHWB:
785 bool forceExplicitPositions) {
811 info.minRowBytes()));
816 case ColorSpace::kHSL: convertFn =
srgb_to_hsl;
break;
817 case ColorSpace::kHWB: convertFn =
srgb_to_hwb;
break;
828 bool anyPowerlessHue =
false;
831 for (
int i = 0;
i < colorCount; ++
i) {
833 anyPowerlessHue = anyPowerlessHue || hueIsPowerless[
i];
837 if (anyPowerlessHue) {
844 for (
int i = 0;
i < colorCount; ++
i) {
846 float curPos = shader->
getPos(
i);
848 if (!hueIsPowerless[
i]) {
866 if (
i != colorCount - 1) {
886 for (
int i = 0;
i < colorCount - 1; ++
i) {
891 case HueMethod::kShorter:
895 }
else if (h2 - h1 < -180) {
900 case HueMethod::kLonger:
905 }
else if (0 < h2 - h1 && h2 - h1 < 180) {
908 }
else if (-180 < h2 - h1 && h2 - h1 <= 0) {
913 case HueMethod::kIncreasing:
919 case HueMethod::kDecreasing:
931 if (
static_cast<bool>(interpolation.
fInPremul)) {
933 case ColorSpace::kHSL:
934 case ColorSpace::kHWB:
935 case ColorSpace::kLCH:
936 case ColorSpace::kOKLCH:
946 for (
int i = 0;
i < colorCount; ++
i) {
954 float posScale = 1.0f / (colorCount - 1);
955 for (
int i = 0;
i < colorCount;
i++) {
963 const float ONE_OVER_255 = 1.f / 255;
989 info->fGradientFlags =
1012 , fColorSpace(
std::move(colorSpace))
1013 , fPositions(positions)
1014 , fColorCount(colorCount)
1016 , fInterpolation(interpolation) {
1028 for (
int i = 0;
i < colorCount - 1; ++
i) {
1052 if (
i == colorCount - 2) {
1057 blend += (1.f - p1) * c;
1061 w = 1.f / (colorCount - 1);
1064 blend += 0.5f *
w * (c1 + c0);
1091 std::move(colorSpace));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
sk_bzero(glyphs, sizeof(glyphs))
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static float prev(float f)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkDEBUGFAIL(message)
SkRGBA4f< kPremul_SkAlphaType > SkPMColor4f
SkColorSpace * sk_srgb_singleton()
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
#define SkColorGetR(color)
SkRGBA4f< kUnpremul_SkAlphaType > SkColor4f
#define SkColorGetG(color)
#define SkColorGetA(color)
#define SkColorGetB(color)
bool SkConvertPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRB, const SkImageInfo &srcInfo, const void *srcPixels, size_t srcRB)
static float SkBits2Float(uint32_t bits)
static uint32_t SkFloat2Bits(float value)
static bool SkIsFinite(T x, Pack... values)
static constexpr float sk_ieee_float_divide(float numer, float denom)
static constexpr float sk_float_radians_to_degrees(float radians)
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 add_stop_color(SkRasterPipeline_GradientCtx *ctx, size_t stop, SkPMColor4f Fs, SkPMColor4f Bs)
static SkPMColor4f srgb_to_hwb(SkPMColor4f rgb, bool *hueIsPowerless)
static SkPMColor4f lin_srgb_to_okhcl(SkPMColor4f rgb, bool *hueIsPowerless)
static SkPMColor4f xyzd50_to_lab(SkPMColor4f xyz, bool *)
SkPMColor4f(*)(SkPMColor4f, bool *) ConvertColorProc
static SkPMColor4f srgb_to_hsl(SkPMColor4f rgb, bool *hueIsPowerless)
static bool color_space_is_polar(SkGradientShader::Interpolation::ColorSpace cs)
GradientSerializationFlags
@ kInterpolationColorSpaceMask_GSF
@ kHasLegacyLocalMatrix_GSF
@ kInterpolationColorSpaceShift_GSF
@ kInterpolationHueMethodShift_GSF
@ kInterpolationInPremul_GSF
@ kInterpolationHueMethodMask_GSF
SkPMColor4f(*)(SkPMColor4f) PremulColorProc
static bool validate_array(SkReadBuffer &buffer, size_t count, STArray< N, T, MEM_MOVE > *array)
static SkColor4f average_gradient_color(const SkColor4f colors[], const SkScalar pos[], int colorCount)
static SkPMColor4f xyzd50_to_hcl(SkPMColor4f xyz, bool *hueIsPowerless)
static void init_stop_pos(SkRasterPipeline_GradientCtx *ctx, size_t stop, float t_l, float c_scale, SkPMColor4f c_l, SkPMColor4f c_r)
static SkPMColor4f premul_polar(SkPMColor4f hsl)
static SkPMColor4f premul_rgb(SkPMColor4f rgb)
static SkPMColor4f lin_srgb_to_oklab(SkPMColor4f rgb, bool *)
static sk_sp< SkColorSpace > intermediate_color_space(SkGradientShader::Interpolation::ColorSpace cs, SkColorSpace *dst)
static bool apply(Pass *pass, SkRecord *record)
sk_sp< T > sk_ref_sp(T *obj)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
static constexpr int kSkTileModeCount
static constexpr bool SkToBool(const T &x)
T * makeArray(size_t count)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > Deserialize(const void *data, size_t length)
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
sk_sp< SkData > serialize() const
static sk_sp< SkColorSpace > MakeSRGBLinear()
bool unflatten(SkReadBuffer &, SkMatrix *legacyLocalMatrix)
static bool ValidGradient(const SkColor4f colors[], int count, SkTileMode tileMode, const Interpolation &interpolation)
Interpolation fInterpolation
SkColor getLegacyColor(int i) const
bool colorsAreOpaque() const
bool isOpaque() const override
SkGradientBaseShader(const Descriptor &desc, const SkMatrix &ptsToUnit)
bool fFirstStopIsImplicit
virtual void appendGradientStages(SkArenaAlloc *alloc, SkRasterPipeline *tPipeline, SkRasterPipeline *postPipeline) const =0
bool onAsLuminanceColor(SkColor4f *) const override
SkScalar getPos(int i) const
static sk_sp< SkShader > MakeDegenerateGradient(const SkColor4f colors[], const SkScalar pos[], int colorCount, sk_sp< SkColorSpace > colorSpace, SkTileMode mode)
~SkGradientBaseShader() override
void flatten(SkWriteBuffer &) const override
bool appendStages(const SkStageRec &, const SkShaders::MatrixRec &) const override
const SkMatrix fPtsToUnit
void commonAsAGradient(GradientInfo *) const
sk_sp< SkColorSpace > fColorSpace
bool interpolateInPremul() const
static void AppendGradientFillStages(SkRasterPipeline *p, SkArenaAlloc *alloc, const SkPMColor4f *colors, const SkScalar *positions, int count)
static void AppendInterpolatedToDstStages(SkRasterPipeline *p, SkArenaAlloc *alloc, bool colorsAreOpaque, const Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace)
SkTileMode getTileMode() const
@ kInterpolateColorsInPremul_Flag
static const SkMatrix & I()
std::optional< MatrixRec > apply(const SkStageRec &rec, const SkMatrix &postInv={}) const
void resize_back(int newCount)
void reserve_exact(int n)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
FlutterSemanticsFlag flags
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
static float sat(float r, float g, float b)
static void hue(float dr, float dg, float db, float *sr, float *sg, float *sb)
static float max(float r, float g, float b)
static float lum(float r, float g, float b)
static float min(float r, float g, float b)
static constexpr skcms_Matrix3x3 kXYZ
static constexpr skcms_TransferFunction kLinear
PODArray< SkColor > colors
SK_API sk_sp< SkShader > Color(SkColor)
SK_API sk_sp< SkShader > Empty()
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
SkColorConverter(const SkColor *colors, int count)
skia_private::STArray< 2, SkColor4f > fColors4f
static constexpr int kColorSpaceCount
static constexpr int kHueMethodCount
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
const float * vec() const
int fColorCount
In-out parameter, specifies passed size.
SkScalar * fColorOffsets
The unit offset for color transitions.
SkRasterPipeline * fPipeline
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
std::shared_ptr< const fml::Mapping > data