Home | History | Annotate | Download | only in animator
      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