• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/animator/SkDrawGradient.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkDrawGradient.h"
19 #include "SkAnimateMaker.h"
20 #include "SkAnimatorScript.h"
21 #include "SkGradientShader.h"
22 #include "SkUnitMapper.h"
23 
SkUnitToScalar(U16CPU x)24 SkScalar SkUnitToScalar(U16CPU x) {
25 #ifdef SK_SCALAR_IS_FLOAT
26     return x / 65535.0f;
27 #else
28     return x + (x >> 8);
29 #endif
30 }
31 
SkScalarToUnit(SkScalar x)32 U16CPU SkScalarToUnit(SkScalar x) {
33     SkScalar pin =  SkScalarPin(x, 0, SK_Scalar1);
34 #ifdef SK_SCALAR_IS_FLOAT
35     return (int) (pin * 65535.0f);
36 #else
37     return pin - (pin >= 32768);
38 #endif
39 }
40 
41 class SkGradientUnitMapper : public SkUnitMapper {
42 public:
SkGradientUnitMapper(SkAnimateMaker * maker,const char * script)43     SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
44     }
45 
46     // overrides for SkFlattenable
getFactory()47     virtual Factory getFactory() { return NULL; }
48 
49 protected:
mapUnit16(uint16_t x)50     virtual uint16_t mapUnit16(uint16_t x) {
51         fUnit = SkUnitToScalar(x);
52         SkScriptValue value;
53         SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
54         engine.propertyCallBack(GetUnitValue, &fUnit);
55         if (engine.evaluate(fScript, &value, SkType_Float))
56             x = SkScalarToUnit(value.fOperand.fScalar);
57         return x;
58     }
59 
GetUnitValue(const char * token,size_t len,void * unitPtr,SkScriptValue * value)60     static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) {
61         if (SK_LITERAL_STR_EQUAL("unit", token, len)) {
62             value->fOperand.fScalar = *(SkScalar*) unitPtr;
63             value->fType = SkType_Float;
64             return true;
65         }
66         return false;
67     }
68 
69     SkAnimateMaker* fMaker;
70     const char* fScript;
71     SkScalar fUnit;
72 };
73 
74 
75 #if SK_USE_CONDENSED_INFO == 0
76 
77 const SkMemberInfo SkGradient::fInfo[] = {
78     SK_MEMBER_INHERITED,
79     SK_MEMBER_ARRAY(offsets, Float),
80     SK_MEMBER(unitMapper, String)
81 };
82 
83 #endif
84 
85 DEFINE_GET_MEMBER(SkGradient);
86 
SkGradient()87 SkGradient::SkGradient() : fUnitMapper(NULL) {
88 }
89 
~SkGradient()90 SkGradient::~SkGradient() {
91     for (int index = 0; index < fDrawColors.count(); index++)
92         delete fDrawColors[index];
93     delete fUnitMapper;
94 }
95 
add(SkAnimateMaker &,SkDisplayable * child)96 bool SkGradient::add(SkAnimateMaker& , SkDisplayable* child) {
97     SkASSERT(child);
98     if (child->isColor()) {
99         SkDrawColor* color = (SkDrawColor*) child;
100         *fDrawColors.append() = color;
101         return true;
102     }
103     return false;
104 }
105 
addPrelude()106 int SkGradient::addPrelude() {
107     int count = fDrawColors.count();
108     fColors.setCount(count);
109     for (int index = 0; index < count; index++)
110         fColors[index] = fDrawColors[index]->color;
111     return count;
112 }
113 
114 #ifdef SK_DUMP_ENABLED
dumpRest(SkAnimateMaker * maker)115 void SkGradient::dumpRest(SkAnimateMaker* maker) {
116     dumpAttrs(maker);
117     //can a gradient have no colors?
118     bool closedYet = false;
119     SkDisplayList::fIndent += 4;
120     for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
121         if (closedYet == false) {
122             SkDebugf(">\n");
123             closedYet = true;
124         }
125         SkDrawColor* color = *ptr;
126         color->dump(maker);
127     }
128     SkDisplayList::fIndent -= 4;
129     dumpChildren(maker, closedYet); //dumps the matrix if it has one
130 }
131 #endif
132 
onEndElement(SkAnimateMaker & maker)133 void SkGradient::onEndElement(SkAnimateMaker& maker) {
134     if (offsets.count() != 0) {
135         if (offsets.count() != fDrawColors.count()) {
136             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
137             return;
138         }
139         if (offsets[0] != 0) {
140             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
141             return;
142         }
143         if (offsets[offsets.count()-1] != SK_Scalar1) {
144             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
145             return;
146         }
147         for (int i = 1; i < offsets.count(); i++) {
148             if (offsets[i] <= offsets[i-1]) {
149                 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
150                 return;
151             }
152             if (offsets[i] > SK_Scalar1) {
153                 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
154                 return;
155             }
156         }
157     }
158     if (unitMapper.size() > 0)
159         fUnitMapper = new SkGradientUnitMapper(&maker, unitMapper.c_str());
160     INHERITED::onEndElement(maker);
161 }
162 
163 #if SK_USE_CONDENSED_INFO == 0
164 
165 const SkMemberInfo SkLinearGradient::fInfo[] = {
166     SK_MEMBER_INHERITED,
167     SK_MEMBER_ARRAY(points, Float),
168 };
169 
170 #endif
171 
172 DEFINE_GET_MEMBER(SkLinearGradient);
173 
SkLinearGradient()174 SkLinearGradient::SkLinearGradient() {
175 }
176 
onEndElement(SkAnimateMaker & maker)177 void SkLinearGradient::onEndElement(SkAnimateMaker& maker)
178 {
179     if (points.count() != 4)
180         maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
181     INHERITED::onEndElement(maker);
182 }
183 
184 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)185 void SkLinearGradient::dump(SkAnimateMaker* maker) {
186     dumpBase(maker);
187     dumpRest(maker);
188     }
189 #endif
190 
getShader()191 SkShader* SkLinearGradient::getShader() {
192     if (addPrelude() == 0 || points.count() != 4)
193         return NULL;
194     SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
195         fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
196     SkAutoTDelete<SkShader> autoDel(shader);
197     addPostlude(shader);
198     (void)autoDel.detach();
199     return shader;
200 }
201 
202 
203 #if SK_USE_CONDENSED_INFO == 0
204 
205 const SkMemberInfo SkRadialGradient::fInfo[] = {
206     SK_MEMBER_INHERITED,
207     SK_MEMBER(center, Point),
208     SK_MEMBER(radius, Float)
209 };
210 
211 #endif
212 
213 DEFINE_GET_MEMBER(SkRadialGradient);
214 
SkRadialGradient()215 SkRadialGradient::SkRadialGradient() : radius(0) {
216     center.set(0, 0);
217 }
218 
219 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)220 void SkRadialGradient::dump(SkAnimateMaker* maker) {
221     dumpBase(maker);
222     dumpRest(maker);
223 }
224 #endif
225 
getShader()226 SkShader* SkRadialGradient::getShader() {
227     if (addPrelude() == 0)
228         return NULL;
229     SkShader* shader = SkGradientShader::CreateRadial(center,
230         radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
231     SkAutoTDelete<SkShader> autoDel(shader);
232     addPostlude(shader);
233     (void)autoDel.detach();
234     return shader;
235 }
236