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 "include/core/SkColorFilter.h"
9 #include "include/core/SkPaint.h"
10 #include "include/private/SkColorData.h"
11 #include "include/private/SkTemplates.h"
12 #include "src/core/SkArenaAlloc.h"
13 #include "src/core/SkBlitRow.h"
14 #include "src/core/SkSpriteBlitter.h"
15 #include "src/core/SkXfermodePriv.h"
16
17 ///////////////////////////////////////////////////////////////////////////////
18
19 class Sprite_D32_S32 : public SkSpriteBlitter {
20 public:
Sprite_D32_S32(const SkPixmap & src,U8CPU alpha)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
blitRect(int x,int y,int width,int height)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 using INHERITED = SkSpriteBlitter;
57 };
58
59 ///////////////////////////////////////////////////////////////////////////////
60
61 class Sprite_D32_S32A_Xfer: public SkSpriteBlitter {
62 public:
Sprite_D32_S32A_Xfer(const SkPixmap & source,const SkPaint & paint)63 Sprite_D32_S32A_Xfer(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
64 fXfermode = SkXfermode::Peek(paint.getBlendMode_or(SkBlendMode::kSrcOver));
65 SkASSERT(fXfermode);
66 }
67
blitRect(int x,int y,int width,int height)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 using INHERITED = SkSpriteBlitter;
89 };
90
91 ///////////////////////////////////////////////////////////////////////////////
92
ChooseL32(const SkPixmap & source,const SkPaint & paint,SkArenaAlloc * allocator)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 if (!paint.asBlendMode()) {
104 return nullptr;
105 }
106
107 U8CPU alpha = paint.getAlpha();
108
109 if (source.colorType() == kN32_SkColorType) {
110 if (paint.isSrcOver()) {
111 // this can handle alpha, but not xfermode
112 return allocator->make<Sprite_D32_S32>(source, alpha);
113 }
114 if (255 == alpha) {
115 // this can handle an xfermode, but not alpha
116 return allocator->make<Sprite_D32_S32A_Xfer>(source, paint);
117 }
118 }
119 return nullptr;
120 }
121