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 "SkDrawGradient.h"
     11 #include "SkAnimateMaker.h"
     12 #include "SkAnimatorScript.h"
     13 #include "SkGradientShader.h"
     14 #include "SkUnitMapper.h"
     15 
     16 SkScalar SkUnitToScalar(U16CPU x) {
     17 #ifdef SK_SCALAR_IS_FLOAT
     18     return x / 65535.0f;
     19 #else
     20     return x + (x >> 8);
     21 #endif
     22 }
     23 
     24 U16CPU SkScalarToUnit(SkScalar x) {
     25     SkScalar pin =  SkScalarPin(x, 0, SK_Scalar1);
     26 #ifdef SK_SCALAR_IS_FLOAT
     27     return (int) (pin * 65535.0f);
     28 #else
     29     return pin - (pin >= 32768);
     30 #endif
     31 }
     32 
     33 class SkGradientUnitMapper : public SkUnitMapper {
     34 public:
     35     SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
     36     }
     37 
     38     // overrides for SkFlattenable
     39     virtual Factory getFactory() { return NULL; }
     40 
     41 protected:
     42     virtual uint16_t mapUnit16(uint16_t x) {
     43         fUnit = SkUnitToScalar(x);
     44         SkScriptValue value;
     45         SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
     46         engine.propertyCallBack(GetUnitValue, &fUnit);
     47         if (engine.evaluate(fScript, &value, SkType_Float))
     48             x = SkScalarToUnit(value.fOperand.fScalar);
     49         return x;
     50     }
     51 
     52     static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) {
     53         if (SK_LITERAL_STR_EQUAL("unit", token, len)) {
     54             value->fOperand.fScalar = *(SkScalar*) unitPtr;
     55             value->fType = SkType_Float;
     56             return true;
     57         }
     58         return false;
     59     }
     60 
     61     SkAnimateMaker* fMaker;
     62     const char* fScript;
     63     SkScalar fUnit;
     64 };
     65 
     66 
     67 #if SK_USE_CONDENSED_INFO == 0
     68 
     69 const SkMemberInfo SkGradient::fInfo[] = {
     70     SK_MEMBER_INHERITED,
     71     SK_MEMBER_ARRAY(offsets, Float),
     72     SK_MEMBER(unitMapper, String)
     73 };
     74 
     75 #endif
     76 
     77 DEFINE_GET_MEMBER(SkGradient);
     78 
     79 SkGradient::SkGradient() : fUnitMapper(NULL) {
     80 }
     81 
     82 SkGradient::~SkGradient() {
     83     for (int index = 0; index < fDrawColors.count(); index++)
     84         delete fDrawColors[index];
     85     delete fUnitMapper;
     86 }
     87 
     88 bool SkGradient::add(SkAnimateMaker& , SkDisplayable* child) {
     89     SkASSERT(child);
     90     if (child->isColor()) {
     91         SkDrawColor* color = (SkDrawColor*) child;
     92         *fDrawColors.append() = color;
     93         return true;
     94     }
     95     return false;
     96 }
     97 
     98 int SkGradient::addPrelude() {
     99     int count = fDrawColors.count();
    100     fColors.setCount(count);
    101     for (int index = 0; index < count; index++)
    102         fColors[index] = fDrawColors[index]->color;
    103     return count;
    104 }
    105 
    106 #ifdef SK_DUMP_ENABLED
    107 void SkGradient::dumpRest(SkAnimateMaker* maker) {
    108     dumpAttrs(maker);
    109     //can a gradient have no colors?
    110     bool closedYet = false;
    111     SkDisplayList::fIndent += 4;
    112     for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) {
    113         if (closedYet == false) {
    114             SkDebugf(">\n");
    115             closedYet = true;
    116         }
    117         SkDrawColor* color = *ptr;
    118         color->dump(maker);
    119     }
    120     SkDisplayList::fIndent -= 4;
    121     dumpChildren(maker, closedYet); //dumps the matrix if it has one
    122 }
    123 #endif
    124 
    125 void SkGradient::onEndElement(SkAnimateMaker& maker) {
    126     if (offsets.count() != 0) {
    127         if (offsets.count() != fDrawColors.count()) {
    128             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors);
    129             return;
    130         }
    131         if (offsets[0] != 0) {
    132             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero);
    133             return;
    134         }
    135         if (offsets[offsets.count()-1] != SK_Scalar1) {
    136             maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne);
    137             return;
    138         }
    139         for (int i = 1; i < offsets.count(); i++) {
    140             if (offsets[i] <= offsets[i-1]) {
    141                 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease);
    142                 return;
    143             }
    144             if (offsets[i] > SK_Scalar1) {
    145                 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne);
    146                 return;
    147             }
    148         }
    149     }
    150     if (unitMapper.size() > 0)
    151         fUnitMapper = new SkGradientUnitMapper(&maker, unitMapper.c_str());
    152     INHERITED::onEndElement(maker);
    153 }
    154 
    155 #if SK_USE_CONDENSED_INFO == 0
    156 
    157 const SkMemberInfo SkLinearGradient::fInfo[] = {
    158     SK_MEMBER_INHERITED,
    159     SK_MEMBER_ARRAY(points, Float),
    160 };
    161 
    162 #endif
    163 
    164 DEFINE_GET_MEMBER(SkLinearGradient);
    165 
    166 SkLinearGradient::SkLinearGradient() {
    167 }
    168 
    169 void SkLinearGradient::onEndElement(SkAnimateMaker& maker)
    170 {
    171     if (points.count() != 4)
    172         maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour);
    173     INHERITED::onEndElement(maker);
    174 }
    175 
    176 #ifdef SK_DUMP_ENABLED
    177 void SkLinearGradient::dump(SkAnimateMaker* maker) {
    178     dumpBase(maker);
    179     dumpRest(maker);
    180     }
    181 #endif
    182 
    183 SkShader* SkLinearGradient::getShader() {
    184     if (addPrelude() == 0 || points.count() != 4)
    185         return NULL;
    186     SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
    187         fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
    188     SkAutoTDelete<SkShader> autoDel(shader);
    189     addPostlude(shader);
    190     (void)autoDel.detach();
    191     return shader;
    192 }
    193 
    194 
    195 #if SK_USE_CONDENSED_INFO == 0
    196 
    197 const SkMemberInfo SkRadialGradient::fInfo[] = {
    198     SK_MEMBER_INHERITED,
    199     SK_MEMBER(center, Point),
    200     SK_MEMBER(radius, Float)
    201 };
    202 
    203 #endif
    204 
    205 DEFINE_GET_MEMBER(SkRadialGradient);
    206 
    207 SkRadialGradient::SkRadialGradient() : radius(0) {
    208     center.set(0, 0);
    209 }
    210 
    211 #ifdef SK_DUMP_ENABLED
    212 void SkRadialGradient::dump(SkAnimateMaker* maker) {
    213     dumpBase(maker);
    214     dumpRest(maker);
    215 }
    216 #endif
    217 
    218 SkShader* SkRadialGradient::getShader() {
    219     if (addPrelude() == 0)
    220         return NULL;
    221     SkShader* shader = SkGradientShader::CreateRadial(center,
    222         radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
    223     SkAutoTDelete<SkShader> autoDel(shader);
    224     addPostlude(shader);
    225     (void)autoDel.detach();
    226     return shader;
    227 }
    228