Home | History | Annotate | Download | only in effects
      1 /* libs/graphics/effects/SkGradientShader.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkGradientShader.h"
     19 #include "SkColorPriv.h"
     20 #include "SkUnitMapper.h"
     21 #include "SkUtils.h"
     22 
     23 ///////////////////////////////////////////////////////////////////////////
     24 
     25 typedef SkFixed (*TileProc)(SkFixed);
     26 
     27 static SkFixed clamp_tileproc(SkFixed x) {
     28     return SkClampMax(x, 0xFFFF);
     29 }
     30 
     31 static SkFixed repeat_tileproc(SkFixed x) {
     32     return x & 0xFFFF;
     33 }
     34 
     35 static inline SkFixed mirror_tileproc(SkFixed x) {
     36     int s = x << 15 >> 31;
     37     return (x ^ s) & 0xFFFF;
     38 }
     39 
     40 static const TileProc gTileProcs[] = {
     41     clamp_tileproc,
     42     repeat_tileproc,
     43     mirror_tileproc
     44 };
     45 
     46 //////////////////////////////////////////////////////////////////////////////
     47 
     48 static inline int repeat_bits(int x, const int bits) {
     49     return x & ((1 << bits) - 1);
     50 }
     51 
     52 static inline int mirror_bits(int x, const int bits) {
     53 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
     54     if (x & (1 << bits))
     55         x = ~x;
     56     return x & ((1 << bits) - 1);
     57 #else
     58     int s = x << (31 - bits) >> 31;
     59     return (x ^ s) & ((1 << bits) - 1);
     60 #endif
     61 }
     62 
     63 static inline int repeat_8bits(int x) {
     64     return x & 0xFF;
     65 }
     66 
     67 static inline int mirror_8bits(int x) {
     68 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
     69     if (x & 256) {
     70         x = ~x;
     71     }
     72     return x & 255;
     73 #else
     74     int s = x << 23 >> 31;
     75     return (x ^ s) & 0xFF;
     76 #endif
     77 }
     78 
     79 //////////////////////////////////////////////////////////////////////////////
     80 
     81 class Gradient_Shader : public SkShader {
     82 public:
     83     Gradient_Shader(const SkColor colors[], const SkScalar pos[],
     84                 int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper);
     85     virtual ~Gradient_Shader();
     86 
     87     // overrides
     88     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
     89     virtual uint32_t getFlags() { return fFlags; }
     90 
     91 protected:
     92     Gradient_Shader(SkFlattenableReadBuffer& );
     93     SkUnitMapper* fMapper;
     94     SkMatrix    fPtsToUnit;     // set by subclass
     95     SkMatrix    fDstToIndex;
     96     SkMatrix::MapXYProc fDstToIndexProc;
     97     TileMode    fTileMode;
     98     TileProc    fTileProc;
     99     int         fColorCount;
    100     uint8_t     fDstToIndexClass;
    101     uint8_t     fFlags;
    102 
    103     struct Rec {
    104         SkFixed     fPos;   // 0...1
    105         uint32_t    fScale; // (1 << 24) / range
    106     };
    107     Rec*        fRecs;
    108 
    109     enum {
    110         kCache16Bits    = 8,    // seems like enough for visual accuracy
    111         kCache16Count   = 1 << kCache16Bits,
    112         kCache16Mask    = kCache16Count - 1,
    113         kCache16Shift   = 16 - kCache16Bits,
    114 
    115         kCache32Bits    = 8,    // pretty much should always be 8
    116         kCache32Count   = 1 << kCache32Bits
    117     };
    118     virtual void flatten(SkFlattenableWriteBuffer& );
    119     const uint16_t*     getCache16();
    120     const SkPMColor*    getCache32();
    121 
    122     // called when we kill our cached colors (to be rebuilt later on demand)
    123     virtual void onCacheReset()  = 0;
    124 
    125 private:
    126     enum {
    127         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
    128 
    129         kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
    130     };
    131     SkColor     fStorage[(kStorageSize + 3) >> 2];
    132     SkColor*    fOrigColors;
    133 
    134     uint16_t*   fCache16;   // working ptr. If this is NULL, we need to recompute the cache values
    135     SkPMColor*  fCache32;   // working ptr. If this is NULL, we need to recompute the cache values
    136 
    137     uint16_t*   fCache16Storage;    // storage for fCache16, allocated on demand
    138     SkPMColor*  fCache32Storage;    // storage for fCache32, allocated on demand
    139     unsigned    fCacheAlpha;        // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
    140 
    141     static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
    142 
    143     typedef SkShader INHERITED;
    144 };
    145 
    146 static inline unsigned scalarToU16(SkScalar x) {
    147     SkASSERT(x >= 0 && x <= SK_Scalar1);
    148 
    149 #ifdef SK_SCALAR_IS_FLOAT
    150     return (unsigned)(x * 0xFFFF);
    151 #else
    152     return x - (x >> 16);   // probably should be x - (x > 0x7FFF) but that is slower
    153 #endif
    154 }
    155 
    156 Gradient_Shader::Gradient_Shader(const SkColor colors[], const SkScalar pos[],
    157              int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) {
    158     SkASSERT(colorCount > 1);
    159 
    160     fCacheAlpha = 256;  // init to a value that paint.getAlpha() can't return
    161 
    162     fMapper = mapper;
    163     mapper->safeRef();
    164 
    165     SkASSERT((unsigned)mode < SkShader::kTileModeCount);
    166     SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
    167     fTileMode = mode;
    168     fTileProc = gTileProcs[mode];
    169 
    170     fCache16 = fCache16Storage = NULL;
    171     fCache32 = fCache32Storage = NULL;
    172 
    173     /*  Note: we let the caller skip the first and/or last position.
    174         i.e. pos[0] = 0.3, pos[1] = 0.7
    175         In these cases, we insert dummy entries to ensure that the final data
    176         will be bracketed by [0, 1].
    177         i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1
    178 
    179         Thus colorCount (the caller's value, and fColorCount (our value) may
    180         differ by up to 2. In the above example:
    181             colorCount = 2
    182             fColorCount = 4
    183      */
    184     fColorCount = colorCount;
    185     // check if we need to add in dummy start and/or end position/colors
    186     bool dummyFirst = false;
    187     bool dummyLast = false;
    188     if (pos) {
    189         dummyFirst = pos[0] != 0;
    190         dummyLast = pos[colorCount - 1] != SK_Scalar1;
    191         fColorCount += dummyFirst + dummyLast;
    192     }
    193 
    194     if (fColorCount > kColorStorageCount) {
    195         size_t size = sizeof(SkColor) + sizeof(Rec);
    196         fOrigColors = reinterpret_cast<SkColor*>(
    197                                         sk_malloc_throw(size * fColorCount));
    198     }
    199     else {
    200         fOrigColors = fStorage;
    201     }
    202 
    203     // Now copy over the colors, adding the dummies as needed
    204     {
    205         SkColor* origColors = fOrigColors;
    206         if (dummyFirst) {
    207             *origColors++ = colors[0];
    208         }
    209         memcpy(origColors, colors, colorCount * sizeof(SkColor));
    210         if (dummyLast) {
    211             origColors += colorCount;
    212             *origColors = colors[colorCount - 1];
    213         }
    214     }
    215 
    216     fRecs = (Rec*)(fOrigColors + fColorCount);
    217     if (fColorCount > 2) {
    218         Rec* recs = fRecs;
    219         recs->fPos = 0;
    220         //  recs->fScale = 0; // unused;
    221         recs += 1;
    222         if (pos) {
    223             /*  We need to convert the user's array of relative positions into
    224                 fixed-point positions and scale factors. We need these results
    225                 to be strictly monotonic (no two values equal or out of order).
    226                 Hence this complex loop that just jams a zero for the scale
    227                 value if it sees a segment out of order, and it assures that
    228                 we start at 0 and end at 1.0
    229             */
    230             SkFixed prev = 0;
    231             int startIndex = dummyFirst ? 0 : 1;
    232             int count = colorCount + dummyLast;
    233             for (int i = startIndex; i < count; i++) {
    234                 // force the last value to be 1.0
    235                 SkFixed curr;
    236                 if (i == colorCount) {  // we're really at the dummyLast
    237                     curr = SK_Fixed1;
    238                 } else {
    239                     curr = SkScalarToFixed(pos[i]);
    240                 }
    241                 // pin curr withing range
    242                 if (curr < 0) {
    243                     curr = 0;
    244                 } else if (curr > SK_Fixed1) {
    245                     curr = SK_Fixed1;
    246                 }
    247                 recs->fPos = curr;
    248                 if (curr > prev) {
    249                     recs->fScale = (1 << 24) / (curr - prev);
    250                 } else {
    251                     recs->fScale = 0; // ignore this segment
    252                 }
    253                 // get ready for the next value
    254                 prev = curr;
    255                 recs += 1;
    256             }
    257         } else {    // assume even distribution
    258             SkFixed dp = SK_Fixed1 / (colorCount - 1);
    259             SkFixed p = dp;
    260             SkFixed scale = (colorCount - 1) << 8;  // (1 << 24) / dp
    261             for (int i = 1; i < colorCount; i++) {
    262                 recs->fPos   = p;
    263                 recs->fScale = scale;
    264                 recs += 1;
    265                 p += dp;
    266             }
    267         }
    268     }
    269     fFlags = 0;
    270 }
    271 
    272 Gradient_Shader::Gradient_Shader(SkFlattenableReadBuffer& buffer) :
    273     INHERITED(buffer) {
    274     fCacheAlpha = 256;
    275 
    276     fMapper = static_cast<SkUnitMapper*>(buffer.readFlattenable());
    277 
    278     fCache16 = fCache16Storage = NULL;
    279     fCache32 = fCache32Storage = NULL;
    280 
    281     int colorCount = fColorCount = buffer.readU32();
    282     if (colorCount > kColorStorageCount) {
    283         size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec);
    284         fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount);
    285     } else {
    286         fOrigColors = fStorage;
    287     }
    288     buffer.read(fOrigColors, colorCount * sizeof(SkColor));
    289 
    290     fTileMode = (TileMode)buffer.readU8();
    291     fTileProc = gTileProcs[fTileMode];
    292     fRecs = (Rec*)(fOrigColors + colorCount);
    293     if (colorCount > 2) {
    294         Rec* recs = fRecs;
    295         recs[0].fPos = 0;
    296         for (int i = 1; i < colorCount; i++) {
    297             recs[i].fPos = buffer.readS32();
    298             recs[i].fScale = buffer.readU32();
    299         }
    300     }
    301     buffer.read(&fPtsToUnit, sizeof(SkMatrix));
    302     fFlags = 0;
    303 }
    304 
    305 Gradient_Shader::~Gradient_Shader() {
    306     if (fCache16Storage) {
    307         sk_free(fCache16Storage);
    308     }
    309     if (fCache32Storage) {
    310         sk_free(fCache32Storage);
    311     }
    312     if (fOrigColors != fStorage) {
    313         sk_free(fOrigColors);
    314     }
    315     fMapper->safeUnref();
    316 }
    317 
    318 void Gradient_Shader::flatten(SkFlattenableWriteBuffer& buffer) {
    319     this->INHERITED::flatten(buffer);
    320     buffer.writeFlattenable(fMapper);
    321     buffer.write32(fColorCount);
    322     buffer.writeMul4(fOrigColors, fColorCount * sizeof(SkColor));
    323     buffer.write8(fTileMode);
    324     if (fColorCount > 2) {
    325         Rec* recs = fRecs;
    326         for (int i = 1; i < fColorCount; i++) {
    327             buffer.write32(recs[i].fPos);
    328             buffer.write32(recs[i].fScale);
    329         }
    330     }
    331     buffer.writeMul4(&fPtsToUnit, sizeof(SkMatrix));
    332 }
    333 
    334 bool Gradient_Shader::setContext(const SkBitmap& device,
    335                                  const SkPaint& paint,
    336                                  const SkMatrix& matrix) {
    337     if (!this->INHERITED::setContext(device, paint, matrix)) {
    338         return false;
    339     }
    340 
    341     const SkMatrix& inverse = this->getTotalInverse();
    342 
    343     if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) {
    344         return false;
    345     }
    346 
    347     fDstToIndexProc = fDstToIndex.getMapXYProc();
    348     fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex);
    349 
    350     // now convert our colors in to PMColors
    351     unsigned paintAlpha = this->getPaintAlpha();
    352     unsigned colorAlpha = 0xFF;
    353 
    354     // FIXME: record colorAlpha in constructor, since this is not affected
    355     // by setContext()
    356     for (int i = 0; i < fColorCount; i++) {
    357         SkColor src = fOrigColors[i];
    358         unsigned sa = SkColorGetA(src);
    359         colorAlpha &= sa;
    360     }
    361 
    362     fFlags = this->INHERITED::getFlags();
    363     if ((colorAlpha & paintAlpha) == 0xFF) {
    364         fFlags |= kOpaqueAlpha_Flag;
    365     }
    366     // we can do span16 as long as our individual colors are opaque,
    367     // regardless of the paint's alpha
    368     if (0xFF == colorAlpha) {
    369         fFlags |= kHasSpan16_Flag;
    370     }
    371 
    372     // if the new alpha differs from the previous time we were called, inval our cache
    373     // this will trigger the cache to be rebuilt.
    374     // we don't care about the first time, since the cache ptrs will already be NULL
    375     if (fCacheAlpha != paintAlpha) {
    376         fCache16 = NULL;                // inval the cache
    377         fCache32 = NULL;                // inval the cache
    378         fCacheAlpha = paintAlpha;       // record the new alpha
    379         // inform our subclasses
    380         this->onCacheReset();
    381     }
    382     return true;
    383 }
    384 
    385 static inline int blend8(int a, int b, int scale) {
    386     SkASSERT(a == SkToU8(a));
    387     SkASSERT(b == SkToU8(b));
    388     SkASSERT(scale >= 0 && scale <= 256);
    389     return a + ((b - a) * scale >> 8);
    390 }
    391 
    392 static inline uint32_t dot8_blend_packed32(uint32_t s0, uint32_t s1,
    393                                            int blend) {
    394 #if 0
    395     int a = blend8(SkGetPackedA32(s0), SkGetPackedA32(s1), blend);
    396     int r = blend8(SkGetPackedR32(s0), SkGetPackedR32(s1), blend);
    397     int g = blend8(SkGetPackedG32(s0), SkGetPackedG32(s1), blend);
    398     int b = blend8(SkGetPackedB32(s0), SkGetPackedB32(s1), blend);
    399 
    400     return SkPackARGB32(a, r, g, b);
    401 #else
    402     int otherBlend = 256 - blend;
    403 
    404 #if 0
    405     U32 t0 = (((s0 & 0xFF00FF) * blend + (s1 & 0xFF00FF) * otherBlend) >> 8) & 0xFF00FF;
    406     U32 t1 = (((s0 >> 8) & 0xFF00FF) * blend + ((s1 >> 8) & 0xFF00FF) * otherBlend) & 0xFF00FF00;
    407     SkASSERT((t0 & t1) == 0);
    408     return t0 | t1;
    409 #else
    410     return  ((((s0 & 0xFF00FF) * blend + (s1 & 0xFF00FF) * otherBlend) >> 8) & 0xFF00FF) |
    411             ((((s0 >> 8) & 0xFF00FF) * blend + ((s1 >> 8) & 0xFF00FF) * otherBlend) & 0xFF00FF00);
    412 #endif
    413 
    414 #endif
    415 }
    416 
    417 #define Fixed_To_Dot8(x)        (((x) + 0x80) >> 8)
    418 
    419 /** We take the original colors, not our premultiplied PMColors, since we can
    420     build a 16bit table as long as the original colors are opaque, even if the
    421     paint specifies a non-opaque alpha.
    422 */
    423 void Gradient_Shader::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
    424                                       int count) {
    425     SkASSERT(count > 1);
    426     SkASSERT(SkColorGetA(c0) == 0xFF);
    427     SkASSERT(SkColorGetA(c1) == 0xFF);
    428 
    429     SkFixed r = SkColorGetR(c0);
    430     SkFixed g = SkColorGetG(c0);
    431     SkFixed b = SkColorGetB(c0);
    432 
    433     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    434     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    435     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
    436 
    437     r = SkIntToFixed(r) + 0x8000;
    438     g = SkIntToFixed(g) + 0x8000;
    439     b = SkIntToFixed(b) + 0x8000;
    440 
    441     do {
    442         unsigned rr = r >> 16;
    443         unsigned gg = g >> 16;
    444         unsigned bb = b >> 16;
    445         cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
    446         cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
    447         cache += 1;
    448         r += dr;
    449         g += dg;
    450         b += db;
    451     } while (--count != 0);
    452 }
    453 
    454 static void build_32bit_cache(SkPMColor cache[], SkColor c0, SkColor c1,
    455                               int count, U8CPU paintAlpha) {
    456     SkASSERT(count > 1);
    457 
    458     // need to apply paintAlpha to our two endpoints
    459     SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
    460     SkFixed da;
    461     {
    462         int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
    463         da = SkIntToFixed(tmp - a) / (count - 1);
    464     }
    465 
    466     SkFixed r = SkColorGetR(c0);
    467     SkFixed g = SkColorGetG(c0);
    468     SkFixed b = SkColorGetB(c0);
    469     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    470     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    471     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
    472 
    473     a = SkIntToFixed(a) + 0x8000;
    474     r = SkIntToFixed(r) + 0x8000;
    475     g = SkIntToFixed(g) + 0x8000;
    476     b = SkIntToFixed(b) + 0x8000;
    477 
    478     do {
    479         *cache++ = SkPreMultiplyARGB(a >> 16, r >> 16, g >> 16, b >> 16);
    480         a += da;
    481         r += dr;
    482         g += dg;
    483         b += db;
    484     } while (--count != 0);
    485 }
    486 
    487 static inline int SkFixedToFFFF(SkFixed x) {
    488     SkASSERT((unsigned)x <= SK_Fixed1);
    489     return x - (x >> 16);
    490 }
    491 
    492 static inline U16CPU bitsTo16(unsigned x, const unsigned bits) {
    493     SkASSERT(x < (1U << bits));
    494     if (6 == bits) {
    495         return (x << 10) | (x << 4) | (x >> 2);
    496     }
    497     if (8 == bits) {
    498         return (x << 8) | x;
    499     }
    500     sk_throw();
    501     return 0;
    502 }
    503 
    504 const uint16_t* Gradient_Shader::getCache16() {
    505     if (fCache16 == NULL) {
    506         if (fCache16Storage == NULL) { // set the storage and our working ptr
    507             fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
    508         }
    509         fCache16 = fCache16Storage;
    510         if (fColorCount == 2) {
    511             Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], kCache16Count);
    512         } else {
    513             Rec* rec = fRecs;
    514             int prevIndex = 0;
    515             for (int i = 1; i < fColorCount; i++) {
    516                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
    517                 SkASSERT(nextIndex < kCache16Count);
    518 
    519                 if (nextIndex > prevIndex)
    520                     Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
    521                 prevIndex = nextIndex;
    522             }
    523             SkASSERT(prevIndex == kCache16Count - 1);
    524         }
    525 
    526         if (fMapper) {
    527             fCache16Storage = (uint16_t*)sk_malloc_throw(sizeof(uint16_t) * kCache16Count * 2);
    528             uint16_t* linear = fCache16;         // just computed linear data
    529             uint16_t* mapped = fCache16Storage;  // storage for mapped data
    530             SkUnitMapper* map = fMapper;
    531             for (int i = 0; i < kCache16Count; i++) {
    532                 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift;
    533                 mapped[i] = linear[index];
    534                 mapped[i + kCache16Count] = linear[index + kCache16Count];
    535             }
    536             sk_free(fCache16);
    537             fCache16 = fCache16Storage;
    538         }
    539     }
    540     return fCache16;
    541 }
    542 
    543 const SkPMColor* Gradient_Shader::getCache32() {
    544     if (fCache32 == NULL) {
    545         if (fCache32Storage == NULL) // set the storage and our working ptr
    546             fCache32Storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * kCache32Count);
    547 
    548         fCache32 = fCache32Storage;
    549         if (fColorCount == 2) {
    550             build_32bit_cache(fCache32, fOrigColors[0], fOrigColors[1],
    551                               kCache32Count, fCacheAlpha);
    552         } else {
    553             Rec* rec = fRecs;
    554             int prevIndex = 0;
    555             for (int i = 1; i < fColorCount; i++) {
    556                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> (16 - kCache32Bits);
    557                 SkASSERT(nextIndex < kCache32Count);
    558 
    559                 if (nextIndex > prevIndex)
    560                     build_32bit_cache(fCache32 + prevIndex, fOrigColors[i-1],
    561                                       fOrigColors[i],
    562                                       nextIndex - prevIndex + 1, fCacheAlpha);
    563                 prevIndex = nextIndex;
    564             }
    565             SkASSERT(prevIndex == kCache32Count - 1);
    566         }
    567 
    568         if (fMapper) {
    569             fCache32Storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * kCache32Count);
    570             SkPMColor* linear = fCache32;           // just computed linear data
    571             SkPMColor* mapped = fCache32Storage;    // storage for mapped data
    572             SkUnitMapper* map = fMapper;
    573             for (int i = 0; i < 256; i++) {
    574                 mapped[i] = linear[map->mapUnit16((i << 8) | i) >> 8];
    575             }
    576             sk_free(fCache32);
    577             fCache32 = fCache32Storage;
    578         }
    579     }
    580     return fCache32;
    581 }
    582 
    583 ///////////////////////////////////////////////////////////////////////////
    584 
    585 static void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) {
    586     SkVector    vec = pts[1] - pts[0];
    587     SkScalar    mag = vec.length();
    588     SkScalar    inv = mag ? SkScalarInvert(mag) : 0;
    589 
    590     vec.scale(inv);
    591     matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
    592     matrix->postTranslate(-pts[0].fX, -pts[0].fY);
    593     matrix->postScale(inv, inv);
    594 }
    595 
    596 ///////////////////////////////////////////////////////////////////////////////
    597 
    598 class Linear_Gradient : public Gradient_Shader {
    599 public:
    600     Linear_Gradient(const SkPoint pts[2],
    601                     const SkColor colors[], const SkScalar pos[], int colorCount,
    602                     SkShader::TileMode mode, SkUnitMapper* mapper)
    603         : Gradient_Shader(colors, pos, colorCount, mode, mapper)
    604     {
    605         fCachedBitmap = NULL;
    606         pts_to_unit_matrix(pts, &fPtsToUnit);
    607     }
    608     virtual ~Linear_Gradient() {
    609         if (fCachedBitmap) {
    610             SkDELETE(fCachedBitmap);
    611         }
    612     }
    613 
    614     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
    615     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
    616     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
    617     virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*);
    618     virtual void onCacheReset() {
    619         if (fCachedBitmap) {
    620             SkDELETE(fCachedBitmap);
    621             fCachedBitmap = NULL;
    622         }
    623     }
    624 
    625     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
    626         return SkNEW_ARGS(Linear_Gradient, (buffer));
    627     }
    628 
    629 protected:
    630     Linear_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {
    631         fCachedBitmap = NULL;
    632     }
    633     virtual Factory getFactory() { return CreateProc; }
    634 
    635 private:
    636     SkBitmap* fCachedBitmap;    // allocated on demand
    637 
    638     typedef Gradient_Shader INHERITED;
    639 };
    640 
    641 bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
    642                                  const SkMatrix& matrix) {
    643     if (!this->INHERITED::setContext(device, paint, matrix)) {
    644         return false;
    645     }
    646 
    647     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    648     if ((fDstToIndex.getType() & ~mask) == 0) {
    649         fFlags |= SkShader::kConstInY32_Flag;
    650         if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
    651             // only claim this if we do have a 16bit mode (i.e. none of our
    652             // colors have alpha), and if we are not dithering (which obviously
    653             // is not const in Y).
    654             fFlags |= SkShader::kConstInY16_Flag;
    655         }
    656     }
    657     return true;
    658 }
    659 
    660 //  Return true if fx, fx+dx, fx+2*dx, ... is always in range
    661 static inline bool no_need_for_clamp(int fx, int dx, int count)
    662 {
    663     SkASSERT(count > 0);
    664     return (unsigned)((fx | (fx + (count - 1) * dx)) >> 8) <= 0xFF;
    665 }
    666 
    667 void Linear_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count)
    668 {
    669     SkASSERT(count > 0);
    670 
    671     SkPoint             srcPt;
    672     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
    673     TileProc            proc = fTileProc;
    674     const SkPMColor*    cache = this->getCache32();
    675 
    676     if (fDstToIndexClass != kPerspective_MatrixClass) {
    677         dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
    678         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
    679         // preround fx by half the amount we throw away
    680         fx += 1 << 7;
    681 
    682         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
    683             SkFixed dxStorage[1];
    684             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
    685             dx = dxStorage[0];
    686         } else {
    687             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
    688             dx = SkScalarToFixed(fDstToIndex.getScaleX());
    689         }
    690 
    691         if (SkFixedNearlyZero(dx)) {
    692             // we're a vertical gradient, so no change in a span
    693             unsigned fi = proc(fx);
    694             SkASSERT(fi <= 0xFFFF);
    695             sk_memset32(dstC, cache[fi >> (16 - kCache32Bits)], count);
    696         } else if (proc == clamp_tileproc) {
    697 #if 0
    698             if (no_need_for_clamp(fx, dx, count))
    699             {
    700                 unsigned fi;
    701                 while ((count -= 4) >= 0)
    702                 {
    703                     fi = fx >> 8; SkASSERT(fi <= 0xFF); fx += dx; *dstC++ = cache[fi];
    704                     fi = fx >> 8; SkASSERT(fi <= 0xFF); fx += dx; *dstC++ = cache[fi];
    705                     fi = fx >> 8; SkASSERT(fi <= 0xFF); fx += dx; *dstC++ = cache[fi];
    706                     fi = fx >> 8; SkASSERT(fi <= 0xFF); fx += dx; *dstC++ = cache[fi];
    707                 }
    708                 SkASSERT(count <= -1 && count >= -4);
    709                 count += 4;
    710                 while (--count >= 0)
    711                 {
    712                     fi = fx >> 8;
    713                     SkASSERT(fi <= 0xFF);
    714                     fx += dx;
    715                     *dstC++ = cache[fi];
    716                 }
    717             }
    718             else
    719 #endif
    720                 do {
    721                     unsigned fi = SkClampMax(fx >> 8, 0xFF);
    722                     SkASSERT(fi <= 0xFF);
    723                     fx += dx;
    724                     *dstC++ = cache[fi];
    725                 } while (--count != 0);
    726         } else if (proc == mirror_tileproc) {
    727             do {
    728                 unsigned fi = mirror_8bits(fx >> 8);
    729                 SkASSERT(fi <= 0xFF);
    730                 fx += dx;
    731                 *dstC++ = cache[fi];
    732             } while (--count != 0);
    733         } else {
    734             SkASSERT(proc == repeat_tileproc);
    735             do {
    736                 unsigned fi = repeat_8bits(fx >> 8);
    737                 SkASSERT(fi <= 0xFF);
    738                 fx += dx;
    739                 *dstC++ = cache[fi];
    740             } while (--count != 0);
    741         }
    742     } else {
    743         SkScalar    dstX = SkIntToScalar(x);
    744         SkScalar    dstY = SkIntToScalar(y);
    745         do {
    746             dstProc(fDstToIndex, dstX, dstY, &srcPt);
    747             unsigned fi = proc(SkScalarToFixed(srcPt.fX));
    748             SkASSERT(fi <= 0xFFFF);
    749             *dstC++ = cache[fi >> (16 - kCache32Bits)];
    750             dstX += SK_Scalar1;
    751         } while (--count != 0);
    752     }
    753 }
    754 
    755 bool Linear_Gradient::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
    756                                 TileMode xy[]) {
    757     // we cache our "bitmap", so it's generationID will be const on subsequent
    758     // calls to asABitmap
    759     if (NULL == fCachedBitmap) {
    760         fCachedBitmap = SkNEW(SkBitmap);
    761         fCachedBitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1);
    762         fCachedBitmap->setPixels((void*)this->getCache32(), NULL);
    763     }
    764 
    765     if (bitmap) {
    766         *bitmap = *fCachedBitmap;
    767     }
    768     if (matrix) {
    769         matrix->setScale(SkIntToScalar(kCache32Count), SK_Scalar1);
    770         matrix->preConcat(fPtsToUnit);
    771     }
    772     if (xy) {
    773         xy[0] = fTileMode;
    774         xy[1] = kClamp_TileMode;
    775     }
    776     return true;
    777 }
    778 
    779 static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
    780                             int count) {
    781     if (reinterpret_cast<uintptr_t>(dst) & 2) {
    782         *dst++ = value;
    783         count -= 1;
    784         SkTSwap(value, other);
    785     }
    786 
    787     sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
    788 
    789     if (count & 1) {
    790         dst[count - 1] = value;
    791     }
    792 }
    793 
    794 void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
    795 {
    796     SkASSERT(count > 0);
    797 
    798     SkPoint             srcPt;
    799     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
    800     TileProc            proc = fTileProc;
    801     const uint16_t*     cache = this->getCache16();
    802     int                 toggle = ((x ^ y) & 1) << kCache16Bits;
    803 
    804     if (fDstToIndexClass != kPerspective_MatrixClass) {
    805         dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
    806         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
    807         // preround fx by half the amount we throw away
    808         fx += 1 << 7;
    809 
    810         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
    811             SkFixed dxStorage[1];
    812             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
    813             dx = dxStorage[0];
    814         } else {
    815             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
    816             dx = SkScalarToFixed(fDstToIndex.getScaleX());
    817         }
    818 
    819         if (SkFixedNearlyZero(dx)) {
    820             // we're a vertical gradient, so no change in a span
    821             unsigned fi = proc(fx) >> kCache16Shift;
    822             SkASSERT(fi <= kCache16Mask);
    823             dither_memset16(dstC, cache[toggle + fi], cache[(toggle ^ (1 << kCache16Bits)) + fi], count);
    824         } else if (proc == clamp_tileproc) {
    825             do {
    826                 unsigned fi = SkClampMax(fx >> kCache16Shift, kCache16Mask);
    827                 SkASSERT(fi <= kCache16Mask);
    828                 fx += dx;
    829                 *dstC++ = cache[toggle + fi];
    830                 toggle ^= (1 << kCache16Bits);
    831             } while (--count != 0);
    832         } else if (proc == mirror_tileproc) {
    833             do {
    834                 unsigned fi = mirror_bits(fx >> kCache16Shift, kCache16Bits);
    835                 SkASSERT(fi <= kCache16Mask);
    836                 fx += dx;
    837                 *dstC++ = cache[toggle + fi];
    838                 toggle ^= (1 << kCache16Bits);
    839             } while (--count != 0);
    840         } else {
    841             SkASSERT(proc == repeat_tileproc);
    842             do {
    843                 unsigned fi = repeat_bits(fx >> kCache16Shift, kCache16Bits);
    844                 SkASSERT(fi <= kCache16Mask);
    845                 fx += dx;
    846                 *dstC++ = cache[toggle + fi];
    847                 toggle ^= (1 << kCache16Bits);
    848             } while (--count != 0);
    849         }
    850     } else {
    851         SkScalar    dstX = SkIntToScalar(x);
    852         SkScalar    dstY = SkIntToScalar(y);
    853         do {
    854             dstProc(fDstToIndex, dstX, dstY, &srcPt);
    855             unsigned fi = proc(SkScalarToFixed(srcPt.fX));
    856             SkASSERT(fi <= 0xFFFF);
    857 
    858             int index = fi >> kCache16Shift;
    859             *dstC++ = cache[toggle + index];
    860             toggle ^= (1 << kCache16Bits);
    861 
    862             dstX += SK_Scalar1;
    863         } while (--count != 0);
    864     }
    865 }
    866 
    867 ///////////////////////////////////////////////////////////////////////////////
    868 
    869 #define kSQRT_TABLE_BITS    11
    870 #define kSQRT_TABLE_SIZE    (1 << kSQRT_TABLE_BITS)
    871 
    872 #include "SkRadialGradient_Table.h"
    873 
    874 #if defined(SK_BUILD_FOR_WIN32) && defined(SK_DEBUG)
    875 
    876 #include <stdio.h>
    877 
    878 void SkRadialGradient_BuildTable()
    879 {
    880     // build it 0..127 x 0..127, so we use 2^15 - 1 in the numerator for our "fixed" table
    881 
    882     FILE* file = ::fopen("SkRadialGradient_Table.h", "w");
    883     SkASSERT(file);
    884     ::fprintf(file, "static const uint8_t gSqrt8Table[] = {\n");
    885 
    886     for (int i = 0; i < kSQRT_TABLE_SIZE; i++)
    887     {
    888         if ((i & 15) == 0)
    889             ::fprintf(file, "\t");
    890 
    891         uint8_t value = SkToU8(SkFixedSqrt(i * SK_Fixed1 / kSQRT_TABLE_SIZE) >> 8);
    892 
    893         ::fprintf(file, "0x%02X", value);
    894         if (i < kSQRT_TABLE_SIZE-1)
    895             ::fprintf(file, ", ");
    896         if ((i & 15) == 15)
    897             ::fprintf(file, "\n");
    898     }
    899     ::fprintf(file, "};\n");
    900     ::fclose(file);
    901 }
    902 
    903 #endif
    904 
    905 
    906 static void rad_to_unit_matrix(const SkPoint& center, SkScalar radius, SkMatrix* matrix)
    907 {
    908     SkScalar    inv = SkScalarInvert(radius);
    909 
    910     matrix->setTranslate(-center.fX, -center.fY);
    911     matrix->postScale(inv, inv);
    912 }
    913 
    914 class Radial_Gradient : public Gradient_Shader {
    915 public:
    916     Radial_Gradient(const SkPoint& center, SkScalar radius,
    917                     const SkColor colors[], const SkScalar pos[], int colorCount,
    918                     SkShader::TileMode mode, SkUnitMapper* mapper)
    919         : Gradient_Shader(colors, pos, colorCount, mode, mapper)
    920     {
    921         // make sure our table is insync with our current #define for kSQRT_TABLE_SIZE
    922         SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE);
    923 
    924         rad_to_unit_matrix(center, radius, &fPtsToUnit);
    925     }
    926     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
    927     {
    928         SkASSERT(count > 0);
    929 
    930         SkPoint             srcPt;
    931         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
    932         TileProc            proc = fTileProc;
    933         const SkPMColor*    cache = this->getCache32();
    934 
    935         if (fDstToIndexClass != kPerspective_MatrixClass)
    936         {
    937             dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
    938             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
    939             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
    940 
    941             if (fDstToIndexClass == kFixedStepInX_MatrixClass)
    942             {
    943                 SkFixed storage[2];
    944                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
    945                 dx = storage[0];
    946                 dy = storage[1];
    947             }
    948             else
    949             {
    950                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
    951                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
    952                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
    953             }
    954 
    955             if (proc == clamp_tileproc)
    956             {
    957                 const uint8_t* sqrt_table = gSqrt8Table;
    958                 fx >>= 1;
    959                 dx >>= 1;
    960                 fy >>= 1;
    961                 dy >>= 1;
    962                 do {
    963                     unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
    964                     unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
    965                     fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
    966                     fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
    967                     *dstC++ = cache[sqrt_table[fi] >> (8 - kCache32Bits)];
    968                     fx += dx;
    969                     fy += dy;
    970                 } while (--count != 0);
    971             }
    972             else if (proc == mirror_tileproc)
    973             {
    974                 do {
    975                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
    976                     unsigned fi = mirror_tileproc(dist);
    977                     SkASSERT(fi <= 0xFFFF);
    978                     *dstC++ = cache[fi >> (16 - kCache32Bits)];
    979                     fx += dx;
    980                     fy += dy;
    981                 } while (--count != 0);
    982             }
    983             else
    984             {
    985                 SkASSERT(proc == repeat_tileproc);
    986                 do {
    987                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
    988                     unsigned fi = repeat_tileproc(dist);
    989                     SkASSERT(fi <= 0xFFFF);
    990                     *dstC++ = cache[fi >> (16 - kCache32Bits)];
    991                     fx += dx;
    992                     fy += dy;
    993                 } while (--count != 0);
    994             }
    995         }
    996         else    // perspective case
    997         {
    998             SkScalar dstX = SkIntToScalar(x);
    999             SkScalar dstY = SkIntToScalar(y);
   1000             do {
   1001                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1002                 unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   1003                 SkASSERT(fi <= 0xFFFF);
   1004                 *dstC++ = cache[fi >> (16 - kCache32Bits)];
   1005                 dstX += SK_Scalar1;
   1006             } while (--count != 0);
   1007         }
   1008     }
   1009 
   1010     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) {
   1011         SkASSERT(count > 0);
   1012 
   1013         SkPoint             srcPt;
   1014         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1015         TileProc            proc = fTileProc;
   1016         const uint16_t*     cache = this->getCache16();
   1017         int                 toggle = ((x ^ y) & 1) << kCache16Bits;
   1018 
   1019         if (fDstToIndexClass != kPerspective_MatrixClass) {
   1020             dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
   1021             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1022             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1023 
   1024             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   1025                 SkFixed storage[2];
   1026                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
   1027                 dx = storage[0];
   1028                 dy = storage[1];
   1029             } else {
   1030                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1031                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1032                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
   1033             }
   1034 
   1035             if (proc == clamp_tileproc) {
   1036                 const uint8_t* sqrt_table = gSqrt8Table;
   1037 
   1038                 /* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
   1039                     rather than 0xFFFF which is slower. This is a compromise, since it reduces our
   1040                     precision, but that appears to be visually OK. If we decide this is OK for
   1041                     all of our cases, we could (it seems) put this scale-down into fDstToIndex,
   1042                     to avoid having to do these extra shifts each time.
   1043                 */
   1044                 fx >>= 1;
   1045                 dx >>= 1;
   1046                 fy >>= 1;
   1047                 dy >>= 1;
   1048                 if (dy == 0) {    // might perform this check for the other modes, but the win will be a smaller % of the total
   1049                     fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   1050                     fy *= fy;
   1051                     do {
   1052                         unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   1053                         unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
   1054                         fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   1055                         fx += dx;
   1056                         *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
   1057                         toggle ^= (1 << kCache16Bits);
   1058                     } while (--count != 0);
   1059                 } else {
   1060                     do {
   1061                         unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   1062                         unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   1063                         fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
   1064                         fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   1065                         fx += dx;
   1066                         fy += dy;
   1067                         *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
   1068                         toggle ^= (1 << kCache16Bits);
   1069                     } while (--count != 0);
   1070                 }
   1071             } else if (proc == mirror_tileproc) {
   1072                 do {
   1073                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
   1074                     unsigned fi = mirror_tileproc(dist);
   1075                     SkASSERT(fi <= 0xFFFF);
   1076                     fx += dx;
   1077                     fy += dy;
   1078                     *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
   1079                     toggle ^= (1 << kCache16Bits);
   1080                 } while (--count != 0);
   1081             } else {
   1082                 SkASSERT(proc == repeat_tileproc);
   1083                 do {
   1084                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
   1085                     unsigned fi = repeat_tileproc(dist);
   1086                     SkASSERT(fi <= 0xFFFF);
   1087                     fx += dx;
   1088                     fy += dy;
   1089                     *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
   1090                     toggle ^= (1 << kCache16Bits);
   1091                 } while (--count != 0);
   1092             }
   1093         } else {    // perspective case
   1094             SkScalar dstX = SkIntToScalar(x);
   1095             SkScalar dstY = SkIntToScalar(y);
   1096             do {
   1097                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1098                 unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   1099                 SkASSERT(fi <= 0xFFFF);
   1100 
   1101                 int index = fi >> (16 - kCache16Bits);
   1102                 *dstC++ = cache[toggle + index];
   1103                 toggle ^= (1 << kCache16Bits);
   1104 
   1105                 dstX += SK_Scalar1;
   1106             } while (--count != 0);
   1107         }
   1108     }
   1109 
   1110     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1111         return SkNEW_ARGS(Radial_Gradient, (buffer));
   1112     }
   1113 
   1114 protected:
   1115     Radial_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {};
   1116     virtual Factory getFactory() { return CreateProc; }
   1117     virtual void onCacheReset() {}
   1118 
   1119 private:
   1120     typedef Gradient_Shader INHERITED;
   1121 };
   1122 
   1123 /* Two-point radial gradients are specified by two circles, each with a center
   1124    point and radius.  The gradient can be considered to be a series of
   1125    concentric circles, with the color interpolated from the start circle
   1126    (at t=0) to the end circle (at t=1).
   1127 
   1128    For each point (x, y) in the span, we want to find the
   1129    interpolated circle that intersects that point.  The center
   1130    of the desired circle (Cx, Cy) falls at some distance t
   1131    along the line segment between the start point (Sx, Sy) and
   1132    end point (Ex, Ey):
   1133 
   1134       Cx = (1 - t) * Sx + t * Ex        (0 <= t <= 1)
   1135       Cy = (1 - t) * Sy + t * Ey
   1136 
   1137    The radius of the desired circle (r) is also a linear interpolation t
   1138    between the start and end radii (Sr and Er):
   1139 
   1140       r = (1 - t) * Sr + t * Er
   1141 
   1142    But
   1143 
   1144       (x - Cx)^2 + (y - Cy)^2 = r^2
   1145 
   1146    so
   1147 
   1148      (x - ((1 - t) * Sx + t * Ex))^2
   1149    + (y - ((1 - t) * Sy + t * Ey))^2
   1150    = ((1 - t) * Sr + t * Er)^2
   1151 
   1152    Solving for t yields
   1153 
   1154      [(Sx - Ex)^2 + (Sy - Ey)^2 - (Er - Sr)^2)] * t^2
   1155    + [2 * (Sx - Ex)(x - Sx) + 2 * (Sy - Ey)(y - Sy) - 2 * (Er - Sr) * Sr] * t
   1156    + [(x - Sx)^2 + (y - Sy)^2 - Sr^2] = 0
   1157 
   1158    To simplify, let Dx = Sx - Ex, Dy = Sy - Ey, Dr = Er - Sr, dx = x - Sx, dy = y - Sy
   1159 
   1160      [Dx^2 + Dy^2 - Dr^2)] * t^2
   1161    + 2 * [Dx * dx + Dy * dy - Dr * Sr] * t
   1162    + [dx^2 + dy^2 - Sr^2] = 0
   1163 
   1164    A quadratic in t.  The two roots of the quadratic reflect the two
   1165    possible circles on which the point may fall.  Solving for t yields
   1166    the gradient value to use.
   1167 
   1168    If a<0, the start circle is entirely contained in the
   1169    end circle, and one of the roots will be <0 or >1 (off the line
   1170    segment).  If a>0, the start circle falls at least partially
   1171    outside the end circle (or vice versa), and the gradient
   1172    defines a "tube" where a point may be on one circle (on the
   1173    inside of the tube) or the other (outside of the tube).  We choose
   1174    one arbitrarily.
   1175 
   1176    In order to keep the math to within the limits of fixed point,
   1177    we divide the entire quadratic by Dr^2, and replace
   1178    (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
   1179 
   1180    [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
   1181    + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
   1182    + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
   1183 
   1184    (x' and y' are computed by appending the subtract and scale to the
   1185    fDstToIndex matrix in the constructor).
   1186 
   1187    Since the 'A' component of the quadratic is independent of x' and y', it
   1188    is precomputed in the constructor.  Since the 'B' component is linear in
   1189    x' and y', if x and y are linear in the span, 'B' can be computed
   1190    incrementally with a simple delta (db below).  If it is not (e.g.,
   1191    a perspective projection), it must be computed in the loop.
   1192 
   1193 */
   1194 
   1195 static inline SkFixed two_point_radial(SkFixed b, SkFixed fx, SkFixed fy, SkFixed sr2d2, SkFixed foura, SkFixed oneOverTwoA, bool posRoot) {
   1196     SkFixed c = SkFixedSquare(fx) + SkFixedSquare(fy) - sr2d2;
   1197     SkFixed discrim = SkFixedSquare(b) - SkFixedMul(foura, c);
   1198     if (discrim < 0) {
   1199         discrim = -discrim;
   1200     }
   1201     SkFixed rootDiscrim = SkFixedSqrt(discrim);
   1202     if (posRoot) {
   1203         return SkFixedMul(-b + rootDiscrim, oneOverTwoA);
   1204     } else {
   1205         return SkFixedMul(-b - rootDiscrim, oneOverTwoA);
   1206     }
   1207 }
   1208 
   1209 class Two_Point_Radial_Gradient : public Gradient_Shader {
   1210 public:
   1211     Two_Point_Radial_Gradient(const SkPoint& start, SkScalar startRadius,
   1212                               const SkPoint& end, SkScalar endRadius,
   1213                               const SkColor colors[], const SkScalar pos[],
   1214                               int colorCount, SkShader::TileMode mode,
   1215                               SkUnitMapper* mapper)
   1216         : Gradient_Shader(colors, pos, colorCount, mode, mapper)
   1217     {
   1218         fDiff = start - end;
   1219         fDiffRadius = endRadius - startRadius;
   1220         SkScalar inv = SkScalarInvert(fDiffRadius);
   1221         fDiff.fX = SkScalarMul(fDiff.fX, inv);
   1222         fDiff.fY = SkScalarMul(fDiff.fY, inv);
   1223         fStartRadius = SkScalarMul(startRadius, inv);
   1224         fSr2D2 = SkScalarSquare(fStartRadius);
   1225         fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
   1226         fOneOverTwoA = SkScalarInvert(fA * 2);
   1227 
   1228         fPtsToUnit.setTranslate(-start.fX, -start.fY);
   1229         fPtsToUnit.postScale(inv, inv);
   1230     }
   1231     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
   1232     {
   1233         SkASSERT(count > 0);
   1234 
   1235         // Zero difference between radii:  fill with transparent black.
   1236         if (fDiffRadius == 0) {
   1237           sk_bzero(dstC, count * sizeof(*dstC));
   1238           return;
   1239         }
   1240         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1241         TileProc            proc = fTileProc;
   1242         const SkPMColor*    cache = this->getCache32();
   1243         SkFixed diffx = SkScalarToFixed(fDiff.fX);
   1244         SkFixed diffy = SkScalarToFixed(fDiff.fY);
   1245         SkFixed foura = SkScalarToFixed(SkScalarMul(fA, 4));
   1246         SkFixed startRadius = SkScalarToFixed(fStartRadius);
   1247         SkFixed sr2D2 = SkScalarToFixed(fSr2D2);
   1248         SkFixed oneOverTwoA = SkScalarToFixed(fOneOverTwoA);
   1249         bool posRoot = fDiffRadius < 0;
   1250         if (fDstToIndexClass != kPerspective_MatrixClass)
   1251         {
   1252             SkPoint srcPt;
   1253             dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt);
   1254             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1255             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1256 
   1257             if (fDstToIndexClass == kFixedStepInX_MatrixClass)
   1258             {
   1259                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &dx, &dy);
   1260             }
   1261             else
   1262             {
   1263                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1264                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1265                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
   1266             }
   1267             SkFixed b = (SkFixedMul(diffx, fx) +
   1268                          SkFixedMul(diffy, fy) - startRadius) << 1;
   1269             SkFixed db = (SkFixedMul(diffx, dx) +
   1270                           SkFixedMul(diffy, dy)) << 1;
   1271             if (proc == clamp_tileproc)
   1272             {
   1273                 for (; count > 0; --count) {
   1274                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1275                     SkFixed index = SkClampMax(t, 0xFFFF);
   1276                     SkASSERT(index <= 0xFFFF);
   1277                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1278                     fx += dx;
   1279                     fy += dy;
   1280                     b += db;
   1281                 }
   1282             }
   1283             else if (proc == mirror_tileproc)
   1284             {
   1285                 for (; count > 0; --count) {
   1286                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1287                     SkFixed index = mirror_tileproc(t);
   1288                     SkASSERT(index <= 0xFFFF);
   1289                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1290                     fx += dx;
   1291                     fy += dy;
   1292                     b += db;
   1293                 }
   1294             }
   1295             else
   1296             {
   1297                 SkASSERT(proc == repeat_tileproc);
   1298                 for (; count > 0; --count) {
   1299                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1300                     SkFixed index = repeat_tileproc(t);
   1301                     SkASSERT(index <= 0xFFFF);
   1302                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1303                     fx += dx;
   1304                     fy += dy;
   1305                     b += db;
   1306                 }
   1307             }
   1308         }
   1309         else    // perspective case
   1310         {
   1311             SkScalar dstX = SkIntToScalar(x);
   1312             SkScalar dstY = SkIntToScalar(y);
   1313             for (; count > 0; --count) {
   1314                 SkPoint             srcPt;
   1315                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1316                 SkFixed fx = SkScalarToFixed(srcPt.fX);
   1317                 SkFixed fy = SkScalarToFixed(srcPt.fY);
   1318                 SkFixed b = (SkFixedMul(diffx, fx) +
   1319                              SkFixedMul(diffy, fy) - startRadius) << 1;
   1320                 SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1321                 SkFixed index = proc(t);
   1322                 SkASSERT(index <= 0xFFFF);
   1323                 *dstC++ = cache[index >> (16 - kCache32Bits)];
   1324                 dstX += SK_Scalar1;
   1325             }
   1326         }
   1327     }
   1328 
   1329     virtual bool setContext(const SkBitmap& device,
   1330                             const SkPaint& paint,
   1331                             const SkMatrix& matrix) {
   1332         if (!this->INHERITED::setContext(device, paint, matrix)) {
   1333             return false;
   1334         }
   1335 
   1336         // we don't have a span16 proc
   1337         fFlags &= ~kHasSpan16_Flag;
   1338         return true;
   1339     }
   1340 
   1341     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1342         return SkNEW_ARGS(Two_Point_Radial_Gradient, (buffer));
   1343     }
   1344 
   1345     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
   1346         this->INHERITED::flatten(buffer);
   1347         buffer.writeScalar(fDiff.fX);
   1348         buffer.writeScalar(fDiff.fY);
   1349         buffer.writeScalar(fStartRadius);
   1350         buffer.writeScalar(fDiffRadius);
   1351         buffer.writeScalar(fSr2D2);
   1352         buffer.writeScalar(fA);
   1353         buffer.writeScalar(fOneOverTwoA);
   1354     }
   1355 
   1356 protected:
   1357     Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
   1358             : Gradient_Shader(buffer) {
   1359         fDiff.fX = buffer.readScalar();
   1360         fDiff.fY = buffer.readScalar();
   1361         fStartRadius = buffer.readScalar();
   1362         fDiffRadius = buffer.readScalar();
   1363         fSr2D2 = buffer.readScalar();
   1364         fA = buffer.readScalar();
   1365         fOneOverTwoA = buffer.readScalar();
   1366     };
   1367     virtual Factory getFactory() { return CreateProc; }
   1368     virtual void onCacheReset() {}
   1369 
   1370 private:
   1371     typedef Gradient_Shader INHERITED;
   1372     SkPoint fDiff;
   1373     SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
   1374 };
   1375 
   1376 ///////////////////////////////////////////////////////////////////////////////
   1377 
   1378 class Sweep_Gradient : public Gradient_Shader {
   1379 public:
   1380     Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
   1381                    const SkScalar pos[], int count, SkUnitMapper* mapper)
   1382     : Gradient_Shader(colors, pos, count, SkShader::kClamp_TileMode, mapper)
   1383     {
   1384         fPtsToUnit.setTranslate(-cx, -cy);
   1385     }
   1386     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
   1387     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
   1388 
   1389     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1390         return SkNEW_ARGS(Sweep_Gradient, (buffer));
   1391     }
   1392 
   1393 protected:
   1394     Sweep_Gradient(SkFlattenableReadBuffer& buffer) : Gradient_Shader(buffer) {}
   1395     virtual Factory getFactory() { return CreateProc; }
   1396     virtual void onCacheReset() {}
   1397 
   1398 private:
   1399     typedef Gradient_Shader INHERITED;
   1400 };
   1401 
   1402 #ifdef COMPUTE_SWEEP_TABLE
   1403 #define PI  3.14159265
   1404 static bool gSweepTableReady;
   1405 static uint8_t gSweepTable[65];
   1406 
   1407 /*  Our table stores precomputed values for atan: [0...1] -> [0..PI/4]
   1408     We scale the results to [0..32]
   1409 */
   1410 static const uint8_t* build_sweep_table()
   1411 {
   1412     if (!gSweepTableReady)
   1413     {
   1414         const int N = 65;
   1415         const double DENOM = N - 1;
   1416 
   1417         for (int i = 0; i < N; i++)
   1418         {
   1419             double arg = i / DENOM;
   1420             double v = atan(arg);
   1421             int iv = (int)round(v * DENOM * 2 / PI);
   1422 //            printf("[%d] atan(%g) = %g %d\n", i, arg, v, iv);
   1423             printf("%d, ", iv);
   1424             gSweepTable[i] = iv;
   1425         }
   1426         gSweepTableReady = true;
   1427     }
   1428     return gSweepTable;
   1429 }
   1430 #else
   1431 static const uint8_t gSweepTable[] = {
   1432     0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9,
   1433     10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18,
   1434     19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26,
   1435     26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
   1436     32
   1437 };
   1438 static const uint8_t* build_sweep_table() { return gSweepTable; }
   1439 #endif
   1440 
   1441 // divide numer/denom, with a bias of 6bits. Assumes numer <= denom
   1442 // and denom != 0. Since our table is 6bits big (+1), this is a nice fit.
   1443 // Same as (but faster than) SkFixedDiv(numer, denom) >> 10
   1444 
   1445 //unsigned div_64(int numer, int denom);
   1446 static unsigned div_64(int numer, int denom)
   1447 {
   1448     SkASSERT(numer <= denom);
   1449     SkASSERT(numer > 0);
   1450     SkASSERT(denom > 0);
   1451 
   1452     int nbits = SkCLZ(numer);
   1453     int dbits = SkCLZ(denom);
   1454     int bits = 6 - nbits + dbits;
   1455     SkASSERT(bits <= 6);
   1456 
   1457     if (bits < 0)   // detect underflow
   1458         return 0;
   1459 
   1460     denom <<= dbits - 1;
   1461     numer <<= nbits - 1;
   1462 
   1463     unsigned result = 0;
   1464 
   1465     // do the first one
   1466     if ((numer -= denom) >= 0)
   1467         result = 1;
   1468     else
   1469         numer += denom;
   1470 
   1471     // Now fall into our switch statement if there are more bits to compute
   1472     if (bits > 0)
   1473     {
   1474         // make room for the rest of the answer bits
   1475         result <<= bits;
   1476         switch (bits) {
   1477         case 6:
   1478             if ((numer = (numer << 1) - denom) >= 0)
   1479                 result |= 32;
   1480             else
   1481                 numer += denom;
   1482         case 5:
   1483             if ((numer = (numer << 1) - denom) >= 0)
   1484                 result |= 16;
   1485             else
   1486                 numer += denom;
   1487         case 4:
   1488             if ((numer = (numer << 1) - denom) >= 0)
   1489                 result |= 8;
   1490             else
   1491                 numer += denom;
   1492         case 3:
   1493             if ((numer = (numer << 1) - denom) >= 0)
   1494                 result |= 4;
   1495             else
   1496                 numer += denom;
   1497         case 2:
   1498             if ((numer = (numer << 1) - denom) >= 0)
   1499                 result |= 2;
   1500             else
   1501                 numer += denom;
   1502         case 1:
   1503         default:    // not strictly need, but makes GCC make better ARM code
   1504             if ((numer = (numer << 1) - denom) >= 0)
   1505                 result |= 1;
   1506             else
   1507                 numer += denom;
   1508         }
   1509     }
   1510     return result;
   1511 }
   1512 
   1513 // Given x,y in the first quadrant, return 0..63 for the angle [0..90]
   1514 static unsigned atan_0_90(SkFixed y, SkFixed x)
   1515 {
   1516 #ifdef SK_DEBUG
   1517     {
   1518         static bool gOnce;
   1519         if (!gOnce)
   1520         {
   1521             gOnce = true;
   1522             SkASSERT(div_64(55, 55) == 64);
   1523             SkASSERT(div_64(128, 256) == 32);
   1524             SkASSERT(div_64(2326528, 4685824) == 31);
   1525             SkASSERT(div_64(753664, 5210112) == 9);
   1526             SkASSERT(div_64(229376, 4882432) == 3);
   1527             SkASSERT(div_64(2, 64) == 2);
   1528             SkASSERT(div_64(1, 64) == 1);
   1529             // test that we handle underflow correctly
   1530             SkASSERT(div_64(12345, 0x54321234) == 0);
   1531         }
   1532     }
   1533 #endif
   1534 
   1535     SkASSERT(y > 0 && x > 0);
   1536     const uint8_t* table = build_sweep_table();
   1537 
   1538     unsigned result;
   1539     bool swap = (x < y);
   1540     if (swap)
   1541     {
   1542         // first part of the atan(v) = PI/2 - atan(1/v) identity
   1543         // since our div_64 and table want v <= 1, where v = y/x
   1544         SkTSwap<SkFixed>(x, y);
   1545     }
   1546 
   1547     result = div_64(y, x);
   1548 
   1549 #ifdef SK_DEBUG
   1550     {
   1551         unsigned result2 = SkDivBits(y, x, 6);
   1552         SkASSERT(result2 == result ||
   1553                  (result == 1 && result2 == 0));
   1554     }
   1555 #endif
   1556 
   1557     SkASSERT(result < SK_ARRAY_COUNT(gSweepTable));
   1558     result = table[result];
   1559 
   1560     if (swap)
   1561     {
   1562         // complete the atan(v) = PI/2 - atan(1/v) identity
   1563         result = 64 - result;
   1564         // pin to 63
   1565         result -= result >> 6;
   1566     }
   1567 
   1568     SkASSERT(result <= 63);
   1569     return result;
   1570 }
   1571 
   1572 //  returns angle in a circle [0..2PI) -> [0..255]
   1573 static unsigned SkATan2_255(SkFixed y, SkFixed x)
   1574 {
   1575     if (x == 0)
   1576     {
   1577         if (y == 0)
   1578             return 0;
   1579         return y < 0 ? 192 : 64;
   1580     }
   1581     if (y == 0)
   1582         return x < 0 ? 128 : 0;
   1583 
   1584     /*  Find the right quadrant for x,y
   1585         Since atan_0_90 only handles the first quadrant, we rotate x,y
   1586         appropriately before calling it, and then add the right amount
   1587         to account for the real quadrant.
   1588         quadrant 0 : add 0                  | x > 0 && y > 0
   1589         quadrant 1 : add 64 (90 degrees)    | x < 0 && y > 0
   1590         quadrant 2 : add 128 (180 degrees)  | x < 0 && y < 0
   1591         quadrant 3 : add 192 (270 degrees)  | x > 0 && y < 0
   1592 
   1593         map x<0 to (1 << 6)
   1594         map y<0 to (3 << 6)
   1595         add = map_x ^ map_y
   1596     */
   1597     int xsign = x >> 31;
   1598     int ysign = y >> 31;
   1599     int add = ((-xsign) ^ (ysign & 3)) << 6;
   1600 
   1601 #ifdef SK_DEBUG
   1602     if (0 == add)
   1603         SkASSERT(x > 0 && y > 0);
   1604     else if (64 == add)
   1605         SkASSERT(x < 0 && y > 0);
   1606     else if (128 == add)
   1607         SkASSERT(x < 0 && y < 0);
   1608     else if (192 == add)
   1609         SkASSERT(x > 0 && y < 0);
   1610     else
   1611         SkASSERT(!"bad value for add");
   1612 #endif
   1613 
   1614     /*  This ^ trick makes x, y positive, and the swap<> handles quadrants
   1615         where we need to rotate x,y by 90 or -90
   1616     */
   1617     x = (x ^ xsign) - xsign;
   1618     y = (y ^ ysign) - ysign;
   1619     if (add & 64)               // quads 1 or 3 need to swap x,y
   1620         SkTSwap<SkFixed>(x, y);
   1621 
   1622     unsigned result = add + atan_0_90(y, x);
   1623     SkASSERT(result < 256);
   1624     return result;
   1625 }
   1626 
   1627 void Sweep_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count)
   1628 {
   1629     SkMatrix::MapXYProc proc = fDstToIndexProc;
   1630     const SkMatrix&     matrix = fDstToIndex;
   1631     const SkPMColor*    cache = this->getCache32();
   1632     SkPoint             srcPt;
   1633 
   1634     if (fDstToIndexClass != kPerspective_MatrixClass)
   1635     {
   1636         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   1637                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1638         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1639         SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1640 
   1641         if (fDstToIndexClass == kFixedStepInX_MatrixClass)
   1642         {
   1643             SkFixed storage[2];
   1644             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
   1645                                       &storage[0], &storage[1]);
   1646             dx = storage[0];
   1647             dy = storage[1];
   1648         }
   1649         else
   1650         {
   1651             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1652             dx = SkScalarToFixed(matrix.getScaleX());
   1653             dy = SkScalarToFixed(matrix.getSkewY());
   1654         }
   1655 
   1656         for (; count > 0; --count)
   1657         {
   1658             *dstC++ = cache[SkATan2_255(fy, fx)];
   1659             fx += dx;
   1660             fy += dy;
   1661         }
   1662     }
   1663     else    // perspective case
   1664     {
   1665         for (int stop = x + count; x < stop; x++)
   1666         {
   1667             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   1668                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1669 
   1670             int index = SkATan2_255(SkScalarToFixed(srcPt.fY),
   1671                                     SkScalarToFixed(srcPt.fX));
   1672             *dstC++ = cache[index];
   1673         }
   1674     }
   1675 }
   1676 
   1677 void Sweep_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count)
   1678 {
   1679     SkMatrix::MapXYProc proc = fDstToIndexProc;
   1680     const SkMatrix&     matrix = fDstToIndex;
   1681     const uint16_t*     cache = this->getCache16();
   1682     int                 toggle = ((x ^ y) & 1) << kCache16Bits;
   1683     SkPoint             srcPt;
   1684 
   1685     if (fDstToIndexClass != kPerspective_MatrixClass)
   1686     {
   1687         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   1688                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1689         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1690         SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1691 
   1692         if (fDstToIndexClass == kFixedStepInX_MatrixClass)
   1693         {
   1694             SkFixed storage[2];
   1695             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
   1696                                       &storage[0], &storage[1]);
   1697             dx = storage[0];
   1698             dy = storage[1];
   1699         }
   1700         else
   1701         {
   1702             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1703             dx = SkScalarToFixed(matrix.getScaleX());
   1704             dy = SkScalarToFixed(matrix.getSkewY());
   1705         }
   1706 
   1707         for (; count > 0; --count)
   1708         {
   1709             int index = SkATan2_255(fy, fx) >> (8 - kCache16Bits);
   1710             *dstC++ = cache[toggle + index];
   1711             toggle ^= (1 << kCache16Bits);
   1712             fx += dx;
   1713             fy += dy;
   1714         }
   1715     }
   1716     else    // perspective case
   1717     {
   1718         for (int stop = x + count; x < stop; x++)
   1719         {
   1720             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   1721                          SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1722 
   1723             int index = SkATan2_255(SkScalarToFixed(srcPt.fY),
   1724                                     SkScalarToFixed(srcPt.fX));
   1725             index >>= (8 - kCache16Bits);
   1726             *dstC++ = cache[toggle + index];
   1727             toggle ^= (1 << kCache16Bits);
   1728         }
   1729     }
   1730 }
   1731 
   1732 ///////////////////////////////////////////////////////////////////////////
   1733 ///////////////////////////////////////////////////////////////////////////
   1734 
   1735 // assumes colors is SkColor* and pos is SkScalar*
   1736 #define EXPAND_1_COLOR(count)               \
   1737     SkColor tmp[2];                         \
   1738     do {                                    \
   1739         if (1 == count) {                   \
   1740             tmp[0] = tmp[1] = colors[0];    \
   1741             colors = tmp;                   \
   1742             pos = NULL;                     \
   1743             count = 2;                      \
   1744         }                                   \
   1745     } while (0)
   1746 
   1747 SkShader* SkGradientShader::CreateLinear(   const SkPoint pts[2],
   1748                                             const SkColor colors[], const SkScalar pos[], int colorCount,
   1749                                             SkShader::TileMode mode, SkUnitMapper* mapper)
   1750 {
   1751     if (NULL == pts || NULL == colors || colorCount < 1) {
   1752         return NULL;
   1753     }
   1754     EXPAND_1_COLOR(colorCount);
   1755 
   1756     return SkNEW_ARGS(Linear_Gradient,
   1757                       (pts, colors, pos, colorCount, mode, mapper));
   1758 }
   1759 
   1760 SkShader* SkGradientShader::CreateRadial(   const SkPoint& center, SkScalar radius,
   1761                                             const SkColor colors[], const SkScalar pos[], int colorCount,
   1762                                             SkShader::TileMode mode, SkUnitMapper* mapper)
   1763 {
   1764     if (radius <= 0 || NULL == colors || colorCount < 1) {
   1765         return NULL;
   1766     }
   1767     EXPAND_1_COLOR(colorCount);
   1768 
   1769     return SkNEW_ARGS(Radial_Gradient,
   1770                       (center, radius, colors, pos, colorCount, mode, mapper));
   1771 }
   1772 
   1773 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
   1774                                                  SkScalar startRadius,
   1775                                                  const SkPoint& end,
   1776                                                  SkScalar endRadius,
   1777                                                  const SkColor colors[],
   1778                                                  const SkScalar pos[],
   1779                                                  int colorCount,
   1780                                                  SkShader::TileMode mode,
   1781                                                  SkUnitMapper* mapper)
   1782 {
   1783     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
   1784         return NULL;
   1785     }
   1786     EXPAND_1_COLOR(colorCount);
   1787 
   1788     return SkNEW_ARGS(Two_Point_Radial_Gradient,
   1789                       (start, startRadius, end, endRadius, colors, pos, colorCount, mode, mapper));
   1790 }
   1791 
   1792 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
   1793                                         const SkColor colors[],
   1794                                         const SkScalar pos[],
   1795                                         int count, SkUnitMapper* mapper)
   1796 {
   1797     if (NULL == colors || count < 1) {
   1798         return NULL;
   1799     }
   1800     EXPAND_1_COLOR(count);
   1801 
   1802     return SkNEW_ARGS(Sweep_Gradient, (cx, cy, colors, pos, count, mapper));
   1803 }
   1804 
   1805 static SkFlattenable::Registrar gLinearGradientReg("Linear_Gradient",
   1806                                                    Linear_Gradient::CreateProc);
   1807 
   1808 static SkFlattenable::Registrar gRadialGradientReg("Radial_Gradient",
   1809                                                    Radial_Gradient::CreateProc);
   1810 
   1811 static SkFlattenable::Registrar gSweepGradientReg("Sweep_Gradient",
   1812                                                    Sweep_Gradient::CreateProc);
   1813 
   1814