From 6932c836cfb5f02565feb4700f42633ed5c84d68 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 16 Jun 2008 23:38:21 +0000 Subject: Added massive parser documentation. Some parser changes. svn-id: r32726 --- graphics/VectorRenderer.cpp | 14 +-- graphics/VectorRenderer.h | 20 +-- gui/InterfaceManager.cpp | 42 +++---- gui/ThemeParser.cpp | 41 ++++--- gui/ThemeParser.h | 287 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 343 insertions(+), 61 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index abfd53edcd..0194231427 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -54,19 +54,19 @@ VectorRenderer *createRenderer(int mode) { void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { if (step.flags & DrawStep::kStepCallbackOnly) { - (this->*(step.drawing_call))(area, step); + (this->*(step.drawingCall))(area, step); return; } if (step.flags & DrawStep::kStepSetBG) - setBgColor(step.color2.r, step.color2.g, step.color2.b); + setBgColor(step.bgColor.r, step.bgColor.g, step.bgColor.b); if (step.flags & DrawStep::kStepSetFG) - setFgColor(step.color1.r, step.color1.g, step.color1.b); + setFgColor(step.fgColor.r, step.fgColor.g, step.fgColor.b); if (step.flags & DrawStep::kStepSetGradient) - setGradientColors(step.color1.r, step.color1.g, step.color1.b, - step.color2.r, step.color2.g, step.color2.b); + setGradientColors(step.gradColor1.r, step.gradColor1.g, step.gradColor1.b, + step.gradColor2.r, step.gradColor2.g, step.gradColor2.b); if (step.flags & DrawStep::kStepSetShadow) shadowEnable(step.shadow); @@ -78,12 +78,12 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { setStrokeWidth(step.stroke); if (step.flags & DrawStep::kStepSetFillMode) - setFillMode((FillMode)step.fill_mode); + setFillMode((FillMode)step.fillMode); if (step.flags & DrawStep::kStepSettingsOnly) return; - (this->*(step.drawing_call))(area, step); + (this->*(step.drawingCall))(area, step); } /******************************************************************** diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 310f32f856..b4c4bb656d 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -45,10 +45,12 @@ struct DrawStep { struct { uint8 r, g, b; } - color1, /** Foreground color/gradient start */ - color2; /** Background color/gradient end */ + fgColor, /** Foreground color */ + bgColor, /** backgroudn color */ + gradColor1, /** gradient start*/ + gradColor2; /** gradient end */ - bool fill_area; /** If enabled, the draw step occupies the whole drawing area */ + bool fillArea; /** If enabled, the draw step occupies the whole drawing area */ struct { uint16 pos; @@ -60,12 +62,12 @@ struct DrawStep { uint8 shadow, stroke, factor, radius; /** Misc options... */ - uint8 fill_mode; /** active fill mode */ - uint8 extra_data; /** Generic parameter for extra options (orientation/bevel) */ + uint8 fillMode; /** active fill mode */ + uint8 extraData; /** Generic parameter for extra options (orientation/bevel) */ uint32 scale; /** scale of all the coordinates in FIXED POINT with 16 bits mantissa */ - void (VectorRenderer::*drawing_call)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ + void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ enum DrawStepFlags { kStepCallbackOnly = (1 << 0), @@ -330,7 +332,7 @@ public: } void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { - if (step.fill_area) { + if (step.fillArea) { in_x = area.left; in_y = area.top; in_w = area.width(); @@ -392,13 +394,13 @@ public: void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; stepGetPositions(step, area, x, y, w, h); - drawTriangle(x, y, w, h, (TriangleOrientation)step.extra_data); + drawTriangle(x, y, w, h, (TriangleOrientation)step.extraData); } void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; stepGetPositions(step, area, x, y, w, h); - drawBeveledSquare(x, y, w, h, step.extra_data); + drawBeveledSquare(x, y, w, h, step.extraData); } /** diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 380f1d4644..ae52387502 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -163,43 +163,43 @@ int InterfaceManager::runGUI() { Graphics::DrawStep *steps = new Graphics::DrawStep[5]; - steps[0].color1.r = 214; - steps[0].color1.g = 113; - steps[0].color1.b = 8; - steps[0].color2.r = 240; - steps[0].color2.g = 200; - steps[0].color2.b = 25; - steps[0].fill_mode = VectorRenderer::kFillGradient; - steps[0].drawing_call = &VectorRenderer::drawCallback_FILLSURFACE; + steps[0].gradColor1.r = 214; + steps[0].gradColor1.g = 113; + steps[0].gradColor1.b = 8; + steps[0].gradColor2.r = 240; + steps[0].gradColor2.g = 200; + steps[0].gradColor2.b = 25; + steps[0].fillMode = VectorRenderer::kFillGradient; + steps[0].drawingCall = &VectorRenderer::drawCallback_FILLSURFACE; steps[0].flags = DrawStep::kStepSetGradient | DrawStep::kStepSetFillMode; - steps[1].color1.r = 206; - steps[1].color1.g = 121; - steps[1].color1.b = 99; - steps[1].color2.r = 173; - steps[1].color2.g = 40; - steps[1].color2.b = 8; + steps[1].gradColor1.r = 206; + steps[1].gradColor1.g = 121; + steps[1].gradColor1.b = 99; + steps[1].gradColor2.r = 173; + steps[1].gradColor2.g = 40; + steps[1].gradColor2.b = 8; steps[1].radius = 8; // radius - steps[1].fill_area = true; - steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[1].fillArea = true; + steps[1].drawingCall = &VectorRenderer::drawCallback_ROUNDSQ; steps[1].flags = DrawStep::kStepSetGradient; steps[1].scale = (1 << 16); steps[2].radius = 8; // radius - steps[2].fill_area = false; + steps[2].fillArea = false; steps[2].x.relative = true; steps[2].x.pos = 32; steps[2].y.relative = false; steps[2].y.pos = 32; steps[2].w = 128; steps[2].h = 32; - steps[2].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[2].drawingCall = &VectorRenderer::drawCallback_ROUNDSQ; steps[2].flags = DrawStep::kStepCallbackOnly; steps[2].scale = (1 << 16); - steps[3].color1.r = 255; - steps[3].color1.g = 255; - steps[3].color1.b = 255; + steps[3].fgColor.r = 255; + steps[3].fgColor.g = 255; + steps[3].fgColor.b = 255; steps[3].flags = DrawStep::kStepSettingsOnly | DrawStep::kStepSetFG; Common::Rect area = Common::Rect(32, 32, 256, 256); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 498679c88f..267efba371 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -44,10 +44,10 @@ namespace GUI { void ThemeParser::debug_testEval() { static const char *debugConfigText = - "" - "" - "" - "/* lol this is just a simple test*/"; + "\n" + "\n" + "//\n" + "/* lol this is just a simple test*/\n"; _text = strdup(debugConfigText); parse(); @@ -59,7 +59,7 @@ void ThemeParser::parserError(const char *error_string) { printf("PARSER ERROR: %s\n", error_string); } -void ThemeParser::parserCallback_DRAW() { +void ThemeParser::parserCallback_DRAWSTEP() { printf("Draw callback!\n"); } @@ -68,29 +68,28 @@ void ThemeParser::parserCallback_DRAWDATA() { } void ThemeParser::parseActiveKey(bool closed) { - printf("Parsed key %s.\n", _activeKey.top().c_str()); + printf("Parsed key %s.\n", _activeKey.top()->name.c_str()); - if (!_callbacks.contains(_activeKey.top())) { + if (!_callbacks.contains(_activeKey.top()->name)) { parserError("Unhandled value inside key."); return; } // Don't you just love C++ syntax? Water clear. - (this->*(_callbacks[_activeKey.top()]))(); + (this->*(_callbacks[_activeKey.top()->name]))(); - for (Common::StringMap::const_iterator t = _keyValues.top().begin(); t != _keyValues.top().end(); ++t) + for (Common::StringMap::const_iterator t = _activeKey.top()->values.begin(); t != _activeKey.top()->values.end(); ++t) printf(" Key %s = %s\n", t->_key.c_str(), t->_value.c_str()); if (closed) { - _keyValues.pop(); - _activeKey.pop(); + delete _activeKey.pop(); } } bool ThemeParser::parseKeyValue(Common::String keyName) { - assert(_keyValues.empty() == false); + assert(_activeKey.empty() == false); - if (_keyValues.top().contains(keyName)) + if (_activeKey.top()->values.contains(keyName)) return false; _token.clear(); @@ -109,7 +108,7 @@ bool ThemeParser::parseKeyValue(Common::String keyName) { return false; } - _keyValues.top()[keyName] = _token; + _activeKey.top()->values[keyName] = _token; return true; } @@ -120,7 +119,6 @@ bool ThemeParser::parse() { _state = kParserNeedKey; _pos = 0; - _keyValues.clear(); _activeKey.clear(); while (_text[_pos]) { @@ -160,11 +158,12 @@ bool ThemeParser::parse() { } if (activeClosure) { - if (_activeKey.empty() || _token != _activeKey.top()) + if (_activeKey.empty() || _token != _activeKey.top()->name) parserError("Unexpected closure."); } else { - _keyValues.push(Common::StringMap()); - _activeKey.push(_token); + ParserNode *node = new ParserNode; + node->name = _token; + _activeKey.push(node); } _state = kParserNeedPropertyName; @@ -173,8 +172,7 @@ bool ThemeParser::parse() { case kParserNeedPropertyName: if (activeClosure) { activeClosure = false; - _activeKey.pop(); - _keyValues.pop(); + delete _activeKey.pop(); if (_text[_pos++] != '>') parserError("Invalid syntax in key closure."); @@ -215,6 +213,9 @@ bool ThemeParser::parse() { _state = kParserNeedPropertyName; break; + + default: + break; } } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 334677fd39..956a6d1df2 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -34,6 +34,272 @@ #include "common/hash-str.h" #include "common/stack.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 { class ThemeParser { @@ -44,7 +310,7 @@ class ThemeParser { public: ThemeParser() { _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; - _callbacks["draw"] = &ThemeParser::parserCallback_DRAW; + _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; } ~ThemeParser() {} @@ -64,7 +330,7 @@ public: void debug_testEval(); protected: - void parserCallback_DRAW(); + void parserCallback_DRAWSTEP(); void parserCallback_DRAWDATA(); bool parseKeyValue(Common::String keyName); @@ -87,9 +353,19 @@ protected: while (_text[_pos++]) { if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') break; + if (_text[_pos] == 0) + parserError("Comment has no closure."); } return true; } + + if (_text[_pos] == '/' && _text[_pos + 1] == '/') { + _pos += 2; + while (_text[_pos] && _text[_pos] != '\n') + _pos++; + return true; + } + return false; } @@ -113,9 +389,12 @@ protected: Common::String _error; Common::String _token; - Common::FixedStack _activeKey; - Common::FixedStack _keyValues; + struct ParserNode { + Common::String name; + Common::StringMap values; + }; + Common::FixedStack _activeKey; Common::HashMap _callbacks; }; -- cgit v1.2.3