SkShader.cpp revision 7ed173b1ebac84671fb0dc1b9bd323a5e6e63771
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Use of this source code is governed by a BSD-style license that can be
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * found in the LICENSE file.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkBitmapProcShader.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkEmptyShader.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkReadBuffer.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMallocPixelRef.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkPaint.h"
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkPicture.h"
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkPictureShader.h"
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkScalar.h"
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkShader.h"
17cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root#include "SkThread.h"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkWriteBuffer.h"
19854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
20854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey//#define SK_TRACK_SHADER_LIFETIME
212798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
222798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root#ifdef SK_TRACK_SHADER_LIFETIME
23fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    static int32_t gShaderCounter;
240ac3031c159a0904e73eb4439cdc724d8df4a6e6Dianne Hackborn#endif
252798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
26be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkeystatic inline void inc_shader_counter() {
27e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey#ifdef SK_TRACK_SHADER_LIFETIME
28e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    int32_t prev = sk_atomic_inc(&gShaderCounter);
29e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    SkDebugf("+++ shader counter %d\n", prev + 1);
30e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey#endif
31e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey}
32e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkeystatic inline void dec_shader_counter() {
33e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey#ifdef SK_TRACK_SHADER_LIFETIME
34e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    int32_t prev = sk_atomic_dec(&gShaderCounter);
35e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    SkDebugf("--- shader counter %d\n", prev - 1);
36e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey#endif
37e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey}
38e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey
39e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff SharkeySkShader::SkShader(const SkMatrix* localMatrix) {
40e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    inc_shader_counter();
41e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey    if (localMatrix) {
42e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey        fLocalMatrix = *localMatrix;
43513a074de68a4772a9900e90f38e74ff92c15e7cJeff Sharkey    } else {
4488d2a3c0e1b4a8c53a489db5d627beb80b1b9957Jeff Sharkey        fLocalMatrix.reset();
45be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey    }
46e0b0bef75b66f0a87039c8f58c17b1596a2baebeJeff Sharkey}
4773767b9d607d99b3a027619b5c6b7f1a09b7673dJeff Sharkey
486422abef786632e53337c6c298ffa64f7ddf4d90Brian CarlstromSkShader::SkShader(SkReadBuffer& buffer) : INHERITED(buffer) {
496422abef786632e53337c6c298ffa64f7ddf4d90Brian Carlstrom    inc_shader_counter();
50be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey    if (buffer.readBool()) {
51be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey        buffer.readMatrix(&fLocalMatrix);
5210fa67c77e11699391e27975fc2d276a0b8c7cbbNicolas Prevot    } else {
536422abef786632e53337c6c298ffa64f7ddf4d90Brian Carlstrom        fLocalMatrix.reset();
54941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey    }
55941a8ba1a6043cf84a7bf622e44a0b4f7abd0178Jeff Sharkey}
56854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
57854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff SharkeySkShader::~SkShader() {
582798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root    dec_shader_counter();
59be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn}
600c54798aac8a86fed24b14a66f09797d58ad0399Jeff Sharkey
61ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstromvoid SkShader::flatten(SkWriteBuffer& buffer) const {
62c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu    this->INHERITED::flatten(buffer);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool hasLocalM = !fLocalMatrix.isIdentity();
6485387d7ba36e56b291cbde87acb5a5b2200fe01cKenny Root    buffer.writeBool(hasLocalM);
655b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu    if (hasLocalM) {
66be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey        buffer.writeMatrix(fLocalMatrix);
678a4c9721a9e09d20c63381c13fa29bd9f7cbc3e3Jeff Sharkey    }
688c84109b9fbbf473b225707a38261ff5f99d95fbDianne Hackborn}
69fc8b7fe02630f64a1d6c8ecb06f4c250e7478f1dDianne Hackborn
70a10311434778ea1be1621c2251c0c8c2966f337bJeff Sharkeybool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const {
71cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    SkMatrix total;
72cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    total.setConcat(*rec.fMatrix, fLocalMatrix);
73ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinski
743bbef521d4b07f86010ba0729a36ff8b73bcb0acBrian Carlstrom    const SkMatrix* m = &total;
75be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    if (rec.fLocalMatrix) {
76fa012b35b8d51889c8b0239ef9894bc7ebf92de8Dianne Hackborn        total.setConcat(*m, *rec.fLocalMatrix);
776422abef786632e53337c6c298ffa64f7ddf4d90Brian Carlstrom        m = &total;
786422abef786632e53337c6c298ffa64f7ddf4d90Brian Carlstrom    }
79ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom    return m->invert(totalInverse);
80fc8b7fe02630f64a1d6c8ecb06f4c250e7478f1dDianne Hackborn}
81a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks
82a2064df6ab77f71e9187da380cbe355c5eaf5a64rich canningsSkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!this->computeTotalInverse(rec, NULL)) {
8465cde7d42d741c7d9aa2714a397b7333f688ab55Jeff Hao        return NULL;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    return this->onCreateContext(rec, storage);
874528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tate}
887eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao
897eb599b267d00cbde891c0a87924f2f5086f4497Jeff HaoSkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const {
905ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root    return NULL;
91a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks}
922798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
93ecb0e637870553f9c12dc6b9178de0512563af9cDianne Hackbornsize_t SkShader::contextSize() const {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
961ccac75e1f1b97eccb916a8de04fc1012b30f6e5Suchi Amalapurapu
97a3cdaa5337fa573c4c61770195d6232c2e587090Jason parksSkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
981378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi    : fShader(shader), fCTM(*rec.fMatrix)
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Because the context parameters must be valid at this point, we know that the matrix is
10149237345d83e62fdb9eb8d50b13ad086636a04faDianne Hackborn    // invertible.
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse));
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
104fbd0e9fa37fc17ccd25e4c1f16195bbd27de3c4cJeff Sharkey
105f1977b4500e82b72ea6aa5c46d97406a20017cafChristopher Tate    fPaintAlpha = rec.fPaint->getAlpha();
1063a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey}
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1088946dd3355fc1dcbad872c0546e356474d4cc5deSuchi AmalapurapuSkShader::Context::~Context() {}
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
111c6f22499f3046684d7175e10ca42cce1492cd36fdcashman    return NULL;
1121378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi}
1137767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkColorPriv.h"
115a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu
116a0907436c01fd8c545a6b5c7b28bc3bc9db59270Jeff Sharkeyvoid SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(span16);
1186c0b9da65e36543bb50833d1b54ca532d0bd3aabJeff Sharkey    SkASSERT(count > 0);
119ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom    SkASSERT(this->canCallShadeSpan16());
120d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey
121c4858a2ba972e86436d629c4d3f18eb49116de14Jeff Sharkey    // basically, if we get here, the subclass screwed up
122a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks    SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
1232798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root}
1241378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi
1250e2c0f37d98bb5539b0fe41865aaf1add0ff1bb3Kenny Root#define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
126a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks#define kTempColorCount     (kTempColorQuadCount << 2)
1272798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef SK_CPU_BENDIAN
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
1327f7b0c759e2970178ef68805b21f06a26e24eb76Nicolas Prevot#endif
133706e8ba26bf0de19ad5f736516dae40c4c88c2d7rich cannings
1340aaa0d931716e9f57a1d84d795fab2df75092756Kenny Rootvoid SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
13505ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root    SkASSERT(count > 0);
136bb9682e12009aaad696f0b162085efc4b94f5048Jose Lima
137ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinski    SkPMColor   colors[kTempColorCount];
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((count -= kTempColorCount) >= 0) {
140851a54143c15a1c33361efae2db3f7f45059b472Dianne Hackborn        this->shadeSpan(x, y, colors, kTempColorCount);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        x += kTempColorCount;
1422798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
1431378aba7aeeb7f6dd6cc2503968ba7b0e58d9333Ramin Zaghi        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
1447265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate        int quads = kTempColorQuadCount;
145742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey        do {
1468cd28b57ed732656d002d97879e15c5695b54fffAmith Yamasani            U8CPU a0 = srcA[0];
1472798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root            U8CPU a1 = srcA[4];
1482798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root            U8CPU a2 = srcA[8];
149c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu            U8CPU a3 = srcA[12];
1500214e9475fa3b9aa00a784b5152bf4f1939c941eSuchi Amalapurapu            srcA += 4*4;
1510214e9475fa3b9aa00a784b5152bf4f1939c941eSuchi Amalapurapu            *alpha++ = SkToU8(a0);
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *alpha++ = SkToU8(a1);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *alpha++ = SkToU8(a2);
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *alpha++ = SkToU8(a3);
1552798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root        } while (--quads != 0);
156554cb0c290406f5bba34908489db5382a69d0a9arpcraig    }
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(count < 0);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(count + kTempColorCount >= 0);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count += kTempColorCount) {
160f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        this->shadeSpan(x, y, colors, count);
161d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root
162d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
163d02546b4151214abb2db1c88bf7debfc70bd2421Oscar Montemayor        do {
16434385d352da19805ae948215e2edbeedd16b7941Elliott Hughes            *alpha++ = *srcA;
16534385d352da19805ae948215e2edbeedd16b7941Elliott Hughes            srcA += 4;
16634385d352da19805ae948215e2edbeedd16b7941Elliott Hughes        } while (--count != 0);
167bb9682e12009aaad696f0b162085efc4b94f5048Jose Lima    }
1687265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate#if 0
169b87de28f50e9f02a365f35348f8da6cc2629bc1cJeff Sharkey    do {
170ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom        int n = count;
1712798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root        if (n > kTempColorCount)
1722798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root            n = kTempColorCount;
17378a130144bdd047665f00782c481d31edb3e5fb7Jeff Sharkey        SkASSERT(n > 0);
1742798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
1752798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root        this->shadeSpan(x, y, colors, n);
176e9ecc8b49992840249bfb9d5d52b8824dd5de39bAmith Yamasani        x += n;
1772798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root        count -= n;
1782798942bc4c0aeb8dd31d8471a367aaa5d8a2667Kenny Root
17963798c596dc757135950313eb4bb44ca58696c68Nicolas Prevot        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        do {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *alpha++ = *srcA;
182ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom            srcA += 4;
183fc8b7fe02630f64a1d6c8ecb06f4c250e7478f1dDianne Hackborn        } while (--n != 0);
1841c133105774835deaa99db78d9668b107246abefJeff Sharkey    } while (count > 0);
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MatrixClass mc = kLinear_MatrixClass;
1901c133105774835deaa99db78d9668b107246abefJeff Sharkey
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mat.hasPerspective()) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mat.fixedStepInX(0, NULL, NULL)) {
193ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom            mc = kFixedStepInX_MatrixClass;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
195ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom            mc = kPerspective_MatrixClass;
196d02546b4151214abb2db1c88bf7debfc70bd2421Oscar Montemayor        }
19705ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root    }
198a8e65fd82a323e6065ae9ae6cc8eaa130d3c1efdKenny Root    return mc;
19905ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root}
200b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//////////////////////////////////////////////////////////////////////////////
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20349237345d83e62fdb9eb8d50b13ad086636a04faDianne HackbornSkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return kNone_BitmapType;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
206b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return kNone_GradientType;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
210bfed9f34c0cf7cdf7d25e6a7677e03f5a3d87e0eJeff Sharkey
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectGrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const {
212ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom    return NULL;
213ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom}
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
215ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian CarlstromSkShader* SkShader::refAsALocalMatrixShader(SkMatrix*) const {
216ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom    return NULL;
2170f206a149d27385ef092a34e0009a8607d663659Narayan Kamath}
2183a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey
2193f99afc0d5c25321b870f95415d7f31e2b3ec934Kenny RootSkShader* SkShader::CreateEmptyShader() {
220742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey    return SkNEW(SkEmptyShader);
22166269ea6f68f2f25888ce1080c94ac782742fafcKenny Root}
222d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn
223d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne HackbornSkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
224d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                                       const SkMatrix* localMatrix) {
225d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
226d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn}
227d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn
228d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne HackbornSkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy,
229d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn                                       const SkMatrix* localMatrix) {
230d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn    return SkPictureShader::Create(src, tmx, tmy, localMatrix);
231cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root}
232cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
233d4310ac944e5f3063bb23558ba25ccf76fec0968Dianne Hackborn#ifndef SK_IGNORE_TO_STRING
234cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootvoid SkShader::toString(SkString* str) const {
235cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    if (!fLocalMatrix.isIdentity()) {
236cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        str->append(" ");
237c895be7bc68b6f5b37fbb9881f464dd5ea0eb017Dianne Hackborn        fLocalMatrix.toString(str);
238cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
2391bb6906c7a903ee6427c8ff37bdc5896c386ff73Christopher Tate}
2409718cf5e5837d20983cab695d0f54834ffa3b2f4Kenny Root#endif
2417767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn
2429718cf5e5837d20983cab695d0f54834ffa3b2f4Kenny Root//////////////////////////////////////////////////////////////////////////////
2439718cf5e5837d20983cab695d0f54834ffa3b2f4Kenny Root
2449718cf5e5837d20983cab695d0f54834ffa3b2f4Kenny Root#include "SkColorShader.h"
2459718cf5e5837d20983cab695d0f54834ffa3b2f4Kenny Root#include "SkUtils.h"
24605ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root
247ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian CarlstromSkColorShader::SkColorShader(SkColor c)
248ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath    : fColor(c) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
251d42685d5de1dbd6d75b48d42418f370adaa4daefMike Lockwoodbool SkColorShader::isOpaque() const {
252cd0e839a2448deea50f79bddeba782c546b33893Nick Pelly    return SkColorGetA(fColor) == 255;
2531abb1cb3a8fe17f7866150604c2fd73751da787eJaikumar Ganesh}
254514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectSkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
256c55f9c04427796d5b6f833fe43adffd9d7b99ad2Christopher Tate    // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
257c55f9c04427796d5b6f833fe43adffd9d7b99ad2Christopher Tate    // color. We don't support that any more.
258c55f9c04427796d5b6f833fe43adffd9d7b99ad2Christopher Tate    if (b.isVersionLT(SkReadBuffer::kColorShaderNoBool_Version)) {
2598946dd3355fc1dcbad872c0546e356474d4cc5deSuchi Amalapurapu        if (b.readBool()) {
2608946dd3355fc1dcbad872c0546e356474d4cc5deSuchi Amalapurapu            SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
2618946dd3355fc1dcbad872c0546e356474d4cc5deSuchi Amalapurapu            fColor = SK_ColorWHITE;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fColor = b.readColor();
266af8e9f4805643f90a9dc0ecfa119e0a860c12f8aSuchi Amalapurapu}
267af8e9f4805643f90a9dc0ecfa119e0a860c12f8aSuchi Amalapurapu
26878d688369a2240009d3bbe4126996a973b2e2fe2Dianne Hackbornvoid SkColorShader::flatten(SkWriteBuffer& buffer) const {
269661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    this->INHERITED::flatten(buffer);
270d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn    buffer.writeColor(fColor);
27148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
272d5c8044e7e1f1402fdd4a035690329294ab07b33Nick Kralevich
273381d94b712605112b35d7f70064b0d18bd877877Jeff Sharkeyuint32_t SkColorShader::ColorShaderContext::getFlags() const {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return fFlags;
275399cccb85749e02f6d3e12d1d2846310e7cbfdf1Dianne Hackborn}
276111285763204cabff682b381928fd5447a5c6a90Kenny Root
2775ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Rootuint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
278e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate    return SkGetPackedA32(fPMColor);
279e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate}
280e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate
281e6f81cf1f69e0683f969238f921950befba8e6c3Christopher TateSkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const {
282e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate    return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
283e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate}
284e6f81cf1f69e0683f969238f921950befba8e6c3Christopher Tate
285e6f81cf1f69e0683f969238f921950befba8e6c3Christopher TateSkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
2867265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate                                                      const ContextRec& rec)
2877265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    : INHERITED(shader, rec)
2887265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate{
2897265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    SkColor color = shader.fColor;
2907265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
2917265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate
2927265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    unsigned r = SkColorGetR(color);
2937265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    unsigned g = SkColorGetG(color);
2947265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    unsigned b = SkColorGetB(color);
2957265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate
2967265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    // we want this before we apply any alpha
2977265abe77a76f848a316640b5da106e882bdbc8aChristopher Tate    fColor16 = SkPack888ToRGB16(r, g, b);
2985ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root
2995ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root    if (a != 255) {
30036c67c236ed188a034fdf13977fbc8d4fe0023e2rich cannings        r = SkMulDiv255Round(r, a);
3015ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root        g = SkMulDiv255Round(g, a);
3025ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root        b = SkMulDiv255Round(b, a);
3035ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root    }
3045ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root    fPMColor = SkPackARGB32(a, r, g, b);
3055ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root
306aa8513e171e4714809235e08a75aff3814d9a02brich cannings    fFlags = kConstInY32_Flag;
3075ab2157bf1f105b02d3e2913cd3a33f9765b74caKenny Root    if (255 == a) {
308a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings        fFlags |= kOpaqueAlpha_Flag;
309a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings        if (rec.fPaint->isDither() == false) {
310a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings            fFlags |= kHasSpan16_Flag;
311a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings        }
312a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings    }
313a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings}
314a6cfe52eb83995b124efec5f73bcb179caadf888rich cannings
315a6cfe52eb83995b124efec5f73bcb179caadf888rich canningsvoid SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
316111285763204cabff682b381928fd5447a5c6a90Kenny Root    sk_memset32(span, fPMColor, count);
317111285763204cabff682b381928fd5447a5c6a90Kenny Root}
318e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn
319111285763204cabff682b381928fd5447a5c6a90Kenny Rootvoid SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
320e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn    sk_memset16(span, fColor16, count);
321c78a8079740bfcad2e4439ccd74da52f6dc7fae2Kenny Root}
32205ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root
32305ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Rootvoid SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
32448d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    memset(alpha, SkGetPackedA32(fPMColor), count);
32548d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
3260f206a149d27385ef092a34e0009a8607d663659Narayan Kamath
3270f206a149d27385ef092a34e0009a8607d663659Narayan Kamath// if we had a asAColor method, that would be more efficient...
3286f357d3284a833cc50a990e14b39f389b8972254Jeff BrownSkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
329dd3d95f182a634acdcc1b1e8e4954234d048eb54Nick Kralevich                                              TileMode modes[]) const {
33048d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad    return kNone_BitmapType;
33148d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad}
33248d22323ce39f9aab003dce74456889b6414af55Mårten Kongstad
3330214e9475fa3b9aa00a784b5152bf4f1939c941eSuchi AmalapurapuSkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (info) {
335ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey        if (info->fColors && info->fColorCount >= 1) {
336ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey            info->fColors[0] = fColor;
337ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey        }
338ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey        info->fColorCount = 1;
339ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey        info->fTileMode = SkShader::kRepeat_TileMode;
340ca27d452c14f8a275cf2b7d0e59080690e0dc5c1Jeff Sharkey    }
341851a54143c15a1c33361efae2db3f7f45059b472Dianne Hackborn    return kColor_GradientType;
342ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker}
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef SK_IGNORE_TO_STRING
345d2509fd83597595914ef0627685e917380863eb6Dianne Hackbornvoid SkColorShader::toString(SkString* str) const {
346230561eef41047f04dac1a10949f4bcb43915017Brian Carlstrom    str->append("SkColorShader: (");
3477eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str->append("Color: ");
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str->appendHex(fColor);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519f60c08a446e38f9e2d5271546ef69ca5941eba9Jeff Hao    this->INHERITED::toString(str);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str->append(")");
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3560b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
3570b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani///////////////////////////////////////////////////////////////////////////////
3580b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
35951a573c76737733638c475f52e441c814e6645ccKenny Root#ifndef SK_IGNORE_TO_STRING
36051a573c76737733638c475f52e441c814e6645ccKenny Root#include "SkEmptyShader.h"
36151a573c76737733638c475f52e441c814e6645ccKenny Root
362ddbe50df2ca70700a46e5849347989b520d1113eKenny Rootvoid SkEmptyShader::toString(SkString* str) const {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str->append("SkEmptyShader: (");
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
365ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker    this->INHERITED::toString(str);
36657dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str->append(")");
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
369ddbe50df2ca70700a46e5849347989b520d1113eKenny Root#endif
370ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath