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 "SkMallocPixelRef.h"
     21 #include "SkUnitMapper.h"
     22 #include "SkUtils.h"
     23 #include "SkTemplates.h"
     24 #include "SkBitmapCache.h"
     25 
     26 #ifndef SK_DISABLE_DITHER_32BIT_GRADIENT
     27     #define USE_DITHER_32BIT_GRADIENT
     28 #endif
     29 
     30 #define SK_ENABLE_FAST_LINEAR_GRADIENTS
     31 
     32 #ifdef SK_ENABLE_FAST_LINEAR_GRADIENTS
     33 static void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
     34                                int count) {
     35     if (count > 0) {
     36         if (v0 == v1) {
     37             sk_memset32(dst, v0, count);
     38         } else {
     39             int pairs = count >> 1;
     40             for (int i = 0; i < pairs; i++) {
     41                 *dst++ = v0;
     42                 *dst++ = v1;
     43             }
     44             if (count & 1) {
     45                 *dst = v0;
     46             }
     47         }
     48     }
     49 }
     50 #endif
     51 
     52 ///////////////////////////////////////////////////////////////////////////////
     53 // Can't use a two-argument function with side effects like this in a
     54 // constructor's initializer's argument list because the order of
     55 // evaluations in that context is undefined (and backwards on linux/gcc).
     56 static SkPoint unflatten_point(SkReader32& buffer) {
     57     SkPoint retval;
     58     retval.fX = buffer.readScalar();
     59     retval.fY = buffer.readScalar();
     60     return retval;
     61 }
     62 
     63 ///////////////////////////////////////////////////////////////////////////////
     64 
     65 typedef SkFixed (*TileProc)(SkFixed);
     66 
     67 static SkFixed clamp_tileproc(SkFixed x) {
     68     return SkClampMax(x, 0xFFFF);
     69 }
     70 
     71 static SkFixed repeat_tileproc(SkFixed x) {
     72     return x & 0xFFFF;
     73 }
     74 
     75 static inline SkFixed mirror_tileproc(SkFixed x) {
     76     int s = x << 15 >> 31;
     77     return (x ^ s) & 0xFFFF;
     78 }
     79 
     80 static const TileProc gTileProcs[] = {
     81     clamp_tileproc,
     82     repeat_tileproc,
     83     mirror_tileproc
     84 };
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 
     88 static inline int repeat_bits(int x, const int bits) {
     89     return x & ((1 << bits) - 1);
     90 }
     91 
     92 static inline int mirror_bits(int x, const int bits) {
     93 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
     94     if (x & (1 << bits))
     95         x = ~x;
     96     return x & ((1 << bits) - 1);
     97 #else
     98     int s = x << (31 - bits) >> 31;
     99     return (x ^ s) & ((1 << bits) - 1);
    100 #endif
    101 }
    102 
    103 static inline int repeat_8bits(int x) {
    104     return x & 0xFF;
    105 }
    106 
    107 static inline int mirror_8bits(int x) {
    108 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
    109     if (x & 256) {
    110         x = ~x;
    111     }
    112     return x & 255;
    113 #else
    114     int s = x << 23 >> 31;
    115     return (x ^ s) & 0xFF;
    116 #endif
    117 }
    118 
    119 ///////////////////////////////////////////////////////////////////////////////
    120 
    121 class Gradient_Shader : public SkShader {
    122 public:
    123     Gradient_Shader(const SkColor colors[], const SkScalar pos[],
    124                 int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper);
    125     virtual ~Gradient_Shader();
    126 
    127     // overrides
    128     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
    129     virtual uint32_t getFlags() { return fFlags; }
    130 
    131 protected:
    132     Gradient_Shader(SkFlattenableReadBuffer& );
    133     SkUnitMapper* fMapper;
    134     SkMatrix    fPtsToUnit;     // set by subclass
    135     SkMatrix    fDstToIndex;
    136     SkMatrix::MapXYProc fDstToIndexProc;
    137     TileMode    fTileMode;
    138     TileProc    fTileProc;
    139     int         fColorCount;
    140     uint8_t     fDstToIndexClass;
    141     uint8_t     fFlags;
    142 
    143     struct Rec {
    144         SkFixed     fPos;   // 0...1
    145         uint32_t    fScale; // (1 << 24) / range
    146     };
    147     Rec*        fRecs;
    148 
    149     enum {
    150         kCache16Bits    = 8,    // seems like enough for visual accuracy
    151         kCache16Count   = 1 << kCache16Bits,
    152         kCache16Mask    = kCache16Count - 1,
    153         kCache16Shift   = 16 - kCache16Bits,
    154 
    155         kCache32Bits    = 8,    // pretty much should always be 8
    156         kCache32Count   = 1 << kCache32Bits
    157     };
    158     virtual void flatten(SkFlattenableWriteBuffer& );
    159     const uint16_t*     getCache16() const;
    160     const SkPMColor*    getCache32() const;
    161 
    162     void commonAsABitmap(SkBitmap*) const;
    163     void commonAsAGradient(GradientInfo*) const;
    164 
    165 private:
    166     enum {
    167         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
    168 
    169         kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
    170     };
    171     SkColor     fStorage[(kStorageSize + 3) >> 2];
    172     SkColor*    fOrigColors;
    173 
    174     mutable uint16_t*   fCache16;   // working ptr. If this is NULL, we need to recompute the cache values
    175     mutable SkPMColor*  fCache32;   // working ptr. If this is NULL, we need to recompute the cache values
    176 
    177     mutable uint16_t*   fCache16Storage;    // storage for fCache16, allocated on demand
    178     mutable SkMallocPixelRef* fCache32PixelRef;
    179     unsigned    fCacheAlpha;        // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
    180 
    181     static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
    182     static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
    183                                 U8CPU alpha);
    184 
    185     typedef SkShader INHERITED;
    186 };
    187 
    188 static inline unsigned scalarToU16(SkScalar x) {
    189     SkASSERT(x >= 0 && x <= SK_Scalar1);
    190 
    191 #ifdef SK_SCALAR_IS_FLOAT
    192     return (unsigned)(x * 0xFFFF);
    193 #else
    194     return x - (x >> 16);   // probably should be x - (x > 0x7FFF) but that is slower
    195 #endif
    196 }
    197 
    198 Gradient_Shader::Gradient_Shader(const SkColor colors[], const SkScalar pos[],
    199              int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) {
    200     SkASSERT(colorCount > 1);
    201 
    202     fCacheAlpha = 256;  // init to a value that paint.getAlpha() can't return
    203 
    204     fMapper = mapper;
    205     SkSafeRef(mapper);
    206 
    207     SkASSERT((unsigned)mode < SkShader::kTileModeCount);
    208     SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
    209     fTileMode = mode;
    210     fTileProc = gTileProcs[mode];
    211 
    212     fCache16 = fCache16Storage = NULL;
    213     fCache32 = NULL;
    214     fCache32PixelRef = NULL;
    215 
    216     /*  Note: we let the caller skip the first and/or last position.
    217         i.e. pos[0] = 0.3, pos[1] = 0.7
    218         In these cases, we insert dummy entries to ensure that the final data
    219         will be bracketed by [0, 1].
    220         i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1
    221 
    222         Thus colorCount (the caller's value, and fColorCount (our value) may
    223         differ by up to 2. In the above example:
    224             colorCount = 2
    225             fColorCount = 4
    226      */
    227     fColorCount = colorCount;
    228     // check if we need to add in dummy start and/or end position/colors
    229     bool dummyFirst = false;
    230     bool dummyLast = false;
    231     if (pos) {
    232         dummyFirst = pos[0] != 0;
    233         dummyLast = pos[colorCount - 1] != SK_Scalar1;
    234         fColorCount += dummyFirst + dummyLast;
    235     }
    236 
    237     if (fColorCount > kColorStorageCount) {
    238         size_t size = sizeof(SkColor) + sizeof(Rec);
    239         fOrigColors = reinterpret_cast<SkColor*>(
    240                                         sk_malloc_throw(size * fColorCount));
    241     }
    242     else {
    243         fOrigColors = fStorage;
    244     }
    245 
    246     // Now copy over the colors, adding the dummies as needed
    247     {
    248         SkColor* origColors = fOrigColors;
    249         if (dummyFirst) {
    250             *origColors++ = colors[0];
    251         }
    252         memcpy(origColors, colors, colorCount * sizeof(SkColor));
    253         if (dummyLast) {
    254             origColors += colorCount;
    255             *origColors = colors[colorCount - 1];
    256         }
    257     }
    258 
    259     fRecs = (Rec*)(fOrigColors + fColorCount);
    260     if (fColorCount > 2) {
    261         Rec* recs = fRecs;
    262         recs->fPos = 0;
    263         //  recs->fScale = 0; // unused;
    264         recs += 1;
    265         if (pos) {
    266             /*  We need to convert the user's array of relative positions into
    267                 fixed-point positions and scale factors. We need these results
    268                 to be strictly monotonic (no two values equal or out of order).
    269                 Hence this complex loop that just jams a zero for the scale
    270                 value if it sees a segment out of order, and it assures that
    271                 we start at 0 and end at 1.0
    272             */
    273             SkFixed prev = 0;
    274             int startIndex = dummyFirst ? 0 : 1;
    275             int count = colorCount + dummyLast;
    276             for (int i = startIndex; i < count; i++) {
    277                 // force the last value to be 1.0
    278                 SkFixed curr;
    279                 if (i == colorCount) {  // we're really at the dummyLast
    280                     curr = SK_Fixed1;
    281                 } else {
    282                     curr = SkScalarToFixed(pos[i]);
    283                 }
    284                 // pin curr withing range
    285                 if (curr < 0) {
    286                     curr = 0;
    287                 } else if (curr > SK_Fixed1) {
    288                     curr = SK_Fixed1;
    289                 }
    290                 recs->fPos = curr;
    291                 if (curr > prev) {
    292                     recs->fScale = (1 << 24) / (curr - prev);
    293                 } else {
    294                     recs->fScale = 0; // ignore this segment
    295                 }
    296                 // get ready for the next value
    297                 prev = curr;
    298                 recs += 1;
    299             }
    300         } else {    // assume even distribution
    301             SkFixed dp = SK_Fixed1 / (colorCount - 1);
    302             SkFixed p = dp;
    303             SkFixed scale = (colorCount - 1) << 8;  // (1 << 24) / dp
    304             for (int i = 1; i < colorCount; i++) {
    305                 recs->fPos   = p;
    306                 recs->fScale = scale;
    307                 recs += 1;
    308                 p += dp;
    309             }
    310         }
    311     }
    312     fFlags = 0;
    313 }
    314 
    315 Gradient_Shader::Gradient_Shader(SkFlattenableReadBuffer& buffer) :
    316     INHERITED(buffer) {
    317     fCacheAlpha = 256;
    318 
    319     fMapper = static_cast<SkUnitMapper*>(buffer.readFlattenable());
    320 
    321     fCache16 = fCache16Storage = NULL;
    322     fCache32 = NULL;
    323     fCache32PixelRef = NULL;
    324 
    325     int colorCount = fColorCount = buffer.readU32();
    326     if (colorCount > kColorStorageCount) {
    327         size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec);
    328         fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount);
    329     } else {
    330         fOrigColors = fStorage;
    331     }
    332     buffer.read(fOrigColors, colorCount * sizeof(SkColor));
    333 
    334     fTileMode = (TileMode)buffer.readU8();
    335     fTileProc = gTileProcs[fTileMode];
    336     fRecs = (Rec*)(fOrigColors + colorCount);
    337     if (colorCount > 2) {
    338         Rec* recs = fRecs;
    339         recs[0].fPos = 0;
    340         for (int i = 1; i < colorCount; i++) {
    341             recs[i].fPos = buffer.readS32();
    342             recs[i].fScale = buffer.readU32();
    343         }
    344     }
    345     SkReadMatrix(&buffer, &fPtsToUnit);
    346     fFlags = 0;
    347 }
    348 
    349 Gradient_Shader::~Gradient_Shader() {
    350     if (fCache16Storage) {
    351         sk_free(fCache16Storage);
    352     }
    353     SkSafeUnref(fCache32PixelRef);
    354     if (fOrigColors != fStorage) {
    355         sk_free(fOrigColors);
    356     }
    357     SkSafeUnref(fMapper);
    358 }
    359 
    360 void Gradient_Shader::flatten(SkFlattenableWriteBuffer& buffer) {
    361     this->INHERITED::flatten(buffer);
    362     buffer.writeFlattenable(fMapper);
    363     buffer.write32(fColorCount);
    364     buffer.writeMul4(fOrigColors, fColorCount * sizeof(SkColor));
    365     buffer.write8(fTileMode);
    366     if (fColorCount > 2) {
    367         Rec* recs = fRecs;
    368         for (int i = 1; i < fColorCount; i++) {
    369             buffer.write32(recs[i].fPos);
    370             buffer.write32(recs[i].fScale);
    371         }
    372     }
    373     SkWriteMatrix(&buffer, fPtsToUnit);
    374 }
    375 
    376 bool Gradient_Shader::setContext(const SkBitmap& device,
    377                                  const SkPaint& paint,
    378                                  const SkMatrix& matrix) {
    379     if (!this->INHERITED::setContext(device, paint, matrix)) {
    380         return false;
    381     }
    382 
    383     const SkMatrix& inverse = this->getTotalInverse();
    384 
    385     if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) {
    386         return false;
    387     }
    388 
    389     fDstToIndexProc = fDstToIndex.getMapXYProc();
    390     fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex);
    391 
    392     // now convert our colors in to PMColors
    393     unsigned paintAlpha = this->getPaintAlpha();
    394     unsigned colorAlpha = 0xFF;
    395 
    396     // FIXME: record colorAlpha in constructor, since this is not affected
    397     // by setContext()
    398     for (int i = 0; i < fColorCount; i++) {
    399         SkColor src = fOrigColors[i];
    400         unsigned sa = SkColorGetA(src);
    401         colorAlpha &= sa;
    402     }
    403 
    404     fFlags = this->INHERITED::getFlags();
    405     if ((colorAlpha & paintAlpha) == 0xFF) {
    406         fFlags |= kOpaqueAlpha_Flag;
    407     }
    408     // we can do span16 as long as our individual colors are opaque,
    409     // regardless of the paint's alpha
    410     if (0xFF == colorAlpha) {
    411         fFlags |= kHasSpan16_Flag;
    412     }
    413 
    414     // if the new alpha differs from the previous time we were called, inval our cache
    415     // this will trigger the cache to be rebuilt.
    416     // we don't care about the first time, since the cache ptrs will already be NULL
    417     if (fCacheAlpha != paintAlpha) {
    418         fCache16 = NULL;                // inval the cache
    419         fCache32 = NULL;                // inval the cache
    420         fCacheAlpha = paintAlpha;       // record the new alpha
    421         // inform our subclasses
    422         if (fCache32PixelRef) {
    423             fCache32PixelRef->notifyPixelsChanged();
    424         }
    425     }
    426     return true;
    427 }
    428 
    429 static inline int blend8(int a, int b, int scale) {
    430     SkASSERT(a == SkToU8(a));
    431     SkASSERT(b == SkToU8(b));
    432     SkASSERT(scale >= 0 && scale <= 256);
    433     return a + ((b - a) * scale >> 8);
    434 }
    435 
    436 static inline uint32_t dot8_blend_packed32(uint32_t s0, uint32_t s1,
    437                                            int blend) {
    438 #if 0
    439     int a = blend8(SkGetPackedA32(s0), SkGetPackedA32(s1), blend);
    440     int r = blend8(SkGetPackedR32(s0), SkGetPackedR32(s1), blend);
    441     int g = blend8(SkGetPackedG32(s0), SkGetPackedG32(s1), blend);
    442     int b = blend8(SkGetPackedB32(s0), SkGetPackedB32(s1), blend);
    443 
    444     return SkPackARGB32(a, r, g, b);
    445 #else
    446     int otherBlend = 256 - blend;
    447 
    448 #if 0
    449     U32 t0 = (((s0 & 0xFF00FF) * blend + (s1 & 0xFF00FF) * otherBlend) >> 8) & 0xFF00FF;
    450     U32 t1 = (((s0 >> 8) & 0xFF00FF) * blend + ((s1 >> 8) & 0xFF00FF) * otherBlend) & 0xFF00FF00;
    451     SkASSERT((t0 & t1) == 0);
    452     return t0 | t1;
    453 #else
    454     return  ((((s0 & 0xFF00FF) * blend + (s1 & 0xFF00FF) * otherBlend) >> 8) & 0xFF00FF) |
    455             ((((s0 >> 8) & 0xFF00FF) * blend + ((s1 >> 8) & 0xFF00FF) * otherBlend) & 0xFF00FF00);
    456 #endif
    457 
    458 #endif
    459 }
    460 
    461 #define Fixed_To_Dot8(x)        (((x) + 0x80) >> 8)
    462 
    463 /** We take the original colors, not our premultiplied PMColors, since we can
    464     build a 16bit table as long as the original colors are opaque, even if the
    465     paint specifies a non-opaque alpha.
    466 */
    467 void Gradient_Shader::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
    468                                       int count) {
    469     SkASSERT(count > 1);
    470     SkASSERT(SkColorGetA(c0) == 0xFF);
    471     SkASSERT(SkColorGetA(c1) == 0xFF);
    472 
    473     SkFixed r = SkColorGetR(c0);
    474     SkFixed g = SkColorGetG(c0);
    475     SkFixed b = SkColorGetB(c0);
    476 
    477     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    478     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    479     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
    480 
    481     r = SkIntToFixed(r) + 0x8000;
    482     g = SkIntToFixed(g) + 0x8000;
    483     b = SkIntToFixed(b) + 0x8000;
    484 
    485     do {
    486         unsigned rr = r >> 16;
    487         unsigned gg = g >> 16;
    488         unsigned bb = b >> 16;
    489         cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
    490         cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
    491         cache += 1;
    492         r += dr;
    493         g += dg;
    494         b += db;
    495     } while (--count != 0);
    496 }
    497 
    498 /*
    499  *  2x2 dither a fixed-point color component (8.16) down to 8, matching the
    500  *  semantics of how we 2x2 dither 32->16
    501  */
    502 static inline U8CPU dither_fixed_to_8(SkFixed n) {
    503     n >>= 8;
    504     return ((n << 1) - ((n >> 8 << 8) | (n >> 8))) >> 8;
    505 }
    506 
    507 /*
    508  *  For dithering with premultiply, we want to ceiling the alpha component,
    509  *  to ensure that it is always >= any color component.
    510  */
    511 static inline U8CPU dither_ceil_fixed_to_8(SkFixed n) {
    512     n >>= 8;
    513     return ((n << 1) - (n | (n >> 8))) >> 8;
    514 }
    515 
    516 void Gradient_Shader::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
    517                                       int count, U8CPU paintAlpha) {
    518     SkASSERT(count > 1);
    519 
    520     // need to apply paintAlpha to our two endpoints
    521     SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
    522     SkFixed da;
    523     {
    524         int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
    525         da = SkIntToFixed(tmp - a) / (count - 1);
    526     }
    527 
    528     SkFixed r = SkColorGetR(c0);
    529     SkFixed g = SkColorGetG(c0);
    530     SkFixed b = SkColorGetB(c0);
    531     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    532     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    533     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
    534 
    535     a = SkIntToFixed(a) + 0x8000;
    536     r = SkIntToFixed(r) + 0x8000;
    537     g = SkIntToFixed(g) + 0x8000;
    538     b = SkIntToFixed(b) + 0x8000;
    539 
    540     do {
    541         cache[0] = SkPreMultiplyARGB(a >> 16, r >> 16, g >> 16, b >> 16);
    542         cache[kCache32Count] = SkPreMultiplyARGB(dither_ceil_fixed_to_8(a),
    543                                                  dither_fixed_to_8(r),
    544                                                  dither_fixed_to_8(g),
    545                                                  dither_fixed_to_8(b));
    546         cache += 1;
    547         a += da;
    548         r += dr;
    549         g += dg;
    550         b += db;
    551     } while (--count != 0);
    552 }
    553 
    554 static inline int SkFixedToFFFF(SkFixed x) {
    555     SkASSERT((unsigned)x <= SK_Fixed1);
    556     return x - (x >> 16);
    557 }
    558 
    559 static inline U16CPU bitsTo16(unsigned x, const unsigned bits) {
    560     SkASSERT(x < (1U << bits));
    561     if (6 == bits) {
    562         return (x << 10) | (x << 4) | (x >> 2);
    563     }
    564     if (8 == bits) {
    565         return (x << 8) | x;
    566     }
    567     sk_throw();
    568     return 0;
    569 }
    570 
    571 const uint16_t* Gradient_Shader::getCache16() const {
    572     if (fCache16 == NULL) {
    573         // double the count for dither entries
    574         const int entryCount = kCache16Count * 2;
    575         const size_t allocSize = sizeof(uint16_t) * entryCount;
    576 
    577         if (fCache16Storage == NULL) { // set the storage and our working ptr
    578             fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
    579         }
    580         fCache16 = fCache16Storage;
    581         if (fColorCount == 2) {
    582             Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], kCache16Count);
    583         } else {
    584             Rec* rec = fRecs;
    585             int prevIndex = 0;
    586             for (int i = 1; i < fColorCount; i++) {
    587                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
    588                 SkASSERT(nextIndex < kCache16Count);
    589 
    590                 if (nextIndex > prevIndex)
    591                     Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
    592                 prevIndex = nextIndex;
    593             }
    594             SkASSERT(prevIndex == kCache16Count - 1);
    595         }
    596 
    597         if (fMapper) {
    598             fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
    599             uint16_t* linear = fCache16;         // just computed linear data
    600             uint16_t* mapped = fCache16Storage;  // storage for mapped data
    601             SkUnitMapper* map = fMapper;
    602             for (int i = 0; i < kCache16Count; i++) {
    603                 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift;
    604                 mapped[i] = linear[index];
    605                 mapped[i + kCache16Count] = linear[index + kCache16Count];
    606             }
    607             sk_free(fCache16);
    608             fCache16 = fCache16Storage;
    609         }
    610     }
    611     return fCache16;
    612 }
    613 
    614 const SkPMColor* Gradient_Shader::getCache32() const {
    615     if (fCache32 == NULL) {
    616         // double the count for dither entries
    617         const int entryCount = kCache32Count * 2;
    618         const size_t allocSize = sizeof(SkPMColor) * entryCount;
    619 
    620         if (NULL == fCache32PixelRef) {
    621             fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef,
    622                                           (NULL, allocSize, NULL));
    623         }
    624         fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
    625         if (fColorCount == 2) {
    626             Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
    627                             kCache32Count, fCacheAlpha);
    628         } else {
    629             Rec* rec = fRecs;
    630             int prevIndex = 0;
    631             for (int i = 1; i < fColorCount; i++) {
    632                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> (16 - kCache32Bits);
    633                 SkASSERT(nextIndex < kCache32Count);
    634 
    635                 if (nextIndex > prevIndex)
    636                     Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
    637                                     fOrigColors[i],
    638                                     nextIndex - prevIndex + 1, fCacheAlpha);
    639                 prevIndex = nextIndex;
    640             }
    641             SkASSERT(prevIndex == kCache32Count - 1);
    642         }
    643 
    644         if (fMapper) {
    645             SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
    646                                                  (NULL, allocSize, NULL));
    647             SkPMColor* linear = fCache32;           // just computed linear data
    648             SkPMColor* mapped = (SkPMColor*)newPR->getAddr();    // storage for mapped data
    649             SkUnitMapper* map = fMapper;
    650             for (int i = 0; i < kCache32Count; i++) {
    651                 int index = map->mapUnit16((i << 8) | i) >> 8;
    652                 mapped[i] = linear[index];
    653                 mapped[i + kCache32Count] = linear[index + kCache32Count];
    654             }
    655             fCache32PixelRef->unref();
    656             fCache32PixelRef = newPR;
    657             fCache32 = (SkPMColor*)newPR->getAddr();
    658         }
    659     }
    660     return fCache32;
    661 }
    662 
    663 /*
    664  *  Because our caller might rebuild the same (logically the same) gradient
    665  *  over and over, we'd like to return exactly the same "bitmap" if possible,
    666  *  allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
    667  *  To do that, we maintain a private cache of built-bitmaps, based on our
    668  *  colors and positions. Note: we don't try to flatten the fMapper, so if one
    669  *  is present, we skip the cache for now.
    670  */
    671 void Gradient_Shader::commonAsABitmap(SkBitmap* bitmap) const {
    672     // don't have a way to put the mapper into our cache-key yet
    673     if (fMapper) {
    674         // force our cahce32pixelref to be built
    675         (void)this->getCache32();
    676         bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1);
    677         bitmap->setPixelRef(fCache32PixelRef);
    678         return;
    679     }
    680 
    681     // build our key: [numColors + colors[] + {positions[]} ]
    682     int count = 1 + fColorCount;
    683     if (fColorCount > 2) {
    684         count += fColorCount - 1;    // fRecs[].fPos
    685     }
    686 
    687     SkAutoSTMalloc<16, int32_t> storage(count);
    688     int32_t* buffer = storage.get();
    689 
    690     *buffer++ = fColorCount;
    691     memcpy(buffer, fOrigColors, fColorCount * sizeof(SkColor));
    692     buffer += fColorCount;
    693     if (fColorCount > 2) {
    694         for (int i = 1; i < fColorCount; i++) {
    695             *buffer++ = fRecs[i].fPos;
    696         }
    697     }
    698     SkASSERT(buffer - storage.get() == count);
    699 
    700     ///////////////////////////////////
    701 
    702     static SkMutex gMutex;
    703     static SkBitmapCache* gCache;
    704     // each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp
    705     static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
    706     SkAutoMutexAcquire ama(gMutex);
    707 
    708     if (NULL == gCache) {
    709         gCache = new SkBitmapCache(MAX_NUM_CACHED_GRADIENT_BITMAPS);
    710     }
    711     size_t size = count * sizeof(int32_t);
    712 
    713     if (!gCache->find(storage.get(), size, bitmap)) {
    714         // force our cahce32pixelref to be built
    715         (void)this->getCache32();
    716         bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1);
    717         bitmap->setPixelRef(fCache32PixelRef);
    718 
    719         gCache->add(storage.get(), size, *bitmap);
    720     }
    721 }
    722 
    723 void Gradient_Shader::commonAsAGradient(GradientInfo* info) const {
    724     if (info) {
    725         if (info->fColorCount >= fColorCount) {
    726             if (info->fColors) {
    727                 memcpy(info->fColors, fOrigColors,
    728                        fColorCount * sizeof(SkColor));
    729             }
    730             if (info->fColorOffsets) {
    731                 if (fColorCount == 2) {
    732                     info->fColorOffsets[0] = 0;
    733                     info->fColorOffsets[1] = SK_Scalar1;
    734                 } else if (fColorCount > 2) {
    735                     for (int i = 0; i < fColorCount; i++)
    736                         info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
    737                 }
    738             }
    739         }
    740         info->fColorCount = fColorCount;
    741         info->fTileMode = fTileMode;
    742     }
    743 }
    744 
    745 ///////////////////////////////////////////////////////////////////////////////
    746 
    747 static void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) {
    748     SkVector    vec = pts[1] - pts[0];
    749     SkScalar    mag = vec.length();
    750     SkScalar    inv = mag ? SkScalarInvert(mag) : 0;
    751 
    752     vec.scale(inv);
    753     matrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
    754     matrix->postTranslate(-pts[0].fX, -pts[0].fY);
    755     matrix->postScale(inv, inv);
    756 }
    757 
    758 ///////////////////////////////////////////////////////////////////////////////
    759 
    760 class Linear_Gradient : public Gradient_Shader {
    761 public:
    762     Linear_Gradient(const SkPoint pts[2],
    763                     const SkColor colors[], const SkScalar pos[], int colorCount,
    764                     SkShader::TileMode mode, SkUnitMapper* mapper)
    765         : Gradient_Shader(colors, pos, colorCount, mode, mapper),
    766           fStart(pts[0]),
    767           fEnd(pts[1])
    768     {
    769         pts_to_unit_matrix(pts, &fPtsToUnit);
    770     }
    771 
    772     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
    773     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
    774     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
    775     virtual BitmapType asABitmap(SkBitmap*, SkMatrix*,
    776                              TileMode*, SkScalar* twoPointRadialParams) const;
    777     virtual GradientType asAGradient(GradientInfo* info) const;
    778 
    779     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
    780         return SkNEW_ARGS(Linear_Gradient, (buffer));
    781     }
    782 
    783     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
    784         this->INHERITED::flatten(buffer);
    785         buffer.writeScalar(fStart.fX);
    786         buffer.writeScalar(fStart.fY);
    787         buffer.writeScalar(fEnd.fX);
    788         buffer.writeScalar(fEnd.fY);
    789     }
    790 
    791 protected:
    792     Linear_Gradient(SkFlattenableReadBuffer& buffer)
    793         : Gradient_Shader(buffer),
    794           fStart(unflatten_point(buffer)),
    795           fEnd(unflatten_point(buffer)) {
    796     }
    797     virtual Factory getFactory() { return CreateProc; }
    798 
    799 private:
    800     typedef Gradient_Shader INHERITED;
    801     const SkPoint fStart;
    802     const SkPoint fEnd;
    803 };
    804 
    805 bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint,
    806                                  const SkMatrix& matrix) {
    807     if (!this->INHERITED::setContext(device, paint, matrix)) {
    808         return false;
    809     }
    810 
    811     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    812     if ((fDstToIndex.getType() & ~mask) == 0) {
    813         fFlags |= SkShader::kConstInY32_Flag;
    814         if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
    815             // only claim this if we do have a 16bit mode (i.e. none of our
    816             // colors have alpha), and if we are not dithering (which obviously
    817             // is not const in Y).
    818             fFlags |= SkShader::kConstInY16_Flag;
    819         }
    820     }
    821     return true;
    822 }
    823 
    824 //  Return true if fx, fx+dx, fx+2*dx, ... is always in range
    825 static inline bool no_need_for_clamp(int fx, int dx, int count) {
    826     SkASSERT(count > 0);
    827     return (unsigned)((fx | (fx + (count - 1) * dx)) >> 8) <= 0xFF;
    828 }
    829 
    830 #include "SkClampRange.h"
    831 
    832 #define NO_CHECK_ITER               \
    833     do {                            \
    834     unsigned fi = fx >> 8;          \
    835     SkASSERT(fi <= 0xFF);           \
    836     fx += dx;                       \
    837     *dstC++ = cache[toggle + fi];   \
    838     toggle ^= TOGGLE_MASK;          \
    839     } while (0)
    840 
    841 
    842 void Linear_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    843     SkASSERT(count > 0);
    844 
    845     SkPoint             srcPt;
    846     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
    847     TileProc            proc = fTileProc;
    848     const SkPMColor*    cache = this->getCache32();
    849 #ifdef USE_DITHER_32BIT_GRADIENT
    850     int                 toggle = ((x ^ y) & 1) << kCache32Bits;
    851     const int           TOGGLE_MASK = (1 << kCache32Bits);
    852 #else
    853     int toggle = 0;
    854     const int TOGGLE_MASK = 0;
    855 #endif
    856 
    857     if (fDstToIndexClass != kPerspective_MatrixClass) {
    858         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
    859                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
    860         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
    861 
    862         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
    863             SkFixed dxStorage[1];
    864             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
    865             dx = dxStorage[0];
    866         } else {
    867             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
    868             dx = SkScalarToFixed(fDstToIndex.getScaleX());
    869         }
    870 
    871         if (SkFixedNearlyZero(dx)) {
    872             // we're a vertical gradient, so no change in a span
    873             unsigned fi = proc(fx);
    874             SkASSERT(fi <= 0xFFFF);
    875             // TODO: dither version
    876             sk_memset32(dstC, cache[fi >> (16 - kCache32Bits)], count);
    877         } else if (proc == clamp_tileproc) {
    878 #ifdef SK_ENABLE_FAST_LINEAR_GRADIENTS
    879             SkClampRange range;
    880             range.init(fx, dx, count, 0, 0xFF);
    881 
    882             if ((count = range.fCount0) > 0) {
    883                 sk_memset32_dither(dstC,
    884                                    cache[toggle + range.fV0],
    885                                    cache[(toggle ^ TOGGLE_MASK) + range.fV0],
    886                                    count);
    887                 dstC += count;
    888             }
    889             if ((count = range.fCount1) > 0) {
    890                 int unroll = count >> 3;
    891                 fx = range.fFx1;
    892                 for (int i = 0; i < unroll; i++) {
    893                     NO_CHECK_ITER;  NO_CHECK_ITER;
    894                     NO_CHECK_ITER;  NO_CHECK_ITER;
    895                     NO_CHECK_ITER;  NO_CHECK_ITER;
    896                     NO_CHECK_ITER;  NO_CHECK_ITER;
    897                 }
    898                 if ((count &= 7) > 0) {
    899                     do {
    900                         NO_CHECK_ITER;
    901                     } while (--count != 0);
    902                 }
    903             }
    904             if ((count = range.fCount2) > 0) {
    905                 sk_memset32_dither(dstC,
    906                                    cache[toggle + range.fV1],
    907                                    cache[(toggle ^ TOGGLE_MASK) + range.fV1],
    908                                    count);
    909             }
    910 #else
    911             do {
    912                 unsigned fi = SkClampMax(fx >> 8, 0xFF);
    913                 SkASSERT(fi <= 0xFF);
    914                 fx += dx;
    915                 *dstC++ = cache[toggle + fi];
    916                 toggle ^= TOGGLE_MASK;
    917             } while (--count != 0);
    918 #endif
    919         } else if (proc == mirror_tileproc) {
    920             do {
    921                 unsigned fi = mirror_8bits(fx >> 8);
    922                 SkASSERT(fi <= 0xFF);
    923                 fx += dx;
    924                 *dstC++ = cache[toggle + fi];
    925                 toggle ^= TOGGLE_MASK;
    926             } while (--count != 0);
    927         } else {
    928             SkASSERT(proc == repeat_tileproc);
    929             do {
    930                 unsigned fi = repeat_8bits(fx >> 8);
    931                 SkASSERT(fi <= 0xFF);
    932                 fx += dx;
    933                 *dstC++ = cache[toggle + fi];
    934                 toggle ^= TOGGLE_MASK;
    935             } while (--count != 0);
    936         }
    937     } else {
    938         SkScalar    dstX = SkIntToScalar(x);
    939         SkScalar    dstY = SkIntToScalar(y);
    940         do {
    941             dstProc(fDstToIndex, dstX, dstY, &srcPt);
    942             unsigned fi = proc(SkScalarToFixed(srcPt.fX));
    943             SkASSERT(fi <= 0xFFFF);
    944             *dstC++ = cache[toggle + (fi >> (16 - kCache32Bits))];
    945             toggle ^= TOGGLE_MASK;
    946             dstX += SK_Scalar1;
    947         } while (--count != 0);
    948     }
    949 }
    950 
    951 SkShader::BitmapType Linear_Gradient::asABitmap(SkBitmap* bitmap,
    952                                                 SkMatrix* matrix,
    953                                                 TileMode xy[],
    954                                         SkScalar* twoPointRadialParams) const {
    955     if (bitmap) {
    956         this->commonAsABitmap(bitmap);
    957     }
    958     if (matrix) {
    959         matrix->setScale(SkIntToScalar(kCache32Count), SK_Scalar1);
    960         matrix->preConcat(fPtsToUnit);
    961     }
    962     if (xy) {
    963         xy[0] = fTileMode;
    964         xy[1] = kClamp_TileMode;
    965     }
    966     return kDefault_BitmapType;
    967 }
    968 
    969 SkShader::GradientType Linear_Gradient::asAGradient(GradientInfo* info) const {
    970     if (info) {
    971         commonAsAGradient(info);
    972         info->fPoint[0] = fStart;
    973         info->fPoint[1] = fEnd;
    974     }
    975     return kLinear_GradientType;
    976 }
    977 
    978 static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
    979                             int count) {
    980     if (reinterpret_cast<uintptr_t>(dst) & 2) {
    981         *dst++ = value;
    982         count -= 1;
    983         SkTSwap(value, other);
    984     }
    985 
    986     sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
    987 
    988     if (count & 1) {
    989         dst[count - 1] = value;
    990     }
    991 }
    992 
    993 #define NO_CHECK_ITER_16                \
    994     do {                                \
    995     unsigned fi = fx >> kCache16Shift;  \
    996     SkASSERT(fi <= kCache16Mask);       \
    997     fx += dx;                           \
    998     *dstC++ = cache[toggle + fi];       \
    999     toggle ^= TOGGLE_MASK;              \
   1000     } while (0)
   1001 
   1002 
   1003 void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
   1004     SkASSERT(count > 0);
   1005 
   1006     SkPoint             srcPt;
   1007     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1008     TileProc            proc = fTileProc;
   1009     const uint16_t*     cache = this->getCache16();
   1010     int                 toggle = ((x ^ y) & 1) << kCache16Bits;
   1011     const int           TOGGLE_MASK = (1 << kCache32Bits);
   1012 
   1013     if (fDstToIndexClass != kPerspective_MatrixClass) {
   1014         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   1015                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1016         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1017 
   1018         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   1019             SkFixed dxStorage[1];
   1020             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
   1021             dx = dxStorage[0];
   1022         } else {
   1023             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1024             dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1025         }
   1026 
   1027         if (SkFixedNearlyZero(dx)) {
   1028             // we're a vertical gradient, so no change in a span
   1029             unsigned fi = proc(fx) >> kCache16Shift;
   1030             SkASSERT(fi <= kCache16Mask);
   1031             dither_memset16(dstC, cache[toggle + fi],
   1032                             cache[(toggle ^ TOGGLE_MASK) + fi], count);
   1033         } else if (proc == clamp_tileproc) {
   1034 #ifdef SK_ENABLE_FAST_LINEAR_GRADIENTS
   1035             SkClampRange range;
   1036             range.init(fx, dx, count, 0, kCache16Mask);
   1037 
   1038             if ((count = range.fCount0) > 0) {
   1039                 dither_memset16(dstC,
   1040                                 cache[toggle + range.fV0],
   1041                                 cache[(toggle ^ TOGGLE_MASK) + range.fV0],
   1042                                 count);
   1043                 dstC += count;
   1044             }
   1045             if ((count = range.fCount1) > 0) {
   1046                 int unroll = count >> 3;
   1047                 fx = range.fFx1;
   1048                 for (int i = 0; i < unroll; i++) {
   1049                     NO_CHECK_ITER_16;  NO_CHECK_ITER_16;
   1050                     NO_CHECK_ITER_16;  NO_CHECK_ITER_16;
   1051                     NO_CHECK_ITER_16;  NO_CHECK_ITER_16;
   1052                     NO_CHECK_ITER_16;  NO_CHECK_ITER_16;
   1053                 }
   1054                 if ((count &= 7) > 0) {
   1055                     do {
   1056                         NO_CHECK_ITER_16;
   1057                     } while (--count != 0);
   1058                 }
   1059             }
   1060             if ((count = range.fCount2) > 0) {
   1061                 dither_memset16(dstC,
   1062                                 cache[toggle + range.fV1],
   1063                                 cache[(toggle ^ TOGGLE_MASK) + range.fV1],
   1064                                 count);
   1065             }
   1066 #else
   1067             do {
   1068                 unsigned fi = SkClampMax(fx >> kCache16Shift, kCache16Mask);
   1069                 SkASSERT(fi <= kCache16Mask);
   1070                 fx += dx;
   1071                 *dstC++ = cache[toggle + fi];
   1072                 toggle ^= TOGGLE_MASK;
   1073             } while (--count != 0);
   1074 #endif
   1075         } else if (proc == mirror_tileproc) {
   1076             do {
   1077                 unsigned fi = mirror_bits(fx >> kCache16Shift, kCache16Bits);
   1078                 SkASSERT(fi <= kCache16Mask);
   1079                 fx += dx;
   1080                 *dstC++ = cache[toggle + fi];
   1081                 toggle ^= TOGGLE_MASK;
   1082             } while (--count != 0);
   1083         } else {
   1084             SkASSERT(proc == repeat_tileproc);
   1085             do {
   1086                 unsigned fi = repeat_bits(fx >> kCache16Shift, kCache16Bits);
   1087                 SkASSERT(fi <= kCache16Mask);
   1088                 fx += dx;
   1089                 *dstC++ = cache[toggle + fi];
   1090                 toggle ^= TOGGLE_MASK;
   1091             } while (--count != 0);
   1092         }
   1093     } else {
   1094         SkScalar    dstX = SkIntToScalar(x);
   1095         SkScalar    dstY = SkIntToScalar(y);
   1096         do {
   1097             dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1098             unsigned fi = proc(SkScalarToFixed(srcPt.fX));
   1099             SkASSERT(fi <= 0xFFFF);
   1100 
   1101             int index = fi >> kCache16Shift;
   1102             *dstC++ = cache[toggle + index];
   1103             toggle ^= TOGGLE_MASK;
   1104 
   1105             dstX += SK_Scalar1;
   1106         } while (--count != 0);
   1107     }
   1108 }
   1109 
   1110 ///////////////////////////////////////////////////////////////////////////////
   1111 
   1112 #define kSQRT_TABLE_BITS    11
   1113 #define kSQRT_TABLE_SIZE    (1 << kSQRT_TABLE_BITS)
   1114 
   1115 #include "SkRadialGradient_Table.h"
   1116 
   1117 #if defined(SK_BUILD_FOR_WIN32) && defined(SK_DEBUG)
   1118 
   1119 #include <stdio.h>
   1120 
   1121 void SkRadialGradient_BuildTable() {
   1122     // build it 0..127 x 0..127, so we use 2^15 - 1 in the numerator for our "fixed" table
   1123 
   1124     FILE* file = ::fopen("SkRadialGradient_Table.h", "w");
   1125     SkASSERT(file);
   1126     ::fprintf(file, "static const uint8_t gSqrt8Table[] = {\n");
   1127 
   1128     for (int i = 0; i < kSQRT_TABLE_SIZE; i++) {
   1129         if ((i & 15) == 0) {
   1130             ::fprintf(file, "\t");
   1131         }
   1132 
   1133         uint8_t value = SkToU8(SkFixedSqrt(i * SK_Fixed1 / kSQRT_TABLE_SIZE) >> 8);
   1134 
   1135         ::fprintf(file, "0x%02X", value);
   1136         if (i < kSQRT_TABLE_SIZE-1) {
   1137             ::fprintf(file, ", ");
   1138         }
   1139         if ((i & 15) == 15) {
   1140             ::fprintf(file, "\n");
   1141         }
   1142     }
   1143     ::fprintf(file, "};\n");
   1144     ::fclose(file);
   1145 }
   1146 
   1147 #endif
   1148 
   1149 
   1150 static void rad_to_unit_matrix(const SkPoint& center, SkScalar radius,
   1151                                SkMatrix* matrix) {
   1152     SkScalar    inv = SkScalarInvert(radius);
   1153 
   1154     matrix->setTranslate(-center.fX, -center.fY);
   1155     matrix->postScale(inv, inv);
   1156 }
   1157 
   1158 class Radial_Gradient : public Gradient_Shader {
   1159 public:
   1160     Radial_Gradient(const SkPoint& center, SkScalar radius,
   1161                     const SkColor colors[], const SkScalar pos[], int colorCount,
   1162                     SkShader::TileMode mode, SkUnitMapper* mapper)
   1163         : Gradient_Shader(colors, pos, colorCount, mode, mapper),
   1164           fCenter(center),
   1165           fRadius(radius)
   1166     {
   1167         // make sure our table is insync with our current #define for kSQRT_TABLE_SIZE
   1168         SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE);
   1169 
   1170         rad_to_unit_matrix(center, radius, &fPtsToUnit);
   1171     }
   1172 
   1173     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   1174         SkASSERT(count > 0);
   1175 
   1176         SkPoint             srcPt;
   1177         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1178         TileProc            proc = fTileProc;
   1179         const SkPMColor*    cache = this->getCache32();
   1180 
   1181         if (fDstToIndexClass != kPerspective_MatrixClass) {
   1182             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   1183                                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1184             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1185             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1186 
   1187             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   1188                 SkFixed storage[2];
   1189                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
   1190                 dx = storage[0];
   1191                 dy = storage[1];
   1192             } else {
   1193                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1194                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1195                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
   1196             }
   1197 
   1198             if (proc == clamp_tileproc) {
   1199                 const uint8_t* sqrt_table = gSqrt8Table;
   1200                 fx >>= 1;
   1201                 dx >>= 1;
   1202                 fy >>= 1;
   1203                 dy >>= 1;
   1204                 do {
   1205                     unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   1206                     unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   1207                     fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
   1208                     fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   1209                     *dstC++ = cache[sqrt_table[fi] >> (8 - kCache32Bits)];
   1210                     fx += dx;
   1211                     fy += dy;
   1212                 } while (--count != 0);
   1213             } else if (proc == mirror_tileproc) {
   1214                 do {
   1215                     SkFixed magnitudeSquared = SkFixedSquare(fx) + SkFixedSquare(fy);
   1216                     if (magnitudeSquared < 0) // Overflow.
   1217                         magnitudeSquared = SK_FixedMax;
   1218                     SkFixed dist = SkFixedSqrt(magnitudeSquared);
   1219                     unsigned fi = mirror_tileproc(dist);
   1220                     SkASSERT(fi <= 0xFFFF);
   1221                     *dstC++ = cache[fi >> (16 - kCache32Bits)];
   1222                     fx += dx;
   1223                     fy += dy;
   1224                 } while (--count != 0);
   1225             } else {
   1226                 SkASSERT(proc == repeat_tileproc);
   1227                 do {
   1228                     SkFixed magnitudeSquared = SkFixedSquare(fx) + SkFixedSquare(fy);
   1229                     if (magnitudeSquared < 0) // Overflow.
   1230                         magnitudeSquared = SK_FixedMax;
   1231                     SkFixed dist = SkFixedSqrt(magnitudeSquared);
   1232                     unsigned fi = repeat_tileproc(dist);
   1233                     SkASSERT(fi <= 0xFFFF);
   1234                     *dstC++ = cache[fi >> (16 - kCache32Bits)];
   1235                     fx += dx;
   1236                     fy += dy;
   1237                 } while (--count != 0);
   1238             }
   1239         } else {    // perspective case
   1240             SkScalar dstX = SkIntToScalar(x);
   1241             SkScalar dstY = SkIntToScalar(y);
   1242             do {
   1243                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1244                 unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   1245                 SkASSERT(fi <= 0xFFFF);
   1246                 *dstC++ = cache[fi >> (16 - kCache32Bits)];
   1247                 dstX += SK_Scalar1;
   1248             } while (--count != 0);
   1249         }
   1250     }
   1251 
   1252     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) {
   1253         SkASSERT(count > 0);
   1254 
   1255         SkPoint             srcPt;
   1256         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1257         TileProc            proc = fTileProc;
   1258         const uint16_t*     cache = this->getCache16();
   1259         int                 toggle = ((x ^ y) & 1) << kCache16Bits;
   1260 
   1261         if (fDstToIndexClass != kPerspective_MatrixClass) {
   1262             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   1263                                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1264             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1265             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1266 
   1267             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   1268                 SkFixed storage[2];
   1269                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &storage[0], &storage[1]);
   1270                 dx = storage[0];
   1271                 dy = storage[1];
   1272             } else {
   1273                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1274                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1275                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
   1276             }
   1277 
   1278             if (proc == clamp_tileproc) {
   1279                 const uint8_t* sqrt_table = gSqrt8Table;
   1280 
   1281                 /* knock these down so we can pin against +- 0x7FFF, which is an immediate load,
   1282                     rather than 0xFFFF which is slower. This is a compromise, since it reduces our
   1283                     precision, but that appears to be visually OK. If we decide this is OK for
   1284                     all of our cases, we could (it seems) put this scale-down into fDstToIndex,
   1285                     to avoid having to do these extra shifts each time.
   1286                 */
   1287                 fx >>= 1;
   1288                 dx >>= 1;
   1289                 fy >>= 1;
   1290                 dy >>= 1;
   1291                 if (dy == 0) {    // might perform this check for the other modes, but the win will be a smaller % of the total
   1292                     fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   1293                     fy *= fy;
   1294                     do {
   1295                         unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   1296                         unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
   1297                         fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   1298                         fx += dx;
   1299                         *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
   1300                         toggle ^= (1 << kCache16Bits);
   1301                     } while (--count != 0);
   1302                 } else {
   1303                     do {
   1304                         unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   1305                         unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   1306                         fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
   1307                         fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   1308                         fx += dx;
   1309                         fy += dy;
   1310                         *dstC++ = cache[toggle + (sqrt_table[fi] >> (8 - kCache16Bits))];
   1311                         toggle ^= (1 << kCache16Bits);
   1312                     } while (--count != 0);
   1313                 }
   1314             } else if (proc == mirror_tileproc) {
   1315                 do {
   1316                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
   1317                     unsigned fi = mirror_tileproc(dist);
   1318                     SkASSERT(fi <= 0xFFFF);
   1319                     fx += dx;
   1320                     fy += dy;
   1321                     *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
   1322                     toggle ^= (1 << kCache16Bits);
   1323                 } while (--count != 0);
   1324             } else {
   1325                 SkASSERT(proc == repeat_tileproc);
   1326                 do {
   1327                     SkFixed dist = SkFixedSqrt(SkFixedSquare(fx) + SkFixedSquare(fy));
   1328                     unsigned fi = repeat_tileproc(dist);
   1329                     SkASSERT(fi <= 0xFFFF);
   1330                     fx += dx;
   1331                     fy += dy;
   1332                     *dstC++ = cache[toggle + (fi >> (16 - kCache16Bits))];
   1333                     toggle ^= (1 << kCache16Bits);
   1334                 } while (--count != 0);
   1335             }
   1336         } else {    // perspective case
   1337             SkScalar dstX = SkIntToScalar(x);
   1338             SkScalar dstY = SkIntToScalar(y);
   1339             do {
   1340                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1341                 unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   1342                 SkASSERT(fi <= 0xFFFF);
   1343 
   1344                 int index = fi >> (16 - kCache16Bits);
   1345                 *dstC++ = cache[toggle + index];
   1346                 toggle ^= (1 << kCache16Bits);
   1347 
   1348                 dstX += SK_Scalar1;
   1349             } while (--count != 0);
   1350         }
   1351     }
   1352 
   1353     virtual BitmapType asABitmap(SkBitmap* bitmap,
   1354                                  SkMatrix* matrix,
   1355                                  TileMode* xy,
   1356                                  SkScalar* twoPointRadialParams) const {
   1357         if (bitmap) {
   1358             this->commonAsABitmap(bitmap);
   1359         }
   1360         if (matrix) {
   1361             matrix->setScale(SkIntToScalar(kCache32Count), SkIntToScalar(kCache32Count));
   1362             matrix->preConcat(fPtsToUnit);
   1363         }
   1364         if (xy) {
   1365             xy[0] = fTileMode;
   1366             xy[1] = kClamp_TileMode;
   1367         }
   1368         return kRadial_BitmapType;
   1369     }
   1370     virtual GradientType asAGradient(GradientInfo* info) const {
   1371         if (info) {
   1372             commonAsAGradient(info);
   1373             info->fPoint[0] = fCenter;
   1374             info->fRadius[0] = fRadius;
   1375         }
   1376         return kRadial_GradientType;
   1377     }
   1378 
   1379     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1380         return SkNEW_ARGS(Radial_Gradient, (buffer));
   1381     }
   1382 
   1383     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
   1384         this->INHERITED::flatten(buffer);
   1385         buffer.writeScalar(fCenter.fX);
   1386         buffer.writeScalar(fCenter.fY);
   1387         buffer.writeScalar(fRadius);
   1388     }
   1389 
   1390 protected:
   1391     Radial_Gradient(SkFlattenableReadBuffer& buffer)
   1392         : Gradient_Shader(buffer),
   1393           fCenter(unflatten_point(buffer)),
   1394           fRadius(buffer.readScalar()) {
   1395     }
   1396     virtual Factory getFactory() { return CreateProc; }
   1397 
   1398 private:
   1399     typedef Gradient_Shader INHERITED;
   1400     const SkPoint fCenter;
   1401     const SkScalar fRadius;
   1402 };
   1403 
   1404 /* Two-point radial gradients are specified by two circles, each with a center
   1405    point and radius.  The gradient can be considered to be a series of
   1406    concentric circles, with the color interpolated from the start circle
   1407    (at t=0) to the end circle (at t=1).
   1408 
   1409    For each point (x, y) in the span, we want to find the
   1410    interpolated circle that intersects that point.  The center
   1411    of the desired circle (Cx, Cy) falls at some distance t
   1412    along the line segment between the start point (Sx, Sy) and
   1413    end point (Ex, Ey):
   1414 
   1415       Cx = (1 - t) * Sx + t * Ex        (0 <= t <= 1)
   1416       Cy = (1 - t) * Sy + t * Ey
   1417 
   1418    The radius of the desired circle (r) is also a linear interpolation t
   1419    between the start and end radii (Sr and Er):
   1420 
   1421       r = (1 - t) * Sr + t * Er
   1422 
   1423    But
   1424 
   1425       (x - Cx)^2 + (y - Cy)^2 = r^2
   1426 
   1427    so
   1428 
   1429      (x - ((1 - t) * Sx + t * Ex))^2
   1430    + (y - ((1 - t) * Sy + t * Ey))^2
   1431    = ((1 - t) * Sr + t * Er)^2
   1432 
   1433    Solving for t yields
   1434 
   1435      [(Sx - Ex)^2 + (Sy - Ey)^2 - (Er - Sr)^2)] * t^2
   1436    + [2 * (Sx - Ex)(x - Sx) + 2 * (Sy - Ey)(y - Sy) - 2 * (Er - Sr) * Sr] * t
   1437    + [(x - Sx)^2 + (y - Sy)^2 - Sr^2] = 0
   1438 
   1439    To simplify, let Dx = Sx - Ex, Dy = Sy - Ey, Dr = Er - Sr, dx = x - Sx, dy = y - Sy
   1440 
   1441      [Dx^2 + Dy^2 - Dr^2)] * t^2
   1442    + 2 * [Dx * dx + Dy * dy - Dr * Sr] * t
   1443    + [dx^2 + dy^2 - Sr^2] = 0
   1444 
   1445    A quadratic in t.  The two roots of the quadratic reflect the two
   1446    possible circles on which the point may fall.  Solving for t yields
   1447    the gradient value to use.
   1448 
   1449    If a<0, the start circle is entirely contained in the
   1450    end circle, and one of the roots will be <0 or >1 (off the line
   1451    segment).  If a>0, the start circle falls at least partially
   1452    outside the end circle (or vice versa), and the gradient
   1453    defines a "tube" where a point may be on one circle (on the
   1454    inside of the tube) or the other (outside of the tube).  We choose
   1455    one arbitrarily.
   1456 
   1457    In order to keep the math to within the limits of fixed point,
   1458    we divide the entire quadratic by Dr^2, and replace
   1459    (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
   1460 
   1461    [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
   1462    + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
   1463    + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
   1464 
   1465    (x' and y' are computed by appending the subtract and scale to the
   1466    fDstToIndex matrix in the constructor).
   1467 
   1468    Since the 'A' component of the quadratic is independent of x' and y', it
   1469    is precomputed in the constructor.  Since the 'B' component is linear in
   1470    x' and y', if x and y are linear in the span, 'B' can be computed
   1471    incrementally with a simple delta (db below).  If it is not (e.g.,
   1472    a perspective projection), it must be computed in the loop.
   1473 
   1474 */
   1475 
   1476 #ifdef SK_USE_SLOW_2POINT_RADIAL_GRADIENT
   1477 static inline SkFixed two_point_radial(SkFixed b, SkFixed fx, SkFixed fy, SkFixed sr2d2, SkFixed foura, SkFixed oneOverTwoA, bool posRoot) {
   1478     SkFixed c = SkFixedSquare(fx) + SkFixedSquare(fy) - sr2d2;
   1479     SkFixed discrim = SkFixedSquare(b) - SkFixedMul(foura, c);
   1480     if (discrim < 0) {
   1481         discrim = -discrim;
   1482     }
   1483     SkFixed rootDiscrim = SkFixedSqrt(discrim);
   1484     if (posRoot) {
   1485         return SkFixedMul(-b + rootDiscrim, oneOverTwoA);
   1486     } else {
   1487         return SkFixedMul(-b - rootDiscrim, oneOverTwoA);
   1488     }
   1489 }
   1490 #else
   1491 static inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
   1492                                        SkScalar sr2d2, SkScalar foura,
   1493                                        SkScalar oneOverTwoA, bool posRoot) {
   1494     SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
   1495     SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
   1496     if (discrim < 0) {
   1497         discrim = -discrim;
   1498     }
   1499     SkScalar rootDiscrim = SkScalarSqrt(discrim);
   1500     SkScalar result;
   1501     if (posRoot) {
   1502         result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
   1503     } else {
   1504         result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
   1505     }
   1506     return SkScalarToFixed(result);
   1507 }
   1508 #endif
   1509 
   1510 class Two_Point_Radial_Gradient : public Gradient_Shader {
   1511 public:
   1512     Two_Point_Radial_Gradient(const SkPoint& start, SkScalar startRadius,
   1513                               const SkPoint& end, SkScalar endRadius,
   1514                               const SkColor colors[], const SkScalar pos[],
   1515                               int colorCount, SkShader::TileMode mode,
   1516                               SkUnitMapper* mapper)
   1517             : Gradient_Shader(colors, pos, colorCount, mode, mapper),
   1518               fCenter1(start),
   1519               fCenter2(end),
   1520               fRadius1(startRadius),
   1521               fRadius2(endRadius) {
   1522         init();
   1523     }
   1524 
   1525     virtual BitmapType asABitmap(SkBitmap* bitmap,
   1526                                  SkMatrix* matrix,
   1527                                  TileMode* xy,
   1528                                  SkScalar* twoPointRadialParams) const {
   1529         if (bitmap) {
   1530             this->commonAsABitmap(bitmap);
   1531         }
   1532         SkScalar diffL = 0; // just to avoid gcc warning
   1533         if (matrix || twoPointRadialParams) {
   1534             diffL = SkScalarSqrt(SkScalarSquare(fDiff.fX) +
   1535                                  SkScalarSquare(fDiff.fY));
   1536         }
   1537         if (matrix) {
   1538             if (diffL) {
   1539                 SkScalar invDiffL = SkScalarInvert(diffL);
   1540                 matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY),
   1541                                   SkScalarMul(invDiffL, fDiff.fX));
   1542             } else {
   1543                 matrix->reset();
   1544             }
   1545             matrix->preConcat(fPtsToUnit);
   1546         }
   1547         if (xy) {
   1548             xy[0] = fTileMode;
   1549             xy[1] = kClamp_TileMode;
   1550         }
   1551         if (NULL != twoPointRadialParams) {
   1552             twoPointRadialParams[0] = diffL;
   1553             twoPointRadialParams[1] = fStartRadius;
   1554             twoPointRadialParams[2] = fDiffRadius;
   1555         }
   1556         return kTwoPointRadial_BitmapType;
   1557     }
   1558 
   1559     virtual GradientType asAGradient(GradientInfo* info) const {
   1560         if (info) {
   1561             commonAsAGradient(info);
   1562             info->fPoint[0] = fCenter1;
   1563             info->fPoint[1] = fCenter2;
   1564             info->fRadius[0] = fRadius1;
   1565             info->fRadius[1] = fRadius2;
   1566         }
   1567         return kRadial2_GradientType;
   1568     }
   1569 
   1570 #ifdef SK_USE_SLOW_2POINT_RADIAL_GRADIENT
   1571     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
   1572     {
   1573         SkASSERT(count > 0);
   1574 
   1575         // Zero difference between radii:  fill with transparent black.
   1576         if (fDiffRadius == 0) {
   1577             sk_bzero(dstC, count * sizeof(*dstC));
   1578             return;
   1579         }
   1580         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1581         TileProc            proc = fTileProc;
   1582         const SkPMColor*    cache = this->getCache32();
   1583         SkFixed diffx = SkScalarToFixed(fDiff.fX);
   1584         SkFixed diffy = SkScalarToFixed(fDiff.fY);
   1585         SkFixed foura = SkScalarToFixed(SkScalarMul(fA, 4));
   1586         SkFixed startRadius = SkScalarToFixed(fStartRadius);
   1587         SkFixed sr2D2 = SkScalarToFixed(fSr2D2);
   1588         SkFixed oneOverTwoA = SkScalarToFixed(fOneOverTwoA);
   1589         bool posRoot = fDiffRadius < 0;
   1590         if (fDstToIndexClass != kPerspective_MatrixClass)
   1591         {
   1592             SkPoint srcPt;
   1593             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   1594                     SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1595             SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   1596             SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   1597 
   1598             if (fDstToIndexClass == kFixedStepInX_MatrixClass)
   1599             {
   1600                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &dx, &dy);
   1601             }
   1602             else
   1603             {
   1604                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1605                 dx = SkScalarToFixed(fDstToIndex.getScaleX());
   1606                 dy = SkScalarToFixed(fDstToIndex.getSkewY());
   1607             }
   1608             SkFixed b = (SkFixedMul(diffx, fx) +
   1609                          SkFixedMul(diffy, fy) - startRadius) << 1;
   1610             SkFixed db = (SkFixedMul(diffx, dx) +
   1611                           SkFixedMul(diffy, dy)) << 1;
   1612             if (proc == clamp_tileproc)
   1613             {
   1614                 for (; count > 0; --count) {
   1615                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1616                     SkFixed index = SkClampMax(t, 0xFFFF);
   1617                     SkASSERT(index <= 0xFFFF);
   1618                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1619                     fx += dx;
   1620                     fy += dy;
   1621                     b += db;
   1622                 }
   1623             }
   1624             else if (proc == mirror_tileproc)
   1625             {
   1626                 for (; count > 0; --count) {
   1627                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1628                     SkFixed index = mirror_tileproc(t);
   1629                     SkASSERT(index <= 0xFFFF);
   1630                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1631                     fx += dx;
   1632                     fy += dy;
   1633                     b += db;
   1634                 }
   1635             }
   1636             else
   1637             {
   1638                 SkASSERT(proc == repeat_tileproc);
   1639                 for (; count > 0; --count) {
   1640                     SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1641                     SkFixed index = repeat_tileproc(t);
   1642                     SkASSERT(index <= 0xFFFF);
   1643                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1644                     fx += dx;
   1645                     fy += dy;
   1646                     b += db;
   1647                 }
   1648             }
   1649         }
   1650         else    // perspective case
   1651         {
   1652             SkScalar dstX = SkIntToScalar(x);
   1653             SkScalar dstY = SkIntToScalar(y);
   1654             for (; count > 0; --count) {
   1655                 SkPoint             srcPt;
   1656                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1657                 SkFixed fx = SkScalarToFixed(srcPt.fX);
   1658                 SkFixed fy = SkScalarToFixed(srcPt.fY);
   1659                 SkFixed b = (SkFixedMul(diffx, fx) +
   1660                              SkFixedMul(diffy, fy) - startRadius) << 1;
   1661                 SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
   1662                 SkFixed index = proc(t);
   1663                 SkASSERT(index <= 0xFFFF);
   1664                 *dstC++ = cache[index >> (16 - kCache32Bits)];
   1665                 dstX += SK_Scalar1;
   1666             }
   1667         }
   1668     }
   1669 #else
   1670     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   1671         SkASSERT(count > 0);
   1672 
   1673         // Zero difference between radii:  fill with transparent black.
   1674         if (fDiffRadius == 0) {
   1675           sk_bzero(dstC, count * sizeof(*dstC));
   1676           return;
   1677         }
   1678         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   1679         TileProc            proc = fTileProc;
   1680         const SkPMColor*    cache = this->getCache32();
   1681 
   1682         SkScalar foura = fA * 4;
   1683         bool posRoot = fDiffRadius < 0;
   1684         if (fDstToIndexClass != kPerspective_MatrixClass) {
   1685             SkPoint srcPt;
   1686             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   1687                                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   1688             SkScalar dx, fx = srcPt.fX;
   1689             SkScalar dy, fy = srcPt.fY;
   1690 
   1691             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   1692                 SkFixed fixedX, fixedY;
   1693                 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
   1694                 dx = SkFixedToScalar(fixedX);
   1695                 dy = SkFixedToScalar(fixedY);
   1696             } else {
   1697                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   1698                 dx = fDstToIndex.getScaleX();
   1699                 dy = fDstToIndex.getSkewY();
   1700             }
   1701             SkScalar b = (SkScalarMul(fDiff.fX, fx) +
   1702                          SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
   1703             SkScalar db = (SkScalarMul(fDiff.fX, dx) +
   1704                           SkScalarMul(fDiff.fY, dy)) * 2;
   1705             if (proc == clamp_tileproc) {
   1706                 for (; count > 0; --count) {
   1707                     SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
   1708                     SkFixed index = SkClampMax(t, 0xFFFF);
   1709                     SkASSERT(index <= 0xFFFF);
   1710                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1711                     fx += dx;
   1712                     fy += dy;
   1713                     b += db;
   1714                 }
   1715             } else if (proc == mirror_tileproc) {
   1716                 for (; count > 0; --count) {
   1717                     SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
   1718                     SkFixed index = mirror_tileproc(t);
   1719                     SkASSERT(index <= 0xFFFF);
   1720                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1721                     fx += dx;
   1722                     fy += dy;
   1723                     b += db;
   1724                 }
   1725             } else {
   1726                 SkASSERT(proc == repeat_tileproc);
   1727                 for (; count > 0; --count) {
   1728                     SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
   1729                     SkFixed index = repeat_tileproc(t);
   1730                     SkASSERT(index <= 0xFFFF);
   1731                     *dstC++ = cache[index >> (16 - kCache32Bits)];
   1732                     fx += dx;
   1733                     fy += dy;
   1734                     b += db;
   1735                 }
   1736             }
   1737         } else {    // perspective case
   1738             SkScalar dstX = SkIntToScalar(x);
   1739             SkScalar dstY = SkIntToScalar(y);
   1740             for (; count > 0; --count) {
   1741                 SkPoint             srcPt;
   1742                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
   1743                 SkScalar fx = srcPt.fX;
   1744                 SkScalar fy = srcPt.fY;
   1745                 SkScalar b = (SkScalarMul(fDiff.fX, fx) +
   1746                              SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
   1747                 SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, posRoot);
   1748                 SkFixed index = proc(t);
   1749                 SkASSERT(index <= 0xFFFF);
   1750                 *dstC++ = cache[index >> (16 - kCache32Bits)];
   1751                 dstX += SK_Scalar1;
   1752             }
   1753         }
   1754     }
   1755 #endif
   1756 
   1757     virtual bool setContext(const SkBitmap& device,
   1758                             const SkPaint& paint,
   1759                             const SkMatrix& matrix) {
   1760         if (!this->INHERITED::setContext(device, paint, matrix)) {
   1761             return false;
   1762         }
   1763 
   1764         // we don't have a span16 proc
   1765         fFlags &= ~kHasSpan16_Flag;
   1766         return true;
   1767     }
   1768 
   1769     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1770         return SkNEW_ARGS(Two_Point_Radial_Gradient, (buffer));
   1771     }
   1772 
   1773     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
   1774         this->INHERITED::flatten(buffer);
   1775         buffer.writeScalar(fCenter1.fX);
   1776         buffer.writeScalar(fCenter1.fY);
   1777         buffer.writeScalar(fCenter2.fX);
   1778         buffer.writeScalar(fCenter2.fY);
   1779         buffer.writeScalar(fRadius1);
   1780         buffer.writeScalar(fRadius2);
   1781     }
   1782 
   1783 protected:
   1784     Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
   1785             : Gradient_Shader(buffer),
   1786               fCenter1(unflatten_point(buffer)),
   1787               fCenter2(unflatten_point(buffer)),
   1788               fRadius1(buffer.readScalar()),
   1789               fRadius2(buffer.readScalar()) {
   1790         init();
   1791     };
   1792     virtual Factory getFactory() { return CreateProc; }
   1793 
   1794 private:
   1795     typedef Gradient_Shader INHERITED;
   1796     const SkPoint fCenter1;
   1797     const SkPoint fCenter2;
   1798     const SkScalar fRadius1;
   1799     const SkScalar fRadius2;
   1800     SkPoint fDiff;
   1801     SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
   1802 
   1803     void init() {
   1804         fDiff = fCenter1 - fCenter2;
   1805         fDiffRadius = fRadius2 - fRadius1;
   1806         SkScalar inv = SkScalarInvert(fDiffRadius);
   1807         fDiff.fX = SkScalarMul(fDiff.fX, inv);
   1808         fDiff.fY = SkScalarMul(fDiff.fY, inv);
   1809         fStartRadius = SkScalarMul(fRadius1, inv);
   1810         fSr2D2 = SkScalarSquare(fStartRadius);
   1811         fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
   1812         fOneOverTwoA = SkScalarInvert(fA * 2);
   1813 
   1814         fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
   1815         fPtsToUnit.postScale(inv, inv);
   1816     }
   1817 };
   1818 
   1819 ///////////////////////////////////////////////////////////////////////////////
   1820 
   1821 class Sweep_Gradient : public Gradient_Shader {
   1822 public:
   1823     Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
   1824                    const SkScalar pos[], int count, SkUnitMapper* mapper)
   1825     : Gradient_Shader(colors, pos, count, SkShader::kClamp_TileMode, mapper),
   1826       fCenter(SkPoint::Make(cx, cy))
   1827     {
   1828         fPtsToUnit.setTranslate(-cx, -cy);
   1829     }
   1830     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
   1831     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
   1832 
   1833     virtual BitmapType asABitmap(SkBitmap* bitmap,
   1834                                  SkMatrix* matrix,
   1835                                  TileMode* xy,
   1836                                  SkScalar* twoPointRadialParams) const {
   1837         if (bitmap) {
   1838             this->commonAsABitmap(bitmap);
   1839         }
   1840         if (matrix) {
   1841             *matrix = fPtsToUnit;
   1842         }
   1843         if (xy) {
   1844             xy[0] = fTileMode;
   1845             xy[1] = kClamp_TileMode;
   1846         }
   1847         return kSweep_BitmapType;
   1848     }
   1849 
   1850     virtual GradientType asAGradient(GradientInfo* info) const {
   1851         if (info) {
   1852             commonAsAGradient(info);
   1853             info->fPoint[0] = fCenter;
   1854         }
   1855         return kSweep_GradientType;
   1856     }
   1857 
   1858     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
   1859         return SkNEW_ARGS(Sweep_Gradient, (buffer));
   1860     }
   1861 
   1862     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
   1863         this->INHERITED::flatten(buffer);
   1864         buffer.writeScalar(fCenter.fX);
   1865         buffer.writeScalar(fCenter.fY);
   1866     }
   1867 
   1868 protected:
   1869     Sweep_Gradient(SkFlattenableReadBuffer& buffer)
   1870         : Gradient_Shader(buffer),
   1871           fCenter(unflatten_point(buffer)) {
   1872     }
   1873 
   1874     virtual Factory getFactory() { return CreateProc; }
   1875 
   1876 private:
   1877     typedef Gradient_Shader INHERITED;
   1878     const SkPoint fCenter;
   1879 };
   1880 
   1881 #ifdef COMPUTE_SWEEP_TABLE
   1882 #define PI  3.14159265
   1883 static bool gSweepTableReady;
   1884 static uint8_t gSweepTable[65];
   1885 
   1886 /*  Our table stores precomputed values for atan: [0...1] -> [0..PI/4]
   1887     We scale the results to [0..32]
   1888 */
   1889 static const uint8_t* build_sweep_table() {
   1890     if (!gSweepTableReady) {
   1891         const int N = 65;
   1892         const double DENOM = N - 1;
   1893 
   1894         for (int i = 0; i < N; i++)
   1895         {
   1896             double arg = i / DENOM;
   1897             double v = atan(arg);
   1898             int iv = (int)round(v * DENOM * 2 / PI);
   1899 //            printf("[%d] atan(%g) = %g %d\n", i, arg, v, iv);
   1900             printf("%d, ", iv);
   1901             gSweepTable[i] = iv;
   1902         }
   1903         gSweepTableReady = true;
   1904     }
   1905     return gSweepTable;
   1906 }
   1907 #else
   1908 static const uint8_t gSweepTable[] = {
   1909     0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9,
   1910     10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18,
   1911     19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26,
   1912     26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
   1913     32
   1914 };
   1915 static const uint8_t* build_sweep_table() { return gSweepTable; }
   1916 #endif
   1917 
   1918 // divide numer/denom, with a bias of 6bits. Assumes numer <= denom
   1919 // and denom != 0. Since our table is 6bits big (+1), this is a nice fit.
   1920 // Same as (but faster than) SkFixedDiv(numer, denom) >> 10
   1921 
   1922 //unsigned div_64(int numer, int denom);
   1923 static unsigned div_64(int numer, int denom) {
   1924     SkASSERT(numer <= denom);
   1925     SkASSERT(numer > 0);
   1926     SkASSERT(denom > 0);
   1927 
   1928     int nbits = SkCLZ(numer);
   1929     int dbits = SkCLZ(denom);
   1930     int bits = 6 - nbits + dbits;
   1931     SkASSERT(bits <= 6);
   1932 
   1933     if (bits < 0) {  // detect underflow
   1934         return 0;
   1935     }
   1936 
   1937     denom <<= dbits - 1;
   1938     numer <<= nbits - 1;
   1939 
   1940     unsigned result = 0;
   1941 
   1942     // do the first one
   1943     if ((numer -= denom) >= 0) {
   1944         result = 1;
   1945     } else {
   1946         numer += denom;
   1947     }
   1948 
   1949     // Now fall into our switch statement if there are more bits to compute
   1950     if (bits > 0) {
   1951         // make room for the rest of the answer bits
   1952         result <<= bits;
   1953         switch (bits) {
   1954         case 6:
   1955             if ((numer = (numer << 1) - denom) >= 0)
   1956                 result |= 32;
   1957             else
   1958                 numer += denom;
   1959         case 5:
   1960             if ((numer = (numer << 1) - denom) >= 0)
   1961                 result |= 16;
   1962             else
   1963                 numer += denom;
   1964         case 4:
   1965             if ((numer = (numer << 1) - denom) >= 0)
   1966                 result |= 8;
   1967             else
   1968                 numer += denom;
   1969         case 3:
   1970             if ((numer = (numer << 1) - denom) >= 0)
   1971                 result |= 4;
   1972             else
   1973                 numer += denom;
   1974         case 2:
   1975             if ((numer = (numer << 1) - denom) >= 0)
   1976                 result |= 2;
   1977             else
   1978                 numer += denom;
   1979         case 1:
   1980         default:    // not strictly need, but makes GCC make better ARM code
   1981             if ((numer = (numer << 1) - denom) >= 0)
   1982                 result |= 1;
   1983             else
   1984                 numer += denom;
   1985         }
   1986     }
   1987     return result;
   1988 }
   1989 
   1990 // Given x,y in the first quadrant, return 0..63 for the angle [0..90]
   1991 static unsigned atan_0_90(SkFixed y, SkFixed x) {
   1992 #ifdef SK_DEBUG
   1993     {
   1994         static bool gOnce;
   1995         if (!gOnce) {
   1996             gOnce = true;
   1997             SkASSERT(div_64(55, 55) == 64);
   1998             SkASSERT(div_64(128, 256) == 32);
   1999             SkASSERT(div_64(2326528, 4685824) == 31);
   2000             SkASSERT(div_64(753664, 5210112) == 9);
   2001             SkASSERT(div_64(229376, 4882432) == 3);
   2002             SkASSERT(div_64(2, 64) == 2);
   2003             SkASSERT(div_64(1, 64) == 1);
   2004             // test that we handle underflow correctly
   2005             SkASSERT(div_64(12345, 0x54321234) == 0);
   2006         }
   2007     }
   2008 #endif
   2009 
   2010     SkASSERT(y > 0 && x > 0);
   2011     const uint8_t* table = build_sweep_table();
   2012 
   2013     unsigned result;
   2014     bool swap = (x < y);
   2015     if (swap) {
   2016         // first part of the atan(v) = PI/2 - atan(1/v) identity
   2017         // since our div_64 and table want v <= 1, where v = y/x
   2018         SkTSwap<SkFixed>(x, y);
   2019     }
   2020 
   2021     result = div_64(y, x);
   2022 
   2023 #ifdef SK_DEBUG
   2024     {
   2025         unsigned result2 = SkDivBits(y, x, 6);
   2026         SkASSERT(result2 == result ||
   2027                  (result == 1 && result2 == 0));
   2028     }
   2029 #endif
   2030 
   2031     SkASSERT(result < SK_ARRAY_COUNT(gSweepTable));
   2032     result = table[result];
   2033 
   2034     if (swap) {
   2035         // complete the atan(v) = PI/2 - atan(1/v) identity
   2036         result = 64 - result;
   2037         // pin to 63
   2038         result -= result >> 6;
   2039     }
   2040 
   2041     SkASSERT(result <= 63);
   2042     return result;
   2043 }
   2044 
   2045 //  returns angle in a circle [0..2PI) -> [0..255]
   2046 static unsigned SkATan2_255(SkFixed y, SkFixed x) {
   2047     if (x == 0) {
   2048         if (y == 0) {
   2049             return 0;
   2050         }
   2051         return y < 0 ? 192 : 64;
   2052     }
   2053     if (y == 0) {
   2054         return x < 0 ? 128 : 0;
   2055     }
   2056 
   2057     /*  Find the right quadrant for x,y
   2058         Since atan_0_90 only handles the first quadrant, we rotate x,y
   2059         appropriately before calling it, and then add the right amount
   2060         to account for the real quadrant.
   2061         quadrant 0 : add 0                  | x > 0 && y > 0
   2062         quadrant 1 : add 64 (90 degrees)    | x < 0 && y > 0
   2063         quadrant 2 : add 128 (180 degrees)  | x < 0 && y < 0
   2064         quadrant 3 : add 192 (270 degrees)  | x > 0 && y < 0
   2065 
   2066         map x<0 to (1 << 6)
   2067         map y<0 to (3 << 6)
   2068         add = map_x ^ map_y
   2069     */
   2070     int xsign = x >> 31;
   2071     int ysign = y >> 31;
   2072     int add = ((-xsign) ^ (ysign & 3)) << 6;
   2073 
   2074 #ifdef SK_DEBUG
   2075     if (0 == add)
   2076         SkASSERT(x > 0 && y > 0);
   2077     else if (64 == add)
   2078         SkASSERT(x < 0 && y > 0);
   2079     else if (128 == add)
   2080         SkASSERT(x < 0 && y < 0);
   2081     else if (192 == add)
   2082         SkASSERT(x > 0 && y < 0);
   2083     else
   2084         SkASSERT(!"bad value for add");
   2085 #endif
   2086 
   2087     /*  This ^ trick makes x, y positive, and the swap<> handles quadrants
   2088         where we need to rotate x,y by 90 or -90
   2089     */
   2090     x = (x ^ xsign) - xsign;
   2091     y = (y ^ ysign) - ysign;
   2092     if (add & 64) {             // quads 1 or 3 need to swap x,y
   2093         SkTSwap<SkFixed>(x, y);
   2094     }
   2095 
   2096     unsigned result = add + atan_0_90(y, x);
   2097     SkASSERT(result < 256);
   2098     return result;
   2099 }
   2100 
   2101 void Sweep_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   2102     SkMatrix::MapXYProc proc = fDstToIndexProc;
   2103     const SkMatrix&     matrix = fDstToIndex;
   2104     const SkPMColor*    cache = this->getCache32();
   2105     SkPoint             srcPt;
   2106 
   2107     if (fDstToIndexClass != kPerspective_MatrixClass) {
   2108         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   2109                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   2110         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   2111         SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   2112 
   2113         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   2114             SkFixed storage[2];
   2115             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
   2116                                       &storage[0], &storage[1]);
   2117             dx = storage[0];
   2118             dy = storage[1];
   2119         } else {
   2120             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   2121             dx = SkScalarToFixed(matrix.getScaleX());
   2122             dy = SkScalarToFixed(matrix.getSkewY());
   2123         }
   2124 
   2125         for (; count > 0; --count) {
   2126             *dstC++ = cache[SkATan2_255(fy, fx)];
   2127             fx += dx;
   2128             fy += dy;
   2129         }
   2130     } else {  // perspective case
   2131         for (int stop = x + count; x < stop; x++) {
   2132             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   2133                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   2134 
   2135             int index = SkATan2_255(SkScalarToFixed(srcPt.fY),
   2136                                     SkScalarToFixed(srcPt.fX));
   2137             *dstC++ = cache[index];
   2138         }
   2139     }
   2140 }
   2141 
   2142 void Sweep_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
   2143     SkMatrix::MapXYProc proc = fDstToIndexProc;
   2144     const SkMatrix&     matrix = fDstToIndex;
   2145     const uint16_t*     cache = this->getCache16();
   2146     int                 toggle = ((x ^ y) & 1) << kCache16Bits;
   2147     SkPoint             srcPt;
   2148 
   2149     if (fDstToIndexClass != kPerspective_MatrixClass) {
   2150         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   2151                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   2152         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
   2153         SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
   2154 
   2155         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   2156             SkFixed storage[2];
   2157             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
   2158                                       &storage[0], &storage[1]);
   2159             dx = storage[0];
   2160             dy = storage[1];
   2161         } else {
   2162             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   2163             dx = SkScalarToFixed(matrix.getScaleX());
   2164             dy = SkScalarToFixed(matrix.getSkewY());
   2165         }
   2166 
   2167         for (; count > 0; --count) {
   2168             int index = SkATan2_255(fy, fx) >> (8 - kCache16Bits);
   2169             *dstC++ = cache[toggle + index];
   2170             toggle ^= (1 << kCache16Bits);
   2171             fx += dx;
   2172             fy += dy;
   2173         }
   2174     } else {  // perspective case
   2175         for (int stop = x + count; x < stop; x++) {
   2176             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   2177                          SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   2178 
   2179             int index = SkATan2_255(SkScalarToFixed(srcPt.fY),
   2180                                     SkScalarToFixed(srcPt.fX));
   2181             index >>= (8 - kCache16Bits);
   2182             *dstC++ = cache[toggle + index];
   2183             toggle ^= (1 << kCache16Bits);
   2184         }
   2185     }
   2186 }
   2187 
   2188 ///////////////////////////////////////////////////////////////////////////////
   2189 ///////////////////////////////////////////////////////////////////////////////
   2190 
   2191 // assumes colors is SkColor* and pos is SkScalar*
   2192 #define EXPAND_1_COLOR(count)               \
   2193     SkColor tmp[2];                         \
   2194     do {                                    \
   2195         if (1 == count) {                   \
   2196             tmp[0] = tmp[1] = colors[0];    \
   2197             colors = tmp;                   \
   2198             pos = NULL;                     \
   2199             count = 2;                      \
   2200         }                                   \
   2201     } while (0)
   2202 
   2203 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
   2204                                          const SkColor colors[],
   2205                                          const SkScalar pos[], int colorCount,
   2206                                          SkShader::TileMode mode,
   2207                                          SkUnitMapper* mapper) {
   2208     if (NULL == pts || NULL == colors || colorCount < 1) {
   2209         return NULL;
   2210     }
   2211     EXPAND_1_COLOR(colorCount);
   2212 
   2213     return SkNEW_ARGS(Linear_Gradient,
   2214                       (pts, colors, pos, colorCount, mode, mapper));
   2215 }
   2216 
   2217 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
   2218                                          const SkColor colors[],
   2219                                          const SkScalar pos[], int colorCount,
   2220                                          SkShader::TileMode mode,
   2221                                          SkUnitMapper* mapper) {
   2222     if (radius <= 0 || NULL == colors || colorCount < 1) {
   2223         return NULL;
   2224     }
   2225     EXPAND_1_COLOR(colorCount);
   2226 
   2227     return SkNEW_ARGS(Radial_Gradient,
   2228                       (center, radius, colors, pos, colorCount, mode, mapper));
   2229 }
   2230 
   2231 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
   2232                                                  SkScalar startRadius,
   2233                                                  const SkPoint& end,
   2234                                                  SkScalar endRadius,
   2235                                                  const SkColor colors[],
   2236                                                  const SkScalar pos[],
   2237                                                  int colorCount,
   2238                                                  SkShader::TileMode mode,
   2239                                                  SkUnitMapper* mapper) {
   2240     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
   2241         return NULL;
   2242     }
   2243     EXPAND_1_COLOR(colorCount);
   2244 
   2245     return SkNEW_ARGS(Two_Point_Radial_Gradient,
   2246                       (start, startRadius, end, endRadius, colors, pos,
   2247                        colorCount, mode, mapper));
   2248 }
   2249 
   2250 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
   2251                                         const SkColor colors[],
   2252                                         const SkScalar pos[],
   2253                                         int count, SkUnitMapper* mapper) {
   2254     if (NULL == colors || count < 1) {
   2255         return NULL;
   2256     }
   2257     EXPAND_1_COLOR(count);
   2258 
   2259     return SkNEW_ARGS(Sweep_Gradient, (cx, cy, colors, pos, count, mapper));
   2260 }
   2261 
   2262 static SkFlattenable::Registrar gLinearGradientReg("Linear_Gradient",
   2263                                                    Linear_Gradient::CreateProc);
   2264 
   2265 static SkFlattenable::Registrar gRadialGradientReg("Radial_Gradient",
   2266                                                    Radial_Gradient::CreateProc);
   2267 
   2268 static SkFlattenable::Registrar gSweepGradientReg("Sweep_Gradient",
   2269                                                    Sweep_Gradient::CreateProc);
   2270 
   2271 static SkFlattenable::Registrar
   2272     gTwoPointRadialGradientReg("Two_Point_Radial_Gradient",
   2273                                Two_Point_Radial_Gradient::CreateProc);
   2274