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 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 : 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 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 123 SkDrawColor::SkDrawColor() : fDirty(false) { 124 color = SK_ColorBLACK; 125 fHue = fSaturation = fValue = SK_ScalarNaN; 126 } 127 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 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 146 void SkDrawColor::dirty(){ 147 fDirty = true; 148 } 149 150 #ifdef SK_DUMP_ENABLED 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 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 172 SkDisplayable* SkDrawColor::getParent() const { 173 return fPaint; 174 } 175 176 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 209 void SkDrawColor::onEndElement(SkAnimateMaker&) { 210 fDirty = true; 211 } 212 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 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