gfx/skia/trunk/src/effects/gradients/SkRadialGradient.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

     2 /*
     3  * Copyright 2012 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #include "SkRadialGradient.h"
    10 #include "SkRadialGradient_Table.h"
    12 #define kSQRT_TABLE_BITS    11
    13 #define kSQRT_TABLE_SIZE    (1 << kSQRT_TABLE_BITS)
    15 #if 0
    17 #include <stdio.h>
    19 void SkRadialGradient_BuildTable() {
    20     // build it 0..127 x 0..127, so we use 2^15 - 1 in the numerator for our "fixed" table
    22     FILE* file = ::fopen("SkRadialGradient_Table.h", "w");
    23     SkASSERT(file);
    24     ::fprintf(file, "static const uint8_t gSqrt8Table[] = {\n");
    26     for (int i = 0; i < kSQRT_TABLE_SIZE; i++) {
    27         if ((i & 15) == 0) {
    28             ::fprintf(file, "\t");
    29         }
    31         uint8_t value = SkToU8(SkFixedSqrt(i * SK_Fixed1 / kSQRT_TABLE_SIZE) >> 8);
    33         ::fprintf(file, "0x%02X", value);
    34         if (i < kSQRT_TABLE_SIZE-1) {
    35             ::fprintf(file, ", ");
    36         }
    37         if ((i & 15) == 15) {
    38             ::fprintf(file, "\n");
    39         }
    40     }
    41     ::fprintf(file, "};\n");
    42     ::fclose(file);
    43 }
    45 #endif
    47 namespace {
    49 // GCC doesn't like using static functions as template arguments.  So force these to be non-static.
    50 inline SkFixed mirror_tileproc_nonstatic(SkFixed x) {
    51     return mirror_tileproc(x);
    52 }
    54 inline SkFixed repeat_tileproc_nonstatic(SkFixed x) {
    55     return repeat_tileproc(x);
    56 }
    58 void rad_to_unit_matrix(const SkPoint& center, SkScalar radius,
    59                                SkMatrix* matrix) {
    60     SkScalar    inv = SkScalarInvert(radius);
    62     matrix->setTranslate(-center.fX, -center.fY);
    63     matrix->postScale(inv, inv);
    64 }
    66 typedef void (* RadialShade16Proc)(SkScalar sfx, SkScalar sdx,
    67         SkScalar sfy, SkScalar sdy,
    68         uint16_t* dstC, const uint16_t* cache,
    69         int toggle, int count);
    71 void shadeSpan16_radial_clamp(SkScalar sfx, SkScalar sdx,
    72         SkScalar sfy, SkScalar sdy,
    73         uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
    74         int toggle, int count) {
    75     const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
    77     /* knock these down so we can pin against +- 0x7FFF, which is an
    78        immediate load, rather than 0xFFFF which is slower. This is a
    79        compromise, since it reduces our precision, but that appears
    80        to be visually OK. If we decide this is OK for all of our cases,
    81        we could (it seems) put this scale-down into fDstToIndex,
    82        to avoid having to do these extra shifts each time.
    83     */
    84     SkFixed fx = SkScalarToFixed(sfx) >> 1;
    85     SkFixed dx = SkScalarToFixed(sdx) >> 1;
    86     SkFixed fy = SkScalarToFixed(sfy) >> 1;
    87     SkFixed dy = SkScalarToFixed(sdy) >> 1;
    88     // might perform this check for the other modes,
    89     // but the win will be a smaller % of the total
    90     if (dy == 0) {
    91         fy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
    92         fy *= fy;
    93         do {
    94             unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
    95             unsigned fi = (xx * xx + fy) >> (14 + 16 - kSQRT_TABLE_BITS);
    96             fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
    97             fx += dx;
    98             *dstC++ = cache[toggle +
    99                             (sqrt_table[fi] >> SkGradientShaderBase::kSqrt16Shift)];
   100             toggle = next_dither_toggle16(toggle);
   101         } while (--count != 0);
   102     } else {
   103         do {
   104             unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   105             unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   106             fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
   107             fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   108             fx += dx;
   109             fy += dy;
   110             *dstC++ = cache[toggle +
   111                             (sqrt_table[fi] >> SkGradientShaderBase::kSqrt16Shift)];
   112             toggle = next_dither_toggle16(toggle);
   113         } while (--count != 0);
   114     }
   115 }
   117 template <SkFixed (*TileProc)(SkFixed)>
   118 void shadeSpan16_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   119                         uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
   120                         int toggle, int count) {
   121     do {
   122         const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy));
   123         const unsigned fi = TileProc(dist);
   124         SkASSERT(fi <= 0xFFFF);
   125         *dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache16Shift)];
   126         toggle = next_dither_toggle16(toggle);
   127         fx += dx;
   128         fy += dy;
   129     } while (--count != 0);
   130 }
   132 void shadeSpan16_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   133                                uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
   134                                int toggle, int count) {
   135     shadeSpan16_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count);
   136 }
   138 void shadeSpan16_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   139                                uint16_t* SK_RESTRICT dstC, const uint16_t* SK_RESTRICT cache,
   140                                int toggle, int count) {
   141     shadeSpan16_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, toggle, count);
   142 }
   144 }  // namespace
   146 /////////////////////////////////////////////////////////////////////
   148 SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius,
   149                                    const Descriptor& desc)
   150     : SkGradientShaderBase(desc),
   151       fCenter(center),
   152       fRadius(radius)
   153 {
   154     // make sure our table is insync with our current #define for kSQRT_TABLE_SIZE
   155     SkASSERT(sizeof(gSqrt8Table) == kSQRT_TABLE_SIZE);
   157     rad_to_unit_matrix(center, radius, &fPtsToUnit);
   158 }
   160 void SkRadialGradient::shadeSpan16(int x, int y, uint16_t* dstCParam,
   161                          int count) {
   162     SkASSERT(count > 0);
   164     uint16_t* SK_RESTRICT dstC = dstCParam;
   166     SkPoint             srcPt;
   167     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   168     TileProc            proc = fTileProc;
   169     const uint16_t* SK_RESTRICT cache = this->getCache16();
   170     int                 toggle = init_dither_toggle16(x, y);
   172     if (fDstToIndexClass != kPerspective_MatrixClass) {
   173         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   174                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   176         SkScalar sdx = fDstToIndex.getScaleX();
   177         SkScalar sdy = fDstToIndex.getSkewY();
   179         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   180             SkFixed storage[2];
   181             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y),
   182                                            &storage[0], &storage[1]);
   183             sdx = SkFixedToScalar(storage[0]);
   184             sdy = SkFixedToScalar(storage[1]);
   185         } else {
   186             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   187         }
   189         RadialShade16Proc shadeProc = shadeSpan16_radial_repeat;
   190         if (SkShader::kClamp_TileMode == fTileMode) {
   191             shadeProc = shadeSpan16_radial_clamp;
   192         } else if (SkShader::kMirror_TileMode == fTileMode) {
   193             shadeProc = shadeSpan16_radial_mirror;
   194         } else {
   195             SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
   196         }
   197         (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC,
   198                      cache, toggle, count);
   199     } else {    // perspective case
   200         SkScalar dstX = SkIntToScalar(x);
   201         SkScalar dstY = SkIntToScalar(y);
   202         do {
   203             dstProc(fDstToIndex, dstX, dstY, &srcPt);
   204             unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   205             SkASSERT(fi <= 0xFFFF);
   207             int index = fi >> (16 - kCache16Bits);
   208             *dstC++ = cache[toggle + index];
   209             toggle = next_dither_toggle16(toggle);
   211             dstX += SK_Scalar1;
   212         } while (--count != 0);
   213     }
   214 }
   216 SkShader::BitmapType SkRadialGradient::asABitmap(SkBitmap* bitmap,
   217     SkMatrix* matrix, SkShader::TileMode* xy) const {
   218     if (bitmap) {
   219         this->getGradientTableBitmap(bitmap);
   220     }
   221     if (matrix) {
   222         matrix->setScale(SkIntToScalar(kCache32Count),
   223                          SkIntToScalar(kCache32Count));
   224         matrix->preConcat(fPtsToUnit);
   225     }
   226     if (xy) {
   227         xy[0] = fTileMode;
   228         xy[1] = kClamp_TileMode;
   229     }
   230     return kRadial_BitmapType;
   231 }
   233 SkShader::GradientType SkRadialGradient::asAGradient(GradientInfo* info) const {
   234     if (info) {
   235         commonAsAGradient(info);
   236         info->fPoint[0] = fCenter;
   237         info->fRadius[0] = fRadius;
   238     }
   239     return kRadial_GradientType;
   240 }
   242 SkRadialGradient::SkRadialGradient(SkReadBuffer& buffer)
   243     : INHERITED(buffer),
   244       fCenter(buffer.readPoint()),
   245       fRadius(buffer.readScalar()) {
   246 }
   248 void SkRadialGradient::flatten(SkWriteBuffer& buffer) const {
   249     this->INHERITED::flatten(buffer);
   250     buffer.writePoint(fCenter);
   251     buffer.writeScalar(fRadius);
   252 }
   254 namespace {
   256 inline bool radial_completely_pinned(int fx, int dx, int fy, int dy) {
   257     // fast, overly-conservative test: checks unit square instead
   258     // of unit circle
   259     bool xClamped = (fx >= SK_FixedHalf && dx >= 0) ||
   260                     (fx <= -SK_FixedHalf && dx <= 0);
   261     bool yClamped = (fy >= SK_FixedHalf && dy >= 0) ||
   262                     (fy <= -SK_FixedHalf && dy <= 0);
   264     return xClamped || yClamped;
   265 }
   267 // Return true if (fx * fy) is always inside the unit circle
   268 // SkPin32 is expensive, but so are all the SkFixedMul in this test,
   269 // so it shouldn't be run if count is small.
   270 inline bool no_need_for_radial_pin(int fx, int dx,
   271                                           int fy, int dy, int count) {
   272     SkASSERT(count > 0);
   273     if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) {
   274         return false;
   275     }
   276     if (fx*fx + fy*fy > 0x7FFF*0x7FFF) {
   277         return false;
   278     }
   279     fx += (count - 1) * dx;
   280     fy += (count - 1) * dy;
   281     if (SkAbs32(fx) > 0x7FFF || SkAbs32(fy) > 0x7FFF) {
   282         return false;
   283     }
   284     return fx*fx + fy*fy <= 0x7FFF*0x7FFF;
   285 }
   287 #define UNPINNED_RADIAL_STEP \
   288     fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \
   289     *dstC++ = cache[toggle + \
   290                     (sqrt_table[fi] >> SkGradientShaderBase::kSqrt32Shift)]; \
   291     toggle = next_dither_toggle(toggle); \
   292     fx += dx; \
   293     fy += dy;
   295 typedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx,
   296         SkScalar sfy, SkScalar sdy,
   297         SkPMColor* dstC, const SkPMColor* cache,
   298         int count, int toggle);
   300 // On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT
   301 void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
   302         SkScalar sfy, SkScalar sdy,
   303         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
   304         int count, int toggle) {
   305     // Floating point seems to be slower than fixed point,
   306     // even when we have float hardware.
   307     const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
   308     SkFixed fx = SkScalarToFixed(sfx) >> 1;
   309     SkFixed dx = SkScalarToFixed(sdx) >> 1;
   310     SkFixed fy = SkScalarToFixed(sfy) >> 1;
   311     SkFixed dy = SkScalarToFixed(sdy) >> 1;
   312     if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) {
   313         unsigned fi = SkGradientShaderBase::kCache32Count - 1;
   314         sk_memset32_dither(dstC,
   315             cache[toggle + fi],
   316             cache[next_dither_toggle(toggle) + fi],
   317             count);
   318     } else if ((count > 4) &&
   319                no_need_for_radial_pin(fx, dx, fy, dy, count)) {
   320         unsigned fi;
   321         // 4x unroll appears to be no faster than 2x unroll on Linux
   322         while (count > 1) {
   323             UNPINNED_RADIAL_STEP;
   324             UNPINNED_RADIAL_STEP;
   325             count -= 2;
   326         }
   327         if (count) {
   328             UNPINNED_RADIAL_STEP;
   329         }
   330     } else  {
   331         // Specializing for dy == 0 gains us 25% on Skia benchmarks
   332         if (dy == 0) {
   333             unsigned yy = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   334             yy *= yy;
   335             do {
   336                 unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   337                 unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS);
   338                 fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   339                 *dstC++ = cache[toggle + (sqrt_table[fi] >>
   340                     SkGradientShaderBase::kSqrt32Shift)];
   341                 toggle = next_dither_toggle(toggle);
   342                 fx += dx;
   343             } while (--count != 0);
   344         } else {
   345             do {
   346                 unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
   347                 unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
   348                 fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
   349                 fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
   350                 *dstC++ = cache[toggle + (sqrt_table[fi] >>
   351                     SkGradientShaderBase::kSqrt32Shift)];
   352                 toggle = next_dither_toggle(toggle);
   353                 fx += dx;
   354                 fy += dy;
   355             } while (--count != 0);
   356         }
   357     }
   358 }
   360 // Unrolling this loop doesn't seem to help (when float); we're stalling to
   361 // get the results of the sqrt (?), and don't have enough extra registers to
   362 // have many in flight.
   363 template <SkFixed (*TileProc)(SkFixed)>
   364 void shadeSpan_radial(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   365                       SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
   366                       int count, int toggle) {
   367     do {
   368         const SkFixed dist = SkFloatToFixed(sk_float_sqrt(fx*fx + fy*fy));
   369         const unsigned fi = TileProc(dist);
   370         SkASSERT(fi <= 0xFFFF);
   371         *dstC++ = cache[toggle + (fi >> SkGradientShaderBase::kCache32Shift)];
   372         toggle = next_dither_toggle(toggle);
   373         fx += dx;
   374         fy += dy;
   375     } while (--count != 0);
   376 }
   378 void shadeSpan_radial_mirror(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   379                              SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
   380                              int count, int toggle) {
   381     shadeSpan_radial<mirror_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle);
   382 }
   384 void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
   385                              SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
   386                              int count, int toggle) {
   387     shadeSpan_radial<repeat_tileproc_nonstatic>(fx, dx, fy, dy, dstC, cache, count, toggle);
   388 }
   390 }  // namespace
   392 void SkRadialGradient::shadeSpan(int x, int y,
   393                                 SkPMColor* SK_RESTRICT dstC, int count) {
   394     SkASSERT(count > 0);
   396     SkPoint             srcPt;
   397     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
   398     TileProc            proc = fTileProc;
   399     const SkPMColor* SK_RESTRICT cache = this->getCache32();
   400     int toggle = init_dither_toggle(x, y);
   402     if (fDstToIndexClass != kPerspective_MatrixClass) {
   403         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
   404                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   405         SkScalar sdx = fDstToIndex.getScaleX();
   406         SkScalar sdy = fDstToIndex.getSkewY();
   408         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   409             SkFixed storage[2];
   410             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y),
   411                                            &storage[0], &storage[1]);
   412             sdx = SkFixedToScalar(storage[0]);
   413             sdy = SkFixedToScalar(storage[1]);
   414         } else {
   415             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   416         }
   418         RadialShadeProc shadeProc = shadeSpan_radial_repeat;
   419         if (SkShader::kClamp_TileMode == fTileMode) {
   420             shadeProc = shadeSpan_radial_clamp;
   421         } else if (SkShader::kMirror_TileMode == fTileMode) {
   422             shadeProc = shadeSpan_radial_mirror;
   423         } else {
   424             SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
   425         }
   426         (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle);
   427     } else {    // perspective case
   428         SkScalar dstX = SkIntToScalar(x);
   429         SkScalar dstY = SkIntToScalar(y);
   430         do {
   431             dstProc(fDstToIndex, dstX, dstY, &srcPt);
   432             unsigned fi = proc(SkScalarToFixed(srcPt.length()));
   433             SkASSERT(fi <= 0xFFFF);
   434             *dstC++ = cache[fi >> SkGradientShaderBase::kCache32Shift];
   435             dstX += SK_Scalar1;
   436         } while (--count != 0);
   437     }
   438 }
   440 /////////////////////////////////////////////////////////////////////
   442 #if SK_SUPPORT_GPU
   444 #include "GrTBackendEffectFactory.h"
   446 class GrGLRadialGradient : public GrGLGradientEffect {
   447 public:
   449     GrGLRadialGradient(const GrBackendEffectFactory& factory,
   450                        const GrDrawEffect&) : INHERITED (factory) { }
   451     virtual ~GrGLRadialGradient() { }
   453     virtual void emitCode(GrGLShaderBuilder*,
   454                           const GrDrawEffect&,
   455                           EffectKey,
   456                           const char* outputColor,
   457                           const char* inputColor,
   458                           const TransformedCoordsArray&,
   459                           const TextureSamplerArray&) SK_OVERRIDE;
   461     static EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
   462         return GenBaseGradientKey(drawEffect);
   463     }
   465 private:
   467     typedef GrGLGradientEffect INHERITED;
   469 };
   471 /////////////////////////////////////////////////////////////////////
   473 class GrRadialGradient : public GrGradientEffect {
   474 public:
   475     static GrEffectRef* Create(GrContext* ctx,
   476                                const SkRadialGradient& shader,
   477                                const SkMatrix& matrix,
   478                                SkShader::TileMode tm) {
   479         AutoEffectUnref effect(SkNEW_ARGS(GrRadialGradient, (ctx, shader, matrix, tm)));
   480         return CreateEffectRef(effect);
   481     }
   483     virtual ~GrRadialGradient() { }
   485     static const char* Name() { return "Radial Gradient"; }
   486     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
   487         return GrTBackendEffectFactory<GrRadialGradient>::getInstance();
   488     }
   490     typedef GrGLRadialGradient GLEffect;
   492 private:
   493     GrRadialGradient(GrContext* ctx,
   494                      const SkRadialGradient& shader,
   495                      const SkMatrix& matrix,
   496                      SkShader::TileMode tm)
   497         : INHERITED(ctx, shader, matrix, tm) {
   498     }
   500     GR_DECLARE_EFFECT_TEST;
   502     typedef GrGradientEffect INHERITED;
   503 };
   505 /////////////////////////////////////////////////////////////////////
   507 GR_DEFINE_EFFECT_TEST(GrRadialGradient);
   509 GrEffectRef* GrRadialGradient::TestCreate(SkRandom* random,
   510                                           GrContext* context,
   511                                           const GrDrawTargetCaps&,
   512                                           GrTexture**) {
   513     SkPoint center = {random->nextUScalar1(), random->nextUScalar1()};
   514     SkScalar radius = random->nextUScalar1();
   516     SkColor colors[kMaxRandomGradientColors];
   517     SkScalar stopsArray[kMaxRandomGradientColors];
   518     SkScalar* stops = stopsArray;
   519     SkShader::TileMode tm;
   520     int colorCount = RandomGradientParams(random, colors, &stops, &tm);
   521     SkAutoTUnref<SkShader> shader(SkGradientShader::CreateRadial(center, radius,
   522                                                                  colors, stops, colorCount,
   523                                                                  tm));
   524     SkPaint paint;
   525     return shader->asNewEffect(context, paint);
   526 }
   528 /////////////////////////////////////////////////////////////////////
   530 void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder,
   531                                   const GrDrawEffect&,
   532                                   EffectKey key,
   533                                   const char* outputColor,
   534                                   const char* inputColor,
   535                                   const TransformedCoordsArray& coords,
   536                                   const TextureSamplerArray& samplers) {
   537     this->emitUniforms(builder, key);
   538     SkString t("length(");
   539     t.append(builder->ensureFSCoords2D(coords, 0));
   540     t.append(")");
   541     this->emitColor(builder, t.c_str(), key, outputColor, inputColor, samplers);
   542 }
   544 /////////////////////////////////////////////////////////////////////
   546 GrEffectRef* SkRadialGradient::asNewEffect(GrContext* context, const SkPaint&) const {
   547     SkASSERT(NULL != context);
   549     SkMatrix matrix;
   550     if (!this->getLocalMatrix().invert(&matrix)) {
   551         return NULL;
   552     }
   553     matrix.postConcat(fPtsToUnit);
   554     return GrRadialGradient::Create(context, *this, matrix, fTileMode);
   555 }
   557 #else
   559 GrEffectRef* SkRadialGradient::asNewEffect(GrContext*, const SkPaint&) const {
   560     SkDEBUGFAIL("Should not call in GPU-less build");
   561     return NULL;
   562 }
   564 #endif
   566 #ifndef SK_IGNORE_TO_STRING
   567 void SkRadialGradient::toString(SkString* str) const {
   568     str->append("SkRadialGradient: (");
   570     str->append("center: (");
   571     str->appendScalar(fCenter.fX);
   572     str->append(", ");
   573     str->appendScalar(fCenter.fY);
   574     str->append(") radius: ");
   575     str->appendScalar(fRadius);
   576     str->append(" ");
   578     this->INHERITED::toString(str);
   580     str->append(")");
   581 }
   582 #endif

mercurial