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