Example #1
0
bool ThemeParser::parserCallback_layout(ParserNode *node) {
	int spacing = -1;

	if (node->values.contains("spacing")) {
		if (!parseIntegerKey(node->values["spacing"].c_str(), 1, &spacing))
			return false;
	}

	if (node->values["type"] == "vertical")
		_theme->getEvaluator()->addLayout(GUI::ThemeLayout::kLayoutVertical, spacing, node->values["center"] == "true");
	else if (node->values["type"] == "horizontal")
		_theme->getEvaluator()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, spacing, node->values["center"] == "true");
	else
		return parserError("Invalid layout type. Only 'horizontal' and 'vertical' layouts allowed.");


	if (node->values.contains("padding")) {
		int paddingL, paddingR, paddingT, paddingB;

		if (!parseIntegerKey(node->values["padding"].c_str(), 4, &paddingL, &paddingR, &paddingT, &paddingB))
			return false;

		_theme->getEvaluator()->addPadding(paddingL, paddingR, paddingT, paddingB);
	}

	return true;
}
Example #2
0
bool FontResource::parserCallback_font(ParserNode *node) {
	// Get the attributes of the font
	Common::String bitmapFilename = node->values["bitmap"];

	if (!parseIntegerKey(node->values["lineheight"], 1, &_lineHeight)) {
		warning("Illegal or missing lineheight attribute in <font> tag in \"%s\". Assuming default (\"%d\").",
		                 getFileName().c_str(), DEFAULT_LINEHEIGHT);
		_lineHeight = DEFAULT_LINEHEIGHT;
	}

	if (!parseIntegerKey(node->values["gap"], 1, &_gapWidth)) {
		warning("Illegal or missing gap attribute in <font> tag in \"%s\". Assuming default (\"%d\").",
		                 getFileName().c_str(), DEFAULT_GAPWIDTH);
		_gapWidth = DEFAULT_GAPWIDTH;
	}
	
	// Get a reference to the package manager
	assert(_pKernel);
	PackageManager *pPackage = _pKernel->getPackage();
	assert(pPackage);

	// Get the full path and filename for the bitmap resource
	_bitmapFileName = pPackage->getAbsolutePath(bitmapFilename);
	if (_bitmapFileName == "") {
		error("Image file \"%s\" was specified in <font> tag of \"%s\" but could not be found.",
		               _bitmapFileName.c_str(), getFileName().c_str());
	}

	// Pre-cache the resource
	if (!_pKernel->getResourceManager()->precacheResource(_bitmapFileName)) {
		error("Could not precache \"%s\".", _bitmapFileName.c_str());
	}

	return true;
}
Example #3
0
bool ThemeParser::parserCallback_widget(ParserNode *node) {
	Common::String var;

	if (getParentNode(node)->name == "globals") {

		if (resolutionCheck(node->values["resolution"]) == false) {
			node->ignore = true;
			return true;
		}

		var = "Globals." + node->values["name"] + ".";
		if (!parseCommonLayoutProps(node, var))
			return parserError("Error parsing Layout properties of '%s'.", var.c_str());

	} else {
		// FIXME: Shouldn't we distinguish the name/id and the label of a widget?
		var = node->values["name"];
		int width = -1;
		int height = -1;
		bool enabled = true;

		if (node->values.contains("enabled")) {
			if (node->values["enabled"] == "false")
				enabled = false;
			else if (node->values["enabled"] != "true")
				return parserError("Invalid value for Widget enabling (expecting true/false)");
		}

		if (node->values.contains("width")) {
			if (_theme->getEvaluator()->hasVar(node->values["width"]) == true)
				width = _theme->getEvaluator()->getVar(node->values["width"]);

			else if (!parseIntegerKey(node->values["width"].c_str(), 1, &width))
				return parserError("Corrupted width value in key for %s", var.c_str());
		}

		if (node->values.contains("height")) {
			if (_theme->getEvaluator()->hasVar(node->values["height"]) == true)
				height = _theme->getEvaluator()->getVar(node->values["height"]);

			else if (!parseIntegerKey(node->values["height"].c_str(), 1, &height))
				return parserError("Corrupted height value in key for %s", var.c_str());
		}

		Graphics::TextAlign alignH = Graphics::kTextAlignLeft;

		if (node->values.contains("textalign")) {
			if((alignH = parseTextHAlign(node->values["textalign"])) == Graphics::kTextAlignInvalid)
				return parserError("Invalid value for text alignment.");
		}

		_theme->getEvaluator()->addWidget(var, width, height, node->values["type"], enabled, alignH);
	}

	return true;
}
bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) {
	assert(!_mode->resolution.empty());

	String res = node->values["resolution"];

	if (res != _mode->resolution) {
		node->ignore = true;
		return true;
	}

	_mode->bitmapName = node->values["bitmap"];

	SeekableReadStream *file = _keyboard->_fileArchive->createReadStreamForMember(_mode->bitmapName);
	if (!file)
		return parserError("Bitmap '" + _mode->bitmapName + "' not found");

	const Graphics::PixelFormat format = g_system->getOverlayFormat();

	{
		Graphics::BitmapDecoder bmp;
		if (!bmp.loadStream(*file))
			return parserError("Error loading bitmap '" + _mode->bitmapName + "'");

		_mode->image = bmp.getSurface()->convertTo(format);
	}

	delete file;

	int r, g, b;
	if (node->values.contains("transparent_color")) {
		if (!parseIntegerKey(node->values["transparent_color"], 3, &r, &g, &b))
			return parserError("Could not parse color value");
	} else {
		// default to purple
		r = 255;
		g = 0;
		b = 255;
	}
	_mode->transparentColor = format.RGBToColor(r, g, b);

	if (node->values.contains("display_font_color")) {
		if (!parseIntegerKey(node->values["display_font_color"], 3, &r, &g, &b))
			return parserError("Could not parse color value");
	} else {
		r = g = b = 0; // default to black
	}
	_mode->displayFontColor = format.RGBToColor(r, g, b);

	_layoutParsed = true;

	return true;
}
Example #5
0
bool ThemeParser::parserCallback_dialog(ParserNode *node) {
	Common::String var = "Dialog." + node->values["name"];
	bool enabled = true;
	int inset = 0;

	if (resolutionCheck(node->values["resolution"]) == false) {
		node->ignore = true;
		return true;
	}

	if (node->values.contains("enabled")) {
		if (!Common::parseBool(node->values["enabled"], enabled))
			return parserError("Invalid value for Dialog enabling (expecting true/false)");
	}

	if (node->values.contains("inset")) {
		if (!parseIntegerKey(node->values["inset"], 1, &inset))
			return false;
	}

	_theme->getEvaluator()->addDialog(var, node->values["overlays"], enabled, inset);

	if (node->values.contains("shading")) {
		int shading = 0;
		if (node->values["shading"] == "dim")
			shading = 1;
		else if (node->values["shading"] == "luminance")
			shading = 2;
		else return parserError("Invalid value for Dialog background shading.");

		_theme->getEvaluator()->setVar(var + ".Shading", shading);
	}

	return true;
}
Example #6
0
bool AnimationResource::parserCallback_animation(ParserNode *node) {
    if (!parseIntegerKey(node->values["fps"], 1, &_FPS) || (_FPS < MIN_FPS) || (_FPS > MAX_FPS)) {
        return parserError("Illegal or missing fps attribute in <animation> tag in \"%s\". Assuming default (\"%d\").",
                           getFileName().c_str(), DEFAULT_FPS);
    }

    // Loop type value
    const char *loopTypeString = node->values["type"].c_str();

    if (strcmp(loopTypeString, "oneshot") == 0) {
        _animationType = Animation::AT_ONESHOT;
    } else if (strcmp(loopTypeString, "loop") == 0) {
        _animationType = Animation::AT_LOOP;
    } else if (strcmp(loopTypeString, "jojo") == 0) {
        _animationType = Animation::AT_JOJO;
    } else {
        warning("Illegal type value (\"%s\") in <animation> tag in \"%s\". Assuming default (\"loop\").",
                loopTypeString, getFileName().c_str());
        _animationType = Animation::AT_LOOP;
    }

    // Calculate the milliseconds required per frame
    // FIXME: Double check variable naming. Based on the constant, it may be microseconds
    _millisPerFrame = 1000000 / _FPS;

    return true;
}
Example #7
0
bool ThemeParser::parserCallback_cursor(ParserNode *node) {
	if (resolutionCheck(node->values["resolution"]) == false) {
		node->ignore = true;
		return true;
	}

	int spotx, spoty, scale;

	if (!parseIntegerKey(node->values["hotspot"].c_str(), 2, &spotx, &spoty))
		return parserError("Error parsing cursor Hot Spot coordinates.");

	if (!parseIntegerKey(node->values["scale"].c_str(), 1, &scale))
		return parserError("Error parsing cursor scale.");

	if (!_theme->createCursor(node->values["file"], spotx, spoty, scale))
		return parserError("Error creating Bitmap Cursor.");

	return true;
}
bool VirtualKeyboardParser::parseRect(Rect &rect, const String& coords) {
    int x1, y1, x2, y2;
    if (!parseIntegerKey(coords, 4, &x1, &y1, &x2, &y2))
        return parserError("Invalid coords for rect area");
    rect.left = x1;
    rect.top = y1;
    rect.right = x2;
    rect.bottom = y2;
    if (!rect.isValidRect())
        return parserError("Rect area is not a valid rectangle");
    return true;
}
Example #9
0
bool ThemeParser::parserCallback_space(ParserNode *node) {
	int size = -1;

	if (node->values.contains("size")) {
		if (_theme->getEvaluator()->hasVar(node->values["size"]))
			size = _theme->getEvaluator()->getVar(node->values["size"]);

		else if (!parseIntegerKey(node->values["size"].c_str(), 1, &size))
			return parserError("Invalid value for Spacing size.");
	}

	_theme->getEvaluator()->addSpace(size);
	return true;
}
Example #10
0
bool FontResource::parserCallback_character(ParserNode *node) {
	// Get the attributes of the character
	int charCode, top, left, right, bottom;

	if (!parseIntegerKey(node->values["code"], 1, &charCode) || (charCode < 0) || (charCode >= 256)) {
		return parserError("Illegal or missing code attribute in <character> tag in \"%s\".", getFileName().c_str());
	}

	if (!parseIntegerKey(node->values["top"], 1, &top) || (top < 0)) {
		return parserError("Illegal or missing top attribute in <character> tag in \"%s\".", getFileName().c_str());
	}
	if (!parseIntegerKey(node->values["left"], 1, &left) || (left < 0)) {
		return parserError("Illegal or missing left attribute in <character> tag in \"%s\".", getFileName().c_str());
	}
	if (!parseIntegerKey(node->values["right"], 1, &right) || (right < 0)) {
		return parserError("Illegal or missing right attribute in <character> tag in \"%s\".", getFileName().c_str());
	}
	if (!parseIntegerKey(node->values["bottom"], 1, &bottom) || (bottom < 0)) {
		return parserError("Illegal or missing bottom attribute in <character> tag in \"%s\".", getFileName().c_str());
	}

	this->_characterRects[charCode] = Common::Rect(left, top, right, bottom);
	return true;
}
Example #11
0
bool ThemeParser::parserCallback_text_color(ParserNode *node) {
	int red, green, blue;

	TextColor colorId = parseTextColorId(node->values["id"]);
	if (colorId == kTextColorMAX)
		return parserError("Error text color is not defined.");

	if (_palette.contains(node->values["color"]))
		getPaletteColor(node->values["color"], red, green, blue);
	else if (!parseIntegerKey(node->values["color"], 3, &red, &green, &blue))
		return parserError("Error parsing color value for text color definition.");

	if (!_theme->addTextColor(colorId, red, green, blue))
		return parserError("Error while adding text color information.");

	return true;
}
Example #12
0
bool ThemeParser::parserCallback_color(ParserNode *node) {
	Common::String name = node->values["name"];

	if (_palette.contains(name))
		return parserError("Color '%s' has already been defined.", name.c_str());

	int red, green, blue;

	if (parseIntegerKey(node->values["rgb"].c_str(), 3, &red, &green, &blue) == false ||
		red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255)
		return parserError("Error parsing RGB values for palette color '%s'", name.c_str());\

	_palette[name].r = red;
	_palette[name].g = green;
	_palette[name].b = blue;

	return true;
}
Example #13
0
bool ThemeParser::parserCallback_def(ParserNode *node) {
	if (resolutionCheck(node->values["resolution"]) == false) {
		node->ignore = true;
		return true;
	}

	Common::String var = "Globals." + node->values["var"];
	int value;

	if (_theme->getEvaluator()->hasVar(node->values["value"]) == true)
		value = _theme->getEvaluator()->getVar(node->values["value"]);

	else if (!parseIntegerKey(node->values["value"].c_str(), 1, &value))
		return parserError("Invalid definition for '%s'.", var.c_str());

	_theme->getEvaluator()->setVar(var, value);
	return true;
}
Example #14
0
bool ThemeParser::parserCallback_font(ParserNode *node) {
	int red, green, blue;

	if (resolutionCheck(node->values["resolution"]) == false) {
		node->ignore = true;
		return true;
	}

	if (_palette.contains(node->values["color"]))
		getPaletteColor(node->values["color"], red, green, blue);
	else if (!parseIntegerKey(node->values["color"].c_str(), 3, &red, &green, &blue))
		return parserError("Error parsing color value for font definition.");

	TextData textDataId = parseTextDataId(node->values["id"]);
	if (!_theme->addFont(textDataId, node->values["file"], red, green, blue))
		return parserError("Error loading Font in theme engine.");

	return true;
}
Example #15
0
bool AnimationResource::parserCallback_frame(ParserNode *node) {
    Frame frame;

    const char *fileString = node->values["file"].c_str();
    if (!fileString) {
        error("<frame> tag without file attribute occurred in \"%s\".", getFileName().c_str());
        return false;
    }
    frame.fileName = _pPackage->getAbsolutePath(fileString);
    if (frame.fileName.empty()) {
        error("Could not create absolute path for file specified in <frame> tag in \"%s\": \"%s\".",
              getFileName().c_str(), fileString);
        return false;
    }

    const char *actionString = node->values["action"].c_str();
    if (actionString)
        frame.action = actionString;

    const char *hotspotxString = node->values["hotspotx"].c_str();
    const char *hotspotyString = node->values["hotspoty"].c_str();
    if ((!hotspotxString && hotspotyString) ||
            (hotspotxString && !hotspotyString))
        warning("%s attribute occurred without %s attribute in <frame> tag in \"%s\". Assuming default (\"0\").",
                hotspotxString ? "hotspotx" : "hotspoty",
                !hotspotyString ? "hotspoty" : "hotspotx",
                getFileName().c_str());

    frame.hotspotX = 0;
    if (hotspotxString && !parseIntegerKey(hotspotxString, 1, &frame.hotspotX))
        warning("Illegal hotspotx value (\"%s\") in frame tag in \"%s\". Assuming default (\"%d\").",
                hotspotxString, getFileName().c_str(), frame.hotspotX);

    frame.hotspotY = 0;
    if (hotspotyString && !parseIntegerKey(hotspotyString, 1, &frame.hotspotY))
        warning("Illegal hotspoty value (\"%s\") in frame tag in \"%s\". Assuming default (\"%d\").",
                hotspotyString, getFileName().c_str(), frame.hotspotY);

    Common::String flipVString = node->values["flipv"];
    if (!flipVString.empty()) {
        if (!parseBooleanKey(flipVString, frame.flipV)) {
            warning("Illegal flipv value (\"%s\") in <frame> tag in \"%s\". Assuming default (\"false\").",
                    flipVString.c_str(), getFileName().c_str());
            frame.flipV = false;
        }
    } else
        frame.flipV = false;

    Common::String flipHString = node->values["fliph"];
    if (!flipHString.empty()) {
        if (!parseBooleanKey(flipVString, frame.flipV)) {
            warning("Illegal fliph value (\"%s\") in <frame> tag in \"%s\". Assuming default (\"false\").",
                    flipHString.c_str(), getFileName().c_str());
            frame.flipH = false;
        }
    } else
        frame.flipH = false;

    _frames.push_back(frame);
    return true;
}
Example #16
0
bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific) {
	int red, green, blue, x;
	Common::String val;

/**
 * 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.
 * @param force Sets if the key is optional or necessary.
 */
#define __PARSER_ASSIGN_INT(struct_name, key_name, force) \
	if (stepNode->values.contains(key_name)) { \
		if (!parseIntegerKey(stepNode->values[key_name].c_str(), 1, &x)) \
			return parserError("Error parsing key value for '%s'.", key_name); \
		\
		drawstep->struct_name = x; \
	} else if (force) { \
		return parserError("Missing necessary key '%s'.", key_name); \
	}

/**
 * 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".
 *
 * @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)) { \
		val = stepNode->values[key_name]; \
		if (_palette.contains(val)) { \
			red = _palette[val].r; \
			green = _palette[val].g; \
			blue = _palette[val].b; \
		} else if (parseIntegerKey(val.c_str(), 3, &red, &green, &blue) == false || \
			red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) \
			return parserError("Error parsing color struct '%s'", val.c_str());\
		\
		drawstep->struct_name.r = red; \
		drawstep->struct_name.g = green; \
		drawstep->struct_name.b = blue; \
		drawstep->struct_name.set = true; \
	}

	__PARSER_ASSIGN_INT(stroke, "stroke", false);
	__PARSER_ASSIGN_INT(bevel, "bevel", false);
	__PARSER_ASSIGN_INT(shadow, "shadow", false);
	__PARSER_ASSIGN_INT(factor, "gradient_factor", false);

	__PARSER_ASSIGN_RGB(fgColor, "fg_color");
	__PARSER_ASSIGN_RGB(bgColor, "bg_color");
	__PARSER_ASSIGN_RGB(gradColor1, "gradient_start");
	__PARSER_ASSIGN_RGB(gradColor2, "gradient_end");
	__PARSER_ASSIGN_RGB(bevelColor, "bevel_color");

	if (functionSpecific) {
		assert(stepNode->values.contains("func"));
		Common::String functionName = stepNode->values["func"];

		if (functionName == "bitmap") {
			if (!stepNode->values.contains("file"))
				return parserError("Need to specify a filename for Bitmap blitting.");

			drawstep->blitSrc = _theme->getBitmap(stepNode->values["file"]);

			if (!drawstep->blitSrc)
				return parserError("The given filename hasn't been loaded into the GUI.");
		}

		if (functionName == "roundedsq" || functionName == "circle" || functionName == "tab") {
			if (stepNode->values.contains("radius") && stepNode->values["radius"] == "auto") {
				drawstep->radius = 0xFF;
			} else {
				__PARSER_ASSIGN_INT(radius, "radius", true);
			}
		}

		if (functionName == "triangle") {
			drawstep->extraData = Graphics::VectorRenderer::kTriangleUp;

			if (stepNode->values.contains("orientation")) {
				val = stepNode->values["orientation"];

				if ( val == "top")
					drawstep->extraData = Graphics::VectorRenderer::kTriangleUp;
				else if (val == "bottom")
					drawstep->extraData = Graphics::VectorRenderer::kTriangleDown;
				else if (val == "left")
					drawstep->extraData = Graphics::VectorRenderer::kTriangleLeft;
				else if (val == "right")
					drawstep->extraData = Graphics::VectorRenderer::kTriangleRight;
				else
					return parserError("'%s' is not a valid value for triangle orientation.", val.c_str());
			}
		}

		if (stepNode->values.contains("size")) {
			warning("The <size> keyword has been deprecated. Use <width> and <height> instead");
		}

		if (stepNode->values.contains("width") && stepNode->values["width"] != "auto") {
			drawstep->autoWidth = false;

			val = stepNode->values["width"];
			if (parseIntegerKey(val.c_str(), 1, &x))
				drawstep->w = x;
			else if (val == "height")
				drawstep->w = -1;
			else return parserError("Invalid value for vector width.");

			if (stepNode->values.contains("xpos")) {
				val = stepNode->values["xpos"];

				if (parseIntegerKey(val.c_str(), 1, &x))
					drawstep->x = x;
				else if (val == "center")
					drawstep->xAlign = Graphics::DrawStep::kVectorAlignCenter;
				else if (val == "left")
					drawstep->xAlign = Graphics::DrawStep::kVectorAlignLeft;
				else if (val == "right")
					drawstep->xAlign = Graphics::DrawStep::kVectorAlignRight;
				else
					return parserError("Invalid value for X Position");
			} else {
				return parserError("When width is not set to 'auto', a <xpos> tag must be included.");
			}
		}

		if (stepNode->values.contains("height") && stepNode->values["height"] != "auto") {
			drawstep->autoHeight = false;

			val = stepNode->values["height"];
			if (parseIntegerKey(val.c_str(), 1, &x))
				drawstep->h = x;
			else if (val == "width")
				drawstep->h = -1;
			else return parserError("Invalid value for vector height.");

			if (stepNode->values.contains("ypos")) {
				val = stepNode->values["ypos"];

				if (parseIntegerKey(val.c_str(), 1, &x))
					drawstep->y = x;
				else if (val == "center")
					drawstep->yAlign = Graphics::DrawStep::kVectorAlignCenter;
				else if (val == "top")
					drawstep->yAlign = Graphics::DrawStep::kVectorAlignTop;
				else if (val == "bottom")
					drawstep->yAlign = Graphics::DrawStep::kVectorAlignBottom;
				else
					return parserError("Invalid value for Y Position");
			} else {
				return parserError("When height is not set to 'auto', a <ypos> tag must be included.");
			}
		}

		if (drawstep->h == -1 && drawstep->w == -1)
			return parserError("Cross-reference in Vector Size: Height is set to width and width is set to height.");
	}

	if (stepNode->values.contains("fill")) {
		val = stepNode->values["fill"];
		if (val == "none")
			drawstep->fillMode = Graphics::VectorRenderer::kFillDisabled;
		else if (val == "foreground")
			drawstep->fillMode = Graphics::VectorRenderer::kFillForeground;
		else if (val == "background")
			drawstep->fillMode = Graphics::VectorRenderer::kFillBackground;
		else if (val == "gradient")
			drawstep->fillMode = Graphics::VectorRenderer::kFillGradient;
		else
			return parserError("'%s' is not a valid fill mode for a shape.", stepNode->values["fill"].c_str());
	}

#undef __PARSER_ASSIGN_INT
#undef __PARSER_ASSIGN_RGB

	return true;
}
Example #17
0
bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String &var) {
	if (node->values.contains("size")) {
		int width, height;

		if (!parseIntegerKey(node->values["size"].c_str(), 2, &width, &height)) {
			Common::StringTokenizer tokenizer(node->values["size"], " ,");
			Common::String wtoken, htoken;
			char *parseEnd;

			wtoken = tokenizer.nextToken();

			if (_theme->getEvaluator()->hasVar(wtoken)) {
				width = _theme->getEvaluator()->getVar(wtoken);
			} else {
				width = strtol(wtoken.c_str(), &parseEnd, 10);

				if (*parseEnd != 0 && !(*parseEnd == '%' && *(parseEnd + 1) == 0))
					return false;

				if (wtoken.lastChar() == '%')
					width = g_system->getOverlayWidth() * width / 100;
			}

			htoken = tokenizer.nextToken();

			if (_theme->getEvaluator()->hasVar(htoken)) {
				height = _theme->getEvaluator()->getVar(htoken);
			} else {
				height = strtol(htoken.c_str(), &parseEnd, 10);

				if (*parseEnd != 0 && !(*parseEnd == '%' && *(parseEnd + 1) == 0))
					return false;

				if (htoken.lastChar() == '%')
					height = g_system->getOverlayHeight() * height / 100;
			}

			if (!tokenizer.empty())
				return false;
		}


		_theme->getEvaluator()->setVar(var + "Width", width);
		_theme->getEvaluator()->setVar(var + "Height", height);
	}

	if (node->values.contains("pos")) {
		int x, y;

		if (!parseIntegerKey(node->values["pos"].c_str(), 2, &x, &y)) {
			Common::StringTokenizer tokenizer(node->values["pos"], " ,");
			Common::String xpos, ypos;
			char *parseEnd;

			xpos = tokenizer.nextToken();

			if (xpos == "center") {
				if (!_theme->getEvaluator()->hasVar(var + "Width"))
					return false;

				x = (g_system->getOverlayWidth() / 2) - (_theme->getEvaluator()->getVar(var + "Width") / 2);

			} else if (_theme->getEvaluator()->hasVar(xpos)) {
				x = _theme->getEvaluator()->getVar(xpos);
			} else {
				x = strtol(xpos.c_str(), &parseEnd, 10);

				if (*parseEnd != 0 && !(*parseEnd == 'r' && *(parseEnd + 1) == 0))
					return false;

				if (xpos.lastChar() == 'r')
					x = g_system->getOverlayWidth() - x;
			}

			ypos = tokenizer.nextToken();

			if (ypos == "center") {
				if (!_theme->getEvaluator()->hasVar(var + "Height"))
					return false;

				y = (g_system->getOverlayHeight() / 2) - (_theme->getEvaluator()->getVar(var + "Height") / 2);

			} else if (_theme->getEvaluator()->hasVar(ypos)) {
				y = _theme->getEvaluator()->getVar(ypos);
			} else {
				y = strtol(ypos.c_str(), &parseEnd, 10);

				if (*parseEnd != 0 && !(*parseEnd == 'b' && *(parseEnd + 1) == 0))
					return false;

				if (ypos.lastChar() == 'b')
					y = g_system->getOverlayHeight() - y;
			}

			if (!tokenizer.empty())
				return false;
		}

		_theme->getEvaluator()->setVar(var + "X", x);
		_theme->getEvaluator()->setVar(var + "Y", y);
	}

	if (node->values.contains("padding")) {
		int paddingL, paddingR, paddingT, paddingB;

		if (!parseIntegerKey(node->values["padding"].c_str(), 4, &paddingL, &paddingR, &paddingT, &paddingB))
			return false;

		_theme->getEvaluator()->setVar(var + "Padding.Left", paddingL);
		_theme->getEvaluator()->setVar(var + "Padding.Right", paddingR);
		_theme->getEvaluator()->setVar(var + "Padding.Top", paddingT);
		_theme->getEvaluator()->setVar(var + "Padding.Bottom", paddingB);
	}


	if (node->values.contains("textalign")) {
		Graphics::TextAlign alignH = Graphics::kTextAlignLeft;

		if((alignH = parseTextHAlign(node->values["textalign"])) == Graphics::kTextAlignInvalid)
			return parserError("Invalid value for text alignment.");

		_theme->getEvaluator()->setVar(var + "Align", alignH);
	}
	return true;
}