
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkCoreBlitters.h"
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkShader.h"
#include "SkTemplatesPriv.h"
#include "SkUtils.h"
#include "SkXfermode.h"

static inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst,
                                        U8CPU aa) {
    SkASSERT((unsigned)aa <= 255);

    unsigned src_scale = SkAlpha255To256(aa) >> 4;
    unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale));

    uint32_t src32 = SkExpand_4444(src) * src_scale;
    uint32_t dst32 = SkExpand_4444(dst) * dst_scale;
    return SkCompact_4444((src32 + dst32) >> 4);
}

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

class SkARGB4444_Blitter : public SkRasterBlitter {
public:
    SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint);
    virtual void blitH(int x, int y, int width);
    virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
                           const int16_t runs[]);
    virtual void blitV(int x, int y, int height, SkAlpha alpha);
    virtual void blitRect(int x, int y, int width, int height);
    virtual void blitMask(const SkMask&, const SkIRect&);
    virtual const SkBitmap* justAnOpaqueColor(uint32_t*);

protected:
    SkPMColor16 fPMColor16, fPMColor16Other;
    SkPMColor16 fRawColor16, fRawColor16Other;
    uint8_t     fScale16;

private:
    // illegal
    SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&);

    typedef SkRasterBlitter INHERITED;
};


SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device,
                                   const SkPaint& paint) : INHERITED(device) {
    // cache premultiplied versions in 4444
    SkPMColor c = SkPreMultiplyColor(paint.getColor());
    fPMColor16 = SkPixel32ToPixel4444(c);
    if (paint.isDither()) {
        fPMColor16Other = SkDitherPixel32To4444(c);
    } else {
        fPMColor16Other = fPMColor16;
    }

    // cache raw versions in 4444
    fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
                                 SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
    if (paint.isDither()) {
        fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
                                                SkColorGetG(c), SkColorGetB(c));
    } else {
        fRawColor16Other = fRawColor16;
    }

    fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
    if (16 == fScale16) {
        // force the original to also be opaque
        fPMColor16 |= (0xF << SK_A4444_SHIFT);
    }
}

const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) {
    if (16 == fScale16) {
        *value = fPMColor16;
        return &fDevice;
    }
    return NULL;
}

static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color,
                          SkPMColor16 other, unsigned invScale, int count) {
    int twice = count >> 1;
    while (--twice >= 0) {
        *dst = color + SkAlphaMulQ4(*dst, invScale);
        dst++;
        *dst = other + SkAlphaMulQ4(*dst, invScale);
        dst++;
    }
    if (count & 1) {
        *dst = color + SkAlphaMulQ4(*dst, invScale);
    }
}

static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) {
    uint32_t c32 = SkExpand_4444(c);
    return c32 | (c32 << 4);
}

static void src_over_4444x(SkPMColor16 dst[], uint32_t color,
                           uint32_t other, unsigned invScale, int count) {
    int twice = count >> 1;
    uint32_t tmp;
    while (--twice >= 0) {
        tmp = SkExpand_4444(*dst) * invScale;
        *dst++ = SkCompact_4444((color + tmp) >> 4);
        tmp = SkExpand_4444(*dst) * invScale;
        *dst++ = SkCompact_4444((other + tmp) >> 4);
    }
    if (count & 1) {
        tmp = SkExpand_4444(*dst) * invScale;
        *dst = SkCompact_4444((color + tmp) >> 4);
    }
}

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

    if (0 == fScale16) {
        return;
    }

    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkPMColor16  color = fPMColor16;
    SkPMColor16  other = fPMColor16Other;

    if ((x ^ y) & 1) {
        SkTSwap<SkPMColor16>(color, other);
    }

    if (16 == fScale16) {
        sk_dither_memset16(device, color, other, width);
    } else {
        src_over_4444x(device, SkExpand_4444_Replicate(color),
                       SkExpand_4444_Replicate(other),
                       16 - fScale16, width);
    }
}

