Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
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 */
10 #include "SkDrawGradient.h"
11 #include "SkAnimateMaker.h"
12 #include "SkAnimatorScript.h"
13 #include "SkGradientShader.h"
14 #include "SkUnitMapper.h"
16 static SkScalar SkUnitToScalar(U16CPU x) {
17 return x / 65535.0f;
18 }
20 static U16CPU SkScalarToUnit(SkScalar x) {
21 SkScalar pin = SkScalarPin(x, 0, SK_Scalar1);
22 return (int) (pin * 65535.0f);
23 }
25 class SkDrawGradientUnitMapper : public SkUnitMapper {
26 public:
27 SkDrawGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
28 }
30 SK_DECLARE_UNFLATTENABLE_OBJECT()
32 protected:
33 virtual uint16_t mapUnit16(uint16_t x) {
34 fUnit = SkUnitToScalar(x);
35 SkScriptValue value;
36 SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
37 engine.propertyCallBack(GetUnitValue, &fUnit);
38 if (engine.evaluate(fScript, &value, SkType_Float))
39 x = SkScalarToUnit(value.fOperand.fScalar);
40 return x;
41 }
43 static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) {
44 if (SK_LITERAL_STR_EQUAL("unit", token, len)) {
45 value->fOperand.fScalar = *(SkScalar*) unitPtr;
46 value->fType = SkType_Float;
47 return true;
48 }
49 return false;
50 }
52 SkAnimateMaker* fMaker;
53 const char* fScript;
54 SkScalar fUnit;
55 };
58 #if SK_USE_CONDENSED_INFO == 0
60 const SkMemberInfo SkDrawGradient::fInfo[] = {
61 SK_MEMBER_INHERITED,
62 SK_MEMBER_ARRAY(offsets, Float),
63 SK_MEMBER(unitMapper, String)
64 };
66 #endif
68 DEFINE_GET_MEMBER(SkDrawGradient);
70 SkDrawGradient::SkDrawGradient() : fUnitMapper(NULL) {
71 }
73 SkDrawGradient::~SkDrawGradient() {
74 for (int index = 0; index < fDrawColors.count(); index++)
75 delete fDrawColors[index];
76 delete fUnitMapper;
77 }
79 bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) {
80 SkASSERT(child);
81 if (child->isColor()) {
82 SkDrawColor* color = (SkDrawColor*) child;
83 *fDrawColors.append() = color;
84 return true;
85 }
86 return false;
87 }
89 int SkDrawGradient::addPrelude() {
90 int count = fDrawColors.count();
91 fColors.setCount(count);
92 for (int index = 0; index < count; index++)
93 fColors[index] = fDrawColors[index]->color;
94 return count;
95 }
97 #ifdef SK_DUMP_ENABLED
98 void SkDrawGradient::dumpRest(SkAnimateMaker* maker) {
99 dumpAttrs(maker);
100 //can a gradient have no colors?
101 bool closedYet = false;
102 SkDisplayList::fIndent += 4;
103 for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
104 if (closedYet == false) {
105 SkDebugf(">\n");
106 closedYet = true;
107 }
108 SkDrawColor* color = *ptr;
109 color->dump(maker);
110 }
111 SkDisplayList::fIndent -= 4;
112 dumpChildren(maker, closedYet); //dumps the matrix if it has one
113 }
114 #endif
116 void SkDrawGradient::onEndElement(SkAnimateMaker& maker) {
117 if (offsets.count() != 0) {
118 if (offsets.count() != fDrawColors.count()) {
119 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
120 return;
121 }
122 if (offsets[0] != 0) {
123 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
124 return;
125 }
126 if (offsets[offsets.count()-1] != SK_Scalar1) {
127 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
128 return;
129 }
130 for (int i = 1; i < offsets.count(); i++) {
131 if (offsets[i] <= offsets[i-1]) {
132 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
133 return;
134 }
135 if (offsets[i] > SK_Scalar1) {
136 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
137 return;
138 }
139 }
140 }
141 if (unitMapper.size() > 0)
142 fUnitMapper = new SkDrawGradientUnitMapper(&maker, unitMapper.c_str());
143 INHERITED::onEndElement(maker);
144 }
146 #if SK_USE_CONDENSED_INFO == 0
148 const SkMemberInfo SkDrawLinearGradient::fInfo[] = {
149 SK_MEMBER_INHERITED,
150 SK_MEMBER_ARRAY(points, Float),
151 };
153 #endif
155 DEFINE_GET_MEMBER(SkDrawLinearGradient);
157 SkDrawLinearGradient::SkDrawLinearGradient() {
158 }
160 void SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker)
161 {
162 if (points.count() != 4)
163 maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
164 INHERITED::onEndElement(maker);
165 }
167 #ifdef SK_DUMP_ENABLED
168 void SkDrawLinearGradient::dump(SkAnimateMaker* maker) {
169 dumpBase(maker);
170 dumpRest(maker);
171 }
172 #endif
174 SkShader* SkDrawLinearGradient::getShader() {
175 if (addPrelude() == 0 || points.count() != 4)
176 return NULL;
177 SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
178 fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
179 SkAutoTDelete<SkShader> autoDel(shader);
180 addPostlude(shader);
181 (void)autoDel.detach();
182 return shader;
183 }
186 #if SK_USE_CONDENSED_INFO == 0
188 const SkMemberInfo SkDrawRadialGradient::fInfo[] = {
189 SK_MEMBER_INHERITED,
190 SK_MEMBER(center, Point),
191 SK_MEMBER(radius, Float)
192 };
194 #endif
196 DEFINE_GET_MEMBER(SkDrawRadialGradient);
198 SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) {
199 center.set(0, 0);
200 }
202 #ifdef SK_DUMP_ENABLED
203 void SkDrawRadialGradient::dump(SkAnimateMaker* maker) {
204 dumpBase(maker);
205 dumpRest(maker);
206 }
207 #endif
209 SkShader* SkDrawRadialGradient::getShader() {
210 if (addPrelude() == 0)
211 return NULL;
212 SkShader* shader = SkGradientShader::CreateRadial(center,
213 radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
214 SkAutoTDelete<SkShader> autoDel(shader);
215 addPostlude(shader);
216 (void)autoDel.detach();
217 return shader;
218 }