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