| OLD | NEW |
| (Empty) |
| 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(mak
er), 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, SkScr
iptValue* 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::kGradientOffsetsDontMatc
hColors); | |
| 137 return; | |
| 138 } | |
| 139 if (offsets[0] != 0) { | |
| 140 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStar
tWithZero); | |
| 141 return; | |
| 142 } | |
| 143 if (offsets[offsets.count()-1] != SK_Scalar1) { | |
| 144 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndW
ithOne); | |
| 145 return; | |
| 146 } | |
| 147 for (int i = 1; i < offsets.count(); i++) { | |
| 148 if (offsets[i] <= offsets[i-1]) { | |
| 149 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMust
Increase); | |
| 150 return; | |
| 151 } | |
| 152 if (offsets[i] > SK_Scalar1) { | |
| 153 maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMust
BeNoMoreThanOne); | |
| 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::kGradientPointsLengthMustBeF
our); | |
| 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::Ti
leMode) tileMode, fUnitMapper); | |
| 231 SkAutoTDelete<SkShader> autoDel(shader); | |
| 232 addPostlude(shader); | |
| 233 (void)autoDel.detach(); | |
| 234 return shader; | |
| 235 } | |
| OLD | NEW |