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

#include "include/core/SkColorFilter.h"
#include "include/core/SkPaint.h"
#include "include/private/SkColorData.h"
#include "include/private/SkTemplates.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkBlitRow.h"
#include "src/core/SkSpriteBlitter.h"
#include "src/core/SkXfermodePriv.h"

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

static void S32_src(uint16_t dst[], const SkPMColor src[], int count) {
    for (int i = 0; i < count; ++i) {
        dst[i] = SkPixel32ToPixel16(src[i]);
    }
}

static void S32_srcover(uint16_t dst[], const SkPMColor src[], int count) {
    for (int i = 0; i < count; ++i) {
        dst[i] = SkSrcOver32To16(src[i], dst[i]);
    }
}

class Sprite_D16_S32 : public SkSpriteBlitter {
public:
    Sprite_D16_S32(const SkPixmap& src, SkBlendMode mode)  : INHERITED(src) {
        SkASSERT(src.colorType() == kN32_SkColorType);
        SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);

        fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque();
    }

    void blitRect(int x, int y, int width, int height) override {
        SkASSERT(width > 0 && height > 0);
        uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y);
        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
        size_t dstRB = fDst.rowBytes();
        size_t srcRB = fSource.rowBytes();

        do {
            if (fUseSrcOver) {
                S32_srcover(dst, src, width);
            } else {
                S32_src(dst, src, width);
            }

            dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
        } while (--height != 0);
    }

private:
    bool fUseSrcOver;

    using INHERITED = SkSpriteBlitter;
};

SkSpriteBlitter* SkSpriteBlitter::ChooseL565(const SkPixmap& source, const SkPaint& paint,
                                             SkArenaAlloc* allocator) {
    SkASSERT(allocator != nullptr);

    if (paint.getColorFilter() != nullptr) {
        return nullptr;
    }
    if (paint.getMaskFilter() != nullptr) {
        return nullptr;
    }

    U8CPU alpha = paint.getAlpha();
    if (alpha != 0xFF) {
        return nullptr;
    }

    const auto bm = paint.asBlendMode();
    if ((source.colorType() == kN32_SkColorType) && bm) {
        switch (bm.value()) {
            case SkBlendMode::kSrc:
            case SkBlendMode::kSrcOver:
                return allocator->make<Sprite_D16_S32>(source, bm.value());
            default:
                break;
        }
    }
    return nullptr;
}

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

static unsigned div255(unsigned a, unsigned b) {
    return (a * b * 257 + 127) >> 16;
}

static void S32_src_da8(uint8_t dst[], const SkPMColor src[], int count) {
    for (int i = 0; i < count; ++i) {
        dst[i] = SkGetPackedA32(src[i]);
    }
}

static void S32_srcover_da8(uint8_t dst[], const SkPMColor src[], int count) {
    for (int i = 0; i < count; ++i) {
        SkPMColor c = src[i];
        if (c) {
            unsigned a = SkGetPackedA32(c);
            if (a == 0xFF) {
                dst[i] = 0xFF;
            } else {
                dst[i] = a + div255(255 - a, dst[i]);
            }
        }
    }
}

class Sprite_D8_S32 : public SkSpriteBlitter {
public:
    Sprite_D8_S32(const SkPixmap& src, SkBlendMode mode)  : INHERITED(src) {
        SkASSERT(src.colorType() == kN32_SkColorType);
        SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);

        fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque();
    }

    void blitRect(int x, int y, int width, int height) override {
        SkASSERT(width > 0 && height > 0);
        uint8_t* SK_RESTRICT dst = fDst.writable_addr8(x, y);
        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
        size_t dstRB = fDst.rowBytes();
        size_t srcRB = fSource.rowBytes();

        do {
            if (fUseSrcOver) {
                S32_srcover_da8(dst, src, width);
            } else {
                S32_src_da8(dst, src, width);
            }

            dst = (uint8_t* SK_RESTRICT)((char*)dst + dstRB);
            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
        } while (--height != 0);
    }

private:
    bool fUseSrcOver;

    using INHERITED = SkSpriteBlitter;
};

SkSpriteBlitter* SkSpriteBlitter::ChooseLA8(const SkPixmap& source, const SkPaint& paint,
                                            SkArenaAlloc* allocator) {
    SkASSERT(allocator != nullptr);

    if (paint.getColorFilter() != nullptr) {
        return nullptr;
    }
    if (paint.getMaskFilter() != nullptr) {
        return nullptr;
    }

    U8CPU alpha = paint.getAlpha();
    if (alpha != 0xFF) {
        return nullptr;
    }

    const auto bm = paint.asBlendMode();
    if ((source.colorType() == kN32_SkColorType) && bm) {
        switch (bm.value()) {
            case SkBlendMode::kSrc:
            case SkBlendMode::kSrcOver:
                return allocator->make<Sprite_D8_S32>(source, bm.value());
            default:
                break;
        }
    }
    return nullptr;
}
