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