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 :
9 : #include "SkCoreBlitters.h"
10 : #include "SkColorPriv.h"
11 : #include "SkShader.h"
12 : #include "SkXfermodePriv.h"
13 :
14 0 : SkA8_Blitter::SkA8_Blitter(const SkPixmap& device, const SkPaint& paint) : INHERITED(device) {
15 0 : fSrcA = paint.getAlpha();
16 0 : }
17 :
18 0 : const SkPixmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) {
19 0 : if (255 == fSrcA) {
20 0 : *value = 255;
21 0 : return &fDevice;
22 : }
23 0 : return nullptr;
24 : }
25 :
26 0 : void SkA8_Blitter::blitH(int x, int y, int width) {
27 0 : SkASSERT(x >= 0 && y >= 0 &&
28 : (unsigned)(x + width) <= (unsigned)fDevice.width());
29 :
30 0 : if (fSrcA == 0) {
31 0 : return;
32 : }
33 :
34 0 : uint8_t* device = fDevice.writable_addr8(x, y);
35 :
36 0 : if (fSrcA == 255) {
37 0 : memset(device, 0xFF, width);
38 : } else {
39 0 : unsigned scale = 256 - SkAlpha255To256(fSrcA);
40 0 : unsigned srcA = fSrcA;
41 :
42 0 : for (int i = 0; i < width; i++) {
43 0 : device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
44 : }
45 : }
46 : }
47 :
48 0 : void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
49 : const int16_t runs[]) {
50 0 : if (fSrcA == 0) {
51 0 : return;
52 : }
53 :
54 0 : uint8_t* device = fDevice.writable_addr8(x, y);
55 0 : unsigned srcA = fSrcA;
56 :
57 : for (;;) {
58 0 : int count = runs[0];
59 0 : SkASSERT(count >= 0);
60 0 : if (count == 0) {
61 0 : return;
62 : }
63 0 : unsigned aa = antialias[0];
64 :
65 0 : if (aa == 255 && srcA == 255) {
66 0 : memset(device, 0xFF, count);
67 : } else {
68 0 : unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
69 0 : unsigned scale = 256 - sa;
70 :
71 0 : for (int i = 0; i < count; i++) {
72 0 : device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
73 : }
74 : }
75 0 : runs += count;
76 0 : antialias += count;
77 0 : device += count;
78 0 : }
79 : }
80 :
81 : /////////////////////////////////////////////////////////////////////////////////////
82 :
83 : #define solid_8_pixels(mask, dst) \
84 : do { \
85 : if (mask & 0x80) dst[0] = 0xFF; \
86 : if (mask & 0x40) dst[1] = 0xFF; \
87 : if (mask & 0x20) dst[2] = 0xFF; \
88 : if (mask & 0x10) dst[3] = 0xFF; \
89 : if (mask & 0x08) dst[4] = 0xFF; \
90 : if (mask & 0x04) dst[5] = 0xFF; \
91 : if (mask & 0x02) dst[6] = 0xFF; \
92 : if (mask & 0x01) dst[7] = 0xFF; \
93 : } while (0)
94 :
95 : #define SK_BLITBWMASK_NAME SkA8_BlitBW
96 : #define SK_BLITBWMASK_ARGS
97 : #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst)
98 : #define SK_BLITBWMASK_GETADDR writable_addr8
99 : #define SK_BLITBWMASK_DEVTYPE uint8_t
100 : #include "SkBlitBWMaskTemplate.h"
101 :
102 0 : static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa,
103 : unsigned dst_scale) {
104 0 : if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale));
105 0 : if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale));
106 0 : if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale));
107 0 : if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale));
108 0 : if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale));
109 0 : if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale));
110 0 : if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale));
111 0 : if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale));
112 0 : }
113 :
114 : #define SK_BLITBWMASK_NAME SkA8_BlendBW
115 : #define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale
116 : #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_scale)
117 : #define SK_BLITBWMASK_GETADDR writable_addr8
118 : #define SK_BLITBWMASK_DEVTYPE uint8_t
119 : #include "SkBlitBWMaskTemplate.h"
120 :
121 0 : void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
122 0 : if (fSrcA == 0) {
123 0 : return;
124 : }
125 :
126 0 : if (mask.fFormat == SkMask::kBW_Format) {
127 0 : if (fSrcA == 0xFF) {
128 0 : SkA8_BlitBW(fDevice, mask, clip);
129 : } else {
130 0 : SkA8_BlendBW(fDevice, mask, clip, fSrcA,
131 0 : SkAlpha255To256(255 - fSrcA));
132 : }
133 0 : return;
134 : }
135 :
136 0 : int x = clip.fLeft;
137 0 : int y = clip.fTop;
138 0 : int width = clip.width();
139 0 : int height = clip.height();
140 0 : uint8_t* device = fDevice.writable_addr8(x, y);
141 0 : const uint8_t* alpha = mask.getAddr8(x, y);
142 0 : unsigned srcA = fSrcA;
143 :
144 0 : while (--height >= 0) {
145 0 : for (int i = width - 1; i >= 0; --i) {
146 : unsigned sa;
147 : // scale our src by the alpha value
148 : {
149 0 : int aa = alpha[i];
150 0 : if (aa == 0) {
151 0 : continue;
152 : }
153 0 : if (aa == 255) {
154 0 : if (srcA == 255) {
155 0 : device[i] = 0xFF;
156 0 : continue;
157 : }
158 0 : sa = srcA;
159 : } else {
160 0 : sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
161 : }
162 : }
163 :
164 0 : int scale = 256 - SkAlpha255To256(sa);
165 0 : device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
166 : }
167 0 : device += fDevice.rowBytes();
168 0 : alpha += mask.fRowBytes;
169 : }
170 : }
171 :
172 : ///////////////////////////////////////////////////////////////////////////////
173 :
174 0 : void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
175 0 : if (fSrcA == 0) {
176 0 : return;
177 : }
178 :
179 0 : unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha));
180 0 : uint8_t* device = fDevice.writable_addr8(x, y);
181 0 : size_t rowBytes = fDevice.rowBytes();
182 :
183 0 : if (sa == 0xFF) {
184 0 : for (int i = 0; i < height; i++) {
185 0 : *device = SkToU8(sa);
186 0 : device += rowBytes;
187 : }
188 : } else {
189 0 : unsigned scale = 256 - SkAlpha255To256(sa);
190 :
191 0 : for (int i = 0; i < height; i++) {
192 0 : *device = SkToU8(sa + SkAlphaMul(*device, scale));
193 0 : device += rowBytes;
194 : }
195 : }
196 : }
197 :
198 0 : void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
199 0 : SkASSERT(x >= 0 && y >= 0 &&
200 : (unsigned)(x + width) <= (unsigned)fDevice.width() &&
201 : (unsigned)(y + height) <= (unsigned)fDevice.height());
202 :
203 0 : if (fSrcA == 0) {
204 0 : return;
205 : }
206 :
207 0 : uint8_t* device = fDevice.writable_addr8(x, y);
208 0 : unsigned srcA = fSrcA;
209 :
210 0 : if (srcA == 255) {
211 0 : while (--height >= 0) {
212 0 : memset(device, 0xFF, width);
213 0 : device += fDevice.rowBytes();
214 : }
215 : } else {
216 0 : unsigned scale = 256 - SkAlpha255To256(srcA);
217 :
218 0 : while (--height >= 0) {
219 0 : for (int i = 0; i < width; i++) {
220 0 : device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
221 : }
222 0 : device += fDevice.rowBytes();
223 : }
224 : }
225 : }
226 :
227 : ///////////////////////////////////////////////////////////////////////
228 :
229 2 : SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
230 2 : SkShader::Context* shaderContext)
231 2 : : INHERITED(device, paint, shaderContext)
232 : {
233 2 : fXfermode = SkXfermode::Peek(paint.getBlendMode());
234 2 : SkASSERT(!fXfermode || fShaderContext);
235 :
236 2 : int width = device.width();
237 2 : fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2)));
238 2 : fAAExpand = (uint8_t*)(fBuffer + width);
239 2 : }
240 :
241 4 : SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
242 2 : sk_free(fBuffer);
243 2 : }
244 :
245 58 : void SkA8_Shader_Blitter::blitH(int x, int y, int width) {
246 58 : SkASSERT(x >= 0 && y >= 0 &&
247 : (unsigned)(x + width) <= (unsigned)fDevice.width());
248 :
249 58 : uint8_t* device = fDevice.writable_addr8(x, y);
250 58 : SkShader::Context* shaderContext = fShaderContext;
251 :
252 58 : if ((shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
253 0 : memset(device, 0xFF, width);
254 : } else {
255 58 : SkPMColor* span = fBuffer;
256 :
257 58 : shaderContext->shadeSpan(x, y, span, width);
258 58 : if (fXfermode) {
259 0 : fXfermode->xferA8(device, span, width, nullptr);
260 : } else {
261 19314 : for (int i = width - 1; i >= 0; --i) {
262 19256 : unsigned srcA = SkGetPackedA32(span[i]);
263 19256 : unsigned scale = 256 - SkAlpha255To256(srcA);
264 :
265 19256 : device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
266 : }
267 : }
268 : }
269 58 : }
270 :
271 0 : static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) {
272 0 : SkASSERT((unsigned)aa <= 255);
273 :
274 0 : int src_scale = SkAlpha255To256(aa);
275 0 : int sa = SkGetPackedA32(src);
276 0 : int dst_scale = SkAlphaMulInv256(sa, src_scale);
277 :
278 0 : return SkToU8((sa * src_scale + da * dst_scale) >> 8);
279 : }
280 :
281 0 : void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
282 : const int16_t runs[]) {
283 0 : SkShader::Context* shaderContext = fShaderContext;
284 0 : SkXfermode* mode = fXfermode;
285 0 : uint8_t* aaExpand = fAAExpand;
286 0 : SkPMColor* span = fBuffer;
287 0 : uint8_t* device = fDevice.writable_addr8(x, y);
288 0 : int opaque = shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag;
289 :
290 : for (;;) {
291 0 : int count = *runs;
292 0 : if (count == 0) {
293 0 : break;
294 : }
295 0 : int aa = *antialias;
296 0 : if (aa) {
297 0 : if (opaque && aa == 255 && mode == nullptr) {
298 0 : memset(device, 0xFF, count);
299 : } else {
300 0 : shaderContext->shadeSpan(x, y, span, count);
301 0 : if (mode) {
302 0 : memset(aaExpand, aa, count);
303 0 : mode->xferA8(device, span, count, aaExpand);
304 : } else {
305 0 : for (int i = count - 1; i >= 0; --i) {
306 0 : device[i] = aa_blend8(span[i], device[i], aa);
307 : }
308 : }
309 : }
310 : }
311 0 : device += count;
312 0 : runs += count;
313 0 : antialias += count;
314 0 : x += count;
315 0 : }
316 0 : }
317 :
318 0 : void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
319 0 : if (mask.fFormat == SkMask::kBW_Format) {
320 0 : this->INHERITED::blitMask(mask, clip);
321 0 : return;
322 : }
323 :
324 0 : int x = clip.fLeft;
325 0 : int y = clip.fTop;
326 0 : int width = clip.width();
327 0 : int height = clip.height();
328 0 : uint8_t* device = fDevice.writable_addr8(x, y);
329 0 : const uint8_t* alpha = mask.getAddr8(x, y);
330 0 : SkShader::Context* shaderContext = fShaderContext;
331 :
332 0 : SkPMColor* span = fBuffer;
333 :
334 0 : while (--height >= 0) {
335 0 : shaderContext->shadeSpan(x, y, span, width);
336 0 : if (fXfermode) {
337 0 : fXfermode->xferA8(device, span, width, alpha);
338 : } else {
339 0 : for (int i = width - 1; i >= 0; --i) {
340 0 : device[i] = aa_blend8(span[i], device[i], alpha[i]);
341 : }
342 : }
343 :
344 0 : y += 1;
345 0 : device += fDevice.rowBytes();
346 0 : alpha += mask.fRowBytes;
347 : }
348 : }
349 :
350 : ///////////////////////////////////////////////////////////////////////////////
351 :
352 0 : SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkPixmap& device,
353 0 : const SkPaint& paint) : SkRasterBlitter(device) {
354 0 : SkASSERT(nullptr == paint.getShader());
355 0 : SkASSERT(paint.isSrcOver());
356 0 : SkASSERT(nullptr == paint.getColorFilter());
357 0 : }
358 :
359 0 : void SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
360 : const int16_t runs[]) {
361 0 : uint8_t* device = fDevice.writable_addr8(x, y);
362 0 : SkDEBUGCODE(int totalCount = 0;)
363 :
364 : for (;;) {
365 0 : int count = runs[0];
366 0 : SkASSERT(count >= 0);
367 0 : if (count == 0) {
368 0 : return;
369 : }
370 0 : if (antialias[0]) {
371 0 : memset(device, antialias[0], count);
372 : }
373 0 : runs += count;
374 0 : antialias += count;
375 0 : device += count;
376 :
377 0 : SkDEBUGCODE(totalCount += count;)
378 0 : }
379 : SkASSERT(fDevice.width() == totalCount);
380 : }
381 :
382 0 : void SkA8_Coverage_Blitter::blitH(int x, int y, int width) {
383 0 : memset(fDevice.writable_addr8(x, y), 0xFF, width);
384 0 : }
385 :
386 0 : void SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
387 0 : if (0 == alpha) {
388 0 : return;
389 : }
390 :
391 0 : uint8_t* dst = fDevice.writable_addr8(x, y);
392 0 : const size_t dstRB = fDevice.rowBytes();
393 0 : while (--height >= 0) {
394 0 : *dst = alpha;
395 0 : dst += dstRB;
396 : }
397 : }
398 :
399 0 : void SkA8_Coverage_Blitter::blitRect(int x, int y, int width, int height) {
400 0 : uint8_t* dst = fDevice.writable_addr8(x, y);
401 0 : const size_t dstRB = fDevice.rowBytes();
402 0 : while (--height >= 0) {
403 0 : memset(dst, 0xFF, width);
404 0 : dst += dstRB;
405 : }
406 0 : }
407 :
408 0 : void SkA8_Coverage_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
409 0 : SkASSERT(SkMask::kA8_Format == mask.fFormat);
410 :
411 0 : int x = clip.fLeft;
412 0 : int y = clip.fTop;
413 0 : int width = clip.width();
414 0 : int height = clip.height();
415 :
416 0 : uint8_t* dst = fDevice.writable_addr8(x, y);
417 0 : const uint8_t* src = mask.getAddr8(x, y);
418 0 : const size_t srcRB = mask.fRowBytes;
419 0 : const size_t dstRB = fDevice.rowBytes();
420 :
421 0 : while (--height >= 0) {
422 0 : memcpy(dst, src, width);
423 0 : dst += dstRB;
424 0 : src += srcRB;
425 : }
426 0 : }
427 :
428 0 : const SkPixmap* SkA8_Coverage_Blitter::justAnOpaqueColor(uint32_t*) {
429 0 : return nullptr;
430 : }
|