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

#include "SkLinearBitmapPipeline.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <tuple>

#include "SkLinearBitmapPipeline_core.h"
#include "SkLinearBitmapPipeline_matrix.h"
#include "SkLinearBitmapPipeline_tile.h"
#include "SkLinearBitmapPipeline_sample.h"
#include "SkNx.h"
#include "SkOpts.h"
#include "SkPM4f.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline::Stage
template<typename Base, size_t kSize, typename Next>
SkLinearBitmapPipeline::Stage<Base, kSize, Next>::~Stage() {
    if (fIsInitialized) {
        this->get()->~Base();
    }
}

template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Args&& ... args) {
    SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
              "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));

    new (&fSpace) Variant(next, std::forward<Args>(args)...);
    fStageCloner = [this](Next* nextClone, void* addr) {
        new (addr) Variant(nextClone, (const Variant&)*this->get());
    };
    fIsInitialized = true;
};

template<typename Base, size_t kSize, typename Next>
template<typename Variant, typename... Args>
void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(Args&& ... args) {
    SkASSERTF(sizeof(Variant) <= sizeof(fSpace),
              "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace));
    new (&fSpace) Variant(std::forward<Args>(args)...);
    fIsInitialized = true;
};

template<typename Base, size_t kSize, typename Next>
template <typename To, typename From>
To* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::getInterface() {
    From* down = static_cast<From*>(this->get());
    return static_cast<To*>(down);
}

template<typename Base, size_t kSize, typename Next>
Base* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::cloneStageTo(
    Next* next, Stage* cloneToStage) const
{
    if (!fIsInitialized) return nullptr;
    fStageCloner(next, &cloneToStage->fSpace);
    return cloneToStage->get();
}

namespace  {

////////////////////////////////////////////////////////////////////////////////////////////////////
// Matrix Stage
// PointProcessor uses a strategy to help complete the work of the different stages. The strategy
// must implement the following methods:
// * processPoints(xs, ys) - must mutate the xs and ys for the stage.
// * maybeProcessSpan(span, next) - This represents a horizontal series of pixels
//   to work over.
//   span - encapsulation of span.
//   next - a pointer to the next stage.
//   maybeProcessSpan - returns false if it can not process the span and needs to fallback to
//                      point lists for processing.
template<typename Strategy, typename Next>
class MatrixStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    template <typename... Args>
    MatrixStage(Next* next, Args&&... args)
        : fNext{next}
        , fStrategy{std::forward<Args>(args)...}{ }

    MatrixStage(Next* next, const MatrixStage& stage)
        : fNext{next}
        , fStrategy{stage.fStrategy} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fStrategy.processPoints(&xs, &ys);
        fNext->pointListFew(n, xs, ys);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fStrategy.processPoints(&xs, &ys);
        fNext->pointList4(xs, ys);
    }

    // The span you pass must not be empty.
    void pointSpan(Span span) override {
        SkASSERT(!span.isEmpty());
        if (!fStrategy.maybeProcessSpan(span, fNext)) {
            span_fallback(span, this);
        }
    }

private:
    Next* const fNext;
    Strategy fStrategy;
};

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using TranslateMatrix = MatrixStage<TranslateMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using ScaleMatrix = MatrixStage<ScaleMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using AffineMatrix = MatrixStage<AffineMatrixStrategy, Next>;

template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
using PerspectiveMatrix = MatrixStage<PerspectiveMatrixStrategy, Next>;


static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
    SkLinearBitmapPipeline::PointProcessorInterface* next,
    const SkMatrix& inverse,
    SkLinearBitmapPipeline::MatrixStage* matrixProc) {
    if (inverse.hasPerspective()) {
        matrixProc->initStage<PerspectiveMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()},
            SkVector{inverse.getSkewX(), inverse.getSkewY()},
            SkVector{inverse.getPerspX(), inverse.getPerspY()},
            inverse.get(SkMatrix::kMPersp2));
    } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
        matrixProc->initStage<AffineMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()},
            SkVector{inverse.getSkewX(), inverse.getSkewY()});
    } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
        matrixProc->initStage<ScaleMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()});
    } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) {
        matrixProc->initStage<TranslateMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
    } else {
        return next;
    }
    return matrixProc->get();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Tile Stage

