/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#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/SkFloatingPoint.h"
#include "include/private/SkMalloc.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTPin.h"
#include "include/private/SkTo.h"
#include "modules/skcms/skcms.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkColorData.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkEffectPriv.h"
#include "src/core/SkFloatBits.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/SkVx.h"
#include "src/core/SkWriteBuffer.h"

#include <algorithm>
#include <cmath>
#include <optional>
#include <utility>

using namespace skia_private;

enum GradientSerializationFlags {
    // Bits 29:31 used for various boolean flags
    kHasPosition_GSF          = 0x80000000,
    kHasLegacyLocalMatrix_GSF = 0x40000000,
    kHasColorSpace_GSF        = 0x20000000,

    // Bits 12:28 unused

    // Bits 8:11 for fTileMode
    kTileModeShift_GSF  = 8,
    kTileModeMask_GSF   = 0xF,

    // Bits 4:7 for fInterpolation.fColorSpace
    kInterpolationColorSpaceShift_GSF = 4,
    kInterpolationColorSpaceMask_GSF  = 0xF,

    // Bits 1:3 for fInterpolation.fHueMethod
    kInterpolationHueMethodShift_GSF = 1,
    kInterpolationHueMethodMask_GSF  = 0x7,

    // Bit 0 for fInterpolation.fInPremul
    kInterpolationInPremul_GSF = 0x1,
};

void SkGradientBaseShader::flatten(SkWriteBuffer& buffer) const {
    uint32_t flags = 0;
    if (fPositions) {
        flags |= kHasPosition_GSF;
    }
    sk_sp<SkData> colorSpaceData = fColorSpace ? fColorSpace->serialize() : nullptr;
    if (colorSpaceData) {
        flags |= kHasColorSpace_GSF;
    }
    if (fInterpolation.fInPremul == Interpolation::InPremul::kYes) {
        flags |= kInterpolationInPremul_GSF;
    }
    SkASSERT(static_cast<uint32_t>(fTileMode) <= kTileModeMask_GSF);
    flags |= ((uint32_t)fTileMode << kTileModeShift_GSF);
    SkASSERT(static_cast<uint32_t>(fInterpolation.fColorSpace) <= kInterpolationColorSpaceMask_GSF);
    flags |= ((uint32_t)fInterpolation.fColorSpace << kInterpolationColorSpaceShift_GSF);
    SkASSERT(static_cast<uint32_t>(fInterpolation.fHueMethod) <= kInterpolationHueMethodMask_GSF);
    flags |= ((uint32_t)fInterpolation.fHueMethod << kInterpolationHueMethodShift_GSF);

    buffer.writeUInt(flags);

    // If we injected implicit first/last stops at construction time, omit those when serializing:
    size_t colorCount = fColorCount;
    const SkColor4f* colors = fColors;
    const SkScalar* positions = fPositions;
    if (fFirstStopIsImplicit) {
        colorCount--;
        colors++;
        if (positions) {
            positions++;
        }
    }
    if (fLastStopIsImplicit) {
        colorCount--;
    }

    buffer.writeColor4fArray({colors, colorCount});
    if (colorSpaceData) {
        buffer.writeDataAsByteArray(colorSpaceData.get());
    }
    if (positions) {
        buffer.writeScalarArray({positions, colorCount});
    }
}

template <int N, typename T, bool MEM_MOVE>
static bool validate_array(SkReadBuffer& buffer, size_t count, STArray<N, T, MEM_MOVE>* array) {
    if (!buffer.validateCanReadN<T>(count)) {
        return false;
    }

    array->resize_back(count);
    return true;
}

std::optional<SkGradient> SkGradientScope::unflatten(SkReadBuffer& buffer,
                                                     SkMatrix* legacyLocalMatrix) {
    // New gradient format. Includes floating point color, color space, densely packed flags
    uint32_t flags = buffer.readUInt();

    auto tm = (SkTileMode)((flags >> kTileModeShift_GSF) & kTileModeMask_GSF);

    auto cs = (SkGradient::Interpolation::ColorSpace)(
            (flags >> kInterpolationColorSpaceShift_GSF) & kInterpolationColorSpaceMask_GSF);
    auto hm = (SkGradient::Interpolation::HueMethod)(
            (flags >> kInterpolationHueMethodShift_GSF) & kInterpolationHueMethodMask_GSF);
    auto pm = (flags & kInterpolationInPremul_GSF) ? SkGradient::Interpolation::InPremul::kYes
                                                   : SkGradient::Interpolation::InPremul::kNo;

    const size_t count = buffer.getArrayCount();

    if (!(validate_array(buffer, count, &fColorStorage) &&
          buffer.readColor4fArray({fColorStorage.data(), count}))) {
        return {};
    }
    SkSpan<const SkColor4f> colors = {fColorStorage.begin(), count};

    sk_sp<SkColorSpace> colorSpace;
    if (flags & kHasColorSpace_GSF) {
        if (auto data = buffer.readByteArrayAsData()) {
            colorSpace = SkColorSpace::Deserialize(data->data(), data->size());
        }
    }

    SkSpan<const float> pos;
    if (flags & kHasPosition_GSF) {
        if (!(validate_array(buffer, count, &fPositionStorage) &&
              buffer.readScalarArray({fPositionStorage.data(), count}))) {
            return {};
        }
        pos = {fPositionStorage.begin(), count};
    }

    if (flags & kHasLegacyLocalMatrix_GSF) {
        SkASSERT(buffer.isVersionLT(SkPicturePriv::Version::kNoShaderLocalMatrix));
        buffer.readMatrix(legacyLocalMatrix);
    } else {
        *legacyLocalMatrix = SkMatrix::I();
    }

    if (buffer.isValid()) {
        return SkGradient({colors, pos, tm, std::move(colorSpace)},
                          {pm, cs, hm});
    }
    return {};
}

