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 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 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 131 SkDrawColor::SkDrawColor() : fDirty(false) { 132 color = SK_ColorBLACK; 133 fHue = fSaturation = fValue = SK_ScalarNaN; 134 } 135 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 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 154 void SkDrawColor::dirty(){ 155 fDirty = true; 156 } 157 158 #ifdef SK_DUMP_ENABLED 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 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 180 SkDisplayable* SkDrawColor::getParent() const { 181 return fPaint; 182 } 183 184 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 217 void SkDrawColor::onEndElement(SkAnimateMaker& maker){ 218 fDirty = true; 219 } 220 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 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