• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Sprite_D32_S32(const SkPixmap & src,U8CPU alpha)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 
blitRect(int x,int y,int width,int height)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:
Sprite_D32_S32A_Xfer(const SkPixmap & source,const SkPaint & paint)64     Sprite_D32_S32A_Xfer(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
65         fXfermode = SkXfermode::Peek(paint.getBlendMode());
66         SkASSERT(fXfermode);
67     }
68 
blitRect(int x,int y,int width,int height)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 
ChooseL32(const SkPixmap & source,const SkPaint & paint,SkArenaAlloc * allocator)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