////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkColorSpace> srgb_if_null(sk_sp<SkColorSpace> cs) {
    return cs ? cs : SkColorSpace::MakeSRGB();
}

SkGradientBaseShader::SkGradientBaseShader(const SkGradient& desc, const SkMatrix& ptsToUnit)
        : fPtsToUnit(ptsToUnit)
        , fColorSpace(srgb_if_null(desc.colors().colorSpace()))
        , fFirstStopIsImplicit(false)
        , fLastStopIsImplicit(false)
        , fColorsAreOpaque(true) {
    auto colors = desc.colors().colors();
    auto pos = desc.colors().positions();

    fPtsToUnit.getType();  // Precache so reads are threadsafe.
    SkASSERT(colors.size() > 1);

    fInterpolation = desc.interpolation();

    SkASSERT((unsigned)desc.colors().tileMode() < kSkTileModeCount);
    fTileMode = desc.colors().tileMode();

    /*  Note: we let the caller skip the first and/or last position.
        i.e. pos[0] = 0.3, pos[1] = 0.7
        In these cases, we insert entries to ensure that the final data
        will be bracketed by [0, 1].
        i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1

        Thus colorCount (the caller's value, and fColorCount (our value) may
        differ by up to 2. In the above example:
            colorCount = 2
            fColorCount = 4
     */
    fColorCount = colors.size();

    // Check if we need to add in start and/or end position/colors
    if (pos.size() > 0) {
        fFirstStopIsImplicit = pos.front() > 0;
        fLastStopIsImplicit = pos.back() != SK_Scalar1;
        fColorCount += fFirstStopIsImplicit + fLastStopIsImplicit;
    }

    size_t storageSize =
            fColorCount * (sizeof(SkColor4f) + (pos.size() > 0 ? sizeof(SkScalar) : 0));
    fColors = reinterpret_cast<SkColor4f*>(fStorage.reset(storageSize));
    fPositions = pos.size() > 0 ? reinterpret_cast<float*>(fColors + fColorCount) : nullptr;

    // Now copy over the colors, adding the duplicates at t=0 and t=1 as needed
    SkColor4f* colorPtr = fColors;
    if (fFirstStopIsImplicit) {
        *colorPtr++ = colors[0];
    }
    for (size_t i = 0; i < colors.size(); ++i) {
        colorPtr[i] = colors[i];
        fColorsAreOpaque = fColorsAreOpaque && (colors[i].fA == 1);
    }
    if (fLastStopIsImplicit) {
        colorPtr += colors.size();
        *colorPtr = colors.back();
    }

    if (pos.size() > 0) {
        SkScalar prev = 0;
        SkScalar* positions = fPositions;
        *positions++ = prev;  // force the first pos to 0

        size_t startIndex = fFirstStopIsImplicit ? 0 : 1;
        size_t count = pos.size() + fLastStopIsImplicit;

        bool uniformStops = true;
        const SkScalar uniformStep = pos[startIndex] - prev;
        for (size_t i = startIndex; i < count; i++) {
            // Pin the last value to 1.0, and make sure pos is monotonic.
            float curr = 1.0f;
            if (i != pos.size()) {
                curr = SkTPin(pos[i], prev, 1.0f);

                // If a value is clamped to 1.0 before the last stop, the last stop
                // actually isn't implicit if we thought it was.
                if (curr == 1.0f && fLastStopIsImplicit) {
                    fLastStopIsImplicit = false;
                }
            }

            uniformStops &= SkScalarNearlyEqual(uniformStep, curr - prev);

            *positions++ = prev = curr;
        }

        if (uniformStops) {
            // If the stops are uniform, treat them as implicit.
            fPositions = nullptr;
        } else {
            // Remove duplicate stops with more than two of the same stop,
            // keeping the leftmost and rightmost stop colors.
            // i.e.       0, 0, 0,   0.2, 0.2, 0.3, 0.3, 0.3, 1, 1
            // w/  clamp  0,    0,   0.2, 0.2, 0.3,      0.3, 1, 1
            // w/o clamp        0,   0.2, 0.2, 0.3,      0.3, 1
            size_t i = 0;
            size_t dedupedColorCount = 0;
            for (size_t j = 1; j <= fColorCount; j++) {
                // We can compare the current positions at i and j since once these fPosition
                // values are overwritten, our i and j pointers will be past the overwritten values.
                if (j == fColorCount || fPositions[i] != fPositions[j]) {
                    SkASSERT(j >= i);
                    bool dupStop = j - i > 1;

                    // Ignore the leftmost stop (i) if it is a non-clamp tilemode with
                    // a duplicate stop on t = 0.
                    bool ignoreLeftmost = dupStop && fTileMode != SkTileMode::kClamp
                                                    && fPositions[i] == 0;
                    if (!ignoreLeftmost) {
                        fPositions[dedupedColorCount] = fPositions[i];
                        fColors[dedupedColorCount] =  fColors[i];
                        dedupedColorCount++;
                    }

                    // Include the rightmost stop (j-1) only if the stop has a duplicate,
                    // ignoring the rightmost stop if it is a non-clamp tilemode with t = 1.
                    bool ignoreRightmost = fTileMode != SkTileMode::kClamp
                                                    && fPositions[j - 1] == 1;
                    if (dupStop && !ignoreRightmost) {
                        fPositions[dedupedColorCount] = fPositions[j - 1];
                        fColors[dedupedColorCount] = fColors[j - 1];
                        dedupedColorCount++;
                    }
                    i = j;
                }
            }
            fColorCount = dedupedColorCount;
        }
    }
}

SkGradientBaseShader::~SkGradientBaseShader() {}

