/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef THEME_PARSER_H
#define THEME_PARSER_H
#include "common/scummsys.h"
#include "graphics/surface.h"
#include "common/system.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/stack.h"
#include "common/xmlparser.h"
#include "graphics/VectorRenderer.h"
#include "gui/ThemeRenderer.h"
/**
*********************************************
** Theme Description File format overview. **
*********************************************
This document is a work in progress.
A more complete version will be posted on the wiki soon.
In the new version of the Graphical User Interface for ScummVM, almost
all properties regarding looks, design and positioning of the UI
elements are defined in a set of external files.
The chosen syntax for theme description is a basic subset of XML.
The process of theme description is divided in two main parts: Drawing
specifications for the vector renderer and theme design/layout
information for the actual theme engine.
These two core sections of a theme's description may be placed in a
single file or split for convenience across several files.
_DRAWING SPECIFICATIONS_
The process of rendering a widget on the screen is discretized into
several phases called "drawing steps". A set of such steps, which
generate a basic widget shape on screen is called a Draw Data set. The
GUI Engine loads all the different data sets for a given
widget and takes care of rendering it into the screen based on its
current state.
For example, the basic Button widget may be composed of several sets
of data: Drawing data for the button's idle state, drawing data for
when the button is hovered and drawing data for when the button is
pressed.
The functionality of each set of Drawing Data is hard-coded into the
Graphical User Interface; the most up to date version of all the
drawing sets may be found extensively commented in the
"gui/InterfaceManager.h" file, in the DrawData enumeration inside the
InterfaceManager class.
In order to successfully parse and load a custom theme definition, the
whole list of Draw Data sets must be specified.
_THEME LAYOUT SPECIFICATIONS_
#######
_SYNTAX OVERVIEW AND PARAMETERS_
As stated before, all the theme description is done through a XML-like
syntax. The files are parsed left-to-right, ignoring extra whitespaces
and newlines. Parser data is interpreted during the parsing. As a
general guideline, theme files are composed of keys which may or not
contain specific values for the key and which may parent several
subkeys; independently of this, all keys must be properly closed with
the '/' operator.
Note how keys which contain no children may be closed by themselves
or with an external closure.
- Comments
The parser supports the same comment syntax as the C++ programming
language. Comment blocks may be specified by surrounding them with the
'/ *' and '* /' operators, while whole lines may be commented out by
preceding them with the // operator.
Block comments are parsed in a non-hungry manner, i.e. the first
comment closure is understood to close the whole commenting block, so
syntax like
/ * hey look this comment finishes here * / or maybe here?? * /
is invalid.
- Section keys.
The section key is the root level of a theme description file. Each
file may contain one or more of these keys, which specifies the nature
of all their children, namely if the children keys specify drawing or
layout information. Its syntax is as follows:
// ...
// ...
The "layout_info" key specifies that all children keys contain
information regarding the layout of the theme, while the "render_info"
key specifies that all children keys contain information regarding the
looks of the theme.
Both keys support the two optional parameters "platform" and
"resolution", in order to make a certain layout apply to a single
resolution or to a single platform. To make a key apply for more than
one specific platform or resolution at the same time, you may separate
their names with commas.
- Render Info keys:
The children of a "render_info" key are expected to be one of these
kind:
-- DrawData key:
DrawData keys are the core of the rendering engine. They specifiy
via their own children the looks of all the UI elements. Here's
their syntax:
All drawdata keys must contain an "id" value, specifying which set
of drawing data they implement. Here's a list of all possible ids.
#########
Remember that all these ids must me implemented in order for the
parsing to be considered succesful.
DrawData keys may also contain an optional boolean value "cache",
which states if the set of DrawingSteps may be cached into the
memory so it can be blit into the Overlay each frame or if the set
of Drawing Steps should be performed individually each frame. If
omitted, the "cache" value defaults to false.
Also, just like the key, DrawData keys may also
contain optional "platform" and "resolution" values, making such
draw steps specific for a single or several platforms or
resolutions. In order to specify several platforms or resolutions,
they must be separated by commas inside the key's value.
When making a set of Drawing Data for a widget specific to a
single platform or resolution, remember that the set must be also
implemented later generically for other platforms, or the
rendering of the theme will fail in such platforms.
Lastly, each DrawData key must contain at least a children
"drawstep" subkey, with the necessary info for the
VectorRenderer.
- The DrawStep key
The DrawStep key is probably the most complex definition of
a ThemeDescription file. It contains enough information to
allow the Vector Renderer to draw a basic or complex shape
into the screen.
DrawStep keys are supposed to have no children, so they must
be either self-closed or closed externally.
Their basic syntax is as follows:
The only required value is the function "func" which states
the drawing function that will be used, and it must be
accompanied by a set of parameters specific to each drawing
step. Here's a list of such parameters:
Common parameters for all functions:
fill = "none|foreground|background|gradient"
Specifies the fill mode for the drawn shape.
Possible values:
"none": Disables filling so only the stroke is shown.
"foreground" (default): Fills the whole shape with the active foreground
color.
"background": Fills the whole shape with the active background
color.
"gradient": Fills the whole shape with the active gradient.
gradient_start = "R, G, B" | "color name"
gradient_end = "R, G, B" | "color name"
fg_color = "R, G, B" | "color name"
bg_color = "R, G, B" | "color name"
Sets the active gradient, foreground or backgroud colors. Colors
may be specified with their three components (red, green, blue)
ranging each from 0 to 255, or via a color name which has
previously been defined in the palette section.
These colours have no default values.
stroke = width (integer)
Sets the active stroke width; strokes may be disabled by setting
this value to 0. All shapes are automatically stroked with the
given width and the active foreground color. Defaults to 1.
shadow = offset (integer)
Sets the shadow offset. In the rendering engines that support it,
drawn shapes will have a soft shadow offseted the given amount on
their bottom-right corner. Defaults to 0 (disabled).
factor = amount (integer)
The factor value specifies the displacement of the active
gradient, i.e. its zoom level. It is only taken into account if
the active fill mode is set to gradient. Defaults to 1.
Standard primitive drawing functions:
func = "circle"
Draws a primitive circle. Requires the additional parameter
"radius", with an integer defining the radius of the circle or
the "auto" value.
func = "square"
Draws a primitive square/rectangle. Requires no additional parameters.
func = "roundedsq"
Draws a square/rectangle with rounded corners. Requires the
additional parameter "radius" defining the radius of the rounded
corners.
func = "bevelsq"
Draws a square/rectangle with beveled borders. This square
ignores the active fill mode, as it is never filled. Requires the
additional parameter "bevel" with the amount of bevel.
func = "line"
Draws a line. If the "size" parameter is specified, the line will
be drawn ranging from the bottom-left corner to the top-right
corner of the defined box. Optionally, you may define the ending
point of the line with the "end" parameter.
func = "triangle"
Draws a triangle. Triangles are always isosceles, meaning they
are drawn inside the square defined by the position and size
values, with the given width as the base of the triangle and the
given height as the height of the triangle.
The optional parameter
orientation = "top|left|right|bottom"
may be specified to define the way in which the triangle is
pointing. Defaults to top.
func = "fill"
This call ignores position and size parameters, as it completely
fills the active drawing surface taken into account the active
fill mode and colors.
*/
namespace GUI {
using namespace Graphics;
using namespace Common;
class ThemeRenderer;
class ThemeParser : public XMLParser {
typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &);
public:
ThemeParser(GUI::ThemeRenderer *parent);
bool getPaletteColor(const Common::String &name, int &r, int &g, int &b) {
if (!_palette.contains(name))
return false;
r = _palette[name].r;
g = _palette[name].g;
b = _palette[name].b;
return true;
}
protected:
ThemeRenderer *_theme;
CUSTOM_XML_PARSER(ThemeParser) {
XML_KEY(render_info)
XML_KEY(palette)
XML_KEY(color)
XML_PROP(name, true)
XML_PROP(rgb, true)
KEY_END()
KEY_END()
XML_KEY(fonts)
XML_KEY(font)
XML_PROP(id, true)
XML_PROP(type, true)
XML_PROP(color, true)
KEY_END()
KEY_END()
XML_KEY(defaults)
XML_PROP(stroke, false)
XML_PROP(shadow, false)
XML_PROP(factor, false)
XML_PROP(fg_color, false)
XML_PROP(bg_color, false)
XML_PROP(gradient_start, false)
XML_PROP(gradient_end, false)
XML_PROP(gradient_factor, false)
XML_PROP(fill, false)
KEY_END()
XML_KEY(drawdata)
XML_PROP(id, true)
XML_PROP(cache, false)
XML_KEY(defaults)
XML_PROP(stroke, false)
XML_PROP(shadow, false)
XML_PROP(factor, false)
XML_PROP(fg_color, false)
XML_PROP(bg_color, false)
XML_PROP(gradient_start, false)
XML_PROP(gradient_end, false)
XML_PROP(gradient_factor, false)
XML_PROP(fill, false)
KEY_END()
XML_KEY(drawstep)
XML_PROP(func, true)
XML_PROP(stroke, false)
XML_PROP(shadow, false)
XML_PROP(factor, false)
XML_PROP(fg_color, false)
XML_PROP(bg_color, false)
XML_PROP(gradient_start, false)
XML_PROP(gradient_end, false)
XML_PROP(gradient_factor, false)
XML_PROP(fill, false)
XML_PROP(bevel, false)
XML_PROP(radius, false)
XML_PROP(width, false)
XML_PROP(height, false)
XML_PROP(xpos, false)
XML_PROP(ypos, false)
XML_PROP(orientation, false)
KEY_END()
XML_KEY(text)
XML_PROP(font, true)
XML_PROP(vertical_align, true)
XML_PROP(horizontal_align, true)
KEY_END()
KEY_END()
KEY_END() // render_info end
XML_KEY(layout_info)
XML_KEY(globals)
XML_PROP(resolution, false)
XML_KEY(def)
XML_PROP(var, true)
XML_PROP(value, true)
KEY_END()
XML_KEY(widget)
XML_PROP(name, true)
XML_PROP(size, false)
XML_PROP(pos, false)
XML_PROP(padding, false)
XML_KEY(child)
XML_PROP(name, true)
XML_PROP(size, false)
XML_PROP(padding, false)
KEY_END()
KEY_END()
KEY_END()
XML_KEY(dialog)
XML_PROP(name, true)
XML_PROP(size, false)
XML_PROP(pos, false)
XML_PROP(resolution, false)
XML_KEY(widget)
XML_PROP(name, true)
XML_PROP(size, false)
XML_PROP(pos, false)
XML_PROP(padding, false)
KEY_END()
KEY_END()
KEY_END()
} PARSER_END();
/** Render info callbacks */
bool parserCallback_render_info(ParserNode *node);
bool parserCallback_defaults(ParserNode *node);
bool parserCallback_font(ParserNode *node);
bool parserCallback_fonts(ParserNode *node);
bool parserCallback_text(ParserNode *node);
bool parserCallback_palette(ParserNode *node);
bool parserCallback_color(ParserNode *node);
bool parserCallback_drawstep(ParserNode *node);
bool parserCallback_drawdata(ParserNode *node);
/** Layout info callbacks */
bool parserCallback_layout_info(ParserNode *node);
bool parserCallback_globals(ParserNode *node) { return true; }
bool parserCallback_def(ParserNode *node);
bool parserCallback_widget(ParserNode *node);
bool parserCallback_dialog(ParserNode *node);
bool parserCallback_child(ParserNode *node);
void cleanup();
Graphics::DrawStep *newDrawStep();
Graphics::DrawStep *defaultDrawStep();
bool parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific);
bool parseCommonLayoutProps(ParserNode *node, const Common::String &var);
Graphics::DrawStep *_defaultStepGlobal;
Graphics::DrawStep *_defaultStepLocal;
Common::HashMap _drawFunctions;
struct PaletteColor {
uint8 r, g, b;
};
Common::HashMap _palette;
};
}
#endif