/*
 * 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/SkShader.h"
#include "include/private/SkColorData.h"
#include "include/private/SkColorData.h"
#include "src/core/SkCoreBlitters.h"
#include "src/core/SkXfermodePriv.h"

#include "include/private/SkNx.h"

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

static void D16_S32X_src_coverage(uint16_t dst[], const SkPMColor src[], int count,
                                  uint8_t coverage) {
    switch (coverage) {
        case 0: break;
        case 0xFF:
            for (int i = 0; i < count; ++i) {
                dst[i] = SkPixel32ToPixel16(src[i]);
            }
            break;
        default:
            unsigned scale = coverage + (coverage >> 7);
            for (int i = 0; i < count; ++i) {
                dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
            }
            break;
    }
}

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

static void D16_S32A_srcover_coverage(uint16_t dst[], const SkPMColor src[], int count,
                                      uint8_t coverage) {
    switch (coverage) {
        case 0: break;
        case 0xFF:
            for (int i = 0; i < count; ++i) {
                dst[i] = SkSrcOver32To16(src[i], dst[i]);
            }
            break;
        default:
            unsigned scale = coverage + (coverage >> 7);
            for (int i = 0; i < count; ++i) {
                dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
            }
            break;
    }
}

bool SkRGB565_Shader_Blitter::Supports(const SkPixmap& device, const SkPaint& paint) {
    if (device.colorType() != kRGB_565_SkColorType) {
        return false;
    }
    if (device.colorSpace()) {
        return false;
    }
    const auto bm = paint.asBlendMode();
    if (bm != SkBlendMode::kSrcOver && bm != SkBlendMode::kSrc) {
        return false;
    }
    if (paint.isDither()) {
        return false;
    }
    return true;
}

SkRGB565_Shader_Blitter::SkRGB565_Shader_Blitter(const SkPixmap& device,
        const SkPaint& paint, SkShaderBase::Context* shaderContext)
    : INHERITED(device, paint, shaderContext)
{
    SkASSERT(shaderContext);
    SkASSERT(Supports(device, paint));

    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));

    bool isOpaque = SkToBool(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag);

    if (paint.asBlendMode() == SkBlendMode::kSrc || isOpaque) {
        fBlend = D16_S32X_src;
        fBlendCoverage = D16_S32X_src_coverage;
    } else {    // srcover
        fBlend = isOpaque ? D16_S32X_src : D16_S32A_srcover;
        fBlendCoverage = isOpaque ? D16_S32X_src_coverage : D16_S32A_srcover_coverage;
    }
}

SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() {
    sk_free(fBuffer);
}

void SkRGB565_Shader_Blitter::blitH(int x, int y, int width) {
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());

    uint16_t* device = fDevice.writable_addr16(x, y);

    SkPMColor*  span = fBuffer;
    fShaderContext->shadeSpan(x, y, span, width);
    fBlend(device, span, width, 0xFF);
}

void SkRGB565_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha coverage[],
                                        const int16_t runs[]) {
    SkPMColor* span = fBuffer;
    uint16_t*  device = fDevice.writable_addr16(x, y);
    auto*      shaderContext = fShaderContext;

    for (;;) {
        int count = *runs;
        if (count <= 0) {
            break;
        }
        int aa = *coverage;
        if (aa) {
            shaderContext->shadeSpan(x, y, span, count);
            fBlendCoverage(device, span, count, aa);
        }
        device += count;
        runs += count;
        coverage += count;
        x += count;
    }
}