template<typename XStrategy, typename YStrategy, typename Next>
class CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    CombinedTileStage(Next* next, SkISize dimensions)
        : fNext{next}
        , fXStrategy{dimensions.width()}
        , fYStrategy{dimensions.height()}{ }

    CombinedTileStage(Next* next, const CombinedTileStage& stage)
        : fNext{next}
        , fXStrategy{stage.fXStrategy}
        , fYStrategy{stage.fYStrategy} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        fNext->pointListFew(n, xs, ys);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        fNext->pointList4(xs, ys);
    }

    // The span you pass must not be empty.
    void pointSpan(Span span) override {
        SkASSERT(!span.isEmpty());
        SkPoint start; SkScalar length; int count;
        std::tie(start, length, count) = span;

        if (span.count() == 1) {
            // DANGER:
            // The explicit casts from float to Sk4f are not usually necessary, but are here to
            // work around an MSVC 2015u2 c++ code generation bug. This is tracked using skia bug
            // 5566.
            this->pointListFew(1, Sk4f{span.startX()}, Sk4f{span.startY()});
            return;
        }

        SkScalar x = X(start);
        SkScalar y = fYStrategy.tileY(Y(start));
        Span yAdjustedSpan{{x, y}, length, count};

        if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) {
            span_fallback(span, this);
        }
    }

private:
    Next* const fNext;
    XStrategy fXStrategy;
    YStrategy fYStrategy;
};

template <typename XStrategy, typename Next>
void choose_tiler_ymode(
    SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions,
    Next* next,
    SkLinearBitmapPipeline::TileStage* tileStage) {
    switch (yMode) {
        case SkShader::kClamp_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YClampStrategy, Next>;
            tileStage->initStage<Tiler>(next, dimensions);
            break;
        }
        case SkShader::kRepeat_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, Next>;
            tileStage->initStage<Tiler>(next, dimensions);
            break;
        }
        case SkShader::kMirror_TileMode: {
            using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, Next>;
            tileStage->initStage<Tiler>(next, dimensions);
            break;
        }
    }
};

static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler(
    SkLinearBitmapPipeline::SampleProcessorInterface* next,
    SkISize dimensions,
    SkShader::TileMode xMode,
    SkShader::TileMode yMode,
    SkFilterQuality filterQuality,
    SkScalar dx,
    SkLinearBitmapPipeline::TileStage* tileStage)
{
    switch (xMode) {
        case SkShader::kClamp_TileMode:
            choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions, next, tileStage);
            break;
        case SkShader::kRepeat_TileMode:
            if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) {
                choose_tiler_ymode<XRepeatUnitScaleStrategy>(
                    yMode, kNone_SkFilterQuality, dimensions, next, tileStage);
            } else {
                choose_tiler_ymode<XRepeatStrategy>(
                    yMode, filterQuality, dimensions, next, tileStage);
            }
            break;
        case SkShader::kMirror_TileMode:
            choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions, next, tileStage);
            break;
    }

    return tileStage->get();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Specialized Samplers

// RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the src and destination
// are the same format and do not need in transformations in pixel space. Therefore, there is no
// need to convert them to HiFi pixel format.
class RGBA8888UnitRepeatSrc final : public SkLinearBitmapPipeline::SampleProcessorInterface,
                                    public SkLinearBitmapPipeline::DestinationInterface {
public:
    RGBA8888UnitRepeatSrc(const uint32_t* src, int32_t width)
        : fSrc{src}, fWidth{width} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + n <= fEnd);
        // At this point xs and ys should be >= 0, so trunc is the same as floor.
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);

        if (n >= 1) *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
        if (n >= 2) *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
        if (n >= 3) *fDest++ = *this->pixelAddress(iXs[2], iYs[2]);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + 4 <= fEnd);
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);
        *fDest++ = *this->pixelAddress(iXs[0], iYs[0]);
        *fDest++ = *this->pixelAddress(iXs[1], iYs[1]);
        *fDest++ = *this->pixelAddress(iXs[2], iYs[2]);
        *fDest++ = *this->pixelAddress(iXs[3], iYs[3]);
    }

    void pointSpan(Span span) override {
        SkASSERT(fDest + span.count() <= fEnd);
        if (span.length() != 0.0f) {
            int32_t x = SkScalarTruncToInt(span.startX());
            int32_t y = SkScalarTruncToInt(span.startY());
            const uint32_t* src = this->pixelAddress(x, y);
            memmove(fDest, src, span.count() * sizeof(uint32_t));
            fDest += span.count();
        }
    }

    void repeatSpan(Span span, int32_t repeatCount) override {
        SkASSERT(fDest + span.count() * repeatCount <= fEnd);

        int32_t x = SkScalarTruncToInt(span.startX());
        int32_t y = SkScalarTruncToInt(span.startY());
        const uint32_t* src = this->pixelAddress(x, y);
        uint32_t* dest = fDest;
        while (repeatCount --> 0) {
            memmove(dest, src, span.count() * sizeof(uint32_t));
            dest += span.count();
        }
        fDest = dest;
    }

    void setDestination(void* dst, int count) override  {
        fDest = static_cast<uint32_t*>(dst);
        fEnd = fDest + count;
    }

private:
    const uint32_t* pixelAddress(int32_t x, int32_t y) {
        return &fSrc[fWidth * y + x];
    }
    const uint32_t* const fSrc;
    const int32_t         fWidth;
    uint32_t*             fDest;
    uint32_t*             fEnd;
};

// RGBA8888UnitRepeatSrc - A sampler that takes advantage of the fact the the src and destination
// are the same format and do not need in transformations in pixel space. Therefore, there is no
// need to convert them to HiFi pixel format.
class RGBA8888UnitRepeatSrcOver final : public SkLinearBitmapPipeline::SampleProcessorInterface,
                                        public SkLinearBitmapPipeline::DestinationInterface {
public:
    RGBA8888UnitRepeatSrcOver(const uint32_t* src, int32_t width)
        : fSrc{src}, fWidth{width} { }

    void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + n <= fEnd);
        // At this point xs and ys should be >= 0, so trunc is the same as floor.
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);

        if (n >= 1) blendPixelAt(iXs[0], iYs[0]);
        if (n >= 2) blendPixelAt(iXs[1], iYs[1]);
        if (n >= 3) blendPixelAt(iXs[2], iYs[2]);
    }

    void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        SkASSERT(fDest + 4 <= fEnd);
        Sk4i iXs = SkNx_cast<int>(xs);
        Sk4i iYs = SkNx_cast<int>(ys);
        blendPixelAt(iXs[0], iYs[0]);
        blendPixelAt(iXs[1], iYs[1]);
        blendPixelAt(iXs[2], iYs[2]);
        blendPixelAt(iXs[3], iYs[3]);
    }

    void pointSpan(Span span) override {
        if (span.length() != 0.0f) {
            this->repeatSpan(span, 1);
        }
    }

    void repeatSpan(Span span, int32_t repeatCount) override {
        SkASSERT(fDest + span.count() * repeatCount <= fEnd);
        SkASSERT(span.count() > 0);
        SkASSERT(repeatCount > 0);

        int32_t x = (int32_t)span.startX();
        int32_t y = (int32_t)span.startY();
        const uint32_t* beginSpan = this->pixelAddress(x, y);

        SkOpts::srcover_srgb_srgb(fDest, beginSpan, span.count() * repeatCount, span.count());

        fDest += span.count() * repeatCount;

        SkASSERT(fDest <= fEnd);
    }

    void setDestination(void* dst, int count) override  {
        SkASSERT(count > 0);
        fDest = static_cast<uint32_t*>(dst);
        fEnd = fDest + count;
    }

