blob: 37fc7e8b8e7e7b7475061c38b5194f1c7cf12391 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkDrawGradient.h"
11#include "SkAnimateMaker.h"
12#include "SkAnimatorScript.h"
13#include "SkGradientShader.h"
14#include "SkUnitMapper.h"
15
16SkScalar 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
24U16CPU 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
33class SkGradientUnitMapper : public SkUnitMapper {
34public:
35 SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
36 }
37
38 // overrides for SkFlattenable
39 virtual Factory getFactory() { return NULL; }
40
41protected:
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
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
69const SkMemberInfo SkGradient::fInfo[] = {
70 SK_MEMBER_INHERITED,
71 SK_MEMBER_ARRAY(offsets, Float),
72 SK_MEMBER(unitMapper, String)
73};
74
75#endif
76
77DEFINE_GET_MEMBER(SkGradient);
78
79SkGradient::SkGradient() : fUnitMapper(NULL) {
80}
81
82SkGradient::~SkGradient() {
83 for (int index = 0; index < fDrawColors.count(); index++)
84 delete fDrawColors[index];
85 delete fUnitMapper;
86}
87
88bool 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
98int 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
107void 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
125void 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
157const SkMemberInfo SkLinearGradient::fInfo[] = {
158 SK_MEMBER_INHERITED,
159 SK_MEMBER_ARRAY(points, Float),
160};
161
162#endif
163
164DEFINE_GET_MEMBER(SkLinearGradient);
165
166SkLinearGradient::SkLinearGradient() {
167}
168
169void 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
177void SkLinearGradient::dump(SkAnimateMaker* maker) {
178 dumpBase(maker);
179 dumpRest(maker);
180 }
181#endif
182
183SkShader* 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
197const SkMemberInfo SkRadialGradient::fInfo[] = {
198 SK_MEMBER_INHERITED,
199 SK_MEMBER(center, Point),
200 SK_MEMBER(radius, Float)
201};
202
203#endif
204
205DEFINE_GET_MEMBER(SkRadialGradient);
206
207SkRadialGradient::SkRadialGradient() : radius(0) {
208 center.set(0, 0);
209}
210
211#ifdef SK_DUMP_ENABLED
212void SkRadialGradient::dump(SkAnimateMaker* maker) {
213 dumpBase(maker);
214 dumpRest(maker);
215}
216#endif
217
218SkShader* 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}