michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkSpriteBlitter.h" michael@0: #include "SkBlitRow.h" michael@0: #include "SkColorFilter.h" michael@0: #include "SkColorPriv.h" michael@0: #include "SkTemplates.h" michael@0: #include "SkUtils.h" michael@0: #include "SkXfermode.h" michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class Sprite_D32_S32 : public SkSpriteBlitter { michael@0: public: michael@0: Sprite_D32_S32(const SkBitmap& src, U8CPU alpha) : INHERITED(src) { michael@0: SkASSERT(src.colorType() == kPMColor_SkColorType); michael@0: michael@0: unsigned flags32 = 0; michael@0: if (255 != alpha) { michael@0: flags32 |= SkBlitRow::kGlobalAlpha_Flag32; michael@0: } michael@0: if (!src.isOpaque()) { michael@0: flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; michael@0: } michael@0: michael@0: fProc32 = SkBlitRow::Factory32(flags32); michael@0: fAlpha = alpha; michael@0: } michael@0: michael@0: virtual void blitRect(int x, int y, int width, int height) { michael@0: SkASSERT(width > 0 && height > 0); michael@0: uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); michael@0: const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft, michael@0: y - fTop); michael@0: size_t dstRB = fDevice->rowBytes(); michael@0: size_t srcRB = fSource->rowBytes(); michael@0: SkBlitRow::Proc32 proc = fProc32; michael@0: U8CPU alpha = fAlpha; michael@0: michael@0: do { michael@0: proc(dst, src, width, alpha); michael@0: dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); michael@0: src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); michael@0: } while (--height != 0); michael@0: } michael@0: michael@0: private: michael@0: SkBlitRow::Proc32 fProc32; michael@0: U8CPU fAlpha; michael@0: michael@0: typedef SkSpriteBlitter INHERITED; michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class Sprite_D32_XferFilter : public SkSpriteBlitter { michael@0: public: michael@0: Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint) michael@0: : SkSpriteBlitter(source) { michael@0: fColorFilter = paint.getColorFilter(); michael@0: SkSafeRef(fColorFilter); michael@0: michael@0: fXfermode = paint.getXfermode(); michael@0: SkSafeRef(fXfermode); michael@0: michael@0: fBufferSize = 0; michael@0: fBuffer = NULL; michael@0: michael@0: unsigned flags32 = 0; michael@0: if (255 != paint.getAlpha()) { michael@0: flags32 |= SkBlitRow::kGlobalAlpha_Flag32; michael@0: } michael@0: if (!source.isOpaque()) { michael@0: flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; michael@0: } michael@0: michael@0: fProc32 = SkBlitRow::Factory32(flags32); michael@0: fAlpha = paint.getAlpha(); michael@0: } michael@0: michael@0: virtual ~Sprite_D32_XferFilter() { michael@0: delete[] fBuffer; michael@0: SkSafeUnref(fXfermode); michael@0: SkSafeUnref(fColorFilter); michael@0: } michael@0: michael@0: virtual void setup(const SkBitmap& device, int left, int top, michael@0: const SkPaint& paint) { michael@0: this->INHERITED::setup(device, left, top, paint); michael@0: michael@0: int width = device.width(); michael@0: if (width > fBufferSize) { michael@0: fBufferSize = width; michael@0: delete[] fBuffer; michael@0: fBuffer = new SkPMColor[width]; michael@0: } michael@0: } michael@0: michael@0: protected: michael@0: SkColorFilter* fColorFilter; michael@0: SkXfermode* fXfermode; michael@0: int fBufferSize; michael@0: SkPMColor* fBuffer; michael@0: SkBlitRow::Proc32 fProc32; michael@0: U8CPU fAlpha; michael@0: michael@0: private: michael@0: typedef SkSpriteBlitter INHERITED; michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { michael@0: public: michael@0: Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint) michael@0: : Sprite_D32_XferFilter(source, paint) {} michael@0: michael@0: virtual void blitRect(int x, int y, int width, int height) { michael@0: SkASSERT(width > 0 && height > 0); michael@0: uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); michael@0: const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft, michael@0: y - fTop); michael@0: size_t dstRB = fDevice->rowBytes(); michael@0: size_t srcRB = fSource->rowBytes(); michael@0: SkColorFilter* colorFilter = fColorFilter; michael@0: SkXfermode* xfermode = fXfermode; michael@0: michael@0: do { michael@0: const SkPMColor* tmp = src; michael@0: michael@0: if (NULL != colorFilter) { michael@0: colorFilter->filterSpan(src, width, fBuffer); michael@0: tmp = fBuffer; michael@0: } michael@0: michael@0: if (NULL != xfermode) { michael@0: xfermode->xfer32(dst, tmp, width, NULL); michael@0: } else { michael@0: fProc32(dst, tmp, width, fAlpha); michael@0: } michael@0: michael@0: dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); michael@0: src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); michael@0: } while (--height != 0); michael@0: } michael@0: michael@0: private: michael@0: typedef Sprite_D32_XferFilter INHERITED; michael@0: }; michael@0: michael@0: static void fillbuffer(SkPMColor* SK_RESTRICT dst, michael@0: const SkPMColor16* SK_RESTRICT src, int count) { michael@0: SkASSERT(count > 0); michael@0: michael@0: do { michael@0: *dst++ = SkPixel4444ToPixel32(*src++); michael@0: } while (--count != 0); michael@0: } michael@0: michael@0: class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { michael@0: public: michael@0: Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint) michael@0: : Sprite_D32_XferFilter(source, paint) {} michael@0: michael@0: virtual void blitRect(int x, int y, int width, int height) { michael@0: SkASSERT(width > 0 && height > 0); michael@0: SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); michael@0: const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, michael@0: y - fTop); michael@0: size_t dstRB = fDevice->rowBytes(); michael@0: size_t srcRB = fSource->rowBytes(); michael@0: SkPMColor* SK_RESTRICT buffer = fBuffer; michael@0: SkColorFilter* colorFilter = fColorFilter; michael@0: SkXfermode* xfermode = fXfermode; michael@0: michael@0: do { michael@0: fillbuffer(buffer, src, width); michael@0: michael@0: if (NULL != colorFilter) { michael@0: colorFilter->filterSpan(buffer, width, buffer); michael@0: } michael@0: if (NULL != xfermode) { michael@0: xfermode->xfer32(dst, buffer, width, NULL); michael@0: } else { michael@0: fProc32(dst, buffer, width, fAlpha); michael@0: } michael@0: michael@0: dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); michael@0: src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); michael@0: } while (--height != 0); michael@0: } michael@0: michael@0: private: michael@0: typedef Sprite_D32_XferFilter INHERITED; michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: static void src_row(SkPMColor* SK_RESTRICT dst, michael@0: const SkPMColor16* SK_RESTRICT src, int count) { michael@0: do { michael@0: *dst = SkPixel4444ToPixel32(*src); michael@0: src += 1; michael@0: dst += 1; michael@0: } while (--count != 0); michael@0: } michael@0: michael@0: class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { michael@0: public: michael@0: Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} michael@0: michael@0: virtual void blitRect(int x, int y, int width, int height) { michael@0: SkASSERT(width > 0 && height > 0); michael@0: SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); michael@0: const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, michael@0: y - fTop); michael@0: size_t dstRB = fDevice->rowBytes(); michael@0: size_t srcRB = fSource->rowBytes(); michael@0: michael@0: do { michael@0: src_row(dst, src, width); michael@0: dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); michael@0: src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); michael@0: } while (--height != 0); michael@0: } michael@0: }; michael@0: michael@0: static void srcover_row(SkPMColor* SK_RESTRICT dst, michael@0: const SkPMColor16* SK_RESTRICT src, int count) { michael@0: do { michael@0: *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); michael@0: src += 1; michael@0: dst += 1; michael@0: } while (--count != 0); michael@0: } michael@0: michael@0: class Sprite_D32_S4444 : public SkSpriteBlitter { michael@0: public: michael@0: Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {} michael@0: michael@0: virtual void blitRect(int x, int y, int width, int height) { michael@0: SkASSERT(width > 0 && height > 0); michael@0: SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); michael@0: const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft, michael@0: y - fTop); michael@0: size_t dstRB = fDevice->rowBytes(); michael@0: size_t srcRB = fSource->rowBytes(); michael@0: michael@0: do { michael@0: srcover_row(dst, src, width); michael@0: dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); michael@0: src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); michael@0: } while (--height != 0); michael@0: } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint, michael@0: SkTBlitterAllocator* allocator) { michael@0: SkASSERT(allocator != NULL); michael@0: michael@0: if (paint.getMaskFilter() != NULL) { michael@0: return NULL; michael@0: } michael@0: michael@0: U8CPU alpha = paint.getAlpha(); michael@0: SkXfermode* xfermode = paint.getXfermode(); michael@0: SkColorFilter* filter = paint.getColorFilter(); michael@0: SkSpriteBlitter* blitter = NULL; michael@0: michael@0: switch (source.colorType()) { michael@0: case kARGB_4444_SkColorType: michael@0: if (alpha != 0xFF) { michael@0: return NULL; // we only have opaque sprites michael@0: } michael@0: if (xfermode || filter) { michael@0: blitter = allocator->createT(source, paint); michael@0: } else if (source.isOpaque()) { michael@0: blitter = allocator->createT(source); michael@0: } else { michael@0: blitter = allocator->createT(source); michael@0: } michael@0: break; michael@0: case kPMColor_SkColorType: michael@0: if (xfermode || filter) { michael@0: if (255 == alpha) { michael@0: // this can handle xfermode or filter, but not alpha michael@0: blitter = allocator->createT(source, paint); michael@0: } michael@0: } else { michael@0: // this can handle alpha, but not xfermode or filter michael@0: blitter = allocator->createT(source, alpha); michael@0: } michael@0: break; michael@0: default: michael@0: break; michael@0: } michael@0: return blitter; michael@0: }