/* libs/graphics/sgl/SkSpriteBlitter_ARGB32.cpp ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include "SkSpriteBlitter.h" #include "SkTemplates.h" #include "SkUtils.h" #include "SkColorPriv.h" #define D32_S32A_Opaque_Pixel(dst, sc) \ do { \ if (sc) { \ unsigned srcA = SkGetPackedA32(sc); \ uint32_t result = sc; \ if (srcA != 0xFF) { \ result += SkAlphaMulQ(*dst, SkAlpha255To256(255 - srcA)); \ } \ *dst = result; \ } \ } while (0) #define SkSPRITE_CLASSNAME Sprite_D32_S32A_Opaque #define SkSPRITE_ARGS #define SkSPRITE_FIELDS #define SkSPRITE_INIT #define SkSPRITE_DST_TYPE uint32_t #define SkSPRITE_SRC_TYPE uint32_t #define SkSPRITE_DST_GETADDR getAddr32 #define SkSPRITE_SRC_GETADDR getAddr32 #define SkSPRITE_PREAMBLE(srcBM, x, y) #define SkSPRITE_BLIT_PIXEL(dst, src) D32_S32A_Opaque_Pixel(dst, src) #define SkSPRITE_NEXT_ROW #define SkSPRITE_POSTAMBLE(srcBM) #include "SkSpriteBlitterTemplate.h" /////////////////////////////////////////////////////////////////////////////// class Sprite_D32_S32_Opaque : public SkSpriteBlitter { public: Sprite_D32_S32_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y); const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); size_t size = width * sizeof(uint32_t); do { memcpy(dst, src, size); dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB); src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB); } while (--height != 0); } }; /////////////////////////////////////////////////////////////////////////////// #include "SkColorFilter.h" #include "SkXfermode.h" class Sprite_D32_XferFilter : public SkSpriteBlitter { public: Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { fColorFilter = paint.getColorFilter(); fColorFilter->safeRef(); fXfermode = paint.getXfermode(); fXfermode->safeRef(); fBufferSize = 0; fBuffer = NULL; } virtual ~Sprite_D32_XferFilter() { delete[] fBuffer; fXfermode->safeUnref(); fColorFilter->safeUnref(); } virtual void setup(const SkBitmap& device, int left, int top, const SkPaint& paint) { this->INHERITED::setup(device, left, top, paint); int width = device.width(); if (width > fBufferSize) { fBufferSize = width; delete[] fBuffer; fBuffer = new SkPMColor[width]; } } protected: SkColorFilter* fColorFilter; SkXfermode* fXfermode; int fBufferSize; SkPMColor* fBuffer; private: typedef SkSpriteBlitter INHERITED; }; /////////////////////////////////////////////////////////////////////////////// class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { public: Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint) : Sprite_D32_XferFilter(source, paint) {} virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y); const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); SkColorFilter* colorFilter = fColorFilter; SkXfermode* xfermode = fXfermode; do { const SkPMColor* tmp = src; if (NULL != colorFilter) { colorFilter->filterSpan(src, width, fBuffer); tmp = fBuffer; } if (NULL != xfermode) { xfermode->xfer32(dst, tmp, width, NULL); } else { for (int i = 0; i < width; i++) { dst[i] = SkPMSrcOver(tmp[i], dst[i]); } } dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB); src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB); } while (--height != 0); } private: typedef Sprite_D32_XferFilter INHERITED; }; static void fillbuffer(SK_RESTRICT SkPMColor dst[], const SK_RESTRICT SkPMColor16 src[], int count) { SkASSERT(count > 0); do { *dst++ = SkPixel4444ToPixel32(*src++); } while (--count != 0); } class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { public: Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint) : Sprite_D32_XferFilter(source, paint) {} virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y); const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); SK_RESTRICT SkPMColor* buffer = fBuffer; SkColorFilter* colorFilter = fColorFilter; SkXfermode* xfermode = fXfermode; do { fillbuffer(buffer, src, width); if (NULL != colorFilter) { colorFilter->filterSpan(buffer, width, buffer); } if (NULL != xfermode) { xfermode->xfer32(dst, buffer, width, NULL); } else { for (int i = 0; i < width; i++) { dst[i] = SkPMSrcOver(buffer[i], dst[i]); } } dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB); src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB); } while (--height != 0); } private: typedef Sprite_D32_XferFilter INHERITED; }; /////////////////////////////////////////////////////////////////////////////// static void src_row(SK_RESTRICT SkPMColor dst[], const SK_RESTRICT SkPMColor16 src[], int count) { do { *dst = SkPixel4444ToPixel32(*src); src += 1; dst += 1; } while (--count != 0); } class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { public: Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y); const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); do { src_row(dst, src, width); dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB); src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB); } while (--height != 0); } }; static void srcover_row(SK_RESTRICT SkPMColor dst[], const SK_RESTRICT SkPMColor16 src[], int count) { do { *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); src += 1; dst += 1; } while (--count != 0); } class Sprite_D32_S4444 : public SkSpriteBlitter { public: Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {} virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y); const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); do { srcover_row(dst, src, width); dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB); src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB); } while (--height != 0); } }; /////////////////////////////////////////////////////////////////////////////// #include "SkTemplatesPriv.h" SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint, void* storage, size_t storageSize) { if (paint.getMaskFilter() != NULL || paint.getAlpha() != 0xFF) { return NULL; } SkXfermode* xfermode = paint.getXfermode(); SkColorFilter* filter = paint.getColorFilter(); SkSpriteBlitter* blitter = NULL; switch (source.getConfig()) { case SkBitmap::kARGB_4444_Config: if (xfermode || filter) { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter, storage, storageSize, (source, paint)); } else if (source.isOpaque()) { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque, storage, storageSize, (source)); } else { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444, storage, storageSize, (source)); } break; case SkBitmap::kARGB_8888_Config: if (xfermode || filter) { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter, storage, storageSize, (source, paint)); } else if (source.isOpaque()) { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32_Opaque, storage, storageSize, (source)); } else { SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_Opaque, storage, storageSize, (source)); } break; default: break; } return blitter; }