• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
26 enum HSV_Choice {
27     kGetHue,
28     kGetSaturation,
29     kGetValue
30 };
31 
RGB_to_HSV(SkColor color,HSV_Choice choice)32 static 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 
HSV_to_RGB(SkColor color,HSV_Choice choice,SkScalar hsv)68 static 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 
104 enum 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 
116 const 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 
129 DEFINE_GET_MEMBER(SkDrawColor);
130 
SkDrawColor()131 SkDrawColor::SkDrawColor() : fDirty(false) {
132     color = SK_ColorBLACK;
133     fHue = fSaturation = fValue = SK_ScalarNaN;
134 }
135 
add()136 bool 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 
deepCopy(SkAnimateMaker * maker)144 SkDisplayable* 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 
dirty()154 void SkDrawColor::dirty(){
155     fDirty = true;
156 }
157 
158 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)159 void 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 
getColor()167 SkColor 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 
getParent() const180 SkDisplayable* SkDrawColor::getParent() const {
181     return fPaint;
182 }
183 
getProperty(int index,SkScriptValue * value) const184 bool 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 
onEndElement(SkAnimateMaker & maker)217 void SkDrawColor::onEndElement(SkAnimateMaker& maker){
218     fDirty = true;
219 }
220 
setParent(SkDisplayable * parent)221 bool 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 
setProperty(int index,SkScriptValue & value)231 bool 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 
279