/*
 * 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 "src/utils/SkUTF.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;
    }
    if (paint.getBlendMode() != SkBlendMode::kSrcOver &&
        paint.getBlendMode() != 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.getBlendMode() == 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;
    }
}
