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