blob: 00c429b5a1842132fdc48f604155a99b96d40c23 [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 "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
18enum HSV_Choice {
19 kGetHue,
20 kGetSaturation,
21 kGetValue
22};
23
24static 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 : SkScalarDiv(delta, value);
34 if (choice == kGetSaturation)
35 return saturation;
36 SkScalar hue;
37 if (saturation == 0)
38 hue = 0;
39 else {
40 SkScalar part60 = SkScalarDiv(60 * SK_Scalar1, 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
60static 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 = SkScalarFloor(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));
rmistry@google.comd6176b02012-08-23 18:14:13 +000076 SkScalar t = SkScalarMul(value, SK_Scalar1 -
reed@android.com8a1c16f2008-12-17 15:59:43 +000077 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
rmistry@google.comd6176b02012-08-23 18:14:13 +000088 return SkColorSetARGB(SkColorGetA(color), SkScalarRound(red),
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 SkScalarRound(green), SkScalarRound(blue));
90}
91
rmistry@google.comd6176b02012-08-23 18:14:13 +000092#if defined _WIN32 && _MSC_VER >= 1300
reed@android.com8a1c16f2008-12-17 15:59:43 +000093#pragma warning ( pop )
94#endif
95
96enum 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
108const 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
121DEFINE_GET_MEMBER(SkDrawColor);
122
rmistry@google.comd6176b02012-08-23 18:14:13 +0000123SkDrawColor::SkDrawColor() : fDirty(false) {
124 color = SK_ColorBLACK;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 fHue = fSaturation = fValue = SK_ScalarNaN;
126}
127
128bool 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
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000136SkDisplayable* SkDrawColor::deepCopy(SkAnimateMaker*) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 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
146void SkDrawColor::dirty(){
147 fDirty = true;
148}
149
150#ifdef SK_DUMP_ENABLED
151void SkDrawColor::dump(SkAnimateMaker* maker) {
152 dumpBase(maker);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000153 SkDebugf("alpha=\"%d\" red=\"%d\" green=\"%d\" blue=\"%d\" />\n",
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154 SkColorGetA(color)/255, SkColorGetR(color),
155 SkColorGetG(color), SkColorGetB(color));
156}
157#endif
158
rmistry@google.comd6176b02012-08-23 18:14:13 +0000159SkColor SkDrawColor::getColor() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000169 return color;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170}
171
172SkDisplayable* SkDrawColor::getParent() const {
173 return fPaint;
174}
175
176bool 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
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000209void SkDrawColor::onEndElement(SkAnimateMaker&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 fDirty = true;
211}
212
213bool SkDrawColor::setParent(SkDisplayable* parent) {
214 SkASSERT(parent != NULL);
rileya@google.com99547762012-07-26 21:25:09 +0000215 if (parent->getType() == SkType_DrawLinearGradient || parent->getType() == SkType_DrawRadialGradient)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 return false;
217 if (parent->isPaint() == false)
218 return true;
219 fPaint = (SkDrawPaint*) parent;
220 return false;
221}
222
223bool 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229 alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000230 color = SkColorSetARGB(alpha, SkColorGetR(color),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 SkColorGetG(color), SkColorGetB(color));
232 break;
233 case SK_PROPERTY(blue):
234 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000235 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 SkColorGetG(color), SkToU8((U8CPU) scalar));
237 break;
238 case SK_PROPERTY(green):
239 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000240 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 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);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000249 color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar),
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250 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}