1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTransparentShader.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
1276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#include "SkString.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec,
15ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                                                        void* storage) const {
16e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec));
1787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkTransparentShader::contextSize() const {
2087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return sizeof(TransparentShaderContext);
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTransparentShader::TransparentShaderContext::TransparentShaderContext(
24e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        const SkTransparentShader& shader, const ContextRec& rec)
25e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    : INHERITED(shader, rec)
26e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    , fDevice(rec.fDevice) {}
2787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
2887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {}
2987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
3087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orguint32_t SkTransparentShader::TransparentShaderContext::getFlags() const {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = this->INHERITED::getFlags();
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    switch (fDevice->colorType()) {
34e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kRGB_565_SkColorType:
353334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            flags |= kHasSpan16_Flag;
3687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (this->getPaintAlpha() == 255)
373334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                flags |= kOpaqueAlpha_Flag;
383334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
3928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
4087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (this->getPaintAlpha() == 255 && fDevice->isOpaque())
413334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                flags |= kOpaqueAlpha_Flag;
423334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
433334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org        default:
443334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return flags;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPMColor span[],
5087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                              int count) {
5187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    unsigned scale = SkAlpha255To256(this->getPaintAlpha());
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    switch (fDevice->colorType()) {
5428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
553334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            if (scale == 256) {
56e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org                SkPMColor* src = fDevice->getAddr32(x, y);
57e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org                if (src != span) {
58e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org                    memcpy(span, src, count * sizeof(SkPMColor));
59e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org                }
603334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            } else {
613334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                const SkPMColor* src = fDevice->getAddr32(x, y);
623334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                for (int i = count - 1; i >= 0; --i) {
633334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                    span[i] = SkAlphaMulQ(src[i], scale);
643334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
653334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            }
663334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
67e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kRGB_565_SkColorType: {
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* src = fDevice->getAddr16(x, y);
693334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            if (scale == 256) {
703334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                for (int i = count - 1; i >= 0; --i) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = SkPixel16ToPixel32(src[i]);
723334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
733334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            } else {
7487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned alpha = this->getPaintAlpha();
753334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                for (int i = count - 1; i >= 0; --i) {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    uint16_t c = src[i];
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned r = SkPacked16ToR32(c);
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned g = SkPacked16ToG32(c);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned b = SkPacked16ToB32(c);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = SkPackARGB32( alpha,
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            SkAlphaMul(r, scale),
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            SkAlphaMul(g, scale),
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            SkAlphaMul(b, scale));
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
873334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
89e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kAlpha_8_SkColorType: {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint8_t* src = fDevice->getAddr8(x, y);
913334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            if (scale == 256) {
923334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                for (int i = count - 1; i >= 0; --i) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = SkPackARGB32(src[i], 0, 0, 0);
943334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
953334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            } else {
963334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                for (int i = count - 1; i >= 0; --i) {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
983334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org                }
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1003334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
102e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        default:
103e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            SkDEBUGFAIL("colorType not supported as a destination device");
1043334c3a1fa05b5ee0cab0f2f1ec7b19939737337mike@reedtribe.org            break;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTransparentShader::TransparentShaderContext::shadeSpan16(int x, int y, uint16_t span[],
10987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                                                int count) {
110e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    SkASSERT(fDevice->colorType() == kRGB_565_SkColorType);
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
112e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org    uint16_t* src = fDevice->getAddr16(x, y);
113e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org    if (src != span) {
114e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org        memcpy(span, src, count << 1);
115e4c98ff48da46c61b73b72301a1811ad1c45a617senorblanco@chromium.org    }
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
1180f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
11976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTransparentShader::toString(SkString* str) const {
12076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append("SkTransparentShader: (");
121ff21c2e0ae23da0f4742b47d4d37969a2a18bd99skia.committer@gmail.com
12276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    this->INHERITED::toString(str);
12376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
12476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
12576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com}
12676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
127