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