private:
    const uint32_t* pixelAddress(int32_t x, int32_t y) {
        return &fSrc[fWidth * y + x];
    }

    void blendPixelAt(int32_t x, int32_t y) {
        const uint32_t* src = this->pixelAddress(x, y);
        SkOpts::srcover_srgb_srgb(fDest, src, 1, 1);
        fDest += 1;
    };

    const uint32_t* const fSrc;
    const int32_t         fWidth;
    uint32_t*             fDest;
    uint32_t*             fEnd;
};

using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;

template <SkColorType colorType>
static SkLinearBitmapPipeline::PixelAccessorInterface* choose_specific_accessor(
    const SkPixmap& srcPixmap, SkLinearBitmapPipeline::Accessor* accessor)
{
    if (srcPixmap.info().gammaCloseToSRGB()) {
        using PA = PixelAccessor<colorType, kSRGB_SkGammaType>;
        accessor->init<PA>(srcPixmap);
        return accessor->get();
    } else {
        using PA = PixelAccessor<colorType, kLinear_SkGammaType>;
        accessor->init<PA>(srcPixmap);
        return accessor->get();
    }
}

static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor(
    const SkPixmap& srcPixmap,
    const SkColor A8TintColor,
    SkLinearBitmapPipeline::Accessor* accessor)
{
    const SkImageInfo& imageInfo = srcPixmap.info();

    SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr;
    switch (imageInfo.colorType()) {
        case kAlpha_8_SkColorType: {
                using PA = PixelAccessor<kAlpha_8_SkColorType, kLinear_SkGammaType>;
                accessor->init<PA>(srcPixmap, A8TintColor);
                pixelAccessor = accessor->get();
            }
            break;
        case kARGB_4444_SkColorType:
            pixelAccessor = choose_specific_accessor<kARGB_4444_SkColorType>(srcPixmap, accessor);
            break;
        case kRGB_565_SkColorType:
            pixelAccessor = choose_specific_accessor<kRGB_565_SkColorType>(srcPixmap, accessor);
            break;
        case kRGBA_8888_SkColorType:
            pixelAccessor = choose_specific_accessor<kRGBA_8888_SkColorType>(srcPixmap, accessor);
            break;
        case kBGRA_8888_SkColorType:
            pixelAccessor = choose_specific_accessor<kBGRA_8888_SkColorType>(srcPixmap, accessor);
            break;
        case kIndex_8_SkColorType:
            pixelAccessor = choose_specific_accessor<kIndex_8_SkColorType>(srcPixmap, accessor);
            break;
        case kGray_8_SkColorType:
            pixelAccessor = choose_specific_accessor<kGray_8_SkColorType>(srcPixmap, accessor);
            break;
        case kRGBA_F16_SkColorType: {
                using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaType>;
                accessor->init<PA>(srcPixmap);
                pixelAccessor = accessor->get();
            }
            break;
        default:
            SkFAIL("Not implemented. Unsupported src");
            break;
    }

    return pixelAccessor;
}

SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
    Blender* next,
    SkFilterQuality filterQuality,
    SkShader::TileMode xTile, SkShader::TileMode yTile,
    const SkPixmap& srcPixmap,
    const SkColor A8TintColor,
    SkLinearBitmapPipeline::SampleStage* sampleStage,
    SkLinearBitmapPipeline::Accessor* accessor) {
    const SkImageInfo& imageInfo = srcPixmap.info();
    SkISize dimensions = imageInfo.dimensions();

    // Special case samplers with fully expanded templates
    if (imageInfo.gammaCloseToSRGB()) {
        if (filterQuality == kNone_SkFilterQuality) {
            switch (imageInfo.colorType()) {
                case kN32_SkColorType: {
                    using S =
                    NearestNeighborSampler<
                        PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
                    sampleStage->initStage<S>(next, srcPixmap);
                    return sampleStage->get();
                }
                case kIndex_8_SkColorType: {
                    using S =
                    NearestNeighborSampler<
                        PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
                    sampleStage->initStage<S>(next, srcPixmap);
                    return sampleStage->get();
                }
                default:
                    break;
            }
        } else {
            switch (imageInfo.colorType()) {
                case kN32_SkColorType: {
                    using S =
                    BilerpSampler<
                        PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
                    sampleStage->initStage<S>(next, dimensions, xTile, yTile, srcPixmap);
                    return sampleStage->get();
                }
                case kIndex_8_SkColorType: {
                    using S =
                    BilerpSampler<
                        PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
                    sampleStage->initStage<S>(next, dimensions, xTile, yTile, srcPixmap);
                    return sampleStage->get();
                }
                default:
                    break;
            }
        }
    }

    auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor);
    // General cases.
    if (filterQuality == kNone_SkFilterQuality) {
        using S = NearestNeighborSampler<PixelAccessorShim, Blender>;
        sampleStage->initStage<S>(next, pixelAccessor);
    } else {
        using S = BilerpSampler<PixelAccessorShim, Blender>;
        sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor);
    }
    return sampleStage->get();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Blender Stage
template <SkAlphaType alphaType>
class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface {
public:
    SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
    SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {}
    void SK_VECTORCALL blendPixel(Sk4f pixel) override {
        SkASSERT(fDst + 1 <= fEnd );
        this->srcPixel(fDst, pixel, 0);
        fDst += 1;
    }

    void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
        SkASSERT(fDst + 4 <= fEnd);
        SkPM4f* dst = fDst;
        this->srcPixel(dst, p0, 0);
        this->srcPixel(dst, p1, 1);
        this->srcPixel(dst, p2, 2);
        this->srcPixel(dst, p3, 3);
        fDst += 4;
    }

    void setDestination(void* dst, int count) override {
        fDst = static_cast<SkPM4f*>(dst);
        fEnd = fDst + count;
    }

private:
    void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) {
        check_pixel(pixel);

        Sk4f newPixel = pixel;
        if (alphaType == kUnpremul_SkAlphaType) {
            newPixel = Premultiply(pixel);
        }
        newPixel = newPixel * fPostAlpha;
        newPixel.store(dst + index);
    }
    static Sk4f SK_VECTORCALL Premultiply(Sk4f pixel) {
        float alpha = pixel[3];
        return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
    }

    SkPM4f* fDst;
    SkPM4f* fEnd;
    Sk4f fPostAlpha;
};

static SkLinearBitmapPipeline::BlendProcessorInterface* choose_blender_for_shading(
    SkAlphaType alphaType,
    float postAlpha,
    SkLinearBitmapPipeline::BlenderStage* blenderStage) {
    if (alphaType == kUnpremul_SkAlphaType) {
        blenderStage->initSink<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
    } else {
        // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
        blenderStage->initSink<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha);
    }
    return blenderStage->get();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkLinearBitmapPipeline
SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {}

