SkTransparentShader.cpp revision 54924243c1b65b3ee6d8fa064b50a9b1bb2a19a5
1
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
9
10#include "SkTransparentShader.h"
11#include "SkColorPriv.h"
12
13bool SkTransparentShader::setContext(const SkBitmap& device,
14                                     const SkPaint& paint,
15                                     const SkMatrix& matrix) {
16    fDevice = &device;
17    fAlpha = paint.getAlpha();
18
19    return this->INHERITED::setContext(device, paint, matrix);
20}
21
22uint32_t SkTransparentShader::getFlags() {
23    uint32_t flags = this->INHERITED::getFlags();
24
25    switch (fDevice->getConfig()) {
26        case SkBitmap::kRGB_565_Config:
27            flags |= kHasSpan16_Flag;
28            if (fAlpha == 255)
29                flags |= kOpaqueAlpha_Flag;
30            break;
31        case SkBitmap::kARGB_8888_Config:
32        case SkBitmap::kARGB_4444_Config:
33            if (fAlpha == 255 && fDevice->isOpaque())
34                flags |= kOpaqueAlpha_Flag;
35            break;
36        default:
37            break;
38    }
39    return flags;
40}
41
42void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
43    unsigned scale = SkAlpha255To256(fAlpha);
44
45    switch (fDevice->getConfig()) {
46        case SkBitmap::kARGB_8888_Config:
47            if (scale == 256) {
48                SkPMColor* src = fDevice->getAddr32(x, y);
49                if (src != span) {
50                    memcpy(span, src, count * sizeof(SkPMColor));
51                }
52            } else {
53                const SkPMColor* src = fDevice->getAddr32(x, y);
54                for (int i = count - 1; i >= 0; --i) {
55                    span[i] = SkAlphaMulQ(src[i], scale);
56                }
57            }
58            break;
59        case SkBitmap::kRGB_565_Config: {
60            const uint16_t* src = fDevice->getAddr16(x, y);
61            if (scale == 256) {
62                for (int i = count - 1; i >= 0; --i) {
63                    span[i] = SkPixel16ToPixel32(src[i]);
64                }
65            } else {
66                unsigned alpha = fAlpha;
67                for (int i = count - 1; i >= 0; --i) {
68                    uint16_t c = src[i];
69                    unsigned r = SkPacked16ToR32(c);
70                    unsigned g = SkPacked16ToG32(c);
71                    unsigned b = SkPacked16ToB32(c);
72
73                    span[i] = SkPackARGB32( alpha,
74                                            SkAlphaMul(r, scale),
75                                            SkAlphaMul(g, scale),
76                                            SkAlphaMul(b, scale));
77                }
78            }
79            break;
80        }
81        case SkBitmap::kARGB_4444_Config: {
82            const uint16_t* src = fDevice->getAddr16(x, y);
83            if (scale == 256) {
84                for (int i = count - 1; i >= 0; --i) {
85                    span[i] = SkPixel4444ToPixel32(src[i]);
86                }
87            } else {
88                unsigned scale16 = scale >> 4;
89                for (int i = count - 1; i >= 0; --i) {
90                    uint32_t c = SkExpand_4444(src[i]) * scale16;
91                    span[i] = SkCompact_8888(c);
92                }
93            }
94            break;
95        }
96        case SkBitmap::kIndex8_Config:
97            SkDEBUGFAIL("index8 not supported as a destination device");
98            break;
99        case SkBitmap::kA8_Config: {
100            const uint8_t* src = fDevice->getAddr8(x, y);
101            if (scale == 256) {
102                for (int i = count - 1; i >= 0; --i) {
103                    span[i] = SkPackARGB32(src[i], 0, 0, 0);
104                }
105            } else {
106                for (int i = count - 1; i >= 0; --i) {
107                    span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
108                }
109            }
110            break;
111        }
112        case SkBitmap::kA1_Config:
113            SkDEBUGFAIL("kA1_Config umimplemented at this time");
114            break;
115        default:    // to avoid warnings
116            break;
117    }
118}
119
120void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
121    SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
122
123    uint16_t* src = fDevice->getAddr16(x, y);
124    if (src != span) {
125        memcpy(span, src, count << 1);
126    }
127}
128