Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 */
8 #include "SkCoreBlitters.h"
9 #include "SkColorPriv.h"
10 #include "SkShader.h"
11 #include "SkUtils.h"
12 #include "SkXfermode.h"
13 #include "SkBlitMask.h"
15 ///////////////////////////////////////////////////////////////////////////////
17 static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
18 const SkIRect& clip, SkPMColor srcColor) {
19 U8CPU alpha = SkGetPackedA32(srcColor);
20 unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21 if (alpha != 255) {
22 flags |= SkBlitRow::kGlobalAlpha_Flag32;
23 }
24 SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
26 int x = clip.fLeft;
27 int y = clip.fTop;
28 int width = clip.width();
29 int height = clip.height();
31 SkPMColor* dstRow = device.getAddr32(x, y);
32 const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
34 do {
35 proc(dstRow, srcRow, width, alpha);
36 dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37 srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38 } while (--height != 0);
39 }
41 //////////////////////////////////////////////////////////////////////////////////////
43 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
44 : INHERITED(device) {
45 SkColor color = paint.getColor();
46 fColor = color;
48 fSrcA = SkColorGetA(color);
49 unsigned scale = SkAlpha255To256(fSrcA);
50 fSrcR = SkAlphaMul(SkColorGetR(color), scale);
51 fSrcG = SkAlphaMul(SkColorGetG(color), scale);
52 fSrcB = SkAlphaMul(SkColorGetB(color), scale);
54 fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
55 fColor32Proc = SkBlitRow::ColorProcFactory();
56 fColorRect32Proc = SkBlitRow::ColorRectProcFactory();
57 }
59 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
60 if (255 == fSrcA) {
61 *value = fPMColor;
62 return &fDevice;
63 }
64 return NULL;
65 }
67 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized
68 #pragma warning ( push )
69 #pragma warning ( disable : 4701 )
70 #endif
72 void SkARGB32_Blitter::blitH(int x, int y, int width) {
73 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
75 uint32_t* device = fDevice.getAddr32(x, y);
76 fColor32Proc(device, device, width, fPMColor);
77 }
79 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
80 const int16_t runs[]) {
81 if (fSrcA == 0) {
82 return;
83 }
85 uint32_t color = fPMColor;
86 uint32_t* device = fDevice.getAddr32(x, y);
87 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
89 for (;;) {
90 int count = runs[0];
91 SkASSERT(count >= 0);
92 if (count <= 0) {
93 return;
94 }
95 unsigned aa = antialias[0];
96 if (aa) {
97 if ((opaqueMask & aa) == 255) {
98 sk_memset32(device, color, count);
99 } else {
100 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
101 fColor32Proc(device, device, count, sc);
102 }
103 }
104 runs += count;
105 antialias += count;
106 device += count;
107 }
108 }
110 //////////////////////////////////////////////////////////////////////////////////////
112 #define solid_8_pixels(mask, dst, color) \
113 do { \
114 if (mask & 0x80) dst[0] = color; \
115 if (mask & 0x40) dst[1] = color; \
116 if (mask & 0x20) dst[2] = color; \
117 if (mask & 0x10) dst[3] = color; \
118 if (mask & 0x08) dst[4] = color; \
119 if (mask & 0x04) dst[5] = color; \
120 if (mask & 0x02) dst[6] = color; \
121 if (mask & 0x01) dst[7] = color; \
122 } while (0)
124 #define SK_BLITBWMASK_NAME SkARGB32_BlitBW
125 #define SK_BLITBWMASK_ARGS , SkPMColor color
126 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
127 #define SK_BLITBWMASK_GETADDR getAddr32
128 #define SK_BLITBWMASK_DEVTYPE uint32_t
129 #include "SkBlitBWMaskTemplate.h"
131 #define blend_8_pixels(mask, dst, sc, dst_scale) \
132 do { \
133 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \
134 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \
135 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \
136 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \
137 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \
138 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \
139 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \
140 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \
141 } while (0)
143 #define SK_BLITBWMASK_NAME SkARGB32_BlendBW
144 #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale
145 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale)
146 #define SK_BLITBWMASK_GETADDR getAddr32
147 #define SK_BLITBWMASK_DEVTYPE uint32_t
148 #include "SkBlitBWMaskTemplate.h"
150 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
151 SkASSERT(mask.fBounds.contains(clip));
152 SkASSERT(fSrcA != 0xFF);
154 if (fSrcA == 0) {
155 return;
156 }
158 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
159 return;
160 }
162 if (mask.fFormat == SkMask::kBW_Format) {
163 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
164 } else if (SkMask::kARGB32_Format == mask.fFormat) {
165 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
166 }
167 }
169 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
170 const SkIRect& clip) {
171 SkASSERT(mask.fBounds.contains(clip));
173 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
174 return;
175 }
177 if (mask.fFormat == SkMask::kBW_Format) {
178 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
179 } else if (SkMask::kARGB32_Format == mask.fFormat) {
180 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
181 }
182 }
184 ///////////////////////////////////////////////////////////////////////////////
186 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
187 if (alpha == 0 || fSrcA == 0) {
188 return;
189 }
191 uint32_t* device = fDevice.getAddr32(x, y);
192 uint32_t color = fPMColor;
194 if (alpha != 255) {
195 color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
196 }
198 unsigned dst_scale = 255 - SkGetPackedA32(color);
199 size_t rowBytes = fDevice.rowBytes();
200 while (--height >= 0) {
201 device[0] = color + SkAlphaMulQ(device[0], dst_scale);
202 device = (uint32_t*)((char*)device + rowBytes);
203 }
204 }
206 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
207 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
209 if (fSrcA == 0) {
210 return;
211 }
213 uint32_t* device = fDevice.getAddr32(x, y);
214 uint32_t color = fPMColor;
215 size_t rowBytes = fDevice.rowBytes();
217 if (255 == SkGetPackedA32(color)) {
218 fColorRect32Proc(device, width, height, rowBytes, color);
219 } else {
220 while (--height >= 0) {
221 fColor32Proc(device, device, width, color);
222 device = (uint32_t*)((char*)device + rowBytes);
223 }
224 }
225 }
227 #if defined _WIN32 && _MSC_VER >= 1300
228 #pragma warning ( pop )
229 #endif
231 ///////////////////////////////////////////////////////////////////////
233 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
234 const int16_t runs[]) {
235 uint32_t* device = fDevice.getAddr32(x, y);
236 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
238 for (;;) {
239 int count = runs[0];
240 SkASSERT(count >= 0);
241 if (count <= 0) {
242 return;
243 }
244 unsigned aa = antialias[0];
245 if (aa) {
246 if (aa == 255) {
247 sk_memset32(device, black, count);
248 } else {
249 SkPMColor src = aa << SK_A32_SHIFT;
250 unsigned dst_scale = 256 - aa;
251 int n = count;
252 do {
253 --n;
254 device[n] = src + SkAlphaMulQ(device[n], dst_scale);
255 } while (n > 0);
256 }
257 }
258 runs += count;
259 antialias += count;
260 device += count;
261 }
262 }
264 ///////////////////////////////////////////////////////////////////////////////
266 // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
267 // instead of kSrcOver_Mode
268 static void blend_srcmode(SkPMColor* SK_RESTRICT device,
269 const SkPMColor* SK_RESTRICT span,
270 int count, U8CPU aa) {
271 int aa256 = SkAlpha255To256(aa);
272 for (int i = 0; i < count; ++i) {
273 device[i] = SkFourByteInterp256(span[i], device[i], aa256);
274 }
275 }
277 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
278 const SkPaint& paint) : INHERITED(device, paint) {
279 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
281 fXfermode = paint.getXfermode();
282 SkSafeRef(fXfermode);
284 int flags = 0;
285 if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
286 flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
287 }
288 // we call this on the output from the shader
289 fProc32 = SkBlitRow::Factory32(flags);
290 // we call this on the output from the shader + alpha from the aa buffer
291 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
293 fShadeDirectlyIntoDevice = false;
294 if (fXfermode == NULL) {
295 if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
296 fShadeDirectlyIntoDevice = true;
297 }
298 } else {
299 SkXfermode::Mode mode;
300 if (fXfermode->asMode(&mode)) {
301 if (SkXfermode::kSrc_Mode == mode) {
302 fShadeDirectlyIntoDevice = true;
303 fProc32Blend = blend_srcmode;
304 }
305 }
306 }
308 fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag);
309 }
311 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
312 SkSafeUnref(fXfermode);
313 sk_free(fBuffer);
314 }
316 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
317 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
319 uint32_t* device = fDevice.getAddr32(x, y);
321 if (fShadeDirectlyIntoDevice) {
322 fShader->shadeSpan(x, y, device, width);
323 } else {
324 SkPMColor* span = fBuffer;
325 fShader->shadeSpan(x, y, span, width);
326 if (fXfermode) {
327 fXfermode->xfer32(device, span, width, NULL);
328 } else {
329 fProc32(device, span, width, 255);
330 }
331 }
332 }
334 void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
335 SkASSERT(x >= 0 && y >= 0 &&
336 x + width <= fDevice.width() && y + height <= fDevice.height());
338 uint32_t* device = fDevice.getAddr32(x, y);
339 size_t deviceRB = fDevice.rowBytes();
340 SkShader* shader = fShader;
341 SkPMColor* span = fBuffer;
343 if (fConstInY) {
344 if (fShadeDirectlyIntoDevice) {
345 // shade the first row directly into the device
346 fShader->shadeSpan(x, y, device, width);
347 span = device;
348 while (--height > 0) {
349 device = (uint32_t*)((char*)device + deviceRB);
350 memcpy(device, span, width << 2);
351 }
352 } else {
353 fShader->shadeSpan(x, y, span, width);
354 SkXfermode* xfer = fXfermode;
355 if (xfer) {
356 do {
357 xfer->xfer32(device, span, width, NULL);
358 y += 1;
359 device = (uint32_t*)((char*)device + deviceRB);
360 } while (--height > 0);
361 } else {
362 SkBlitRow::Proc32 proc = fProc32;
363 do {
364 proc(device, span, width, 255);
365 y += 1;
366 device = (uint32_t*)((char*)device + deviceRB);
367 } while (--height > 0);
368 }
369 }
370 return;
371 }
373 if (fShadeDirectlyIntoDevice) {
374 void* ctx;
375 SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
376 if (shadeProc) {
377 do {
378 shadeProc(ctx, x, y, device, width);
379 y += 1;
380 device = (uint32_t*)((char*)device + deviceRB);
381 } while (--height > 0);
382 } else {
383 do {
384 shader->shadeSpan(x, y, device, width);
385 y += 1;
386 device = (uint32_t*)((char*)device + deviceRB);
387 } while (--height > 0);
388 }
389 } else {
390 SkXfermode* xfer = fXfermode;
391 if (xfer) {
392 do {
393 shader->shadeSpan(x, y, span, width);
394 xfer->xfer32(device, span, width, NULL);
395 y += 1;
396 device = (uint32_t*)((char*)device + deviceRB);
397 } while (--height > 0);
398 } else {
399 SkBlitRow::Proc32 proc = fProc32;
400 do {
401 shader->shadeSpan(x, y, span, width);
402 proc(device, span, width, 255);
403 y += 1;
404 device = (uint32_t*)((char*)device + deviceRB);
405 } while (--height > 0);
406 }
407 }
408 }
410 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
411 const int16_t runs[]) {
412 SkPMColor* span = fBuffer;
413 uint32_t* device = fDevice.getAddr32(x, y);
414 SkShader* shader = fShader;
416 if (fXfermode && !fShadeDirectlyIntoDevice) {
417 for (;;) {
418 SkXfermode* xfer = fXfermode;
420 int count = *runs;
421 if (count <= 0)
422 break;
423 int aa = *antialias;
424 if (aa) {
425 shader->shadeSpan(x, y, span, count);
426 if (aa == 255) {
427 xfer->xfer32(device, span, count, NULL);
428 } else {
429 // count is almost always 1
430 for (int i = count - 1; i >= 0; --i) {
431 xfer->xfer32(&device[i], &span[i], 1, antialias);
432 }
433 }
434 }
435 device += count;
436 runs += count;
437 antialias += count;
438 x += count;
439 }
440 } else if (fShadeDirectlyIntoDevice ||
441 (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
442 for (;;) {
443 int count = *runs;
444 if (count <= 0) {
445 break;
446 }
447 int aa = *antialias;
448 if (aa) {
449 if (aa == 255) {
450 // cool, have the shader draw right into the device
451 shader->shadeSpan(x, y, device, count);
452 } else {
453 shader->shadeSpan(x, y, span, count);
454 fProc32Blend(device, span, count, aa);
455 }
456 }
457 device += count;
458 runs += count;
459 antialias += count;
460 x += count;
461 }
462 } else {
463 for (;;) {
464 int count = *runs;
465 if (count <= 0) {
466 break;
467 }
468 int aa = *antialias;
469 if (aa) {
470 fShader->shadeSpan(x, y, span, count);
471 if (aa == 255) {
472 fProc32(device, span, count, 255);
473 } else {
474 fProc32Blend(device, span, count, aa);
475 }
476 }
477 device += count;
478 runs += count;
479 antialias += count;
480 x += count;
481 }
482 }
483 }
485 void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
486 // we only handle kA8 with an xfermode
487 if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
488 this->INHERITED::blitMask(mask, clip);
489 return;
490 }
492 SkASSERT(mask.fBounds.contains(clip));
494 SkBlitMask::RowProc proc = NULL;
495 if (!fXfermode) {
496 unsigned flags = 0;
497 if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
498 flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
499 }
500 proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
501 (SkBlitMask::RowFlags)flags);
502 if (NULL == proc) {
503 this->INHERITED::blitMask(mask, clip);
504 return;
505 }
506 }
508 const int x = clip.fLeft;
509 const int width = clip.width();
510 int y = clip.fTop;
511 int height = clip.height();
513 char* dstRow = (char*)fDevice.getAddr32(x, y);
514 const size_t dstRB = fDevice.rowBytes();
515 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
516 const size_t maskRB = mask.fRowBytes;
518 SkShader* shader = fShader;
519 SkPMColor* span = fBuffer;
521 if (fXfermode) {
522 SkASSERT(SkMask::kA8_Format == mask.fFormat);
523 SkXfermode* xfer = fXfermode;
524 do {
525 shader->shadeSpan(x, y, span, width);
526 xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
527 dstRow += dstRB;
528 maskRow += maskRB;
529 y += 1;
530 } while (--height > 0);
531 } else {
532 do {
533 shader->shadeSpan(x, y, span, width);
534 proc(dstRow, maskRow, span, width);
535 dstRow += dstRB;
536 maskRow += maskRB;
537 y += 1;
538 } while (--height > 0);
539 }
540 }
542 void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
543 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
545 uint32_t* device = fDevice.getAddr32(x, y);
546 size_t deviceRB = fDevice.rowBytes();
547 SkShader* shader = fShader;
549 if (fConstInY) {
550 SkPMColor c;
551 fShader->shadeSpan(x, y, &c, 1);
553 if (fShadeDirectlyIntoDevice) {
554 if (255 == alpha) {
555 do {
556 *device = c;
557 device = (uint32_t*)((char*)device + deviceRB);
558 } while (--height > 0);
559 } else {
560 do {
561 *device = SkFourByteInterp(c, *device, alpha);
562 device = (uint32_t*)((char*)device + deviceRB);
563 } while (--height > 0);
564 }
565 } else {
566 SkXfermode* xfer = fXfermode;
567 if (xfer) {
568 do {
569 xfer->xfer32(device, &c, 1, &alpha);
570 device = (uint32_t*)((char*)device + deviceRB);
571 } while (--height > 0);
572 } else {
573 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
574 do {
575 proc(device, &c, 1, alpha);
576 device = (uint32_t*)((char*)device + deviceRB);
577 } while (--height > 0);
578 }
579 }
580 return;
581 }
583 if (fShadeDirectlyIntoDevice) {
584 void* ctx;
585 SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
586 if (255 == alpha) {
587 if (shadeProc) {
588 do {
589 shadeProc(ctx, x, y, device, 1);
590 y += 1;
591 device = (uint32_t*)((char*)device + deviceRB);
592 } while (--height > 0);
593 } else {
594 do {
595 shader->shadeSpan(x, y, device, 1);
596 y += 1;
597 device = (uint32_t*)((char*)device + deviceRB);
598 } while (--height > 0);
599 }
600 } else { // alpha < 255
601 SkPMColor c;
602 if (shadeProc) {
603 do {
604 shadeProc(ctx, x, y, &c, 1);
605 *device = SkFourByteInterp(c, *device, alpha);
606 y += 1;
607 device = (uint32_t*)((char*)device + deviceRB);
608 } while (--height > 0);
609 } else {
610 do {
611 shader->shadeSpan(x, y, &c, 1);
612 *device = SkFourByteInterp(c, *device, alpha);
613 y += 1;
614 device = (uint32_t*)((char*)device + deviceRB);
615 } while (--height > 0);
616 }
617 }
618 } else {
619 SkPMColor* span = fBuffer;
620 SkXfermode* xfer = fXfermode;
621 if (xfer) {
622 do {
623 shader->shadeSpan(x, y, span, 1);
624 xfer->xfer32(device, span, 1, &alpha);
625 y += 1;
626 device = (uint32_t*)((char*)device + deviceRB);
627 } while (--height > 0);
628 } else {
629 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
630 do {
631 shader->shadeSpan(x, y, span, 1);
632 proc(device, span, 1, alpha);
633 y += 1;
634 device = (uint32_t*)((char*)device + deviceRB);
635 } while (--height > 0);
636 }
637 }
638 }