static void add_stop_color(SkRasterPipelineContexts::GradientCtx* ctx,
                           size_t stop,
                           const SkPMColor4f& Fs,
                           const SkPMColor4f& Bs) {
    (ctx->factors[0])[stop] = Fs.fR;
    (ctx->factors[1])[stop] = Fs.fG;
    (ctx->factors[2])[stop] = Fs.fB;
    (ctx->factors[3])[stop] = Fs.fA;

    (ctx->biases[0])[stop] = Bs.fR;
    (ctx->biases[1])[stop] = Bs.fG;
    (ctx->biases[2])[stop] = Bs.fB;
    (ctx->biases[3])[stop] = Bs.fA;
}

static void add_const_color(SkRasterPipelineContexts::GradientCtx* ctx,
                            size_t stop,
                            const SkPMColor4f& color) {
    add_stop_color(ctx, stop, {0, 0, 0, 0}, color);
}

// Calculate a factor F and a bias B so that color = F*t + B when t is in range of
// the stop. Assume that all stops have width 1/gapCount and the stop parameter
// refers to the nth stop.
static void init_stop_evenly(SkRasterPipelineContexts::GradientCtx* ctx,
                             float gapCount,
                             size_t stop,
                             const SkPMColor4f& leftC,
                             const SkPMColor4f& rightC) {
    auto left = skvx::float4::Load(leftC.vec());
    auto right = skvx::float4::Load(rightC.vec());

    SkPMColor4f factor, bias;

    // We start with the following 2 linear equations and 2 unknowns (factor, bias)
    // left = factor * t + bias
    // right = factor * (t + gap) + bias
    // gap = 1/gapCount
    // t = gap * stop

    // right - left = factor * (t + gap) - factor * t
    // right - left = factor * gap
    // factor = (right - left) / gap  (and gap = 1/gapCount)
    auto factor4 = ((right - left) * gapCount);
    (left - (factor4 * (stop / gapCount))).store(bias.vec());
    factor4.store(factor.vec());

    add_stop_color(ctx, stop, factor, bias);
}

// Calculate a factor F and a bias B so that color = F*t + B when t is in range of
// the stop. Unlike init_stop_evenly, this handles stops
static void init_stop_pos(SkRasterPipelineContexts::GradientCtx* ctx,
                          size_t stop,
                          float t_l,
                          float gapReciprocal,
                          const SkPMColor4f& leftC,
                          const SkPMColor4f& rightC) {
    // gapReciprocal is 1/gapWidth. If two colors were on top of each other, we should
    // have skipped that as a "stop".
    SkASSERT(SkIsFinite(gapReciprocal));

    auto left = skvx::float4::Load(leftC.vec());
    auto right = skvx::float4::Load(rightC.vec());

    SkPMColor4f factor, bias;

    // See init_stop_evenly for this derivation, noting that gap = 1/gapReciprocal
    // and t = t_l
    auto factor4 = ((right - left) * gapReciprocal);
    (left - (factor4 * t_l)).store(bias.vec());
    factor4.store(factor.vec());

    ctx->ts[stop] = t_l;
    add_stop_color(ctx, stop, factor, bias);
}

void SkGradientBaseShader::AppendGradientFillStages(SkRasterPipeline* p,
                                                    SkArenaAlloc* alloc,
                                                    const SkPMColor4f* pmColors,
                                                    const SkScalar* positions,
                                                    int count) {
    // The two-stop case with stops at 0 and 1.
    if (count == 2 && positions == nullptr) {
        const SkPMColor4f c_l = pmColors[0], c_r = pmColors[1];

        auto ctx = alloc->make<SkRasterPipelineContexts::EvenlySpaced2StopGradientCtx>();
        (skvx::float4::Load(c_r.vec()) - skvx::float4::Load(c_l.vec())).store(ctx->factor);
        (skvx::float4::Load(c_l.vec())).store(ctx->bias);

        p->append(SkRasterPipelineOp::evenly_spaced_2_stop_gradient, ctx);
        return;
    }
    // Linear gradients with evenly spaced stops involve doing calculations to interpolate
    // between color n and color n+1 based on t (in range [0.0,1.0]).
    //   color_n * (t - t_n) / gap_n + color_{n+1} * (t_{n+1} - t) / gap_n
    // We could just stick the colors and the gaps calculation in RP and do this calculation,
    // but instead we can precompute things to make the RP calculation simpler and faster.
    // For each gap, we calculate four linear equations in the form y = m*x + b, or rather
    //  color_channel = factor * t + bias
    // We do this pre-computation in init_stop_evenly and init_stop_pos.

    auto* ctx = alloc->make<SkRasterPipelineContexts::GradientCtx>();

    // Allocate at least enough for the AVX2 gather from a YMM register.
    constexpr int kMaxRegisterSize = 8;

    // There are n - 1 gaps between n colors plus 2 regions to the left and right
    // of the gradient to account for colors. For evenly spaced gradients, we cheat
    // and skip the left gap, using one block of floats unused.
    const size_t factorBiasFloats = std::max(count + 1, kMaxRegisterSize);
    const size_t tsForArbitraryStops = count + 1;
    using SkRasterPipelineContexts::kRGBAChannels;

    // We need space for all factors and biases, and while we are at it, some space
    // if we need to include the arbitrary stops.
    const size_t toAlloc = 2 * kRGBAChannels * factorBiasFloats + tsForArbitraryStops;
    float* gradientCtxBuffer = alloc->makeArray<float>(toAlloc);
    for (size_t i = 0; i < kRGBAChannels; i++) {
        ctx->factors[i] = gradientCtxBuffer;
        gradientCtxBuffer += factorBiasFloats;
        ctx->biases[i] = gradientCtxBuffer;
        gradientCtxBuffer += factorBiasFloats;
    }

    if (positions == nullptr) {
        // Handle evenly distributed stops.

        size_t stopCount = count;
        float gapCount = stopCount - 1;

        SkPMColor4f c_l = pmColors[0];
        for (size_t i = 0; i < gapCount; i++) {
            SkPMColor4f c_r = pmColors[i + 1];
            init_stop_evenly(ctx, gapCount, i, c_l, c_r);
            c_l = c_r;
        }
        add_const_color(ctx, stopCount - 1, c_l);

        ctx->stopCount = stopCount;
        p->append(SkRasterPipelineOp::evenly_spaced_gradient, ctx);
        return;
    }

    // Handle arbitrary stops.
    ctx->ts = gradientCtxBuffer;

    // Remove the default stops inserted by SkGradientBaseShader::SkGradientBaseShader
    // because they are naturally handled by the search method.
    int firstStop;
    int lastStop;
    if (count > 2) {
        firstStop = pmColors[0] != pmColors[1] ? 0 : 1;
        lastStop = pmColors[count - 2] != pmColors[count - 1] ? count - 1 : count - 2;
    } else {
        firstStop = 0;
        lastStop = 1;
    }

    size_t stopCount = 0;
    float t_l = positions[firstStop];
    SkPMColor4f c_l = pmColors[firstStop];
    add_const_color(ctx, stopCount++, c_l);

    for (int i = firstStop; i < lastStop; i++) {
        float t_r = positions[i + 1];
        SkPMColor4f c_r = pmColors[i + 1];
        SkASSERT(t_l <= t_r);
        if (t_l < t_r) {
            float c_scale = sk_ieee_float_divide(1, t_r - t_l);
            if (SkIsFinite(c_scale)) {
                init_stop_pos(ctx, stopCount, t_l, c_scale, c_l, c_r);
                stopCount += 1;
            }
        }
        t_l = t_r;
        c_l = c_r;
    }

    ctx->ts[stopCount] = t_l;
    add_const_color(ctx, stopCount++, c_l);

    ctx->stopCount = stopCount;
    p->append(SkRasterPipelineOp::gradient, ctx);
}

void SkGradientBaseShader::AppendInterpolatedToDstStages(SkRasterPipeline* p,
                                                         SkArenaAlloc* alloc,
                                                         bool colorsAreOpaque,
                                                         const Interpolation& interpolation,
                                                         const SkColorSpace* intermediateColorSpace,
                                                         const SkColorSpace* dstColorSpace) {
    using ColorSpace = Interpolation::ColorSpace;
    bool colorIsPremul = static_cast<bool>(interpolation.fInPremul);

    // If we interpolated premul colors in any of the special color spaces, we need to unpremul
    if (colorIsPremul && !colorsAreOpaque) {
        switch (interpolation.fColorSpace) {
            case ColorSpace::kLab:
            case ColorSpace::kOKLab:
            case ColorSpace::kOKLabGamutMap:
                p->append(SkRasterPipelineOp::unpremul);
                colorIsPremul = false;
                break;
            case ColorSpace::kLCH:
            case ColorSpace::kOKLCH:
            case ColorSpace::kOKLCHGamutMap:
            case ColorSpace::kHSL:
            case ColorSpace::kHWB:
                p->append(SkRasterPipelineOp::unpremul_polar);
                colorIsPremul = false;
                break;
            default:
                break;
        }
    }

    // Convert colors in exotic spaces back to their intermediate SkColorSpace
    switch (interpolation.fColorSpace) {
        case ColorSpace::kLab:   p->append(SkRasterPipelineOp::css_lab_to_xyz);           break;
        case ColorSpace::kOKLab: p->append(SkRasterPipelineOp::css_oklab_to_linear_srgb); break;
        case ColorSpace::kOKLabGamutMap:
            p->append(SkRasterPipelineOp::css_oklab_gamut_map_to_linear_srgb);
            break;
        case ColorSpace::kLCH:   p->append(SkRasterPipelineOp::css_hcl_to_lab);
                                 p->append(SkRasterPipelineOp::css_lab_to_xyz);           break;
        case ColorSpace::kOKLCH: p->append(SkRasterPipelineOp::css_hcl_to_lab);
                                 p->append(SkRasterPipelineOp::css_oklab_to_linear_srgb); break;
        case ColorSpace::kOKLCHGamutMap:
            p->append(SkRasterPipelineOp::css_hcl_to_lab);
            p->append(SkRasterPipelineOp::css_oklab_gamut_map_to_linear_srgb);
            break;
        case ColorSpace::kHSL:   p->append(SkRasterPipelineOp::css_hsl_to_srgb);          break;
        case ColorSpace::kHWB:   p->append(SkRasterPipelineOp::css_hwb_to_srgb);          break;
        default: break;
    }

    // Now transform from intermediate to destination color space.
    // See comments in GrGradientShader.cpp about the decisions here.
    if (!dstColorSpace) {
        dstColorSpace = sk_srgb_singleton();
    }
    SkAlphaType intermediateAlphaType = colorIsPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
    // TODO(skbug.com/40044213): Get dst alpha type correctly
    SkAlphaType dstAlphaType = kPremul_SkAlphaType;

    if (colorsAreOpaque) {
        intermediateAlphaType = dstAlphaType = kUnpremul_SkAlphaType;
    }

    alloc->make<SkColorSpaceXformSteps>(
                 intermediateColorSpace, intermediateAlphaType, dstColorSpace, dstAlphaType)
            ->apply(p);
}

