gfx/skia/trunk/src/effects/gradients/SkGradientShader.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright 2006 The Android Open Source Project
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkGradientShaderPriv.h"
     9 #include "SkLinearGradient.h"
    10 #include "SkRadialGradient.h"
    11 #include "SkTwoPointRadialGradient.h"
    12 #include "SkTwoPointConicalGradient.h"
    13 #include "SkSweepGradient.h"
    15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
    16     SkASSERT(desc.fCount > 1);
    18     fCacheAlpha = 256;  // init to a value that paint.getAlpha() can't return
    20     fMapper = desc.fMapper;
    21     SkSafeRef(fMapper);
    22     fGradFlags = SkToU8(desc.fFlags);
    24     SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
    25     SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
    26     fTileMode = desc.fTileMode;
    27     fTileProc = gTileProcs[desc.fTileMode];
    29     fCache16 = fCache16Storage = NULL;
    30     fCache32 = NULL;
    31     fCache32PixelRef = NULL;
    33     /*  Note: we let the caller skip the first and/or last position.
    34         i.e. pos[0] = 0.3, pos[1] = 0.7
    35         In these cases, we insert dummy entries to ensure that the final data
    36         will be bracketed by [0, 1].
    37         i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1
    39         Thus colorCount (the caller's value, and fColorCount (our value) may
    40         differ by up to 2. In the above example:
    41             colorCount = 2
    42             fColorCount = 4
    43      */
    44     fColorCount = desc.fCount;
    45     // check if we need to add in dummy start and/or end position/colors
    46     bool dummyFirst = false;
    47     bool dummyLast = false;
    48     if (desc.fPos) {
    49         dummyFirst = desc.fPos[0] != 0;
    50         dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1;
    51         fColorCount += dummyFirst + dummyLast;
    52     }
    54     if (fColorCount > kColorStorageCount) {
    55         size_t size = sizeof(SkColor) + sizeof(Rec);
    56         fOrigColors = reinterpret_cast<SkColor*>(
    57                                         sk_malloc_throw(size * fColorCount));
    58     }
    59     else {
    60         fOrigColors = fStorage;
    61     }
    63     // Now copy over the colors, adding the dummies as needed
    64     {
    65         SkColor* origColors = fOrigColors;
    66         if (dummyFirst) {
    67             *origColors++ = desc.fColors[0];
    68         }
    69         memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor));
    70         if (dummyLast) {
    71             origColors += desc.fCount;
    72             *origColors = desc.fColors[desc.fCount - 1];
    73         }
    74     }
    76     fRecs = (Rec*)(fOrigColors + fColorCount);
    77     if (fColorCount > 2) {
    78         Rec* recs = fRecs;
    79         recs->fPos = 0;
    80         //  recs->fScale = 0; // unused;
    81         recs += 1;
    82         if (desc.fPos) {
    83             /*  We need to convert the user's array of relative positions into
    84                 fixed-point positions and scale factors. We need these results
    85                 to be strictly monotonic (no two values equal or out of order).
    86                 Hence this complex loop that just jams a zero for the scale
    87                 value if it sees a segment out of order, and it assures that
    88                 we start at 0 and end at 1.0
    89             */
    90             SkFixed prev = 0;
    91             int startIndex = dummyFirst ? 0 : 1;
    92             int count = desc.fCount + dummyLast;
    93             for (int i = startIndex; i < count; i++) {
    94                 // force the last value to be 1.0
    95                 SkFixed curr;
    96                 if (i == desc.fCount) {  // we're really at the dummyLast
    97                     curr = SK_Fixed1;
    98                 } else {
    99                     curr = SkScalarToFixed(desc.fPos[i]);
   100                 }
   101                 // pin curr withing range
   102                 if (curr < 0) {
   103                     curr = 0;
   104                 } else if (curr > SK_Fixed1) {
   105                     curr = SK_Fixed1;
   106                 }
   107                 recs->fPos = curr;
   108                 if (curr > prev) {
   109                     recs->fScale = (1 << 24) / (curr - prev);
   110                 } else {
   111                     recs->fScale = 0; // ignore this segment
   112                 }
   113                 // get ready for the next value
   114                 prev = curr;
   115                 recs += 1;
   116             }
   117         } else {    // assume even distribution
   118             SkFixed dp = SK_Fixed1 / (desc.fCount - 1);
   119             SkFixed p = dp;
   120             SkFixed scale = (desc.fCount - 1) << 8;  // (1 << 24) / dp
   121             for (int i = 1; i < desc.fCount; i++) {
   122                 recs->fPos   = p;
   123                 recs->fScale = scale;
   124                 recs += 1;
   125                 p += dp;
   126             }
   127         }
   128     }
   129     this->initCommon();
   130 }
   132 static uint32_t pack_mode_flags(SkShader::TileMode mode, uint32_t flags) {
   133     SkASSERT(0 == (flags >> 28));
   134     SkASSERT(0 == ((uint32_t)mode >> 4));
   135     return (flags << 4) | mode;
   136 }
   138 static SkShader::TileMode unpack_mode(uint32_t packed) {
   139     return (SkShader::TileMode)(packed & 0xF);
   140 }
   142 static uint32_t unpack_flags(uint32_t packed) {
   143     return packed >> 4;
   144 }
   146 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) {
   147     fCacheAlpha = 256;
   149     fMapper = buffer.readUnitMapper();
   151     fCache16 = fCache16Storage = NULL;
   152     fCache32 = NULL;
   153     fCache32PixelRef = NULL;
   155     int colorCount = fColorCount = buffer.getArrayCount();
   156     if (colorCount > kColorStorageCount) {
   157         size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount;
   158         if (buffer.validateAvailable(allocSize)) {
   159             fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize));
   160         } else {
   161             fOrigColors =  NULL;
   162             colorCount = fColorCount = 0;
   163         }
   164     } else {
   165         fOrigColors = fStorage;
   166     }
   167     buffer.readColorArray(fOrigColors, colorCount);
   169     {
   170         uint32_t packed = buffer.readUInt();
   171         fGradFlags = SkToU8(unpack_flags(packed));
   172         fTileMode = unpack_mode(packed);
   173     }
   174     fTileProc = gTileProcs[fTileMode];
   175     fRecs = (Rec*)(fOrigColors + colorCount);
   176     if (colorCount > 2) {
   177         Rec* recs = fRecs;
   178         recs[0].fPos = 0;
   179         for (int i = 1; i < colorCount; i++) {
   180             recs[i].fPos = buffer.readInt();
   181             recs[i].fScale = buffer.readUInt();
   182         }
   183     }
   184     buffer.readMatrix(&fPtsToUnit);
   185     this->initCommon();
   186 }
   188 SkGradientShaderBase::~SkGradientShaderBase() {
   189     if (fCache16Storage) {
   190         sk_free(fCache16Storage);
   191     }
   192     SkSafeUnref(fCache32PixelRef);
   193     if (fOrigColors != fStorage) {
   194         sk_free(fOrigColors);
   195     }
   196     SkSafeUnref(fMapper);
   197 }
   199 void SkGradientShaderBase::initCommon() {
   200     fFlags = 0;
   201     unsigned colorAlpha = 0xFF;
   202     for (int i = 0; i < fColorCount; i++) {
   203         colorAlpha &= SkColorGetA(fOrigColors[i]);
   204     }
   205     fColorsAreOpaque = colorAlpha == 0xFF;
   206 }
   208 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
   209     this->INHERITED::flatten(buffer);
   210     buffer.writeFlattenable(fMapper);
   211     buffer.writeColorArray(fOrigColors, fColorCount);
   212     buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags));
   213     if (fColorCount > 2) {
   214         Rec* recs = fRecs;
   215         for (int i = 1; i < fColorCount; i++) {
   216             buffer.writeInt(recs[i].fPos);
   217             buffer.writeUInt(recs[i].fScale);
   218         }
   219     }
   220     buffer.writeMatrix(fPtsToUnit);
   221 }
   223 bool SkGradientShaderBase::isOpaque() const {
   224     return fColorsAreOpaque;
   225 }
   227 bool SkGradientShaderBase::setContext(const SkBitmap& device,
   228                                  const SkPaint& paint,
   229                                  const SkMatrix& matrix) {
   230     if (!this->INHERITED::setContext(device, paint, matrix)) {
   231         return false;
   232     }
   234     const SkMatrix& inverse = this->getTotalInverse();
   236     if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) {
   237         // need to keep our set/end context calls balanced.
   238         this->INHERITED::endContext();
   239         return false;
   240     }
   242     fDstToIndexProc = fDstToIndex.getMapXYProc();
   243     fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex);
   245     // now convert our colors in to PMColors
   246     unsigned paintAlpha = this->getPaintAlpha();
   248     fFlags = this->INHERITED::getFlags();
   249     if (fColorsAreOpaque && paintAlpha == 0xFF) {
   250         fFlags |= kOpaqueAlpha_Flag;
   251     }
   252     // we can do span16 as long as our individual colors are opaque,
   253     // regardless of the paint's alpha
   254     if (fColorsAreOpaque) {
   255         fFlags |= kHasSpan16_Flag;
   256     }
   258     this->setCacheAlpha(paintAlpha);
   259     return true;
   260 }
   262 void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const {
   263     // if the new alpha differs from the previous time we were called, inval our cache
   264     // this will trigger the cache to be rebuilt.
   265     // we don't care about the first time, since the cache ptrs will already be NULL
   266     if (fCacheAlpha != alpha) {
   267         fCache16 = NULL;            // inval the cache
   268         fCache32 = NULL;            // inval the cache
   269         fCacheAlpha = alpha;        // record the new alpha
   270         // inform our subclasses
   271         if (fCache32PixelRef) {
   272             fCache32PixelRef->notifyPixelsChanged();
   273         }
   274     }
   275 }
   277 #define Fixed_To_Dot8(x)        (((x) + 0x80) >> 8)
   279 /** We take the original colors, not our premultiplied PMColors, since we can
   280     build a 16bit table as long as the original colors are opaque, even if the
   281     paint specifies a non-opaque alpha.
   282 */
   283 void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
   284                                       int count) {
   285     SkASSERT(count > 1);
   286     SkASSERT(SkColorGetA(c0) == 0xFF);
   287     SkASSERT(SkColorGetA(c1) == 0xFF);
   289     SkFixed r = SkColorGetR(c0);
   290     SkFixed g = SkColorGetG(c0);
   291     SkFixed b = SkColorGetB(c0);
   293     SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
   294     SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
   295     SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
   297     r = SkIntToFixed(r) + 0x8000;
   298     g = SkIntToFixed(g) + 0x8000;
   299     b = SkIntToFixed(b) + 0x8000;
   301     do {
   302         unsigned rr = r >> 16;
   303         unsigned gg = g >> 16;
   304         unsigned bb = b >> 16;
   305         cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
   306         cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
   307         cache += 1;
   308         r += dr;
   309         g += dg;
   310         b += db;
   311     } while (--count != 0);
   312 }
   314 /*
   315  *  r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
   316  *  release builds, we saw a compiler error where the 0xFF parameter in
   317  *  SkPackARGB32() was being totally ignored whenever it was called with
   318  *  a non-zero add (e.g. 0x8000).
   319  *
   320  *  We found two work-arounds:
   321  *      1. change r,g,b to unsigned (or just one of them)
   322  *      2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
   323  *         of using |
   324  *
   325  *  We chose #1 just because it was more localized.
   326  *  See http://code.google.com/p/skia/issues/detail?id=1113
   327  *
   328  *  The type SkUFixed encapsulate this need for unsigned, but logically Fixed.
   329  */
   330 typedef uint32_t SkUFixed;
   332 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
   333                                       int count, U8CPU paintAlpha, uint32_t gradFlags) {
   334     SkASSERT(count > 1);
   336     // need to apply paintAlpha to our two endpoints
   337     uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
   338     uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
   341     const bool interpInPremul = SkToBool(gradFlags &
   342                            SkGradientShader::kInterpolateColorsInPremul_Flag);
   344     uint32_t r0 = SkColorGetR(c0);
   345     uint32_t g0 = SkColorGetG(c0);
   346     uint32_t b0 = SkColorGetB(c0);
   348     uint32_t r1 = SkColorGetR(c1);
   349     uint32_t g1 = SkColorGetG(c1);
   350     uint32_t b1 = SkColorGetB(c1);
   352     if (interpInPremul) {
   353         r0 = SkMulDiv255Round(r0, a0);
   354         g0 = SkMulDiv255Round(g0, a0);
   355         b0 = SkMulDiv255Round(b0, a0);
   357         r1 = SkMulDiv255Round(r1, a1);
   358         g1 = SkMulDiv255Round(g1, a1);
   359         b1 = SkMulDiv255Round(b1, a1);
   360     }
   362     SkFixed da = SkIntToFixed(a1 - a0) / (count - 1);
   363     SkFixed dr = SkIntToFixed(r1 - r0) / (count - 1);
   364     SkFixed dg = SkIntToFixed(g1 - g0) / (count - 1);
   365     SkFixed db = SkIntToFixed(b1 - b0) / (count - 1);
   367     /*  We pre-add 1/8 to avoid having to add this to our [0] value each time
   368         in the loop. Without this, the bias for each would be
   369             0x2000  0xA000  0xE000  0x6000
   370         With this trick, we can add 0 for the first (no-op) and just adjust the
   371         others.
   372      */
   373     SkUFixed a = SkIntToFixed(a0) + 0x2000;
   374     SkUFixed r = SkIntToFixed(r0) + 0x2000;
   375     SkUFixed g = SkIntToFixed(g0) + 0x2000;
   376     SkUFixed b = SkIntToFixed(b0) + 0x2000;
   378     /*
   379      *  Our dither-cell (spatially) is
   380      *      0 2
   381      *      3 1
   382      *  Where
   383      *      [0] -> [-1/8 ... 1/8 ) values near 0
   384      *      [1] -> [ 1/8 ... 3/8 ) values near 1/4
   385      *      [2] -> [ 3/8 ... 5/8 ) values near 1/2
   386      *      [3] -> [ 5/8 ... 7/8 ) values near 3/4
   387      */
   389     if (0xFF == a0 && 0 == da) {
   390         do {
   391             cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0     ) >> 16,
   392                                                         (g + 0     ) >> 16,
   393                                                         (b + 0     ) >> 16);
   394             cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + 0x8000) >> 16,
   395                                                         (g + 0x8000) >> 16,
   396                                                         (b + 0x8000) >> 16);
   397             cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + 0xC000) >> 16,
   398                                                         (g + 0xC000) >> 16,
   399                                                         (b + 0xC000) >> 16);
   400             cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + 0x4000) >> 16,
   401                                                         (g + 0x4000) >> 16,
   402                                                         (b + 0x4000) >> 16);
   403             cache += 1;
   404             r += dr;
   405             g += dg;
   406             b += db;
   407         } while (--count != 0);
   408     } else if (interpInPremul) {
   409         do {
   410             cache[kCache32Count*0] = SkPackARGB32((a + 0     ) >> 16,
   411                                                   (r + 0     ) >> 16,
   412                                                   (g + 0     ) >> 16,
   413                                                   (b + 0     ) >> 16);
   414             cache[kCache32Count*1] = SkPackARGB32((a + 0x8000) >> 16,
   415                                                   (r + 0x8000) >> 16,
   416                                                   (g + 0x8000) >> 16,
   417                                                   (b + 0x8000) >> 16);
   418             cache[kCache32Count*2] = SkPackARGB32((a + 0xC000) >> 16,
   419                                                   (r + 0xC000) >> 16,
   420                                                   (g + 0xC000) >> 16,
   421                                                   (b + 0xC000) >> 16);
   422             cache[kCache32Count*3] = SkPackARGB32((a + 0x4000) >> 16,
   423                                                   (r + 0x4000) >> 16,
   424                                                   (g + 0x4000) >> 16,
   425                                                   (b + 0x4000) >> 16);
   426             cache += 1;
   427             a += da;
   428             r += dr;
   429             g += dg;
   430             b += db;
   431         } while (--count != 0);
   432     } else {    // interpolate in unpreml space
   433         do {
   434             cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0     ) >> 16,
   435                                                              (r + 0     ) >> 16,
   436                                                              (g + 0     ) >> 16,
   437                                                              (b + 0     ) >> 16);
   438             cache[kCache32Count*1] = SkPremultiplyARGBInline((a + 0x8000) >> 16,
   439                                                              (r + 0x8000) >> 16,
   440                                                              (g + 0x8000) >> 16,
   441                                                              (b + 0x8000) >> 16);
   442             cache[kCache32Count*2] = SkPremultiplyARGBInline((a + 0xC000) >> 16,
   443                                                              (r + 0xC000) >> 16,
   444                                                              (g + 0xC000) >> 16,
   445                                                              (b + 0xC000) >> 16);
   446             cache[kCache32Count*3] = SkPremultiplyARGBInline((a + 0x4000) >> 16,
   447                                                              (r + 0x4000) >> 16,
   448                                                              (g + 0x4000) >> 16,
   449                                                              (b + 0x4000) >> 16);
   450             cache += 1;
   451             a += da;
   452             r += dr;
   453             g += dg;
   454             b += db;
   455         } while (--count != 0);
   456     }
   457 }
   459 static inline int SkFixedToFFFF(SkFixed x) {
   460     SkASSERT((unsigned)x <= SK_Fixed1);
   461     return x - (x >> 16);
   462 }
   464 static inline U16CPU bitsTo16(unsigned x, const unsigned bits) {
   465     SkASSERT(x < (1U << bits));
   466     if (6 == bits) {
   467         return (x << 10) | (x << 4) | (x >> 2);
   468     }
   469     if (8 == bits) {
   470         return (x << 8) | x;
   471     }
   472     sk_throw();
   473     return 0;
   474 }
   476 const uint16_t* SkGradientShaderBase::getCache16() const {
   477     if (fCache16 == NULL) {
   478         // double the count for dither entries
   479         const int entryCount = kCache16Count * 2;
   480         const size_t allocSize = sizeof(uint16_t) * entryCount;
   482         if (fCache16Storage == NULL) { // set the storage and our working ptr
   483             fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
   484         }
   485         fCache16 = fCache16Storage;
   486         if (fColorCount == 2) {
   487             Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1],
   488                             kCache16Count);
   489         } else {
   490             Rec* rec = fRecs;
   491             int prevIndex = 0;
   492             for (int i = 1; i < fColorCount; i++) {
   493                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
   494                 SkASSERT(nextIndex < kCache16Count);
   496                 if (nextIndex > prevIndex)
   497                     Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
   498                 prevIndex = nextIndex;
   499             }
   500         }
   502         if (fMapper) {
   503             fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
   504             uint16_t* linear = fCache16;         // just computed linear data
   505             uint16_t* mapped = fCache16Storage;  // storage for mapped data
   506             SkUnitMapper* map = fMapper;
   507             for (int i = 0; i < kCache16Count; i++) {
   508                 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift;
   509                 mapped[i] = linear[index];
   510                 mapped[i + kCache16Count] = linear[index + kCache16Count];
   511             }
   512             sk_free(fCache16);
   513             fCache16 = fCache16Storage;
   514         }
   515     }
   516     return fCache16;
   517 }
   519 const SkPMColor* SkGradientShaderBase::getCache32() const {
   520     if (fCache32 == NULL) {
   521         SkImageInfo info;
   522         info.fWidth = kCache32Count;
   523         info.fHeight = 4;   // for our 4 dither rows
   524         info.fAlphaType = kPremul_SkAlphaType;
   525         info.fColorType = kPMColor_SkColorType;
   527         if (NULL == fCache32PixelRef) {
   528             fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
   529         }
   530         fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
   531         if (fColorCount == 2) {
   532             Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
   533                             kCache32Count, fCacheAlpha, fGradFlags);
   534         } else {
   535             Rec* rec = fRecs;
   536             int prevIndex = 0;
   537             for (int i = 1; i < fColorCount; i++) {
   538                 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
   539                 SkASSERT(nextIndex < kCache32Count);
   541                 if (nextIndex > prevIndex)
   542                     Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
   543                                     fOrigColors[i], nextIndex - prevIndex + 1,
   544                                     fCacheAlpha, fGradFlags);
   545                 prevIndex = nextIndex;
   546             }
   547         }
   549         if (fMapper) {
   550             SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL);
   551             SkPMColor* linear = fCache32;           // just computed linear data
   552             SkPMColor* mapped = (SkPMColor*)newPR->getAddr();    // storage for mapped data
   553             SkUnitMapper* map = fMapper;
   554             for (int i = 0; i < kCache32Count; i++) {
   555                 int index = map->mapUnit16((i << 8) | i) >> 8;
   556                 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0];
   557                 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1];
   558                 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2];
   559                 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3];
   560             }
   561             fCache32PixelRef->unref();
   562             fCache32PixelRef = newPR;
   563             fCache32 = (SkPMColor*)newPR->getAddr();
   564         }
   565     }
   566     return fCache32;
   567 }
   569 /*
   570  *  Because our caller might rebuild the same (logically the same) gradient
   571  *  over and over, we'd like to return exactly the same "bitmap" if possible,
   572  *  allowing the client to utilize a cache of our bitmap (e.g. with a GPU).
   573  *  To do that, we maintain a private cache of built-bitmaps, based on our
   574  *  colors and positions. Note: we don't try to flatten the fMapper, so if one
   575  *  is present, we skip the cache for now.
   576  */
   577 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
   578     // our caller assumes no external alpha, so we ensure that our cache is
   579     // built with 0xFF
   580     this->setCacheAlpha(0xFF);
   582     // don't have a way to put the mapper into our cache-key yet
   583     if (fMapper) {
   584         // force our cahce32pixelref to be built
   585         (void)this->getCache32();
   586         bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
   587         bitmap->setPixelRef(fCache32PixelRef);
   588         return;
   589     }
   591     // build our key: [numColors + colors[] + {positions[]} + flags ]
   592     int count = 1 + fColorCount + 1;
   593     if (fColorCount > 2) {
   594         count += fColorCount - 1;    // fRecs[].fPos
   595     }
   597     SkAutoSTMalloc<16, int32_t> storage(count);
   598     int32_t* buffer = storage.get();
   600     *buffer++ = fColorCount;
   601     memcpy(buffer, fOrigColors, fColorCount * sizeof(SkColor));
   602     buffer += fColorCount;
   603     if (fColorCount > 2) {
   604         for (int i = 1; i < fColorCount; i++) {
   605             *buffer++ = fRecs[i].fPos;
   606         }
   607     }
   608     *buffer++ = fGradFlags;
   609     SkASSERT(buffer - storage.get() == count);
   611     ///////////////////////////////////
   613     SK_DECLARE_STATIC_MUTEX(gMutex);
   614     static SkBitmapCache* gCache;
   615     // each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp
   616     static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32;
   617     SkAutoMutexAcquire ama(gMutex);
   619     if (NULL == gCache) {
   620         gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS));
   621     }
   622     size_t size = count * sizeof(int32_t);
   624     if (!gCache->find(storage.get(), size, bitmap)) {
   625         // force our cahce32pixelref to be built
   626         (void)this->getCache32();
   627         bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1));
   628         bitmap->setPixelRef(fCache32PixelRef);
   630         gCache->add(storage.get(), size, *bitmap);
   631     }
   632 }
   634 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
   635     if (info) {
   636         if (info->fColorCount >= fColorCount) {
   637             if (info->fColors) {
   638                 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
   639             }
   640             if (info->fColorOffsets) {
   641                 if (fColorCount == 2) {
   642                     info->fColorOffsets[0] = 0;
   643                     info->fColorOffsets[1] = SK_Scalar1;
   644                 } else if (fColorCount > 2) {
   645                     for (int i = 0; i < fColorCount; ++i) {
   646                         info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
   647                     }
   648                 }
   649             }
   650         }
   651         info->fColorCount = fColorCount;
   652         info->fTileMode = fTileMode;
   653         info->fGradientFlags = fGradFlags;
   654     }
   655 }
   657 #ifndef SK_IGNORE_TO_STRING
   658 void SkGradientShaderBase::toString(SkString* str) const {
   660     str->appendf("%d colors: ", fColorCount);
   662     for (int i = 0; i < fColorCount; ++i) {
   663         str->appendHex(fOrigColors[i]);
   664         if (i < fColorCount-1) {
   665             str->append(", ");
   666         }
   667     }
   669     if (fColorCount > 2) {
   670         str->append(" points: (");
   671         for (int i = 0; i < fColorCount; ++i) {
   672             str->appendScalar(SkFixedToScalar(fRecs[i].fPos));
   673             if (i < fColorCount-1) {
   674                 str->append(", ");
   675             }
   676         }
   677         str->append(")");
   678     }
   680     static const char* gTileModeName[SkShader::kTileModeCount] = {
   681         "clamp", "repeat", "mirror"
   682     };
   684     str->append(" ");
   685     str->append(gTileModeName[fTileMode]);
   687     // TODO: add "fMapper->toString(str);" when SkUnitMapper::toString is added
   689     this->INHERITED::toString(str);
   690 }
   691 #endif
   693 ///////////////////////////////////////////////////////////////////////////////
   694 ///////////////////////////////////////////////////////////////////////////////
   696 #include "SkEmptyShader.h"
   698 // assumes colors is SkColor* and pos is SkScalar*
   699 #define EXPAND_1_COLOR(count)               \
   700     SkColor tmp[2];                         \
   701     do {                                    \
   702         if (1 == count) {                   \
   703             tmp[0] = tmp[1] = colors[0];    \
   704             colors = tmp;                   \
   705             pos = NULL;                     \
   706             count = 2;                      \
   707         }                                   \
   708     } while (0)
   710 static void desc_init(SkGradientShaderBase::Descriptor* desc,
   711                       const SkColor colors[],
   712                       const SkScalar pos[], int colorCount,
   713                       SkShader::TileMode mode,
   714                       SkUnitMapper* mapper, uint32_t flags) {
   715     desc->fColors   = colors;
   716     desc->fPos      = pos;
   717     desc->fCount    = colorCount;
   718     desc->fTileMode = mode;
   719     desc->fMapper   = mapper;
   720     desc->fFlags    = flags;
   721 }
   723 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
   724                                          const SkColor colors[],
   725                                          const SkScalar pos[], int colorCount,
   726                                          SkShader::TileMode mode,
   727                                          SkUnitMapper* mapper,
   728                                          uint32_t flags) {
   729     if (NULL == pts || NULL == colors || colorCount < 1) {
   730         return NULL;
   731     }
   732     EXPAND_1_COLOR(colorCount);
   734     SkGradientShaderBase::Descriptor desc;
   735     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
   736     return SkNEW_ARGS(SkLinearGradient, (pts, desc));
   737 }
   739 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
   740                                          const SkColor colors[],
   741                                          const SkScalar pos[], int colorCount,
   742                                          SkShader::TileMode mode,
   743                                          SkUnitMapper* mapper,
   744                                          uint32_t flags) {
   745     if (radius <= 0 || NULL == colors || colorCount < 1) {
   746         return NULL;
   747     }
   748     EXPAND_1_COLOR(colorCount);
   750     SkGradientShaderBase::Descriptor desc;
   751     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
   752     return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
   753 }
   755 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
   756                                                  SkScalar startRadius,
   757                                                  const SkPoint& end,
   758                                                  SkScalar endRadius,
   759                                                  const SkColor colors[],
   760                                                  const SkScalar pos[],
   761                                                  int colorCount,
   762                                                  SkShader::TileMode mode,
   763                                                  SkUnitMapper* mapper,
   764                                                  uint32_t flags) {
   765     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
   766         return NULL;
   767     }
   768     EXPAND_1_COLOR(colorCount);
   770     SkGradientShaderBase::Descriptor desc;
   771     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
   772     return SkNEW_ARGS(SkTwoPointRadialGradient,
   773                       (start, startRadius, end, endRadius, desc));
   774 }
   776 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
   777                                                   SkScalar startRadius,
   778                                                   const SkPoint& end,
   779                                                   SkScalar endRadius,
   780                                                   const SkColor colors[],
   781                                                   const SkScalar pos[],
   782                                                   int colorCount,
   783                                                   SkShader::TileMode mode,
   784                                                   SkUnitMapper* mapper,
   785                                                   uint32_t flags) {
   786     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
   787         return NULL;
   788     }
   789     if (start == end && startRadius == endRadius) {
   790         return SkNEW(SkEmptyShader);
   791     }
   792     EXPAND_1_COLOR(colorCount);
   794     SkGradientShaderBase::Descriptor desc;
   795     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
   796     return SkNEW_ARGS(SkTwoPointConicalGradient,
   797                       (start, startRadius, end, endRadius, desc));
   798 }
   800 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
   801                                         const SkColor colors[],
   802                                         const SkScalar pos[],
   803                                         int colorCount, SkUnitMapper* mapper,
   804                                         uint32_t flags) {
   805     if (NULL == colors || colorCount < 1) {
   806         return NULL;
   807     }
   808     EXPAND_1_COLOR(colorCount);
   810     SkGradientShaderBase::Descriptor desc;
   811     desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
   812     return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
   813 }
   815 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader)
   816     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient)
   817     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient)
   818     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient)
   819     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient)
   820     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient)
   821 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
   823 ///////////////////////////////////////////////////////////////////////////////
   825 #if SK_SUPPORT_GPU
   827 #include "effects/GrTextureStripAtlas.h"
   828 #include "GrTBackendEffectFactory.h"
   829 #include "SkGr.h"
   831 GrGLGradientEffect::GrGLGradientEffect(const GrBackendEffectFactory& factory)
   832     : INHERITED(factory)
   833     , fCachedYCoord(SK_ScalarMax) {
   834 }
   836 GrGLGradientEffect::~GrGLGradientEffect() { }
   838 void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) {
   840     if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case
   841         fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   842                                              kVec4f_GrSLType, "GradientStartColor");
   843         fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   844                                            kVec4f_GrSLType, "GradientEndColor");
   846     } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case
   847         fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   848                                              kVec4f_GrSLType, "GradientStartColor");
   849         fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   850                                            kVec4f_GrSLType, "GradientMidColor");
   851         fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   852                                              kVec4f_GrSLType, "GradientEndColor");
   854     } else { // if not a fast case
   855         fFSYUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   856                                       kFloat_GrSLType, "GradientYCoordFS");
   857     }
   858 }
   860 static inline void set_color_uni(const GrGLUniformManager& uman,
   861                                  const GrGLUniformManager::UniformHandle uni,
   862                                  const SkColor* color) {
   863        uman.set4f(uni,
   864                   SkColorGetR(*color) / 255.f,
   865                   SkColorGetG(*color) / 255.f,
   866                   SkColorGetB(*color) / 255.f,
   867                   SkColorGetA(*color) / 255.f);
   868 }
   870 static inline void set_mul_color_uni(const GrGLUniformManager& uman,
   871                                      const GrGLUniformManager::UniformHandle uni,
   872                                      const SkColor* color){
   873        float a = SkColorGetA(*color) / 255.f;
   874        float aDiv255 = a / 255.f;
   875        uman.set4f(uni,
   876                   SkColorGetR(*color) * aDiv255,
   877                   SkColorGetG(*color) * aDiv255,
   878                   SkColorGetB(*color) * aDiv255,
   879                   a);
   880 }
   882 void GrGLGradientEffect::setData(const GrGLUniformManager& uman,
   883                                  const GrDrawEffect& drawEffect) {
   885     const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
   888     if (GrGradientEffect::kTwo_ColorType == e.getColorType()){
   890         if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
   891             set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
   892             set_mul_color_uni(uman, fColorEndUni,   e.getColors(1));
   893         } else {
   894             set_color_uni(uman, fColorStartUni, e.getColors(0));
   895             set_color_uni(uman, fColorEndUni,   e.getColors(1));
   896         }
   898     } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
   900         if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
   901             set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
   902             set_mul_color_uni(uman, fColorMidUni,   e.getColors(1));
   903             set_mul_color_uni(uman, fColorEndUni,   e.getColors(2));
   904         } else {
   905             set_color_uni(uman, fColorStartUni, e.getColors(0));
   906             set_color_uni(uman, fColorMidUni,   e.getColors(1));
   907             set_color_uni(uman, fColorEndUni,   e.getColors(2));
   908         }
   909     } else {
   911         SkScalar yCoord = e.getYCoord();
   912         if (yCoord != fCachedYCoord) {
   913             uman.set1f(fFSYUni, yCoord);
   914             fCachedYCoord = yCoord;
   915         }
   916     }
   917 }
   920 GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect& drawEffect) {
   921     const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
   923     EffectKey key = 0;
   925     if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
   926         key |= kTwoColorKey;
   927     } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
   928         key |= kThreeColorKey;
   929     }
   931     if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
   932         key |= kPremulBeforeInterpKey;
   933     }
   935     return key;
   936 }
   938 void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
   939                                    const char* gradientTValue,
   940                                    EffectKey key,
   941                                    const char* outputColor,
   942                                    const char* inputColor,
   943                                    const TextureSamplerArray& samplers) {
   944     if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){
   945         builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
   946                                builder->getUniformVariable(fColorStartUni).c_str(),
   947                                builder->getUniformVariable(fColorEndUni).c_str(),
   948                                gradientTValue);
   949         // Note that we could skip this step if both colors are known to be opaque. Two
   950         // considerations:
   951         // The gradient SkShader reporting opaque is more restrictive than necessary in the two pt
   952         // case. Make sure the key reflects this optimization (and note that it can use the same
   953         // shader as thekBeforeIterp case). This same optimization applies to the 3 color case below.
   954         if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
   955             builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
   956         }
   958         builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
   959                                (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
   960     } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
   961         builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
   962                                gradientTValue);
   963         builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
   964                                builder->getUniformVariable(fColorStartUni).c_str());
   965         if (kTegra3_GrGLRenderer == builder->ctxInfo().renderer()) {
   966             // The Tegra3 compiler will sometimes never return if we have
   967             // min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
   968             builder->fsCodeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
   969             builder->fsCodeAppend("\tminAbs = minAbs > 1.0 ? 1.0 : minAbs;\n");
   970             builder->fsCodeAppendf("\tcolorTemp += (1.0 - minAbs) * %s;\n",
   971                                    builder->getUniformVariable(fColorMidUni).c_str());
   972         } else {
   973             builder->fsCodeAppendf("\tcolorTemp += (1.0 - min(abs(oneMinus2t), 1.0)) * %s;\n",
   974                                    builder->getUniformVariable(fColorMidUni).c_str());
   975         }
   976         builder->fsCodeAppendf("\tcolorTemp += clamp(-oneMinus2t, 0.0, 1.0) * %s;\n",
   977                                builder->getUniformVariable(fColorEndUni).c_str());
   978         if (GrGradientEffect::kAfterInterp_PremulType == PremulTypeFromKey(key)) {
   979             builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
   980         }
   982         builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
   983                                (GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
   984     } else {
   985         builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
   986                                gradientTValue,
   987                                builder->getUniformVariable(fFSYUni).c_str());
   988         builder->fsCodeAppendf("\t%s = ", outputColor);
   989         builder->fsAppendTextureLookupAndModulate(inputColor,
   990                                                   samplers[0],
   991                                                   "coord");
   992         builder->fsCodeAppend(";\n");
   993     }
   994 }
   996 /////////////////////////////////////////////////////////////////////
   998 GrGradientEffect::GrGradientEffect(GrContext* ctx,
   999                                    const SkGradientShaderBase& shader,
  1000                                    const SkMatrix& matrix,
  1001                                    SkShader::TileMode tileMode) {
  1003     fIsOpaque = shader.isOpaque();
  1005     SkShader::GradientInfo info;
  1006     SkScalar pos[3] = {0};
  1008     info.fColorCount = 3;
  1009     info.fColors = &fColors[0];
  1010     info.fColorOffsets = &pos[0];
  1011     shader.asAGradient(&info);
  1013     // The two and three color specializations do not currently support tiling.
  1014     bool foundSpecialCase = false;
  1015     if (SkShader::kClamp_TileMode == info.fTileMode) {
  1016         if (2 == info.fColorCount) {
  1017             fRow = -1; // flag for no atlas
  1018             fColorType = kTwo_ColorType;
  1019             foundSpecialCase = true;
  1020         } else if (3 == info.fColorCount &&
  1021                    (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric
  1022             fRow = -1; // flag for no atlas
  1023             fColorType = kThree_ColorType;
  1024             foundSpecialCase = true;
  1027     if (foundSpecialCase) {
  1028         if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFlags) {
  1029             fPremulType = kBeforeInterp_PremulType;
  1030         } else {
  1031             fPremulType = kAfterInterp_PremulType;
  1033         fCoordTransform.reset(kCoordSet, matrix);
  1034     } else {
  1035         // doesn't matter how this is set, just be consistent because it is part of the effect key.
  1036         fPremulType = kBeforeInterp_PremulType;
  1037         SkBitmap bitmap;
  1038         shader.getGradientTableBitmap(&bitmap);
  1039         fColorType = kTexture_ColorType;
  1041         GrTextureStripAtlas::Desc desc;
  1042         desc.fWidth  = bitmap.width();
  1043         desc.fHeight = 32;
  1044         desc.fRowHeight = bitmap.height();
  1045         desc.fContext = ctx;
  1046         desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.colorType(), bitmap.alphaType());
  1047         fAtlas = GrTextureStripAtlas::GetAtlas(desc);
  1048         SkASSERT(NULL != fAtlas);
  1050         // We always filter the gradient table. Each table is one row of a texture, always y-clamp.
  1051         GrTextureParams params;
  1052         params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
  1053         params.setTileModeX(tileMode);
  1055         fRow = fAtlas->lockRow(bitmap);
  1056         if (-1 != fRow) {
  1057             fYCoord = fAtlas->getYOffset(fRow) + SK_ScalarHalf *
  1058             fAtlas->getVerticalScaleFactor();
  1059             fCoordTransform.reset(kCoordSet, matrix, fAtlas->getTexture());
  1060             fTextureAccess.reset(fAtlas->getTexture(), params);
  1061         } else {
  1062             GrTexture* texture = GrLockAndRefCachedBitmapTexture(ctx, bitmap, &params);
  1063             fCoordTransform.reset(kCoordSet, matrix, texture);
  1064             fTextureAccess.reset(texture, params);
  1065             fYCoord = SK_ScalarHalf;
  1067             // Unlock immediately, this is not great, but we don't have a way of
  1068             // knowing when else to unlock it currently, so it may get purged from
  1069             // the cache, but it'll still be ref'd until it's no longer being used.
  1070             GrUnlockAndUnrefCachedBitmapTexture(texture);
  1072         this->addTextureAccess(&fTextureAccess);
  1074     this->addCoordTransform(&fCoordTransform);
  1077 GrGradientEffect::~GrGradientEffect() {
  1078     if (this->useAtlas()) {
  1079         fAtlas->unlockRow(fRow);
  1083 bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
  1084     const GrGradientEffect& s = CastEffect<GrGradientEffect>(effect);
  1086     if (this->fColorType == s.getColorType()){
  1088         if (kTwo_ColorType == fColorType) {
  1089             if (*this->getColors(0) != *s.getColors(0) ||
  1090                 *this->getColors(1) != *s.getColors(1)) {
  1091                 return false;
  1093         } else if (kThree_ColorType == fColorType) {
  1094             if (*this->getColors(0) != *s.getColors(0) ||
  1095                 *this->getColors(1) != *s.getColors(1) ||
  1096                 *this->getColors(2) != *s.getColors(2)) {
  1097                 return false;
  1099         } else {
  1100             if (fYCoord != s.getYCoord()) {
  1101                 return false;
  1105         return fTextureAccess.getTexture() == s.fTextureAccess.getTexture()  &&
  1106             fTextureAccess.getParams().getTileModeX() ==
  1107                 s.fTextureAccess.getParams().getTileModeX() &&
  1108             this->useAtlas() == s.useAtlas() &&
  1109             fCoordTransform.getMatrix().cheapEqualTo(s.fCoordTransform.getMatrix());
  1112     return false;
  1115 void GrGradientEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
  1116     if (fIsOpaque && (kA_GrColorComponentFlag & *validFlags) && 0xff == GrColorUnpackA(*color)) {
  1117         *validFlags = kA_GrColorComponentFlag;
  1118     } else {
  1119         *validFlags = 0;
  1123 int GrGradientEffect::RandomGradientParams(SkRandom* random,
  1124                                            SkColor colors[],
  1125                                            SkScalar** stops,
  1126                                            SkShader::TileMode* tm) {
  1127     int outColors = random->nextRangeU(1, kMaxRandomGradientColors);
  1129     // if one color, omit stops, otherwise randomly decide whether or not to
  1130     if (outColors == 1 || (outColors >= 2 && random->nextBool())) {
  1131         *stops = NULL;
  1134     SkScalar stop = 0.f;
  1135     for (int i = 0; i < outColors; ++i) {
  1136         colors[i] = random->nextU();
  1137         if (NULL != *stops) {
  1138             (*stops)[i] = stop;
  1139             stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - stop) : 1.f;
  1142     *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileModeCount));
  1144     return outColors;
  1147 #endif

mercurial