[Scummvm-cvs-logs] SF.net SVN: scummvm: [32768] scummvm/branches/gsoc2008-gui

Tanoku at users.sourceforge.net Tanoku at users.sourceforge.net
Tue Jun 24 21:48:01 CEST 2008


Revision: 32768
          http://scummvm.svn.sourceforge.net/scummvm/?rev=32768&view=rev
Author:   Tanoku
Date:     2008-06-24 12:48:01 -0700 (Tue, 24 Jun 2008)

Log Message:
-----------
Common: 
- Added function to get the active host type as a string.

XMLParser: 
- Added support for ignoring keys while parsing (check documentation). Backwards compatible.
- parserError() has been revamped. Shows all kinds of detailed information regarding the error ala Python

InterfaceManager/ThemeParser:
- DrawData keys and their DrawStep subkeys are now successfully parsed and loaded into structs. That's a win.
- Bug fixes.

Modified Paths:
--------------
    scummvm/branches/gsoc2008-gui/common/util.cpp
    scummvm/branches/gsoc2008-gui/common/util.h
    scummvm/branches/gsoc2008-gui/common/xmlparser.cpp
    scummvm/branches/gsoc2008-gui/common/xmlparser.h
    scummvm/branches/gsoc2008-gui/gui/InterfaceManager.cpp
    scummvm/branches/gsoc2008-gui/gui/InterfaceManager.h
    scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp
    scummvm/branches/gsoc2008-gui/gui/ThemeParser.h

Modified: scummvm/branches/gsoc2008-gui/common/util.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/common/util.cpp	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/common/util.cpp	2008-06-24 19:48:01 UTC (rev 32768)
@@ -481,7 +481,35 @@
 	return gDebugLevelsEnabled;
 }
 
+const char *getHostPlatformString() {
 
+#if defined(__SYMBIAN32__)
+	return "symbian";
+#elif defined(_WIN32_WCE) || defined(_MSC_VER) || defined(__MINGW32__) || defined(UNIX)
+	return "pc";
+#elif defined(__PALMOS_TRAPS__)	|| defined (__PALMOS_ARMLET__)
+	return "palmos";
+#elif defined(__DC__)
+	return "dc";
+#elif defined(__GP32__)
+	return "gp32";
+#elif defined(__PLAYSTATION2__)
+	return "ps2";
+#elif defined(__PSP__)
+	return "psp";
+#elif defined(__amigaos4__)
+	return "amigaos";
+#elif defined (__DS__) //NeilM
+	return "nds";
+#elif defined(__WII__)
+	return "wii";
+#else
+	return "";
+#endif
+
+}
+
+
 }	// End of namespace Common
 
 
@@ -694,3 +722,4 @@
 	str[4] = '\0';
 	return Common::String(str);
 }
+

Modified: scummvm/branches/gsoc2008-gui/common/util.h
===================================================================
--- scummvm/branches/gsoc2008-gui/common/util.h	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/common/util.h	2008-06-24 19:48:01 UTC (rev 32768)
@@ -323,6 +323,13 @@
 uint32 getEnabledSpecialDebugLevels();
 
 
+/**
+ * Return a string containing the name of the currently running host.
+ * E.g. returns "wii" if ScummVM is being run in a Wii, and so on.
+ */
+const char *getHostPlatformString();
+
+
 }	// End of namespace Common
 
 

Modified: scummvm/branches/gsoc2008-gui/common/xmlparser.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/common/xmlparser.cpp	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/common/xmlparser.cpp	2008-06-24 19:48:01 UTC (rev 32768)
@@ -36,35 +36,86 @@
 
 void XMLParser::debug_testEval() {
 	static const char *debugConfigText =
-		"</* lol this is just a moronic test */drawdata id = \"background_default\" cache = true>\n"
-		"<drawstep func = \"roundedsq\" fill = \"gradient\" gradient_start = \"255, 255, 128\" gradient_end = \"128, 128, 128\" size = \"auto\"/>\n"
+		"</* lol this is just a moronic test */drawdata id = \"mainmenu_bg\" cache = true>\n"
+		"<drawstep| func = \"roundedsq\" fill = \"gradient\" gradient_start = \"255, 255, 128\" gradient_end = \"128, 128, 128\" size = \"auto\"/>\n"
 		"//<drawstep func = \"roundedsq\" fill = \"none\" color = /*\"0, 0, 0\"*/\"0, 1, 2\" size = \"auto\"/>\n"
 		"</ drawdata>/* lol this is just a simple test*/\n";
 
 	_text = strdup(debugConfigText);
+	_fileName = strdup("test_parse.xml");
 
 	Common::String test = "12,  125, 125";
 
-	printf("\n\nRegex result: %s.\n\n", test.regexMatch("^[d]*,[d]*,[d]*$", true) ? "Success." : "Fail");
-
 	parse();
 }
 
 