bool SkGradientBaseShader::appendStages(const SkStageRec& rec,
                                        const SkShaders::MatrixRec& mRec) const {
    SkRasterPipeline* p = rec.fPipeline;
    SkArenaAlloc* alloc = rec.fAlloc;
    SkRasterPipelineContexts::DecalTileCtx* decal_ctx = nullptr;

    std::optional<SkShaders::MatrixRec> newMRec = mRec.apply(rec, fPtsToUnit);
    if (!newMRec.has_value()) {
        return false;
    }

    SkRasterPipeline_<256> postPipeline;

    this->appendGradientStages(alloc, p, &postPipeline);

    switch (fTileMode) {
        case SkTileMode::kMirror:
            p->append(SkRasterPipelineOp::mirror_x_1);
            break;
        case SkTileMode::kRepeat:
            p->append(SkRasterPipelineOp::repeat_x_1);
            break;
        case SkTileMode::kDecal:
            decal_ctx = alloc->make<SkRasterPipelineContexts::DecalTileCtx>();
            decal_ctx->limit_x = SkBits2Float(SkFloat2Bits(1.0f) + 1);
            // reuse mask + limit_x stage, or create a custom decal_1 that just stores the mask
            p->append(SkRasterPipelineOp::decal_x, decal_ctx);
            [[fallthrough]];

        case SkTileMode::kClamp:
            if (!fPositions) {
                // We clamp only when the stops are evenly spaced.
                // If not, there may be hard stops, and clamping ruins hard stops at 0 and/or 1.
                // In that case, we must make sure we're using the general "gradient" stage,
                // which is the only stage that will correctly handle unclamped t.
                p->append(SkRasterPipelineOp::clamp_x_1);
            }
            break;
    }

    // Transform all of the colors to destination color space, possibly premultiplied
    SkColor4fXformer xformedColors(this, rec.fDstCS);
    AppendGradientFillStages(p, alloc,
                             xformedColors.fColors.begin(),
                             xformedColors.fPositions,
                             xformedColors.fColors.size());
    AppendInterpolatedToDstStages(p, alloc, fColorsAreOpaque, fInterpolation,
                                  xformedColors.fIntermediateColorSpace.get(), rec.fDstCS);

    if (decal_ctx) {
        p->append(SkRasterPipelineOp::check_decal_mask, decal_ctx);
    }

    p->extend(postPipeline);

    return true;
}

bool SkGradientBaseShader::isOpaque() const {
    return fColorsAreOpaque && (this->getTileMode() != SkTileMode::kDecal);
}

bool SkGradientBaseShader::onAsLuminanceColor(SkColor4f* lum) const {
    // We just compute an average color. There are several things we could do better:
    // 1) We already have a different average_gradient_color helper later in this file, that weights
    //    contribution by the relative size of each band.
    // 2) Colors should be converted to some standard color space! These could be in any space.
    // 3) Do we want to average in the source space, sRGB, or some linear space?
    SkColor4f color{0, 0, 0, 1};
    for (size_t i = 0; i < fColorCount; ++i) {
        color.fR += fColors[i].fR;
        color.fG += fColors[i].fG;
        color.fB += fColors[i].fB;
    }
    const float scale = 1.0f / fColorCount;
    color.fR *= scale;
    color.fG *= scale;
    color.fB *= scale;
    *lum = color;
    return true;
}

static sk_sp<SkColorSpace> intermediate_color_space(SkGradient::Interpolation::ColorSpace cs,
                                                    SkColorSpace* dst) {
    using ColorSpace = SkGradient::Interpolation::ColorSpace;
    switch (cs) {
        case ColorSpace::kDestination:
            return sk_ref_sp(dst);

        // css-color-4 allows XYZD50 and XYZD65. For gradients, those are redundant. Interpolating
        // in any linear RGB space, (regardless of white point), gives the same answer.
        case ColorSpace::kSRGBLinear:
            return SkColorSpace::MakeSRGBLinear();

        case ColorSpace::kSRGB:
        case ColorSpace::kHSL:
        case ColorSpace::kHWB:
            return SkColorSpace::MakeSRGB();

        case ColorSpace::kLab:
        case ColorSpace::kLCH:
            // Conversion to Lab (and LCH) starts with XYZD50
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, SkNamedGamut::kXYZ);

        case ColorSpace::kOKLab:
        case ColorSpace::kOKLabGamutMap:
        case ColorSpace::kOKLCH:
        case ColorSpace::kOKLCHGamutMap:
            // The "standard" conversion to these spaces starts with XYZD65. That requires extra
            // effort to conjure. The author also has reference code for going directly from linear
            // sRGB, so we use that.
            // TODO(skbug.com/40044213): Even better would be to have an LMS color space, because the first
            // part of the conversion is a matrix multiply, which could be absorbed into the
            // color space xform.
            return SkColorSpace::MakeSRGBLinear();

        // These rectangular color spaces have their own transfer curves.
        case ColorSpace::kDisplayP3:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);

        case ColorSpace::kRec2020:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020);

        case ColorSpace::kProphotoRGB: {
            static SkOnce once;
            static skcms_Matrix3x3 lin_proPhoto_to_XYZ_D50;
            once([] { SkNamedPrimaries::kProPhotoRGB.toXYZD50(&lin_proPhoto_to_XYZ_D50); });
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kProPhotoRGB, lin_proPhoto_to_XYZ_D50);
        }

        case ColorSpace::kA98RGB:
            return SkColorSpace::MakeRGB(SkNamedTransferFn::kA98RGB, SkNamedGamut::kAdobeRGB);
    }
    SkUNREACHABLE;
}

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

static SkPMColor4f srgb_to_hsl(SkPMColor4f rgb, bool* hueIsPowerless) {
    float mx = std::max({rgb.fR, rgb.fG, rgb.fB});
    float mn = std::min({rgb.fR, rgb.fG, rgb.fB});
    float hue = 0, sat = 0, light = (mn + mx) / 2;
    float d = mx - mn;

    if (d != 0) {
        sat = (light == 0 || light == 1) ? 0 : (mx - light) / std::min(light, 1 - light);
        if (mx == rgb.fR) {
            hue = (rgb.fG - rgb.fB) / d + (rgb.fG < rgb.fB ? 6 : 0);
        } else if (mx == rgb.fG) {
            hue = (rgb.fB - rgb.fR) / d + 2;
        } else {
            hue = (rgb.fR - rgb.fG) / d + 4;
        }

        hue *= 60;
    }
    if (sat == 0) {
        *hueIsPowerless = true;
    }
    return {hue, sat * 100, light * 100, rgb.fA};
}

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

