/*
* Copyright 2015 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"
#include "../private/GrColor.h"

/**
 * MaskedColor is used to evaluate the color and valid color component flags through the
 * blending equation. Could possibly extend this to be used more broadly.
 */
class MaskedColor {
public:
    MaskedColor(GrColor color, GrColorComponentFlags flags)
        : fColor(color)
        , fFlags(flags) {}

    MaskedColor() {}

    void set(GrColor color, GrColorComponentFlags flags) {
        fColor = color;
        fFlags = flags;
    }

    static MaskedColor Invert(const MaskedColor& in) {
        return MaskedColor(GrInvertColor(in.fColor), in.fFlags);
    }

    static MaskedColor ExtractAlpha(const MaskedColor& in) {
        GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
            kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
        return MaskedColor(GrColorPackA4(GrColorUnpackA(in.fColor)), flags);
    }

    static MaskedColor ExtractInverseAlpha(const MaskedColor& in) {
        GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
            kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
        return MaskedColor(GrColorPackA4(0xFF - GrColorUnpackA(in.fColor)), flags);
    }

    static MaskedColor Mul(const MaskedColor& a, const MaskedColor& b) {
        GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0) |
                                         b.componentsWithValue(0);
        return MaskedColor(GrColorMul(a.fColor, b.fColor), outFlags);
    }

    static MaskedColor SatAdd(const MaskedColor& a, const MaskedColor& b) {
        GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0xFF) |
                                         b.componentsWithValue(0xFF);
        return MaskedColor(GrColorSatAdd(a.fColor, b.fColor), outFlags);
    }

    GrColor color() const { return fColor; }

    GrColorComponentFlags validFlags () const { return fFlags; }

private:
    GrColorComponentFlags componentsWithValue(unsigned value) const {
        GrColorComponentFlags flags = kNone_GrColorComponentFlags;
        if ((kR_GrColorComponentFlag & fFlags) && value == GrColorUnpackR(fColor)) {
            flags |= kR_GrColorComponentFlag;
        }
        if ((kG_GrColorComponentFlag & fFlags) && value == GrColorUnpackG(fColor)) {
            flags |= kG_GrColorComponentFlag;
        }
        if ((kB_GrColorComponentFlag & fFlags) && value == GrColorUnpackB(fColor)) {
            flags |= kB_GrColorComponentFlag;
        }
        if ((kA_GrColorComponentFlag & fFlags) && value == GrColorUnpackA(fColor)) {
            flags |= kA_GrColorComponentFlag;
        }
        return flags;
    }

    GrColor                 fColor;
    GrColorComponentFlags   fFlags;
};

static MaskedColor get_term(GrBlendCoeff coeff, const MaskedColor& src, const MaskedColor& dst,
                            const MaskedColor& value) {
    switch (coeff) {
        case kZero_GrBlendCoeff:
            return MaskedColor(0, kRGBA_GrColorComponentFlags);
        case kOne_GrBlendCoeff:
            return value;
        case kDC_GrBlendCoeff:
            return MaskedColor::Mul(dst, value);
        case kIDC_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::Invert(dst), value);
        case kDA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractAlpha(dst), value);
        case kIDA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(dst), value);
        case kSC_GrBlendCoeff:
            return MaskedColor::Mul(src, value);
        case kISC_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::Invert(src), value);
        case kSA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractAlpha(src), value);
        case kISA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(src), value);
        default:
            SK_ABORT("Illegal coefficient");
            return MaskedColor();
    }
}

void GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff,
                                    GrColor srcColor, GrColorComponentFlags srcColorFlags,
                                    GrColor dstColor, GrColorComponentFlags dstColorFlags,
                                    GrColor* outColor,
                                    GrColorComponentFlags* outFlags) {
    MaskedColor src(srcColor, srcColorFlags);
    MaskedColor dst(dstColor, dstColorFlags);

    MaskedColor srcTerm = get_term(srcCoeff, src, dst, src);
    MaskedColor dstTerm = get_term(dstCoeff, src, dst, dst);

    MaskedColor output = MaskedColor::SatAdd(srcTerm, dstTerm);
    *outColor = output.color();
    *outFlags = output.validFlags();
}
