| epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 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 |  | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 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::add(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::add(SkAnimateMaker& , SkDisplayable*) const { | 
 | 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 |  |