OLD | NEW |
| (Empty) |
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 | |
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 | |
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: | |
43 SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(mak
er), fScript(script) { | |
44 } | |
45 | |
46 // overrides for SkFlattenable | |
47 virtual Factory getFactory() { return NULL; } | |
48 | |
49 protected: | |
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 | |
60 static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScr
iptValue* 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 | |
87 SkGradient::SkGradient() : fUnitMapper(NULL) { | |
88 } | |
89 | |
90 SkGradient::~SkGradient() { | |
91 for (int index = 0; index < fDrawColors.count(); index++) | |
92 delete fDrawColors[index]; | |
93 delete fUnitMapper; | |
94 } | |
95 | |
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 | |
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 | |
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 | |
133 void SkGradient::onEndElement(SkAnimateMaker& maker) { | |
134 if (offsets.count() != 0) { | |
135 if (offsets.count() != fDrawColors.count()) { | |
136 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatc
hColors); | |
137 return; | |
138 } | |
139 if (offsets[0] != 0) { | |
140 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStar
tWithZero); | |
141 return; | |
142 } | |
143 if (offsets[offsets.count()-1] != SK_Scalar1) { | |
144 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndW
ithOne); | |
145 return; | |
146 } | |
147 for (int i = 1; i < offsets.count(); i++) { | |
148 if (offsets[i] <= offsets[i-1]) { | |
149 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMust
Increase); | |
150 return; | |
151 } | |
152 if (offsets[i] > SK_Scalar1) { | |
153 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMust
BeNoMoreThanOne); | |
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 | |
174 SkLinearGradient::SkLinearGradient() { | |
175 } | |
176 | |
177 void SkLinearGradient::onEndElement(SkAnimateMaker& maker) | |
178 { | |
179 if (points.count() != 4) | |
180 maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeF
our); | |
181 INHERITED::onEndElement(maker); | |
182 } | |
183 | |
184 #ifdef SK_DUMP_ENABLED | |
185 void SkLinearGradient::dump(SkAnimateMaker* maker) { | |
186 dumpBase(maker); | |
187 dumpRest(maker); | |
188 } | |
189 #endif | |
190 | |
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 | |
215 SkRadialGradient::SkRadialGradient() : radius(0) { | |
216 center.set(0, 0); | |
217 } | |
218 | |
219 #ifdef SK_DUMP_ENABLED | |
220 void SkRadialGradient::dump(SkAnimateMaker* maker) { | |
221 dumpBase(maker); | |
222 dumpRest(maker); | |
223 } | |
224 #endif | |
225 | |
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::Ti
leMode) tileMode, fUnitMapper); | |
231 SkAutoTDelete<SkShader> autoDel(shader); | |
232 addPostlude(shader); | |
233 (void)autoDel.detach(); | |
234 return shader; | |
235 } | |
OLD | NEW |