1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawPath.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAnimateMaker.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMath.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrixParts.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathParts.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum SkPath_Properties {
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_PROPERTY(fillType),
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_PROPERTY(length)
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkDrawPath::fInfo[] = {
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(d, String),
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_PROPERTY(fillType, FillType),
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_PROPERTY(length, Float)
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkDrawPath);
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawPath::SkDrawPath()
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fParent = NULL;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLength = SK_ScalarNaN;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fChildHasID = false;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDirty = false;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawPath::~SkDrawPath() {
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        delete *part;
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
481d3c411f5e4d2ad31bc92b3a85957004329ac00dtfarina@chromium.orgbool SkDrawPath::addChild(SkAnimateMaker& maker, SkDisplayable* child) {
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(child && child->isPathPart());
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathPart* part = (SkPathPart*) child;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *fParts.append() = part;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (part->add())
53d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDirty = false;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkDrawPath::childrenNeedDisposing() const {
59d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    return false;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comvoid SkDrawPath::dirty() {
63d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    fDirty = true;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLength = SK_ScalarNaN;
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fParent)
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fParent->dirty();
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDrawPath::draw(SkAnimateMaker& maker) {
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPath& path = getPath();
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBoundableAuto boundable(this, maker);
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    maker.fCanvas->drawPath(path, *maker.fPaint);
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDisplayable* SkDrawPath::getParent() const {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fParent;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDrawPath::dump(SkAnimateMaker* maker) {
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpAttrs(maker);
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool closedYet = false;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent += 4;
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for(SkPathPart** part = fParts.begin(); part < fParts.end(); part++) {
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (closedYet == false) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(">\n");
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            closedYet = true;
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (*part)->dump(maker);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent -= 4;
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (closedYet)
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dumpEnd(maker);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("/>\n");
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkPath& SkDrawPath::getPath() {
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDirty == false)
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fPath;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (d.size() > 0)
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        parseSVG();
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        d.reset();
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPath.reset();
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (*part)->add();
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDirty = false;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fPath;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
118d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDrawPath::onEndElement(SkAnimateMaker& ) {
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (d.size() > 0) {
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        parseSVG();
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        d.reset();
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDirty = false;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fChildHasID == false) {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (SkPathPart** part = fParts.begin(); part < fParts.end();  part++)
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            delete *part;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fParts.reset();
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDirty = false;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDrawPath::getProperty(int index, SkScriptValue* value) const {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (index) {
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SK_PROPERTY(length):
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (SkScalarIsNaN(fLength)) {
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkPath& path = ((SkDrawPath*) this)->getPath();
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkPathMeasure pathMeasure(path, false);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fLength = pathMeasure.getLength();
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fType = SkType_Float;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fOperand.fScalar = fLength;
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SK_PROPERTY(fillType):
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fType = SkType_FillType;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            value->fOperand.fS32 = (int) fPath.getFillType();
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(0);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
156d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comvoid SkDrawPath::setChildHasID() {
157d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    fChildHasID = true;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDrawPath::setParent(SkDisplayable* parent) {
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fParent = parent;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDrawPath::setProperty(int index, SkScriptValue& value)
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (index) {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SK_PROPERTY(fillType):
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(value.fType == SkType_FillType);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(value.fOperand.fS32 >= SkPath::kWinding_FillType &&
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                value.fOperand.fS32 <= SkPath::kEvenOdd_FillType);
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPath.setFillType((SkPath::FillType) value.fOperand.fS32);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(0);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkPolyline::fInfo[] = {
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_ARRAY(points, Float)
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkPolyline);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1911d3c411f5e4d2ad31bc92b3a85957004329ac00dtfarina@chromium.orgbool SkPolyline::addChild(SkAnimateMaker& , SkDisplayable*) {
192d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    return false;
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPolyline::onEndElement(SkAnimateMaker& maker) {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (points.count() <= 0)
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPath.reset();
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPath.moveTo(points[0], points[1]);
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = points.count();
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int index = 2; index < count; index += 2)
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPath.lineTo(points[index], points[index+1]);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkPolygon::fInfo[] = {
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkPolygon);
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkPolygon::onEndElement(SkAnimateMaker& maker) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::onEndElement(maker);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPath.close();
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
221