void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    if (0 == alpha || 0 == fScale16) {
        return;
    }

    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkPMColor16  color = fPMColor16;
    SkPMColor16  other = fPMColor16Other;
    unsigned     rb = fDevice.rowBytes();

    if ((x ^ y) & 1) {
        SkTSwap<SkPMColor16>(color, other);
    }

    if (16 == fScale16 && 255 == alpha) {
        while (--height >= 0) {
            *device = color;
            device = (SkPMColor16*)((char*)device + rb);
            SkTSwap<SkPMColor16>(color, other);
        }
    } else {
        unsigned alphaScale = SkAlpha255To256(alpha);
        uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4);
        // need to normalize the low nibble of each expanded component
        // so we don't overflow the add with d32
        c32 = SkCompact_4444(c32 >> 4);
        unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32));
        // now re-expand and replicate
        c32 = SkExpand_4444_Replicate(c32);

        while (--height >= 0) {
            uint32_t d32 = SkExpand_4444(*device) * invScale;
            *device = SkCompact_4444((c32 + d32) >> 4);
            device = (SkPMColor16*)((char*)device + rb);
        }
    }
}

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

    if (0 == fScale16) {
        return;
    }

    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkPMColor16  color = fPMColor16;
    SkPMColor16  other = fPMColor16Other;

    if ((x ^ y) & 1) {
        SkTSwap<SkPMColor16>(color, other);
    }

    if (16 == fScale16) {
        while (--height >= 0) {
            sk_dither_memset16(device, color, other, width);
            device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
            SkTSwap<SkPMColor16>(color, other);
        }
    } else {
        unsigned invScale = 16 - fScale16;

        uint32_t c32 = SkExpand_4444_Replicate(color);
        uint32_t o32 = SkExpand_4444_Replicate(other);
        while (--height >= 0) {
            src_over_4444x(device, c32, o32, invScale, width);
            device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
            SkTSwap<uint32_t>(c32, o32);
        }
    }
}

void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
                                   const int16_t runs[]) {
    if (0 == fScale16) {
        return;
    }

    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkPMColor16  color = fPMColor16;
    SkPMColor16  other = fPMColor16Other;

    if ((x ^ y) & 1) {
        SkTSwap<SkPMColor16>(color, other);
    }

    for (;;) {
        int count = runs[0];
        SkASSERT(count >= 0);
        if (count <= 0) {
            return;
        }

        unsigned aa = antialias[0];
        if (aa) {
            if (0xFF == aa) {
                if (16 == fScale16) {
                    sk_dither_memset16(device, color, other, count);
                } else {
                    src_over_4444(device, color, other, 16 - fScale16, count);
                }
            } else {
                // todo: respect dithering
                aa = SkAlpha255To256(aa);   // FIX
                SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4);
                unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX
                int n = count;
                do {
                    --n;
                    device[n] = src + SkAlphaMulQ4(device[n], dst_scale);
                } while (n > 0);
            }
        }

        runs += count;
        antialias += count;
        device += count;

        if (count & 1) {
            SkTSwap<SkPMColor16>(color, other);
        }
    }
}

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

#define solid_8_pixels(mask, dst, color)    \
    do {                                    \
        if (mask & 0x80) dst[0] = color;    \
        if (mask & 0x40) dst[1] = color;    \
        if (mask & 0x20) dst[2] = color;    \
        if (mask & 0x10) dst[3] = color;    \
        if (mask & 0x08) dst[4] = color;    \
        if (mask & 0x04) dst[5] = color;    \
        if (mask & 0x02) dst[6] = color;    \
        if (mask & 0x01) dst[7] = color;    \
    } while (0)

#define SK_BLITBWMASK_NAME                  SkARGB4444_BlitBW
#define SK_BLITBWMASK_ARGS                  , SkPMColor16 color
#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
#define SK_BLITBWMASK_GETADDR               getAddr16
#define SK_BLITBWMASK_DEVTYPE               uint16_t
#include "SkBlitBWMaskTemplate.h"

#define blend_8_pixels(mask, dst, sc, dst_scale)                             \
    do {                                                                     \
        if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); }  \
        if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); }  \
        if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); }  \
        if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); }  \
        if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); }  \
        if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); }  \
        if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); }  \
        if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); }  \
    } while (0)

#define SK_BLITBWMASK_NAME                  SkARGB4444_BlendBW
#define SK_BLITBWMASK_ARGS                  , uint16_t sc, unsigned dst_scale
#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
#define SK_BLITBWMASK_GETADDR               getAddr16
#define SK_BLITBWMASK_DEVTYPE               uint16_t
#include "SkBlitBWMaskTemplate.h"

