/*
 * 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 "SkPM4f.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include "SkColor.h"
#include "SkSize.h"
#include <tuple>
#include "SkLinearBitmapPipeline_core.h"
#include "SkLinearBitmapPipeline_matrix.h"
#include "SkLinearBitmapPipeline_tile.h"
#include "SkLinearBitmapPipeline_sample.h"

class SkLinearBitmapPipeline::PointProcessorInterface {
public:
    virtual ~PointProcessorInterface() { }
    // Take the first n (where 0 < n && n < 4) items from xs and ys and sample those points. For
    // nearest neighbor, that means just taking the floor xs and ys. For bilerp, this means
    // to expand the bilerp filter around the point and sample using that filter.
    virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0;
    // Same as pointListFew, but n = 4.
    virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0;
    // A span is a compact form of sample points that are obtained by mapping points from
    // destination space to source space. This is used for horizontal lines only, and is mainly
    // used to take advantage of memory coherence for horizontal spans.
    virtual void pointSpan(Span span) = 0;
};

class SkLinearBitmapPipeline::SampleProcessorInterface
    : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    // Used for nearest neighbor when scale factor is 1.0. The span can just be repeated with no
    // edge pixel alignment problems. This is for handling a very common case.
    virtual void repeatSpan(Span span, int32_t repeatCount) = 0;

    // The x's and y's are setup in the following order:
    // +--------+--------+
    // |        |        |
    // |  px00  |  px10  |
    // |    0   |    1   |
    // +--------+--------+
    // |        |        |
    // |  px01  |  px11  |
    // |    2   |    3   |
    // +--------+--------+
    // These pixels coordinates are arranged in the following order in xs and ys:
    // px00  px10  px01  px11
    virtual void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) = 0;

    // A span represents sample points that have been mapped from destination space to source
    // space. Each sample point is then expanded to the four bilerp points by add +/- 0.5. The
    // resulting Y values my be off the tile. When y +/- 0.5 are more than 1 apart because of
    // tiling, the second Y is used to denote the retiled Y value.
    virtual void bilerpSpan(Span span, SkScalar y) = 0;
};

class SkLinearBitmapPipeline::PixelPlacerInterface {
public:
    virtual ~PixelPlacerInterface() { }
    virtual void setDestination(SkPM4f* dst) = 0;
    virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
    virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0;
};

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)...}{ }

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

    void 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->Initialize<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->Initialize<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->Initialize<ScaleMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
            SkVector{inverse.getScaleX(), inverse.getScaleY()});
    } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) {
        matrixProc->Initialize<TranslateMatrix<>>(
            next,
            SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
    } else {
        return next;
    }
    return matrixProc->get();
}

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

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

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

    void 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;
        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 YStrategy, typename Next>
class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
    template <typename... Args>
    BilerpTileStage(Next* next, SkISize dimensions)
        : fXMax(dimensions.width())
        , fYMax(dimensions.height())
        , fNext{next}
        , fXStrategy{dimensions.width()}
        , fYStrategy{dimensions.height()}{ }

    void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        // TODO: check to see if xs and ys are in range then just call pointListFew on next.
        if (n >= 1) this->bilerpPoint(xs[0], ys[0]);
        if (n >= 2) this->bilerpPoint(xs[1], ys[1]);
        if (n >= 3) this->bilerpPoint(xs[2], ys[2]);
    }

    void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fXStrategy.tileXPoints(&xs);
        fYStrategy.tileYPoints(&ys);
        // TODO: check to see if xs and ys are in range then just call pointList4 on next.
        this->bilerpPoint(xs[0], ys[0]);
        this->bilerpPoint(xs[1], ys[1]);
        this->bilerpPoint(xs[2], ys[2]);
        this->bilerpPoint(xs[3], ys[3]);
    }

    struct Wrapper {
        void pointSpan(Span span) {
            processor->breakIntoEdges(span);
        }

        BilerpTileStage* processor;
    };

    // The span you pass must not be empty.
    void pointSpan(Span span) override {
        SkASSERT(!span.isEmpty());

        Wrapper wrapper = {this};
        if (!fXStrategy.maybeProcessSpan(span, &wrapper)) {
            span_fallback(span, this);
        }
    }

private:
    void bilerpPoint(SkScalar x, SkScalar y) {
        Sk4f txs = Sk4f{x} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f};
        Sk4f tys = Sk4f{y} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f};
        fXStrategy.tileXPoints(&txs);
        fYStrategy.tileYPoints(&tys);
        fNext->bilerpEdge(txs, tys);
    }

    void handleEdges(Span span, SkScalar dx) {
        SkPoint start; SkScalar length; int count;
        std::tie(start, length, count) = span;
        SkScalar x = X(start);
        SkScalar y = Y(start);
        SkScalar tiledY = fYStrategy.tileY(y);
        while (count > 0) {
            this->bilerpPoint(x, tiledY);
            x += dx;
            count -= 1;
        }
    }

    void yProcessSpan(Span span) {
        SkScalar tiledY = fYStrategy.tileY(span.startY());
        if (0.5f <= tiledY && tiledY < fYMax - 0.5f ) {
            Span tiledSpan{{span.startX(), tiledY}, span.length(), span.count()};
            fNext->pointSpan(tiledSpan);
        } else {
            // Convert to the Y0 bilerp sample set by shifting by -0.5f. Then tile that new y
            // value and shift it back resulting in the working Y0. Do the same thing with Y1 but
            // in the opposite direction.
            SkScalar y0 = fYStrategy.tileY(span.startY() - 0.5f) + 0.5f;
            SkScalar y1 = fYStrategy.tileY(span.startY() + 0.5f) - 0.5f;
            Span newSpan{{span.startX(), y0}, span.length(), span.count()};
            fNext->bilerpSpan(newSpan, y1);
        }
    }
    void breakIntoEdges(Span span) {
        if (span.length() == 0) {
            yProcessSpan(span);
        } else {
            SkScalar dx = span.length() / (span.count() - 1);
            if (span.length() > 0) {
                Span leftBorder = span.breakAt(0.5f, dx);
                if (!leftBorder.isEmpty()) {
                    this->handleEdges(leftBorder, dx);
                }
                Span center = span.breakAt(fXMax - 0.5f, dx);
                if (!center.isEmpty()) {
                    this->yProcessSpan(center);
                }

                if (!span.isEmpty()) {
                    this->handleEdges(span, dx);
                }
            } else {
                Span center = span.breakAt(fXMax + 0.5f, dx);
                if (!span.isEmpty()) {
                    this->handleEdges(span, dx);
                }
                Span leftEdge = center.breakAt(0.5f, dx);
                if (!center.isEmpty()) {
                    this->yProcessSpan(center);
                }
                if (!leftEdge.isEmpty()) {
                    this->handleEdges(leftEdge, dx);
                }

            }
        }
    }

    SkScalar fXMax;
    SkScalar fYMax;
    Next* const fNext;
    XStrategy fXStrategy;
    YStrategy fYStrategy;
};

template <typename XStrategy, typename YStrategy, typename Next>
void make_tile_stage(
    SkFilterQuality filterQuality, SkISize dimensions,
    Next* next, SkLinearBitmapPipeline::TileStage* tileStage) {
    if (filterQuality == kNone_SkFilterQuality) {
        tileStage->Initialize<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
    } else {
        tileStage->Initialize<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
    }
}
template <typename XStrategy>
void choose_tiler_ymode(
    SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions,
    SkLinearBitmapPipeline::SampleProcessorInterface* next,
    SkLinearBitmapPipeline::TileStage* tileStage) {
    switch (yMode) {
        case SkShader::kClamp_TileMode:
            make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions, next, tileStage);
            break;
        case SkShader::kRepeat_TileMode:
            make_tile_stage<XStrategy, YRepeatStrategy>(filterQuality, dimensions, next, tileStage);
            break;
        case SkShader::kMirror_TileMode:
            make_tile_stage<XStrategy, YMirrorStrategy>(filterQuality, dimensions, next, tileStage);
            break;
    }
};

static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler(
    SkLinearBitmapPipeline::SampleProcessorInterface* next,
    SkISize dimensions,
    SkShader::TileMode xMode,
    SkShader::TileMode yMode,
    SkFilterQuality filterQuality,
    SkLinearBitmapPipeline::TileStage* tileStage) {
    switch (xMode) {
        case SkShader::kClamp_TileMode:
            choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions, next, tileStage);
            break;
        case SkShader::kRepeat_TileMode:
            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();
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// Source Sampling Stage
template <typename SourceStrategy, typename Next>
class NearestNeighborSampler final : public SkLinearBitmapPipeline::SampleProcessorInterface {
public:
    template <typename... Args>
    NearestNeighborSampler(Next* next, Args&&... args)
    : fSampler{next, std::forward<Args>(args)...} { }

    void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fSampler.nearestListFew(n, xs, ys);
    }

    void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fSampler.nearestList4(xs, ys);
    }

    void pointSpan(Span span) override {
        fSampler.nearestSpan(span);
    }

    virtual void repeatSpan(Span span, int32_t repeatCount) override {
        while (repeatCount > 0) {
            fSampler.nearestSpan(span);
            repeatCount--;
        }
    }

    void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override {
        SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge.");
    }

    virtual void bilerpSpan(Span span, SkScalar y) override {
        SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan.");
    }

private:
    GeneralSampler<SourceStrategy, Next> fSampler;
};

template <typename SourceStrategy, typename Next>
class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterface {
public:
    template <typename... Args>
    BilerpSampler(Next* next, Args&&... args)
        : fSampler{next, std::forward<Args>(args)...} { }

    void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
        fSampler.bilerpListFew(n, xs, ys);
    }

    void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
        fSampler.bilerpList4(xs, ys);
    }

    void pointSpan(Span span) override {
        fSampler.bilerpSpan(span);
    }

    virtual void repeatSpan(Span span, int32_t repeatCount) override {
        while (repeatCount > 0) {
            fSampler.bilerpSpan(span);
            repeatCount--;
        }
    }

    void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override {
        fSampler.bilerpEdge(xs, ys);
    }

    virtual void bilerpSpan(Span span, SkScalar y) override {
        fSampler.bilerpSpanWithY(span, y);
    }

private:
    GeneralSampler<SourceStrategy, Next> fSampler;
};

using Placer = SkLinearBitmapPipeline::PixelPlacerInterface;

template<template <typename, typename> class Sampler>
static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_base(
    Placer* next,
    const SkPixmap& srcPixmap,
    SkLinearBitmapPipeline::SampleStage* sampleStage) {
    const SkImageInfo& imageInfo = srcPixmap.info();
    switch (imageInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
                sampleStage->Initialize<Sampler<Pixel8888SRGB, Placer>>(next, srcPixmap);
            } else {
                sampleStage->Initialize<Sampler<Pixel8888LRGB, Placer>>(next, srcPixmap);
            }
            break;
        case kBGRA_8888_SkColorType:
            if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
                sampleStage->Initialize<Sampler<Pixel8888SBGR, Placer>>(next, srcPixmap);
            } else {
                sampleStage->Initialize<Sampler<Pixel8888LBGR, Placer>>(next, srcPixmap);
            }
            break;
        case kIndex_8_SkColorType:
            if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
                sampleStage->Initialize<Sampler<PixelIndex8SRGB, Placer>>(next, srcPixmap);
            } else {
                sampleStage->Initialize<Sampler<PixelIndex8LRGB, Placer>>(next, srcPixmap);
            }
            break;
        default:
            SkFAIL("Not implemented. Unsupported src");
            break;
    }
    return sampleStage->get();
}

SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
    Placer* next,
    SkFilterQuality filterQuality,
    const SkPixmap& srcPixmap,
    SkLinearBitmapPipeline::SampleStage* sampleStage) {
    if (filterQuality == kNone_SkFilterQuality) {
        return choose_pixel_sampler_base<NearestNeighborSampler>(next, srcPixmap, sampleStage);
    } else {
        return choose_pixel_sampler_base<BilerpSampler>(next, srcPixmap, sampleStage);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Placement Stage
template <SkAlphaType alphaType>
class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface {
public:
    PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { }
    void VECTORCALL placePixel(Sk4f pixel) override {
        PlacePixel(fDst, pixel, 0);
        fDst += 1;
    }

    void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
        SkPM4f* dst = fDst;
        PlacePixel(dst, p0, 0);
        PlacePixel(dst, p1, 1);
        PlacePixel(dst, p2, 2);
        PlacePixel(dst, p3, 3);
        fDst += 4;
    }

    void setDestination(SkPM4f* dst) override {
        fDst = dst;
    }

private:
    void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) {
        Sk4f newPixel = pixel;
        if (alphaType == kUnpremul_SkAlphaType) {
            newPixel = Premultiply(pixel);
        }
        newPixel = newPixel * fPostAlpha;
        newPixel.store(dst + index);
    }
    static Sk4f VECTORCALL Premultiply(Sk4f pixel) {
        float alpha = pixel[3];
        return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
    }

    SkPM4f* fDst;
    Sk4f fPostAlpha;
};

static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer(
    SkAlphaType alphaType,
    float postAlpha,
    SkLinearBitmapPipeline::PixelStage* placerStage) {
    if (alphaType == kUnpremul_SkAlphaType) {
        placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
    } else {
        // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
        placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha);
    }
    return placerStage->get();
}
}  // namespace

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

SkLinearBitmapPipeline::SkLinearBitmapPipeline(
    const SkMatrix& inverse,
    SkFilterQuality filterQuality,
    SkShader::TileMode xTile, SkShader::TileMode yTile,
    float postAlpha,
    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())));
        }
    }

    // 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;
    }

    // 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 placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage);
    auto samplerStage   = choose_pixel_sampler(placementStage,
                                               filterQuality, srcPixmap, &fSampleStage);
    auto tilerStage     = choose_tiler(samplerStage,
                                       dimensions, xTile, yTile, filterQuality, &fTiler);
    fFirstStage         = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage);
}

void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
    SkASSERT(count > 0);
    fPixelStage->setDestination(dst);
    // 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});
}
