180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGParser.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGCircle.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGClipPath.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGDefs.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGEllipse.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGFeColorMatrix.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGFilter.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGG.h"
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGImage.h"
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGLine.h"
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGLinearGradient.h"
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGMask.h"
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGMetadata.h"
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGPath.h"
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGPolygon.h"
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGPolyline.h"
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGRadialGradient.h"
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGRect.h"
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGSVG.h"
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGStop.h"
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGSymbol.h"
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGText.h"
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSVGUse.h"
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTSearch.h"
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdio.h>
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int gGeneratedMatrixID = 0;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkSVGParser::SkSVGParser(SkXMLParserError* errHandler) :
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXMLParser(errHandler),
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fHead(&fEmptyPaint), fIDs(256),
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fXMLWriter(&fStream), fCurrElement(NULL), fInSVG(false), fSuppressPaint(false) {
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fLastTransform.reset();
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.f_fill.set("black");
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.f_stroke.set("none");
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.f_strokeMiterlimit.set("4");
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.f_fillRule.set("winding");
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.f_opacity.set("1");
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fEmptyPaint.fNext = NULL;
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int index = SkSVGPaint::kInitial + 1; index < SkSVGPaint::kTerminal; index++) {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString* initial = fEmptyPaint[index];
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (initial->size() == 0)
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fLastFlush[index]->set(*initial);
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkSVGParser::~SkSVGParser() {
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) {
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGElement** ptr;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Delete((*ptr)->fChildren);
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete *ptr;
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkSVGParser::findAttribute(SkSVGBase* element, const char* attrValue,
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t len, bool isPaint) {
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkSVGAttribute* attributes;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t count = element->getAttributes(&attributes);
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t result = 0;
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (result < count) {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (strncmp(attributes->fName, attrValue, len) == 0 && strlen(attributes->fName) == len) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(result == (attributes->fOffset -
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                (isPaint ? sizeof(SkString) : sizeof(SkSVGElement))) / sizeof(SkString));
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return result;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        attributes++;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result++;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return -1;
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkSVGParser::getFinal() {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _startElement("screenplay");
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // generate defs
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGElement** ptr;
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSVGElement* element = *ptr;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        translate(element, true);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // generate onLoad
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _startElement("event");
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _addAttribute("kind", "onLoad");
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _startElement("paint");
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _addAttribute("antiAlias", "true");
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _endElement();
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSVGElement* element = *ptr;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        translate(element, false);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _endElement(); // event
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _endElement(); // screenplay
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Delete(fChildren);
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStream.write("", 1);
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fStream.getStream();
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGPaint* state = fHead;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString* attr = (*state)[field];
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(attr);
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (attr->size() > 0)
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return *attr;
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        state = state->fNext;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (state);
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0);
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fEmptyPaint[field]);
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *fEmptyPaint[field];
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::isStrokeAndFill(  SkSVGPaint** strokeState, SkSVGPaint** fillState) {
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGPaint* walking = fHead;
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool stroke = false;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool fill = false;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool strokeSet = false;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool fillSet = false;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (walking != NULL) {
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (strokeSet == false && walking->f_stroke.size() > 0) {
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            stroke = walking->f_stroke.equals("none") == false;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *strokeState = walking;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            strokeSet = true;
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fillSet == false && walking->f_fill.size() > 0) {
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fill = walking->f_fill.equals("none") == false;
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fillState = walking;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fillSet = true;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        walking = walking->fNext;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return stroke && fill;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onAddAttribute(const char name[], const char value[]) {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return onAddAttributeLen(name, value, strlen(value));
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onAddAttributeLen(const char name[], const char value[], size_t len) {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fCurrElement == NULL)    // this signals we should ignore attributes for this element
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fCurrElement->fIsDef == false && fCurrElement->fIsNotDef == false)
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false; // also an ignored element
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t nameLen = strlen(name);
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int attrIndex = findAttribute(fCurrElement, name, nameLen, false);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (attrIndex == -1) {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        attrIndex = findAttribute(&fCurrElement->fPaintState, name, nameLen, true);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (attrIndex >= 0) {
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fCurrElement->fPaintState.addAttribute(*this, attrIndex, value, len);
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (nameLen == 2 && strncmp("id", name, nameLen) == 0) {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fCurrElement->f_id.set(value, len);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (strchr(name, ':') != 0) // part of a different namespace
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(attrIndex >= 0);
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCurrElement->addAttribute(*this, attrIndex, value, len);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onEndElement(const char elem[]) {
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int parentIndex = fParents.count() - 1;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (parentIndex >= 0) {
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSVGElement* element = fParents[parentIndex];
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->onEndElement(*this);
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fParents.remove(parentIndex);
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onStartElement(const char name[]) {
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return onStartElementLen(name, strlen(name));
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onStartElementLen(const char name[], size_t len) {
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (strncmp(name, "svg", len) == 0) {
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fInSVG = true;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (fInSVG == false)
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* nextColon = strchr(name, ':');
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (nextColon && (size_t)(nextColon - name) < len)
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGTypes type = GetType(name, len);
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    SkASSERT(type >= 0);
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type < 0) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        type = SkSVGType_G;
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//        return true;
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGElement* parent = fParents.count() > 0 ? fParents.top() : NULL;
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGElement* element = CreateElement(type, parent);
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool result = false;
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (parent) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->fParent = parent;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        result = fParents.top()->onStartElement(element);
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fChildren.append() = element;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (strncmp(name, "svg", len) != 0)
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fParents.append() = element;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCurrElement = element;
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkSVGParser::onText(const char text[], int len) {
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fInSVG == false)
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGTypes type = fCurrElement->getType();
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type != SkSVGType_Text && type != SkSVGType_Tspan)
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGText* textElement = (SkSVGText*) fCurrElement;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    textElement->f_text.set(text, len);
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int32_t strokeFillID = 0;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSVGParser::translate(SkSVGElement* element, bool isDef) {
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGPaint::Push(&fHead, &element->fPaintState);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isFlushable = element->isFlushable();
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((element->fIsDef == false && element->fIsNotDef == false) ||
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (element->fIsDef && isDef == false && element->fIsNotDef == false) ||
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (element->fIsDef == false && isDef && element->fIsNotDef)) {
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        isFlushable = false;
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGPaint* strokeState = NULL, * fillState = NULL;
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (isFlushable)
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->fPaintState.setSave(*this);
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (isFlushable && isStrokeAndFill(&strokeState, &fillState)) {
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString& elementID = element->f_id;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (elementID.size() == 0) {
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            elementID.set("sf");
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            elementID.appendS32(++strokeFillID);
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString saveStroke(strokeState->f_stroke);
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString saveFill(fillState->f_fill);
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        strokeState->f_stroke.set("none");
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->fPaintState.flush(*this, isFlushable, isDef);
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->translate(*this, isDef);
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        strokeState->f_stroke.set(saveStroke);
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fillState->f_fill.set("none");
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (element->fPaintState.flush(*this, isFlushable, isDef)) {
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            _startElement("add");
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            _addAttributeLen("use", elementID.c_str(), elementID.size());
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            _endElement();  // add
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fillState->f_fill.set(saveFill);
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        element->fPaintState.flush(*this, isFlushable, isDef);
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (isFlushable || element->isGroup())
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            element->translate(*this, isDef);
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGPaint::Pop(&fHead);
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSVGParser::translateMatrix(SkString& string, SkString* stringID) {
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (string.size() == 0)
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (stringID->size() > 0) {
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        _startElement("add");
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        _addAttribute("use", stringID->c_str());
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        _endElement(); // add
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(strncmp(string.c_str(), "matrix", 6) == 0);
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ++gGeneratedMatrixID;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _startElement("matrix");
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char idStr[24];
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    strcpy(idStr, "sk_matrix");
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sprintf(idStr + strlen(idStr), "%d", gGeneratedMatrixID);
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _addAttribute("id", idStr);
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    stringID->set(idStr);
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* str = string.c_str();
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(strncmp(str, "matrix(", 7) == 0);
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str += 6;
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* strEnd = strrchr(str, ')');
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(strEnd != NULL);
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString mat(str, strEnd - str);
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ConvertToArray(mat);
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* elems[6];
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int order[] = {0, 3, 1, 4, 2, 5};
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int* orderPtr = order;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str = mat.c_str();
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    strEnd = str + mat.size();
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (str < strEnd) {
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        elems[*orderPtr++] = str;
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (str < strEnd && *str != ',' )
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            str++;
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str++;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    string.reset();
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int index = 0; index < 6; index++) {
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* end = strchr(elems[index], ',');
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (end == NULL)
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            end= strchr(elems[index], ']');
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        string.append(elems[index], end - elems[index] + 1);
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    string.remove(string.size() - 1, 1);
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    string.append(",0,0,1]");
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _addAttribute("matrix", string);
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    _endElement();  // matrix
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool is_whitespace(char ch) {
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return ch > 0 && ch <= ' ';
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSVGParser::ConvertToArray(SkString& vals) {
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    vals.appendUnichar(']');
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* valCh = (char*) vals.c_str();
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    valCh[0] = '[';
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int index = 1;
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (valCh[index] != ']') {
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (is_whitespace(valCh[index]))
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            index++;
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool foundComma = false;
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char next;
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            next = valCh[index++];
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (next == ',') {
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                foundComma = true;
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (next == ']') {
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                index--;
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto undoLastComma;
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (next == ' ')
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            foundComma = false;
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (is_whitespace(next) == false);
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (foundComma == false)
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            valCh[index - 1] = ',';
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruundoLastComma:
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_whitespace(valCh[--index]))
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ;
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (valCh[index] == ',')
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        valCh[index] = ' ';
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define CASE_NEW(type) case SkSVGType_##type : created = new SkSVG##type(); break
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) {
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSVGElement* created = NULL;
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (type) {
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Circle);
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(ClipPath);
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Defs);
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Ellipse);
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(FeColorMatrix);
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Filter);
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(G);
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Image);
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Line);
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(LinearGradient);
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Mask);
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Metadata);
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Path);
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Polygon);
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Polyline);
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(RadialGradient);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Rect);
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Stop);
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(SVG);
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Symbol);
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Text);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Tspan);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        CASE_NEW(Use);
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    created->fParent = parent;
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isDef = created->fIsDef = created->isDef();
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isNotDef = created->fIsNotDef = created->isNotDef();
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (isDef) {
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSVGElement* up = parent;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (up && up->fIsDef == false) {
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            up->fIsDef = true;
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            up = up->fParent;
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (isNotDef) {
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkSVGElement* up = parent;
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (up && up->fIsNotDef == false) {
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            up->fIsNotDef = true;
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            up = up->fParent;
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return created;
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkSVGTypeName gSVGTypeNames[] = {
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"circle", SkSVGType_Circle},
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"clipPath", SkSVGType_ClipPath},
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"defs", SkSVGType_Defs},
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"ellipse", SkSVGType_Ellipse},
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"feColorMatrix", SkSVGType_FeColorMatrix},
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"filter", SkSVGType_Filter},
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"g", SkSVGType_G},
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"image", SkSVGType_Image},
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"line", SkSVGType_Line},
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"linearGradient", SkSVGType_LinearGradient},
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"mask", SkSVGType_Mask},
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"metadata", SkSVGType_Metadata},
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"path", SkSVGType_Path},
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"polygon", SkSVGType_Polygon},
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"polyline", SkSVGType_Polyline},
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"radialGradient", SkSVGType_RadialGradient},
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"rect", SkSVGType_Rect},
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"stop", SkSVGType_Stop},
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"svg", SkSVGType_SVG},
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"symbol", SkSVGType_Symbol},
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"text", SkSVGType_Text},
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"tspan", SkSVGType_Tspan},
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {"use", SkSVGType_Use}
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst int kSVGTypeNamesSize = SK_ARRAY_COUNT(gSVGTypeNames);
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkSVGTypes SkSVGParser::GetType(const char match[], size_t len ) {
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int index = SkStrSearch(&gSVGTypeNames[0].fName, kSVGTypeNamesSize, match,
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        len, sizeof(gSVGTypeNames[0]));
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return index >= 0 && index < kSVGTypeNamesSize ? gSVGTypeNames[index].fType :
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (SkSVGTypes) -1;
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
442