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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     2 /*
     3  * Copyright 2006 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
    10 #include "SkSVGParser.h"
    11 #include "SkSVGCircle.h"
    12 #include "SkSVGClipPath.h"
    13 #include "SkSVGDefs.h"
    14 #include "SkSVGEllipse.h"
    15 #include "SkSVGFeColorMatrix.h"
    16 #include "SkSVGFilter.h"
    17 #include "SkSVGG.h"
    18 #include "SkSVGImage.h"
    19 #include "SkSVGLine.h"
    20 #include "SkSVGLinearGradient.h"
    21 #include "SkSVGMask.h"
    22 #include "SkSVGMetadata.h"
    23 #include "SkSVGPath.h"
    24 #include "SkSVGPolygon.h"
    25 #include "SkSVGPolyline.h"
    26 #include "SkSVGRadialGradient.h"
    27 #include "SkSVGRect.h"
    28 #include "SkSVGSVG.h"
    29 #include "SkSVGStop.h"
    30 #include "SkSVGSymbol.h"
    31 #include "SkSVGText.h"
    32 #include "SkSVGUse.h"
    33 #include "SkTSearch.h"
    34 #include <stdio.h>
    36 static int gGeneratedMatrixID = 0;
    38 SkSVGParser::SkSVGParser(SkXMLParserError* errHandler) :
    39     SkXMLParser(errHandler),
    40     fHead(&fEmptyPaint), fIDs(256),
    41         fXMLWriter(&fStream), fCurrElement(NULL), fInSVG(false), fSuppressPaint(false) {
    42     fLastTransform.reset();
    43     fEmptyPaint.f_fill.set("black");
    44     fEmptyPaint.f_stroke.set("none");
    45     fEmptyPaint.f_strokeMiterlimit.set("4");
    46     fEmptyPaint.f_fillRule.set("winding");
    47     fEmptyPaint.f_opacity.set("1");
    48     fEmptyPaint.fNext = NULL;
    49     for (int index = SkSVGPaint::kInitial + 1; index < SkSVGPaint::kTerminal; index++) {
    50         SkString* initial = fEmptyPaint[index];
    51         if (initial->size() == 0)
    52             continue;
    53         fLastFlush[index]->set(*initial);
    54     }
    55 }
    57 SkSVGParser::~SkSVGParser() {
    58 }
    60 void SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) {
    61     SkSVGElement** ptr;
    62     for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
    63         Delete((*ptr)->fChildren);
    64         delete *ptr;
    65     }
    66 }
    68 int SkSVGParser::findAttribute(SkSVGBase* element, const char* attrValue,
    69         size_t len, bool isPaint) {
    70     const SkSVGAttribute* attributes;
    71     size_t count = element->getAttributes(&attributes);
    72     size_t result = 0;
    73     while (result < count) {
    74         if (strncmp(attributes->fName, attrValue, len) == 0 && strlen(attributes->fName) == len) {
    75             SkASSERT(result == (attributes->fOffset -
    76                 (isPaint ? sizeof(SkString) : sizeof(SkSVGElement))) / sizeof(SkString));
    77             return result;
    78         }
    79         attributes++;
    80         result++;
    81     }
    82     return -1;
    83 }
    85 #if 0
    86 const char* SkSVGParser::getFinal() {
    87     _startElement("screenplay");
    88     // generate defs
    89     SkSVGElement** ptr;
    90     for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
    91         SkSVGElement* element = *ptr;
    92         translate(element, true);
    93     }
    94     // generate onLoad
    95     _startElement("event");
    96     _addAttribute("kind", "onLoad");
    97     _startElement("paint");
    98     _addAttribute("antiAlias", "true");
    99     _endElement();
   100     for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
   101         SkSVGElement* element = *ptr;
   102         translate(element, false);
   103     }
   104     _endElement(); // event
   105     _endElement(); // screenplay
   106     Delete(fChildren);
   107     fStream.write("", 1);
   108     return fStream.getStream();
   109 }
   110 #endif
   112 SkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
   113     SkSVGPaint* state = fHead;
   114     do {
   115         SkString* attr = (*state)[field];
   116         SkASSERT(attr);
   117         if (attr->size() > 0)
   118             return *attr;
   119         state = state->fNext;
   120     } while (state);
   121     SkASSERT(0);
   122     SkASSERT(fEmptyPaint[field]);
   123     return *fEmptyPaint[field];
   124 }
   126 bool SkSVGParser::isStrokeAndFill(  SkSVGPaint** strokeState, SkSVGPaint** fillState) {
   127     SkSVGPaint* walking = fHead;
   128     bool stroke = false;
   129     bool fill = false;
   130     bool strokeSet = false;
   131     bool fillSet = false;
   132     while (walking != NULL) {
   133         if (strokeSet == false && walking->f_stroke.size() > 0) {
   134             stroke = walking->f_stroke.equals("none") == false;
   135             *strokeState = walking;
   136             strokeSet = true;
   137         }
   138         if (fillSet == false && walking->f_fill.size() > 0) {
   139             fill = walking->f_fill.equals("none") == false;
   140             *fillState = walking;
   141             fillSet = true;
   142         }
   143         walking = walking->fNext;
   144     }
   145     return stroke && fill;
   146 }
   148 bool SkSVGParser::onAddAttribute(const char name[], const char value[]) {
   149     return onAddAttributeLen(name, value, strlen(value));
   150 }
   152 bool SkSVGParser::onAddAttributeLen(const char name[], const char value[], size_t len) {
   153     if (fCurrElement == NULL)    // this signals we should ignore attributes for this element
   154         return true;
   155     if (fCurrElement->fIsDef == false && fCurrElement->fIsNotDef == false)
   156         return false; // also an ignored element
   157     size_t nameLen = strlen(name);
   158     int attrIndex = findAttribute(fCurrElement, name, nameLen, false);
   159     if (attrIndex == -1) {
   160         attrIndex = findAttribute(&fCurrElement->fPaintState, name, nameLen, true);
   161         if (attrIndex >= 0) {
   162             fCurrElement->fPaintState.addAttribute(*this, attrIndex, value, len);
   163             return false;
   164         }
   165         if (nameLen == 2 && strncmp("id", name, nameLen) == 0) {
   166             fCurrElement->f_id.set(value, len);
   167             return false;
   168         }
   169         if (strchr(name, ':') != 0) // part of a different namespace
   170             return false;
   171     }
   172     SkASSERT(attrIndex >= 0);
   173     fCurrElement->addAttribute(*this, attrIndex, value, len);
   174     return false;
   175 }
   177 bool SkSVGParser::onEndElement(const char elem[]) {
   178     int parentIndex = fParents.count() - 1;
   179     if (parentIndex >= 0) {
   180         SkSVGElement* element = fParents[parentIndex];
   181         element->onEndElement(*this);
   182         fParents.remove(parentIndex);
   183     }
   184     return false;
   185 }
   187 bool SkSVGParser::onStartElement(const char name[]) {
   188     return onStartElementLen(name, strlen(name));
   189 }
   191 bool SkSVGParser::onStartElementLen(const char name[], size_t len) {
   192     if (strncmp(name, "svg", len) == 0) {
   193         fInSVG = true;
   194     } else if (fInSVG == false)
   195         return false;
   196     const char* nextColon = strchr(name, ':');
   197     if (nextColon && (size_t)(nextColon - name) < len)
   198         return false;
   199     SkSVGTypes type = GetType(name, len);
   200 //    SkASSERT(type >= 0);
   201     if (type < 0) {
   202         type = SkSVGType_G;
   203 //        return true;
   204     }
   205     SkSVGElement* parent = fParents.count() > 0 ? fParents.top() : NULL;
   206     SkSVGElement* element = CreateElement(type, parent);
   207     bool result = false;
   208     if (parent) {
   209         element->fParent = parent;
   210         result = fParents.top()->onStartElement(element);
   211     } else
   212         *fChildren.append() = element;
   213     if (strncmp(name, "svg", len) != 0)
   214         *fParents.append() = element;
   215     fCurrElement = element;
   216     return result;
   217 }
   219 bool SkSVGParser::onText(const char text[], int len) {
   220     if (fInSVG == false)
   221         return false;
   222     SkSVGTypes type = fCurrElement->getType();
   223     if (type != SkSVGType_Text && type != SkSVGType_Tspan)
   224         return false;
   225     SkSVGText* textElement = (SkSVGText*) fCurrElement;
   226     textElement->f_text.set(text, len);
   227     return false;
   228 }
   230 static int32_t strokeFillID = 0;
   232 void SkSVGParser::translate(SkSVGElement* element, bool isDef) {
   233     SkSVGPaint::Push(&fHead, &element->fPaintState);
   234     bool isFlushable = element->isFlushable();
   235     if ((element->fIsDef == false && element->fIsNotDef == false) ||
   236         (element->fIsDef && isDef == false && element->fIsNotDef == false) ||
   237         (element->fIsDef == false && isDef && element->fIsNotDef)) {
   238         isFlushable = false;
   239     }
   240     SkSVGPaint* strokeState = NULL, * fillState = NULL;
   241     if (isFlushable)
   242         element->fPaintState.setSave(*this);
   243     if (isFlushable && isStrokeAndFill(&strokeState, &fillState)) {
   244         SkString& elementID = element->f_id;
   245         if (elementID.size() == 0) {
   246             elementID.set("sf");
   247             elementID.appendS32(++strokeFillID);
   248         }
   249         SkString saveStroke(strokeState->f_stroke);
   250         SkString saveFill(fillState->f_fill);
   251         strokeState->f_stroke.set("none");
   252         element->fPaintState.flush(*this, isFlushable, isDef);
   253         element->translate(*this, isDef);
   254         strokeState->f_stroke.set(saveStroke);
   255         fillState->f_fill.set("none");
   256         if (element->fPaintState.flush(*this, isFlushable, isDef)) {
   257             _startElement("add");
   258             _addAttributeLen("use", elementID.c_str(), elementID.size());
   259             _endElement();  // add
   260         }
   261         fillState->f_fill.set(saveFill);
   262     } else {
   263         element->fPaintState.flush(*this, isFlushable, isDef);
   264         if (isFlushable || element->isGroup())
   265             element->translate(*this, isDef);
   266     }
   267     SkSVGPaint::Pop(&fHead);
   268 }
   270 void SkSVGParser::translateMatrix(SkString& string, SkString* stringID) {
   271     if (string.size() == 0)
   272         return;
   273     if (stringID->size() > 0) {
   274         _startElement("add");
   275         _addAttribute("use", stringID->c_str());
   276         _endElement(); // add
   277         return;
   278     }
   279     SkASSERT(strncmp(string.c_str(), "matrix", 6) == 0);
   280     ++gGeneratedMatrixID;
   281     _startElement("matrix");
   282     char idStr[24];
   283     strcpy(idStr, "sk_matrix");
   284     sprintf(idStr + strlen(idStr), "%d", gGeneratedMatrixID);
   285     _addAttribute("id", idStr);
   286     stringID->set(idStr);
   287     const char* str = string.c_str();
   288     SkASSERT(strncmp(str, "matrix(", 7) == 0);
   289     str += 6;
   290     const char* strEnd = strrchr(str, ')');
   291     SkASSERT(strEnd != NULL);
   292     SkString mat(str, strEnd - str);
   293     ConvertToArray(mat);
   294     const char* elems[6];
   295     static const int order[] = {0, 3, 1, 4, 2, 5};
   296     const int* orderPtr = order;
   297     str = mat.c_str();
   298     strEnd = str + mat.size();
   299     while (str < strEnd) {
   300         elems[*orderPtr++] = str;
   301         while (str < strEnd && *str != ',' )
   302             str++;
   303         str++;
   304     }
   305     string.reset();
   306     for (int index = 0; index < 6; index++) {
   307         const char* end = strchr(elems[index], ',');
   308         if (end == NULL)
   309             end= strchr(elems[index], ']');
   310         string.append(elems[index], end - elems[index] + 1);
   311     }
   312     string.remove(string.size() - 1, 1);
   313     string.append(",0,0,1]");
   314     _addAttribute("matrix", string);
   315     _endElement();  // matrix
   316 }
   318 static bool is_whitespace(char ch) {
   319     return ch > 0 && ch <= ' ';
   320 }
   322 void SkSVGParser::ConvertToArray(SkString& vals) {
   323     vals.appendUnichar(']');
   324     char* valCh = (char*) vals.c_str();
   325     valCh[0] = '[';
   326     int index = 1;
   327     while (valCh[index] != ']') {
   328         while (is_whitespace(valCh[index]))
   329             index++;
   330         bool foundComma = false;
   331         char next;
   332         do {
   333             next = valCh[index++];
   334             if (next == ',') {
   335                 foundComma = true;
   336                 continue;
   337             }
   338             if (next == ']') {
   339                 index--;
   340                 goto undoLastComma;
   341             }
   342             if (next == ' ')
   343                 break;
   344             foundComma = false;
   345         } while (is_whitespace(next) == false);
   346         if (foundComma == false)
   347             valCh[index - 1] = ',';
   348     }
   349 undoLastComma:
   350     while (is_whitespace(valCh[--index]))
   351         ;
   352     if (valCh[index] == ',')
   353         valCh[index] = ' ';
   354 }
   356 #define CASE_NEW(type) case SkSVGType_##type : created = new SkSVG##type(); break
   358 SkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) {
   359     SkSVGElement* created = NULL;
   360     switch (type) {
   361         CASE_NEW(Circle);
   362         CASE_NEW(ClipPath);
   363         CASE_NEW(Defs);
   364         CASE_NEW(Ellipse);
   365         CASE_NEW(FeColorMatrix);
   366         CASE_NEW(Filter);
   367         CASE_NEW(G);
   368         CASE_NEW(Image);
   369         CASE_NEW(Line);
   370         CASE_NEW(LinearGradient);
   371         CASE_NEW(Mask);
   372         CASE_NEW(Metadata);
   373         CASE_NEW(Path);
   374         CASE_NEW(Polygon);
   375         CASE_NEW(Polyline);
   376         CASE_NEW(RadialGradient);
   377         CASE_NEW(Rect);
   378         CASE_NEW(Stop);
   379         CASE_NEW(SVG);
   380         CASE_NEW(Symbol);
   381         CASE_NEW(Text);
   382         CASE_NEW(Tspan);
   383         CASE_NEW(Use);
   384         default:
   385             SkASSERT(0);
   386             return NULL;
   387     }
   388     created->fParent = parent;
   389     bool isDef = created->fIsDef = created->isDef();
   390     bool isNotDef = created->fIsNotDef = created->isNotDef();
   391     if (isDef) {
   392         SkSVGElement* up = parent;
   393         while (up && up->fIsDef == false) {
   394             up->fIsDef = true;
   395             up = up->fParent;
   396         }
   397     }
   398     if (isNotDef) {
   399         SkSVGElement* up = parent;
   400         while (up && up->fIsNotDef == false) {
   401             up->fIsNotDef = true;
   402             up = up->fParent;
   403         }
   404     }
   405     return created;
   406 }
   408 const SkSVGTypeName gSVGTypeNames[] = {
   409     {"circle", SkSVGType_Circle},
   410     {"clipPath", SkSVGType_ClipPath},
   411     {"defs", SkSVGType_Defs},
   412     {"ellipse", SkSVGType_Ellipse},
   413     {"feColorMatrix", SkSVGType_FeColorMatrix},
   414     {"filter", SkSVGType_Filter},
   415     {"g", SkSVGType_G},
   416     {"image", SkSVGType_Image},
   417     {"line", SkSVGType_Line},
   418     {"linearGradient", SkSVGType_LinearGradient},
   419     {"mask", SkSVGType_Mask},
   420     {"metadata", SkSVGType_Metadata},
   421     {"path", SkSVGType_Path},
   422     {"polygon", SkSVGType_Polygon},
   423     {"polyline", SkSVGType_Polyline},
   424     {"radialGradient", SkSVGType_RadialGradient},
   425     {"rect", SkSVGType_Rect},
   426     {"stop", SkSVGType_Stop},
   427     {"svg", SkSVGType_SVG},
   428     {"symbol", SkSVGType_Symbol},
   429     {"text", SkSVGType_Text},
   430     {"tspan", SkSVGType_Tspan},
   431     {"use", SkSVGType_Use}
   432 };
   434 const int kSVGTypeNamesSize = SK_ARRAY_COUNT(gSVGTypeNames);
   436 SkSVGTypes SkSVGParser::GetType(const char match[], size_t len ) {
   437     int index = SkStrSearch(&gSVGTypeNames[0].fName, kSVGTypeNamesSize, match,
   438         len, sizeof(gSVGTypeNames[0]));
   439     return index >= 0 && index < kSVGTypeNamesSize ? gSVGTypeNames[index].fType :
   440         (SkSVGTypes) -1;
   441 }

mercurial