static SkPMColor4f xyzd50_to_lab(SkPMColor4f xyz, bool* /*hueIsPowerless*/) {
    constexpr float D50[3] = {0.3457f / 0.3585f, 1.0f, (1.0f - 0.3457f - 0.3585f) / 0.3585f};

    constexpr float e = 216.0f / 24389;
    constexpr float k = 24389.0f / 27;

    SkPMColor4f f;
    for (int i = 0; i < 3; ++i) {
        float v = xyz[i] / D50[i];
        f[i] = (v > e) ? std::cbrtf(v) : (k * v + 16) / 116;
    }

    return {(116 * f[1]) - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2]), xyz.fA};
}

// The color space is technically LCH, but we produce HCL, so that all polar spaces have hue in the
// first component. This simplifies the hue handling for HueMethod and premul/unpremul.
static SkPMColor4f xyzd50_to_hcl(SkPMColor4f xyz, bool* hueIsPowerless) {
    SkPMColor4f Lab = xyzd50_to_lab(xyz, hueIsPowerless);
    float hue = sk_float_radians_to_degrees(atan2f(Lab[2], Lab[1]));
    float chroma = sqrtf(Lab[1] * Lab[1] + Lab[2] * Lab[2]);
    // The LCH math produces small-ish (but not tiny) chroma values for achromatic colors:
    constexpr float kMaxChromaForPowerlessHue = 1e-2f;
    if (chroma <= kMaxChromaForPowerlessHue) {
        *hueIsPowerless = true;
    }
    return {hue >= 0 ? hue : hue + 360, chroma, Lab[0], xyz.fA};
}

// https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab
static SkPMColor4f lin_srgb_to_oklab(SkPMColor4f rgb, bool* /*hueIsPowerless*/) {
    float l = 0.4122214708f * rgb.fR + 0.5363325363f * rgb.fG + 0.0514459929f * rgb.fB;
    float m = 0.2119034982f * rgb.fR + 0.6806995451f * rgb.fG + 0.1073969566f * rgb.fB;
    float s = 0.0883024619f * rgb.fR + 0.2817188376f * rgb.fG + 0.6299787005f * rgb.fB;
    l = std::cbrtf(l);
    m = std::cbrtf(m);
    s = std::cbrtf(s);
    return {0.2104542553f * l + 0.7936177850f * m - 0.0040720468f * s,
            1.9779984951f * l - 2.4285922050f * m + 0.4505937099f * s,
            0.0259040371f * l + 0.7827717662f * m - 0.8086757660f * s,
            rgb.fA};
}

// The color space is technically OkLCH, but we produce HCL, so that all polar spaces have hue in
// the first component. This simplifies the hue handling for HueMethod and premul/unpremul.
static SkPMColor4f lin_srgb_to_okhcl(SkPMColor4f rgb, bool* hueIsPowerless) {
    SkPMColor4f OKLab = lin_srgb_to_oklab(rgb, hueIsPowerless);
    float hue = sk_float_radians_to_degrees(atan2f(OKLab[2], OKLab[1]));
    float chroma = sqrtf(OKLab[1] * OKLab[1] + OKLab[2] * OKLab[2]);
    // The OKLCH math produces very small chroma values for achromatic colors:
    constexpr float kMaxChromaForPowerlessHue = 1e-6f;
    if (chroma <= kMaxChromaForPowerlessHue) {
        *hueIsPowerless = true;
    }
    return {hue >= 0 ? hue : hue + 360, chroma, OKLab[0], rgb.fA};
}

static SkPMColor4f premul_polar(SkPMColor4f hsl) {
    return {hsl.fR, hsl.fG * hsl.fA, hsl.fB * hsl.fA, hsl.fA};
}

static SkPMColor4f premul_rgb(SkPMColor4f rgb) {
    return {rgb.fR * rgb.fA, rgb.fG * rgb.fA, rgb.fB * rgb.fA, rgb.fA};
}

static bool color_space_is_polar(SkGradient::Interpolation::ColorSpace cs) {
    using ColorSpace = SkGradient::Interpolation::ColorSpace;
    switch (cs) {
        case ColorSpace::kLCH:
        case ColorSpace::kOKLCH:
        case ColorSpace::kHSL:
        case ColorSpace::kHWB:
            return true;
        default:
            return false;
    }
}

