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