|  | /* | 
|  | * 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 "SkSpriteBlitter.h" | 
|  | #include "SkArenaAlloc.h" | 
|  | #include "SkBlitRow.h" | 
|  | #include "SkColorFilter.h" | 
|  | #include "SkColorData.h" | 
|  | #include "SkTemplates.h" | 
|  | #include "SkUtils.h" | 
|  | #include "SkXfermodePriv.h" | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | class Sprite_D32_S32 : public SkSpriteBlitter { | 
|  | public: | 
|  | Sprite_D32_S32(const SkPixmap& src, U8CPU alpha)  : INHERITED(src) { | 
|  | SkASSERT(src.colorType() == kN32_SkColorType); | 
|  |  | 
|  | unsigned flags32 = 0; | 
|  | if (255 != alpha) { | 
|  | flags32 |= SkBlitRow::kGlobalAlpha_Flag32; | 
|  | } | 
|  | if (!src.isOpaque()) { | 
|  | flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; | 
|  | } | 
|  |  | 
|  | fProc32 = SkBlitRow::Factory32(flags32); | 
|  | fAlpha = alpha; | 
|  | } | 
|  |  | 
|  | void blitRect(int x, int y, int width, int height) override { | 
|  | SkASSERT(width > 0 && height > 0); | 
|  | uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); | 
|  | const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); | 
|  | size_t dstRB = fDst.rowBytes(); | 
|  | size_t srcRB = fSource.rowBytes(); | 
|  | SkBlitRow::Proc32 proc = fProc32; | 
|  | U8CPU             alpha = fAlpha; | 
|  |  | 
|  | do { | 
|  | proc(dst, src, width, alpha); | 
|  | dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); | 
|  | src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); | 
|  | } while (--height != 0); | 
|  | } | 
|  |  | 
|  | private: | 
|  | SkBlitRow::Proc32   fProc32; | 
|  | U8CPU               fAlpha; | 
|  |  | 
|  | typedef SkSpriteBlitter INHERITED; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | class Sprite_D32_S32A_Xfer: public SkSpriteBlitter { | 
|  | public: | 
|  | Sprite_D32_S32A_Xfer(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { | 
|  | fXfermode = SkXfermode::Peek(paint.getBlendMode()); | 
|  | SkASSERT(fXfermode); | 
|  | } | 
|  |  | 
|  | void blitRect(int x, int y, int width, int height) override { | 
|  | SkASSERT(width > 0 && height > 0); | 
|  | uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); | 
|  | const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); | 
|  | size_t dstRB = fDst.rowBytes(); | 
|  | size_t srcRB = fSource.rowBytes(); | 
|  | SkXfermode* xfermode = fXfermode; | 
|  |  | 
|  | do { | 
|  | xfermode->xfer32(dst, src, width, nullptr); | 
|  |  | 
|  | dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); | 
|  | src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); | 
|  | } while (--height != 0); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | SkXfermode* fXfermode; | 
|  |  | 
|  | private: | 
|  | typedef SkSpriteBlitter INHERITED; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint, | 
|  | SkArenaAlloc* allocator) { | 
|  | SkASSERT(allocator != nullptr); | 
|  |  | 
|  | if (paint.getColorFilter() != nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  | if (paint.getMaskFilter() != nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | U8CPU alpha = paint.getAlpha(); | 
|  |  | 
|  | if (source.colorType() == kN32_SkColorType) { | 
|  | if (paint.isSrcOver()) { | 
|  | // this can handle alpha, but not xfermode | 
|  | return allocator->make<Sprite_D32_S32>(source, alpha); | 
|  | } | 
|  | if (255 == alpha) { | 
|  | // this can handle an xfermode, but not alpha | 
|  | return allocator->make<Sprite_D32_S32A_Xfer>(source, paint); | 
|  | } | 
|  | } | 
|  | return nullptr; | 
|  | } |