aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/xml/SkDOM.cpp
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2015-02-20 13:54:40 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-20 13:54:40 -0800
commit7a048690d3cb6b3c1bdef594c3bd4b66f6b400c1 (patch)
tree2bd30bcc04e8db8db2de40e33a2a4435c7bc4072 /src/xml/SkDOM.cpp
parentc1b71d6c30041f01675dd54a77adc9c177afdf44 (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.cpp108
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()