1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkFilterShader.h"
9
10#include "SkColorFilter.h"
11#include "SkFlattenableBuffers.h"
12#include "SkShader.h"
13#include "SkString.h"
14
15SkFilterShader::SkFilterShader(SkShader* shader, SkColorFilter* filter) {
16    fShader = shader;
17    shader->ref();
18
19    fFilter = filter;
20    filter->ref();
21}
22
23SkFilterShader::SkFilterShader(SkFlattenableReadBuffer& buffer)
24    : INHERITED(buffer) {
25    fShader = buffer.readShader();
26    fFilter = buffer.readColorFilter();
27}
28
29SkFilterShader::~SkFilterShader() {
30    fFilter->unref();
31    fShader->unref();
32}
33
34void SkFilterShader::flatten(SkFlattenableWriteBuffer& buffer) const {
35    this->INHERITED::flatten(buffer);
36    buffer.writeFlattenable(fShader);
37    buffer.writeFlattenable(fFilter);
38}
39
40uint32_t SkFilterShader::getFlags() {
41    uint32_t shaderF = fShader->getFlags();
42    uint32_t filterF = fFilter->getFlags();
43
44    // if the filter doesn't support 16bit, clear the matching bit in the shader
45    if (!(filterF & SkColorFilter::kHasFilter16_Flag)) {
46        shaderF &= ~SkShader::kHasSpan16_Flag;
47    }
48    // if the filter might change alpha, clear the opaque flag in the shader
49    if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) {
50        shaderF &= ~(SkShader::kOpaqueAlpha_Flag | SkShader::kHasSpan16_Flag);
51    }
52    return shaderF;
53}
54
55bool SkFilterShader::setContext(const SkBitmap& device,
56                                const SkPaint& paint,
57                                const SkMatrix& matrix) {
58    // we need to keep the setContext/endContext calls balanced. If we return
59    // false, our endContext() will not be called.
60
61    if (!this->INHERITED::setContext(device, paint, matrix)) {
62        return false;
63    }
64    if (!fShader->setContext(device, paint, matrix)) {
65        this->INHERITED::endContext();
66        return false;
67    }
68    return true;
69}
70
71void SkFilterShader::endContext() {
72    fShader->endContext();
73    this->INHERITED::endContext();
74}
75
76void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
77    fShader->shadeSpan(x, y, result, count);
78    fFilter->filterSpan(result, count, result);
79}
80
81void SkFilterShader::shadeSpan16(int x, int y, uint16_t result[], int count) {
82    SkASSERT(fShader->getFlags() & SkShader::kHasSpan16_Flag);
83    SkASSERT(fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag);
84
85    fShader->shadeSpan16(x, y, result, count);
86    fFilter->filterSpan16(result, count, result);
87}
88
89#ifdef SK_DEVELOPER
90void SkFilterShader::toString(SkString* str) const {
91    str->append("SkFilterShader: (");
92
93    str->append("Shader: ");
94    fShader->toString(str);
95    str->append(" Filter: ");
96    // TODO: add "fFilter->toString(str);" once SkColorFilter::toString is added
97
98    this->INHERITED::toString(str);
99
100    str->append(")");
101}
102#endif
103