gfx/skia/trunk/src/svg/SkSVGParser.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/svg/SkSVGParser.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,441 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#include "SkSVGParser.h"
    1.14 +#include "SkSVGCircle.h"
    1.15 +#include "SkSVGClipPath.h"
    1.16 +#include "SkSVGDefs.h"
    1.17 +#include "SkSVGEllipse.h"
    1.18 +#include "SkSVGFeColorMatrix.h"
    1.19 +#include "SkSVGFilter.h"
    1.20 +#include "SkSVGG.h"
    1.21 +#include "SkSVGImage.h"
    1.22 +#include "SkSVGLine.h"
    1.23 +#include "SkSVGLinearGradient.h"
    1.24 +#include "SkSVGMask.h"
    1.25 +#include "SkSVGMetadata.h"
    1.26 +#include "SkSVGPath.h"
    1.27 +#include "SkSVGPolygon.h"
    1.28 +#include "SkSVGPolyline.h"
    1.29 +#include "SkSVGRadialGradient.h"
    1.30 +#include "SkSVGRect.h"
    1.31 +#include "SkSVGSVG.h"
    1.32 +#include "SkSVGStop.h"
    1.33 +#include "SkSVGSymbol.h"
    1.34 +#include "SkSVGText.h"
    1.35 +#include "SkSVGUse.h"
    1.36 +#include "SkTSearch.h"
    1.37 +#include <stdio.h>
    1.38 +
    1.39 +static int gGeneratedMatrixID = 0;
    1.40 +
    1.41 +SkSVGParser::SkSVGParser(SkXMLParserError* errHandler) :
    1.42 +    SkXMLParser(errHandler),
    1.43 +    fHead(&fEmptyPaint), fIDs(256),
    1.44 +        fXMLWriter(&fStream), fCurrElement(NULL), fInSVG(false), fSuppressPaint(false) {
    1.45 +    fLastTransform.reset();
    1.46 +    fEmptyPaint.f_fill.set("black");
    1.47 +    fEmptyPaint.f_stroke.set("none");
    1.48 +    fEmptyPaint.f_strokeMiterlimit.set("4");
    1.49 +    fEmptyPaint.f_fillRule.set("winding");
    1.50 +    fEmptyPaint.f_opacity.set("1");
    1.51 +    fEmptyPaint.fNext = NULL;
    1.52 +    for (int index = SkSVGPaint::kInitial + 1; index < SkSVGPaint::kTerminal; index++) {
    1.53 +        SkString* initial = fEmptyPaint[index];
    1.54 +        if (initial->size() == 0)
    1.55 +            continue;
    1.56 +        fLastFlush[index]->set(*initial);
    1.57 +    }
    1.58 +}
    1.59 +
    1.60 +SkSVGParser::~SkSVGParser() {
    1.61 +}
    1.62 +
    1.63 +void SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) {
    1.64 +    SkSVGElement** ptr;
    1.65 +    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
    1.66 +        Delete((*ptr)->fChildren);
    1.67 +        delete *ptr;
    1.68 +    }
    1.69 +}
    1.70 +
    1.71 +int SkSVGParser::findAttribute(SkSVGBase* element, const char* attrValue,
    1.72 +        size_t len, bool isPaint) {
    1.73 +    const SkSVGAttribute* attributes;
    1.74 +    size_t count = element->getAttributes(&attributes);
    1.75 +    size_t result = 0;
    1.76 +    while (result < count) {
    1.77 +        if (strncmp(attributes->fName, attrValue, len) == 0 && strlen(attributes->fName) == len) {
    1.78 +            SkASSERT(result == (attributes->fOffset -
    1.79 +                (isPaint ? sizeof(SkString) : sizeof(SkSVGElement))) / sizeof(SkString));
    1.80 +            return result;
    1.81 +        }
    1.82 +        attributes++;
    1.83 +        result++;
    1.84 +    }
    1.85 +    return -1;
    1.86 +}
    1.87 +
    1.88 +#if 0
    1.89 +const char* SkSVGParser::getFinal() {
    1.90 +    _startElement("screenplay");
    1.91 +    // generate defs
    1.92 +    SkSVGElement** ptr;
    1.93 +    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
    1.94 +        SkSVGElement* element = *ptr;
    1.95 +        translate(element, true);
    1.96 +    }
    1.97 +    // generate onLoad
    1.98 +    _startElement("event");
    1.99 +    _addAttribute("kind", "onLoad");
   1.100 +    _startElement("paint");
   1.101 +    _addAttribute("antiAlias", "true");
   1.102 +    _endElement();
   1.103 +    for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
   1.104 +        SkSVGElement* element = *ptr;
   1.105 +        translate(element, false);
   1.106 +    }
   1.107 +    _endElement(); // event
   1.108 +    _endElement(); // screenplay
   1.109 +    Delete(fChildren);
   1.110 +    fStream.write("", 1);
   1.111 +    return fStream.getStream();
   1.112 +}
   1.113 +#endif
   1.114 +
   1.115 +SkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
   1.116 +    SkSVGPaint* state = fHead;
   1.117 +    do {
   1.118 +        SkString* attr = (*state)[field];
   1.119 +        SkASSERT(attr);
   1.120 +        if (attr->size() > 0)
   1.121 +            return *attr;
   1.122 +        state = state->fNext;
   1.123 +    } while (state);
   1.124 +    SkASSERT(0);
   1.125 +    SkASSERT(fEmptyPaint[field]);
   1.126 +    return *fEmptyPaint[field];
   1.127 +}
   1.128 +
   1.129 +bool SkSVGParser::isStrokeAndFill(  SkSVGPaint** strokeState, SkSVGPaint** fillState) {
   1.130 +    SkSVGPaint* walking = fHead;
   1.131 +    bool stroke = false;
   1.132 +    bool fill = false;
   1.133 +    bool strokeSet = false;
   1.134 +    bool fillSet = false;
   1.135 +    while (walking != NULL) {
   1.136 +        if (strokeSet == false && walking->f_stroke.size() > 0) {
   1.137 +            stroke = walking->f_stroke.equals("none") == false;
   1.138 +            *strokeState = walking;
   1.139 +            strokeSet = true;
   1.140 +        }
   1.141 +        if (fillSet == false && walking->f_fill.size() > 0) {
   1.142 +            fill = walking->f_fill.equals("none") == false;
   1.143 +            *fillState = walking;
   1.144 +            fillSet = true;
   1.145 +        }
   1.146 +        walking = walking->fNext;
   1.147 +    }
   1.148 +    return stroke && fill;
   1.149 +}
   1.150 +
   1.151 +bool SkSVGParser::onAddAttribute(const char name[], const char value[]) {
   1.152 +    return onAddAttributeLen(name, value, strlen(value));
   1.153 +}
   1.154 +
   1.155 +bool SkSVGParser::onAddAttributeLen(const char name[], const char value[], size_t len) {
   1.156 +    if (fCurrElement == NULL)    // this signals we should ignore attributes for this element
   1.157 +        return true;
   1.158 +    if (fCurrElement->fIsDef == false && fCurrElement->fIsNotDef == false)
   1.159 +        return false; // also an ignored element
   1.160 +    size_t nameLen = strlen(name);
   1.161 +    int attrIndex = findAttribute(fCurrElement, name, nameLen, false);
   1.162 +    if (attrIndex == -1) {
   1.163 +        attrIndex = findAttribute(&fCurrElement->fPaintState, name, nameLen, true);
   1.164 +        if (attrIndex >= 0) {
   1.165 +            fCurrElement->fPaintState.addAttribute(*this, attrIndex, value, len);
   1.166 +            return false;
   1.167 +        }
   1.168 +        if (nameLen == 2 && strncmp("id", name, nameLen) == 0) {
   1.169 +            fCurrElement->f_id.set(value, len);
   1.170 +            return false;
   1.171 +        }
   1.172 +        if (strchr(name, ':') != 0) // part of a different namespace
   1.173 +            return false;
   1.174 +    }
   1.175 +    SkASSERT(attrIndex >= 0);
   1.176 +    fCurrElement->addAttribute(*this, attrIndex, value, len);
   1.177 +    return false;
   1.178 +}
   1.179 +
   1.180 +bool SkSVGParser::onEndElement(const char elem[]) {
   1.181 +    int parentIndex = fParents.count() - 1;
   1.182 +    if (parentIndex >= 0) {
   1.183 +        SkSVGElement* element = fParents[parentIndex];
   1.184 +        element->onEndElement(*this);
   1.185 +        fParents.remove(parentIndex);
   1.186 +    }
   1.187 +    return false;
   1.188 +}
   1.189 +
   1.190 +bool SkSVGParser::onStartElement(const char name[]) {
   1.191 +    return onStartElementLen(name, strlen(name));
   1.192 +}
   1.193 +
   1.194 +bool SkSVGParser::onStartElementLen(const char name[], size_t len) {
   1.195 +    if (strncmp(name, "svg", len) == 0) {
   1.196 +        fInSVG = true;
   1.197 +    } else if (fInSVG == false)
   1.198 +        return false;
   1.199 +    const char* nextColon = strchr(name, ':');
   1.200 +    if (nextColon && (size_t)(nextColon - name) < len)
   1.201 +        return false;
   1.202 +    SkSVGTypes type = GetType(name, len);
   1.203 +//    SkASSERT(type >= 0);
   1.204 +    if (type < 0) {
   1.205 +        type = SkSVGType_G;
   1.206 +//        return true;
   1.207 +    }
   1.208 +    SkSVGElement* parent = fParents.count() > 0 ? fParents.top() : NULL;
   1.209 +    SkSVGElement* element = CreateElement(type, parent);
   1.210 +    bool result = false;
   1.211 +    if (parent) {
   1.212 +        element->fParent = parent;
   1.213 +        result = fParents.top()->onStartElement(element);
   1.214 +    } else
   1.215 +        *fChildren.append() = element;
   1.216 +    if (strncmp(name, "svg", len) != 0)
   1.217 +        *fParents.append() = element;
   1.218 +    fCurrElement = element;
   1.219 +    return result;
   1.220 +}
   1.221 +
   1.222 +bool SkSVGParser::onText(const char text[], int len) {
   1.223 +    if (fInSVG == false)
   1.224 +        return false;
   1.225 +    SkSVGTypes type = fCurrElement->getType();
   1.226 +    if (type != SkSVGType_Text && type != SkSVGType_Tspan)
   1.227 +        return false;
   1.228 +    SkSVGText* textElement = (SkSVGText*) fCurrElement;
   1.229 +    textElement->f_text.set(text, len);
   1.230 +    return false;
   1.231 +}
   1.232 +
   1.233 +static int32_t strokeFillID = 0;
   1.234 +
   1.235 +void SkSVGParser::translate(SkSVGElement* element, bool isDef) {
   1.236 +    SkSVGPaint::Push(&fHead, &element->fPaintState);
   1.237 +    bool isFlushable = element->isFlushable();
   1.238 +    if ((element->fIsDef == false && element->fIsNotDef == false) ||
   1.239 +        (element->fIsDef && isDef == false && element->fIsNotDef == false) ||
   1.240 +        (element->fIsDef == false && isDef && element->fIsNotDef)) {
   1.241 +        isFlushable = false;
   1.242 +    }
   1.243 +    SkSVGPaint* strokeState = NULL, * fillState = NULL;
   1.244 +    if (isFlushable)
   1.245 +        element->fPaintState.setSave(*this);
   1.246 +    if (isFlushable && isStrokeAndFill(&strokeState, &fillState)) {
   1.247 +        SkString& elementID = element->f_id;
   1.248 +        if (elementID.size() == 0) {
   1.249 +            elementID.set("sf");
   1.250 +            elementID.appendS32(++strokeFillID);
   1.251 +        }
   1.252 +        SkString saveStroke(strokeState->f_stroke);
   1.253 +        SkString saveFill(fillState->f_fill);
   1.254 +        strokeState->f_stroke.set("none");
   1.255 +        element->fPaintState.flush(*this, isFlushable, isDef);
   1.256 +        element->translate(*this, isDef);
   1.257 +        strokeState->f_stroke.set(saveStroke);
   1.258 +        fillState->f_fill.set("none");
   1.259 +        if (element->fPaintState.flush(*this, isFlushable, isDef)) {
   1.260 +            _startElement("add");
   1.261 +            _addAttributeLen("use", elementID.c_str(), elementID.size());
   1.262 +            _endElement();  // add
   1.263 +        }
   1.264 +        fillState->f_fill.set(saveFill);
   1.265 +    } else {
   1.266 +        element->fPaintState.flush(*this, isFlushable, isDef);
   1.267 +        if (isFlushable || element->isGroup())
   1.268 +            element->translate(*this, isDef);
   1.269 +    }
   1.270 +    SkSVGPaint::Pop(&fHead);
   1.271 +}
   1.272 +
   1.273 +void SkSVGParser::translateMatrix(SkString& string, SkString* stringID) {
   1.274 +    if (string.size() == 0)
   1.275 +        return;
   1.276 +    if (stringID->size() > 0) {
   1.277 +        _startElement("add");
   1.278 +        _addAttribute("use", stringID->c_str());
   1.279 +        _endElement(); // add
   1.280 +        return;
   1.281 +    }
   1.282 +    SkASSERT(strncmp(string.c_str(), "matrix", 6) == 0);
   1.283 +    ++gGeneratedMatrixID;
   1.284 +    _startElement("matrix");
   1.285 +    char idStr[24];
   1.286 +    strcpy(idStr, "sk_matrix");
   1.287 +    sprintf(idStr + strlen(idStr), "%d", gGeneratedMatrixID);
   1.288 +    _addAttribute("id", idStr);
   1.289 +    stringID->set(idStr);
   1.290 +    const char* str = string.c_str();
   1.291 +    SkASSERT(strncmp(str, "matrix(", 7) == 0);
   1.292 +    str += 6;
   1.293 +    const char* strEnd = strrchr(str, ')');
   1.294 +    SkASSERT(strEnd != NULL);
   1.295 +    SkString mat(str, strEnd - str);
   1.296 +    ConvertToArray(mat);
   1.297 +    const char* elems[6];
   1.298 +    static const int order[] = {0, 3, 1, 4, 2, 5};
   1.299 +    const int* orderPtr = order;
   1.300 +    str = mat.c_str();
   1.301 +    strEnd = str + mat.size();
   1.302 +    while (str < strEnd) {
   1.303 +        elems[*orderPtr++] = str;
   1.304 +        while (str < strEnd && *str != ',' )
   1.305 +            str++;
   1.306 +        str++;
   1.307 +    }
   1.308 +    string.reset();
   1.309 +    for (int index = 0; index < 6; index++) {
   1.310 +        const char* end = strchr(elems[index], ',');
   1.311 +        if (end == NULL)
   1.312 +            end= strchr(elems[index], ']');
   1.313 +        string.append(elems[index], end - elems[index] + 1);
   1.314 +    }
   1.315 +    string.remove(string.size() - 1, 1);
   1.316 +    string.append(",0,0,1]");
   1.317 +    _addAttribute("matrix", string);
   1.318 +    _endElement();  // matrix
   1.319 +}
   1.320 +
   1.321 +static bool is_whitespace(char ch) {
   1.322 +    return ch > 0 && ch <= ' ';
   1.323 +}
   1.324 +
   1.325 +void SkSVGParser::ConvertToArray(SkString& vals) {
   1.326 +    vals.appendUnichar(']');
   1.327 +    char* valCh = (char*) vals.c_str();
   1.328 +    valCh[0] = '[';
   1.329 +    int index = 1;
   1.330 +    while (valCh[index] != ']') {
   1.331 +        while (is_whitespace(valCh[index]))
   1.332 +            index++;
   1.333 +        bool foundComma = false;
   1.334 +        char next;
   1.335 +        do {
   1.336 +            next = valCh[index++];
   1.337 +            if (next == ',') {
   1.338 +                foundComma = true;
   1.339 +                continue;
   1.340 +            }
   1.341 +            if (next == ']') {
   1.342 +                index--;
   1.343 +                goto undoLastComma;
   1.344 +            }
   1.345 +            if (next == ' ')
   1.346 +                break;
   1.347 +            foundComma = false;
   1.348 +        } while (is_whitespace(next) == false);
   1.349 +        if (foundComma == false)
   1.350 +            valCh[index - 1] = ',';
   1.351 +    }
   1.352 +undoLastComma:
   1.353 +    while (is_whitespace(valCh[--index]))
   1.354 +        ;
   1.355 +    if (valCh[index] == ',')
   1.356 +        valCh[index] = ' ';
   1.357 +}
   1.358 +
   1.359 +#define CASE_NEW(type) case SkSVGType_##type : created = new SkSVG##type(); break
   1.360 +
   1.361 +SkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) {
   1.362 +    SkSVGElement* created = NULL;
   1.363 +    switch (type) {
   1.364 +        CASE_NEW(Circle);
   1.365 +        CASE_NEW(ClipPath);
   1.366 +        CASE_NEW(Defs);
   1.367 +        CASE_NEW(Ellipse);
   1.368 +        CASE_NEW(FeColorMatrix);
   1.369 +        CASE_NEW(Filter);
   1.370 +        CASE_NEW(G);
   1.371 +        CASE_NEW(Image);
   1.372 +        CASE_NEW(Line);
   1.373 +        CASE_NEW(LinearGradient);
   1.374 +        CASE_NEW(Mask);
   1.375 +        CASE_NEW(Metadata);
   1.376 +        CASE_NEW(Path);
   1.377 +        CASE_NEW(Polygon);
   1.378 +        CASE_NEW(Polyline);
   1.379 +        CASE_NEW(RadialGradient);
   1.380 +        CASE_NEW(Rect);
   1.381 +        CASE_NEW(Stop);
   1.382 +        CASE_NEW(SVG);
   1.383 +        CASE_NEW(Symbol);
   1.384 +        CASE_NEW(Text);
   1.385 +        CASE_NEW(Tspan);
   1.386 +        CASE_NEW(Use);
   1.387 +        default:
   1.388 +            SkASSERT(0);
   1.389 +            return NULL;
   1.390 +    }
   1.391 +    created->fParent = parent;
   1.392 +    bool isDef = created->fIsDef = created->isDef();
   1.393 +    bool isNotDef = created->fIsNotDef = created->isNotDef();
   1.394 +    if (isDef) {
   1.395 +        SkSVGElement* up = parent;
   1.396 +        while (up && up->fIsDef == false) {
   1.397 +            up->fIsDef = true;
   1.398 +            up = up->fParent;
   1.399 +        }
   1.400 +    }
   1.401 +    if (isNotDef) {
   1.402 +        SkSVGElement* up = parent;
   1.403 +        while (up && up->fIsNotDef == false) {
   1.404 +            up->fIsNotDef = true;
   1.405 +            up = up->fParent;
   1.406 +        }
   1.407 +    }
   1.408 +    return created;
   1.409 +}
   1.410 +
   1.411 +const SkSVGTypeName gSVGTypeNames[] = {
   1.412 +    {"circle", SkSVGType_Circle},
   1.413 +    {"clipPath", SkSVGType_ClipPath},
   1.414 +    {"defs", SkSVGType_Defs},
   1.415 +    {"ellipse", SkSVGType_Ellipse},
   1.416 +    {"feColorMatrix", SkSVGType_FeColorMatrix},
   1.417 +    {"filter", SkSVGType_Filter},
   1.418 +    {"g", SkSVGType_G},
   1.419 +    {"image", SkSVGType_Image},
   1.420 +    {"line", SkSVGType_Line},
   1.421 +    {"linearGradient", SkSVGType_LinearGradient},
   1.422 +    {"mask", SkSVGType_Mask},
   1.423 +    {"metadata", SkSVGType_Metadata},
   1.424 +    {"path", SkSVGType_Path},
   1.425 +    {"polygon", SkSVGType_Polygon},
   1.426 +    {"polyline", SkSVGType_Polyline},
   1.427 +    {"radialGradient", SkSVGType_RadialGradient},
   1.428 +    {"rect", SkSVGType_Rect},
   1.429 +    {"stop", SkSVGType_Stop},
   1.430 +    {"svg", SkSVGType_SVG},
   1.431 +    {"symbol", SkSVGType_Symbol},
   1.432 +    {"text", SkSVGType_Text},
   1.433 +    {"tspan", SkSVGType_Tspan},
   1.434 +    {"use", SkSVGType_Use}
   1.435 +};
   1.436 +
   1.437 +const int kSVGTypeNamesSize = SK_ARRAY_COUNT(gSVGTypeNames);
   1.438 +
   1.439 +SkSVGTypes SkSVGParser::GetType(const char match[], size_t len ) {
   1.440 +    int index = SkStrSearch(&gSVGTypeNames[0].fName, kSVGTypeNamesSize, match,
   1.441 +        len, sizeof(gSVGTypeNames[0]));
   1.442 +    return index >= 0 && index < kSVGTypeNamesSize ? gSVGTypeNames[index].fType :
   1.443 +        (SkSVGTypes) -1;
   1.444 +}

mercurial