SkLinearBitmapPipeline::SkLinearBitmapPipeline(
    const SkMatrix& inverse,
    SkFilterQuality filterQuality,
    SkShader::TileMode xTile, SkShader::TileMode yTile,
    SkColor paintColor,
    const SkPixmap& srcPixmap)
{
    SkISize dimensions = srcPixmap.info().dimensions();
    const SkImageInfo& srcImageInfo = srcPixmap.info();

    SkMatrix adjustedInverse = inverse;
    if (filterQuality == kNone_SkFilterQuality) {
        if (inverse.getScaleX() >= 0.0f) {
            adjustedInverse.setTranslateX(
                nextafterf(inverse.getTranslateX(), std::floor(inverse.getTranslateX())));
        }
        if (inverse.getScaleY() >= 0.0f) {
            adjustedInverse.setTranslateY(
                nextafterf(inverse.getTranslateY(), std::floor(inverse.getTranslateY())));
        }
    }

    SkScalar dx = adjustedInverse.getScaleX();

    // If it is an index 8 color type, the sampler converts to unpremul for better fidelity.
    SkAlphaType alphaType = srcImageInfo.alphaType();
    if (srcPixmap.colorType() == kIndex_8_SkColorType) {
        alphaType = kUnpremul_SkAlphaType;
    }

    float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f);
    // As the stages are built, the chooser function may skip a stage. For example, with the
    // identity matrix, the matrix stage is skipped, and the tilerStage is the first stage.
    auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlenderStage);
    auto samplerStage = choose_pixel_sampler(
        blenderStage, filterQuality, xTile, yTile,
        srcPixmap, paintColor, &fSampleStage, &fAccessor);
    auto tilerStage   = choose_tiler(samplerStage, dimensions, xTile, yTile,
                                     filterQuality, dx, &fTileStage);
    fFirstStage       = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage);
    fLastStage        = blenderStage;
}

bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
    SkEmbeddableLinearPipeline* pipelineStorage,
    const SkLinearBitmapPipeline& pipeline,
    SkMatrix::TypeMask matrixMask,
    SkShader::TileMode xTileMode,
    SkShader::TileMode yTileMode,
    SkFilterQuality filterQuality,
    const SkPixmap& srcPixmap,
    float finalAlpha,
    SkXfermode::Mode xferMode,
    const SkImageInfo& dstInfo)
{
    if (xferMode == SkXfermode::kSrcOver_Mode
        && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
        xferMode = SkXfermode::kSrc_Mode;
    }

    if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; }
    if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; }
    if (finalAlpha != 1.0f) { return false; }
    if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType
        || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; }

    if (!srcPixmap.info().gammaCloseToSRGB() || !dstInfo.gammaCloseToSRGB()) {
        return false;
    }

    if (xferMode != SkXfermode::kSrc_Mode && xferMode != SkXfermode::kSrcOver_Mode) {
        return false;
    }

    pipelineStorage->init(pipeline, srcPixmap, xferMode, dstInfo);

    return true;
}

SkLinearBitmapPipeline::SkLinearBitmapPipeline(
    const SkLinearBitmapPipeline& pipeline,
    const SkPixmap& srcPixmap,
    SkXfermode::Mode mode,
    const SkImageInfo& dstInfo)
{
    SkASSERT(mode == SkXfermode::kSrc_Mode || mode == SkXfermode::kSrcOver_Mode);
    SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
             && srcPixmap.info().colorType() == kRGBA_8888_SkColorType);

    if (mode == SkXfermode::kSrc_Mode) {
        fSampleStage.initSink<RGBA8888UnitRepeatSrc>(
            srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
        fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRepeatSrc>();
    } else {
        fSampleStage.initSink<RGBA8888UnitRepeatSrcOver>(
            srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
        fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRepeatSrcOver>();
    }

    auto sampleStage = fSampleStage.get();
    auto tilerStage = pipeline.fTileStage.cloneStageTo(sampleStage, &fTileStage);
    tilerStage = (tilerStage != nullptr) ? tilerStage : sampleStage;
    auto matrixStage = pipeline.fMatrixStage.cloneStageTo(tilerStage, &fMatrixStage);
    matrixStage = (matrixStage != nullptr) ? matrixStage : tilerStage;
    fFirstStage = matrixStage;
}

void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
    SkASSERT(count > 0);
    this->blitSpan(x, y, dst, count);
}

void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) {
    SkASSERT(count > 0);
    fLastStage->setDestination(dst, count);

    // The count and length arguments start out in a precise relation in order to keep the
    // math correct through the different stages. Count is the number of pixel to produce.
    // Since the code samples at pixel centers, length is the distance from the center of the
    // first pixel to the center of the last pixel. This implies that length is count-1.
    fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count});
}