-void XMLParser::parserError(const char *error_string) {
+void XMLParser::parserError(const char *error_string, ...) {
 	_state = kParserError;
-	printf("PARSER ERROR: %s\n", error_string);
+
+	int pos = _pos;
+	int line_count = 1;
+	int line_start = -1;
+	int line_width = 1;
+
+	do {
+		if (_text[pos] == '\n' || _text[pos] == '\r') {
+			line_count++;
+			
+			if (line_start == -1)
+				line_start = pos;
+		}
+	} while (pos-- > 0);
+
+	line_start = MAX(line_start, _pos - 80);
+
+	do {
+		if (_text[line_start + line_width] == '\n' || _text[line_start + line_width] == '\r')
+			break;
+	} while (_text[line_start + line_width++]);
+
+	line_width = MIN(line_width, 80);
+
+	char linestr[81];
+	strncpy(linestr, &_text[line_start] + 1, line_width );
+	linestr[line_width - 1] = 0;
+
+	printf("  File <%s>, line %d:\n", _fileName, line_count);
+
+	printf("%s\n", linestr);
+	for (int i = 1; i < _pos - line_start; ++i)
+		printf(" ");
+
+	printf("^\n");
+	printf("Parser error: ");
+
+	va_list args;
+	va_start(args, error_string);
+	vprintf(error_string, args);
+	va_end(args);
+
+	printf("\n");
 }
 
-void XMLParser::parseActiveKey(bool closed) {
-	if (keyCallback(_activeKey.top()->name) == false) {
-		parserError("Unhandled value inside key.");
-		return;
+bool XMLParser::parseActiveKey(bool closed) {
+	bool ignore = false;
+
+	// check if any of the parents must be ignored.
+	// if a parent is ignored, all children are too.
+	for (int i = _activeKey.size() - 1; i >= 0; --i) {
+		if (_activeKey[i]->ignore)
+			ignore = true;
 	}
+
+	if (ignore == false && keyCallback(_activeKey.top()->name) == false) {
+		return false;
+	}
 	
 	if (closed) {
 		delete _activeKey.pop();
 	}
+
+	return true;
 }
 
 bool XMLParser::parseKeyValue(Common::String keyName) {
@@ -115,7 +166,7 @@
 		switch (_state) {
 			case kParserNeedKey:
 				if (_text[_pos++] != '<') {
-					parserError("Expecting key start.");
+					parserError("Parser expecting key start.");
 					break;
 				}
 
@@ -144,6 +195,7 @@
 				} else {
 					ParserNode *node = new ParserNode;
 					node->name = _token;
+					node->ignore = false;
 					_activeKey.push(node);
 				}
 
@@ -166,9 +218,10 @@
 				selfClosure = (_text[_pos] == '/');
 
 				if ((selfClosure && _text[_pos + 1] == '>') || _text[_pos] == '>') {
-					parseActiveKey(selfClosure);
-					_pos += selfClosure ? 2 : 1;
-					_state = kParserNeedKey;
+					if (parseActiveKey(selfClosure)) {
+						_pos += selfClosure ? 2 : 1;
+						_state = kParserNeedKey;
+					}
 					break;
 				}
 
@@ -181,7 +234,7 @@
 
 			case kParserNeedPropertyOperator:
 				if (_text[_pos++] != '=') 
-					parserError("Unexpected character after key name.");
+					parserError("Syntax error after key name.");
 				else  
 					_state = kParserNeedPropertyValue;
 
@@ -189,7 +242,7 @@
 
 			case kParserNeedPropertyValue:
 				if (!parseKeyValue(_token)) 
-					parserError("Unable to parse key value.");
+					parserError("Invalid key value.");
 				else 
 					_state = kParserNeedPropertyName;
 

Modified: scummvm/branches/gsoc2008-gui/common/xmlparser.h
===================================================================
--- scummvm/branches/gsoc2008-gui/common/xmlparser.h	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/common/xmlparser.h	2008-06-24 19:48:01 UTC (rev 32768)
@@ -74,6 +74,7 @@
 	struct ParserNode {
 		Common::String name;
 		Common::StringMap values;
+		bool ignore;
 	};
 
 	virtual bool parse();
@@ -103,7 +104,13 @@
 	 * Remember to leave the node stack _UNCHANGED_ in your own function. Removal
 	 * of closed keys is done automatically.
 	 *
-	 * Return true if the key was properly handled. False otherwise.
+	 * When parsing a key, one may chose to skip it, e.g. because it's not needed
+	 * on the current configuration. In order to ignore a key, you must set
+	 * the "ignore" field of its KeyNode struct to "true": The key and all its children
+	 * will then be automatically ignored by the parser.
+	 *
+	 * Return true if the key was properly handled (this includes the case when the
+	 * key is being ignored). False otherwise.
 	 * See the sample implementation in GUI::ThemeParser.
 	 */
 	virtual bool keyCallback(Common::String keyName) {
@@ -120,13 +127,12 @@
 	 * node stack and calls the keyCallback.
 	 * There's no reason to overload this.
 	 */
-	virtual void parseActiveKey(bool closed);
+	virtual bool parseActiveKey(bool closed);
 
 	/**
 	 * Prints an error message when parsing fails and stops the parser.
-	 * TODO: More descriptive error messages.
 	 */
-	virtual void parserError(const char *errorString);
+	virtual void parserError(const char *errorString, ...);
 
 	/**
 	 * Skips spaces/whitelines etc. Returns true if any spaces were skipped.
@@ -163,7 +169,7 @@
 
 		if (_text[_pos] == '/' && _text[_pos + 1] == '/') {
 			_pos += 2;
-			while (_text[_pos] && _text[_pos] != '\n')
+			while (_text[_pos] && _text[_pos] != '\n' && _text[_pos] != '\r')
 				_pos++;
 			return true;
 		}
@@ -194,6 +200,7 @@
 
 	int _pos; /** Current position on the XML buffer. */
 	char *_text; /** Buffer with the text being parsed */
+	char *_fileName;
 
 	ParserState _state; /** Internal state of the parser */
 

Modified: scummvm/branches/gsoc2008-gui/gui/InterfaceManager.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/InterfaceManager.cpp	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/gui/InterfaceManager.cpp	2008-06-24 19:48:01 UTC (rev 32768)
@@ -38,11 +38,44 @@
 
 using namespace Graphics;
 
+const char *InterfaceManager::kDrawDataStrings[] = {
+	"mainmenu_bg",
+	"special_bg",
+	"plain_bg",
+	"default_bg",
+
+	"button_idle",
+	"button_hover",
+
+	"surface",
+
+	"slider_full",
+	"slider_empty",
+
+	"checkbox_enabled",
+	"checkbox_disabled",
+
+	"tab",
+
+	"scrollbar_base",
+	"scrollbar_top",
+	"scrollbar_bottom",
+	"scrollbar_handle",
+
+	"popup",
+	"caret",
+	"separator"
+};
+
 InterfaceManager::InterfaceManager() : 
 	_vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), 
 	_screen(0), _bytesPerPixel(0) {
 	_system = g_system;
 
+	for (int i = 0; i < kDrawDataMAX; ++i) {
+		_widgets[i] = 0;
+	}
+
 	setGraphicsMode(kGfxStandard16bit);
 }
 
@@ -78,10 +111,26 @@
 }
 
 void InterfaceManager::addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step) {
-	_widgets[getDrawDataId(drawDataId)]->_steps.push_back(step);
+	DrawData id = getDrawDataId(drawDataId);
+	
+	assert(_widgets[id] != 0);
+	_widgets[id]->_steps.push_back(step);
 }
 
+bool InterfaceManager::addDrawData(DrawData data_id, bool cached) {
+	assert(data_id >= 0 && data_id < kDrawDataMAX);
 
+	if (_widgets[data_id] != 0)
+		return false;
+
+	_widgets[data_id] = new WidgetDrawData;
+	_widgets[data_id]->_cached = cached;
+	_widgets[data_id]->_type = data_id;
+	_widgets[data_id]->_scaled = false;
+
+	return true;
+}
+
 bool InterfaceManager::init() {
 	return false;
 }

Modified: scummvm/branches/gsoc2008-gui/gui/InterfaceManager.h
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/InterfaceManager.h	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/gui/InterfaceManager.h	2008-06-24 19:48:01 UTC (rev 32768)
@@ -47,6 +47,8 @@
 	friend class Common::Singleton<SingletonBaseType>;
 	typedef Common::String String;
 
+	static const char *kDrawDataStrings[];
+
 public:
 	enum Graphics_Mode {
 		kGfxDisabled = 0,
@@ -168,10 +170,15 @@
 	void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
 
 	DrawData getDrawDataId(Common::String &name) {
-		return (DrawData)0;
+		for (int i = 0; i < kDrawDataMAX; ++i)
+			if (name.compareToIgnoreCase(kDrawDataStrings[i]) == 0)
+				return (DrawData)i;
+
+		return (DrawData)-1;
 	}
 
 	void addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step);
+	bool addDrawData(DrawData data_id, bool cached);
 
 protected:
 	template<typename PixelType> void screenInit();

Modified: scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp	2008-06-24 19:48:01 UTC (rev 32768)
@@ -42,6 +42,15 @@
 ThemeParser::ThemeParser() : XMLParser() {
 	_callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP;
 	_callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA;
+
+	_drawFunctions["circle"]  = &Graphics::VectorRenderer::drawCallback_CIRCLE;
+	_drawFunctions["square"]  = &Graphics::VectorRenderer::drawCallback_SQUARE;
+	_drawFunctions["roundedsq"]  = &Graphics::VectorRenderer::drawCallback_ROUNDSQ;
+	_drawFunctions["bevelsq"]  = &Graphics::VectorRenderer::drawCallback_BEVELSQ;
+	_drawFunctions["line"]  = &Graphics::VectorRenderer::drawCallback_LINE;
+	_drawFunctions["triangle"]  = &Graphics::VectorRenderer::drawCallback_TRIANGLE;
+	_drawFunctions["fill"]  = &Graphics::VectorRenderer::drawCallback_FILLSURFACE;
+	_drawFunctions["void"]  = &Graphics::VectorRenderer::drawCallback_VOID;
 }
 
 bool ThemeParser::keyCallback(Common::String keyName) {
@@ -73,9 +82,13 @@
 }
 
 bool ThemeParser::parserCallback_DRAWSTEP() {
-	ParserNode *stepNode = _activeKey.pop();
-	ParserNode *drawdataNode = _activeKey.pop();
+	ParserNode *stepNode = _activeKey.top();
 
+	// 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];
+
 	assert(stepNode->name == "drawstep");
 	assert(drawdataNode->name == "drawdata");
 	assert(drawdataNode->values.contains("id"));
@@ -85,32 +98,108 @@
 	Common::String functionName = stepNode->values["func"]; 
 
 	if (_drawFunctions.contains(functionName) == false) {
-		parserError("Invalid drawing function in draw step.");
-		_activeKey.push(drawdataNode);
-		_activeKey.push(stepNode);
+		parserError("%s is not a valid drawing function name", functionName.c_str());
 		return false;
 	}	
 
 	drawstep->drawingCall = _drawFunctions[functionName];
 
-	if (stepNode->values.contains("stroke")) {
+	uint32 red, green, blue;
 
+/**
+ * Helper macro to sanitize and assign an integer value from a key
+ * to the draw step.
+ *
+ * @param struct_name Name of the field of a DrawStep struct that must be
+ *                    assigned.
+ * @param key_name Name as STRING of the key identifier as it appears in the
+ *                 theme description format.
+ */
+#define __PARSER_ASSIGN_INT(struct_name, key_name) \
+	if (stepNode->values.contains(key_name)) { \
+		if (!validateKeyInt(stepNode->values[key_name].c_str())) \
+			return false; \
+		\
+		drawstep->struct_name = atoi(stepNode->values[key_name].c_str()); \
 	}
 
-	if (functionName == "roundedsq") {
+/**
+ * Helper macro to sanitize and assign a RGB value from a key to the draw
+ * step. RGB values have the following syntax: "R, G, B".
+ *
+ * TODO: Handle also specific name colors such as "red", "green", etc.
+ *
+ * @param struct_name Name of the field of a DrawStep struct that must be
+ *                    assigned.
+ * @param key_name Name as STRING of the key identifier as it appears in the
+ *                 theme description format.
+ */
+#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) \
+			return false; \
+		\
+		drawstep->struct_name.r = red; \
+		drawstep->struct_name.g = green; \
+		drawstep->struct_name.b = blue; \
+	}
 
+	__PARSER_ASSIGN_INT(stroke, "stroke");
+	__PARSER_ASSIGN_INT(shadow, "shadow");
+	__PARSER_ASSIGN_INT(factor, "gradient_factor");
+
+	__PARSER_ASSIGN_RGB(fgColor, "fg_color");
+	__PARSER_ASSIGN_RGB(bgColor, "bg_color");
+	__PARSER_ASSIGN_RGB(gradColor1, "gradient_start");
+	__PARSER_ASSIGN_RGB(gradColor2, "gradient_end");
+
+	if (functionName == "roundedsq" || functionName == "circle") {
+		__PARSER_ASSIGN_INT(radius, "radius");
 	}
 
-	g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep);
+	if (functionName == "bevelsq") {
+		__PARSER_ASSIGN_INT(extraData, "bevel");
+	}
 
-	_activeKey.push(drawdataNode);
-	_activeKey.push(stepNode);
+#undef __PARSER_ASSIGN_INT
+#undef __PARSER_ASSIGN_RGB
 
+	g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep);
 	return true;
 }
 
 bool ThemeParser::parserCallback_DRAWDATA() {
-	printf("Drawdata callback!\n");
+	ParserNode *drawdataNode = _activeKey.top();
+	bool cached = false;
+
+	if (drawdataNode->values.contains("id") == false) {
+		parserError("DrawData notes must contain an identifier.");
+		return false;
+	}
+
+	InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]);
+
+	if (id == -1) {
+		parserError("%d is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str());
+		return false;
+	}
+
+	if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") {
+		cached = true;
+	}
+
+	if (drawdataNode->values.contains("platform")) {
+		if (drawdataNode->values["platform"].compareToIgnoreCase(Common::getHostPlatformString()) != 0) {
+			drawdataNode->ignore = true;
+			return true;
+		}
+	}
+
+	if (g_InterfaceManager.addDrawData(id, cached) == false) {
+		parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform.");
+		return false;
+	}
+
 	return true;
 }
 

Modified: scummvm/branches/gsoc2008-gui/gui/ThemeParser.h
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/ThemeParser.h	2008-06-24 19:44:49 UTC (rev 32767)
+++ scummvm/branches/gsoc2008-gui/gui/ThemeParser.h	2008-06-24 19:48:01 UTC (rev 32768)
@@ -321,6 +321,24 @@
 	bool parserCallback_DRAWSTEP();
 	bool parserCallback_DRAWDATA();
 
+	bool validateKeyIntSigned(const char *key) {
+		if (!isdigit(*key) && *key != '+' && *key != '-')
+			return false;
+
+		return validateKeyInt(key + 1);
+	}
+
+	bool validateKeyInt(const char *key) {
+		if (*key == 0)
+			return false;
+
+		while (*key)
+			if (!isdigit(*key++))
+				return false;
+
+		return true;
+	}
+
 	Graphics::DrawStep *newDrawStep();
 
 	Common::HashMap<Common::String, DrawingFunctionCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _drawFunctions;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list