/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkDrawPath.h" #include "SkAnimateMaker.h" #include "SkCanvas.h" #include "SkMath.h" #include "SkMatrixParts.h" #include "SkPaint.h" #include "SkPathParts.h" enum SkPath_Properties { SK_PROPERTY(fillType), SK_PROPERTY(length) }; #if SK_USE_CONDENSED_INFO == 0 const SkMemberInfo SkDrawPath::fInfo[] = { SK_MEMBER(d, String), SK_MEMBER_PROPERTY(fillType, FillType), SK_MEMBER_PROPERTY(length, Float) }; #endif DEFINE_GET_MEMBER(SkDrawPath); SkDrawPath::SkDrawPath() { fParent = NULL; fLength = SK_ScalarNaN; fChildHasID = false; fDirty = false; } SkDrawPath::~SkDrawPath() { for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) delete *part; } bool SkDrawPath::addChild(SkAnimateMaker& maker, SkDisplayable* child) { SkASSERT(child && child->isPathPart()); SkPathPart* part = (SkPathPart*) child; *fParts.append() = part; if (part->add()) maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath); fDirty = false; return true; } bool SkDrawPath::childrenNeedDisposing() const { return false; } void SkDrawPath::dirty() { fDirty = true; fLength = SK_ScalarNaN; if (fParent) fParent->dirty(); } bool SkDrawPath::draw(SkAnimateMaker& maker) { SkPath& path = getPath(); SkBoundableAuto boundable(this, maker); maker.fCanvas->drawPath(path, *maker.fPaint); return false; } SkDisplayable* SkDrawPath::getParent() const { return fParent; } #ifdef SK_DUMP_ENABLED void SkDrawPath::dump(SkAnimateMaker* maker) { dumpBase(maker); dumpAttrs(maker); bool closedYet = false; SkDisplayList::fIndent += 4; for(SkPathPart** part = fParts.begin(); part < fParts.end(); part++) { if (closedYet == false) { SkDebugf(">\n"); closedYet = true; } (*part)->dump(maker); } SkDisplayList::fIndent -= 4; if (closedYet) dumpEnd(maker); else SkDebugf("/>\n"); } #endif SkPath& SkDrawPath::getPath() { if (fDirty == false) return fPath; if (d.size() > 0) { parseSVG(); d.reset(); } else { fPath.reset(); for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) (*part)->add(); } fDirty = false; return fPath; } void SkDrawPath::onEndElement(SkAnimateMaker& ) { if (d.size() > 0) { parseSVG(); d.reset(); fDirty = false; return; } if (fChildHasID == false) { for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) delete *part; fParts.reset(); fDirty = false; } } bool SkDrawPath::getProperty(int index, SkScriptValue* value) const { switch (index) { case SK_PROPERTY(length): if (SkScalarIsNaN(fLength)) { const SkPath& path = ((SkDrawPath*) this)->getPath(); SkPathMeasure pathMeasure(path, false); fLength = pathMeasure.getLength(); } value->fType = SkType_Float; value->fOperand.fScalar = fLength; break; case SK_PROPERTY(fillType): value->fType = SkType_FillType; value->fOperand.fS32 = (int) fPath.getFillType(); break; default: SkASSERT(0); return false; } return true; } void SkDrawPath::setChildHasID() { fChildHasID = true; } bool SkDrawPath::setParent(SkDisplayable* parent) { fParent = parent; return false; } bool SkDrawPath::setProperty(int index, SkScriptValue& value) { switch (index) { case SK_PROPERTY(fillType): SkASSERT(value.fType == SkType_FillType); SkASSERT(value.fOperand.fS32 >= SkPath::kWinding_FillType && value.fOperand.fS32 <= SkPath::kEvenOdd_FillType); fPath.setFillType((SkPath::FillType) value.fOperand.fS32); break; default: SkASSERT(0); return false; } return true; } #if SK_USE_CONDENSED_INFO == 0 const SkMemberInfo SkPolyline::fInfo[] = { SK_MEMBER_ARRAY(points, Float) }; #endif DEFINE_GET_MEMBER(SkPolyline); bool SkPolyline::addChild(SkAnimateMaker& , SkDisplayable*) { return false; } void SkPolyline::onEndElement(SkAnimateMaker& maker) { INHERITED::onEndElement(maker); if (points.count() <= 0) return; fPath.reset(); fPath.moveTo(points[0], points[1]); int count = points.count(); for (int index = 2; index < count; index += 2) fPath.lineTo(points[index], points[index+1]); } #if SK_USE_CONDENSED_INFO == 0 const SkMemberInfo SkPolygon::fInfo[] = { SK_MEMBER_INHERITED }; #endif DEFINE_GET_MEMBER(SkPolygon); void SkPolygon::onEndElement(SkAnimateMaker& maker) { INHERITED::onEndElement(maker); fPath.close(); }