1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/animator/SkDrawGradient.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,218 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkDrawGradient.h" 1.14 +#include "SkAnimateMaker.h" 1.15 +#include "SkAnimatorScript.h" 1.16 +#include "SkGradientShader.h" 1.17 +#include "SkUnitMapper.h" 1.18 + 1.19 +static SkScalar SkUnitToScalar(U16CPU x) { 1.20 + return x / 65535.0f; 1.21 +} 1.22 + 1.23 +static U16CPU SkScalarToUnit(SkScalar x) { 1.24 + SkScalar pin = SkScalarPin(x, 0, SK_Scalar1); 1.25 + return (int) (pin * 65535.0f); 1.26 +} 1.27 + 1.28 +class SkDrawGradientUnitMapper : public SkUnitMapper { 1.29 +public: 1.30 + SkDrawGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) { 1.31 + } 1.32 + 1.33 + SK_DECLARE_UNFLATTENABLE_OBJECT() 1.34 + 1.35 +protected: 1.36 + virtual uint16_t mapUnit16(uint16_t x) { 1.37 + fUnit = SkUnitToScalar(x); 1.38 + SkScriptValue value; 1.39 + SkAnimatorScript engine(*fMaker, NULL, SkType_Float); 1.40 + engine.propertyCallBack(GetUnitValue, &fUnit); 1.41 + if (engine.evaluate(fScript, &value, SkType_Float)) 1.42 + x = SkScalarToUnit(value.fOperand.fScalar); 1.43 + return x; 1.44 + } 1.45 + 1.46 + static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) { 1.47 + if (SK_LITERAL_STR_EQUAL("unit", token, len)) { 1.48 + value->fOperand.fScalar = *(SkScalar*) unitPtr; 1.49 + value->fType = SkType_Float; 1.50 + return true; 1.51 + } 1.52 + return false; 1.53 + } 1.54 + 1.55 + SkAnimateMaker* fMaker; 1.56 + const char* fScript; 1.57 + SkScalar fUnit; 1.58 +}; 1.59 + 1.60 + 1.61 +#if SK_USE_CONDENSED_INFO == 0 1.62 + 1.63 +const SkMemberInfo SkDrawGradient::fInfo[] = { 1.64 + SK_MEMBER_INHERITED, 1.65 + SK_MEMBER_ARRAY(offsets, Float), 1.66 + SK_MEMBER(unitMapper, String) 1.67 +}; 1.68 + 1.69 +#endif 1.70 + 1.71 +DEFINE_GET_MEMBER(SkDrawGradient); 1.72 + 1.73 +SkDrawGradient::SkDrawGradient() : fUnitMapper(NULL) { 1.74 +} 1.75 + 1.76 +SkDrawGradient::~SkDrawGradient() { 1.77 + for (int index = 0; index < fDrawColors.count(); index++) 1.78 + delete fDrawColors[index]; 1.79 + delete fUnitMapper; 1.80 +} 1.81 + 1.82 +bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) { 1.83 + SkASSERT(child); 1.84 + if (child->isColor()) { 1.85 + SkDrawColor* color = (SkDrawColor*) child; 1.86 + *fDrawColors.append() = color; 1.87 + return true; 1.88 + } 1.89 + return false; 1.90 +} 1.91 + 1.92 +int SkDrawGradient::addPrelude() { 1.93 + int count = fDrawColors.count(); 1.94 + fColors.setCount(count); 1.95 + for (int index = 0; index < count; index++) 1.96 + fColors[index] = fDrawColors[index]->color; 1.97 + return count; 1.98 +} 1.99 + 1.100 +#ifdef SK_DUMP_ENABLED 1.101 +void SkDrawGradient::dumpRest(SkAnimateMaker* maker) { 1.102 + dumpAttrs(maker); 1.103 + //can a gradient have no colors? 1.104 + bool closedYet = false; 1.105 + SkDisplayList::fIndent += 4; 1.106 + for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) { 1.107 + if (closedYet == false) { 1.108 + SkDebugf(">\n"); 1.109 + closedYet = true; 1.110 + } 1.111 + SkDrawColor* color = *ptr; 1.112 + color->dump(maker); 1.113 + } 1.114 + SkDisplayList::fIndent -= 4; 1.115 + dumpChildren(maker, closedYet); //dumps the matrix if it has one 1.116 +} 1.117 +#endif 1.118 + 1.119 +void SkDrawGradient::onEndElement(SkAnimateMaker& maker) { 1.120 + if (offsets.count() != 0) { 1.121 + if (offsets.count() != fDrawColors.count()) { 1.122 + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors); 1.123 + return; 1.124 + } 1.125 + if (offsets[0] != 0) { 1.126 + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero); 1.127 + return; 1.128 + } 1.129 + if (offsets[offsets.count()-1] != SK_Scalar1) { 1.130 + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne); 1.131 + return; 1.132 + } 1.133 + for (int i = 1; i < offsets.count(); i++) { 1.134 + if (offsets[i] <= offsets[i-1]) { 1.135 + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease); 1.136 + return; 1.137 + } 1.138 + if (offsets[i] > SK_Scalar1) { 1.139 + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne); 1.140 + return; 1.141 + } 1.142 + } 1.143 + } 1.144 + if (unitMapper.size() > 0) 1.145 + fUnitMapper = new SkDrawGradientUnitMapper(&maker, unitMapper.c_str()); 1.146 + INHERITED::onEndElement(maker); 1.147 +} 1.148 + 1.149 +#if SK_USE_CONDENSED_INFO == 0 1.150 + 1.151 +const SkMemberInfo SkDrawLinearGradient::fInfo[] = { 1.152 + SK_MEMBER_INHERITED, 1.153 + SK_MEMBER_ARRAY(points, Float), 1.154 +}; 1.155 + 1.156 +#endif 1.157 + 1.158 +DEFINE_GET_MEMBER(SkDrawLinearGradient); 1.159 + 1.160 +SkDrawLinearGradient::SkDrawLinearGradient() { 1.161 +} 1.162 + 1.163 +void SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker) 1.164 +{ 1.165 + if (points.count() != 4) 1.166 + maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour); 1.167 + INHERITED::onEndElement(maker); 1.168 +} 1.169 + 1.170 +#ifdef SK_DUMP_ENABLED 1.171 +void SkDrawLinearGradient::dump(SkAnimateMaker* maker) { 1.172 + dumpBase(maker); 1.173 + dumpRest(maker); 1.174 + } 1.175 +#endif 1.176 + 1.177 +SkShader* SkDrawLinearGradient::getShader() { 1.178 + if (addPrelude() == 0 || points.count() != 4) 1.179 + return NULL; 1.180 + SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(), 1.181 + fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); 1.182 + SkAutoTDelete<SkShader> autoDel(shader); 1.183 + addPostlude(shader); 1.184 + (void)autoDel.detach(); 1.185 + return shader; 1.186 +} 1.187 + 1.188 + 1.189 +#if SK_USE_CONDENSED_INFO == 0 1.190 + 1.191 +const SkMemberInfo SkDrawRadialGradient::fInfo[] = { 1.192 + SK_MEMBER_INHERITED, 1.193 + SK_MEMBER(center, Point), 1.194 + SK_MEMBER(radius, Float) 1.195 +}; 1.196 + 1.197 +#endif 1.198 + 1.199 +DEFINE_GET_MEMBER(SkDrawRadialGradient); 1.200 + 1.201 +SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) { 1.202 + center.set(0, 0); 1.203 +} 1.204 + 1.205 +#ifdef SK_DUMP_ENABLED 1.206 +void SkDrawRadialGradient::dump(SkAnimateMaker* maker) { 1.207 + dumpBase(maker); 1.208 + dumpRest(maker); 1.209 +} 1.210 +#endif 1.211 + 1.212 +SkShader* SkDrawRadialGradient::getShader() { 1.213 + if (addPrelude() == 0) 1.214 + return NULL; 1.215 + SkShader* shader = SkGradientShader::CreateRadial(center, 1.216 + radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); 1.217 + SkAutoTDelete<SkShader> autoDel(shader); 1.218 + addPostlude(shader); 1.219 + (void)autoDel.detach(); 1.220 + return shader; 1.221 +}