diff options
author | Vicent Marti | 2008-06-25 17:56:00 +0000 |
---|---|---|
committer | Vicent Marti | 2008-06-25 17:56:00 +0000 |
commit | 917b750839282f768178d8436d54deda3078a1f6 (patch) | |
tree | 4f9fa51ef17c17e0fafc7efbdb39274fb8450654 | |
parent | 2fcbb970056c9b596699f22d949fe17f9df791d3 (diff) | |
download | scummvm-rg350-917b750839282f768178d8436d54deda3078a1f6.tar.gz scummvm-rg350-917b750839282f768178d8436d54deda3078a1f6.tar.bz2 scummvm-rg350-917b750839282f768178d8436d54deda3078a1f6.zip |
XMLParser:
- Bug fixes.
ThemeParser:
- Support for palette colors.
- Expanded theme syntax.
svn-id: r32787
-rw-r--r-- | common/xmlparser.cpp | 40 | ||||
-rw-r--r-- | common/xmlparser.h | 12 | ||||
-rw-r--r-- | gui/ThemeParser.cpp | 82 | ||||
-rw-r--r-- | gui/ThemeParser.h | 9 |
4 files changed, 116 insertions, 27 deletions
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index bb8754d480..b2178afbd0 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -36,14 +36,18 @@ using namespace Graphics; void XMLParser::debug_testEval() { static const char *debugConfigText = - "</* lol this is just assa moronic test */drawdata id = \"mainmenu_bg\" cache = true>\n" - "<drawstep func = \"roundedsq\" fill = \"none\" color = \"0, 1, 2\" size = \"auto\" />\n" - "<drawstep func = \"roundedsqXD\" fill = \"none\" color = \"0, 1, 2\" size = \"auto\"/>\n" - "</ drawdata>/* lol this is just a simple test*/\n" - "I loled"; + "<render_info>\n" + "<palette>\n" + "<color name = \"red\" rgb = \"255, 255, 255\"/>\n" + "</palette>\n" + "<drawdata id = \"mainmenu_bg\" cache = true>\n" + "<drawstep func = \"roundedsq\" radius = 23 fill = \"none\" color = \"0, 1, 2\" size = \"auto\" />\n" + "<drawstep func = \"roundedsq\" radius = 15 fill = \"none\" color = \"red\" size = \"auto\"/>\n" + "</drawdata>/* lol this is just a simple test*/\n" + "</render_info>"; loadBuffer(debugConfigText); - _fileName = strdup("test_parse.xml"); + _fileName = "test_parse.xml"; parse(); } @@ -54,13 +58,13 @@ bool XMLParser::parserError(const char *errorString, ...) { int pos = _pos; int lineCount = 1; - int lineStart = -1; + int lineStart = 0; do { if (_text[pos] == '\n' || _text[pos] == '\r') { lineCount++; - if (lineStart == -1) + if (lineStart == 0) lineStart = MAX(pos + 1, _pos - 60); } } while (pos-- > 0); @@ -69,14 +73,17 @@ bool XMLParser::parserError(const char *errorString, ...) { _text.stream()->seek(lineStart, SEEK_SET); _text.stream()->readLine(lineStr, 70); - printf(" File <%s>, line %d:\n", _fileName, lineCount); + printf(" File <%s>, line %d:\n", _fileName.c_str(), lineCount); - printf("%s%s%s\n", - lineStr[0] == '<' ? "" : "...", - lineStr[strlen(lineStr) - 1] == '>' ? "" : "...", - lineStr); + bool startFull = lineStr[0] == '<'; + bool endFull = lineStr[strlen(lineStr) - 1] == '>'; - for (int i = 0; i < _pos - lineStart + 3; ++i) + printf("%s%s%s\n", startFull ? "" : "...", endFull ? "" : "...", lineStr); + + if (!startFull) + lineStart -= 3; + + for (int i = 0; i < _pos - lineStart; ++i) printf(" "); printf("^\n"); @@ -185,12 +192,15 @@ bool XMLParser::parse() { } if (activeClosure) { - if (_activeKey.empty() || _token != _activeKey.top()->name) + if (_activeKey.empty() || _token != _activeKey.top()->name) { parserError("Unexpected closure."); + break; + } } else { ParserNode *node = new ParserNode; node->name = _token; node->ignore = false; + node->depth = _activeKey.size(); _activeKey.push(node); } diff --git a/common/xmlparser.h b/common/xmlparser.h index 5b03f54b9d..548b9cf3e2 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -113,6 +113,7 @@ public: Common::String name; Common::StringMap values; bool ignore; + int depth; }; virtual bool loadFile(const char *filename) { @@ -137,13 +138,20 @@ public: * Returns the active node being parsed (the one on top of * the node stack). */ - ParserNode *activeNode() { + ParserNode *getActiveNode() { if (!_activeKey.empty()) return _activeKey.top(); return 0; } + /** + * Returns the parent of a given node in the stack. + */ + ParserNode *getParentNode(ParserNode *child) { + return child->depth > 0 ? _activeKey[child->depth - 1] : 0; + } + protected: /** * The keycallback function must be overloaded by inheriting classes @@ -255,7 +263,7 @@ protected: int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ - char *_fileName; + Common::String _fileName; ParserState _state; /** Internal state of the parser */ diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 03feaaa96d..d9d8c9cd7c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -42,6 +42,9 @@ using namespace Common; ThemeParser::ThemeParser() : XMLParser() { _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; + _callbacks["palette"] = &ThemeParser::parserCallback_palette; + _callbacks["color"] = &ThemeParser::parserCallback_color; + _callbacks["render_info"] = &ThemeParser::parserCallback_renderInfo; _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; @@ -81,20 +84,69 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { return step; } +bool ThemeParser::parserCallback_renderInfo() { + ParserNode *infoNode = getActiveNode(); + + assert(infoNode->name == "render_info"); + + if (getParentNode(infoNode) != 0) + return parserError("<render_info> keys must be root elements."); + + // TODO: Skip key if it's not for this platform. + + return true; +} + +bool ThemeParser::parserCallback_palette() { + ParserNode *paletteNode = getActiveNode(); + + assert(paletteNode->name == "palette"); + + if (getParentNode(paletteNode) == 0 || getParentNode(paletteNode)->name != "render_info") + return parserError("Palette keys must be contained inside a <render_info> section."); + + return true; +} + +bool ThemeParser::parserCallback_color() { + ParserNode *colorNode = getActiveNode(); + + if (getParentNode(colorNode) == 0 || getParentNode(colorNode)->name != "palette") + return parserError("Colors must be specified inside <palette> tags."); + + if (!colorNode->values.contains("name") || !colorNode->values.contains("rgb")) + return parserError("Color keys must contain 'name' and 'rgb' values for the color."); + + Common::String name = colorNode->values["name"]; + + if (_palette.contains(name)) + return parserError("Color '%s' has already been defined.", name.c_str()); + + int red, green, blue; + + if (sscanf(colorNode->values["rgb"].c_str(), "%d, %d, %d", &red, &green, &blue) != 3 || + red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) + return parserError("Error when parsing RGB values for palette color '%s'", name.c_str());\ + + _palette[name].r = red; + _palette[name].g = green; + _palette[name].b = blue; + + return true; +} + + bool ThemeParser::parserCallback_DRAWSTEP() { ParserNode *stepNode = _activeKey.top(); + ParserNode *drawdataNode = getParentNode(stepNode); - // HACK: Any cleaner way to access the second item from - // the top without popping? Let's keep it this way and hope - // the internal representation doesn't change - ParserNode *drawdataNode = _activeKey[_activeKey.size() - 2]; + if (!drawdataNode || drawdataNode->name != "drawdata") + return parserError("DrawStep keys must be located inside a DrawData set."); assert(stepNode->name == "drawstep"); - assert(drawdataNode->name == "drawdata"); assert(drawdataNode->values.contains("id")); Graphics::DrawStep *drawstep = newDrawStep(); - Common::String functionName = stepNode->values["func"]; if (_drawFunctions.contains(functionName) == false) @@ -102,7 +154,7 @@ bool ThemeParser::parserCallback_DRAWSTEP() { drawstep->drawingCall = _drawFunctions[functionName]; - uint32 red, green, blue, w, h; + int red, green, blue, w, h; Common::String val; /** @@ -138,9 +190,14 @@ bool ThemeParser::parserCallback_DRAWSTEP() { */ #define __PARSER_ASSIGN_RGB(struct_name, key_name) \ if (stepNode->values.contains(key_name)) { \ - if (sscanf(stepNode->values[key_name].c_str(), "%d, %d, %d", &red, &green, &blue) != 3 || \ + val = stepNode->values[key_name]; \ + if (_palette.contains(val)) { \ + red = _palette[val].r; \ + green = _palette[val].g; \ + blue = _palette[val].b; \ + } else if (sscanf(val.c_str(), "%d, %d, %d", &red, &green, &blue) != 3 || \ red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) \ - return parserError("Error when parsing color struct '%s'", stepNode->values[key_name].c_str());\ + return parserError("Error when parsing color struct '%s'", val.c_str());\ \ drawstep->struct_name.r = red; \ drawstep->struct_name.g = green; \ @@ -221,8 +278,13 @@ bool ThemeParser::parserCallback_DRAWDATA() { ParserNode *drawdataNode = _activeKey.top(); bool cached = false; + assert(drawdataNode->name == "drawdata"); + + if (getParentNode(drawdataNode) == 0 || getParentNode(drawdataNode)->name != "render_info") + return parserError("DrawData keys must be contained inside a <render_info> section."); + if (drawdataNode->values.contains("id") == false) - return parserError("DrawData notes must contain an identifier."); + return parserError("DrawData keys must contain an identifier."); InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 4103098a63..c012e4fb45 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -320,6 +320,9 @@ protected: bool parserCallback_DRAWSTEP(); bool parserCallback_DRAWDATA(); + bool parserCallback_palette(); + bool parserCallback_color(); + bool parserCallback_renderInfo(); bool validateKeyIntSigned(const char *key) { if (!isdigit(*key) && *key != '+' && *key != '-') @@ -343,6 +346,12 @@ protected: Common::HashMap<Common::String, DrawingFunctionCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _drawFunctions; Common::HashMap<Common::String, ParserCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _callbacks; + + struct PaletteColor { + uint8 r, g, b; + }; + + Common::HashMap<Common::String, PaletteColor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _palette; }; } |