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

#include "GrBlend.h"

static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) {
    switch (coeff) {
        case kDC_GrBlendCoeff:
            return kSC_GrBlendCoeff;
        case kIDC_GrBlendCoeff:
            return kISC_GrBlendCoeff;
        case kDA_GrBlendCoeff:
            return kSA_GrBlendCoeff;
        case kIDA_GrBlendCoeff:
            return kISA_GrBlendCoeff;
        case kSC_GrBlendCoeff:
            return kDC_GrBlendCoeff;
        case kISC_GrBlendCoeff:
            return kIDC_GrBlendCoeff;
        case kSA_GrBlendCoeff:
            return kDA_GrBlendCoeff;
        case kISA_GrBlendCoeff:
            return kIDA_GrBlendCoeff;
        default:
            return coeff;
    }
}

static inline unsigned saturated_add(unsigned a, unsigned b) {
    SkASSERT(a <= 255);
    SkASSERT(b <= 255);
    unsigned sum = a + b;
    if (sum > 255) {
        sum = 255;
    }
    return sum;
}

static GrColor add_colors(GrColor src, GrColor dst) {
    unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst));
    unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst));
    unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst));
    unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst));
    return GrColorPackRGBA(r, g, b, a);
}

static inline bool valid_color(uint32_t compFlags) {
     return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags;
}

static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff,
                                   GrColor srcColor, uint32_t srcCompFlags,
                                   GrColor dstColor, uint32_t dstCompFlags,
                                   GrColor constantColor) {

    SkASSERT(!GrBlendCoeffRefsSrc(*srcCoeff));
    SkASSERT(srcCoeff);

    // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs.
    // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color,
    // if possible, below but that is not implemented now.
    switch (*srcCoeff) {
        case kIDC_GrBlendCoeff:
            dstColor = ~dstColor; // fallthrough
        case kDC_GrBlendCoeff:
            if (valid_color(dstCompFlags)) {
                if (0xffffffff == dstColor) {
                    *srcCoeff = kOne_GrBlendCoeff;
                } else if (0 == dstColor) {
                    *srcCoeff = kZero_GrBlendCoeff;
                }
            }
            break;

        case kIDA_GrBlendCoeff:
            dstColor = ~dstColor; // fallthrough
        case kDA_GrBlendCoeff:
            if (kA_GrColorComponentFlag & dstCompFlags) {
                if (0xff == GrColorUnpackA(dstColor)) {
                    *srcCoeff = kOne_GrBlendCoeff;
                } else if (0 == GrColorUnpackA(dstColor)) {
                    *srcCoeff = kZero_GrBlendCoeff;
                }
            }
            break;

        case kIConstC_GrBlendCoeff:
            constantColor = ~constantColor; // fallthrough
        case kConstC_GrBlendCoeff:
            if (0xffffffff == constantColor) {
                *srcCoeff = kOne_GrBlendCoeff;
            } else if (0 == constantColor) {
                *srcCoeff = kZero_GrBlendCoeff;
            }
            break;

        case kIConstA_GrBlendCoeff:
            constantColor = ~constantColor; // fallthrough
        case kConstA_GrBlendCoeff:
            if (0xff == GrColorUnpackA(constantColor)) {
                *srcCoeff = kOne_GrBlendCoeff;
            } else if (0 == GrColorUnpackA(constantColor)) {
                *srcCoeff = kZero_GrBlendCoeff;
            }
            break;

        default:
            break;
    }
    // We may have invalidated these above and shouldn't read them again.
    SkDEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;)

    if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) {
        *srcCoeff = kZero_GrBlendCoeff;
        return 0;
    }

    if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) {
        return srcColor;
    } else {
        return GrColor_ILLEGAL;
    }
}

GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff,
                        GrBlendCoeff* dstCoeff,
                        GrColor srcColor, uint32_t srcCompFlags,
                        GrColor dstColor, uint32_t dstCompFlags,
                        GrColor constantColor) {
    GrColor srcTermColor = simplify_blend_term(srcCoeff,
                                               srcColor, srcCompFlags,
                                               dstColor, dstCompFlags,
                                               constantColor);

    // We call the same function to simplify the dst blend coeff. We trick it out by swapping the
    // src and dst.
    GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff);
    GrColor dstTermColor = simplify_blend_term(&spoofedCoeff,
                                               dstColor, dstCompFlags,
                                               srcColor, srcCompFlags,
                                               constantColor);
    *dstCoeff = swap_coeff_src_dst(spoofedCoeff);

    if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) {
        return add_colors(srcTermColor, dstTermColor);
    } else {
        return GrColor_ILLEGAL;
    }
}
