SkShader.cpp revision 37a201231b8f6381938282675eb9abb50ab3b389
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* libs/graphics/sgl/SkShader.cpp
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Copyright 2006, The Android Open Source Project
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Licensed under the Apache License, Version 2.0 (the "License");
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** you may not use this file except in compliance with the License.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** You may obtain a copy of the License at
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     http://www.apache.org/licenses/LICENSE-2.0
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unless required by applicable law or agreed to in writing, software
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** distributed under the License is distributed on an "AS IS" BASIS,
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** See the License for the specific language governing permissions and
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci** limitations under the License.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkScalar.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkShader.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPaint.h"
21bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "SkMallocPixelRef.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader::SkShader() : fLocalMatrix(NULL) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkDEBUGCODE(fInSession = false;)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader::SkShader(SkFlattenableReadBuffer& buffer)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : INHERITED(buffer), fLocalMatrix(NULL) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer.readBool()) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkMatrix matrix;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkReadMatrix(&buffer, &matrix);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setLocalMatrix(matrix);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkDEBUGCODE(fInSession = false;)
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader::~SkShader() {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(!fInSession);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sk_free(fLocalMatrix);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::beginSession() {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(!fInSession);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkDEBUGCODE(fInSession = true;)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::endSession() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(fInSession);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkDEBUGCODE(fInSession = false;)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this->INHERITED::flatten(buffer);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer.writeBool(fLocalMatrix != NULL);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fLocalMatrix) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkWriteMatrix(&buffer, *fLocalMatrix);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SkShader::getLocalMatrix(SkMatrix* localM) const {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fLocalMatrix) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (localM) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *localM = *fLocalMatrix;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (localM) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            localM->reset();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::setLocalMatrix(const SkMatrix& localM) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (localM.isIdentity()) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this->resetLocalMatrix();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (fLocalMatrix == NULL) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *fLocalMatrix = localM;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::resetLocalMatrix() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fLocalMatrix) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sk_free(fLocalMatrix);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fLocalMatrix = NULL;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool SkShader::setContext(const SkBitmap& device,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const SkPaint& paint,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const SkMatrix& matrix) {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SkMatrix* m = &matrix;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkMatrix        total;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fDeviceConfig = SkToU8(device.getConfig());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fPaintAlpha = paint.getAlpha();
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fLocalMatrix) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        total.setConcat(matrix, *fLocalMatrix);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        m = &total;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (m->invert(&fTotalInverse)) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkColorPriv.h"
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(span16);
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SkASSERT(count > 0);
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SkASSERT(this->canCallShadeSpan16());
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // basically, if we get here, the subclass screwed up
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#define kTempColorCount     (kTempColorQuadCount << 2)
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#ifdef SK_CPU_BENDIAN
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(count > 0);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkPMColor   colors[kTempColorCount];
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while ((count -= kTempColorCount) >= 0) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->shadeSpan(x, y, colors, kTempColorCount);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x += kTempColorCount;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int quads = kTempColorQuadCount;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        do {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            U8CPU a0 = srcA[0];
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            U8CPU a1 = srcA[4];
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            U8CPU a2 = srcA[8];
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            U8CPU a3 = srcA[12];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            srcA += 4*4;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *alpha++ = SkToU8(a0);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *alpha++ = SkToU8(a1);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *alpha++ = SkToU8(a2);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *alpha++ = SkToU8(a3);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } while (--quads != 0);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(count < 0);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(count + kTempColorCount >= 0);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count += kTempColorCount) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->shadeSpan(x, y, colors, count);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        do {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *alpha++ = *srcA;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            srcA += 4;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } while (--count != 0);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if 0
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    do {
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        int n = count;
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (n > kTempColorCount)
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            n = kTempColorCount;
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        SkASSERT(n > 0);
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        this->shadeSpan(x, y, colors, n);
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        x += n;
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        count -= n;
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        do {
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            *alpha++ = *srcA;
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            srcA += 4;
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        } while (--n != 0);
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } while (count > 0);
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MatrixClass mc = kLinear_MatrixClass;
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (mat.hasPerspective()) {
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (mat.fixedStepInX(0, NULL, NULL)) {
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            mc = kFixedStepInX_MatrixClass;
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        } else {
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            mc = kPerspective_MatrixClass;
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return mc;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         TileMode*, SkScalar*) const {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kNone_BitmapType;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return kNone_GradientType;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       TileMode tmx, TileMode tmy) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkColorShader.h"
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkUtils.h"
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColorShader::SkColorShader() {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fFlags = 0;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fInheritColor = true;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fAsABitmapPixelRef = NULL;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColorShader::SkColorShader(SkColor c) {
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    fFlags = 0;
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    fColor = c;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fInheritColor = false;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fAsABitmapPixelRef = NULL;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColorShader::~SkColorShader() {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkSafeUnref(fAsABitmapPixelRef);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
237    fFlags = 0; // computed in setContext
238    fAsABitmapPixelRef = NULL;
239
240    fInheritColor = b.readU8();
241    if (fInheritColor) {
242        return;
243    }
244    fColor = b.readU32();
245}
246
247void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
248    this->INHERITED::flatten(buffer);
249    buffer.write8(fInheritColor);
250    if (fInheritColor) {
251        return;
252    }
253    buffer.write32(fColor);
254}
255
256uint8_t SkColorShader::getSpan16Alpha() const {
257    return SkGetPackedA32(fPMColor);
258}
259
260bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
261                               const SkMatrix& matrix) {
262    if (!this->INHERITED::setContext(device, paint, matrix)) {
263        return false;
264    }
265
266    unsigned a;
267
268    if (fInheritColor) {
269        fColor = paint.getColor();
270        a = SkColorGetA(fColor);
271    } else {
272        a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha()));
273    }
274
275    unsigned r = SkColorGetR(fColor);
276    unsigned g = SkColorGetG(fColor);
277    unsigned b = SkColorGetB(fColor);
278
279    // we want this before we apply any alpha
280    fColor16 = SkPack888ToRGB16(r, g, b);
281
282    if (a != 255) {
283        r = SkMulDiv255Round(r, a);
284        g = SkMulDiv255Round(g, a);
285        b = SkMulDiv255Round(b, a);
286    }
287    fPMColor = SkPackARGB32(a, r, g, b);
288
289    fFlags = kConstInY32_Flag;
290    if (255 == a) {
291        fFlags |= kOpaqueAlpha_Flag;
292        if (paint.isDither() == false) {
293            fFlags |= kHasSpan16_Flag;
294        }
295    }
296
297    return true;
298}
299
300void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
301    sk_memset32(span, fPMColor, count);
302}
303
304void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
305    sk_memset16(span, fColor16, count);
306}
307
308void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
309    memset(alpha, SkGetPackedA32(fPMColor), count);
310}
311
312// if we had a asAColor method, that would be more efficient...
313SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
314                                              TileMode modes[],
315                                      SkScalar* twoPointRadialParams) const {
316    // we cache the pixelref, since its generateID is used in the texture cache
317    if (NULL == fAsABitmapPixelRef) {
318        SkPMColor* storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor));
319        *storage = fPMColor;
320        fAsABitmapPixelRef = new SkMallocPixelRef(storage, sizeof(SkPMColor),
321                                                  NULL);
322    }
323
324    if (bitmap) {
325        bitmap->setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
326        bitmap->setPixelRef(fAsABitmapPixelRef);
327    }
328    if (matrix) {
329        matrix->reset();
330    }
331    if (modes) {
332        modes[0] = modes[1] = SkShader::kRepeat_TileMode;
333    }
334    return kDefault_BitmapType;
335}
336
337SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
338    if (info) {
339        if (info->fColors && info->fColorCount >= 1) {
340            info->fColors[0] = fColor;
341        }
342        info->fColorCount = 1;
343        info->fTileMode = SkShader::kRepeat_TileMode;
344    }
345    return kColor_GradientType;
346}
347
348///////////////////////////////////////////////////////////////////////////////
349
350#include "SkEmptyShader.h"
351
352SkEmptyShader::SkEmptyShader() {}
353SkEmptyShader::SkEmptyShader(SkFlattenableReadBuffer& b) : INHERITED(b) {}
354
355uint32_t SkEmptyShader::getFlags() { return 0; }
356uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; }
357bool SkEmptyShader::setContext(const SkBitmap& device, const SkPaint& paint,
358                               const SkMatrix& matrix) {
359    return false;
360}
361void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) {}
362void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) {}
363void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {}
364
365SkFlattenable::Factory SkEmptyShader::getFactory() { return NULL; }
366void SkEmptyShader::flatten(SkFlattenableWriteBuffer& buffer) {
367    this->INHERITED::flatten(buffer);
368}
369
370