diff options
author | 2015-02-20 13:54:40 -0800 | |
---|---|---|
committer | 2015-02-20 13:54:40 -0800 | |
commit | 7a048690d3cb6b3c1bdef594c3bd4b66f6b400c1 (patch) | |
tree | 2bd30bcc04e8db8db2de40e33a2a4435c7bc4072 /src/xml/SkDOM.cpp | |
parent | c1b71d6c30041f01675dd54a77adc9c177afdf44 (diff) |
[SVGDevice] Text whitespace unittest
Plumb SkDOM as needed to make it suitable for an SkXMLWriter backend.
Also fix a potential null typeface issue in
SkSVGDevice::AutoElement::addTextAttributes().
R=reed@google.com,mtklein@google.com
Review URL: https://codereview.chromium.org/940283002
Diffstat (limited to 'src/xml/SkDOM.cpp')
-rw-r--r-- | src/xml/SkDOM.cpp | 108 |
1 files changed, 60 insertions, 48 deletions
diff --git a/src/xml/SkDOM.cpp b/src/xml/SkDOM.cpp index 98546089fa..eb1bc092fe 100644 --- a/src/xml/SkDOM.cpp +++ b/src/xml/SkDOM.cpp @@ -8,11 +8,12 @@ #include "SkDOM.h" +#include "SkStream.h" +#include "SkXMLWriter.h" ///////////////////////////////////////////////////////////////////////// #include "SkXMLParser.h" - bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) { const char* elemName = dom.getName(node); @@ -199,19 +200,22 @@ static char* dupstr(SkChunkAlloc* chunk, const char src[]) } class SkDOMParser : public SkXMLParser { - bool fNeedToFlush; public: SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) { + fAlloc->reset(); fRoot = NULL; fLevel = 0; fNeedToFlush = true; } SkDOM::Node* getRoot() const { return fRoot; } SkXMLParserError fParserError; + protected: void flushAttributes() { + SkASSERT(fLevel > 0); + int attrCount = fAttrs.count(); SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr), @@ -220,7 +224,7 @@ protected: node->fName = fElemName; node->fFirstChild = NULL; node->fAttrCount = SkToU16(attrCount); - node->fType = SkDOM::kElement_Type; + node->fType = fElemType; if (fRoot == NULL) { @@ -240,24 +244,20 @@ protected: fAttrs.reset(); } - virtual bool onStartElement(const char elem[]) - { - if (fLevel > 0 && fNeedToFlush) - this->flushAttributes(); - fNeedToFlush = true; - fElemName = dupstr(fAlloc, elem); - ++fLevel; + + bool onStartElement(const char elem[]) override { + this->startCommon(elem, SkDOM::kElement_Type); return false; } - virtual bool onAddAttribute(const char name[], const char value[]) - { + + bool onAddAttribute(const char name[], const char value[]) override { SkDOM::Attr* attr = fAttrs.append(); attr->fName = dupstr(fAlloc, name); attr->fValue = dupstr(fAlloc, value); return false; } - virtual bool onEndElement(const char elem[]) - { + + bool onEndElement(const char elem[]) override { --fLevel; if (fNeedToFlush) this->flushAttributes(); @@ -279,20 +279,40 @@ protected: parent->fFirstChild = prev; return false; } + + bool onText(const char text[], int len) override { + SkString str(text, len); + this->startCommon(str.c_str(), SkDOM::kText_Type); + this->SkDOMParser::onEndElement(str.c_str()); + + return false; + } + private: + void startCommon(const char elem[], SkDOM::Type type) { + if (fLevel > 0 && fNeedToFlush) + this->flushAttributes(); + + fNeedToFlush = true; + fElemName = dupstr(fAlloc, elem); + fElemType = type; + ++fLevel; + } + SkTDArray<SkDOM::Node*> fParentStack; - SkChunkAlloc* fAlloc; - SkDOM::Node* fRoot; + SkChunkAlloc* fAlloc; + SkDOM::Node* fRoot; + bool fNeedToFlush; // state needed for flushAttributes() SkTDArray<SkDOM::Attr> fAttrs; char* fElemName; + SkDOM::Type fElemType; int fLevel; }; const SkDOM::Node* SkDOM::build(const char doc[], size_t len) { - fAlloc.reset(); SkDOMParser parser(&fAlloc); if (!parser.parse(doc, len)) { @@ -310,6 +330,11 @@ const SkDOM::Node* SkDOM::build(const char doc[], size_t len) static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) { const char* elem = dom.getName(node); + if (dom.getType(node) == SkDOM::kText_Type) { + SkASSERT(dom.countChildren(node) == 0); + parser->text(elem, SkToInt(strlen(elem))); + return; + } parser->startElement(elem); @@ -331,7 +356,6 @@ static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) { - fAlloc.reset(); SkDOMParser parser(&fAlloc); walk_dom(dom, node, &parser); @@ -340,6 +364,21 @@ const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) return fRoot; } +SkXMLParser* SkDOM::beginParsing() { + SkASSERT(!fParser); + fParser.reset(SkNEW_ARGS(SkDOMParser, (&fAlloc))); + + return fParser.get(); +} + +const SkDOM::Node* SkDOM::finishParsing() { + SkASSERT(fParser); + fRoot = fParser->getRoot(); + fParser.free(); + + return fRoot; +} + ////////////////////////////////////////////////////////////////////////// int SkDOM::countChildren(const Node* node, const char elem[]) const @@ -427,41 +466,14 @@ bool SkDOM::hasBool(const Node* node, const char name[], bool target) const #ifdef SK_DEBUG -static void tab(int level) -{ - while (--level >= 0) - SkDebugf("\t"); -} - void SkDOM::dump(const Node* node, int level) const { if (node == NULL) node = this->getRootNode(); - if (node) - { - tab(level); - SkDebugf("<%s", this->getName(node)); - - const Attr* attr = node->attrs(); - const Attr* stop = attr + node->fAttrCount; - for (; attr < stop; attr++) - SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue); - const Node* child = this->getFirstChild(node); - if (child) - { - SkDebugf(">\n"); - while (child) - { - this->dump(child, level+1); - child = this->getNextSibling(child); - } - tab(level); - SkDebugf("</%s>\n", node->fName); - } - else - SkDebugf("/>\n"); - } + SkDebugWStream debugStream; + SkXMLStreamWriter xmlWriter(&debugStream); + xmlWriter.writeDOM(*this, node, false); } void SkDOM::UnitTest() |