blob: 7b92fde6dbbfcec15584e17dd9c8aeb7f02aef4e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkTransparentShader.h"
11#include "SkColorPriv.h"
robertphillips@google.com76f9e932013-01-15 20:17:47 +000012#include "SkString.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013
14bool SkTransparentShader::setContext(const SkBitmap& device,
15 const SkPaint& paint,
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000016 const SkMatrix& matrix) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000017 fDevice = &device;
18 fAlpha = paint.getAlpha();
19
20 return this->INHERITED::setContext(device, paint, matrix);
21}
22
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000023uint32_t SkTransparentShader::getFlags() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000024 uint32_t flags = this->INHERITED::getFlags();
25
26 switch (fDevice->getConfig()) {
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000027 case SkBitmap::kRGB_565_Config:
28 flags |= kHasSpan16_Flag;
29 if (fAlpha == 255)
30 flags |= kOpaqueAlpha_Flag;
31 break;
32 case SkBitmap::kARGB_8888_Config:
33 case SkBitmap::kARGB_4444_Config:
34 if (fAlpha == 255 && fDevice->isOpaque())
35 flags |= kOpaqueAlpha_Flag;
36 break;
37 default:
38 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 }
40 return flags;
41}
42
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000043void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 unsigned scale = SkAlpha255To256(fAlpha);
45
46 switch (fDevice->getConfig()) {
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000047 case SkBitmap::kARGB_8888_Config:
48 if (scale == 256) {
senorblanco@chromium.orge4c98ff2011-05-20 19:06:10 +000049 SkPMColor* src = fDevice->getAddr32(x, y);
50 if (src != span) {
51 memcpy(span, src, count * sizeof(SkPMColor));
52 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000053 } else {
54 const SkPMColor* src = fDevice->getAddr32(x, y);
55 for (int i = count - 1; i >= 0; --i) {
56 span[i] = SkAlphaMulQ(src[i], scale);
57 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000058 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000059 break;
60 case SkBitmap::kRGB_565_Config: {
61 const uint16_t* src = fDevice->getAddr16(x, y);
62 if (scale == 256) {
63 for (int i = count - 1; i >= 0; --i) {
64 span[i] = SkPixel16ToPixel32(src[i]);
65 }
66 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 unsigned alpha = fAlpha;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000068 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 uint16_t c = src[i];
70 unsigned r = SkPacked16ToR32(c);
71 unsigned g = SkPacked16ToG32(c);
72 unsigned b = SkPacked16ToB32(c);
73
74 span[i] = SkPackARGB32( alpha,
75 SkAlphaMul(r, scale),
76 SkAlphaMul(g, scale),
77 SkAlphaMul(b, scale));
78 }
79 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000080 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000082 case SkBitmap::kARGB_4444_Config: {
reed@android.com8a1c16f2008-12-17 15:59:43 +000083 const uint16_t* src = fDevice->getAddr16(x, y);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000084 if (scale == 256) {
85 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000086 span[i] = SkPixel4444ToPixel32(src[i]);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000087 }
88 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 unsigned scale16 = scale >> 4;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000090 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 uint32_t c = SkExpand_4444(src[i]) * scale16;
92 span[i] = SkCompact_8888(c);
93 }
94 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000097 case SkBitmap::kIndex8_Config:
tomhudson@google.com0c00f212011-12-28 14:59:50 +000098 SkDEBUGFAIL("index8 not supported as a destination device");
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000099 break;
100 case SkBitmap::kA8_Config: {
101 const uint8_t* src = fDevice->getAddr8(x, y);
102 if (scale == 256) {
103 for (int i = count - 1; i >= 0; --i) {
104 span[i] = SkPackARGB32(src[i], 0, 0, 0);
105 }
106 } else {
107 for (int i = count - 1; i >= 0; --i) {
108 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
109 }
110 }
111 break;
112 }
113 case SkBitmap::kA1_Config:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000114 SkDEBUGFAIL("kA1_Config umimplemented at this time");
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000115 break;
116 default: // to avoid warnings
117 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118 }
119}
120
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000121void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
123
senorblanco@chromium.orge4c98ff2011-05-20 19:06:10 +0000124 uint16_t* src = fDevice->getAddr16(x, y);
125 if (src != span) {
126 memcpy(span, src, count << 1);
127 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128}
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000129
130#ifdef SK_DEVELOPER
131void SkTransparentShader::toString(SkString* str) const {
132 str->append("SkTransparentShader: (");
skia.committer@gmail.comff21c2e2013-01-16 07:05:56 +0000133
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000134 this->INHERITED::toString(str);
135
136 str->append(")");
137}
138#endif