diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/animator/SkDrawGradient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/animator/SkDrawGradient.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,218 @@ + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "SkDrawGradient.h" +#include "SkAnimateMaker.h" +#include "SkAnimatorScript.h" +#include "SkGradientShader.h" +#include "SkUnitMapper.h" + +static SkScalar SkUnitToScalar(U16CPU x) { + return x / 65535.0f; +} + +static U16CPU SkScalarToUnit(SkScalar x) { + SkScalar pin = SkScalarPin(x, 0, SK_Scalar1); + return (int) (pin * 65535.0f); +} + +class SkDrawGradientUnitMapper : public SkUnitMapper { +public: + SkDrawGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) { + } + + SK_DECLARE_UNFLATTENABLE_OBJECT() + +protected: + virtual uint16_t mapUnit16(uint16_t x) { + fUnit = SkUnitToScalar(x); + SkScriptValue value; + SkAnimatorScript engine(*fMaker, NULL, SkType_Float); + engine.propertyCallBack(GetUnitValue, &fUnit); + if (engine.evaluate(fScript, &value, SkType_Float)) + x = SkScalarToUnit(value.fOperand.fScalar); + return x; + } + + static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("unit", token, len)) { + value->fOperand.fScalar = *(SkScalar*) unitPtr; + value->fType = SkType_Float; + return true; + } + return false; + } + + SkAnimateMaker* fMaker; + const char* fScript; + SkScalar fUnit; +}; + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER_ARRAY(offsets, Float), + SK_MEMBER(unitMapper, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawGradient); + +SkDrawGradient::SkDrawGradient() : fUnitMapper(NULL) { +} + +SkDrawGradient::~SkDrawGradient() { + for (int index = 0; index < fDrawColors.count(); index++) + delete fDrawColors[index]; + delete fUnitMapper; +} + +bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) { + SkASSERT(child); + if (child->isColor()) { + SkDrawColor* color = (SkDrawColor*) child; + *fDrawColors.append() = color; + return true; + } + return false; +} + +int SkDrawGradient::addPrelude() { + int count = fDrawColors.count(); + fColors.setCount(count); + for (int index = 0; index < count; index++) + fColors[index] = fDrawColors[index]->color; + return count; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawGradient::dumpRest(SkAnimateMaker* maker) { + dumpAttrs(maker); + //can a gradient have no colors? + bool closedYet = false; + SkDisplayList::fIndent += 4; + for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + SkDrawColor* color = *ptr; + color->dump(maker); + } + SkDisplayList::fIndent -= 4; + dumpChildren(maker, closedYet); //dumps the matrix if it has one +} +#endif + +void SkDrawGradient::onEndElement(SkAnimateMaker& maker) { + if (offsets.count() != 0) { + if (offsets.count() != fDrawColors.count()) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors); + return; + } + if (offsets[0] != 0) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero); + return; + } + if (offsets[offsets.count()-1] != SK_Scalar1) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne); + return; + } + for (int i = 1; i < offsets.count(); i++) { + if (offsets[i] <= offsets[i-1]) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease); + return; + } + if (offsets[i] > SK_Scalar1) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne); + return; + } + } + } + if (unitMapper.size() > 0) + fUnitMapper = new SkDrawGradientUnitMapper(&maker, unitMapper.c_str()); + INHERITED::onEndElement(maker); +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawLinearGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER_ARRAY(points, Float), +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawLinearGradient); + +SkDrawLinearGradient::SkDrawLinearGradient() { +} + +void SkDrawLinearGradient::onEndElement(SkAnimateMaker& maker) +{ + if (points.count() != 4) + maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour); + INHERITED::onEndElement(maker); +} + +#ifdef SK_DUMP_ENABLED +void SkDrawLinearGradient::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpRest(maker); + } +#endif + +SkShader* SkDrawLinearGradient::getShader() { + if (addPrelude() == 0 || points.count() != 4) + return NULL; + SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(), + fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); + SkAutoTDelete autoDel(shader); + addPostlude(shader); + (void)autoDel.detach(); + return shader; +} + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawRadialGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(center, Point), + SK_MEMBER(radius, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawRadialGradient); + +SkDrawRadialGradient::SkDrawRadialGradient() : radius(0) { + center.set(0, 0); +} + +#ifdef SK_DUMP_ENABLED +void SkDrawRadialGradient::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpRest(maker); +} +#endif + +SkShader* SkDrawRadialGradient::getShader() { + if (addPrelude() == 0) + return NULL; + SkShader* shader = SkGradientShader::CreateRadial(center, + radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); + SkAutoTDelete autoDel(shader); + addPostlude(shader); + (void)autoDel.detach(); + return shader; +}