SkDrawPath.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
1/* libs/graphics/animator/SkDrawPath.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 "SkDrawPath.h" 19#include "SkAnimateMaker.h" 20#include "SkCanvas.h" 21#include "SkMath.h" 22#include "SkMatrixParts.h" 23#include "SkPaint.h" 24#include "SkPathParts.h" 25 26enum SkPath_Properties { 27 SK_PROPERTY(fillType), 28 SK_PROPERTY(length) 29}; 30 31#if SK_USE_CONDENSED_INFO == 0 32 33const SkMemberInfo SkDrawPath::fInfo[] = { 34 SK_MEMBER(d, String), 35 SK_MEMBER_PROPERTY(fillType, FillType), 36 SK_MEMBER_PROPERTY(length, Float) 37}; 38 39#endif 40 41DEFINE_GET_MEMBER(SkDrawPath); 42 43SkDrawPath::SkDrawPath() 44{ 45 fParent = NULL; 46 fLength = SK_ScalarNaN; 47 fChildHasID = false; 48 fDirty = false; 49} 50 51SkDrawPath::~SkDrawPath() { 52 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) 53 delete *part; 54} 55 56bool SkDrawPath::add(SkAnimateMaker& maker, SkDisplayable* child) { 57 SkASSERT(child && child->isPathPart()); 58 SkPathPart* part = (SkPathPart*) child; 59 *fParts.append() = part; 60 if (part->add()) 61 maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath); 62 fDirty = false; 63 return true; 64} 65 66bool SkDrawPath::childrenNeedDisposing() const { 67 return false; 68} 69 70void SkDrawPath::dirty() { 71 fDirty = true; 72 fLength = SK_ScalarNaN; 73 if (fParent) 74 fParent->dirty(); 75} 76 77bool SkDrawPath::draw(SkAnimateMaker& maker) { 78 SkPath& path = getPath(); 79 SkBoundableAuto boundable(this, maker); 80 maker.fCanvas->drawPath(path, *maker.fPaint); 81 return false; 82} 83 84SkDisplayable* SkDrawPath::getParent() const { 85 return fParent; 86} 87 88#ifdef SK_DUMP_ENABLED 89void SkDrawPath::dump(SkAnimateMaker* maker) { 90 dumpBase(maker); 91 dumpAttrs(maker); 92 bool closedYet = false; 93 SkDisplayList::fIndent += 4; 94 for(SkPathPart** part = fParts.begin(); part < fParts.end(); part++) { 95 if (closedYet == false) { 96 SkDebugf(">\n"); 97 closedYet = true; 98 } 99 (*part)->dump(maker); 100 } 101 SkDisplayList::fIndent -= 4; 102 if (closedYet) 103 dumpEnd(maker); 104 else 105 SkDebugf("/>\n"); 106} 107#endif 108 109SkPath& SkDrawPath::getPath() { 110 if (fDirty == false) 111 return fPath; 112 if (d.size() > 0) 113 { 114 parseSVG(); 115 d.reset(); 116 } 117 else 118 { 119 fPath.reset(); 120 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) 121 (*part)->add(); 122 } 123 fDirty = false; 124 return fPath; 125} 126 127void SkDrawPath::onEndElement(SkAnimateMaker& ) { 128 if (d.size() > 0) { 129 parseSVG(); 130 d.reset(); 131 fDirty = false; 132 return; 133 } 134 if (fChildHasID == false) { 135 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) 136 delete *part; 137 fParts.reset(); 138 fDirty = false; 139 } 140} 141 142bool SkDrawPath::getProperty(int index, SkScriptValue* value) const { 143 switch (index) { 144 case SK_PROPERTY(length): 145 if (SkScalarIsNaN(fLength)) { 146 const SkPath& path = ((SkDrawPath*) this)->getPath(); 147 SkPathMeasure pathMeasure(path, false); 148 fLength = pathMeasure.getLength(); 149 } 150 value->fType = SkType_Float; 151 value->fOperand.fScalar = fLength; 152 break; 153 case SK_PROPERTY(fillType): 154 value->fType = SkType_FillType; 155 value->fOperand.fS32 = (int) fPath.getFillType(); 156 break; 157 default: 158 SkASSERT(0); 159 return false; 160 } 161 return true; 162} 163 164void SkDrawPath::setChildHasID() { 165 fChildHasID = true; 166} 167 168bool SkDrawPath::setParent(SkDisplayable* parent) { 169 fParent = parent; 170 return false; 171} 172 173bool SkDrawPath::setProperty(int index, SkScriptValue& value) 174{ 175 switch (index) { 176 case SK_PROPERTY(fillType): 177 SkASSERT(value.fType == SkType_FillType); 178 SkASSERT(value.fOperand.fS32 >= SkPath::kWinding_FillType && 179 value.fOperand.fS32 <= SkPath::kEvenOdd_FillType); 180 fPath.setFillType((SkPath::FillType) value.fOperand.fS32); 181 break; 182 default: 183 SkASSERT(0); 184 return false; 185 } 186 return true; 187} 188 189#if SK_USE_CONDENSED_INFO == 0 190 191const SkMemberInfo SkPolyline::fInfo[] = { 192 SK_MEMBER_ARRAY(points, Float) 193}; 194 195#endif 196 197DEFINE_GET_MEMBER(SkPolyline); 198 199bool SkPolyline::add(SkAnimateMaker& , SkDisplayable*) const { 200 return false; 201} 202 203void SkPolyline::onEndElement(SkAnimateMaker& maker) { 204 INHERITED::onEndElement(maker); 205 if (points.count() <= 0) 206 return; 207 fPath.reset(); 208 fPath.moveTo(points[0], points[1]); 209 int count = points.count(); 210 for (int index = 2; index < count; index += 2) 211 fPath.lineTo(points[index], points[index+1]); 212} 213 214 215#if SK_USE_CONDENSED_INFO == 0 216 217const SkMemberInfo SkPolygon::fInfo[] = { 218 SK_MEMBER_INHERITED 219}; 220 221#endif 222 223DEFINE_GET_MEMBER(SkPolygon); 224 225void SkPolygon::onEndElement(SkAnimateMaker& maker) { 226 INHERITED::onEndElement(maker); 227 fPath.close(); 228} 229 230