void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    SkASSERT(mask.fBounds.contains(clip));

    if (0 == fScale16) {
        return;
    }

    if (mask.fFormat == SkMask::kBW_Format) {
        if (16 == fScale16) {
            SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16);
        } else {
            SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16);
        }
        return;
    }

    int x = clip.fLeft;
    int y = clip.fTop;
    int width = clip.width();
    int height = clip.height();

    SkPMColor16*    device = fDevice.getAddr16(x, y);
    const uint8_t*  alpha = mask.getAddr8(x, y);
    SkPMColor16     srcColor = fPMColor16;
    unsigned        devRB = fDevice.rowBytes() - (width << 1);
    unsigned        maskRB = mask.fRowBytes - width;

    do {
        int w = width;
        do {
            unsigned aa = *alpha++;
            *device = SkBlendARGB4444(srcColor, *device, aa);
            device += 1;
        } while (--w != 0);
        device = (SkPMColor16*)((char*)device + devRB);
        alpha += maskRB;
    } while (--height != 0);
}

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

class SkARGB4444_Shader_Blitter : public SkShaderBlitter {
    SkXfermode*     fXfermode;
    SkBlitRow::Proc fOpaqueProc;
    SkBlitRow::Proc fAlphaProc;
    SkPMColor*      fBuffer;
    uint8_t*        fAAExpand;
public:

SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
        : INHERITED(device, paint) {
    const int width = device.width();
    fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width);
    fAAExpand = (uint8_t*)(fBuffer + width);

    fXfermode = paint.getXfermode();
    SkSafeRef(fXfermode);

    unsigned flags = 0;
    if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
    }
    if (paint.isDither()) {
        flags |= SkBlitRow::kDither_Flag;
    }
    fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config);
    fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
                                    SkBitmap::kARGB_4444_Config);
}

virtual ~SkARGB4444_Shader_Blitter() {
    SkSafeUnref(fXfermode);
    sk_free(fBuffer);
}

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

    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkPMColor*   span = fBuffer;

    fShader->shadeSpan(x, y, span, width);
    if (fXfermode) {
        fXfermode->xfer4444(device, span, width, NULL);
    } else {
        fOpaqueProc(device, span, width, 0xFF, x, y);
    }
}

virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
                       const int16_t runs[]) {
    SkPMColor* SK_RESTRICT span = fBuffer;
    uint8_t* SK_RESTRICT aaExpand = fAAExpand;
    SkPMColor16* device = fDevice.getAddr16(x, y);
    SkShader*    shader = fShader;
    SkXfermode*  xfer = fXfermode;

    if (NULL != xfer) {
        for (;;) {
            int count = *runs;
            if (count <= 0) {
                break;
            }
            int aa = *antialias;
            if (aa) {
                shader->shadeSpan(x, y, span, count);
                if (255 == aa) {
                    xfer->xfer4444(device, span, count, NULL);
                } else {
                    const uint8_t* aaBuffer = antialias;
                    if (count > 1) {
                        memset(aaExpand, aa, count);
                        aaBuffer = aaExpand;
                    }
                    xfer->xfer4444(device, span, count, aaBuffer);
                }
            }
            device += count;
            runs += count;
            antialias += count;
            x += count;
        }
    } else {    // no xfermode
        for (;;) {
            int count = *runs;
            if (count <= 0) {
                break;
            }
            int aa = *antialias;
            if (aa) {
                fShader->shadeSpan(x, y, span, count);
                if (255 == aa) {
                    fOpaqueProc(device, span, count, aa, x, y);
                } else {
                    fAlphaProc(device, span, count, aa, x, y);
                }
            }
            device += count;
            runs += count;
            antialias += count;
            x += count;
        }
    }
}

private:
    typedef SkShaderBlitter INHERITED;
};

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

SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device,
                                 const SkPaint& paint,
                                 void* storage, size_t storageSize)
{
    SkBlitter* blitter;

    if (paint.getShader()) {
        SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint));
    } else {
        SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint));
    }
    return blitter;
}
