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