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 "SkCoreBlitters.h"
9 : #include "SkColorPriv.h"
10 : #include "SkShader.h"
11 : #include "SkUtils.h"
12 : #include "SkXfermode.h"
13 : #include "SkBlitMask.h"
14 :
15 : ///////////////////////////////////////////////////////////////////////////////
16 :
17 0 : static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
18 : const SkIRect& clip, SkPMColor srcColor) {
19 0 : U8CPU alpha = SkGetPackedA32(srcColor);
20 0 : unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21 0 : if (alpha != 255) {
22 0 : flags |= SkBlitRow::kGlobalAlpha_Flag32;
23 : }
24 0 : SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25 :
26 0 : int x = clip.fLeft;
27 0 : int y = clip.fTop;
28 0 : int width = clip.width();
29 0 : int height = clip.height();
30 :
31 0 : SkPMColor* dstRow = device.getAddr32(x, y);
32 0 : const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33 :
34 0 : do {
35 0 : proc(dstRow, srcRow, width, alpha);
36 0 : dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37 0 : srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38 : } while (--height != 0);
39 0 : }
40 :
41 : //////////////////////////////////////////////////////////////////////////////////////
42 :
43 0 : SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
44 0 : : INHERITED(device) {
45 0 : SkColor color = paint.getColor();
46 0 : fColor = color;
47 :
48 0 : fSrcA = SkColorGetA(color);
49 0 : unsigned scale = SkAlpha255To256(fSrcA);
50 0 : fSrcR = SkAlphaMul(SkColorGetR(color), scale);
51 0 : fSrcG = SkAlphaMul(SkColorGetG(color), scale);
52 0 : fSrcB = SkAlphaMul(SkColorGetB(color), scale);
53 :
54 0 : fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
55 0 : fColor32Proc = SkBlitRow::ColorProcFactory();
56 0 : }
57 :
58 0 : const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
59 0 : if (255 == fSrcA) {
60 0 : *value = fPMColor;
61 0 : return &fDevice;
62 : }
63 0 : return NULL;
64 : }
65 :
66 : #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized
67 : #pragma warning ( push )
68 : #pragma warning ( disable : 4701 )
69 : #endif
70 :
71 0 : void SkARGB32_Blitter::blitH(int x, int y, int width) {
72 0 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
73 :
74 0 : uint32_t* device = fDevice.getAddr32(x, y);
75 0 : fColor32Proc(device, device, width, fPMColor);
76 0 : }
77 :
78 0 : void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
79 : const int16_t runs[]) {
80 0 : if (fSrcA == 0) {
81 0 : return;
82 : }
83 :
84 0 : uint32_t color = fPMColor;
85 0 : uint32_t* device = fDevice.getAddr32(x, y);
86 0 : unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
87 :
88 0 : for (;;) {
89 0 : int count = runs[0];
90 0 : SkASSERT(count >= 0);
91 0 : if (count <= 0) {
92 0 : return;
93 : }
94 0 : unsigned aa = antialias[0];
95 0 : if (aa) {
96 0 : if ((opaqueMask & aa) == 255) {
97 0 : sk_memset32(device, color, count);
98 : } else {
99 0 : uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
100 0 : fColor32Proc(device, device, count, sc);
101 : }
102 : }
103 0 : runs += count;
104 0 : antialias += count;
105 0 : device += count;
106 : }
107 : }
108 :
109 : //////////////////////////////////////////////////////////////////////////////////////
110 :
111 : #define solid_8_pixels(mask, dst, color) \
112 : do { \
113 : if (mask & 0x80) dst[0] = color; \
114 : if (mask & 0x40) dst[1] = color; \
115 : if (mask & 0x20) dst[2] = color; \
116 : if (mask & 0x10) dst[3] = color; \
117 : if (mask & 0x08) dst[4] = color; \
118 : if (mask & 0x04) dst[5] = color; \
119 : if (mask & 0x02) dst[6] = color; \
120 : if (mask & 0x01) dst[7] = color; \
121 : } while (0)
122 :
123 : #define SK_BLITBWMASK_NAME SkARGB32_BlitBW
124 : #define SK_BLITBWMASK_ARGS , SkPMColor color
125 : #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
126 : #define SK_BLITBWMASK_GETADDR getAddr32
127 : #define SK_BLITBWMASK_DEVTYPE uint32_t
128 : #include "SkBlitBWMaskTemplate.h"
129 :
130 : #define blend_8_pixels(mask, dst, sc, dst_scale) \
131 : do { \
132 : if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \
133 : if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \
134 : if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \
135 : if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \
136 : if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \
137 : if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \
138 : if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \
139 : if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \
140 : } while (0)
141 :
142 : #define SK_BLITBWMASK_NAME SkARGB32_BlendBW
143 : #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale
144 : #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale)
145 : #define SK_BLITBWMASK_GETADDR getAddr32
146 : #define SK_BLITBWMASK_DEVTYPE uint32_t
147 : #include "SkBlitBWMaskTemplate.h"
148 :
149 0 : void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
150 0 : SkASSERT(mask.fBounds.contains(clip));
151 0 : SkASSERT(fSrcA != 0xFF);
152 :
153 0 : if (fSrcA == 0) {
154 0 : return;
155 : }
156 :
157 0 : if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
158 0 : return;
159 : }
160 :
161 0 : if (mask.fFormat == SkMask::kBW_Format) {
162 0 : SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
163 0 : } else if (SkMask::kARGB32_Format == mask.fFormat) {
164 0 : SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
165 : }
166 : }
167 :
168 0 : void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
169 : const SkIRect& clip) {
170 0 : SkASSERT(mask.fBounds.contains(clip));
171 :
172 0 : if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
173 0 : return;
174 : }
175 :
176 0 : if (mask.fFormat == SkMask::kBW_Format) {
177 0 : SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
178 0 : } else if (SkMask::kARGB32_Format == mask.fFormat) {
179 0 : SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
180 : }
181 : }
182 :
183 : ///////////////////////////////////////////////////////////////////////////////
184 :
185 0 : void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
186 0 : if (alpha == 0 || fSrcA == 0) {
187 0 : return;
188 : }
189 :
190 0 : uint32_t* device = fDevice.getAddr32(x, y);
191 0 : uint32_t color = fPMColor;
192 :
193 0 : if (alpha != 255) {
194 0 : color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
195 : }
196 :
197 0 : unsigned dst_scale = 255 - SkGetPackedA32(color);
198 0 : uint32_t rowBytes = fDevice.rowBytes();
199 0 : while (--height >= 0) {
200 0 : device[0] = color + SkAlphaMulQ(device[0], dst_scale);
201 0 : device = (uint32_t*)((char*)device + rowBytes);
202 : }
203 : }
204 :
205 0 : void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
206 0 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
207 :
208 0 : if (fSrcA == 0) {
209 0 : return;
210 : }
211 :
212 0 : uint32_t* device = fDevice.getAddr32(x, y);
213 0 : uint32_t color = fPMColor;
214 0 : size_t rowBytes = fDevice.rowBytes();
215 :
216 0 : while (--height >= 0) {
217 0 : fColor32Proc(device, device, width, color);
218 0 : device = (uint32_t*)((char*)device + rowBytes);
219 : }
220 : }
221 :
222 : #if defined _WIN32 && _MSC_VER >= 1300
223 : #pragma warning ( pop )
224 : #endif
225 :
226 : ///////////////////////////////////////////////////////////////////////
227 :
228 0 : void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
229 : const int16_t runs[]) {
230 0 : uint32_t* device = fDevice.getAddr32(x, y);
231 0 : SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
232 :
233 0 : for (;;) {
234 0 : int count = runs[0];
235 0 : SkASSERT(count >= 0);
236 0 : if (count <= 0) {
237 : return;
238 : }
239 0 : unsigned aa = antialias[0];
240 0 : if (aa) {
241 0 : if (aa == 255) {
242 0 : sk_memset32(device, black, count);
243 : } else {
244 0 : SkPMColor src = aa << SK_A32_SHIFT;
245 0 : unsigned dst_scale = 256 - aa;
246 0 : int n = count;
247 0 : do {
248 0 : --n;
249 0 : device[n] = src + SkAlphaMulQ(device[n], dst_scale);
250 : } while (n > 0);
251 : }
252 : }
253 0 : runs += count;
254 0 : antialias += count;
255 0 : device += count;
256 : }
257 : }
258 :
259 : ///////////////////////////////////////////////////////////////////////////////
260 :
261 0 : SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
262 0 : const SkPaint& paint) : INHERITED(device, paint) {
263 0 : fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
264 :
265 0 : fXfermode = paint.getXfermode();
266 0 : SkSafeRef(fXfermode);
267 :
268 0 : int flags = 0;
269 0 : if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
270 0 : flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
271 : }
272 : // we call this on the output from the shader
273 0 : fProc32 = SkBlitRow::Factory32(flags);
274 : // we call this on the output from the shader + alpha from the aa buffer
275 0 : fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
276 0 : }
277 :
278 0 : SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
279 0 : SkSafeUnref(fXfermode);
280 0 : sk_free(fBuffer);
281 0 : }
282 :
283 0 : void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
284 0 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
285 :
286 0 : uint32_t* device = fDevice.getAddr32(x, y);
287 :
288 0 : if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
289 0 : fShader->shadeSpan(x, y, device, width);
290 : } else {
291 0 : SkPMColor* span = fBuffer;
292 0 : fShader->shadeSpan(x, y, span, width);
293 0 : if (fXfermode) {
294 0 : fXfermode->xfer32(device, span, width, NULL);
295 : } else {
296 0 : fProc32(device, span, width, 255);
297 : }
298 : }
299 0 : }
300 :
301 0 : void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
302 : const int16_t runs[]) {
303 0 : SkPMColor* span = fBuffer;
304 0 : uint32_t* device = fDevice.getAddr32(x, y);
305 0 : SkShader* shader = fShader;
306 :
307 0 : if (fXfermode) {
308 0 : for (;;) {
309 0 : SkXfermode* xfer = fXfermode;
310 :
311 0 : int count = *runs;
312 0 : if (count <= 0)
313 : break;
314 0 : int aa = *antialias;
315 0 : if (aa) {
316 0 : shader->shadeSpan(x, y, span, count);
317 0 : if (aa == 255) {
318 0 : xfer->xfer32(device, span, count, NULL);
319 : } else {
320 : // count is almost always 1
321 0 : for (int i = count - 1; i >= 0; --i) {
322 0 : xfer->xfer32(&device[i], &span[i], 1, antialias);
323 : }
324 : }
325 : }
326 0 : device += count;
327 0 : runs += count;
328 0 : antialias += count;
329 0 : x += count;
330 : }
331 0 : } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
332 0 : for (;;) {
333 0 : int count = *runs;
334 0 : if (count <= 0) {
335 : break;
336 : }
337 0 : int aa = *antialias;
338 0 : if (aa) {
339 0 : if (aa == 255) {
340 : // cool, have the shader draw right into the device
341 0 : shader->shadeSpan(x, y, device, count);
342 : } else {
343 0 : shader->shadeSpan(x, y, span, count);
344 0 : fProc32Blend(device, span, count, aa);
345 : }
346 : }
347 0 : device += count;
348 0 : runs += count;
349 0 : antialias += count;
350 0 : x += count;
351 : }
352 : } else { // no xfermode but the shader not opaque
353 0 : for (;;) {
354 0 : int count = *runs;
355 0 : if (count <= 0) {
356 0 : break;
357 : }
358 0 : int aa = *antialias;
359 0 : if (aa) {
360 0 : fShader->shadeSpan(x, y, span, count);
361 0 : if (aa == 255) {
362 0 : fProc32(device, span, count, 255);
363 : } else {
364 0 : fProc32Blend(device, span, count, aa);
365 : }
366 : }
367 0 : device += count;
368 0 : runs += count;
369 0 : antialias += count;
370 0 : x += count;
371 : }
372 : }
373 0 : }
374 :
375 0 : void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
376 : // we only handle kA8 with an xfermode
377 0 : if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
378 0 : this->INHERITED::blitMask(mask, clip);
379 0 : return;
380 : }
381 :
382 0 : SkASSERT(mask.fBounds.contains(clip));
383 :
384 0 : SkBlitMask::RowProc proc = NULL;
385 0 : if (!fXfermode) {
386 0 : unsigned flags = 0;
387 0 : if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
388 0 : flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
389 : }
390 : proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
391 0 : (SkBlitMask::RowFlags)flags);
392 0 : if (NULL == proc) {
393 0 : this->INHERITED::blitMask(mask, clip);
394 0 : return;
395 : }
396 : }
397 :
398 0 : const int x = clip.fLeft;
399 0 : const int width = clip.width();
400 0 : int y = clip.fTop;
401 0 : int height = clip.height();
402 :
403 0 : char* dstRow = (char*)fDevice.getAddr32(x, y);
404 0 : const size_t dstRB = fDevice.rowBytes();
405 0 : const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
406 0 : const size_t maskRB = mask.fRowBytes;
407 :
408 0 : SkShader* shader = fShader;
409 0 : SkPMColor* span = fBuffer;
410 :
411 0 : if (fXfermode) {
412 0 : SkASSERT(SkMask::kA8_Format == mask.fFormat);
413 0 : SkXfermode* xfer = fXfermode;
414 0 : do {
415 0 : shader->shadeSpan(x, y, span, width);
416 0 : xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
417 0 : dstRow += dstRB;
418 0 : maskRow += maskRB;
419 0 : y += 1;
420 : } while (--height > 0);
421 : } else {
422 0 : do {
423 0 : shader->shadeSpan(x, y, span, width);
424 0 : proc(dstRow, maskRow, span, width);
425 0 : dstRow += dstRB;
426 0 : maskRow += maskRB;
427 0 : y += 1;
428 : } while (--height > 0);
429 : }
430 : }
431 :
|