1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkDrawGradient.h" 11 #include "SkAnimateMaker.h" 12 #include "SkAnimatorScript.h" 13 #include "SkGradientShader.h" 14 15 #if SK_USE_CONDENSED_INFO == 0 16 17 const SkMemberInfo SkDrawGradient::fInfo[] = { 18 SK_MEMBER_INHERITED, 19 SK_MEMBER_ARRAY(offsets, Float), 20 SK_MEMBER(unitMapper, String) 21 }; 22 23 #endif 24 25 DEFINE_GET_MEMBER(SkDrawGradient); 26 27 SkDrawGradient::SkDrawGradient() { 28 } 29 30 SkDrawGradient::~SkDrawGradient() { 31 for (int index = 0; index < fDrawColors.count(); index++) 32 delete fDrawColors[index]; 33 } 34 35 bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) { 36 SkASSERT(child); 37 if (child->isColor()) { 38 SkDrawColor* color = (SkDrawColor*) child; 39 *fDrawColors.append() = color; 40 return true; 41 } 42 return false; 43 } 44 45 int SkDrawGradient::addPrelude() { 46 int count = fDrawColors.count(); 47 fColors.setCount(count); 48 for (int index = 0; index < count; index++) 49 fColors[index] = fDrawColors[index]->color; 50 return count; 51 } 52 53 #ifdef SK_DUMP_ENABLED 54 void SkDrawGradient::dumpRest(SkAnimateMaker* maker) { 55 dumpAttrs(maker); 56 //can a gradient have no colors? 57 bool closedYet = false; 58 SkDisplayList::fIndent += 4; 59 for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) { 60 if (closedYet == false) { 61 SkDebugf(">\n"); 62 closedYet = true; 63 } 64 SkDrawColor* color = *ptr; 65 color->dump(maker); 66 } 67 SkDisplayList::fIndent -= 4; 68 dumpChildren(maker, closedYet); //dumps the matrix if it has one 69 } 70 #endif 71 72 void SkDrawGradient::onEndElement(SkAnimateMaker& maker) { 73 if (offsets.count() != 0) { 74 if (offsets.count() != fDrawColors.count()) { 75 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors); 76 return; 77 } 78 if (offsets[0] != 0) { 79 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero); 80 return; 81 } 82 if (offsets[offsets.count()-1] != SK_Scalar1) { 83 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne); 84 return; 85 } 86 for (int i = 1; i < offsets.count(); i++) { 87 if (offsets[i] <= offsets[i-1]) { 88 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease); 89 return; 90 } 91 if (offsets[i] > SK_Scalar1) { 92 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne); 93 return; 94 } 95 } 96 } 97 INHERITED::onEndElement(maker); 98 } 99 100 #if SK_USE_CONDENSED_INFO == 0 101 102 const SkMemberInfo SkDrawLinearGradient::fInfo[] = { 103 SK_MEMBER_INHERITED, 104 SK_MEMBER_ARRAY(points, Float), 105 }; 106 107 #endif 108 109 DEFINE_GET_MEMBER(SkDrawLinearGradient); 110 111 SkDrawLinearGradient::SkDrawLinearGradient() { 112 } 113 114 void SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker) 115 { 116 if (points.count() != 4) 117 maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour); 118 INHERITED::onEndElement(maker); 119 } 120 121 #ifdef SK_DUMP_ENABLED 122 void SkDrawLinearGradient::dump(SkAnimateMaker* maker) { 123 dumpBase(maker); 124 dumpRest(maker); 125 } 126 #endif 127 128 SkShader* SkDrawLinearGradient::getShader() { 129 if (addPrelude() == 0 || points.count() != 4) 130 return nullptr; 131 SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(), 132 fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, 133 0, getMatrix()); 134 SkAutoTDelete<SkShader> autoDel(shader); 135 (void)autoDel.detach(); 136 return shader; 137 } 138 139 140 #if SK_USE_CONDENSED_INFO == 0 141 142 const SkMemberInfo SkDrawRadialGradient::fInfo[] = { 143 SK_MEMBER_INHERITED, 144 SK_MEMBER(center, Point), 145 SK_MEMBER(radius, Float) 146 }; 147 148 #endif 149 150 DEFINE_GET_MEMBER(SkDrawRadialGradient); 151 152 SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) { 153 center.set(0, 0); 154 } 155 156 #ifdef SK_DUMP_ENABLED 157 void SkDrawRadialGradient::dump(SkAnimateMaker* maker) { 158 dumpBase(maker); 159 dumpRest(maker); 160 } 161 #endif 162 163 SkShader* SkDrawRadialGradient::getShader() { 164 if (addPrelude() == 0) 165 return nullptr; 166 SkShader* shader = SkGradientShader::CreateRadial(center, 167 radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, 168 0, getMatrix()); 169 SkAutoTDelete<SkShader> autoDel(shader); 170 (void)autoDel.detach(); 171 return shader; 172 } 173