gfx/skia/trunk/src/effects/gradients/SkSweepGradient.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 "SkSweepGradient.h"
    11 SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy,
    12                                  const Descriptor& desc)
    13     : SkGradientShaderBase(desc)
    14     , fCenter(SkPoint::Make(cx, cy))
    15 {
    16     fPtsToUnit.setTranslate(-cx, -cy);
    18     // overwrite the tilemode to a canonical value (since sweep ignores it)
    19     fTileMode = SkShader::kClamp_TileMode;
    20 }
    22 SkShader::BitmapType SkSweepGradient::asABitmap(SkBitmap* bitmap,
    23     SkMatrix* matrix, SkShader::TileMode* xy) const {
    24     if (bitmap) {
    25         this->getGradientTableBitmap(bitmap);
    26     }
    27     if (matrix) {
    28         *matrix = fPtsToUnit;
    29     }
    30     if (xy) {
    31         xy[0] = fTileMode;
    32         xy[1] = kClamp_TileMode;
    33     }
    34     return kSweep_BitmapType;
    35 }
    37 SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const {
    38     if (info) {
    39         commonAsAGradient(info);
    40         info->fPoint[0] = fCenter;
    41     }
    42     return kSweep_GradientType;
    43 }
    45 SkSweepGradient::SkSweepGradient(SkReadBuffer& buffer)
    46     : INHERITED(buffer),
    47       fCenter(buffer.readPoint()) {
    48 }
    50 void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
    51     this->INHERITED::flatten(buffer);
    52     buffer.writePoint(fCenter);
    53 }
    55 //  returns angle in a circle [0..2PI) -> [0..255]
    56 static unsigned SkATan2_255(float y, float x) {
    57     //    static const float g255Over2PI = 255 / (2 * SK_ScalarPI);
    58     static const float g255Over2PI = 40.584510488433314f;
    60     float result = sk_float_atan2(y, x);
    61     if (result < 0) {
    62         result += 2 * SK_ScalarPI;
    63     }
    64     SkASSERT(result >= 0);
    65     // since our value is always >= 0, we can cast to int, which is faster than
    66     // calling floorf()
    67     int ir = (int)(result * g255Over2PI);
    68     SkASSERT(ir >= 0 && ir <= 255);
    69     return ir;
    70 }
    72 void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
    73                                int count) {
    74     SkMatrix::MapXYProc proc = fDstToIndexProc;
    75     const SkMatrix&     matrix = fDstToIndex;
    76     const SkPMColor* SK_RESTRICT cache = this->getCache32();
    77     int                 toggle = init_dither_toggle(x, y);
    78     SkPoint             srcPt;
    80     if (fDstToIndexClass != kPerspective_MatrixClass) {
    81         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
    82                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
    83         SkScalar dx, fx = srcPt.fX;
    84         SkScalar dy, fy = srcPt.fY;
    86         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
    87             SkFixed storage[2];
    88             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
    89                                       &storage[0], &storage[1]);
    90             dx = SkFixedToScalar(storage[0]);
    91             dy = SkFixedToScalar(storage[1]);
    92         } else {
    93             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
    94             dx = matrix.getScaleX();
    95             dy = matrix.getSkewY();
    96         }
    98         for (; count > 0; --count) {
    99             *dstC++ = cache[toggle + SkATan2_255(fy, fx)];
   100             fx += dx;
   101             fy += dy;
   102             toggle = next_dither_toggle(toggle);
   103         }
   104     } else {  // perspective case
   105         for (int stop = x + count; x < stop; x++) {
   106             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   107                          SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   108             *dstC++ = cache[toggle + SkATan2_255(srcPt.fY, srcPt.fX)];
   109             toggle = next_dither_toggle(toggle);
   110         }
   111     }
   112 }
   114 void SkSweepGradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC,
   115                                  int count) {
   116     SkMatrix::MapXYProc proc = fDstToIndexProc;
   117     const SkMatrix&     matrix = fDstToIndex;
   118     const uint16_t* SK_RESTRICT cache = this->getCache16();
   119     int                 toggle = init_dither_toggle16(x, y);
   120     SkPoint             srcPt;
   122     if (fDstToIndexClass != kPerspective_MatrixClass) {
   123         proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   124                      SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   125         SkScalar dx, fx = srcPt.fX;
   126         SkScalar dy, fy = srcPt.fY;
   128         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
   129             SkFixed storage[2];
   130             (void)matrix.fixedStepInX(SkIntToScalar(y) + SK_ScalarHalf,
   131                                       &storage[0], &storage[1]);
   132             dx = SkFixedToScalar(storage[0]);
   133             dy = SkFixedToScalar(storage[1]);
   134         } else {
   135             SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
   136             dx = matrix.getScaleX();
   137             dy = matrix.getSkewY();
   138         }
   140         for (; count > 0; --count) {
   141             int index = SkATan2_255(fy, fx) >> (8 - kCache16Bits);
   142             *dstC++ = cache[toggle + index];
   143             toggle = next_dither_toggle16(toggle);
   144             fx += dx;
   145             fy += dy;
   146         }
   147     } else {  // perspective case
   148         for (int stop = x + count; x < stop; x++) {
   149             proc(matrix, SkIntToScalar(x) + SK_ScalarHalf,
   150                          SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
   152             int index = SkATan2_255(srcPt.fY, srcPt.fX);
   153             index >>= (8 - kCache16Bits);
   154             *dstC++ = cache[toggle + index];
   155             toggle = next_dither_toggle16(toggle);
   156         }
   157     }
   158 }
   160 /////////////////////////////////////////////////////////////////////
   162 #if SK_SUPPORT_GPU
   164 #include "GrTBackendEffectFactory.h"
   166 class GrGLSweepGradient : public GrGLGradientEffect {
   167 public:
   169     GrGLSweepGradient(const GrBackendEffectFactory& factory,
   170                       const GrDrawEffect&) : INHERITED (factory) { }
   171     virtual ~GrGLSweepGradient() { }
   173     virtual void emitCode(GrGLShaderBuilder*,
   174                           const GrDrawEffect&,
   175                           EffectKey,
   176                           const char* outputColor,
   177                           const char* inputColor,
   178                           const TransformedCoordsArray&,
   179                           const TextureSamplerArray&) SK_OVERRIDE;
   181     static EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
   182         return GenBaseGradientKey(drawEffect);
   183     }
   185 private:
   187     typedef GrGLGradientEffect INHERITED;
   189 };
   191 /////////////////////////////////////////////////////////////////////
   193 class GrSweepGradient : public GrGradientEffect {
   194 public:
   195     static GrEffectRef* Create(GrContext* ctx,
   196                                const SkSweepGradient& shader,
   197                                const SkMatrix& matrix) {
   198         AutoEffectUnref effect(SkNEW_ARGS(GrSweepGradient, (ctx, shader, matrix)));
   199         return CreateEffectRef(effect);
   200     }
   201     virtual ~GrSweepGradient() { }
   203     static const char* Name() { return "Sweep Gradient"; }
   204     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
   205         return GrTBackendEffectFactory<GrSweepGradient>::getInstance();
   206     }
   208     typedef GrGLSweepGradient GLEffect;
   210 private:
   211     GrSweepGradient(GrContext* ctx,
   212                     const SkSweepGradient& shader,
   213                     const SkMatrix& matrix)
   214     : INHERITED(ctx, shader, matrix, SkShader::kClamp_TileMode) { }
   215     GR_DECLARE_EFFECT_TEST;
   217     typedef GrGradientEffect INHERITED;
   218 };
   220 /////////////////////////////////////////////////////////////////////
   222 GR_DEFINE_EFFECT_TEST(GrSweepGradient);
   224 GrEffectRef* GrSweepGradient::TestCreate(SkRandom* random,
   225                                          GrContext* context,
   226                                          const GrDrawTargetCaps&,
   227                                          GrTexture**) {
   228     SkPoint center = {random->nextUScalar1(), random->nextUScalar1()};
   230     SkColor colors[kMaxRandomGradientColors];
   231     SkScalar stopsArray[kMaxRandomGradientColors];
   232     SkScalar* stops = stopsArray;
   233     SkShader::TileMode tmIgnored;
   234     int colorCount = RandomGradientParams(random, colors, &stops, &tmIgnored);
   235     SkAutoTUnref<SkShader> shader(SkGradientShader::CreateSweep(center.fX, center.fY,
   236                                                                 colors, stops, colorCount));
   237     SkPaint paint;
   238     return shader->asNewEffect(context, paint);
   239 }
   241 /////////////////////////////////////////////////////////////////////
   243 void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder,
   244                                  const GrDrawEffect&,
   245                                  EffectKey key,
   246                                  const char* outputColor,
   247                                  const char* inputColor,
   248                                  const TransformedCoordsArray& coords,
   249                                  const TextureSamplerArray& samplers) {
   250     this->emitUniforms(builder, key);
   251     SkString coords2D = builder->ensureFSCoords2D(coords, 0);
   252     const GrGLContextInfo ctxInfo = builder->ctxInfo();
   253     SkString t;
   254     // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
   255     // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
   256     // thus must us -1.0 * %s.x to work correctly
   257     if (kIntel_GrGLVendor != ctxInfo.vendor()){
   258         t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
   259                  coords2D.c_str(), coords2D.c_str());
   260     } else {
   261         t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
   262                  coords2D.c_str(), coords2D.c_str());
   263     }
   264     this->emitColor(builder, t.c_str(), key,
   265                           outputColor, inputColor, samplers);
   266 }
   268 /////////////////////////////////////////////////////////////////////
   270 GrEffectRef* SkSweepGradient::asNewEffect(GrContext* context, const SkPaint&) const {
   271     SkMatrix matrix;
   272     if (!this->getLocalMatrix().invert(&matrix)) {
   273         return NULL;
   274     }
   275     matrix.postConcat(fPtsToUnit);
   276     return GrSweepGradient::Create(context, *this, matrix);
   277 }
   279 #else
   281 GrEffectRef* SkSweepGradient::asNewEffect(GrContext*, const SkPaint&) const {
   282     SkDEBUGFAIL("Should not call in GPU-less build");
   283     return NULL;
   284 }
   286 #endif
   288 #ifndef SK_IGNORE_TO_STRING
   289 void SkSweepGradient::toString(SkString* str) const {
   290     str->append("SkSweepGradient: (");
   292     str->append("center: (");
   293     str->appendScalar(fCenter.fX);
   294     str->append(", ");
   295     str->appendScalar(fCenter.fY);
   296     str->append(") ");
   298     this->INHERITED::toString(str);
   300     str->append(")");
   301 }
   302 #endif

mercurial