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#include "SkString.h"
13
14bool SkTransparentShader::setContext(const SkBitmap& device,
15                                     const SkPaint& paint,
16                                     const SkMatrix& matrix) {
17    fDevice = &device;
18    fAlpha = paint.getAlpha();
19
20    return this->INHERITED::setContext(device, paint, matrix);
21}
22
23uint32_t SkTransparentShader::getFlags() {
24    uint32_t flags = this->INHERITED::getFlags();
25
26    switch (fDevice->config()) {
27        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            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->config()) {
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::kIndex8_Config:
82            SkDEBUGFAIL("index8 not supported as a destination device");
83            break;
84        case SkBitmap::kA8_Config: {
85            const uint8_t* src = fDevice->getAddr8(x, y);
86            if (scale == 256) {
87                for (int i = count - 1; i >= 0; --i) {
88                    span[i] = SkPackARGB32(src[i], 0, 0, 0);
89                }
90            } else {
91                for (int i = count - 1; i >= 0; --i) {
92                    span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
93                }
94            }
95            break;
96        }
97        default:    // to avoid warnings
98            break;
99    }
100}
101
102void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
103    SkASSERT(fDevice->config() == SkBitmap::kRGB_565_Config);
104
105    uint16_t* src = fDevice->getAddr16(x, y);
106    if (src != span) {
107        memcpy(span, src, count << 1);
108    }
109}
110
111#ifdef SK_DEVELOPER
112void SkTransparentShader::toString(SkString* str) const {
113    str->append("SkTransparentShader: (");
114
115    this->INHERITED::toString(str);
116
117    str->append(")");
118}
119#endif
120