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 "Sk4fLinearGradient.h" | 8 #include "Sk4fLinearGradient.h" |
9 #include "SkGradientShaderPriv.h" | 9 #include "SkGradientShaderPriv.h" |
10 #include "SkLinearGradient.h" | 10 #include "SkLinearGradient.h" |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 fFlags |= kOpaqueAlpha_Flag; | 299 fFlags |= kOpaqueAlpha_Flag; |
300 } | 300 } |
301 } | 301 } |
302 | 302 |
303 SkGradientShaderBase::GradientShaderCache::GradientShaderCache( | 303 SkGradientShaderBase::GradientShaderCache::GradientShaderCache( |
304 U8CPU alpha, bool dither, const SkGradientShaderBase& shader) | 304 U8CPU alpha, bool dither, const SkGradientShaderBase& shader) |
305 : fCacheAlpha(alpha) | 305 : fCacheAlpha(alpha) |
306 , fCacheDither(dither) | 306 , fCacheDither(dither) |
307 , fShader(shader) | 307 , fShader(shader) |
308 { | 308 { |
309 // Only initialize the cache in getCache16/32. | 309 // Only initialize the cache in getCache32. |
310 fCache16 = nullptr; | |
311 fCache32 = nullptr; | 310 fCache32 = nullptr; |
312 fCache16Storage = nullptr; | |
313 fCache32PixelRef = nullptr; | 311 fCache32PixelRef = nullptr; |
314 } | 312 } |
315 | 313 |
316 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { | 314 SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() { |
317 sk_free(fCache16Storage); | |
318 SkSafeUnref(fCache32PixelRef); | 315 SkSafeUnref(fCache32PixelRef); |
319 } | 316 } |
320 | 317 |
321 #define Fixed_To_Dot8(x) (((x) + 0x80) >> 8) | |
322 | |
323 /** We take the original colors, not our premultiplied PMColors, since we can | |
324 build a 16bit table as long as the original colors are opaque, even if the | |
325 paint specifies a non-opaque alpha. | |
326 */ | |
327 void SkGradientShaderBase::GradientShaderCache::Build16bitCache( | |
328 uint16_t cache[], SkColor c0, SkColor c1, int count, bool dither) { | |
329 SkASSERT(count > 1); | |
330 SkASSERT(SkColorGetA(c0) == 0xFF); | |
331 SkASSERT(SkColorGetA(c1) == 0xFF); | |
332 | |
333 SkFixed r = SkColorGetR(c0); | |
334 SkFixed g = SkColorGetG(c0); | |
335 SkFixed b = SkColorGetB(c0); | |
336 | |
337 SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); | |
338 SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); | |
339 SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1); | |
340 | |
341 r = SkIntToFixed(r) + 0x8000; | |
342 g = SkIntToFixed(g) + 0x8000; | |
343 b = SkIntToFixed(b) + 0x8000; | |
344 | |
345 if (dither) { | |
346 do { | |
347 unsigned rr = r >> 16; | |
348 unsigned gg = g >> 16; | |
349 unsigned bb = b >> 16; | |
350 cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb
)); | |
351 cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb); | |
352 cache += 1; | |
353 r += dr; | |
354 g += dg; | |
355 b += db; | |
356 } while (--count != 0); | |
357 } else { | |
358 do { | |
359 unsigned rr = r >> 16; | |
360 unsigned gg = g >> 16; | |
361 unsigned bb = b >> 16; | |
362 cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb
)); | |
363 cache[kCache16Count] = cache[0]; | |
364 cache += 1; | |
365 r += dr; | |
366 g += dg; | |
367 b += db; | |
368 } while (--count != 0); | |
369 } | |
370 } | |
371 | |
372 /* | 318 /* |
373 * r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in | 319 * r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in |
374 * release builds, we saw a compiler error where the 0xFF parameter in | 320 * release builds, we saw a compiler error where the 0xFF parameter in |
375 * SkPackARGB32() was being totally ignored whenever it was called with | 321 * SkPackARGB32() was being totally ignored whenever it was called with |
376 * a non-zero add (e.g. 0x8000). | 322 * a non-zero add (e.g. 0x8000). |
377 * | 323 * |
378 * We found two work-arounds: | 324 * We found two work-arounds: |
379 * 1. change r,g,b to unsigned (or just one of them) | 325 * 1. change r,g,b to unsigned (or just one of them) |
380 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead | 326 * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead |
381 * of using | | 327 * of using | |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 b += db; | 464 b += db; |
519 } while (--count != 0); | 465 } while (--count != 0); |
520 } | 466 } |
521 } | 467 } |
522 | 468 |
523 static inline int SkFixedToFFFF(SkFixed x) { | 469 static inline int SkFixedToFFFF(SkFixed x) { |
524 SkASSERT((unsigned)x <= SK_Fixed1); | 470 SkASSERT((unsigned)x <= SK_Fixed1); |
525 return x - (x >> 16); | 471 return x - (x >> 16); |
526 } | 472 } |
527 | 473 |
528 const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() { | |
529 fCache16InitOnce(SkGradientShaderBase::GradientShaderCache::initCache16, thi
s); | |
530 SkASSERT(fCache16); | |
531 return fCache16; | |
532 } | |
533 | |
534 void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache*
cache) { | |
535 // double the count for dither entries | |
536 const int entryCount = kCache16Count * 2; | |
537 const size_t allocSize = sizeof(uint16_t) * entryCount; | |
538 | |
539 SkASSERT(nullptr == cache->fCache16Storage); | |
540 cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize); | |
541 cache->fCache16 = cache->fCache16Storage; | |
542 if (cache->fShader.fColorCount == 2) { | |
543 Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0], | |
544 cache->fShader.fOrigColors[1], kCache16Count, cache->fCa
cheDither); | |
545 } else { | |
546 Rec* rec = cache->fShader.fRecs; | |
547 int prevIndex = 0; | |
548 for (int i = 1; i < cache->fShader.fColorCount; i++) { | |
549 int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift; | |
550 SkASSERT(nextIndex < kCache16Count); | |
551 | |
552 if (nextIndex > prevIndex) | |
553 Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOri
gColors[i-1], | |
554 cache->fShader.fOrigColors[i], nextIndex - prevI
ndex + 1, | |
555 cache->fCacheDither); | |
556 prevIndex = nextIndex; | |
557 } | |
558 } | |
559 } | |
560 | |
561 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { | 474 const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() { |
562 fCache32InitOnce(SkGradientShaderBase::GradientShaderCache::initCache32, thi
s); | 475 fCache32InitOnce(SkGradientShaderBase::GradientShaderCache::initCache32, thi
s); |
563 SkASSERT(fCache32); | 476 SkASSERT(fCache32); |
564 return fCache32; | 477 return fCache32; |
565 } | 478 } |
566 | 479 |
567 void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
cache) { | 480 void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
cache) { |
568 const int kNumberOfDitherRows = 4; | 481 const int kNumberOfDitherRows = 4; |
569 const SkImageInfo info = SkImageInfo::MakeN32Premul(kCache32Count, kNumberOf
DitherRows); | 482 const SkImageInfo info = SkImageInfo::MakeN32Premul(kCache32Count, kNumberOf
DitherRows); |
570 | 483 |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1484 (*stops)[i] = stop; | 1397 (*stops)[i] = stop; |
1485 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; | 1398 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; |
1486 } | 1399 } |
1487 } | 1400 } |
1488 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); | 1401 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); |
1489 | 1402 |
1490 return outColors; | 1403 return outColors; |
1491 } | 1404 } |
1492 | 1405 |
1493 #endif | 1406 #endif |
OLD | NEW |