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