Index: src/svg/parser/SkSVGPaintState.cpp |
diff --git a/src/svg/parser/SkSVGPaintState.cpp b/src/svg/parser/SkSVGPaintState.cpp |
deleted file mode 100644 |
index 8fa9139d0f684010aae58404cfe9ef3601ddf822..0000000000000000000000000000000000000000 |
--- a/src/svg/parser/SkSVGPaintState.cpp |
+++ /dev/null |
@@ -1,453 +0,0 @@ |
-/* |
- * Copyright 2006 The Android Open Source Project |
- * |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
- |
-#include "SkSVGPaintState.h" |
-#include "SkSVGElements.h" |
-#include "SkSVGParser.h" |
-#include "SkParse.h" |
- |
-SkSVGAttribute SkSVGPaint::gAttributes[] = { |
- SVG_LITERAL_ATTRIBUTE(clip-path, f_clipPath), |
- SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule), |
- SVG_LITERAL_ATTRIBUTE(enable-background, f_enableBackground), |
- SVG_ATTRIBUTE(fill), |
- SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule), |
- SVG_ATTRIBUTE(filter), |
- SVG_LITERAL_ATTRIBUTE(font-family, f_fontFamily), |
- SVG_LITERAL_ATTRIBUTE(font-size, f_fontSize), |
- SVG_LITERAL_ATTRIBUTE(letter-spacing, f_letterSpacing), |
- SVG_ATTRIBUTE(mask), |
- SVG_ATTRIBUTE(opacity), |
- SVG_LITERAL_ATTRIBUTE(stop-color, f_stopColor), |
- SVG_LITERAL_ATTRIBUTE(stop-opacity, f_stopOpacity), |
- SVG_ATTRIBUTE(stroke), |
- SVG_LITERAL_ATTRIBUTE(stroke-dasharray, f_strokeDasharray), |
- SVG_LITERAL_ATTRIBUTE(stroke-linecap, f_strokeLinecap), |
- SVG_LITERAL_ATTRIBUTE(stroke-linejoin, f_strokeLinejoin), |
- SVG_LITERAL_ATTRIBUTE(stroke-miterlimit, f_strokeMiterlimit), |
- SVG_LITERAL_ATTRIBUTE(stroke-width, f_strokeWidth), |
- SVG_ATTRIBUTE(style), |
- SVG_ATTRIBUTE(transform) |
-}; |
- |
-const int SkSVGPaint::kAttributesSize = SK_ARRAY_COUNT(SkSVGPaint::gAttributes); |
- |
-SkSVGPaint::SkSVGPaint() : fNext(nullptr) { |
-} |
- |
-SkString* SkSVGPaint::operator[](int index) { |
- SkASSERT(index >= 0); |
- SkASSERT(index < &fTerminal - &fInitial); |
- SkASSERT(&fTerminal - &fInitial == kTerminal - kInitial); |
- SkString* result = &fInitial + index + 1; |
- return result; |
-} |
- |
-void SkSVGPaint::addAttribute(SkSVGParser& parser, int attrIndex, |
- const char* attrValue, size_t attrLength) { |
- SkString* attr = (*this)[attrIndex]; |
- switch(attrIndex) { |
- case kClipPath: |
- case kClipRule: |
- case kEnableBackground: |
- case kFill: |
- case kFillRule: |
- case kFilter: |
- case kFontFamily: |
- case kFontSize: |
- case kLetterSpacing: |
- case kMask: |
- case kOpacity: |
- case kStopColor: |
- case kStopOpacity: |
- case kStroke: |
- case kStroke_Dasharray: |
- case kStroke_Linecap: |
- case kStroke_Linejoin: |
- case kStroke_Miterlimit: |
- case kStroke_Width: |
- case kTransform: |
- attr->set(attrValue, attrLength); |
- return; |
- case kStyle: { |
- // iterate through colon / semi-colon delimited pairs |
- int pairs = SkParse::Count(attrValue, ';'); |
- const char* attrEnd = attrValue + attrLength; |
- do { |
- const char* end = strchr(attrValue, ';'); |
- if (end == nullptr) |
- end = attrEnd; |
- const char* delimiter = strchr(attrValue, ':'); |
- SkASSERT(delimiter != 0 && delimiter < end); |
- int index = parser.findAttribute(this, attrValue, (int) (delimiter - attrValue), true); |
- SkASSERT(index >= 0); |
- delimiter++; |
- addAttribute(parser, index, delimiter, (int) (end - delimiter)); |
- attrValue = end + 1; |
- } while (--pairs); |
- return; |
- } |
- default: |
- SkASSERT(0); |
- } |
-} |
- |
-bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) { |
- SkSVGPaint current; |
- SkSVGPaint* walking = parser.fHead; |
- int index; |
- while (walking != nullptr) { |
- 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; |
-} |
- |
-int SkSVGPaint::getAttributes(const SkSVGAttribute** attrPtr) { |
- *attrPtr = gAttributes; |
- return kAttributesSize; |
-} |
- |
-void SkSVGPaint::setSave(SkSVGParser& parser) { |
- SkTDArray<SkString*> clips; |
- SkSVGPaint* walking = parser.fHead; |
- int index; |
- SkMatrix sum; |
- sum.reset(); |
- while (walking != nullptr) { |
- for (index = kInitial + 1; index < kTerminal; index++) { |
- SkString* lastAttr = (*walking)[index]; |
- if (lastAttr->size() == 0) |
- continue; |
- if (index == kTransform) { |
- const char* str = lastAttr->c_str(); |
- SkASSERT(strncmp(str, "matrix(", 7) == 0); |
- str += 6; |
- const char* strEnd = strrchr(str, ')'); |
- SkASSERT(strEnd != nullptr); |
- SkString mat(str, strEnd - str); |
- SkSVGParser::ConvertToArray(mat); |
- SkScalar values[6]; |
- SkParse::FindScalars(mat.c_str() + 1, values, 6); |
- SkMatrix matrix; |
- matrix.reset(); |
- matrix.setScaleX(values[0]); |
- matrix.setSkewY(values[1]); |
- matrix.setSkewX(values[2]); |
- matrix.setScaleY(values[3]); |
- matrix.setTranslateX(values[4]); |
- matrix.setTranslateY(values[5]); |
- sum.setConcat(matrix, sum); |
- continue; |
- } |
- if ( index == kClipPath) |
- *clips.insert(0) = lastAttr; |
- } |
- walking = walking->fNext; |
- } |
- if ((sum == parser.fLastTransform) == false) { |
- SkMatrix inverse; |
- bool success = parser.fLastTransform.invert(&inverse); |
- SkASSERT(success == true); |
- SkMatrix output; |
- output.setConcat(inverse, sum); |
- parser.fLastTransform = sum; |
- SkString outputStr; |
- outputStr.appendUnichar('['); |
- outputStr.appendScalar(output.getScaleX()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getSkewX()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getTranslateX()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getSkewY()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getScaleY()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getTranslateY()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getPerspX()); |
- outputStr.appendUnichar(','); |
- outputStr.appendScalar(output.getPerspY()); |
- outputStr.append(",1]"); |
- parser._startElement("matrix"); |
- parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size()); |
- parser._endElement(); |
- } |
-#if 0 // incomplete |
- if (parser.fTransformClips.size() > 0) { |
- // need to reset the clip when the 'g' scope is ended |
- parser._startElement("add"); |
- const char* start = strchr(current->f_clipPath.c_str(), '#') + 1; |
- SkASSERT(start); |
- parser._addAttributeLen("use", start, strlen(start) - 1); |
- parser._endElement(); // clip |
- } |
-#endif |
-} |
- |
-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::writeChangedElements(SkSVGParser& parser, |
- SkSVGPaint& current, bool* changed) { |
- SkSVGPaint& lastState = parser.fLastFlush; |
- for (int index = kInitial + 1; index < kTerminal; index++) { |
- 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: |
- // !!! need to add this outside of paint |
- break; |
- case kEnableBackground: |
- // !!! don't know what to do with this |
- break; |
- case kFill: |
- goto addColor; |
- case kFillRule: |
- case kFilter: |
- break; |
- case kFontFamily: |
- parser._startElement("typeface"); |
- parser._addAttributeLen("fontName", attrValue, attrLength); |
- parser._endElement(); // typeface |
- break; |
- case kFontSize: |
- case kLetterSpacing: |
- break; |
- case kMask: |
- case kOpacity: |
- if (changed[kStroke] == false && changed[kFill] == false) { |
- parser._startElement("color"); |
- SkString& opacity = current.f_opacity; |
- parser._addAttributeLen("color", parser.fLastColor.c_str(), parser.fLastColor.size()); |
- parser._addAttributeLen("alpha", opacity.c_str(), opacity.size()); |
- parser._endElement(); // color |
- } |
- break; |
- case kStopColor: |
- break; |
- case kStopOpacity: |
- break; |
- case kStroke: |
-addColor: |
- if (strncmp(lastAttr->c_str(), "url(", 4) == 0 && strncmp(attrValue, "url(", 4) != 0) { |
- parser._startElement("shader"); |
- parser._endElement(); |
- } |
- if (topAttr->equals(*lastAttr)) |
- continue; |
- { |
- bool urlRef = strncmp(attrValue, "url(", 4) == 0; |
- bool colorNone = strcmp(attrValue, "none") == 0; |
- bool lastEqual = parser.fLastColor.equals(attrValue, attrLength); |
- bool newColor = urlRef == false && colorNone == false && lastEqual == false; |
- if (newColor || changed[kOpacity]) { |
- parser._startElement("color"); |
- if (newColor || changed[kOpacity]) { |
- parser._addAttributeLen("color", attrValue, attrLength); |
- parser.fLastColor.set(attrValue, attrLength); |
- } |
- if (changed[kOpacity]) { |
- SkString& opacity = current.f_opacity; |
- parser._addAttributeLen("alpha", opacity.c_str(), opacity.size()); |
- } |
- parser._endElement(); // color |
- } |
- } |
- break; |
- case kStroke_Dasharray: |
- parser._startElement("dash"); |
- SkSVGParser::ConvertToArray(*topAttr); |
- parser._addAttribute("intervals", topAttr->c_str()); |
- parser._endElement(); // dash |
- break; |
- case kStroke_Linecap: |
- case kStroke_Linejoin: |
- case kStroke_Miterlimit: |
- case kStroke_Width: |
- case kStyle: |
- case kTransform: |
- break; |
- default: |
- SkASSERT(0); |
- return false; |
- } |
- } |
- return true; |
-} |
- |
-void SkSVGPaint::Push(SkSVGPaint** head, SkSVGPaint* newRecord) { |
- newRecord->fNext = *head; |
- *head = newRecord; |
-} |
- |
-void SkSVGPaint::Pop(SkSVGPaint** head) { |
- SkSVGPaint* next = (*head)->fNext; |
- *head = next; |
-} |