Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: src/effects/gradients/SkGradientShader.cpp

Issue 2337313002: (Some) gradients are gamma and gamut correct on GPU (Closed)
Patch Set: Rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "Sk4fLinearGradient.h" 8 #include "Sk4fLinearGradient.h"
9 #include "SkGradientShaderPriv.h" 9 #include "SkGradientShaderPriv.h"
10 #include "SkLinearGradient.h" 10 #include "SkLinearGradient.h"
11 #include "SkRadialGradient.h" 11 #include "SkRadialGradient.h"
12 #include "SkTwoPointConicalGradient.h" 12 #include "SkTwoPointConicalGradient.h"
13 #include "SkSweepGradient.h" 13 #include "SkSweepGradient.h"
14 14
15 void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const { 15 void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const {
16 buffer.writeColorArray(fColors, fCount); 16 buffer.writeColorArray(fColors, fCount);
17 // TODO: Flatten fColors4f and fColorSpace
17 if (fPos) { 18 if (fPos) {
18 buffer.writeBool(true); 19 buffer.writeBool(true);
19 buffer.writeScalarArray(fPos, fCount); 20 buffer.writeScalarArray(fPos, fCount);
20 } else { 21 } else {
21 buffer.writeBool(false); 22 buffer.writeBool(false);
22 } 23 }
23 buffer.write32(fTileMode); 24 buffer.write32(fTileMode);
24 buffer.write32(fGradFlags); 25 buffer.write32(fGradFlags);
25 if (fLocalMatrix) { 26 if (fLocalMatrix) {
26 buffer.writeBool(true); 27 buffer.writeBool(true);
27 buffer.writeMatrix(*fLocalMatrix); 28 buffer.writeMatrix(*fLocalMatrix);
28 } else { 29 } else {
29 buffer.writeBool(false); 30 buffer.writeBool(false);
30 } 31 }
31 } 32 }
32 33
33 bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) { 34 bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) {
35 // TODO: Unflatten fColors4f and fColorSpace
34 fCount = buffer.getArrayCount(); 36 fCount = buffer.getArrayCount();
35 if (fCount > kStorageCount) { 37 if (fCount > kStorageCount) {
36 size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount; 38 size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount;
37 fDynamicStorage.reset(allocSize); 39 fDynamicStorage.reset(allocSize);
38 fColors = (SkColor*)fDynamicStorage.get(); 40 fColors = (SkColor*)fDynamicStorage.get();
39 fPos = (SkScalar*)(fColors + fCount); 41 fPos = (SkScalar*)(fColors + fCount);
40 } else { 42 } else {
41 fColors = fColorStorage; 43 fColors = fColorStorage;
42 fPos = fPosStorage; 44 fPos = fPosStorage;
43 } 45 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 // check if we need to add in dummy start and/or end position/colors 98 // check if we need to add in dummy start and/or end position/colors
97 bool dummyFirst = false; 99 bool dummyFirst = false;
98 bool dummyLast = false; 100 bool dummyLast = false;
99 if (desc.fPos) { 101 if (desc.fPos) {
100 dummyFirst = desc.fPos[0] != 0; 102 dummyFirst = desc.fPos[0] != 0;
101 dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1; 103 dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1;
102 fColorCount += dummyFirst + dummyLast; 104 fColorCount += dummyFirst + dummyLast;
103 } 105 }
104 106
105 if (fColorCount > kColorStorageCount) { 107 if (fColorCount > kColorStorageCount) {
106 size_t size = sizeof(SkColor) + sizeof(Rec); 108 size_t size = sizeof(SkColor) + sizeof(SkColor4f) + sizeof(Rec);
107 if (desc.fPos) { 109 if (desc.fPos) {
108 size += sizeof(SkScalar); 110 size += sizeof(SkScalar);
109 } 111 }
110 fOrigColors = reinterpret_cast<SkColor*>( 112 fOrigColors = reinterpret_cast<SkColor*>(
111 sk_malloc_throw(size * fColorCount)); 113 sk_malloc_throw(size * fColorCount));
112 } 114 }
113 else { 115 else {
114 fOrigColors = fStorage; 116 fOrigColors = fStorage;
115 } 117 }
116 118
117 // Now copy over the colors, adding the dummies as needed 119 fOrigColors4f = (SkColor4f*)(fOrigColors + fColorCount);
118 { 120
121 // We should have been supplied with either fColors *or* (fColors4f and fCol orSpace)
122 if (desc.fColors) {
123 // TODO: Should we support alternate gamma-encoded colorspaces with SkCo lor inputs?
124 SkASSERT(!desc.fColors4f && !desc.fColorSpace);
125
126 // Now copy over the colors, adding the dummies as needed
119 SkColor* origColors = fOrigColors; 127 SkColor* origColors = fOrigColors;
120 if (dummyFirst) { 128 if (dummyFirst) {
121 *origColors++ = desc.fColors[0]; 129 *origColors++ = desc.fColors[0];
122 } 130 }
123 memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor)); 131 memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor));
124 if (dummyLast) { 132 if (dummyLast) {
125 origColors += desc.fCount; 133 origColors += desc.fCount;
126 *origColors = desc.fColors[desc.fCount - 1]; 134 *origColors = desc.fColors[desc.fCount - 1];
127 } 135 }
136
137 // Convert our SkColor colors to SkColor4f as well
138 for (int i = 0; i < fColorCount; ++i) {
139 fOrigColors4f[i] = SkColor4f::FromColor(fOrigColors[i]);
140 }
141
142 // Color space refers to fColors4f, so it's always linear gamma
143 fColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLin earGamma();
144 } else {
145 SkASSERT(desc.fColors4f && desc.fColorSpace && desc.fColorSpace->gammaIs Linear());
146
147 // Now copy over the colors, adding the dummies as needed
148 SkColor4f* origColors = fOrigColors4f;
149 if (dummyFirst) {
150 *origColors++ = desc.fColors4f[0];
151 }
152 memcpy(origColors, desc.fColors4f, desc.fCount * sizeof(SkColor4f));
153 if (dummyLast) {
154 origColors += desc.fCount;
155 *origColors = desc.fColors4f[desc.fCount - 1];
156 }
157
158 // Convert our SkColor4f colors to SkColor as well. Note that this is in correct if the
159 // source colors are not in sRGB gamut. We would need to do a gamut tran sformation, but
160 // SkColorSpaceXform can't do that (yet). GrColorSpaceXform can, but we may not have GPU
161 // support compiled in here.
162 for (int i = 0; i < fColorCount; ++i) {
163 fOrigColors[i] = fOrigColors4f[i].toSkColor();
164 }
165 fColorSpace = desc.fColorSpace;
128 } 166 }
129 167
130 if (desc.fPos && fColorCount) { 168 if (desc.fPos && fColorCount) {
131 fOrigPos = (SkScalar*)(fOrigColors + fColorCount); 169 fOrigPos = (SkScalar*)(fOrigColors4f + fColorCount);
132 fRecs = (Rec*)(fOrigPos + fColorCount); 170 fRecs = (Rec*)(fOrigPos + fColorCount);
133 } else { 171 } else {
134 fOrigPos = nullptr; 172 fOrigPos = nullptr;
135 fRecs = (Rec*)(fOrigColors + fColorCount); 173 fRecs = (Rec*)(fOrigColors4f + fColorCount);
136 } 174 }
137 175
138 if (fColorCount > 2) { 176 if (fColorCount > 2) {
139 Rec* recs = fRecs; 177 Rec* recs = fRecs;
140 recs->fPos = 0; 178 recs->fPos = 0;
141 // recs->fScale = 0; // unused; 179 // recs->fScale = 0; // unused;
142 recs += 1; 180 recs += 1;
143 if (desc.fPos) { 181 if (desc.fPos) {
144 SkScalar* origPosPtr = fOrigPos; 182 SkScalar* origPosPtr = fOrigPos;
145 *origPosPtr++ = 0; 183 *origPosPtr++ = 0;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 unsigned colorAlpha = 0xFF; 249 unsigned colorAlpha = 0xFF;
212 for (int i = 0; i < fColorCount; i++) { 250 for (int i = 0; i < fColorCount; i++) {
213 colorAlpha &= SkColorGetA(fOrigColors[i]); 251 colorAlpha &= SkColorGetA(fOrigColors[i]);
214 } 252 }
215 fColorsAreOpaque = colorAlpha == 0xFF; 253 fColorsAreOpaque = colorAlpha == 0xFF;
216 } 254 }
217 255
218 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { 256 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
219 Descriptor desc; 257 Descriptor desc;
220 desc.fColors = fOrigColors; 258 desc.fColors = fOrigColors;
259 desc.fColors4f = fOrigColors4f;
260 desc.fColorSpace = fColorSpace;
221 desc.fPos = fOrigPos; 261 desc.fPos = fOrigPos;
222 desc.fCount = fColorCount; 262 desc.fCount = fColorCount;
223 desc.fTileMode = fTileMode; 263 desc.fTileMode = fTileMode;
224 desc.fGradFlags = fGradFlags; 264 desc.fGradFlags = fGradFlags;
225 265
226 const SkMatrix& m = this->getLocalMatrix(); 266 const SkMatrix& m = this->getLocalMatrix();
227 desc.fLocalMatrix = m.isIdentity() ? nullptr : &m; 267 desc.fLocalMatrix = m.isIdentity() ? nullptr : &m;
228 desc.flatten(buffer); 268 desc.flatten(buffer);
229 } 269 }
230 270
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 static bool valid_grad(const SkColor colors[], const SkScalar pos[], int count, unsigned tileMode) { 781 static bool valid_grad(const SkColor colors[], const SkScalar pos[], int count, unsigned tileMode) {
742 return nullptr != colors && count >= 1 && tileMode < (unsigned)SkShader::kTi leModeCount; 782 return nullptr != colors && count >= 1 && tileMode < (unsigned)SkShader::kTi leModeCount;
743 } 783 }
744 784
745 static void desc_init(SkGradientShaderBase::Descriptor* desc, 785 static void desc_init(SkGradientShaderBase::Descriptor* desc,
746 const SkColor colors[], const SkScalar pos[], int colorCou nt, 786 const SkColor colors[], const SkScalar pos[], int colorCou nt,
747 SkShader::TileMode mode, uint32_t flags, const SkMatrix* l ocalMatrix) { 787 SkShader::TileMode mode, uint32_t flags, const SkMatrix* l ocalMatrix) {
748 SkASSERT(colorCount > 1); 788 SkASSERT(colorCount > 1);
749 789
750 desc->fColors = colors; 790 desc->fColors = colors;
791 desc->fColors4f = nullptr;
792 desc->fColorSpace = nullptr; // SkColor is always sRGB
751 desc->fPos = pos; 793 desc->fPos = pos;
752 desc->fCount = colorCount; 794 desc->fCount = colorCount;
753 desc->fTileMode = mode; 795 desc->fTileMode = mode;
754 desc->fGradFlags = flags; 796 desc->fGradFlags = flags;
755 desc->fLocalMatrix = localMatrix; 797 desc->fLocalMatrix = localMatrix;
756 } 798 }
757 799
758 // assumes colors is SkColor* and pos is SkScalar* 800 // assumes colors is SkColor* and pos is SkScalar*
759 #define EXPAND_1_COLOR(count) \ 801 #define EXPAND_1_COLOR(count) \
760 SkColor tmp[2]; \ 802 SkColor tmp[2]; \
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 kDefault_GrSLPrecision, 1067 kDefault_GrSLPrecision,
1026 "Colors", 1068 "Colors",
1027 colorCount); 1069 colorCount);
1028 } else { 1070 } else {
1029 fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 1071 fFSYUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1030 kFloat_GrSLType, kDefault_GrSLPreci sion, 1072 kFloat_GrSLType, kDefault_GrSLPreci sion,
1031 "GradientYCoordFS"); 1073 "GradientYCoordFS");
1032 } 1074 }
1033 } 1075 }
1034 1076
1077 static inline void set_after_interp_color_uni_array(
1078 const GrGLSLProgramDataManager & pdman,
1079 const GrGLSLProgramDataManager ::UniformHandle uni,
1080 const SkTDArray<SkColor4f>& co lors,
1081 const GrColorSpaceXform* color SpaceXform) {
1082 int count = colors.count();
1083 if (colorSpaceXform) {
1084 constexpr int kSmallCount = 10;
1085 SkAutoSTArray<4 * kSmallCount, float> vals(4 * count);
1086
1087 for (int i = 0; i < count; i++) {
1088 colorSpaceXform->srcToDst().mapScalars(colors[i].vec(), &vals[4 * i] );
1089 }
1090
1091 pdman.set4fv(uni, count, vals.get());
1092 } else {
1093 pdman.set4fv(uni, count, (float*)&colors[0]);
1094 }
1095 }
1096
1097 static inline void set_before_interp_color_uni_array(
1098 const GrGLSLProgramDataManager & pdman,
1099 const GrGLSLProgramDataManager ::UniformHandle uni,
1100 const SkTDArray<SkColor4f>& co lors,
1101 const GrColorSpaceXform* color SpaceXform) {
1102 int count = colors.count();
1103 constexpr int kSmallCount = 10;
1104 SkAutoSTArray<4 * kSmallCount, float> vals(4 * count);
1105
1106 for (int i = 0; i < count; i++) {
1107 float a = colors[i].fA;
1108 vals[4 * i + 0] = colors[i].fR * a;
1109 vals[4 * i + 1] = colors[i].fG * a;
1110 vals[4 * i + 2] = colors[i].fB * a;
1111 vals[4 * i + 3] = a;
1112 }
1113
1114 if (colorSpaceXform) {
1115 for (int i = 0; i < count; i++) {
1116 colorSpaceXform->srcToDst().mapScalars(&vals[4 * i]);
1117 }
1118 }
1119
1120 pdman.set4fv(uni, count, vals.get());
1121 }
1122
1035 static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManag er& pdman, 1123 static inline void set_after_interp_color_uni_array(const GrGLSLProgramDataManag er& pdman,
1036 const GrGLSLProgramDataManager::UniformHa ndle uni, 1124 const GrGLSLProgramDataManager::UniformHa ndle uni,
1037 const SkTDArray<SkColor>& colors) { 1125 const SkTDArray<SkColor>& colors) {
1038 int count = colors.count(); 1126 int count = colors.count();
1039 constexpr int kSmallCount = 10; 1127 constexpr int kSmallCount = 10;
1040 1128
1041 SkAutoSTArray<4*kSmallCount, float> vals(4*count); 1129 SkAutoSTArray<4*kSmallCount, float> vals(4*count);
1042 1130
1043 for (int i = 0; i < colors.count(); i++) { 1131 for (int i = 0; i < colors.count(); i++) {
1044 // RGBA 1132 // RGBA
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 const GrGradientEffect& e = processor.cast<GrGradientEffect>(); 1166 const GrGradientEffect& e = processor.cast<GrGradientEffect>();
1079 1167
1080 switch (e.getColorType()) { 1168 switch (e.getColorType()) {
1081 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1169 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1082 case GrGradientEffect::kHardStopCentered_ColorType: 1170 case GrGradientEffect::kHardStopCentered_ColorType:
1083 case GrGradientEffect::kHardStopLeftEdged_ColorType: 1171 case GrGradientEffect::kHardStopLeftEdged_ColorType:
1084 case GrGradientEffect::kHardStopRightEdged_ColorType: 1172 case GrGradientEffect::kHardStopRightEdged_ColorType:
1085 #endif 1173 #endif
1086 case GrGradientEffect::kTwo_ColorType: 1174 case GrGradientEffect::kTwo_ColorType:
1087 case GrGradientEffect::kThree_ColorType: { 1175 case GrGradientEffect::kThree_ColorType: {
1088 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) { 1176 if (e.fColors4f.count() > 0) {
1089 set_before_interp_color_uni_array(pdman, fColorsUni, e.fColors); 1177 // Gamma-correct / color-space aware
1178 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulTyp e()) {
1179 set_before_interp_color_uni_array(pdman, fColorsUni, e.fColo rs4f,
1180 e.fColorSpaceXform.get());
1181 } else {
1182 set_after_interp_color_uni_array(pdman, fColorsUni, e.fColor s4f,
1183 e.fColorSpaceXform.get());
1184 }
1090 } else { 1185 } else {
1091 set_after_interp_color_uni_array(pdman, fColorsUni, e.fColors); 1186 // Legacy mode. Would be nice if we had converted the 8-bit colo rs to float earlier
1187 if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulTyp e()) {
1188 set_before_interp_color_uni_array(pdman, fColorsUni, e.fColo rs);
1189 } else {
1190 set_after_interp_color_uni_array(pdman, fColorsUni, e.fColor s);
1191 }
1092 } 1192 }
1093 1193
1094 break; 1194 break;
1095 } 1195 }
1096 1196
1097 case GrGradientEffect::kTexture_ColorType: { 1197 case GrGradientEffect::kTexture_ColorType: {
1098 SkScalar yCoord = e.getYCoord(); 1198 SkScalar yCoord = e.getYCoord();
1099 if (yCoord != fCachedYCoord) { 1199 if (yCoord != fCachedYCoord) {
1100 pdman.set1f(fFSYUni, yCoord); 1200 pdman.set1f(fFSYUni, yCoord);
1101 fCachedYCoord = yCoord; 1201 fCachedYCoord = yCoord;
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 ///////////////////////////////////////////////////////////////////// 1433 /////////////////////////////////////////////////////////////////////
1334 1434
1335 GrGradientEffect::GrGradientEffect(const CreateArgs& args) { 1435 GrGradientEffect::GrGradientEffect(const CreateArgs& args) {
1336 const SkGradientShaderBase& shader(*args.fShader); 1436 const SkGradientShaderBase& shader(*args.fShader);
1337 1437
1338 fIsOpaque = shader.isOpaque(); 1438 fIsOpaque = shader.isOpaque();
1339 1439
1340 fColorType = this->determineColorType(shader); 1440 fColorType = this->determineColorType(shader);
1341 1441
1342 if (kTexture_ColorType != fColorType) { 1442 if (kTexture_ColorType != fColorType) {
1343 if (shader.fOrigColors) { 1443 SkASSERT(shader.fOrigColors && shader.fOrigColors4f);
1444 if (args.fGammaCorrect) {
1445 fColors4f = SkTDArray<SkColor4f>(shader.fOrigColors4f, shader.fColor Count);
1446 fColorSpaceXform = std::move(args.fColorSpaceXform);
1447 } else {
1344 fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount) ; 1448 fColors = SkTDArray<SkColor>(shader.fOrigColors, shader.fColorCount) ;
1345 } 1449 }
1346 1450
1347 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1451 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
1348 if (shader.fOrigPos) { 1452 if (shader.fOrigPos) {
1349 fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount ); 1453 fPositions = SkTDArray<SkScalar>(shader.fOrigPos, shader.fColorCount );
1350 } 1454 }
1351 #endif 1455 #endif
1352 } 1456 }
1353 1457
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const { 1537 bool GrGradientEffect::onIsEqual(const GrFragmentProcessor& processor) const {
1434 const GrGradientEffect& ge = processor.cast<GrGradientEffect>(); 1538 const GrGradientEffect& ge = processor.cast<GrGradientEffect>();
1435 1539
1436 if (this->fColorType == ge.getColorType()) { 1540 if (this->fColorType == ge.getColorType()) {
1437 if (kTexture_ColorType == fColorType) { 1541 if (kTexture_ColorType == fColorType) {
1438 if (fYCoord != ge.getYCoord()) { 1542 if (fYCoord != ge.getYCoord()) {
1439 return false; 1543 return false;
1440 } 1544 }
1441 } else { 1545 } else {
1442 if (this->getPremulType() != ge.getPremulType() || 1546 if (this->getPremulType() != ge.getPremulType() ||
1443 this->fColors.count() != ge.fColors.count()) { 1547 this->fColors.count() != ge.fColors.count() ||
1548 this->fColors4f.count() != ge.fColors4f.count()) {
1444 return false; 1549 return false;
1445 } 1550 }
1446 1551
1447 for (int i = 0; i < this->fColors.count(); i++) { 1552 for (int i = 0; i < this->fColors.count(); i++) {
1448 if (*this->getColors(i) != *ge.getColors(i)) { 1553 if (*this->getColors(i) != *ge.getColors(i)) {
1449 return false; 1554 return false;
1450 } 1555 }
1451 } 1556 }
1557 for (int i = 0; i < this->fColors4f.count(); i++) {
1558 if (*this->getColors4f(i) != *ge.getColors4f(i)) {
1559 return false;
1560 }
1561 }
1452 } 1562 }
1453 1563
1564
1454 SkASSERT(this->useAtlas() == ge.useAtlas()); 1565 SkASSERT(this->useAtlas() == ge.useAtlas());
1455 return true; 1566 return GrColorSpaceXform::Equals(this->fColorSpaceXform.get(), ge.fColor SpaceXform.get());
1456 } 1567 }
1457 1568
1458 return false; 1569 return false;
1459 } 1570 }
1460 1571
1461 void GrGradientEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 1572 void GrGradientEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
1462 if (fIsOpaque) { 1573 if (fIsOpaque) {
1463 inout->mulByUnknownOpaqueFourComponents(); 1574 inout->mulByUnknownOpaqueFourComponents();
1464 } else { 1575 } else {
1465 inout->mulByUnknownFourComponents(); 1576 inout->mulByUnknownFourComponents();
(...skipping 18 matching lines...) Expand all
1484 (*stops)[i] = stop; 1595 (*stops)[i] = stop;
1485 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; 1596 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f;
1486 } 1597 }
1487 } 1598 }
1488 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); 1599 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount));
1489 1600
1490 return outColors; 1601 return outColors;
1491 } 1602 }
1492 1603
1493 #endif 1604 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698