/* libs/graphics/animator/SkDrawPath.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#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::add(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::add(SkAnimateMaker& , SkDisplayable*) const {
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();
}