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