// Given `colors` in `src` color space, an interpolation space, and a `dst` color space,
// we are doing several things. First, some definitions:
//
// The interpolation color space is "special" if it can't be represented as an SkColorSpace. This
// applies to any color space that isn't an RGB space, like Lab or HSL. These need special handling
// because we have to run bespoke code to do the conversion (before interpolation here, and after
// interpolation in the backend shader/pipeline).
//
// The interpolation color space is "polar" if it involves hue (HSL, HWB, LCH, Oklch). These need
// special handling, becuase hue is never premultiplied, and because HueMethod comes into play.
//
// 1) Pick an `intermediate` SkColorSpace. If the interpolation color space is not "special",
//    (kDestination, kSRGB, etc... ), then `intermediate` is exact. Otherwise, `intermediate` is the
//    RGB space that prepares us to do the final conversion. For example, conversion to Lab starts
//    with XYZD50, so `intermediate` will be XYZD50 if we're actually interpolating in Lab.
// 2) Transform all colors to the `intermediate` color space, leaving them unpremultiplied.
// 3) If the interpolation color space is "special", transform the colors to that space.
// 4) If the interpolation color space is "polar", adjust the angles to respect HueMethod.
// 5) If premul interpolation is requested, apply that. For "polar" interpolated colors, don't
//    premultiply hue, only the other two channels. Note that there are four polar spaces.
//    Two have hue as the first component, and two have it as the third component. To reduce
//    complexity, we always store hue in the first component, swapping it with luminance for
//    LCH and Oklch. The backend code (eg, shaders) needs to know about this.
SkColor4fXformer::SkColor4fXformer(const SkGradientBaseShader* shader,
                                   SkColorSpace* dst,
                                   bool forceExplicitPositions) {
    using ColorSpace = SkGradient::Interpolation::ColorSpace;
    using HueMethod = SkGradient::Interpolation::HueMethod;

    size_t colorCount = shader->colors().size();
    const auto& interpolation = shader->interpolation();

    // 0) Copy the shader's position pointer. Certain interpolation modes might force us to add
    //    new stops, in which case we'll allocate & edit the positions.
    fPositions = shader->positions().data();

    // 1) Determine the color space of our intermediate colors.
    fIntermediateColorSpace = intermediate_color_space(interpolation.fColorSpace, dst);

    // 2) Convert all colors to the intermediate color space
    auto info = SkImageInfo::Make(colorCount, 1, kRGBA_F32_SkColorType, kUnpremul_SkAlphaType);

    auto dstInfo = info.makeColorSpace(fIntermediateColorSpace);
    auto srcInfo = info.makeColorSpace(shader->colorSpace());

    fColors.reset(colorCount);
    SkAssertResult(SkConvertPixels(dstInfo,
                                   fColors.begin(),
                                   info.minRowBytes(),
                                   srcInfo,
                                   shader->colors().data(),
                                   info.minRowBytes()));

    // 3) Transform to the interpolation color space (if it's special)
    ConvertColorProc convertFn = nullptr;
    switch (interpolation.fColorSpace) {
        case ColorSpace::kHSL:           convertFn = srgb_to_hsl;       break;
        case ColorSpace::kHWB:           convertFn = srgb_to_hwb;       break;
        case ColorSpace::kLab:           convertFn = xyzd50_to_lab;     break;
        case ColorSpace::kLCH:           convertFn = xyzd50_to_hcl;     break;
        case ColorSpace::kOKLab:         convertFn = lin_srgb_to_oklab; break;
        case ColorSpace::kOKLabGamutMap: convertFn = lin_srgb_to_oklab; break;
        case ColorSpace::kOKLCH:         convertFn = lin_srgb_to_okhcl; break;
        case ColorSpace::kOKLCHGamutMap: convertFn = lin_srgb_to_okhcl; break;
        default: break;
    }

    skia_private::STArray<4, bool> hueIsPowerless;
    bool anyPowerlessHue = false;
    hueIsPowerless.push_back_n(colorCount, false);
    if (convertFn) {
        for (size_t i = 0; i < colorCount; ++i) {
            fColors[i] = convertFn(fColors[i], hueIsPowerless.data() + i);
            anyPowerlessHue = anyPowerlessHue || hueIsPowerless[i];
        }
    }

    if (anyPowerlessHue) {
        // In theory, if we knew we were just going to adjust the existing colors (without adding
        // new ones), we could do it all in-place. To keep things simple, we always generate the
        // new colors in separate storage.
        ColorStorage newColors;
        PositionStorage newPositions;

        for (size_t i = 0; i < colorCount; ++i) {
            const SkPMColor4f& curColor = fColors[i];
            float curPos = shader->getPos(i);

            if (!hueIsPowerless[i]) {
                newColors.push_back(curColor);
                newPositions.push_back(curPos);
                continue;
            }

            auto colorWithHueFrom = [](const SkPMColor4f& color, const SkPMColor4f& hueColor) {
                // If we have any powerless hue, then all colors are already in (some) polar space,
                // and they all store their hue in the red channel.
                return SkPMColor4f{hueColor.fR, color.fG, color.fB, color.fA};
            };

            // In each case, we might be copying a powerless (invalid) hue from the neighbor, but
            // that should be fine, as it will match that neighbor perfectly, and any hue is ok.
            if (i != 0) {
                newPositions.push_back(curPos);
                newColors.push_back(colorWithHueFrom(curColor, fColors[i - 1]));
            }
            if (i != colorCount - 1) {
                newPositions.push_back(curPos);
                newColors.push_back(colorWithHueFrom(curColor, fColors[i + 1]));
            }
        }

        fColors.swap(newColors);
        fPositionStorage.swap(newPositions);
        fPositions = fPositionStorage.data();
        colorCount = fColors.size();
    }

    // 4) For polar colors, adjust hue values to respect the hue method. We're using a trick here...
    //    The specification looks at adjacent colors, and adjusts one or the other. Because we store
    //    the stops in uniforms (and our backend conversions normalize the hue angle), we can
    //    instead always apply the adjustment to the *second* color. That lets us keep a running
    //    total, and do a single pass across all the colors to respect the requested hue method,
    //    without needing to do any extra work per-pixel.
    if (color_space_is_polar(interpolation.fColorSpace)) {
        float delta = 0;
        for (size_t i = 0; i < colorCount - 1; ++i) {
            float h1 = fColors[i].fR;
            float& h2 = fColors[i + 1].fR;
            h2 += delta;
            switch (interpolation.fHueMethod) {
                case HueMethod::kShorter:
                    if (h2 - h1 > 180) {
                        h2 -= 360;  // i.e. h1 += 360
                        delta -= 360;
                    } else if (h2 - h1 < -180) {
                        h2 += 360;
                        delta += 360;
                    }
                    break;
                case HueMethod::kLonger:
                    if ((i == 0 && shader->firstStopIsImplicit()) ||
                        (i == colorCount - 2 && shader->lastStopIsImplicit())) {
                        // Do nothing. We don't want to introduce a full revolution for these stops
                        // Full rationale at skbug.com/40044215
                    } else if (0 < h2 - h1 && h2 - h1 < 180) {
                        h2 -= 360;  // i.e. h1 += 360
                        delta -= 360;
                    } else if (-180 < h2 - h1 && h2 - h1 <= 0) {
                        h2 += 360;
                        delta += 360;
                    }
                    break;
                case HueMethod::kIncreasing:
                    if (h2 < h1) {
                        h2 += 360;
                        delta += 360;
                    }
                    break;
                case HueMethod::kDecreasing:
                    if (h1 < h2) {
                        h2 -= 360;  // i.e. h1 += 360;
                        delta -= 360;
                    }
                    break;
            }
        }
    }

    // 5) Apply premultiplication
    PremulColorProc premulFn = nullptr;
    if (static_cast<bool>(interpolation.fInPremul)) {
        switch (interpolation.fColorSpace) {
            case ColorSpace::kHSL:
            case ColorSpace::kHWB:
            case ColorSpace::kLCH:
            case ColorSpace::kOKLCH:
                premulFn = premul_polar;
                break;
            default:
                premulFn = premul_rgb;
                break;
        }
    }

    if (premulFn) {
        for (size_t i = 0; i < colorCount; ++i) {
            fColors[i] = premulFn(fColors[i]);
        }
    }

    // Ganesh requires that the positions be explicit (rather than implicitly evenly spaced)
    if (forceExplicitPositions && !fPositions) {
        fPositionStorage.reserve_exact(colorCount);
        float posScale = 1.0f / (colorCount - 1);
        for (size_t i = 0; i < colorCount; i++) {
            fPositionStorage.push_back(i * posScale);
        }
        fPositions = fPositionStorage.data();
    }
}

