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