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:
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 typedef SkSpriteBlitter INHERITED;
57 };
58
59 ///////////////////////////////////////////////////////////////////////////////
60
61 class Sprite_D32_XferFilter : public SkSpriteBlitter {
62 public:
Sprite_D32_XferFilter(const SkPixmap & source,const SkPaint & paint)63 Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
64 fColorFilter = paint.getColorFilter();
65 SkSafeRef(fColorFilter);
66
67 fXfermode = SkXfermode::Peek(paint.getBlendMode());
68
69 fBufferSize = 0;
70 fBuffer = nullptr;
71
72 unsigned flags32 = 0;
73 if (255 != paint.getAlpha()) {
74 flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
75 }
76 if (!source.isOpaque()) {
77 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
78 }
79
80 fProc32 = SkBlitRow::Factory32(flags32);
81 fAlpha = paint.getAlpha();
82 }
83
~Sprite_D32_XferFilter()84 ~Sprite_D32_XferFilter() override {
85 delete[] fBuffer;
86 SkSafeUnref(fColorFilter);
87 }
88
setup(const SkPixmap & dst,int left,int top,const SkPaint & paint)89 void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
90 this->INHERITED::setup(dst, left, top, paint);
91
92 int width = dst.width();
93 if (width > fBufferSize) {
94 fBufferSize = width;
95 delete[] fBuffer;
96 fBuffer = new SkPMColor[width];
97 }
98 }
99
100 protected:
101 SkColorFilter* fColorFilter;
102 SkXfermode* fXfermode;
103 int fBufferSize;
104 SkPMColor* fBuffer;
105 SkBlitRow::Proc32 fProc32;
106 U8CPU fAlpha;
107
108 private:
109 typedef SkSpriteBlitter INHERITED;
110 };
111
112 ///////////////////////////////////////////////////////////////////////////////
113
114 class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
115 public:
Sprite_D32_S32A_XferFilter(const SkPixmap & source,const SkPaint & paint)116 Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint)
117 : Sprite_D32_XferFilter(source, paint) {}
118
blitRect(int x,int y,int width,int height)119 void blitRect(int x, int y, int width, int height) override {
120 SkASSERT(width > 0 && height > 0);
121 uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
122 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
123 size_t dstRB = fDst.rowBytes();
124 size_t srcRB = fSource.rowBytes();
125 SkColorFilter* colorFilter = fColorFilter;
126 SkXfermode* xfermode = fXfermode;
127
128 do {
129 const SkPMColor* tmp = src;
130
131 if (colorFilter) {
132 colorFilter->filterSpan(src, width, fBuffer);
133 tmp = fBuffer;
134 }
135
136 if (xfermode) {
137 xfermode->xfer32(dst, tmp, width, nullptr);
138 } else {
139 fProc32(dst, tmp, width, fAlpha);
140 }
141
142 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
143 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
144 } while (--height != 0);
145 }
146
147 private:
148 typedef Sprite_D32_XferFilter INHERITED;
149 };
150
fillbuffer(SkPMColor * SK_RESTRICT dst,const SkPMColor16 * SK_RESTRICT src,int count)151 static void fillbuffer(SkPMColor* SK_RESTRICT dst,
152 const SkPMColor16* SK_RESTRICT src, int count) {
153 SkASSERT(count > 0);
154
155 do {
156 *dst++ = SkPixel4444ToPixel32(*src++);
157 } while (--count != 0);
158 }
159
160 class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
161 public:
Sprite_D32_S4444_XferFilter(const SkPixmap & source,const SkPaint & paint)162 Sprite_D32_S4444_XferFilter(const SkPixmap& source, const SkPaint& paint)
163 : Sprite_D32_XferFilter(source, paint) {}
164
blitRect(int x,int y,int width,int height)165 void blitRect(int x, int y, int width, int height) override {
166 SkASSERT(width > 0 && height > 0);
167 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
168 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
169 size_t dstRB = fDst.rowBytes();
170 size_t srcRB = fSource.rowBytes();
171 SkPMColor* SK_RESTRICT buffer = fBuffer;
172 SkColorFilter* colorFilter = fColorFilter;
173 SkXfermode* xfermode = fXfermode;
174
175 do {
176 fillbuffer(buffer, src, width);
177
178 if (colorFilter) {
179 colorFilter->filterSpan(buffer, width, buffer);
180 }
181 if (xfermode) {
182 xfermode->xfer32(dst, buffer, width, nullptr);
183 } else {
184 fProc32(dst, buffer, width, fAlpha);
185 }
186
187 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
188 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
189 } while (--height != 0);
190 }
191
192 private:
193 typedef Sprite_D32_XferFilter INHERITED;
194 };
195
196 ///////////////////////////////////////////////////////////////////////////////
197
src_row(SkPMColor * SK_RESTRICT dst,const SkPMColor16 * SK_RESTRICT src,int count)198 static void src_row(SkPMColor* SK_RESTRICT dst,
199 const SkPMColor16* SK_RESTRICT src, int count) {
200 do {
201 *dst = SkPixel4444ToPixel32(*src);
202 src += 1;
203 dst += 1;
204 } while (--count != 0);
205 }
206
207 class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
208 public:
Sprite_D32_S4444_Opaque(const SkPixmap & source)209 Sprite_D32_S4444_Opaque(const SkPixmap& source) : SkSpriteBlitter(source) {}
210
blitRect(int x,int y,int width,int height)211 void blitRect(int x, int y, int width, int height) override {
212 SkASSERT(width > 0 && height > 0);
213 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
214 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
215 size_t dstRB = fDst.rowBytes();
216 size_t srcRB = fSource.rowBytes();
217
218 do {
219 src_row(dst, src, width);
220 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
221 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
222 } while (--height != 0);
223 }
224 };
225
srcover_row(SkPMColor * SK_RESTRICT dst,const SkPMColor16 * SK_RESTRICT src,int count)226 static void srcover_row(SkPMColor* SK_RESTRICT dst,
227 const SkPMColor16* SK_RESTRICT src, int count) {
228 do {
229 *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
230 src += 1;
231 dst += 1;
232 } while (--count != 0);
233 }
234
235 class Sprite_D32_S4444 : public SkSpriteBlitter {
236 public:
Sprite_D32_S4444(const SkPixmap & source)237 Sprite_D32_S4444(const SkPixmap& source) : SkSpriteBlitter(source) {}
238
blitRect(int x,int y,int width,int height)239 void blitRect(int x, int y, int width, int height) override {
240 SkASSERT(width > 0 && height > 0);
241 SkPMColor* SK_RESTRICT dst = fDst.writable_addr32(x, y);
242 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
243 size_t dstRB = fDst.rowBytes();
244 size_t srcRB = fSource.rowBytes();
245
246 do {
247 srcover_row(dst, src, width);
248 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
249 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
250 } while (--height != 0);
251 }
252 };
253
254 ///////////////////////////////////////////////////////////////////////////////
255
ChooseL32(const SkPixmap & source,const SkPaint & paint,SkArenaAlloc * allocator)256 SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint,
257 SkArenaAlloc* allocator) {
258 SkASSERT(allocator != nullptr);
259
260 if (paint.getMaskFilter() != nullptr) {
261 return nullptr;
262 }
263
264 U8CPU alpha = paint.getAlpha();
265 bool isSrcOver = paint.isSrcOver();
266 SkColorFilter* filter = paint.getColorFilter();
267 SkSpriteBlitter* blitter = nullptr;
268
269 switch (source.colorType()) {
270 case kARGB_4444_SkColorType:
271 if (alpha != 0xFF) {
272 return nullptr; // we only have opaque sprites
273 }
274 if (!isSrcOver || filter) {
275 blitter = allocator->make<Sprite_D32_S4444_XferFilter>(source, paint);
276 } else if (source.isOpaque()) {
277 blitter = allocator->make<Sprite_D32_S4444_Opaque>(source);
278 } else {
279 blitter = allocator->make<Sprite_D32_S4444>(source);
280 }
281 break;
282 case kN32_SkColorType:
283 if (!isSrcOver || filter) {
284 if (255 == alpha) {
285 // this can handle xfermode or filter, but not alpha
286 blitter = allocator->make<Sprite_D32_S32A_XferFilter>(source, paint);
287 }
288 } else {
289 // this can handle alpha, but not xfermode or filter
290 blitter = allocator->make<Sprite_D32_S32>(source, alpha);
291 }
292 break;
293 default:
294 break;
295 }
296 return blitter;
297 }
298