void SkGradientBaseShader::commonAsAGradient(GradientInfo* info) const {
    if (info) {
        const int colorCount = SkToInt(fColorCount);
        if (info->fColorCount >= colorCount) {
            if (info->fColors) {
                for (int i = 0; i < colorCount; ++i) {
                    info->fColors[i] = fColors[i];
                }
            }
            if (info->fColorOffsets) {
                for (int i = 0; i < colorCount; ++i) {
                    info->fColorOffsets[i] = this->getPos(i);
                }
            }
        }
        info->fColorCount = colorCount;
        info->fTileMode = fTileMode;
        info->fPremulInterp = this->interpolateInPremul();
    }
}

// Return true if these parameters are valid/legal/safe to construct a gradient
//
bool SkGradientBaseShader::ValidGradient(SkSpan<const SkColor4f> colors,
                                         SkTileMode tileMode,
                                         const Interpolation& interpolation) {
    return colors.data() && !colors.empty() && (unsigned)tileMode < kSkTileModeCount &&
           (unsigned)interpolation.fColorSpace < Interpolation::kColorSpaceCount &&
           (unsigned)interpolation.fHueMethod < Interpolation::kHueMethodCount;
}

static SkColor4f average_gradient_color(SkSpan<const SkColor4f> colors,
                                        SkSpan<const float> pos) {
    // The gradient is a piecewise linear interpolation between colors. For a given interval,
    // the integral between the two endpoints is 0.5 * (ci + cj) * (pj - pi), which provides that
    // intervals average color. The overall average color is thus the sum of each piece. The thing
    // to keep in mind is that the provided gradient definition may implicitly use p=0 and p=1.
    skvx::float4 blend(0.0f);
    for (size_t i = 0; i < colors.size() - 1; ++i) {
        // Calculate the average color for the interval between pos(i) and pos(i+1)
        auto c0 = skvx::float4::Load(&colors[i]);
        auto c1 = skvx::float4::Load(&colors[i + 1]);

        // when pos == null, there are colorCount uniformly distributed stops, going from 0 to 1,
        // so pos[i + 1] - pos[i] = 1/(colorCount-1)
        SkScalar w;
        if (!pos.empty()) {
            // Match position fixing in SkGradientShader's constructor, clamping positions outside
            // [0, 1] and forcing the sequence to be monotonic
            SkScalar p0 = SkTPin(pos[i], 0.f, 1.f);
            SkScalar p1 = SkTPin(pos[i + 1], p0, 1.f);
            w = p1 - p0;

            // And account for any implicit intervals at the start or end of the positions
            if (i == 0) {
                if (p0 > 0.0f) {
                    // The first color is fixed between p = 0 to pos[0], so 0.5*(ci + cj)*(pj - pi)
                    // becomes 0.5*(c + c)*(pj - 0) = c * pj
                    auto c = skvx::float4::Load(&colors[0]);
                    blend += p0 * c;
                }
            }
            if (i == colors.size() - 2) {
                if (p1 < 1.f) {
                    // The last color is fixed between pos[n-1] to p = 1, so 0.5*(ci + cj)*(pj - pi)
                    // becomes 0.5*(c + c)*(1 - pi) = c * (1 - pi)
                    auto c = skvx::float4::Load(&colors.back());
                    blend += (1.f - p1) * c;
                }
            }
        } else {
            w = 1.f / (colors.size() - 1);
        }

        blend += 0.5f * w * (c1 + c0);
    }

    SkColor4f avg;
    blend.store(&avg);
    return avg;
}

// Except for special circumstances of clamped gradients, every gradient shape--when degenerate--
// can be mapped to the same fallbacks. The specific shape factories must account for special
// clamped conditions separately, this will always return the last color for clamped gradients.
sk_sp<SkShader> SkGradientBaseShader::MakeDegenerateGradient(const SkGradient::Colors& c) {
    switch (c.tileMode()) {
        case SkTileMode::kDecal:
            // normally this would reject the area outside of the interpolation region, so since
            // inside region is empty when the radii are equal, the entire draw region is empty
            return SkShaders::Empty();
        case SkTileMode::kRepeat:
        case SkTileMode::kMirror:
            // repeat and mirror are treated the same: the border colors are never visible,
            // but approximate the final color as infinite repetitions of the colors, so
            // it can be represented as the average color of the gradient.
            return SkShaders::Color(average_gradient_color(c.colors(), c.positions()),
                                    c.colorSpace());
        case SkTileMode::kClamp:
            // Depending on how the gradient shape degenerates, there may be a more specialized
            // fallback representation for the factories to use, but this is a reasonable default.
            return SkShaders::Color(c.colors().back(), c.colorSpace());
    }
    SkDEBUGFAIL("Should not be reached");
    return nullptr;
}
