| 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 SkColor colors[], const SkScala
r pos[], | 15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
| 16 int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) { | 16 SkASSERT(desc.fCount > 1); |
| 17 SkASSERT(colorCount > 1); | |
| 18 | 17 |
| 19 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return | 18 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return |
| 20 | 19 |
| 21 fMapper = mapper; | 20 fMapper = desc.fMapper; |
| 22 SkSafeRef(mapper); | 21 SkSafeRef(fMapper); |
| 23 | 22 |
| 24 SkASSERT((unsigned)mode < SkShader::kTileModeCount); | 23 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); |
| 25 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); | 24 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); |
| 26 fTileMode = mode; | 25 fTileMode = desc.fTileMode; |
| 27 fTileProc = gTileProcs[mode]; | 26 fTileProc = gTileProcs[desc.fTileMode]; |
| 28 | 27 |
| 29 fCache16 = fCache16Storage = NULL; | 28 fCache16 = fCache16Storage = NULL; |
| 30 fCache32 = NULL; | 29 fCache32 = NULL; |
| 31 fCache32PixelRef = NULL; | 30 fCache32PixelRef = NULL; |
| 32 | 31 |
| 33 /* Note: we let the caller skip the first and/or last position. | 32 /* Note: we let the caller skip the first and/or last position. |
| 34 i.e. pos[0] = 0.3, pos[1] = 0.7 | 33 i.e. pos[0] = 0.3, pos[1] = 0.7 |
| 35 In these cases, we insert dummy entries to ensure that the final data | 34 In these cases, we insert dummy entries to ensure that the final data |
| 36 will be bracketed by [0, 1]. | 35 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 | 36 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 |
| 38 | 37 |
| 39 Thus colorCount (the caller's value, and fColorCount (our value) may | 38 Thus colorCount (the caller's value, and fColorCount (our value) may |
| 40 differ by up to 2. In the above example: | 39 differ by up to 2. In the above example: |
| 41 colorCount = 2 | 40 colorCount = 2 |
| 42 fColorCount = 4 | 41 fColorCount = 4 |
| 43 */ | 42 */ |
| 44 fColorCount = colorCount; | 43 fColorCount = desc.fCount; |
| 45 // check if we need to add in dummy start and/or end position/colors | 44 // check if we need to add in dummy start and/or end position/colors |
| 46 bool dummyFirst = false; | 45 bool dummyFirst = false; |
| 47 bool dummyLast = false; | 46 bool dummyLast = false; |
| 48 if (pos) { | 47 if (desc.fPos) { |
| 49 dummyFirst = pos[0] != 0; | 48 dummyFirst = desc.fPos[0] != 0; |
| 50 dummyLast = pos[colorCount - 1] != SK_Scalar1; | 49 dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1; |
| 51 fColorCount += dummyFirst + dummyLast; | 50 fColorCount += dummyFirst + dummyLast; |
| 52 } | 51 } |
| 53 | 52 |
| 54 if (fColorCount > kColorStorageCount) { | 53 if (fColorCount > kColorStorageCount) { |
| 55 size_t size = sizeof(SkColor) + sizeof(Rec); | 54 size_t size = sizeof(SkColor) + sizeof(Rec); |
| 56 fOrigColors = reinterpret_cast<SkColor*>( | 55 fOrigColors = reinterpret_cast<SkColor*>( |
| 57 sk_malloc_throw(size * fColorCount)); | 56 sk_malloc_throw(size * fColorCount)); |
| 58 } | 57 } |
| 59 else { | 58 else { |
| 60 fOrigColors = fStorage; | 59 fOrigColors = fStorage; |
| 61 } | 60 } |
| 62 | 61 |
| 63 // Now copy over the colors, adding the dummies as needed | 62 // Now copy over the colors, adding the dummies as needed |
| 64 { | 63 { |
| 65 SkColor* origColors = fOrigColors; | 64 SkColor* origColors = fOrigColors; |
| 66 if (dummyFirst) { | 65 if (dummyFirst) { |
| 67 *origColors++ = colors[0]; | 66 *origColors++ = desc.fColors[0]; |
| 68 } | 67 } |
| 69 memcpy(origColors, colors, colorCount * sizeof(SkColor)); | 68 memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor)); |
| 70 if (dummyLast) { | 69 if (dummyLast) { |
| 71 origColors += colorCount; | 70 origColors += desc.fCount; |
| 72 *origColors = colors[colorCount - 1]; | 71 *origColors = desc.fColors[desc.fCount - 1]; |
| 73 } | 72 } |
| 74 } | 73 } |
| 75 | 74 |
| 76 fRecs = (Rec*)(fOrigColors + fColorCount); | 75 fRecs = (Rec*)(fOrigColors + fColorCount); |
| 77 if (fColorCount > 2) { | 76 if (fColorCount > 2) { |
| 78 Rec* recs = fRecs; | 77 Rec* recs = fRecs; |
| 79 recs->fPos = 0; | 78 recs->fPos = 0; |
| 80 // recs->fScale = 0; // unused; | 79 // recs->fScale = 0; // unused; |
| 81 recs += 1; | 80 recs += 1; |
| 82 if (pos) { | 81 if (desc.fPos) { |
| 83 /* We need to convert the user's array of relative positions into | 82 /* We need to convert the user's array of relative positions into |
| 84 fixed-point positions and scale factors. We need these results | 83 fixed-point positions and scale factors. We need these results |
| 85 to be strictly monotonic (no two values equal or out of order). | 84 to be strictly monotonic (no two values equal or out of order). |
| 86 Hence this complex loop that just jams a zero for the scale | 85 Hence this complex loop that just jams a zero for the scale |
| 87 value if it sees a segment out of order, and it assures that | 86 value if it sees a segment out of order, and it assures that |
| 88 we start at 0 and end at 1.0 | 87 we start at 0 and end at 1.0 |
| 89 */ | 88 */ |
| 90 SkFixed prev = 0; | 89 SkFixed prev = 0; |
| 91 int startIndex = dummyFirst ? 0 : 1; | 90 int startIndex = dummyFirst ? 0 : 1; |
| 92 int count = colorCount + dummyLast; | 91 int count = desc.fCount + dummyLast; |
| 93 for (int i = startIndex; i < count; i++) { | 92 for (int i = startIndex; i < count; i++) { |
| 94 // force the last value to be 1.0 | 93 // force the last value to be 1.0 |
| 95 SkFixed curr; | 94 SkFixed curr; |
| 96 if (i == colorCount) { // we're really at the dummyLast | 95 if (i == desc.fCount) { // we're really at the dummyLast |
| 97 curr = SK_Fixed1; | 96 curr = SK_Fixed1; |
| 98 } else { | 97 } else { |
| 99 curr = SkScalarToFixed(pos[i]); | 98 curr = SkScalarToFixed(desc.fPos[i]); |
| 100 } | 99 } |
| 101 // pin curr withing range | 100 // pin curr withing range |
| 102 if (curr < 0) { | 101 if (curr < 0) { |
| 103 curr = 0; | 102 curr = 0; |
| 104 } else if (curr > SK_Fixed1) { | 103 } else if (curr > SK_Fixed1) { |
| 105 curr = SK_Fixed1; | 104 curr = SK_Fixed1; |
| 106 } | 105 } |
| 107 recs->fPos = curr; | 106 recs->fPos = curr; |
| 108 if (curr > prev) { | 107 if (curr > prev) { |
| 109 recs->fScale = (1 << 24) / (curr - prev); | 108 recs->fScale = (1 << 24) / (curr - prev); |
| 110 } else { | 109 } else { |
| 111 recs->fScale = 0; // ignore this segment | 110 recs->fScale = 0; // ignore this segment |
| 112 } | 111 } |
| 113 // get ready for the next value | 112 // get ready for the next value |
| 114 prev = curr; | 113 prev = curr; |
| 115 recs += 1; | 114 recs += 1; |
| 116 } | 115 } |
| 117 } else { // assume even distribution | 116 } else { // assume even distribution |
| 118 SkFixed dp = SK_Fixed1 / (colorCount - 1); | 117 SkFixed dp = SK_Fixed1 / (desc.fCount - 1); |
| 119 SkFixed p = dp; | 118 SkFixed p = dp; |
| 120 SkFixed scale = (colorCount - 1) << 8; // (1 << 24) / dp | 119 SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp |
| 121 for (int i = 1; i < colorCount; i++) { | 120 for (int i = 1; i < desc.fCount; i++) { |
| 122 recs->fPos = p; | 121 recs->fPos = p; |
| 123 recs->fScale = scale; | 122 recs->fScale = scale; |
| 124 recs += 1; | 123 recs += 1; |
| 125 p += dp; | 124 p += dp; |
| 126 } | 125 } |
| 127 } | 126 } |
| 128 } | 127 } |
| 129 this->initCommon(); | 128 this->initCommon(); |
| 130 } | 129 } |
| 131 | 130 |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 SkColor tmp[2]; \ | 632 SkColor tmp[2]; \ |
| 634 do { \ | 633 do { \ |
| 635 if (1 == count) { \ | 634 if (1 == count) { \ |
| 636 tmp[0] = tmp[1] = colors[0]; \ | 635 tmp[0] = tmp[1] = colors[0]; \ |
| 637 colors = tmp; \ | 636 colors = tmp; \ |
| 638 pos = NULL; \ | 637 pos = NULL; \ |
| 639 count = 2; \ | 638 count = 2; \ |
| 640 } \ | 639 } \ |
| 641 } while (0) | 640 } while (0) |
| 642 | 641 |
| 642 static void desc_init(SkGradientShaderBase::Descriptor* desc, |
| 643 const SkColor colors[], |
| 644 const SkScalar pos[], int colorCount, |
| 645 SkShader::TileMode mode, |
| 646 SkUnitMapper* mapper) { |
| 647 desc->fColors = colors; |
| 648 desc->fPos = pos; |
| 649 desc->fCount = colorCount; |
| 650 desc->fTileMode = mode; |
| 651 desc->fMapper = mapper; |
| 652 } |
| 653 |
| 643 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], | 654 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], |
| 644 const SkColor colors[], | 655 const SkColor colors[], |
| 645 const SkScalar pos[], int colorCount, | 656 const SkScalar pos[], int colorCount, |
| 646 SkShader::TileMode mode, | 657 SkShader::TileMode mode, |
| 647 SkUnitMapper* mapper) { | 658 SkUnitMapper* mapper) { |
| 648 if (NULL == pts || NULL == colors || colorCount < 1) { | 659 if (NULL == pts || NULL == colors || colorCount < 1) { |
| 649 return NULL; | 660 return NULL; |
| 650 } | 661 } |
| 651 EXPAND_1_COLOR(colorCount); | 662 EXPAND_1_COLOR(colorCount); |
| 652 | 663 |
| 653 return SkNEW_ARGS(SkLinearGradient, | 664 SkGradientShaderBase::Descriptor desc; |
| 654 (pts, colors, pos, colorCount, mode, mapper)); | 665 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 666 return SkNEW_ARGS(SkLinearGradient, (pts, desc)); |
| 655 } | 667 } |
| 656 | 668 |
| 657 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, | 669 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, |
| 658 const SkColor colors[], | 670 const SkColor colors[], |
| 659 const SkScalar pos[], int colorCount, | 671 const SkScalar pos[], int colorCount, |
| 660 SkShader::TileMode mode, | 672 SkShader::TileMode mode, |
| 661 SkUnitMapper* mapper) { | 673 SkUnitMapper* mapper) { |
| 662 if (radius <= 0 || NULL == colors || colorCount < 1) { | 674 if (radius <= 0 || NULL == colors || colorCount < 1) { |
| 663 return NULL; | 675 return NULL; |
| 664 } | 676 } |
| 665 EXPAND_1_COLOR(colorCount); | 677 EXPAND_1_COLOR(colorCount); |
| 666 | 678 |
| 667 return SkNEW_ARGS(SkRadialGradient, | 679 SkGradientShaderBase::Descriptor desc; |
| 668 (center, radius, colors, pos, colorCount, mode, mapper)); | 680 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 681 return SkNEW_ARGS(SkRadialGradient, (center, radius, desc)); |
| 669 } | 682 } |
| 670 | 683 |
| 671 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, | 684 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, |
| 672 SkScalar startRadius, | 685 SkScalar startRadius, |
| 673 const SkPoint& end, | 686 const SkPoint& end, |
| 674 SkScalar endRadius, | 687 SkScalar endRadius, |
| 675 const SkColor colors[], | 688 const SkColor colors[], |
| 676 const SkScalar pos[], | 689 const SkScalar pos[], |
| 677 int colorCount, | 690 int colorCount, |
| 678 SkShader::TileMode mode, | 691 SkShader::TileMode mode, |
| 679 SkUnitMapper* mapper) { | 692 SkUnitMapper* mapper) { |
| 680 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { | 693 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { |
| 681 return NULL; | 694 return NULL; |
| 682 } | 695 } |
| 683 EXPAND_1_COLOR(colorCount); | 696 EXPAND_1_COLOR(colorCount); |
| 684 | 697 |
| 698 SkGradientShaderBase::Descriptor desc; |
| 699 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 685 return SkNEW_ARGS(SkTwoPointRadialGradient, | 700 return SkNEW_ARGS(SkTwoPointRadialGradient, |
| 686 (start, startRadius, end, endRadius, colors, pos, | 701 (start, startRadius, end, endRadius, desc)); |
| 687 colorCount, mode, mapper)); | |
| 688 } | 702 } |
| 689 | 703 |
| 690 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, | 704 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, |
| 691 SkScalar startRadius, | 705 SkScalar startRadius, |
| 692 const SkPoint& end, | 706 const SkPoint& end, |
| 693 SkScalar endRadius, | 707 SkScalar endRadius, |
| 694 const SkColor colors[], | 708 const SkColor colors[], |
| 695 const SkScalar pos[], | 709 const SkScalar pos[], |
| 696 int colorCount, | 710 int colorCount, |
| 697 SkShader::TileMode mode, | 711 SkShader::TileMode mode, |
| 698 SkUnitMapper* mapper) { | 712 SkUnitMapper* mapper) { |
| 699 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { | 713 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { |
| 700 return NULL; | 714 return NULL; |
| 701 } | 715 } |
| 702 if (start == end && startRadius == endRadius) { | 716 if (start == end && startRadius == endRadius) { |
| 703 return SkNEW(SkEmptyShader); | 717 return SkNEW(SkEmptyShader); |
| 704 } | 718 } |
| 705 EXPAND_1_COLOR(colorCount); | 719 EXPAND_1_COLOR(colorCount); |
| 706 | 720 |
| 721 SkGradientShaderBase::Descriptor desc; |
| 722 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 707 return SkNEW_ARGS(SkTwoPointConicalGradient, | 723 return SkNEW_ARGS(SkTwoPointConicalGradient, |
| 708 (start, startRadius, end, endRadius, colors, pos, | 724 (start, startRadius, end, endRadius, desc)); |
| 709 colorCount, mode, mapper)); | |
| 710 } | 725 } |
| 711 | 726 |
| 712 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, | 727 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, |
| 713 const SkColor colors[], | 728 const SkColor colors[], |
| 714 const SkScalar pos[], | 729 const SkScalar pos[], |
| 715 int count, SkUnitMapper* mapper) { | 730 int colorCount, SkUnitMapper* mapper) { |
| 716 if (NULL == colors || count < 1) { | 731 if (NULL == colors || colorCount < 1) { |
| 717 return NULL; | 732 return NULL; |
| 718 } | 733 } |
| 719 EXPAND_1_COLOR(count); | 734 EXPAND_1_COLOR(colorCount); |
| 720 | 735 |
| 721 return SkNEW_ARGS(SkSweepGradient, (cx, cy, colors, pos, count, mapper)); | 736 SkGradientShaderBase::Descriptor desc; |
| 737 desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper)
; |
| 738 return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc)); |
| 722 } | 739 } |
| 723 | 740 |
| 724 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) | 741 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) |
| 725 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) | 742 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) |
| 726 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) | 743 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) |
| 727 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) | 744 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) |
| 728 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) | 745 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) |
| 729 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) | 746 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) |
| 730 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 747 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 731 | 748 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 (*stops)[i] = stop; | 908 (*stops)[i] = stop; |
| 892 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; | 909 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; |
| 893 } | 910 } |
| 894 } | 911 } |
| 895 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); | 912 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); |
| 896 | 913 |
| 897 return outColors; | 914 return outColors; |
| 898 } | 915 } |
| 899 | 916 |
| 900 #endif | 917 #endif |
| OLD | NEW |