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 26 enum SkPath_Properties { 27 SK_PROPERTY(fillType), 28 SK_PROPERTY(length) 29 }; 30 31 #if SK_USE_CONDENSED_INFO == 0 32 33 const 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 41 DEFINE_GET_MEMBER(SkDrawPath); 42 43 SkDrawPath::SkDrawPath() 44 { 45 fParent = NULL; 46 fLength = SK_ScalarNaN; 47 fChildHasID = false; 48 fDirty = false; 49 } 50 51 SkDrawPath::~SkDrawPath() { 52 for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) 53 delete *part; 54 } 55 56 bool 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 66 bool SkDrawPath::childrenNeedDisposing() const { 67 return false; 68 } 69 70 void SkDrawPath::dirty() { 71 fDirty = true; 72 fLength = SK_ScalarNaN; 73 if (fParent) 74 fParent->dirty(); 75 } 76 77 bool 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 84 SkDisplayable* SkDrawPath::getParent() const { 85 return fParent; 86 } 87 88 #ifdef SK_DUMP_ENABLED 89 void 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 109 SkPath& 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 127 void 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 142 bool 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 164 void SkDrawPath::setChildHasID() { 165 fChildHasID = true; 166 } 167 168 bool SkDrawPath::setParent(SkDisplayable* parent) { 169 fParent = parent; 170 return false; 171 } 172 173 bool 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 191 const SkMemberInfo SkPolyline::fInfo[] = { 192 SK_MEMBER_ARRAY(points, Float) 193 }; 194 195 #endif 196 197 DEFINE_GET_MEMBER(SkPolyline); 198 199 bool SkPolyline::add(SkAnimateMaker& , SkDisplayable*) const { 200 return false; 201 } 202 203 void 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 217 const SkMemberInfo SkPolygon::fInfo[] = { 218 SK_MEMBER_INHERITED 219 }; 220 221 #endif 222 223 DEFINE_GET_MEMBER(SkPolygon); 224 225 void SkPolygon::onEndElement(SkAnimateMaker& maker) { 226 INHERITED::onEndElement(maker); 227 fPath.close(); 228 } 229 230