blob: 009ca10c65b7877b076fb0704749e63b9da6e94b [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/animator/SkDrawColor.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 "SkDrawColor.h"
19#ifdef SK_DEBUG
20#include "SkDisplayList.h"
21#endif
22#include "SkDrawPaint.h"
23#include "SkParse.h"
24#include "SkScript.h"
25
26enum HSV_Choice {
27 kGetHue,
28 kGetSaturation,
29 kGetValue
30};
31
32static SkScalar RGB_to_HSV(SkColor color, HSV_Choice choice) {
33 SkScalar red = SkIntToScalar(SkColorGetR(color));
34 SkScalar green = SkIntToScalar(SkColorGetG(color));
35 SkScalar blue = SkIntToScalar(SkColorGetB(color));
36 SkScalar min = SkMinScalar(SkMinScalar(red, green), blue);
37 SkScalar value = SkMaxScalar(SkMaxScalar(red, green), blue);
38 if (choice == kGetValue)
39 return value/255;
40 SkScalar delta = value - min;
41 SkScalar saturation = value == 0 ? 0 : SkScalarDiv(delta, value);
42 if (choice == kGetSaturation)
43 return saturation;
44 SkScalar hue;
45 if (saturation == 0)
46 hue = 0;
47 else {
48 SkScalar part60 = SkScalarDiv(60 * SK_Scalar1, delta);
49 if (red == value) {
50 hue = SkScalarMul(green - blue, part60);
51 if (hue < 0)
52 hue += 360 * SK_Scalar1;
53 }
54 else if (green == value)
55 hue = 120 * SK_Scalar1 + SkScalarMul(blue - red, part60);
56 else // blue == value
57 hue = 240 * SK_Scalar1 + SkScalarMul(red - green, part60);
58 }
59 SkASSERT(choice == kGetHue);
60 return hue;
61}
62
63#if defined _WIN32 && _MSC_VER >= 1300 // disable 'red', etc. may be used without having been initialized
64#pragma warning ( push )
65#pragma warning ( disable : 4701 )
66#endif
67
68static SkColor HSV_to_RGB(SkColor color, HSV_Choice choice, SkScalar hsv) {
69 SkScalar hue = choice == kGetHue ? hsv : RGB_to_HSV(color, kGetHue);
70 SkScalar saturation = choice == kGetSaturation ? hsv : RGB_to_HSV(color, kGetSaturation);
71 SkScalar value = choice == kGetValue ? hsv : RGB_to_HSV(color, kGetValue);
72 value *= 255;
73 SkScalar red SK_INIT_TO_AVOID_WARNING;
74 SkScalar green SK_INIT_TO_AVOID_WARNING;
75 SkScalar blue SK_INIT_TO_AVOID_WARNING;
76 if (saturation == 0) // color is on black-and-white center line
77 red = green = blue = value;
78 else {
79 //SkScalar fraction = SkScalarMod(hue, 60 * SK_Scalar1);
80 int sextant = SkScalarFloor(hue / 60);
81 SkScalar fraction = hue / 60 - SkIntToScalar(sextant);
82 SkScalar p = SkScalarMul(value , SK_Scalar1 - saturation);
83 SkScalar q = SkScalarMul(value, SK_Scalar1 - SkScalarMul(saturation, fraction));
84 SkScalar t = SkScalarMul(value, SK_Scalar1 -
85 SkScalarMul(saturation, SK_Scalar1 - fraction));
86 switch (sextant % 6) {
87 case 0: red = value; green = t; blue = p; break;
88 case 1: red = q; green = value; blue = p; break;
89 case 2: red = p; green = value; blue = t; break;
90 case 3: red = p; green = q; blue = value; break;
91 case 4: red = t; green = p; blue = value; break;
92 case 5: red = value; green = p; blue = q; break;
93 }
94 }
95 //used to say SkToU8((U8CPU) red) etc
96 return SkColorSetARGB(SkColorGetA(color), SkScalarRound(red),
97 SkScalarRound(green), SkScalarRound(blue));
98}
99
100#if defined _WIN32 && _MSC_VER >= 1300
101#pragma warning ( pop )
102#endif
103
104enum SkDrawColor_Properties {
105 SK_PROPERTY(alpha),
106 SK_PROPERTY(blue),
107 SK_PROPERTY(green),
108 SK_PROPERTY(hue),
109 SK_PROPERTY(red),
110 SK_PROPERTY(saturation),
111 SK_PROPERTY(value)
112};
113
114#if SK_USE_CONDENSED_INFO == 0
115
116const SkMemberInfo SkDrawColor::fInfo[] = {
117 SK_MEMBER_PROPERTY(alpha, Float),
118 SK_MEMBER_PROPERTY(blue, Float),
119 SK_MEMBER(color, ARGB),
120 SK_MEMBER_PROPERTY(green, Float),
121 SK_MEMBER_PROPERTY(hue, Float),
122 SK_MEMBER_PROPERTY(red, Float),
123 SK_MEMBER_PROPERTY(saturation, Float),
124 SK_MEMBER_PROPERTY(value, Float),
125};
126
127#endif
128
129DEFINE_GET_MEMBER(SkDrawColor);
130
131SkDrawColor::SkDrawColor() : fDirty(false) {
132 color = SK_ColorBLACK;
133 fHue = fSaturation = fValue = SK_ScalarNaN;
134}
135
136bool SkDrawColor::add() {
137 if (fPaint->color != NULL)
138 return true; // error (probably color in paint as attribute as well)
139 fPaint->color = this;
140 fPaint->fOwnsColor = true;
141 return false;
142}
143
144SkDisplayable* SkDrawColor::deepCopy(SkAnimateMaker* maker) {
145 SkDrawColor* copy = new SkDrawColor();
146 copy->color = color;
147 copy->fHue = fHue;
148 copy->fSaturation = fSaturation;
149 copy->fValue = fValue;
150 copy->fDirty = fDirty;
151 return copy;
152}
153
154void SkDrawColor::dirty(){
155 fDirty = true;
156}
157
158#ifdef SK_DUMP_ENABLED
159void SkDrawColor::dump(SkAnimateMaker* maker) {
160 dumpBase(maker);
161 SkDebugf("alpha=\"%d\" red=\"%d\" green=\"%d\" blue=\"%d\" />\n",
162 SkColorGetA(color)/255, SkColorGetR(color),
163 SkColorGetG(color), SkColorGetB(color));
164}
165#endif
166
167SkColor SkDrawColor::getColor() {
168 if (fDirty) {
169 if (SkScalarIsNaN(fValue) == false)
170 color = HSV_to_RGB(color, kGetValue, fValue);
171 if (SkScalarIsNaN(fSaturation) == false)
172 color = HSV_to_RGB(color, kGetSaturation, fSaturation);
173 if (SkScalarIsNaN(fHue) == false)
174 color = HSV_to_RGB(color, kGetHue, fHue);
175 fDirty = false;
176 }
177 return color;
178}
179
180SkDisplayable* SkDrawColor::getParent() const {
181 return fPaint;
182}
183
184bool SkDrawColor::getProperty(int index, SkScriptValue* value) const {
185 value->fType = SkType_Float;
186 SkScalar result;
187 switch(index) {
188 case SK_PROPERTY(alpha):
189 result = SkIntToScalar(SkColorGetA(color)) / 255;
190 break;
191 case SK_PROPERTY(blue):
192 result = SkIntToScalar(SkColorGetB(color));
193 break;
194 case SK_PROPERTY(green):
195 result = SkIntToScalar(SkColorGetG(color));
196 break;
197 case SK_PROPERTY(hue):
198 result = RGB_to_HSV(color, kGetHue);
199 break;
200 case SK_PROPERTY(red):
201 result = SkIntToScalar(SkColorGetR(color));
202 break;
203 case SK_PROPERTY(saturation):
204 result = RGB_to_HSV(color, kGetSaturation);
205 break;
206 case SK_PROPERTY(value):
207 result = RGB_to_HSV(color, kGetValue);
208 break;
209 default:
210 SkASSERT(0);
211 return false;
212 }
213 value->fOperand.fScalar = result;
214 return true;
215}
216
217void SkDrawColor::onEndElement(SkAnimateMaker& maker){
218 fDirty = true;
219}
220
221bool SkDrawColor::setParent(SkDisplayable* parent) {
222 SkASSERT(parent != NULL);
223 if (parent->getType() == SkType_LinearGradient || parent->getType() == SkType_RadialGradient)
224 return false;
225 if (parent->isPaint() == false)
226 return true;
227 fPaint = (SkDrawPaint*) parent;
228 return false;
229}
230
231bool SkDrawColor::setProperty(int index, SkScriptValue& value) {
232 SkASSERT(value.fType == SkType_Float);
233 SkScalar scalar = value.fOperand.fScalar;
234 switch (index) {
235 case SK_PROPERTY(alpha):
236 uint8_t alpha;
237 #ifdef SK_SCALAR_IS_FLOAT
238 alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256));
239 #else
240 alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8);
241 #endif
242 color = SkColorSetARGB(alpha, SkColorGetR(color),
243 SkColorGetG(color), SkColorGetB(color));
244 break;
245 case SK_PROPERTY(blue):
246 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1);
247 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color),
248 SkColorGetG(color), SkToU8((U8CPU) scalar));
249 break;
250 case SK_PROPERTY(green):
251 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1);
252 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color),
253 SkToU8((U8CPU) scalar), SkColorGetB(color));
254 break;
255 case SK_PROPERTY(hue):
256 fHue = scalar;//RGB_to_HSV(color, kGetHue);
257 fDirty = true;
258 break;
259 case SK_PROPERTY(red):
260 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1);
261 color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar),
262 SkColorGetG(color), SkColorGetB(color));
263 break;
264 case SK_PROPERTY(saturation):
265 fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation);
266 fDirty = true;
267 break;
268 case SK_PROPERTY(value):
269 fValue = scalar;//RGB_to_HSV(color, kGetValue);
270 fDirty = true;
271 break;
272 default:
273 SkASSERT(0);
274 return false;
275 }
276 return true;
277}
278