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 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 = 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 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 123SkDrawColor::SkDrawColor() : fDirty(false) { 124 color = SK_ColorBLACK; 125 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 136SkDisplayable* 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 146void SkDrawColor::dirty(){ 147 fDirty = true; 148} 149 150#ifdef SK_DUMP_ENABLED 151void 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 159SkColor 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 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 209void SkDrawColor::onEndElement(SkAnimateMaker&) { 210 fDirty = true; 211} 212 213bool 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 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; 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