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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial