bool SkSVGElement::isGroupParent() { SkSVGElement* parent = fParent; while (parent) { if (parent->getType() != SkSVGType_G) return false; parent = parent->fParent; } return true; }
bool SkSVGParser::onEndElement(const char elem[]) { int parentIndex = fParents.count() - 1; if (parentIndex >= 0) { SkSVGElement* element = fParents[parentIndex]; element->onEndElement(*this); fParents.remove(parentIndex); } return false; }
SkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) { SkSVGElement* created = NULL; switch (type) { CASE_NEW(Circle); CASE_NEW(ClipPath); CASE_NEW(Defs); CASE_NEW(Ellipse); CASE_NEW(FeColorMatrix); CASE_NEW(Filter); CASE_NEW(G); CASE_NEW(Image); CASE_NEW(Line); CASE_NEW(LinearGradient); CASE_NEW(Mask); CASE_NEW(Metadata); CASE_NEW(Path); CASE_NEW(Polygon); CASE_NEW(Polyline); CASE_NEW(RadialGradient); CASE_NEW(Rect); CASE_NEW(Stop); CASE_NEW(SVG); CASE_NEW(Symbol); CASE_NEW(Text); CASE_NEW(Tspan); CASE_NEW(Use); default: SkASSERT(0); return NULL; } created->fParent = parent; bool isDef = created->fIsDef = created->isDef(); bool isNotDef = created->fIsNotDef = created->isNotDef(); if (isDef) { SkSVGElement* up = parent; while (up && up->fIsDef == false) { up->fIsDef = true; up = up->fParent; } } if (isNotDef) { SkSVGElement* up = parent; while (up && up->fIsNotDef == false) { up->fIsNotDef = true; up = up->fParent; } } return created; }
void SkSVGClipPath::translate(SkSVGParser& parser, bool defState) { parser._startElement("clip"); INHERITED::translate(parser, defState); SkASSERT(fChildren.count() == 1); SkSVGElement* child = *fChildren.begin(); SkASSERT(child->getType() == SkSVGType_Use); SkSVGUse* use = (SkSVGUse*) child; SkSVGElement* ref = NULL; const char* refStr = &use->f_xlink_href.c_str()[1]; SkASSERT(parser.getIDs().find(refStr, &ref)); SkASSERT(ref); if (ref->getType() == SkSVGType_Rect) parser._addAttribute("rectangle", refStr); else parser._addAttribute("path", refStr); parser._endElement(); }
bool SkSVGPaint::writeChangedAttributes(SkSVGParser& parser, SkSVGPaint& current, bool* changed) { SkSVGPaint& lastState = parser.fLastFlush; for (int index = kInitial + 1; index < kTerminal; index++) { if (changed[index] == false) continue; SkString* topAttr = current[index]; size_t attrLength = topAttr->size(); if (attrLength == 0) continue; const char* attrValue = topAttr->c_str(); SkString* lastAttr = lastState[index]; switch(index) { case kClipPath: case kClipRule: case kEnableBackground: break; case kFill: if (topAttr->equals("none") == false && lastAttr->equals("none") == true) parser._addAttribute("stroke", "false"); goto fillStrokeAttrCommon; case kFillRule: case kFilter: case kFontFamily: break; case kFontSize: parser._addAttributeLen("textSize", attrValue, attrLength); break; case kLetterSpacing: parser._addAttributeLen("textTracking", attrValue, attrLength); break; case kMask: break; case kOpacity: break; case kStopColor: break; case kStopOpacity: break; case kStroke: if (topAttr->equals("none") == false && lastAttr->equals("none") == true) parser._addAttribute("stroke", "true"); fillStrokeAttrCommon: if (strncmp(attrValue, "url(", 4) == 0) { SkASSERT(attrValue[4] == '#'); const char* idStart = attrValue + 5; const char* idEnd = strrchr(attrValue, ')'); SkASSERT(idStart < idEnd); SkString id(idStart, idEnd - idStart); SkSVGElement* found; if (strncmp(id.c_str(), "mask", 4) != 0) { bool itsFound = parser.fIDs.find(id.c_str(), &found); SkASSERT(itsFound); SkASSERT(found->getType() == SkSVGType_LinearGradient || found->getType() == SkSVGType_RadialGradient); } parser._addAttribute("shader", id.c_str()); } break; case kStroke_Dasharray: break; case kStroke_Linecap: parser._addAttributeLen("strokeCap", attrValue, attrLength); break; case kStroke_Linejoin: parser._addAttributeLen("strokeJoin", attrValue, attrLength); break; case kStroke_Miterlimit: parser._addAttributeLen("strokeMiter", attrValue, attrLength); break; case kStroke_Width: parser._addAttributeLen("strokeWidth", attrValue, attrLength); case kStyle: case kTransform: break; default: SkASSERT(0); return false; } } return true; }
bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) { SkSVGPaint current; SkSVGPaint* walking = parser.fHead; int index; while (walking != NULL) { for (index = kInitial + 1; index < kTerminal; index++) { SkString* lastAttr = (*walking)[index]; if (lastAttr->size() == 0) continue; if (current[index]->size() > 0) continue; current[index]->set(*lastAttr); } walking = walking->fNext; } bool paintChanged = false; SkSVGPaint& lastState = parser.fLastFlush; if (isFlushable == false) { if (isDef == true) { if (current.f_mask.size() > 0 && current.f_mask.equals(lastState.f_mask) == false) { SkSVGElement* found; const char* idStart = strchr(current.f_mask.c_str(), '#'); SkASSERT(idStart); SkString id(idStart + 1, strlen(idStart) - 2); bool itsFound = parser.fIDs.find(id.c_str(), &found); SkASSERT(itsFound); SkSVGElement* gradient = found->getGradient(); if (gradient) { gradient->write(parser, current.f_fill); gradient->write(parser, current.f_stroke); } } } goto setLast; } { bool changed[kTerminal]; memset(changed, 0, sizeof(changed)); for (index = kInitial + 1; index < kTerminal; index++) { if (index == kTransform || index == kClipPath || index == kStopColor || index == kStopOpacity || index == kClipRule || index == kFillRule) continue; SkString* lastAttr = lastState[index]; SkString* currentAttr = current[index]; paintChanged |= changed[index] = lastAttr->equals(*currentAttr) == false; } if (paintChanged) { if (current.f_mask.size() > 0) { if (current.f_fill.equals("none") == false && strncmp(current.f_fill.c_str(), "url(#", 5) != 0) { SkASSERT(current.f_fill.c_str()[0] == '#'); SkString replacement("url(#mask"); replacement.append(current.f_fill.c_str() + 1); replacement.appendUnichar(')'); current.f_fill.set(replacement); } if (current.f_stroke.equals("none") == false && strncmp(current.f_stroke.c_str(), "url(#", 5) != 0) { SkASSERT(current.f_stroke.c_str()[0] == '#'); SkString replacement("url(#mask"); replacement.append(current.f_stroke.c_str() + 1); replacement.appendUnichar(')'); current.f_stroke.set(replacement); } } if (current.f_fill.equals("none") && current.f_stroke.equals("none")) current.f_opacity.set("0"); if (parser.fSuppressPaint == false) { parser._startElement("paint"); bool success = writeChangedAttributes(parser, current, changed); if (success == false) return paintChanged; success = writeChangedElements(parser, current, changed); if (success == false) return paintChanged; parser._endElement(); // paint } } } setLast: for (index = kInitial + 1; index < kTerminal; index++) { SkString* lastAttr = lastState[index]; SkString* currentAttr = current[index]; lastAttr->set(*currentAttr); } return paintChanged; }