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 +}