/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBlitRow.h"
#include "SkColorPriv.h"
#include "SkDither.h"
///////////////////////////////////////////////////////////////////////////////
static void S32_D4444_Opaque(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 == alpha);
if (count > 0) {
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
*dst++ = SkPixel32ToPixel4444(c);
} while (--count != 0);
}
}
static void S32_D4444_Blend(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 > alpha);
if (count > 0) {
unsigned scale16 = SkAlpha255To256(alpha) >> 4;
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
uint32_t src_expand = SkExpand32_4444(c);
uint32_t dst_expand = SkExpand_4444(*dst);
dst_expand += (src_expand - dst_expand) * scale16 >> 4;
*dst++ = SkCompact_4444(dst_expand);
} while (--count != 0);
}
}
static void S32A_D4444_Opaque(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 == alpha);
if (count > 0) {
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
// if (__builtin_expect(c!=0, 1))
if (c)
{
unsigned scale16 = SkAlpha255To256(255 - SkGetPackedA32(c)) >> 4;
uint32_t src_expand = SkExpand_8888(c);
uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
*dst = SkCompact_4444((src_expand + dst_expand) >> 4);
}
dst += 1;
} while (--count != 0);
}
}
static void S32A_D4444_Blend(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 > alpha);
if (count > 0) {
int src_scale = SkAlpha255To256(alpha) >> 4;
do {
SkPMColor sc = *src++;
SkPMColorAssert(sc);
if (sc) {
unsigned dst_scale = 16 - (SkGetPackedA32(sc) * src_scale >> 8);
uint32_t src_expand = SkExpand32_4444(sc) * src_scale;
uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
*dst = SkCompact_4444((src_expand + dst_expand) >> 4);
}
dst += 1;
} while (--count != 0);
}
}
/////////////////////////////////////////////////////////////////////////////
static void S32_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 == alpha);
if (count > 0) {
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
unsigned dither = DITHER_VALUE(x);
*dst++ = SkDitherARGB32To4444(c, dither);
DITHER_INC_X(x);
} while (--count != 0);
}
}
static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 > alpha);
if (count > 0) {
int scale16 = SkAlpha255To256(alpha) >> 4;
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
uint32_t src_expand = SkExpand32_4444(c) * scale16;
uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16);
c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor
*dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
DITHER_INC_X(x);
} while (--count != 0);
}
}
static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 == alpha);
if (count > 0) {
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
if (c) {
unsigned a = SkGetPackedA32(c);
int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
unsigned scale16 = SkAlpha255To256(255 - a) >> 4;
uint32_t src_expand = SkExpand_8888(c);
uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
// convert back to SkPMColor
c = SkCompact_8888(src_expand + dst_expand);
*dst = SkDitherARGB32To4444(c, d);
}
dst += 1;
DITHER_INC_X(x);
} while (--count != 0);
}
}
// need DitherExpand888To4444(expand, dither)
static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 > alpha);
if (count > 0) {
int src_scale = SkAlpha255To256(alpha) >> 4;
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
if (c) {
unsigned a = SkAlpha255To256(SkGetPackedA32(c));
int d = SkAlphaMul(DITHER_VALUE(x), a);
unsigned dst_scale = 16 - SkAlphaMul(src_scale, a);
uint32_t src_expand = SkExpand32_4444(c) * src_scale;
uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
// convert back to SkPMColor
c = SkCompact_8888(src_expand + dst_expand);
*dst = SkDitherARGB32To4444(c, d);
}
dst += 1;
DITHER_INC_X(x);
} while (--count != 0);
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static const SkBlitRow::Proc gProcs4444[] = {
// no dither
S32_D4444_Opaque,
S32_D4444_Blend,
S32A_D4444_Opaque,
S32A_D4444_Blend,
// dither
S32_D4444_Opaque_Dither,
S32_D4444_Blend_Dither,
S32A_D4444_Opaque_Dither,
S32A_D4444_Blend_Dither
};
SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags)
{
SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444));
return gProcs4444[flags];
}