OLD | NEW |
---|---|
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 "SkGradientShaderPriv.h" | 8 #include "SkGradientShaderPriv.h" |
9 #include "SkLinearGradient.h" | 9 #include "SkLinearGradient.h" |
10 #include "SkRadialGradient.h" | 10 #include "SkRadialGradient.h" |
11 #include "SkTwoPointRadialGradient.h" | 11 #include "SkTwoPointRadialGradient.h" |
12 #include "SkTwoPointConicalGradient.h" | 12 #include "SkTwoPointConicalGradient.h" |
13 #include "SkSweepGradient.h" | 13 #include "SkSweepGradient.h" |
14 | 14 |
15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { | 15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
16 SkASSERT(desc.fCount > 1); | 16 SkASSERT(desc.fCount > 1); |
17 | 17 |
18 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return | |
19 | |
20 fMapper = desc.fMapper; | 18 fMapper = desc.fMapper; |
21 SkSafeRef(fMapper); | 19 SkSafeRef(fMapper); |
22 fGradFlags = SkToU8(desc.fFlags); | 20 fGradFlags = SkToU8(desc.fFlags); |
23 | 21 |
24 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); | 22 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); |
25 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); | 23 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); |
26 fTileMode = desc.fTileMode; | 24 fTileMode = desc.fTileMode; |
27 fTileProc = gTileProcs[desc.fTileMode]; | 25 fTileProc = gTileProcs[desc.fTileMode]; |
28 | 26 |
29 fCache16 = fCache16Storage = NULL; | |
30 fCache32 = NULL; | |
31 fCache32PixelRef = NULL; | |
32 | |
33 /* Note: we let the caller skip the first and/or last position. | 27 /* Note: we let the caller skip the first and/or last position. |
34 i.e. pos[0] = 0.3, pos[1] = 0.7 | 28 i.e. pos[0] = 0.3, pos[1] = 0.7 |
35 In these cases, we insert dummy entries to ensure that the final data | 29 In these cases, we insert dummy entries to ensure that the final data |
36 will be bracketed by [0, 1]. | 30 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 | 31 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 |
38 | 32 |
39 Thus colorCount (the caller's value, and fColorCount (our value) may | 33 Thus colorCount (the caller's value, and fColorCount (our value) may |
40 differ by up to 2. In the above example: | 34 differ by up to 2. In the above example: |
41 colorCount = 2 | 35 colorCount = 2 |
42 fColorCount = 4 | 36 fColorCount = 4 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 | 131 |
138 static SkShader::TileMode unpack_mode(uint32_t packed) { | 132 static SkShader::TileMode unpack_mode(uint32_t packed) { |
139 return (SkShader::TileMode)(packed & 0xF); | 133 return (SkShader::TileMode)(packed & 0xF); |
140 } | 134 } |
141 | 135 |
142 static uint32_t unpack_flags(uint32_t packed) { | 136 static uint32_t unpack_flags(uint32_t packed) { |
143 return packed >> 4; | 137 return packed >> 4; |
144 } | 138 } |
145 | 139 |
146 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf fer) { | 140 SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf fer) { |
147 fCacheAlpha = 256; | |
148 | |
149 fMapper = buffer.readUnitMapper(); | 141 fMapper = buffer.readUnitMapper(); |
150 | 142 |
151 fCache16 = fCache16Storage = NULL; | |
152 fCache32 = NULL; | |
153 fCache32PixelRef = NULL; | |
154 | |
155 int colorCount = fColorCount = buffer.getArrayCount(); | 143 int colorCount = fColorCount = buffer.getArrayCount(); |
156 if (colorCount > kColorStorageCount) { | 144 if (colorCount > kColorStorageCount) { |
157 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount; | 145 size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount; |
158 if (buffer.validateAvailable(allocSize)) { | 146 if (buffer.validateAvailable(allocSize)) { |
159 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize)) ; | 147 fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize)) ; |
160 } else { | 148 } else { |
161 fOrigColors = NULL; | 149 fOrigColors = NULL; |
162 colorCount = fColorCount = 0; | 150 colorCount = fColorCount = 0; |
163 } | 151 } |
164 } else { | 152 } else { |
(...skipping 14 matching lines...) Expand all Loading... | |
179 for (int i = 1; i < colorCount; i++) { | 167 for (int i = 1; i < colorCount; i++) { |
180 recs[i].fPos = buffer.readInt(); | 168 recs[i].fPos = buffer.readInt(); |
181 recs[i].fScale = buffer.readUInt(); | 169 recs[i].fScale = buffer.readUInt(); |
182 } | 170 } |
183 } | 171 } |
184 buffer.readMatrix(&fPtsToUnit); | 172 buffer.readMatrix(&fPtsToUnit); |
185 this->initCommon(); | 173 this->initCommon(); |
186 } | 174 } |
187 | 175 |
188 SkGradientShaderBase::~SkGradientShaderBase() { | 176 SkGradientShaderBase::~SkGradientShaderBase() { |
189 if (fCache16Storage) { | |
190 sk_free(fCache16Storage); | |
191 } | |
192 SkSafeUnref(fCache32PixelRef); | |
193 if (fOrigColors != fStorage) { | 177 if (fOrigColors != fStorage) { |
194 sk_free(fOrigColors); | 178 sk_free(fOrigColors); |
195 } | 179 } |
196 SkSafeUnref(fMapper); | 180 SkSafeUnref(fMapper); |
197 } | 181 } |
198 | 182 |
199 void SkGradientShaderBase::initCommon() { | 183 void SkGradientShaderBase::initCommon() { |
200 fFlags = 0; | |
201 unsigned colorAlpha = 0xFF; | 184 unsigned colorAlpha = 0xFF; |
202 for (int i = 0; i < fColorCount; i++) { | 185 for (int i = 0; i < fColorCount; i++) { |
203 colorAlpha &= SkColorGetA(fOrigColors[i]); | 186 colorAlpha &= SkColorGetA(fOrigColors[i]); |
204 } | 187 } |
205 fColorsAreOpaque = colorAlpha == 0xFF; | 188 fColorsAreOpaque = colorAlpha == 0xFF; |
206 } | 189 } |
207 | 190 |
208 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { | 191 void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { |
209 this->INHERITED::flatten(buffer); | 192 this->INHERITED::flatten(buffer); |
210 buffer.writeFlattenable(fMapper); | 193 buffer.writeFlattenable(fMapper); |
211 buffer.writeColorArray(fOrigColors, fColorCount); | 194 buffer.writeColorArray(fOrigColors, fColorCount); |
212 buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); | 195 buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); |
213 if (fColorCount > 2) { | 196 if (fColorCount > 2) { |
214 Rec* recs = fRecs; | 197 Rec* recs = fRecs; |
215 for (int i = 1; i < fColorCount; i++) { | 198 for (int i = 1; i < fColorCount; i++) { |
216 buffer.writeInt(recs[i].fPos); | 199 buffer.writeInt(recs[i].fPos); |
217 buffer.writeUInt(recs[i].fScale); | 200 buffer.writeUInt(recs[i].fScale); |
218 } | 201 } |
219 } | 202 } |
220 buffer.writeMatrix(fPtsToUnit); | 203 buffer.writeMatrix(fPtsToUnit); |
221 } | 204 } |
222 | 205 |
223 bool SkGradientShaderBase::isOpaque() const { | 206 bool SkGradientShaderBase::isOpaque() const { |
224 return fColorsAreOpaque; | 207 return fColorsAreOpaque; |
225 } | 208 } |
226 | 209 |
210 bool SkGradientShaderBase::validContext(const SkBitmap& device, const SkPaint& p aint, | |
211 const SkMatrix& matrix, SkMatrix* totalI nverse) const { | |
212 // Make sure we can use totalInverse as a cache. | |
213 SkMatrix totalInverseLocal; | |
214 if (NULL == totalInverse) { | |
215 totalInverse = &totalInverseLocal; | |
216 } | |
217 | |
218 if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { | |
219 return false; | |
220 } | |
221 | |
222 SkMatrix dstToIndex; | |
223 return dstToIndex.setConcat(fPtsToUnit, *totalInverse); | |
224 } | |
225 | |
226 size_t SkGradientShaderBase::contextSize() const { | |
scroggo
2014/04/02 20:16:53
Is it possible to create an SkGradientShaderBase?
Dominik Grewe
2014/04/03 12:12:59
No. Removed.
| |
227 return sizeof(GradientShaderBaseContext); | |
228 } | |
229 | |
230 SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext( | |
231 const SkGradientShaderBase& shader, const SkBitmap& device, | |
232 const SkPaint& paint, const SkMatrix& matrix) | |
233 : INHERITED(shader, device, paint, matrix), fCache(this->getPaintAlpha()) | |
scroggo
2014/04/02 20:16:53
nit: fCache should go on its own line.
Dominik Grewe
2014/04/03 12:12:59
Done.
| |
234 { | |
235 const SkMatrix& inverse = this->getTotalInverse(); | |
236 | |
237 SkAssertResult(fDstToIndex.setConcat(shader.fPtsToUnit, inverse)); | |
scroggo
2014/04/02 20:16:53
I don't think you can assert this result unless yo
Dominik Grewe
2014/04/03 12:12:59
The constructor of SkShader::Context asserts that
| |
238 | |
239 fDstToIndexProc = fDstToIndex.getMapXYProc(); | |
240 fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToInde x); | |
241 | |
242 // now convert our colors in to PMColors | |
243 unsigned paintAlpha = this->getPaintAlpha(); | |
244 | |
245 fFlags = this->INHERITED::getFlags(); | |
246 if (shader.fColorsAreOpaque && paintAlpha == 0xFF) { | |
247 fFlags |= kOpaqueAlpha_Flag; | |
248 } | |
249 // we can do span16 as long as our individual colors are opaque, | |
250 // regardless of the paint's alpha | |
251 if (shader.fColorsAreOpaque) { | |
252 fFlags |= kHasSpan16_Flag; | |
253 } | |
254 } | |
255 | |
256 #if 0 | |
227 bool SkGradientShaderBase::setContext(const SkBitmap& device, | 257 bool SkGradientShaderBase::setContext(const SkBitmap& device, |
228 const SkPaint& paint, | 258 const SkPaint& paint, |
229 const SkMatrix& matrix) { | 259 const SkMatrix& matrix) { |
230 if (!this->INHERITED::setContext(device, paint, matrix)) { | 260 if (!this->INHERITED::setContext(device, paint, matrix)) { |
231 return false; | 261 return false; |
232 } | 262 } |
233 | 263 |
234 const SkMatrix& inverse = this->getTotalInverse(); | 264 const SkMatrix& inverse = this->getTotalInverse(); |
235 | 265 |
236 if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) { | 266 if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) { |
(...skipping 14 matching lines...) Expand all Loading... | |
251 } | 281 } |
252 // we can do span16 as long as our individual colors are opaque, | 282 // we can do span16 as long as our individual colors are opaque, |
253 // regardless of the paint's alpha | 283 // regardless of the paint's alpha |
254 if (fColorsAreOpaque) { | 284 if (fColorsAreOpaque) { |
255 fFlags |= kHasSpan16_Flag; | 285 fFlags |= kHasSpan16_Flag; |
256 } | 286 } |
257 | 287 |
258 this->setCacheAlpha(paintAlpha); | 288 this->setCacheAlpha(paintAlpha); |
259 return true; | 289 return true; |
260 } | 290 } |
291 #endif | |
261 | 292 |
262 void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const { | 293 |
263 // if the new alpha differs from the previous time we were called, inval our cache | 294 SkGradientShaderBase::GradientShaderCache::GradientShaderCache(U8CPU alpha) { |
264 // this will trigger the cache to be rebuilt. | 295 // Invalidate the cache. |
scroggo
2014/04/02 20:16:53
I don't think this comment is appropriate, given t
Dominik Grewe
2014/04/03 12:12:59
Maybe "invalidate" is the wrong term, but I wanted
| |
265 // we don't care about the first time, since the cache ptrs will already be NULL | 296 fCache16 = NULL; |
266 if (fCacheAlpha != alpha) { | 297 fCache32 = NULL; |
267 fCache16 = NULL; // inval the cache | 298 fCache16Storage = NULL; |
268 fCache32 = NULL; // inval the cache | 299 fCache32PixelRef = NULL; |
269 fCacheAlpha = alpha; // record the new alpha | 300 fCacheAlpha = alpha; |
270 // inform our subclasses | 301 } |
271 if (fCache32PixelRef) { | 302 |
272 fCache32PixelRef->notifyPixelsChanged(); | 303 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { |
273 } | 304 sk_free(fCache16Storage); |
274 } | 305 SkSafeUnref(fCache32PixelRef); |
275 } | 306 } |
276 | 307 |
277 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) | 308 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) |
278 | 309 |
279 /** We take the original colors, not our premultiplied PMColors, since we can | 310 /** 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 | 311 build a 16bit table as long as the original colors are opaque, even if the |
281 paint specifies a non-opaque alpha. | 312 paint specifies a non-opaque alpha. |
282 */ | 313 */ |
283 void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1, | 314 void SkGradientShaderBase::GradientShaderCache::Build16bitCache( |
284 int count) { | 315 uint16_t cache[], SkColor c0, SkColor c1, int count) { |
285 SkASSERT(count > 1); | 316 SkASSERT(count > 1); |
286 SkASSERT(SkColorGetA(c0) == 0xFF); | 317 SkASSERT(SkColorGetA(c0) == 0xFF); |
287 SkASSERT(SkColorGetA(c1) == 0xFF); | 318 SkASSERT(SkColorGetA(c1) == 0xFF); |
288 | 319 |
289 SkFixed r = SkColorGetR(c0); | 320 SkFixed r = SkColorGetR(c0); |
290 SkFixed g = SkColorGetG(c0); | 321 SkFixed g = SkColorGetG(c0); |
291 SkFixed b = SkColorGetB(c0); | 322 SkFixed b = SkColorGetB(c0); |
292 | 323 |
293 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); | 324 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); |
294 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); | 325 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); |
(...skipping 27 matching lines...) Expand all Loading... | |
322 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead | 353 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead |
323 * of using | | 354 * of using | |
324 * | 355 * |
325 * We chose #1 just because it was more localized. | 356 * We chose #1 just because it was more localized. |
326 * See http://code.google.com/p/skia/issues/detail?id=1113 | 357 * See http://code.google.com/p/skia/issues/detail?id=1113 |
327 * | 358 * |
328 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. | 359 * The type SkUFixed encapsulate this need for unsigned, but logically Fixed. |
329 */ | 360 */ |
330 typedef uint32_t SkUFixed; | 361 typedef uint32_t SkUFixed; |
331 | 362 |
332 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo r c1, | 363 void SkGradientShaderBase::GradientShaderCache::Build32bitCache( |
333 int count, U8CPU paintAlpha, uint32_t grad Flags) { | 364 SkPMColor cache[], SkColor c0, SkColor c1, |
365 int count, U8CPU paintAlpha, uint32_t gradFlags) { | |
334 SkASSERT(count > 1); | 366 SkASSERT(count > 1); |
335 | 367 |
336 // need to apply paintAlpha to our two endpoints | 368 // need to apply paintAlpha to our two endpoints |
337 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); | 369 uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha); |
338 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); | 370 uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha); |
339 | 371 |
340 | 372 |
341 const bool interpInPremul = SkToBool(gradFlags & | 373 const bool interpInPremul = SkToBool(gradFlags & |
342 SkGradientShader::kInterpolateColorsInPremul_Flag); | 374 SkGradientShader::kInterpolateColorsInPremul_Flag); |
343 | 375 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 if (6 == bits) { | 498 if (6 == bits) { |
467 return (x << 10) | (x << 4) | (x >> 2); | 499 return (x << 10) | (x << 4) | (x >> 2); |
468 } | 500 } |
469 if (8 == bits) { | 501 if (8 == bits) { |
470 return (x << 8) | x; | 502 return (x << 8) | x; |
471 } | 503 } |
472 sk_throw(); | 504 sk_throw(); |
473 return 0; | 505 return 0; |
474 } | 506 } |
475 | 507 |
476 const uint16_t* SkGradientShaderBase::getCache16() const { | 508 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16( |
509 const SkGradientShaderBase& shader) { | |
477 if (fCache16 == NULL) { | 510 if (fCache16 == NULL) { |
478 // double the count for dither entries | 511 // double the count for dither entries |
479 const int entryCount = kCache16Count * 2; | 512 const int entryCount = kCache16Count * 2; |
480 const size_t allocSize = sizeof(uint16_t) * entryCount; | 513 const size_t allocSize = sizeof(uint16_t) * entryCount; |
481 | 514 |
482 if (fCache16Storage == NULL) { // set the storage and our working ptr | 515 if (fCache16Storage == NULL) { // set the storage and our working ptr |
483 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 516 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
484 } | 517 } |
485 fCache16 = fCache16Storage; | 518 fCache16 = fCache16Storage; |
486 if (fColorCount == 2) { | 519 if (shader.fColorCount == 2) { |
487 Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1], | 520 Build16bitCache(fCache16, shader.fOrigColors[0], shader.fOrigColors[ 1], |
488 kCache16Count); | 521 kCache16Count); |
489 } else { | 522 } else { |
490 Rec* rec = fRecs; | 523 Rec* rec = shader.fRecs; |
491 int prevIndex = 0; | 524 int prevIndex = 0; |
492 for (int i = 1; i < fColorCount; i++) { | 525 for (int i = 1; i < shader.fColorCount; i++) { |
493 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; | 526 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; |
494 SkASSERT(nextIndex < kCache16Count); | 527 SkASSERT(nextIndex < kCache16Count); |
495 | 528 |
496 if (nextIndex > prevIndex) | 529 if (nextIndex > prevIndex) |
497 Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOri gColors[i], nextIndex - prevIndex + 1); | 530 Build16bitCache(fCache16 + prevIndex, shader.fOrigColors[i-1 ], |
531 shader.fOrigColors[i], nextIndex - prevIndex + 1); | |
498 prevIndex = nextIndex; | 532 prevIndex = nextIndex; |
499 } | 533 } |
500 } | 534 } |
501 | 535 |
502 if (fMapper) { | 536 if (shader.fMapper) { |
503 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | 537 fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); |
504 uint16_t* linear = fCache16; // just computed linear data | 538 uint16_t* linear = fCache16; // just computed linear data |
505 uint16_t* mapped = fCache16Storage; // storage for mapped data | 539 uint16_t* mapped = fCache16Storage; // storage for mapped data |
506 SkUnitMapper* map = fMapper; | 540 SkUnitMapper* map = shader.fMapper; |
507 for (int i = 0; i < kCache16Count; i++) { | 541 for (int i = 0; i < kCache16Count; i++) { |
508 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1 6Shift; | 542 int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache1 6Shift; |
509 mapped[i] = linear[index]; | 543 mapped[i] = linear[index]; |
510 mapped[i + kCache16Count] = linear[index + kCache16Count]; | 544 mapped[i + kCache16Count] = linear[index + kCache16Count]; |
511 } | 545 } |
512 sk_free(fCache16); | 546 sk_free(fCache16); |
513 fCache16 = fCache16Storage; | 547 fCache16 = fCache16Storage; |
514 } | 548 } |
515 } | 549 } |
516 return fCache16; | 550 return fCache16; |
517 } | 551 } |
518 | 552 |
519 const SkPMColor* SkGradientShaderBase::getCache32() const { | 553 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32( |
554 const SkGradientShaderBase& shader) { | |
520 if (fCache32 == NULL) { | 555 if (fCache32 == NULL) { |
521 SkImageInfo info; | 556 SkImageInfo info; |
522 info.fWidth = kCache32Count; | 557 info.fWidth = kCache32Count; |
523 info.fHeight = 4; // for our 4 dither rows | 558 info.fHeight = 4; // for our 4 dither rows |
524 info.fAlphaType = kPremul_SkAlphaType; | 559 info.fAlphaType = kPremul_SkAlphaType; |
525 info.fColorType = kPMColor_SkColorType; | 560 info.fColorType = kPMColor_SkColorType; |
526 | 561 |
527 if (NULL == fCache32PixelRef) { | 562 if (NULL == fCache32PixelRef) { |
528 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); | 563 fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL); |
529 } | 564 } |
530 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); | 565 fCache32 = (SkPMColor*)fCache32PixelRef->getAddr(); |
531 if (fColorCount == 2) { | 566 if (shader.fColorCount == 2) { |
532 Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1], | 567 Build32bitCache(fCache32, shader.fOrigColors[0], shader.fOrigColors[ 1], |
533 kCache32Count, fCacheAlpha, fGradFlags); | 568 kCache32Count, fCacheAlpha, shader.fGradFlags); |
534 } else { | 569 } else { |
535 Rec* rec = fRecs; | 570 Rec* rec = shader.fRecs; |
536 int prevIndex = 0; | 571 int prevIndex = 0; |
537 for (int i = 1; i < fColorCount; i++) { | 572 for (int i = 1; i < shader.fColorCount; i++) { |
538 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; | 573 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift; |
539 SkASSERT(nextIndex < kCache32Count); | 574 SkASSERT(nextIndex < kCache32Count); |
540 | 575 |
541 if (nextIndex > prevIndex) | 576 if (nextIndex > prevIndex) |
542 Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1], | 577 Build32bitCache(fCache32 + prevIndex, shader.fOrigColors[i-1 ], |
543 fOrigColors[i], nextIndex - prevIndex + 1, | 578 shader.fOrigColors[i], nextIndex - prevIndex + 1, |
544 fCacheAlpha, fGradFlags); | 579 fCacheAlpha, shader.fGradFlags); |
545 prevIndex = nextIndex; | 580 prevIndex = nextIndex; |
546 } | 581 } |
547 } | 582 } |
548 | 583 |
549 if (fMapper) { | 584 if (shader.fMapper) { |
550 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL L); | 585 SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NUL L); |
551 SkPMColor* linear = fCache32; // just computed linear data | 586 SkPMColor* linear = fCache32; // just computed linear data |
552 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data | 587 SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data |
553 SkUnitMapper* map = fMapper; | 588 SkUnitMapper* map = shader.fMapper; |
554 for (int i = 0; i < kCache32Count; i++) { | 589 for (int i = 0; i < kCache32Count; i++) { |
555 int index = map->mapUnit16((i << 8) | i) >> 8; | 590 int index = map->mapUnit16((i << 8) | i) >> 8; |
556 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; | 591 mapped[i + kCache32Count*0] = linear[index + kCache32Count*0]; |
557 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; | 592 mapped[i + kCache32Count*1] = linear[index + kCache32Count*1]; |
558 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; | 593 mapped[i + kCache32Count*2] = linear[index + kCache32Count*2]; |
559 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; | 594 mapped[i + kCache32Count*3] = linear[index + kCache32Count*3]; |
560 } | 595 } |
561 fCache32PixelRef->unref(); | 596 fCache32PixelRef->unref(); |
562 fCache32PixelRef = newPR; | 597 fCache32PixelRef = newPR; |
563 fCache32 = (SkPMColor*)newPR->getAddr(); | 598 fCache32 = (SkPMColor*)newPR->getAddr(); |
564 } | 599 } |
565 } | 600 } |
566 return fCache32; | 601 return fCache32; |
567 } | 602 } |
568 | 603 |
569 /* | 604 /* |
570 * Because our caller might rebuild the same (logically the same) gradient | 605 * 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, | 606 * 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). | 607 * 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 | 608 * 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 | 609 * colors and positions. Note: we don't try to flatten the fMapper, so if one |
575 * is present, we skip the cache for now. | 610 * is present, we skip the cache for now. |
576 */ | 611 */ |
577 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { | 612 void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const { |
578 // our caller assumes no external alpha, so we ensure that our cache is | 613 // our caller assumes no external alpha, so we ensure that our cache is |
579 // built with 0xFF | 614 // built with 0xFF |
580 this->setCacheAlpha(0xFF); | 615 GradientShaderCache cache(0xFF); |
581 | 616 |
582 // don't have a way to put the mapper into our cache-key yet | 617 // don't have a way to put the mapper into our cache-key yet |
583 if (fMapper) { | 618 if (fMapper) { |
584 // force our cahce32pixelref to be built | 619 // force our cahce32pixelref to be built |
585 (void)this->getCache32(); | 620 (void)cache.getCache32(*this); |
586 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 621 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
587 bitmap->setPixelRef(fCache32PixelRef); | 622 bitmap->setPixelRef(cache.getCache32PixelRef()); |
588 return; | 623 return; |
589 } | 624 } |
590 | 625 |
591 // build our key: [numColors + colors[] + {positions[]} + flags ] | 626 // build our key: [numColors + colors[] + {positions[]} + flags ] |
592 int count = 1 + fColorCount + 1; | 627 int count = 1 + fColorCount + 1; |
593 if (fColorCount > 2) { | 628 if (fColorCount > 2) { |
594 count += fColorCount - 1; // fRecs[].fPos | 629 count += fColorCount - 1; // fRecs[].fPos |
595 } | 630 } |
596 | 631 |
597 SkAutoSTMalloc<16, int32_t> storage(count); | 632 SkAutoSTMalloc<16, int32_t> storage(count); |
(...skipping 18 matching lines...) Expand all Loading... | |
616 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; | 651 static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; |
617 SkAutoMutexAcquire ama(gMutex); | 652 SkAutoMutexAcquire ama(gMutex); |
618 | 653 |
619 if (NULL == gCache) { | 654 if (NULL == gCache) { |
620 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); | 655 gCache = SkNEW_ARGS(SkBitmapCache, (MAX_NUM_CACHED_GRADIENT_BITMAPS)); |
621 } | 656 } |
622 size_t size = count * sizeof(int32_t); | 657 size_t size = count * sizeof(int32_t); |
623 | 658 |
624 if (!gCache->find(storage.get(), size, bitmap)) { | 659 if (!gCache->find(storage.get(), size, bitmap)) { |
625 // force our cahce32pixelref to be built | 660 // force our cahce32pixelref to be built |
626 (void)this->getCache32(); | 661 (void)cache.getCache32(*this); |
627 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); | 662 bitmap->setConfig(SkImageInfo::MakeN32Premul(kCache32Count, 1)); |
628 bitmap->setPixelRef(fCache32PixelRef); | 663 bitmap->setPixelRef(cache.getCache32PixelRef()); |
629 | 664 |
630 gCache->add(storage.get(), size, *bitmap); | 665 gCache->add(storage.get(), size, *bitmap); |
631 } | 666 } |
632 } | 667 } |
633 | 668 |
634 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { | 669 void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const { |
635 if (info) { | 670 if (info) { |
636 if (info->fColorCount >= fColorCount) { | 671 if (info->fColorCount >= fColorCount) { |
637 if (info->fColors) { | 672 if (info->fColors) { |
638 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) ); | 673 memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor) ); |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1138 (*stops)[i] = stop; | 1173 (*stops)[i] = stop; |
1139 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; | 1174 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st op) : 1.f; |
1140 } | 1175 } |
1141 } | 1176 } |
1142 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); | 1177 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM odeCount)); |
1143 | 1178 |
1144 return outColors; | 1179 return outColors; |
1145 } | 1180 } |
1146 | 1181 |
1147 #endif | 1182 #endif |
OLD | NEW |