1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkSpriteBlitter.h" 9 #include "SkArenaAlloc.h" 10 #include "SkBlitRow.h" 11 #include "SkColorFilter.h" 12 #include "SkColorPriv.h" 13 #include "SkTemplates.h" 14 #include "SkUtils.h" 15 #include "SkXfermodePriv.h" 16 17 /////////////////////////////////////////////////////////////////////////////// 18 19 class Sprite_D32_S32 : public SkSpriteBlitter { 20 public: 21 Sprite_D32_S32(const SkPixmap& src, U8CPU alpha) : INHERITED(src) { 22 SkASSERT(src.colorType() == kN32_SkColorType); 23 24 unsigned flags32 = 0; 25 if (255 != alpha) { 26 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 27 } 28 if (!src.isOpaque()) { 29 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 30 } 31 32 fProc32 = SkBlitRow::Factory32(flags32); 33 fAlpha = alpha; 34 } 35 36 void blitRect(int x, int y, int width, int height) override { 37 SkASSERT(width > 0 && height > 0); 38 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); 39 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 40 size_t dstRB = fDst.rowBytes(); 41 size_t srcRB = fSource.rowBytes(); 42 SkBlitRow::Proc32 proc = fProc32; 43 U8CPU alpha = fAlpha; 44 45 do { 46 proc(dst, src, width, alpha); 47 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 48 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 49 } while (--height != 0); 50 } 51 52 private: 53 SkBlitRow::Proc32 fProc32; 54 U8CPU fAlpha; 55 56 typedef SkSpriteBlitter INHERITED; 57 }; 58 59 /////////////////////////////////////////////////////////////////////////////// 60 61 class Sprite_D32_S32A_Xfer: public SkSpriteBlitter { 62 public: 63 Sprite_D32_S32A_Xfer(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { 64 fXfermode = SkXfermode::Peek(paint.getBlendMode()); 65 SkASSERT(fXfermode); 66 } 67 68 void blitRect(int x, int y, int width, int height) override { 69 SkASSERT(width > 0 && height > 0); 70 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y); 71 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 72 size_t dstRB = fDst.rowBytes(); 73 size_t srcRB = fSource.rowBytes(); 74 SkXfermode* xfermode = fXfermode; 75 76 do { 77 xfermode->xfer32(dst, src, width, nullptr); 78 79 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 80 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 81 } while (--height != 0); 82 } 83 84 protected: 85 SkXfermode* fXfermode; 86 87 private: 88 typedef SkSpriteBlitter INHERITED; 89 }; 90 91 /////////////////////////////////////////////////////////////////////////////// 92 93 SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint, 94 SkArenaAlloc* allocator) { 95 SkASSERT(allocator != nullptr); 96 97 if (paint.getColorFilter() != nullptr) { 98 return nullptr; 99 } 100 if (paint.getMaskFilter() != nullptr) { 101 return nullptr; 102 } 103 104 U8CPU alpha = paint.getAlpha(); 105 106 if (source.colorType() == kN32_SkColorType) { 107 if (paint.isSrcOver()) { 108 // this can handle alpha, but not xfermode 109 return allocator->make<Sprite_D32_S32>(source, alpha); 110 } 111 if (255 == alpha) { 112 // this can handle an xfermode, but not alpha 113 return allocator->make<Sprite_D32_S32A_Xfer>(source, paint); 114 } 115 } 116 return nullptr; 117 } 118