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 = 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)); 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), SkScalarRound(red), 89 SkScalarRound(green), SkScalarRound(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 #ifdef SK_SCALAR_IS_FLOAT 230 alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256)); 231 #else 232 alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8); 233 #endif 234 color = SkColorSetARGB(alpha, SkColorGetR(color), 235 SkColorGetG(color), SkColorGetB(color)); 236 break; 237 case SK_PROPERTY(blue): 238 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); 239 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), 240 SkColorGetG(color), SkToU8((U8CPU) scalar)); 241 break; 242 case SK_PROPERTY(green): 243 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); 244 color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), 245 SkToU8((U8CPU) scalar), SkColorGetB(color)); 246 break; 247 case SK_PROPERTY(hue): 248 fHue = scalar;//RGB_to_HSV(color, kGetHue); 249 fDirty = true; 250 break; 251 case SK_PROPERTY(red): 252 scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); 253 color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar), 254 SkColorGetG(color), SkColorGetB(color)); 255 break; 256 case SK_PROPERTY(saturation): 257 fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation); 258 fDirty = true; 259 break; 260 case SK_PROPERTY(value): 261 fValue = scalar;//RGB_to_HSV(color, kGetValue); 262 fDirty = true; 263 break; 264 default: 265 SkASSERT(0); 266 return false; 267 } 268 return true; 269 } 270