From e117038b62410392979f95cfc889c366b2723650 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 1 May 2008 23:50:14 +0000 Subject: Implemented base API for the Vector Renderer. Added line drawing. svn-id: r31799 --- dists/msvc9/scummvm.vcproj | 10 +- graphics/VectorRenderer.cpp | 201 +++++++++++++++++++++++++++++++++++++ graphics/VectorRenderer.h | 236 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 graphics/VectorRenderer.cpp create mode 100644 graphics/VectorRenderer.h diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index afeafc3dd3..889ea04b75 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1,7 +1,7 @@ + + + + diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp new file mode 100644 index 0000000000..3079d00666 --- /dev/null +++ b/graphics/VectorRenderer.cpp @@ -0,0 +1,201 @@ +/* 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. + * + */ + +#include "common/util.h" +#include "graphics/surface.h" +#include "graphics/VectorRenderer.h" +#include "graphics/colormasks.h" + +namespace Graphics { + +VectorRenderer *createRenderer() +{ + return new VectorRendererAA>; +} + +template +void VectorRendererSpec:: +drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) +{ + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = surfacePitch(); + int xdir = ( x2 > x1 ) ? 1 : -1; + + *ptr = (PixelType)_color; + + if ( dx > dy ) + { + int ddy = dy * 2; + int dysub = ddy - ( dx * 2 ); + int error_term = ddy - dx; + + while ( dx-- ) { + if ( error_term >= 0 ) { + ptr += pitch; + error_term += dysub; + } else { + error_term += ddy; + } + + ptr += xdir; + *ptr = (PixelType)_color; + } + } + else + { + int ddx = dx * 2; + int dxsub = ddx - ( dy * 2 ); + int error_term = ddx - dy; + + while ( dy-- ) { + if ( error_term >= 0 ) { + ptr += xdir; + error_term += dxsub; + } else { + error_term += ddx; + } + + ptr += pitch; + *ptr = (PixelType)_color; + } + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); + *ptr = (PixelType)_color; +} + +template +void VectorRendererAA:: +drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) +{ + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = surfacePitch(); + int xdir = ( x2 > x1 ) ? 1 : -1; + + int error_line, error_tmp, weight; + int error_total = 0; + uint8 line_r, line_g, line_b; + uint8 bg_r, bg_g, bg_b; + + colorToRGB( _color, line_r, line_g, line_b ); + + uint line_lum = (line_r >> 2) + (line_g >> 1) + (line_b >> 3); + uint bg_lum; + + // first pixel, should be perfectly accurate so no fading out + *ptr = (PixelType)_color; + +#define __WULINE_PUTPIXEL( pixel_ptr ) \ + { \ + colorToRGB( (PixelType)*(pixel_ptr), bg_r, bg_g, bg_b ); \ + bg_lum = (bg_r >> 2) + (bg_g >> 1) + (bg_b >> 3); \ + weight = ( line_lum < bg_lum ) ? error_total >> 8 : (error_total >> 8)^0xFF; \ + *(pixel_ptr) = RGBToColor( \ + antialiasingBlendWeight( line_r, bg_r, weight ), \ + antialiasingBlendWeight( line_g, bg_g, weight ), \ + antialiasingBlendWeight( line_b, bg_b, weight ) ); \ + } + + // draw from top to bottom while fading out. + // optimized for mostly vertical lines + if ( dy > dx ) { + error_line = (dx << 16)/dy; + while ( --dy ) { + error_tmp = error_total; + error_total += error_line; + + if ( error_total <= error_tmp ) + ptr += xdir; // move right or left + + ptr += pitch; // move down + + __WULINE_PUTPIXEL( ptr ); + __WULINE_PUTPIXEL( ptr+xdir ); + } + } else { // optimized for mostly horizontal lines + error_line = (dy << 16)/dx; + while ( --dx ) { + error_tmp = error_total; + error_total += error_line; + + if ( error_total <= error_tmp ) + ptr += pitch; // move down + + ptr += xdir; // move left or right + + __WULINE_PUTPIXEL( ptr ); + __WULINE_PUTPIXEL( ptr + pitch ); + } + } // end of line direction cases + + // last pixel, also perfectly accurate. + ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); + *ptr = (PixelType)_color; +} + +template +void VectorRendererSpec:: +drawLine( int x1, int x2, int y1, int y2 ) +{ + // we draw from top to bottom + if ( y2 < y1 ) { + SWAP( x1, x2 ); + SWAP( y1, y2 ); + } + + int dx = ABS(x2 - x1); + int dy = ABS(y2 - y1); + + // this is a point, not a line. stoopid. + if ( dy == 0 && dx == 0 ) + return; + + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = surfacePitch(); + + if ( dy == 0 ) { // horizontal lines + // these can be filled really fast with a single memset. + // TODO: Platform specific ASM in set_to, would make this thing fly + Common::set_to(ptr, ptr + dx + 1, (PixelType)_color); + + } else if ( dx == 0 ) { // vertical lines + // these ones use a static pitch increase. + while (y1++ <= y2) { + *ptr = (PixelType)_color; + ptr += pitch; + } + + } else if ( ABS(dx) == ABS(dy) ) { // diagonal lines + // these ones also use a fixed pitch increase + pitch += ( x2 > x1 ) ? 1 : -1; + + while ( dy-- ) { + *ptr = (PixelType)_color; + ptr += pitch; + } + + } else { // generic lines, use the standard algorithm... + drawLineAlg( x1, x2, y1, y2, dx, dy ); + } +} + +} // end of namespace Graphics \ No newline at end of file diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h new file mode 100644 index 0000000000..b699f5cde9 --- /dev/null +++ b/graphics/VectorRenderer.h @@ -0,0 +1,236 @@ +/* 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. + * + */ + +#ifndef VECTOR_RENDERER_H +#define VECTOR_RENDERER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" + +namespace Graphics { + +/** + * VectorRenderer: The core Vector Renderer Class + * + * This virtual class which exposes the API with all the vectorial + * rendering functions that may be used to draw on a given Surface. + * + * This class must be instantiated as one of its children, which implement + * the actual rendering functionality for each Byte Depth / Byte Format + * combination, and may also contain platform specific code. + * + * TODO: Expand documentation. + * + * @see VectorRendererSpec + * @see VectorRendererAA + */ +class VectorRenderer { + +public: + /** + * Draws a line by considering the special cases for optimization. + * + * @param x1 Horizontal (X) coordinate for the line start + * @param x2 Horizontal (X) coordinate for the line end + * @param y1 Vertical (Y) coordinate for the line start + * @param y2 Vertical (Y) coordinate for the line end + */ + virtual void drawLine( int x1, int x2, int y1, int y2 ) = 0; + + /** + * Gets the pixel pitch for the current drawing surface. + * Note: This is a real pixel-pitch, not a byte-pitch. + * That means it can be safely used in pointer arithmetics and + * in pixel manipulation. + * + * @return integer with the active bytes per pixel + */ + virtual uint16 surfacePitch() { + return _activeSurface->pitch/_activeSurface->bytesPerPixel; + } + + /** + * Gets the BYTES (not bits) per Pixel we are working on, + * based on the active drawing surface. + * + * @return integer byte with the active bytes per pixel value + */ + virtual uint8 bytesPerPixel() { + return _activeSurface->bytesPerPixel; + } + + /** + * Set the active painting color for the renderer. + * All the drawing from then on will be done with that color, unless + * specified otherwise. + * + * @param r value of the red color byte + * @param g value of the green color byte + * @param b value of the blue color byte + */ + virtual void setColor( uint8 r, uint8 g, uint8 b ) = 0; + + /** + * Set the active painting color for the renderer, including alpha + * intensity. All the drawing from then on will be done with that color, + * unless specified otherwise. + * + * @param r value of the red color byte + * @param g value of the green color byte + * @param b value of the blue color byte + * @param a value of the alpha byte + */ + virtual void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) = 0; + +protected: + + /** + * Generic line drawing algorithm. May be implemented by each + * inheriting class, i.e. with platform specific code. + * + * @see VectorRenderer::drawLine() + * @param x1 Horizontal (X) coordinate for the line start + * @param x2 Horizontal (X) coordinate for the line end + * @param y1 Vertical (Y) coordinate for the line start + * @param y2 Vertical (Y) coordinate for the line end + * @param dx Horizontal (X) increasement. + * @param dy Vertical (Y) increasement. + */ + virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) = 0; + + virtual void drawCircleAlg( int x, int y, int r ) = 0; + + Surface *_activeSurface; /** Pointer to the surface currently being drawn */ +}; + + + +/** + * VectorRendererSpec: Specialized Vector Renderer Class + * + * This templated class implements the basic subset of vector operations for + * all platforms by allowing the user to provide the actual Pixel Type and + * pixel information structs. + * + * This class takes two template parameters: + * + * @param PixelType Defines a type which may hold the color value of a single + * pixel, such as "byte" or "uint16" for 8 and 16 BPP respectively. + * + * @param PixelFormat Defines the type of the PixelFormat struct which contains all + * the actual information of the pixels being used, as declared in "graphics/colormasks.h" + * + * TODO: Expand documentation. + * + * @see VectorRenderer + */ +template +class VectorRendererSpec : public VectorRenderer { + + /** + * @see VectorRenderer::drawLine() + */ + void drawLine( int x1, int x2, int y1, int y2 ); + + /** + * @see VectorRenderer::setColor() + */ + void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) { + _color = ARGBToColor(r, g, b, a); + } + + /** + * @see VectorRenderer::setColor() + */ + void setColor( uint8 r, uint8 g, uint8 b ) { + _color = RGBToColor(r, g, b); + } + +protected: + + /* + * "Bresenham's Line Algorithm", as described in Wikipedia. + * Based on the current implementation in "graphics/primitives.cpp". + * + * Generic line drawing algorithm for the aliased renderer. Optimized with no + * floating point operations and direct access to pixel buffer, assumes no special cases. + * + * @see VectorRenderer::drawLineAlg() + */ + virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ); + + virtual void drawCircleAlg( int x, int y, int r ) {} + + PixelType _color; /** Color currently being used to draw on the renderer */ +}; + +/** + * VectorRendererAA: Anti-Aliased Vector Renderer Class + * + * This templated class inherits all the functionality of the VectorRendererSpec + * class but uses better looking yet slightly slower AA algorithms for drawing + * most primivitves. May be used in faster platforms. + * + * TODO: Expand documentation. + * + * @see VectorRenderer + * @see VectorRendererSpec + */ +template +class VectorRendererAA : public VectorRendererSpec { + +protected: + /** + * "Wu's Line Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 + * Based on the implementation found in Michael Abrash's Graphics Programming Black Book. + * + * Generic line drawing algorithm for the Antialiased renderer. Optimized with no + * floating point operations, assumes no special cases. + * + * @see VectorRenderer::drawLineAlg() + */ + void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ); + + /** + * Calculates the blending weight (relative luminosity) value for + * a given pixel, based on the distance to the ideal line. + * Used for blending pixels in the Wu AA algorithm. + * + * @param line_color Byte value of a color component (R/G/B) of the color used to draw the line. + * @param line_color Byte value of a color component (R/G/B) of the color used to draw the BG. + * @param weight Weight of the pixel as calculated by Wu's algorithm. + * @return The new color value for the given component. + */ + inline uint8 antialiasingBlendWeight( uint8 line_color, uint8 bg_color, uint weight ) { + uint8 value; + if ( bg_color > line_color ) { + value = weight / 255 * ( bg_color - line_color ) + bg_color; + } else { + value = weight / 255 * ( line_color - bg_color ) + line_color; + } + return value; + } +}; + +} // end of namespace Graphics + +#endif \ No newline at end of file -- cgit v1.2.3 From 2d67aca715df401d144a290e1d862ed2c5438fe6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 1 May 2008 23:58:05 +0000 Subject: Missing code formatting conventions. svn-id: r31800 --- graphics/VectorRenderer.cpp | 24 ++++++++++-------------- graphics/VectorRenderer.h | 5 ++++- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 3079d00666..bb692b9f0b 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -18,6 +18,9 @@ * 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$ + * */ #include "common/util.h" @@ -27,23 +30,20 @@ namespace Graphics { -VectorRenderer *createRenderer() -{ +VectorRenderer *createRenderer() { return new VectorRendererAA>; } template void VectorRendererSpec:: -drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) -{ +drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); int xdir = ( x2 > x1 ) ? 1 : -1; *ptr = (PixelType)_color; - if ( dx > dy ) - { + if ( dx > dy ) { int ddy = dy * 2; int dysub = ddy - ( dx * 2 ); int error_term = ddy - dx; @@ -59,9 +59,7 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) ptr += xdir; *ptr = (PixelType)_color; } - } - else - { + } else { int ddx = dx * 2; int dxsub = ddx - ( dy * 2 ); int error_term = ddx - dy; @@ -104,8 +102,7 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) // first pixel, should be perfectly accurate so no fading out *ptr = (PixelType)_color; -#define __WULINE_PUTPIXEL( pixel_ptr ) \ - { \ +#define __WULINE_PUTPIXEL( pixel_ptr ) { \ colorToRGB( (PixelType)*(pixel_ptr), bg_r, bg_g, bg_b ); \ bg_lum = (bg_r >> 2) + (bg_g >> 1) + (bg_b >> 3); \ weight = ( line_lum < bg_lum ) ? error_total >> 8 : (error_total >> 8)^0xFF; \ @@ -154,8 +151,7 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) template void VectorRendererSpec:: -drawLine( int x1, int x2, int y1, int y2 ) -{ +drawLine( int x1, int x2, int y1, int y2 ) { // we draw from top to bottom if ( y2 < y1 ) { SWAP( x1, x2 ); @@ -198,4 +194,4 @@ drawLine( int x1, int x2, int y1, int y2 ) } } -} // end of namespace Graphics \ No newline at end of file +} // end of namespace Graphics diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b699f5cde9..ff3711f1f9 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -18,6 +18,9 @@ * 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 VECTOR_RENDERER_H @@ -233,4 +236,4 @@ protected: } // end of namespace Graphics -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 4fd1f929019daab4aa65b0a01339cec08435fae5 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 2 May 2008 07:50:23 +0000 Subject: Even more whitespace fixes. svn-id: r31803 --- graphics/VectorRenderer.cpp | 78 ++++++++++++++++++++++----------------------- graphics/VectorRenderer.h | 32 +++++++++---------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index bb692b9f0b..eb5d28a71f 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -36,20 +36,20 @@ VectorRenderer *createRenderer() { template void VectorRendererSpec:: -drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) { +drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); - int xdir = ( x2 > x1 ) ? 1 : -1; + int xdir = (x2 > x1) ? 1 : -1; *ptr = (PixelType)_color; - if ( dx > dy ) { + if (dx > dy) { int ddy = dy * 2; - int dysub = ddy - ( dx * 2 ); + int dysub = ddy - (dx * 2); int error_term = ddy - dx; - while ( dx-- ) { - if ( error_term >= 0 ) { + while (dx--) { + if (error_term >= 0) { ptr += pitch; error_term += dysub; } else { @@ -61,11 +61,11 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) { } } else { int ddx = dx * 2; - int dxsub = ddx - ( dy * 2 ); + int dxsub = ddx - (dy * 2); int error_term = ddx - dy; - while ( dy-- ) { - if ( error_term >= 0 ) { + while (dy--) { + if (error_term >= 0) { ptr += xdir; error_term += dxsub; } else { @@ -83,18 +83,18 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) { template void VectorRendererAA:: -drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) +drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); - int xdir = ( x2 > x1 ) ? 1 : -1; + int xdir = (x2 > x1) ? 1 : -1; int error_line, error_tmp, weight; int error_total = 0; uint8 line_r, line_g, line_b; uint8 bg_r, bg_g, bg_b; - colorToRGB( _color, line_r, line_g, line_b ); + colorToRGB(_color, line_r, line_g, line_b); uint line_lum = (line_r >> 2) + (line_g >> 1) + (line_b >> 3); uint bg_lum; @@ -103,44 +103,44 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) *ptr = (PixelType)_color; #define __WULINE_PUTPIXEL( pixel_ptr ) { \ - colorToRGB( (PixelType)*(pixel_ptr), bg_r, bg_g, bg_b ); \ + colorToRGB((PixelType)*(pixel_ptr), bg_r, bg_g, bg_b); \ bg_lum = (bg_r >> 2) + (bg_g >> 1) + (bg_b >> 3); \ - weight = ( line_lum < bg_lum ) ? error_total >> 8 : (error_total >> 8)^0xFF; \ + weight = (line_lum < bg_lum) ? error_total >> 8 : (error_total >> 8)^0xFF; \ *(pixel_ptr) = RGBToColor( \ - antialiasingBlendWeight( line_r, bg_r, weight ), \ - antialiasingBlendWeight( line_g, bg_g, weight ), \ - antialiasingBlendWeight( line_b, bg_b, weight ) ); \ + antialiasingBlendWeight(line_r, bg_r, weight), \ + antialiasingBlendWeight(line_g, bg_g, weight), \ + antialiasingBlendWeight(line_b, bg_b, weight)); \ } // draw from top to bottom while fading out. // optimized for mostly vertical lines - if ( dy > dx ) { - error_line = (dx << 16)/dy; - while ( --dy ) { + if (dy > dx) { + error_line = (dx << 16) / dy; + while (--dy) { error_tmp = error_total; error_total += error_line; - if ( error_total <= error_tmp ) + if (error_total <= error_tmp) ptr += xdir; // move right or left ptr += pitch; // move down - __WULINE_PUTPIXEL( ptr ); - __WULINE_PUTPIXEL( ptr+xdir ); + __WULINE_PUTPIXEL(ptr); + __WULINE_PUTPIXEL(ptr + xdir); } } else { // optimized for mostly horizontal lines - error_line = (dy << 16)/dx; - while ( --dx ) { + error_line = (dy << 16) / dx; + while (--dx) { error_tmp = error_total; error_total += error_line; - if ( error_total <= error_tmp ) + if (error_total <= error_tmp) ptr += pitch; // move down ptr += xdir; // move left or right - __WULINE_PUTPIXEL( ptr ); - __WULINE_PUTPIXEL( ptr + pitch ); + __WULINE_PUTPIXEL(ptr); + __WULINE_PUTPIXEL(ptr + pitch); } } // end of line direction cases @@ -151,46 +151,46 @@ drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) template void VectorRendererSpec:: -drawLine( int x1, int x2, int y1, int y2 ) { +drawLine(int x1, int x2, int y1, int y2) { // we draw from top to bottom - if ( y2 < y1 ) { - SWAP( x1, x2 ); - SWAP( y1, y2 ); + if (y2 < y1) { + SWAP(x1, x2); + SWAP(y1, y2); } int dx = ABS(x2 - x1); int dy = ABS(y2 - y1); // this is a point, not a line. stoopid. - if ( dy == 0 && dx == 0 ) + if (dy == 0 && dx == 0) return; PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); - if ( dy == 0 ) { // horizontal lines + if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. // TODO: Platform specific ASM in set_to, would make this thing fly Common::set_to(ptr, ptr + dx + 1, (PixelType)_color); - } else if ( dx == 0 ) { // vertical lines + } else if (dx == 0) { // vertical lines // these ones use a static pitch increase. while (y1++ <= y2) { *ptr = (PixelType)_color; ptr += pitch; } - } else if ( ABS(dx) == ABS(dy) ) { // diagonal lines + } else if (ABS(dx) == ABS(dy)) { // diagonal lines // these ones also use a fixed pitch increase - pitch += ( x2 > x1 ) ? 1 : -1; + pitch += (x2 > x1) ? 1 : -1; - while ( dy-- ) { + while (dy--) { *ptr = (PixelType)_color; ptr += pitch; } } else { // generic lines, use the standard algorithm... - drawLineAlg( x1, x2, y1, y2, dx, dy ); + drawLineAlg(x1, x2, y1, y2, dx, dy); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index ff3711f1f9..f7dffbd621 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -57,7 +57,7 @@ public: * @param y1 Vertical (Y) coordinate for the line start * @param y2 Vertical (Y) coordinate for the line end */ - virtual void drawLine( int x1, int x2, int y1, int y2 ) = 0; + virtual void drawLine(int x1, int x2, int y1, int y2) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -68,7 +68,7 @@ public: * @return integer with the active bytes per pixel */ virtual uint16 surfacePitch() { - return _activeSurface->pitch/_activeSurface->bytesPerPixel; + return _activeSurface->pitch / _activeSurface->bytesPerPixel; } /** @@ -90,7 +90,7 @@ public: * @param g value of the green color byte * @param b value of the blue color byte */ - virtual void setColor( uint8 r, uint8 g, uint8 b ) = 0; + virtual void setColor(uint8 r, uint8 g, uint8 b) = 0; /** * Set the active painting color for the renderer, including alpha @@ -102,7 +102,7 @@ public: * @param b value of the blue color byte * @param a value of the alpha byte */ - virtual void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) = 0; + virtual void setColor(uint8 r, uint8 g, uint8 b, uint8 a) = 0; protected: @@ -118,9 +118,9 @@ protected: * @param dx Horizontal (X) increasement. * @param dy Vertical (Y) increasement. */ - virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ) = 0; + virtual void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) = 0; - virtual void drawCircleAlg( int x, int y, int r ) = 0; + virtual void drawCircleAlg(int x, int y, int r) = 0; Surface *_activeSurface; /** Pointer to the surface currently being drawn */ }; @@ -152,19 +152,19 @@ class VectorRendererSpec : public VectorRenderer { /** * @see VectorRenderer::drawLine() */ - void drawLine( int x1, int x2, int y1, int y2 ); + void drawLine(int x1, int x2, int y1, int y2); /** * @see VectorRenderer::setColor() */ - void setColor( uint8 r, uint8 g, uint8 b, uint8 a ) { + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { _color = ARGBToColor(r, g, b, a); } /** * @see VectorRenderer::setColor() */ - void setColor( uint8 r, uint8 g, uint8 b ) { + void setColor(uint8 r, uint8 g, uint8 b) { _color = RGBToColor(r, g, b); } @@ -179,9 +179,9 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - virtual void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ); + virtual void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy); - virtual void drawCircleAlg( int x, int y, int r ) {} + virtual void drawCircleAlg(int x, int y, int r) {} PixelType _color; /** Color currently being used to draw on the renderer */ }; @@ -211,7 +211,7 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - void drawLineAlg( int x1, int x2, int y1, int y2, int dx, int dy ); + void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy); /** * Calculates the blending weight (relative luminosity) value for @@ -223,12 +223,12 @@ protected: * @param weight Weight of the pixel as calculated by Wu's algorithm. * @return The new color value for the given component. */ - inline uint8 antialiasingBlendWeight( uint8 line_color, uint8 bg_color, uint weight ) { + inline uint8 antialiasingBlendWeight(uint8 line_color, uint8 bg_color, uint weight) { uint8 value; - if ( bg_color > line_color ) { - value = weight / 255 * ( bg_color - line_color ) + bg_color; + if (bg_color > line_color) { + value = weight / 255 * (bg_color - line_color) + bg_color; } else { - value = weight / 255 * ( line_color - bg_color ) + line_color; + value = weight / 255 * (line_color - bg_color) + line_color; } return value; } -- cgit v1.2.3 From b50d430192f16f937b875b3ec77381e847156cb6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 2 May 2008 17:53:21 +0000 Subject: Renderer test function in main.cpp svn-id: r31832 --- base/main.cpp | 15 ++++++++++++++- graphics/VectorRenderer.cpp | 35 ++++++++++++++++++++++++++++++++--- graphics/VectorRenderer.h | 7 +++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index a53595ffca..257d691139 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -43,7 +43,11 @@ #include "gui/newgui.h" #include "gui/message.h" -#if defined(_WIN32_WCE) +#define _VECTOR_RENDERER_DBG 1 + +#if defined(_VECTOR_RENDERER_DBG) +#include "graphics/VectorRenderer.h" +#elif defined(_WIN32_WCE) #include "backends/platform/wince/CELauncherDialog.h" #elif defined(__DC__) #include "backends/platform/dc/DCLauncherDialog.h" @@ -67,6 +71,13 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); +#if defined(_VECTOR_RENDERER_DBG) + + Graphics::vector_renderer_test( &system ); + return true; + +#else + #if defined(_WIN32_WCE) CELauncherDialog dlg; #elif defined(__DC__) @@ -75,6 +86,8 @@ static bool launcherDialog(OSystem &system) { GUI::LauncherDialog dlg; #endif return (dlg.runModal() != -1); + +#endif // vector renderer debug } static const Plugin *detectPlugin() { diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index eb5d28a71f..252fc5722b 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -27,13 +27,43 @@ #include "graphics/surface.h" #include "graphics/VectorRenderer.h" #include "graphics/colormasks.h" +#include "common/system.h" namespace Graphics { VectorRenderer *createRenderer() { - return new VectorRendererAA>; + return new VectorRendererSpec>; } + +void vector_renderer_test( OSystem *_system ) { + VectorRenderer *vr = createRenderer(); + + Surface _screen; + _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); + + if (!_screen.pixels) + return; + + _system->clearOverlay(); + _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); + + vr->setSurface( &_screen ); + vr->setColor( 255, 255, 255 ); + + _system->showOverlay(); + + while( true ) { // draw!! + vr->drawLine( 25, 100, 25, 150 ); + _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); + _system->updateScreen(); + _system->delayMillis(100); + } + + _system->hideOverlay(); +} + + template void VectorRendererSpec:: drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { @@ -83,8 +113,7 @@ drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { template void VectorRendererAA:: -drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) -{ +drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index f7dffbd621..c5a09faf81 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -28,9 +28,12 @@ #include "common/scummsys.h" #include "graphics/surface.h" +#include "common/system.h" namespace Graphics { +void vector_renderer_test( OSystem *_system ); + /** * VectorRenderer: The core Vector Renderer Class * @@ -104,6 +107,10 @@ public: */ virtual void setColor(uint8 r, uint8 g, uint8 b, uint8 a) = 0; + virtual void setSurface( Surface *surface ){ + _activeSurface = surface; + } + protected: /** -- cgit v1.2.3 From 8c043f53edd164644048836202d96ee9ab996c5c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 3 May 2008 19:50:38 +0000 Subject: Generic functions (surface/pixel fill/blend). Line antialiasing. Circle antialiasing. svn-id: r31844 --- graphics/VectorRenderer.cpp | 186 +++++++++++++++++++++++++++++++------------- graphics/VectorRenderer.h | 155 +++++++++++++++++++++++++++++------- 2 files changed, 256 insertions(+), 85 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 252fc5722b..0ffaf9811d 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -31,8 +31,10 @@ namespace Graphics { +inline uint32 fp_sqroot( uint32 x ); + VectorRenderer *createRenderer() { - return new VectorRendererSpec>; + return new VectorRendererAA>; } @@ -49,12 +51,20 @@ void vector_renderer_test( OSystem *_system ) { _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); vr->setSurface( &_screen ); - vr->setColor( 255, 255, 255 ); + vr->setColor( 255, 0, 0 ); + vr->fillSurface(); + vr->setColor( 255, 255, 0 ); _system->showOverlay(); while( true ) { // draw!! - vr->drawLine( 25, 100, 25, 150 ); + + vr->setColor( 255, 255, 255 ); + vr->fillSurface(); + vr->setColor( 255, 0, 0 ); + vr->drawLine( 25, 25, 125, 300 ); + vr->drawCircle( 250, 250, 100 ); + _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); _system->delayMillis(100); @@ -63,10 +73,9 @@ void vector_renderer_test( OSystem *_system ) { _system->hideOverlay(); } - template void VectorRendererSpec:: -drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; @@ -111,76 +120,77 @@ drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { *ptr = (PixelType)_color; } + template void VectorRendererAA:: -drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = surfacePitch(); - int xdir = (x2 > x1) ? 1 : -1; +blendPixelPtr( PixelType *ptr, uint8 alpha ) { + register int idst = *ptr; + register int isrc = _color; + + *ptr = (PixelType)( + (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + + ((int)(((int)(isrc & PixelFormat::kRedMask) - + (int)(idst & PixelFormat::kRedMask)) * alpha) >>8))) | + (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + + ((int)(((int)(isrc & PixelFormat::kGreenMask) - + (int)(idst & PixelFormat::kGreenMask)) * alpha) >>8))) | + (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + + ((int)(((int)(isrc & PixelFormat::kBlueMask) - + (int)(idst & PixelFormat::kBlueMask)) * alpha) >>8))) ); +} - int error_line, error_tmp, weight; - int error_total = 0; - uint8 line_r, line_g, line_b; - uint8 bg_r, bg_g, bg_b; - colorToRGB(_color, line_r, line_g, line_b); +template +void VectorRendererAA:: +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { - uint line_lum = (line_r >> 2) + (line_g >> 1) + (line_b >> 3); - uint bg_lum; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = surfacePitch(); + int xdir = (x2 > x1) ? 1 : -1; + uint16 error_tmp, error_acc, gradient; - // first pixel, should be perfectly accurate so no fading out - *ptr = (PixelType)_color; + *ptr = (PixelType)_color; -#define __WULINE_PUTPIXEL( pixel_ptr ) { \ - colorToRGB((PixelType)*(pixel_ptr), bg_r, bg_g, bg_b); \ - bg_lum = (bg_r >> 2) + (bg_g >> 1) + (bg_b >> 3); \ - weight = (line_lum < bg_lum) ? error_total >> 8 : (error_total >> 8)^0xFF; \ - *(pixel_ptr) = RGBToColor( \ - antialiasingBlendWeight(line_r, bg_r, weight), \ - antialiasingBlendWeight(line_g, bg_g, weight), \ - antialiasingBlendWeight(line_b, bg_b, weight)); \ - } + if ( dx > dy ) { + gradient = (uint32)(dy<<16)/(uint32)dx; + error_acc = 0; - // draw from top to bottom while fading out. - // optimized for mostly vertical lines - if (dy > dx) { - error_line = (dx << 16) / dy; - while (--dy) { - error_tmp = error_total; - error_total += error_line; + while( --dx ) { + error_tmp = error_acc; + error_acc += gradient; - if (error_total <= error_tmp) - ptr += xdir; // move right or left + if ( error_acc <= error_tmp ) + ptr += pitch; - ptr += pitch; // move down + ptr += xdir; - __WULINE_PUTPIXEL(ptr); - __WULINE_PUTPIXEL(ptr + xdir); + blendPixelPtr( ptr, (error_acc >> 8) ^ 0xFF ); + blendPixelPtr( ptr + pitch, (error_acc >> 8) & 0xFF ); } - } else { // optimized for mostly horizontal lines - error_line = (dy << 16) / dx; - while (--dx) { - error_tmp = error_total; - error_total += error_line; + } else { + gradient = (uint32)(dx<<16)/(uint32)dy; + error_acc = 0; + + while( --dy ) { + error_tmp = error_acc; + error_acc += gradient; - if (error_total <= error_tmp) - ptr += pitch; // move down + if ( error_acc <= error_tmp ) + ptr += xdir; - ptr += xdir; // move left or right + ptr += pitch; - __WULINE_PUTPIXEL(ptr); - __WULINE_PUTPIXEL(ptr + pitch); - } - } // end of line direction cases + blendPixelPtr( ptr, (error_acc >> 8) ^ 0xFF ); + blendPixelPtr( ptr + xdir, (error_acc >> 8) & 0xFF ); + } + } - // last pixel, also perfectly accurate. - ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); - *ptr = (PixelType)_color; + putPixel( x2, y2 ); } template void VectorRendererSpec:: -drawLine(int x1, int x2, int y1, int y2) { +drawLine(int x1, int y1, int x2, int y2) { // we draw from top to bottom if (y2 < y1) { SWAP(x1, x2); @@ -219,7 +229,71 @@ drawLine(int x1, int x2, int y1, int y2) { } } else { // generic lines, use the standard algorithm... - drawLineAlg(x1, x2, y1, y2, dx, dy); + drawLineAlg(x1, y1, x2, y2, dx, dy); + } +} + +inline uint32 fp_sqroot( uint32 x ) { + register uint32 root, remHI, remLO, testDIV, count; + + root = 0; + remHI = 0; + remLO = x; + count = 23; + + do { + remHI = (remHI<<2) | (remLO>>30); + remLO <<= 2; + root <<= 1; + testDIV = (root<<1) + 1; + + if ( remHI >= testDIV ) { + remHI -= testDIV; + root++; + } + } while( count-- ); + + return root; +} + +template +void VectorRendererAA:: +drawCircleAlg(int x1, int y1, int r) { + +#define __CIRCLE_SIM(x,y,a) { \ + blendPixel( x1 + (x), y1 + (y), a ); \ + blendPixel( x1 + (x), y1 - (y), a ); \ + blendPixel( x1 - (y), y1 + (x), a ); \ + blendPixel( x1 + (y), y1 + (x), a ); \ + blendPixel( x1 - (x), y1 + (y), a ); \ + blendPixel( x1 - (x), y1 - (y), a ); \ + blendPixel( x1 + (y), y1 - (x), a ); \ + blendPixel( x1 - (y), y1 - (x), a ); \ +} + + // first quadrant +/*#define __CIRCLE_SIM(x,y,a) { \ + blendPixel( x1 + (x), y1 - (y), a ); \ + blendPixel( x1 + (y), y1 - (x), a ); \ +}*/ + + int x = r; + int y = 0; + uint32 rsq = (r*r)<<16; + uint32 T = 0, oldT; + + __CIRCLE_SIM( x, y, 255 ); + + while( x > y++ ) + { + oldT = T; + T = fp_sqroot( rsq - ((y*y)<<16) ) ^ 0xFFFF; + + if ( T < oldT ) + x--; + + __CIRCLE_SIM( x, y, (T>>8) ^ 0xFF ); + __CIRCLE_SIM( x-1, y, (T>>8) & 0xFF ); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index c5a09faf81..b7ee7d1680 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -37,7 +37,7 @@ void vector_renderer_test( OSystem *_system ); /** * VectorRenderer: The core Vector Renderer Class * - * This virtual class which exposes the API with all the vectorial + * This virtual class exposes the API with all the vectorial * rendering functions that may be used to draw on a given Surface. * * This class must be instantiated as one of its children, which implement @@ -60,7 +60,16 @@ public: * @param y1 Vertical (Y) coordinate for the line start * @param y2 Vertical (Y) coordinate for the line end */ - virtual void drawLine(int x1, int x2, int y1, int y2) = 0; + virtual void drawLine(int x1, int y1, int x2, int y2) = 0; + + /** + * Draws a circle centered at (x,y) with radius r. + * + * @param x Horizontal (X) coordinate for the center of the circle + * @param y Vertical (Y) coordinate for the center of the circle + * @param r Radius of the circle. + */ + virtual void drawCircle( int x, int y, int r ) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -96,21 +105,47 @@ public: virtual void setColor(uint8 r, uint8 g, uint8 b) = 0; /** - * Set the active painting color for the renderer, including alpha - * intensity. All the drawing from then on will be done with that color, - * unless specified otherwise. + * Sets the active drawing surface. All drawing from this + * point on will be done on that surface. * - * @param r value of the red color byte - * @param g value of the green color byte - * @param b value of the blue color byte - * @param a value of the alpha byte + * @param surface Pointer to a Surface object. */ - virtual void setColor(uint8 r, uint8 g, uint8 b, uint8 a) = 0; - virtual void setSurface( Surface *surface ){ _activeSurface = surface; } + /** + * Fills the active surface with the currently active drawing color. + */ + virtual void fillSurface() = 0; + + /** + * Clears the active surface. + */ + virtual void clearSurface() { + byte *src = (byte *)_activeSurface->pixels; + memset( src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel ); + } + + /** + * Draws a single pixel on the surface with the given coordinates and + * the currently active drawing color. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + */ + inline virtual void putPixel( int x, int y ) = 0; + + /** + * Blends a single pixel on the surface with the given coordinates, with + * the currently active drawing color and with the given Alpha intensity. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param alpha Alpha intensity of the pixel (0-255) + */ + inline virtual void blendPixel( int x, int y, uint8 alpha ) = 0; + protected: /** @@ -125,8 +160,16 @@ protected: * @param dx Horizontal (X) increasement. * @param dy Vertical (Y) increasement. */ - virtual void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy) = 0; + virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) = 0; + /** + * Specific circle drawing algorithm with symmetry. Must be implemented + * on each renderer. + * + * @param x Horizontal (X) coordinate for the center of the circle + * @param y Vertical (Y) coordinate for the center of the circle + * @param r Radius of the circle. + */ virtual void drawCircleAlg(int x, int y, int r) = 0; Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -156,11 +199,16 @@ protected: template class VectorRendererSpec : public VectorRenderer { +public: /** * @see VectorRenderer::drawLine() */ void drawLine(int x1, int x2, int y1, int y2); + void drawCircle( int x, int y, int r ) { + drawCircleAlg( x, y, r ); + } + /** * @see VectorRenderer::setColor() */ @@ -175,6 +223,33 @@ class VectorRendererSpec : public VectorRenderer { _color = RGBToColor(r, g, b); } + /** + * @see VectorRenderer::fillSurface() + */ + void fillSurface() { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); + int s = _activeSurface->w * _activeSurface->h; + Common::set_to(ptr, ptr + s, (PixelType)_color); + } + + /** + * @see VectorRenderer::putPixel() + */ + inline void putPixel( int x, int y ) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + *ptr = _color; + } + + /** + * On the Specialized Renderer, alpha blending is not supported. + * + * @see VectorRenderer::blendPixel() + */ + virtual inline void blendPixel( int x, int y, uint8 alpha ) { + if ( alpha > 0 ) + putPixel( x, y ); + } + protected: /* @@ -186,8 +261,11 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - virtual void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy); + virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy); + /** + * @see VectorRenderer::drawCircleAlg() + */ virtual void drawCircleAlg(int x, int y, int r) {} PixelType _color; /** Color currently being used to draw on the renderer */ @@ -218,27 +296,46 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - void drawLineAlg(int x1, int x2, int y1, int y2, int dx, int dy); + void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy); /** - * Calculates the blending weight (relative luminosity) value for - * a given pixel, based on the distance to the ideal line. - * Used for blending pixels in the Wu AA algorithm. + * Perform alpha blending on top of a given pixel, not on a given + * coordinate (just so we don't have to recalculate the surface + * pointer while we are blending consecutive pixels). + * + * Everything from blendPixel() applies here. * - * @param line_color Byte value of a color component (R/G/B) of the color used to draw the line. - * @param line_color Byte value of a color component (R/G/B) of the color used to draw the BG. - * @param weight Weight of the pixel as calculated by Wu's algorithm. - * @return The new color value for the given component. + * @see VectorRenderer::blendPixel() + * @param ptr Pointer to the pixel where we must draw + * @param alpha Intensity of the pixel (0-255). */ - inline uint8 antialiasingBlendWeight(uint8 line_color, uint8 bg_color, uint weight) { - uint8 value; - if (bg_color > line_color) { - value = weight / 255 * (bg_color - line_color) + bg_color; - } else { - value = weight / 255 * (line_color - bg_color) + line_color; - } - return value; + inline void blendPixelPtr( PixelType *ptr, uint8 alpha ); + + /** + * @see VectorRenderer::blendPixel() + * + * The AA renderer does support alpha blending. Special cases are + * handled separately. + */ + inline void blendPixel( int x, int y, uint8 alpha ) { + if ( alpha == 0 ) + return; + else if ( alpha < 255 ) + blendPixelPtr( (PixelType*)_activeSurface->getBasePtr(x, y), alpha ); + else + putPixel( x, y ); } + + /** + * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 + * Based on the theoretical concept of the algorithm. + * + * Implementation of Wu's algorithm for circles using fixed point arithmetics. + * Could be quite fast. + * + * @see VectorRenderer::drawCircleAlg() + */ + virtual void drawCircleAlg(int x, int y, int r); }; } // end of namespace Graphics -- cgit v1.2.3 From 8004a64c2f8e80bf2998970bcf352bb9c20f8805 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 3 May 2008 21:09:08 +0000 Subject: - Added missing virtual destructor in VectorRenderer - Added graphics/VectorRenderer.cpp to the build system - Fixed compiling with g++ 4.2 svn-id: r31847 --- graphics/VectorRenderer.cpp | 12 ++++++------ graphics/VectorRenderer.h | 11 +++++++---- graphics/module.mk | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0ffaf9811d..4a462cf5fa 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -34,7 +34,7 @@ namespace Graphics { inline uint32 fp_sqroot( uint32 x ); VectorRenderer *createRenderer() { - return new VectorRendererAA>; + return new VectorRendererAA >; } @@ -125,7 +125,7 @@ template void VectorRendererAA:: blendPixelPtr( PixelType *ptr, uint8 alpha ) { register int idst = *ptr; - register int isrc = _color; + register int isrc = Base::_color; *ptr = (PixelType)( (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + @@ -144,12 +144,12 @@ template void VectorRendererAA:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = surfacePitch(); + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + int pitch = Base::surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; uint16 error_tmp, error_acc, gradient; - *ptr = (PixelType)_color; + *ptr = (PixelType)Base::_color; if ( dx > dy ) { gradient = (uint32)(dy<<16)/(uint32)dx; @@ -185,7 +185,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { } } - putPixel( x2, y2 ); + Base::putPixel( x2, y2 ); } template diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b7ee7d1680..1b71a7164c 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -28,6 +28,7 @@ #include "common/scummsys.h" #include "graphics/surface.h" +#include "graphics/colormasks.h" #include "common/system.h" namespace Graphics { @@ -52,6 +53,8 @@ void vector_renderer_test( OSystem *_system ); class VectorRenderer { public: + virtual ~VectorRenderer() {} + /** * Draws a line by considering the special cases for optimization. * @@ -284,8 +287,8 @@ protected: * @see VectorRendererSpec */ template -class VectorRendererAA : public VectorRendererSpec { - +class VectorRendererAA : public VectorRendererSpec { + typedef VectorRendererSpec Base; protected: /** * "Wu's Line Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 @@ -321,9 +324,9 @@ protected: if ( alpha == 0 ) return; else if ( alpha < 255 ) - blendPixelPtr( (PixelType*)_activeSurface->getBasePtr(x, y), alpha ); + blendPixelPtr( (PixelType*)Base::_activeSurface->getBasePtr(x, y), alpha ); else - putPixel( x, y ); + Base::putPixel( x, y ); } /** diff --git a/graphics/module.mk b/graphics/module.mk index 93e2db26c5..b8dfd94ad2 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -16,7 +16,8 @@ MODULE_OBJS := \ primitives.o \ scaler.o \ scaler/thumbnail.o \ - surface.o + surface.o \ + VectorRenderer.o ifndef DISABLE_SCALERS MODULE_OBJS += \ -- cgit v1.2.3 From eb411d298aff4a062ed9d429a013e4687b6dc541 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 3 May 2008 21:57:29 +0000 Subject: - More coding convention fixes. - Aliased circles. svn-id: r31849 --- graphics/VectorRenderer.cpp | 132 +++++++++++++++++++++++++++----------------- graphics/VectorRenderer.h | 25 ++++----- 2 files changed, 93 insertions(+), 64 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 4a462cf5fa..391b0c2873 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -34,7 +34,7 @@ namespace Graphics { inline uint32 fp_sqroot( uint32 x ); VectorRenderer *createRenderer() { - return new VectorRendererAA >; + return new VectorRendererSpec >; } @@ -50,20 +50,20 @@ void vector_renderer_test( OSystem *_system ) { _system->clearOverlay(); _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); - vr->setSurface( &_screen ); - vr->setColor( 255, 0, 0 ); + vr->setSurface(&_screen); + vr->setColor(255, 0, 0); vr->fillSurface(); - vr->setColor( 255, 255, 0 ); + vr->setColor(255, 255, 0); _system->showOverlay(); - while( true ) { // draw!! + while(true) { // draw!! - vr->setColor( 255, 255, 255 ); + vr->setColor(255, 255, 255); vr->fillSurface(); - vr->setColor( 255, 0, 0 ); - vr->drawLine( 25, 25, 125, 300 ); - vr->drawCircle( 250, 250, 100 ); + vr->setColor(255, 0, 0 ); + vr->drawLine(25, 25, 125, 300); + vr->drawCircle(250, 250, 100); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -130,13 +130,13 @@ blendPixelPtr( PixelType *ptr, uint8 alpha ) { *ptr = (PixelType)( (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + ((int)(((int)(isrc & PixelFormat::kRedMask) - - (int)(idst & PixelFormat::kRedMask)) * alpha) >>8))) | + (int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) | (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + ((int)(((int)(isrc & PixelFormat::kGreenMask) - - (int)(idst & PixelFormat::kGreenMask)) * alpha) >>8))) | + (int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) | (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + ((int)(((int)(isrc & PixelFormat::kBlueMask) - - (int)(idst & PixelFormat::kBlueMask)) * alpha) >>8))) ); + (int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) ); } @@ -151,41 +151,41 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { *ptr = (PixelType)Base::_color; - if ( dx > dy ) { - gradient = (uint32)(dy<<16)/(uint32)dx; + if (dx > dy) { + gradient = (uint32)(dy << 16) / (uint32)dx; error_acc = 0; - while( --dx ) { + while(--dx) { error_tmp = error_acc; error_acc += gradient; - if ( error_acc <= error_tmp ) + if (error_acc <= error_tmp) ptr += pitch; ptr += xdir; - blendPixelPtr( ptr, (error_acc >> 8) ^ 0xFF ); - blendPixelPtr( ptr + pitch, (error_acc >> 8) & 0xFF ); + blendPixelPtr(ptr, (error_acc >> 8) ^ 0xFF); + blendPixelPtr(ptr + pitch, (error_acc >> 8) & 0xFF); } } else { - gradient = (uint32)(dx<<16)/(uint32)dy; + gradient = (uint32)(dx << 16) / (uint32)dy; error_acc = 0; - while( --dy ) { + while(--dy) { error_tmp = error_acc; error_acc += gradient; - if ( error_acc <= error_tmp ) + if (error_acc <= error_tmp) ptr += xdir; ptr += pitch; - blendPixelPtr( ptr, (error_acc >> 8) ^ 0xFF ); - blendPixelPtr( ptr + xdir, (error_acc >> 8) & 0xFF ); + blendPixelPtr(ptr, (error_acc >> 8) ^ 0xFF); + blendPixelPtr(ptr + xdir, (error_acc >> 8) & 0xFF); } } - Base::putPixel( x2, y2 ); + Base::putPixel(x2, y2); } template @@ -233,7 +233,7 @@ drawLine(int x1, int y1, int x2, int y2) { } } -inline uint32 fp_sqroot( uint32 x ) { +inline uint32 fp_sqroot(uint32 x) { register uint32 root, remHI, remLO, testDIV, count; root = 0; @@ -242,58 +242,88 @@ inline uint32 fp_sqroot( uint32 x ) { count = 23; do { - remHI = (remHI<<2) | (remLO>>30); + remHI = (remHI << 2) | (remLO >> 30); remLO <<= 2; root <<= 1; - testDIV = (root<<1) + 1; + testDIV = (root <<1 ) + 1; - if ( remHI >= testDIV ) { + if (remHI >= testDIV) { remHI -= testDIV; root++; } - } while( count-- ); + } while(count--); return root; } template -void VectorRendererAA:: +void VectorRendererSpec:: drawCircleAlg(int x1, int y1, int r) { -#define __CIRCLE_SIM(x,y,a) { \ - blendPixel( x1 + (x), y1 + (y), a ); \ - blendPixel( x1 + (x), y1 - (y), a ); \ - blendPixel( x1 - (y), y1 + (x), a ); \ - blendPixel( x1 + (y), y1 + (x), a ); \ - blendPixel( x1 - (x), y1 + (y), a ); \ - blendPixel( x1 - (x), y1 - (y), a ); \ - blendPixel( x1 + (y), y1 - (x), a ); \ - blendPixel( x1 - (y), y1 - (x), a ); \ +#define __CIRCLE_SIM(x,y) { \ + putPixel(x1 + (x), y1 + (y)); /* 1st quad */ \ + putPixel(x1 + (y), y1 - (x)); \ + putPixel(x1 - (x), y1 - (y)); /* 2nd quad */ \ + putPixel(x1 - (y), y1 - (x)); \ + putPixel(x1 - (y), y1 + (x)); /* 3rd quad */ \ + putPixel(x1 - (x), y1 + (y)); \ + putPixel(x1 + (y), y1 + (x)); /* 4th quad */ \ + putPixel(x1 + (x), y1 - (y)); \ } - // first quadrant -/*#define __CIRCLE_SIM(x,y,a) { \ - blendPixel( x1 + (x), y1 - (y), a ); \ - blendPixel( x1 + (y), y1 - (x), a ); \ -}*/ + int f = 1 - r; + int ddF_x = 0; + int ddF_y = -2 * r; + int x = 0; + int y = r; + + __CIRCLE_SIM(x,y); + while(x++ < y) { + if(f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + + ddF_x += 2; + f += ddF_x + 1; + + __CIRCLE_SIM(x,y); + } +} + +template +void VectorRendererAA:: +drawCircleAlg(int x1, int y1, int r) { + +#define __WU_CIRCLE_SIM(x,y,a) { \ + blendPixel(x1 + (x), y1 + (y), a); /* 1st quad */ \ + blendPixel(x1 + (y), y1 - (x), a); \ + blendPixel(x1 - (x), y1 - (y), a); /* 2nd quad */ \ + blendPixel(x1 - (y), y1 - (x), a); \ + blendPixel(x1 - (y), y1 + (x), a); /* 3rd quad */ \ + blendPixel(x1 - (x), y1 + (y), a); \ + blendPixel(x1 + (y), y1 + (x), a); /* 4th quad */ \ + blendPixel(x1 + (x), y1 - (y), a); \ +} int x = r; int y = 0; - uint32 rsq = (r*r)<<16; + uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; - __CIRCLE_SIM( x, y, 255 ); + __WU_CIRCLE_SIM(x, y, 255); - while( x > y++ ) + while(x > y++) { oldT = T; - T = fp_sqroot( rsq - ((y*y)<<16) ) ^ 0xFFFF; + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; - if ( T < oldT ) + if (T < oldT) x--; - __CIRCLE_SIM( x, y, (T>>8) ^ 0xFF ); - __CIRCLE_SIM( x-1, y, (T>>8) & 0xFF ); + __WU_CIRCLE_SIM(x, y, (T >> 8) ^ 0xFF); + __WU_CIRCLE_SIM(x-1, y, (T >> 8) & 0xFF); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 1b71a7164c..d8fb311f30 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -72,7 +72,7 @@ public: * @param y Vertical (Y) coordinate for the center of the circle * @param r Radius of the circle. */ - virtual void drawCircle( int x, int y, int r ) = 0; + virtual void drawCircle(int x, int y, int r) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -113,7 +113,7 @@ public: * * @param surface Pointer to a Surface object. */ - virtual void setSurface( Surface *surface ){ + virtual void setSurface(Surface *surface){ _activeSurface = surface; } @@ -137,7 +137,7 @@ public: * @param x Horizontal coordinate of the pixel. * @param y Vertical coordinate of the pixel. */ - inline virtual void putPixel( int x, int y ) = 0; + inline virtual void putPixel(int x, int y) = 0; /** * Blends a single pixel on the surface with the given coordinates, with @@ -147,7 +147,7 @@ public: * @param y Vertical coordinate of the pixel. * @param alpha Alpha intensity of the pixel (0-255) */ - inline virtual void blendPixel( int x, int y, uint8 alpha ) = 0; + inline virtual void blendPixel(int x, int y, uint8 alpha) = 0; protected: @@ -209,7 +209,7 @@ public: void drawLine(int x1, int x2, int y1, int y2); void drawCircle( int x, int y, int r ) { - drawCircleAlg( x, y, r ); + drawCircleAlg(x, y, r); } /** @@ -249,8 +249,7 @@ public: * @see VectorRenderer::blendPixel() */ virtual inline void blendPixel( int x, int y, uint8 alpha ) { - if ( alpha > 0 ) - putPixel( x, y ); + putPixel(x, y); } protected: @@ -269,7 +268,7 @@ protected: /** * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r) {} + virtual void drawCircleAlg(int x, int y, int r); PixelType _color; /** Color currently being used to draw on the renderer */ }; @@ -312,7 +311,7 @@ protected: * @param ptr Pointer to the pixel where we must draw * @param alpha Intensity of the pixel (0-255). */ - inline void blendPixelPtr( PixelType *ptr, uint8 alpha ); + inline void blendPixelPtr(PixelType *ptr, uint8 alpha); /** * @see VectorRenderer::blendPixel() @@ -321,12 +320,12 @@ protected: * handled separately. */ inline void blendPixel( int x, int y, uint8 alpha ) { - if ( alpha == 0 ) + if (alpha == 0) return; - else if ( alpha < 255 ) - blendPixelPtr( (PixelType*)Base::_activeSurface->getBasePtr(x, y), alpha ); + else if (alpha < 255) + blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), alpha); else - Base::putPixel( x, y ); + Base::putPixel(x, y); } /** -- cgit v1.2.3 From e5929da662dd328ea6ff46194d4cfae8eedec5a7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 3 May 2008 22:05:17 +0000 Subject: Coding conventions once again. svn-id: r31850 --- graphics/VectorRenderer.cpp | 16 ++++++++-------- graphics/VectorRenderer.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 391b0c2873..0897e530bb 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -31,7 +31,7 @@ namespace Graphics { -inline uint32 fp_sqroot( uint32 x ); +inline uint32 fp_sqroot(uint32 x); VectorRenderer *createRenderer() { return new VectorRendererSpec >; @@ -57,7 +57,7 @@ void vector_renderer_test( OSystem *_system ) { _system->showOverlay(); - while(true) { // draw!! + while (true) { // draw!! vr->setColor(255, 255, 255); vr->fillSurface(); @@ -155,7 +155,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { gradient = (uint32)(dy << 16) / (uint32)dx; error_acc = 0; - while(--dx) { + while (--dx) { error_tmp = error_acc; error_acc += gradient; @@ -171,7 +171,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { gradient = (uint32)(dx << 16) / (uint32)dy; error_acc = 0; - while(--dy) { + while (--dy) { error_tmp = error_acc; error_acc += gradient; @@ -251,7 +251,7 @@ inline uint32 fp_sqroot(uint32 x) { remHI -= testDIV; root++; } - } while(count--); + } while (count--); return root; } @@ -279,8 +279,8 @@ drawCircleAlg(int x1, int y1, int r) { __CIRCLE_SIM(x,y); - while(x++ < y) { - if(f >= 0) { + while (x++ < y) { + if (f >= 0) { y--; ddF_y += 2; f += ddF_y; @@ -314,7 +314,7 @@ drawCircleAlg(int x1, int y1, int r) { __WU_CIRCLE_SIM(x, y, 255); - while(x > y++) + while (x > y++) { oldT = T; T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index d8fb311f30..b5be32e0e1 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -127,7 +127,7 @@ public: */ virtual void clearSurface() { byte *src = (byte *)_activeSurface->pixels; - memset( src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel ); + memset(src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel); } /** @@ -208,7 +208,7 @@ public: */ void drawLine(int x1, int x2, int y1, int y2); - void drawCircle( int x, int y, int r ) { + void drawCircle(int x, int y, int r) { drawCircleAlg(x, y, r); } -- cgit v1.2.3 From 3e8e978c4e05645660251d1b8d5e0db0eb756a57 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 3 May 2008 22:10:52 +0000 Subject: Code formatting. svn-id: r31851 --- graphics/VectorRenderer.cpp | 6 +++--- graphics/VectorRenderer.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0897e530bb..f231531a16 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -34,11 +34,11 @@ namespace Graphics { inline uint32 fp_sqroot(uint32 x); VectorRenderer *createRenderer() { - return new VectorRendererSpec >; + return new VectorRendererSpec>; } -void vector_renderer_test( OSystem *_system ) { +void vector_renderer_test(OSystem *_system) { VectorRenderer *vr = createRenderer(); Surface _screen; @@ -123,7 +123,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { template void VectorRendererAA:: -blendPixelPtr( PixelType *ptr, uint8 alpha ) { +blendPixelPtr(PixelType *ptr, uint8 alpha) { register int idst = *ptr; register int isrc = Base::_color; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b5be32e0e1..2f648b9c56 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -33,7 +33,7 @@ namespace Graphics { -void vector_renderer_test( OSystem *_system ); +void vector_renderer_test(OSystem *_system); /** * VectorRenderer: The core Vector Renderer Class @@ -113,7 +113,7 @@ public: * * @param surface Pointer to a Surface object. */ - virtual void setSurface(Surface *surface){ + virtual void setSurface(Surface *surface) { _activeSurface = surface; } @@ -248,7 +248,7 @@ public: * * @see VectorRenderer::blendPixel() */ - virtual inline void blendPixel( int x, int y, uint8 alpha ) { + virtual inline void blendPixel(int x, int y, uint8 alpha) { putPixel(x, y); } @@ -319,7 +319,7 @@ protected: * The AA renderer does support alpha blending. Special cases are * handled separately. */ - inline void blendPixel( int x, int y, uint8 alpha ) { + inline void blendPixel(int x, int y, uint8 alpha) { if (alpha == 0) return; else if (alpha < 255) -- cgit v1.2.3 From 2c71344685670bc37535a46433739a0998b97c3e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 3 May 2008 23:10:43 +0000 Subject: - fixed invalid C++ - some minor formatting tweaks svn-id: r31853 --- graphics/VectorRenderer.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index f231531a16..256739c614 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -34,7 +34,7 @@ namespace Graphics { inline uint32 fp_sqroot(uint32 x); VectorRenderer *createRenderer() { - return new VectorRendererSpec>; + return new VectorRendererSpec >; } @@ -74,7 +74,7 @@ void vector_renderer_test(OSystem *_system) { } template -void VectorRendererSpec:: +void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); @@ -122,7 +122,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { template -void VectorRendererAA:: +void VectorRendererAA:: blendPixelPtr(PixelType *ptr, uint8 alpha) { register int idst = *ptr; register int isrc = Base::_color; @@ -141,7 +141,7 @@ blendPixelPtr(PixelType *ptr, uint8 alpha) { template -void VectorRendererAA:: +void VectorRendererAA:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); @@ -189,7 +189,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { } template -void VectorRendererSpec:: +void VectorRendererSpec:: drawLine(int x1, int y1, int x2, int y2) { // we draw from top to bottom if (y2 < y1) { @@ -257,7 +257,7 @@ inline uint32 fp_sqroot(uint32 x) { } template -void VectorRendererSpec:: +void VectorRendererSpec:: drawCircleAlg(int x1, int y1, int r) { #define __CIRCLE_SIM(x,y) { \ @@ -294,7 +294,7 @@ drawCircleAlg(int x1, int y1, int r) { } template -void VectorRendererAA:: +void VectorRendererAA:: drawCircleAlg(int x1, int y1, int r) { #define __WU_CIRCLE_SIM(x,y,a) { \ -- cgit v1.2.3 From d33890f110f40318542c382640f95601a44bdb54 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 3 May 2008 23:51:24 +0000 Subject: Rectangle drawing. svn-id: r31854 --- graphics/VectorRenderer.cpp | 21 ++++++++++++++++++++- graphics/VectorRenderer.h | 7 ++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 256739c614..f62ff92092 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -64,7 +64,7 @@ void vector_renderer_test(OSystem *_system) { vr->setColor(255, 0, 0 ); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); - + vr->drawSquare(150, 150, 100, 100, false); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); _system->delayMillis(100); @@ -75,6 +75,25 @@ void vector_renderer_test(OSystem *_system) { template void VectorRendererSpec:: +drawSquare(int x, int y, int w, int h, bool fill) { + if ( fill ) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + int pitch = surfacePitch(); + + while (h--) { + Common::set_to(ptr, ptr + w, (PixelType)_color); + ptr += pitch; + } + } else { + drawLine( x, y, x + w, y ); + drawLine( x + w, y, x + w, y + w ); + drawLine( x, y + w, x + w, y + w ); + drawLine( x, y, x, y + w ); + } +} + +template +void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = surfacePitch(); diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 2f648b9c56..b29a8aa633 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -74,6 +74,9 @@ public: */ virtual void drawCircle(int x, int y, int r) = 0; + + virtual void drawSquare(int x, int y, int w, int h, bool fill) = 0; + /** * Gets the pixel pitch for the current drawing surface. * Note: This is a real pixel-pitch, not a byte-pitch. @@ -206,12 +209,14 @@ public: /** * @see VectorRenderer::drawLine() */ - void drawLine(int x1, int x2, int y1, int y2); + void drawLine(int x1, int y1, int x2, int y2); void drawCircle(int x, int y, int r) { drawCircleAlg(x, y, r); } + void drawSquare(int x, int y, int w, int h, bool fill); + /** * @see VectorRenderer::setColor() */ -- cgit v1.2.3 From 6666b93dd7bec4fcb8b1494b310fa27066c9434e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 4 May 2008 13:53:22 +0000 Subject: Performance tweaks. svn-id: r31863 --- graphics/VectorRenderer.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index f62ff92092..5c58d777c1 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -34,7 +34,7 @@ namespace Graphics { inline uint32 fp_sqroot(uint32 x); VectorRenderer *createRenderer() { - return new VectorRendererSpec >; + return new VectorRendererAA >; } @@ -58,13 +58,12 @@ void vector_renderer_test(OSystem *_system) { _system->showOverlay(); while (true) { // draw!! - vr->setColor(255, 255, 255); vr->fillSurface(); vr->setColor(255, 0, 0 ); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); - vr->drawSquare(150, 150, 100, 100, false); + vr->drawSquare(150, 25, 100, 100, true); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); _system->delayMillis(100); @@ -167,6 +166,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { int pitch = Base::surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; uint16 error_tmp, error_acc, gradient; + uint8 alpha; *ptr = (PixelType)Base::_color; @@ -182,9 +182,10 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { ptr += pitch; ptr += xdir; + alpha = (error_acc >> 8); - blendPixelPtr(ptr, (error_acc >> 8) ^ 0xFF); - blendPixelPtr(ptr + pitch, (error_acc >> 8) & 0xFF); + blendPixelPtr(ptr, ~alpha); + blendPixelPtr(ptr + pitch, alpha); } } else { gradient = (uint32)(dx << 16) / (uint32)dy; @@ -198,9 +199,10 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { ptr += xdir; ptr += pitch; + alpha = (error_acc >> 8); - blendPixelPtr(ptr, (error_acc >> 8) ^ 0xFF); - blendPixelPtr(ptr + xdir, (error_acc >> 8) & 0xFF); + blendPixelPtr(ptr, ~alpha); + blendPixelPtr(ptr + xdir, alpha); } } @@ -264,7 +266,7 @@ inline uint32 fp_sqroot(uint32 x) { remHI = (remHI << 2) | (remLO >> 30); remLO <<= 2; root <<= 1; - testDIV = (root <<1 ) + 1; + testDIV = (root << 1 ) + 1; if (remHI >= testDIV) { remHI -= testDIV; @@ -330,6 +332,7 @@ drawCircleAlg(int x1, int y1, int r) { int y = 0; uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; + uint8 a1, a2; __WU_CIRCLE_SIM(x, y, 255); @@ -341,8 +344,11 @@ drawCircleAlg(int x1, int y1, int r) { if (T < oldT) x--; - __WU_CIRCLE_SIM(x, y, (T >> 8) ^ 0xFF); - __WU_CIRCLE_SIM(x-1, y, (T >> 8) & 0xFF); + a2 = (T >> 8); + a1 = ~a2; + + __WU_CIRCLE_SIM(x, y, a1); + __WU_CIRCLE_SIM(x-1, y, a2); } } -- cgit v1.2.3 From 4ada388fb8a304edec515de3883182d9a744b3fd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 4 May 2008 23:06:38 +0000 Subject: Antialiased circles changed to use screen ptrs. svn-id: r31870 --- graphics/VectorRenderer.cpp | 58 ++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 5c58d777c1..ed6eaff376 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -62,7 +62,7 @@ void vector_renderer_test(OSystem *_system) { vr->fillSurface(); vr->setColor(255, 0, 0 ); vr->drawLine(25, 25, 125, 300); - vr->drawCircle(250, 250, 100); + vr->drawCircle(250, 250, 10); vr->drawSquare(150, 25, 100, 100, true); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -317,38 +317,64 @@ drawCircleAlg(int x1, int y1, int r) { template void VectorRendererAA:: drawCircleAlg(int x1, int y1, int r) { - -#define __WU_CIRCLE_SIM(x,y,a) { \ - blendPixel(x1 + (x), y1 + (y), a); /* 1st quad */ \ - blendPixel(x1 + (y), y1 - (x), a); \ - blendPixel(x1 - (x), y1 - (y), a); /* 2nd quad */ \ - blendPixel(x1 - (y), y1 - (x), a); \ - blendPixel(x1 - (y), y1 + (x), a); /* 3rd quad */ \ - blendPixel(x1 - (x), y1 + (y), a); \ - blendPixel(x1 + (y), y1 + (x), a); /* 4th quad */ \ - blendPixel(x1 + (x), y1 - (y), a); \ -} int x = r; int y = 0; + int p = surfacePitch(), px = 0, py = 0; uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; + bool fill = false; + + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + px = p*x; + py = p*y; + + *(ptr + x) = (PixelType)_color; + *(ptr - x) = (PixelType)_color; + *(ptr + px) = (PixelType)_color; + *(ptr - px) = (PixelType)_color; - __WU_CIRCLE_SIM(x, y, 255); + if (fill) Common::set_to( ptr - x, ptr + x, _color ); while (x > y++) { oldT = T; T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; - if (T < oldT) + py += p; + + if (T < oldT) { x--; + px -= p; + } a2 = (T >> 8); a1 = ~a2; - __WU_CIRCLE_SIM(x, y, a1); - __WU_CIRCLE_SIM(x-1, y, a2); + if (fill) { + Common::set_to( ptr - x + py, ptr + x + py, _color ); + Common::set_to( ptr - x - py, ptr + x - py, _color ); + Common::set_to( ptr - y + px, ptr + y + px, _color ); + Common::set_to( ptr - y - px, ptr + y - px, _color ); + } else { + blendPixelPtr(ptr + x - 1 + py, a2); + blendPixelPtr(ptr + y - (px-p), a2); + blendPixelPtr(ptr - x + 1 - py, a2); + blendPixelPtr(ptr - y - (px-p), a2); + blendPixelPtr(ptr - y + (px-p), a2); + blendPixelPtr(ptr - x + 1 + py, a2); + blendPixelPtr(ptr + y + (px-p), a2); + blendPixelPtr(ptr + x - 1 - py, a2); + } + + blendPixelPtr(ptr + x + py, a1); + blendPixelPtr(ptr + y - px, a1); + blendPixelPtr(ptr - x - py, a1); + blendPixelPtr(ptr - y - px, a1); + blendPixelPtr(ptr - y + px, a1); + blendPixelPtr(ptr - x + py, a1); + blendPixelPtr(ptr + y + px, a1); + blendPixelPtr(ptr + x - py, a1); } } -- cgit v1.2.3 From 8209ab0b7b5f258205eae77d05bac326211fe497 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 5 May 2008 22:21:34 +0000 Subject: Fixes for GCC 4.0.2+ in strict mode. Max, is it working now? svn-id: r31885 --- graphics/VectorRenderer.cpp | 28 ++++++++++++++-------------- graphics/VectorRenderer.h | 12 +++--------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index ed6eaff376..0da5d7568d 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -77,7 +77,7 @@ void VectorRendererSpec:: drawSquare(int x, int y, int w, int h, bool fill) { if ( fill ) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - int pitch = surfacePitch(); + int pitch = Base::surfacePitch(); while (h--) { Common::set_to(ptr, ptr + w, (PixelType)_color); @@ -95,7 +95,7 @@ template void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = surfacePitch(); + int pitch = Base::surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; *ptr = (PixelType)_color; @@ -226,7 +226,7 @@ drawLine(int x1, int y1, int x2, int y2) { return; PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = surfacePitch(); + int pitch = Base::surfacePitch(); if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. @@ -319,22 +319,22 @@ void VectorRendererAA:: drawCircleAlg(int x1, int y1, int r) { int x = r; int y = 0; - int p = surfacePitch(), px = 0, py = 0; + int p = Base::surfacePitch(), px = 0, py = 0; uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; bool fill = false; - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); px = p*x; py = p*y; - *(ptr + x) = (PixelType)_color; - *(ptr - x) = (PixelType)_color; - *(ptr + px) = (PixelType)_color; - *(ptr - px) = (PixelType)_color; + *(ptr + x) = (PixelType)Base::_color; + *(ptr - x) = (PixelType)Base::_color; + *(ptr + px) = (PixelType)Base::_color; + *(ptr - px) = (PixelType)Base::_color; - if (fill) Common::set_to( ptr - x, ptr + x, _color ); + if (fill) Common::set_to(ptr - x, ptr + x, Base::_color); while (x > y++) { @@ -352,10 +352,10 @@ drawCircleAlg(int x1, int y1, int r) { a1 = ~a2; if (fill) { - Common::set_to( ptr - x + py, ptr + x + py, _color ); - Common::set_to( ptr - x - py, ptr + x - py, _color ); - Common::set_to( ptr - y + px, ptr + y + px, _color ); - Common::set_to( ptr - y - px, ptr + y - px, _color ); + Common::set_to(ptr - x + py, ptr + x + py, Base::_color); + Common::set_to(ptr - x - py, ptr + x - py, Base::_color); + Common::set_to(ptr - y + px, ptr + y + px, Base::_color); + Common::set_to(ptr - y - px, ptr + y - px, Base::_color); } else { blendPixelPtr(ptr + x - 1 + py, a2); blendPixelPtr(ptr + y - (px-p), a2); diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b29a8aa633..ab672e789e 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -204,6 +204,7 @@ protected: */ template class VectorRendererSpec : public VectorRenderer { + typedef VectorRenderer Base; public: /** @@ -217,18 +218,11 @@ public: void drawSquare(int x, int y, int w, int h, bool fill); - /** - * @see VectorRenderer::setColor() - */ - void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { - _color = ARGBToColor(r, g, b, a); - } - - /** +/** * @see VectorRenderer::setColor() */ void setColor(uint8 r, uint8 g, uint8 b) { - _color = RGBToColor(r, g, b); + this->_color = RGBToColor(r, g, b); } /** -- cgit v1.2.3 From 7c55a889f2176efaae6f8602f04328de1ca4e8ba Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 5 May 2008 22:28:03 +0000 Subject: Fix formatting. svn-id: r31886 --- graphics/VectorRenderer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index ab672e789e..96b0698de7 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -218,11 +218,11 @@ public: void drawSquare(int x, int y, int w, int h, bool fill); -/** + /** * @see VectorRenderer::setColor() */ void setColor(uint8 r, uint8 g, uint8 b) { - this->_color = RGBToColor(r, g, b); + this->_color = RGBToColor(r, g, b); } /** @@ -248,7 +248,7 @@ public: * @see VectorRenderer::blendPixel() */ virtual inline void blendPixel(int x, int y, uint8 alpha) { - putPixel(x, y); + putPixel(x, y); } protected: -- cgit v1.2.3 From 4331411ebea61072ff0189d7d61ac57199a120af Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 6 May 2008 09:54:10 +0000 Subject: Make it possible to quit the VectorRenderer demo cleanly svn-id: r31892 --- graphics/VectorRenderer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0da5d7568d..4a88eb94b4 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -28,6 +28,7 @@ #include "graphics/VectorRenderer.h" #include "graphics/colormasks.h" #include "common/system.h" +#include "common/events.h" namespace Graphics { @@ -39,6 +40,8 @@ VectorRenderer *createRenderer() { void vector_renderer_test(OSystem *_system) { + Common::EventManager *eventMan = _system->getEventManager(); + VectorRenderer *vr = createRenderer(); Surface _screen; @@ -66,7 +69,12 @@ void vector_renderer_test(OSystem *_system) { vr->drawSquare(150, 25, 100, 100, true); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); + + Common::Event event; _system->delayMillis(100); + if (eventMan->pollEvent(event) && event.type == Common::EVENT_QUIT) { + break; + } } _system->hideOverlay(); -- cgit v1.2.3 From 46fada31b72c4fab68d857a5fa16b57d059f4117 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 7 May 2008 22:51:45 +0000 Subject: - Fixed compiling in MSVC2008 - Aliased circles optimized (drawn using pointers directly) - Filling for aliased circles - Rounded squares - Filling for rounded squares svn-id: r31936 --- dists/msvc9/scumm.vcproj | 4 +- graphics/VectorRenderer.cpp | 144 +++++++++++++++++++++++++++++++++++++------- graphics/VectorRenderer.h | 13 ++++ 3 files changed, 138 insertions(+), 23 deletions(-) diff --git a/dists/msvc9/scumm.vcproj b/dists/msvc9/scumm.vcproj index 4acecd4517..230102db35 100644 --- a/dists/msvc9/scumm.vcproj +++ b/dists/msvc9/scumm.vcproj @@ -43,7 +43,7 @@ AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996" Optimization="0" AdditionalIncludeDirectories="../..;../../engines" - PreprocessorDefinitions="WIN32;_DEBUG;USE_ZLIB;USE_MAD;USE_VORBIS" + PreprocessorDefinitions="WIN32;_DEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS" MinimalRebuild="true" ExceptionHandling="1" BasicRuntimeChecks="3" @@ -116,7 +116,7 @@ InlineFunctionExpansion="1" OmitFramePointers="true" AdditionalIncludeDirectories="../..;../../engines" - PreprocessorDefinitions="WIN32;NDEBUG;USE_ZLIB;USE_MAD;USE_VORBIS" + PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS" StringPooling="true" ExceptionHandling="1" RuntimeLibrary="0" diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 4a88eb94b4..f779c9c09a 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -65,8 +65,9 @@ void vector_renderer_test(OSystem *_system) { vr->fillSurface(); vr->setColor(255, 0, 0 ); vr->drawLine(25, 25, 125, 300); - vr->drawCircle(250, 250, 10); - vr->drawSquare(150, 25, 100, 100, true); + vr->drawCircle(250, 250, 100); +// vr->drawSquare(150, 25, 100, 100, true); + vr->drawRoundedSquare( 150, 25, 8, 100, 75 ); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -288,37 +289,138 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: drawCircleAlg(int x1, int y1, int r) { + int f = 1 - r; + int ddF_x = 0, ddF_y = -2 * r; + int x = 0, y = r, px, py; + int pitch = Base::surfacePitch(); + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + bool fill = true; -#define __CIRCLE_SIM(x,y) { \ - putPixel(x1 + (x), y1 + (y)); /* 1st quad */ \ - putPixel(x1 + (y), y1 - (x)); \ - putPixel(x1 - (x), y1 - (y)); /* 2nd quad */ \ - putPixel(x1 - (y), y1 - (x)); \ - putPixel(x1 - (y), y1 + (x)); /* 3rd quad */ \ - putPixel(x1 - (x), y1 + (y)); \ - putPixel(x1 + (y), y1 + (x)); /* 4th quad */ \ - putPixel(x1 + (x), y1 - (y)); \ -} + px = 0; + py = pitch*y; - int f = 1 - r; - int ddF_x = 0; - int ddF_y = -2 * r; - int x = 0; - int y = r; + *(ptr + y) = _color; + *(ptr - y) = _color; + *(ptr + py) = _color; + *(ptr - py) = _color; - __CIRCLE_SIM(x,y); + if (fill) Common::set_to(ptr - r, ptr + r, _color); while (x++ < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; + py -= pitch; } + px += pitch; ddF_x += 2; - f += ddF_x + 1; - - __CIRCLE_SIM(x,y); + f += ddF_x + 1; + + if (fill) { + Common::set_to(ptr - x + py, ptr + x + py, _color); + Common::set_to(ptr - x - py, ptr + x - py, _color); + Common::set_to(ptr - y + px, ptr + y + px, _color); + Common::set_to(ptr - y - px, ptr + y - px, _color); + } + + *(ptr + x + py) = _color; + *(ptr + y - px) = _color; + *(ptr - x - py) = _color; + *(ptr - y - px) = _color; + *(ptr - y + px) = _color; + *(ptr - x + py) = _color; + *(ptr + y + px) = _color; + *(ptr + x - py) = _color; + } +} + +template +void VectorRendererAA:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { + int x = r; + int y = 0; + int p = Base::surfacePitch(), px, py; + uint32 rsq = (r * r) << 16; + uint32 T = 0, oldT; + uint8 a1, a2; + bool fill = true; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + Common::set_to(ptr_fill + r, ptr_fill + w - r + 1, Base::_color); + Common::set_to(ptr_fill + r + h*p, ptr_fill + w - r + 1 + h*p, Base::_color); + + h -= 2*r; + ptr_fill += p*r; + + if (!fill) { + while (h-- >= 0) { + *(ptr_fill) = (PixelType)Base::_color; + *(ptr_fill + w) = (PixelType)Base::_color; + ptr_fill += p; + } + } else { + while (h-- >= 0) { + Common::set_to(ptr_fill, ptr_fill + w + 1, Base::_color); + ptr_fill += p; + } + } + + px = p*x; + py = 0; + + while (x > y++) + { + oldT = T; + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; + + py += p; + + if (T < oldT) { + x--; + px -= p; + } + + a2 = (T >> 8); + a1 = ~a2; + + if (fill) { + Common::set_to( ptr_tl - x - py, ptr_tr + x - py, Base::_color ); + Common::set_to( ptr_tl - y - px, ptr_tr + y - px, Base::_color ); + + Common::set_to( ptr_bl - x + py, ptr_br + x + py, Base::_color ); + Common::set_to( ptr_bl - y + px, ptr_br + y + px, Base::_color ); + } else { + blendPixelPtr(ptr_tr + y - (px-p), a2); + blendPixelPtr(ptr_tr + x - 1 - py, a2); + + blendPixelPtr(ptr_tl - x + 1 - py, a2); + blendPixelPtr(ptr_tl - y - (px-p), a2); + + blendPixelPtr(ptr_bl - y + (px-p), a2); + blendPixelPtr(ptr_bl - x + 1 + py, a2); + + blendPixelPtr(ptr_br + x - 1 + py, a2); + blendPixelPtr(ptr_br + y + (px-p), a2); + } + + blendPixelPtr(ptr_tr + y - px, a1); + blendPixelPtr(ptr_tr + x - py, a1); + + blendPixelPtr(ptr_tl - x - py, a1); + blendPixelPtr(ptr_tl - y - px, a1); + + blendPixelPtr(ptr_bl - y + px, a1); + blendPixelPtr(ptr_bl - x + py, a1); + + blendPixelPtr(ptr_br + x + py, a1); + blendPixelPtr(ptr_br + y + px, a1); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 96b0698de7..a49170c56a 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -77,6 +77,8 @@ public: virtual void drawSquare(int x, int y, int w, int h, bool fill) = 0; + virtual void drawRoundedSquare(int x1, int y1, int r, int w, int h) = 0; + /** * Gets the pixel pitch for the current drawing surface. * Note: This is a real pixel-pitch, not a byte-pitch. @@ -178,6 +180,8 @@ protected: */ virtual void drawCircleAlg(int x, int y, int r) = 0; + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) = 0; + Surface *_activeSurface; /** Pointer to the surface currently being drawn */ }; @@ -218,6 +222,10 @@ public: void drawSquare(int x, int y, int w, int h, bool fill); + void drawRoundedSquare(int x1, int y1, int r, int w, int h) { + drawRoundedSquareAlg( x1, y1, r, w, h ); + } + /** * @see VectorRenderer::setColor() */ @@ -269,6 +277,9 @@ protected: */ virtual void drawCircleAlg(int x, int y, int r); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { + } + PixelType _color; /** Color currently being used to draw on the renderer */ }; @@ -337,6 +348,8 @@ protected: * @see VectorRenderer::drawCircleAlg() */ virtual void drawCircleAlg(int x, int y, int r); + + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h); }; } // end of namespace Graphics -- cgit v1.2.3 From ab27198bb699b360766813efcb8327d26e8b9907 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 9 May 2008 11:41:34 +0000 Subject: - Code formating. svn-id: r31963 --- graphics/VectorRenderer.cpp | 26 +++++++++++++------------- graphics/VectorRenderer.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index f779c9c09a..5f53c2fdf8 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -67,7 +67,7 @@ void vector_renderer_test(OSystem *_system) { vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); // vr->drawSquare(150, 25, 100, 100, true); - vr->drawRoundedSquare( 150, 25, 8, 100, 75 ); + vr->drawRoundedSquare(150, 25, 8, 100, 75); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -93,10 +93,10 @@ drawSquare(int x, int y, int w, int h, bool fill) { ptr += pitch; } } else { - drawLine( x, y, x + w, y ); - drawLine( x + w, y, x + w, y + w ); - drawLine( x, y + w, x + w, y + w ); - drawLine( x, y, x, y + w ); + drawLine(x, y, x + w, y); + drawLine(x + w, y, x + w, y + w); + drawLine(x, y + w, x + w, y + w); + drawLine(x, y, x, y + w); } } @@ -297,7 +297,7 @@ drawCircleAlg(int x1, int y1, int r) { bool fill = true; px = 0; - py = pitch*y; + py = pitch * y; *(ptr + y) = _color; *(ptr - y) = _color; @@ -372,7 +372,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { } } - px = p*x; + px = p * x; py = 0; while (x > y++) @@ -391,11 +391,11 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { a1 = ~a2; if (fill) { - Common::set_to( ptr_tl - x - py, ptr_tr + x - py, Base::_color ); - Common::set_to( ptr_tl - y - px, ptr_tr + y - px, Base::_color ); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, Base::_color); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, Base::_color); - Common::set_to( ptr_bl - x + py, ptr_br + x + py, Base::_color ); - Common::set_to( ptr_bl - y + px, ptr_br + y + px, Base::_color ); + Common::set_to(ptr_bl - x + py, ptr_br + x + py, Base::_color); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, Base::_color); } else { blendPixelPtr(ptr_tr + y - (px-p), a2); blendPixelPtr(ptr_tr + x - 1 - py, a2); @@ -436,8 +436,8 @@ drawCircleAlg(int x1, int y1, int r) { bool fill = false; PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - px = p*x; - py = p*y; + px = p * x; + py = p * y; *(ptr + x) = (PixelType)Base::_color; *(ptr - x) = (PixelType)Base::_color; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index a49170c56a..4ab5bd5e27 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -223,7 +223,7 @@ public: void drawSquare(int x, int y, int w, int h, bool fill); void drawRoundedSquare(int x1, int y1, int r, int w, int h) { - drawRoundedSquareAlg( x1, y1, r, w, h ); + drawRoundedSquareAlg(x1, y1, r, w, h); } /** -- cgit v1.2.3 From a11b9a169d06d10638d92adad4f87cac9075d629 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 10 May 2008 14:29:49 +0000 Subject: - API changes/refactoring - Foreground/background color support - Finished/improved filling support - Basic shadow support svn-id: r31974 --- graphics/VectorRenderer.cpp | 221 +++++++++++++++++++++-------------------- graphics/VectorRenderer.h | 237 ++++++++++++++++++++++++++++---------------- 2 files changed, 263 insertions(+), 195 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 5f53c2fdf8..67a60bbde1 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -54,20 +54,24 @@ void vector_renderer_test(OSystem *_system) { _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); vr->setSurface(&_screen); - vr->setColor(255, 0, 0); - vr->fillSurface(); - vr->setColor(255, 255, 0); + vr->clearSurface(); _system->showOverlay(); while (true) { // draw!! - vr->setColor(255, 255, 255); + vr->setFgColor(255, 255, 255); vr->fillSurface(); - vr->setColor(255, 0, 0 ); + + vr->setFgColor(255, 0, 0 ); + vr->setBgColor(25, 25, 175 ); + vr->setFillMode( VectorRenderer::kBackgroundFill ); + vr->shadowEnable( 5, 5 ); + vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); -// vr->drawSquare(150, 25, 100, 100, true); - vr->drawRoundedSquare(150, 25, 8, 100, 75); + vr->drawSquare(150, 25, 100, 75); + vr->drawRoundedSquare(275, 25, 8, 100, 75); + _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -83,31 +87,35 @@ void vector_renderer_test(OSystem *_system) { template void VectorRendererSpec:: -drawSquare(int x, int y, int w, int h, bool fill) { - if ( fill ) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - int pitch = Base::surfacePitch(); - +drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + int pitch = Base::surfacePitch(); + + if (fill) { while (h--) { - Common::set_to(ptr, ptr + w, (PixelType)_color); + Common::set_to(ptr, ptr + w, color); ptr += pitch; } } else { - drawLine(x, y, x + w, y); - drawLine(x + w, y, x + w, y + w); - drawLine(x, y + w, x + w, y + w); - drawLine(x, y, x, y + w); + Common::set_to(ptr, ptr + w, color); + Common::set_to(ptr + pitch * h, ptr + w + pitch * h, color); + + while (h--) { + *ptr = color; + *(ptr + w) = color; + ptr += pitch; + } } } template void VectorRendererSpec:: -drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = Base::surfacePitch(); int xdir = (x2 > x1) ? 1 : -1; - *ptr = (PixelType)_color; + *ptr = (PixelType)color; if (dx > dy) { int ddy = dy * 2; @@ -123,7 +131,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { } ptr += xdir; - *ptr = (PixelType)_color; + *ptr = (PixelType)color; } } else { int ddx = dx * 2; @@ -139,20 +147,20 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { } ptr += pitch; - *ptr = (PixelType)_color; + *ptr = (PixelType)color; } } ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); - *ptr = (PixelType)_color; + *ptr = (PixelType)color; } template void VectorRendererAA:: -blendPixelPtr(PixelType *ptr, uint8 alpha) { +blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { register int idst = *ptr; - register int isrc = Base::_color; + register int isrc = color; *ptr = (PixelType)( (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + @@ -169,7 +177,7 @@ blendPixelPtr(PixelType *ptr, uint8 alpha) { template void VectorRendererAA:: -drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); int pitch = Base::surfacePitch(); @@ -177,7 +185,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { uint16 error_tmp, error_acc, gradient; uint8 alpha; - *ptr = (PixelType)Base::_color; + *ptr = (PixelType)color; if (dx > dy) { gradient = (uint32)(dy << 16) / (uint32)dx; @@ -193,8 +201,8 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { ptr += xdir; alpha = (error_acc >> 8); - blendPixelPtr(ptr, ~alpha); - blendPixelPtr(ptr + pitch, alpha); + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + pitch, color, alpha); } } else { gradient = (uint32)(dx << 16) / (uint32)dy; @@ -210,12 +218,12 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) { ptr += pitch; alpha = (error_acc >> 8); - blendPixelPtr(ptr, ~alpha); - blendPixelPtr(ptr + xdir, alpha); + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + xdir, color, alpha); } } - Base::putPixel(x2, y2); + Base::putPixel(x2, y2, color); } template @@ -240,12 +248,12 @@ drawLine(int x1, int y1, int x2, int y2) { if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. // TODO: Platform specific ASM in set_to, would make this thing fly - Common::set_to(ptr, ptr + dx + 1, (PixelType)_color); + Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor); } else if (dx == 0) { // vertical lines // these ones use a static pitch increase. while (y1++ <= y2) { - *ptr = (PixelType)_color; + *ptr = (PixelType)_fgColor; ptr += pitch; } @@ -254,12 +262,12 @@ drawLine(int x1, int y1, int x2, int y2) { pitch += (x2 > x1) ? 1 : -1; while (dy--) { - *ptr = (PixelType)_color; + *ptr = (PixelType)_fgColor; ptr += pitch; } } else { // generic lines, use the standard algorithm... - drawLineAlg(x1, y1, x2, y2, dx, dy); + drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor); } } @@ -288,23 +296,22 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: -drawCircleAlg(int x1, int y1, int r) { +drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { int f = 1 - r; int ddF_x = 0, ddF_y = -2 * r; int x = 0, y = r, px, py; int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - bool fill = true; px = 0; py = pitch * y; - *(ptr + y) = _color; - *(ptr - y) = _color; - *(ptr + py) = _color; - *(ptr - py) = _color; + *(ptr + y) = color; + *(ptr - y) = color; + *(ptr + py) = color; + *(ptr - py) = color; - if (fill) Common::set_to(ptr - r, ptr + r, _color); + if (fill) Common::set_to(ptr - r, ptr + r, color); while (x++ < y) { if (f >= 0) { @@ -319,33 +326,32 @@ drawCircleAlg(int x1, int y1, int r) { f += ddF_x + 1; if (fill) { - Common::set_to(ptr - x + py, ptr + x + py, _color); - Common::set_to(ptr - x - py, ptr + x - py, _color); - Common::set_to(ptr - y + px, ptr + y + px, _color); - Common::set_to(ptr - y - px, ptr + y - px, _color); + Common::set_to(ptr - x + py, ptr + x + py, color); + Common::set_to(ptr - x - py, ptr + x - py, color); + Common::set_to(ptr - y + px, ptr + y + px, color); + Common::set_to(ptr - y - px, ptr + y - px, color); } - *(ptr + x + py) = _color; - *(ptr + y - px) = _color; - *(ptr - x - py) = _color; - *(ptr - y - px) = _color; - *(ptr - y + px) = _color; - *(ptr - x + py) = _color; - *(ptr + y + px) = _color; - *(ptr + x - py) = _color; + *(ptr + x + py) = color; + *(ptr + y - px) = color; + *(ptr - x - py) = color; + *(ptr - y - px) = color; + *(ptr - y + px) = color; + *(ptr - x + py) = color; + *(ptr + y + px) = color; + *(ptr + x - py) = color; } } template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { int x = r; int y = 0; int p = Base::surfacePitch(), px, py; uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; - bool fill = true; PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); @@ -353,21 +359,21 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - Common::set_to(ptr_fill + r, ptr_fill + w - r + 1, Base::_color); - Common::set_to(ptr_fill + r + h*p, ptr_fill + w - r + 1 + h*p, Base::_color); + Common::set_to(ptr_fill + r, ptr_fill + w - r + 1, color); + Common::set_to(ptr_fill + r + h*p, ptr_fill + w - r + 1 + h*p, color); h -= 2*r; ptr_fill += p*r; if (!fill) { while (h-- >= 0) { - *(ptr_fill) = (PixelType)Base::_color; - *(ptr_fill + w) = (PixelType)Base::_color; + *(ptr_fill) = (PixelType)color; + *(ptr_fill + w) = (PixelType)color; ptr_fill += p; } } else { while (h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + w + 1, Base::_color); + Common::set_to(ptr_fill, ptr_fill + w + 1, color); ptr_fill += p; } } @@ -391,60 +397,59 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { a1 = ~a2; if (fill) { - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, Base::_color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, Base::_color); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, Base::_color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, Base::_color); + Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); } else { - blendPixelPtr(ptr_tr + y - (px-p), a2); - blendPixelPtr(ptr_tr + x - 1 - py, a2); + blendPixelPtr(ptr_tr + y - (px-p), color, a2); + blendPixelPtr(ptr_tr + x - 1 - py, color, a2); - blendPixelPtr(ptr_tl - x + 1 - py, a2); - blendPixelPtr(ptr_tl - y - (px-p), a2); + blendPixelPtr(ptr_tl - x + 1 - py, color, a2); + blendPixelPtr(ptr_tl - y - (px-p), color, a2); - blendPixelPtr(ptr_bl - y + (px-p), a2); - blendPixelPtr(ptr_bl - x + 1 + py, a2); + blendPixelPtr(ptr_bl - y + (px-p), color, a2); + blendPixelPtr(ptr_bl - x + 1 + py, color, a2); - blendPixelPtr(ptr_br + x - 1 + py, a2); - blendPixelPtr(ptr_br + y + (px-p), a2); + blendPixelPtr(ptr_br + x - 1 + py, color, a2); + blendPixelPtr(ptr_br + y + (px-p), color, a2); } - blendPixelPtr(ptr_tr + y - px, a1); - blendPixelPtr(ptr_tr + x - py, a1); + blendPixelPtr(ptr_tr + y - px, color, a1); + blendPixelPtr(ptr_tr + x - py, color, a1); - blendPixelPtr(ptr_tl - x - py, a1); - blendPixelPtr(ptr_tl - y - px, a1); + blendPixelPtr(ptr_tl - x - py, color, a1); + blendPixelPtr(ptr_tl - y - px, color, a1); - blendPixelPtr(ptr_bl - y + px, a1); - blendPixelPtr(ptr_bl - x + py, a1); + blendPixelPtr(ptr_bl - y + px, color, a1); + blendPixelPtr(ptr_bl - x + py, color, a1); - blendPixelPtr(ptr_br + x + py, a1); - blendPixelPtr(ptr_br + y + px, a1); + blendPixelPtr(ptr_br + x + py, color, a1); + blendPixelPtr(ptr_br + y + px, color, a1); } } template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r) { +drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { int x = r; int y = 0; int p = Base::surfacePitch(), px = 0, py = 0; uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; - bool fill = false; PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); px = p * x; py = p * y; - *(ptr + x) = (PixelType)Base::_color; - *(ptr - x) = (PixelType)Base::_color; - *(ptr + px) = (PixelType)Base::_color; - *(ptr - px) = (PixelType)Base::_color; + *(ptr + x) = (PixelType)color; + *(ptr - x) = (PixelType)color; + *(ptr + px) = (PixelType)color; + *(ptr - px) = (PixelType)color; - if (fill) Common::set_to(ptr - x, ptr + x, Base::_color); + if (fill) Common::set_to(ptr - x, ptr + x, color); while (x > y++) { @@ -462,29 +467,29 @@ drawCircleAlg(int x1, int y1, int r) { a1 = ~a2; if (fill) { - Common::set_to(ptr - x + py, ptr + x + py, Base::_color); - Common::set_to(ptr - x - py, ptr + x - py, Base::_color); - Common::set_to(ptr - y + px, ptr + y + px, Base::_color); - Common::set_to(ptr - y - px, ptr + y - px, Base::_color); + Common::set_to(ptr - x + py, ptr + x + py, color); + Common::set_to(ptr - x - py, ptr + x - py, color); + Common::set_to(ptr - y + px, ptr + y + px, color); + Common::set_to(ptr - y - px, ptr + y - px, color); } else { - blendPixelPtr(ptr + x - 1 + py, a2); - blendPixelPtr(ptr + y - (px-p), a2); - blendPixelPtr(ptr - x + 1 - py, a2); - blendPixelPtr(ptr - y - (px-p), a2); - blendPixelPtr(ptr - y + (px-p), a2); - blendPixelPtr(ptr - x + 1 + py, a2); - blendPixelPtr(ptr + y + (px-p), a2); - blendPixelPtr(ptr + x - 1 - py, a2); + blendPixelPtr(ptr + x - 1 + py, color, a2); + blendPixelPtr(ptr + y - (px-p), color, a2); + blendPixelPtr(ptr - x + 1 - py, color, a2); + blendPixelPtr(ptr - y - (px-p), color, a2); + blendPixelPtr(ptr - y + (px-p), color, a2); + blendPixelPtr(ptr - x + 1 + py, color, a2); + blendPixelPtr(ptr + y + (px-p), color, a2); + blendPixelPtr(ptr + x - 1 - py, color, a2); } - blendPixelPtr(ptr + x + py, a1); - blendPixelPtr(ptr + y - px, a1); - blendPixelPtr(ptr - x - py, a1); - blendPixelPtr(ptr - y - px, a1); - blendPixelPtr(ptr - y + px, a1); - blendPixelPtr(ptr - x + py, a1); - blendPixelPtr(ptr + y + px, a1); - blendPixelPtr(ptr + x - py, a1); + blendPixelPtr(ptr + x + py, color, a1); + blendPixelPtr(ptr + y - px, color, a1); + blendPixelPtr(ptr - x - py, color, a1); + blendPixelPtr(ptr - y - px, color, a1); + blendPixelPtr(ptr - y + px, color, a1); + blendPixelPtr(ptr - x + py, color, a1); + blendPixelPtr(ptr + y + px, color, a1); + blendPixelPtr(ptr + x - py, color, a1); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 4ab5bd5e27..bc96299fc2 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -53,8 +53,21 @@ void vector_renderer_test(OSystem *_system); class VectorRenderer { public: + VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL) {} virtual ~VectorRenderer() {} + enum FillMode { + kNoFill = 0, + kForegroundFill = 1, + kBackgroundFill = 2, + kGradientFill = 3 + }; + + enum ColorMode { + kForegroundColor, + kBackgroundColor + }; + /** * Draws a line by considering the special cases for optimization. * @@ -75,7 +88,7 @@ public: virtual void drawCircle(int x, int y, int r) = 0; - virtual void drawSquare(int x, int y, int w, int h, bool fill) = 0; + virtual void drawSquare(int x, int y, int w, int h) = 0; virtual void drawRoundedSquare(int x1, int y1, int r, int w, int h) = 0; @@ -110,7 +123,8 @@ public: * @param g value of the green color byte * @param b value of the blue color byte */ - virtual void setColor(uint8 r, uint8 g, uint8 b) = 0; + virtual void setFgColor(uint8 r, uint8 g, uint8 b) = 0; + virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; /** * Sets the active drawing surface. All drawing from this @@ -125,7 +139,7 @@ public: /** * Fills the active surface with the currently active drawing color. */ - virtual void fillSurface() = 0; + virtual void fillSurface(ColorMode mode = kForegroundColor) = 0; /** * Clears the active surface. @@ -135,54 +149,28 @@ public: memset(src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel); } - /** - * Draws a single pixel on the surface with the given coordinates and - * the currently active drawing color. - * - * @param x Horizontal coordinate of the pixel. - * @param y Vertical coordinate of the pixel. - */ - inline virtual void putPixel(int x, int y) = 0; - - /** - * Blends a single pixel on the surface with the given coordinates, with - * the currently active drawing color and with the given Alpha intensity. - * - * @param x Horizontal coordinate of the pixel. - * @param y Vertical coordinate of the pixel. - * @param alpha Alpha intensity of the pixel (0-255) - */ - inline virtual void blendPixel(int x, int y, uint8 alpha) = 0; - -protected: - - /** - * Generic line drawing algorithm. May be implemented by each - * inheriting class, i.e. with platform specific code. - * - * @see VectorRenderer::drawLine() - * @param x1 Horizontal (X) coordinate for the line start - * @param x2 Horizontal (X) coordinate for the line end - * @param y1 Vertical (Y) coordinate for the line start - * @param y2 Vertical (Y) coordinate for the line end - * @param dx Horizontal (X) increasement. - * @param dy Vertical (Y) increasement. - */ - virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy) = 0; + virtual void setFillMode(VectorRenderer::FillMode mode) { + _fillMode = mode; + } - /** - * Specific circle drawing algorithm with symmetry. Must be implemented - * on each renderer. - * - * @param x Horizontal (X) coordinate for the center of the circle - * @param y Vertical (Y) coordinate for the center of the circle - * @param r Radius of the circle. - */ - virtual void drawCircleAlg(int x, int y, int r) = 0; + virtual void shadowEnable(int x_offset, int y_offset) { + _shadows = true; + _shadowXOffset = x_offset; + _shadowYOffset = y_offset; + } - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) = 0; + virtual void shadowDisable() { + _shadows = false; + } +protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ + + FillMode _fillMode; + + bool _shadows; + int _shadowXOffset; + int _shadowYOffset; }; @@ -217,70 +205,147 @@ public: void drawLine(int x1, int y1, int x2, int y2); void drawCircle(int x, int y, int r) { - drawCircleAlg(x, y, r); + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawCircleAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kForegroundFill: + drawCircleAlg(x, y, r, _fgColor, true); + break; + + case kBackgroundFill: + drawCircleAlg(x, y, r - 1, _bgColor, true); + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kGradientFill: + break; + } } - void drawSquare(int x, int y, int w, int h, bool fill); + void drawSquare(int x, int y, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawSquareAlg(x + Base::_shadowXOffset , y + h, w, Base::_shadowYOffset, 0, true); + drawSquareAlg(x + w, y + Base::_shadowYOffset, Base::_shadowXOffset, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawSquareAlg(x, y, w, h, _fgColor, true); + break; + + case kBackgroundFill: + drawSquareAlg(x, y, w, h, _bgColor, true); + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kGradientFill: + break; + } + } + + void drawRoundedSquare(int x, int y, int r, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawRoundedSquareAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, w, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); + break; + + case kBackgroundFill: + drawRoundedSquareAlg(x, y, r + 1, w, h, _bgColor, true); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; - void drawRoundedSquare(int x1, int y1, int r, int w, int h) { - drawRoundedSquareAlg(x1, y1, r, w, h); + case kGradientFill: + break; + } } /** * @see VectorRenderer::setColor() */ - void setColor(uint8 r, uint8 g, uint8 b) { - this->_color = RGBToColor(r, g, b); + void setFgColor(uint8 r, uint8 g, uint8 b) { + this->_fgColor = RGBToColor(r, g, b); + } + + void setBgColor(uint8 r, uint8 g, uint8 b) { + this->_bgColor = RGBToColor(r, g, b); } /** * @see VectorRenderer::fillSurface() */ - void fillSurface() { + void fillSurface(ColorMode mode = kForegroundColor) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); int s = _activeSurface->w * _activeSurface->h; - Common::set_to(ptr, ptr + s, (PixelType)_color); + + if (mode == kBackgroundColor) + Common::set_to(ptr, ptr + s, _bgColor); + else if (mode == kForegroundColor) + Common::set_to(ptr, ptr + s, _fgColor); } +protected: + /** - * @see VectorRenderer::putPixel() + * Draws a single pixel on the surface with the given coordinates and + * the given color. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param color Color of the pixel */ - inline void putPixel( int x, int y ) { + virtual inline void putPixel( int x, int y, PixelType color ) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - *ptr = _color; + *ptr = color; } /** - * On the Specialized Renderer, alpha blending is not supported. + * Blends a single pixel on the surface with the given coordinates, color + * and Alpha intensity. * - * @see VectorRenderer::blendPixel() + * Note: Pixel blending is currently disabled on the Specialized Renderer + * because of performance issues. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) */ - virtual inline void blendPixel(int x, int y, uint8 alpha) { - putPixel(x, y); + virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { + putPixel(x, y, color); } -protected: - /* * "Bresenham's Line Algorithm", as described in Wikipedia. * Based on the current implementation in "graphics/primitives.cpp". * * Generic line drawing algorithm for the aliased renderer. Optimized with no * floating point operations and direct access to pixel buffer, assumes no special cases. - * - * @see VectorRenderer::drawLineAlg() - */ - virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy); - - /** - * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r); - - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h) { - } + virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false) {} + virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill = false); - PixelType _color; /** Color currently being used to draw on the renderer */ + PixelType _fgColor; /** Color currently being used to draw on the renderer */ + PixelType _bgColor; }; /** @@ -308,7 +373,7 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy); + void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); /** * Perform alpha blending on top of a given pixel, not on a given @@ -321,7 +386,7 @@ protected: * @param ptr Pointer to the pixel where we must draw * @param alpha Intensity of the pixel (0-255). */ - inline void blendPixelPtr(PixelType *ptr, uint8 alpha); + inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); /** * @see VectorRenderer::blendPixel() @@ -329,13 +394,11 @@ protected: * The AA renderer does support alpha blending. Special cases are * handled separately. */ - inline void blendPixel(int x, int y, uint8 alpha) { - if (alpha == 0) - return; - else if (alpha < 255) - blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), alpha); - else - Base::putPixel(x, y); + inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { + if (alpha == 255) + putPixel(x, y, color); + else if (alpha > 0 ) + blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } /** @@ -347,9 +410,9 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false); }; } // end of namespace Graphics -- cgit v1.2.3 From b710756f9df0c19de5f060b8cc86f844179d63c0 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 10 May 2008 21:58:05 +0000 Subject: - Documentation updated - More refactoring - Stroke width support for the AA renderer!! - Cleanup svn-id: r31990 --- graphics/VectorRenderer.cpp | 293 ++++++++++++++++++++++++++++---------------- graphics/VectorRenderer.h | 182 ++++++++++++++------------- 2 files changed, 283 insertions(+), 192 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 67a60bbde1..d840b5d35a 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -62,10 +62,11 @@ void vector_renderer_test(OSystem *_system) { vr->setFgColor(255, 255, 255); vr->fillSurface(); - vr->setFgColor(255, 0, 0 ); - vr->setBgColor(25, 25, 175 ); - vr->setFillMode( VectorRenderer::kBackgroundFill ); - vr->shadowEnable( 5, 5 ); + vr->setFgColor(255, 0, 0); + vr->setBgColor(25, 25, 175); + vr->setFillMode(VectorRenderer::kBackgroundFill); + vr->setStrokeWidth(3); + vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); @@ -85,9 +86,88 @@ void vector_renderer_test(OSystem *_system) { _system->hideOverlay(); } +template +void VectorRendererSpec:: +drawCircle(int x, int y, int r) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kForegroundFill: + drawCircleAlg(x, y, r, _fgColor, true); + break; + + case kBackgroundFill: + VectorRendererSpec::drawCircleAlg(x, y, r - 1, _bgColor, true); + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + +template +void VectorRendererSpec:: +drawSquare(int x, int y, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, w, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawSquareAlg(x, y, w, h, _fgColor, true); + break; + + case kBackgroundFill: + drawSquareAlg(x, y, w, h, _bgColor, true); + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + +template +void VectorRendererSpec:: +drawRoundedSquare(int x, int y, int r, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawRoundedSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, w, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); + break; + + case kBackgroundFill: + VectorRendererSpec::drawRoundedSquareAlg(x + 1, y + 1, r, w - 1, h - 1, _bgColor, true); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + template void VectorRendererSpec:: drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int pitch = Base::surfacePitch(); @@ -97,12 +177,17 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { ptr += pitch; } } else { - Common::set_to(ptr, ptr + w, color); - Common::set_to(ptr + pitch * h, ptr + w + pitch * h, color); + int sw = _strokeWidth, sp = 0, hp = pitch * (h - 1); + + while(sw--) { + Common::set_to(ptr + sp, ptr + w + sp, color); + Common::set_to(ptr + hp - sp, ptr + w + hp - sp, color); + sp += pitch; + } while (h--) { - *ptr = color; - *(ptr + w) = color; + Common::set_to(ptr, ptr + _strokeWidth, color); + Common::set_to(ptr + w - _strokeWidth, ptr + w, color); ptr += pitch; } } @@ -159,6 +244,11 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { template void VectorRendererAA:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + if (alpha == 255) { + *ptr = color; + return; + } + register int idst = *ptr; register int isrc = color; @@ -283,7 +373,7 @@ inline uint32 fp_sqroot(uint32 x) { remHI = (remHI << 2) | (remLO >> 30); remLO <<= 2; root <<= 1; - testDIV = (root << 1 ) + 1; + testDIV = (root << 1) + 1; if (remHI >= testDIV) { remHI -= testDIV; @@ -343,12 +433,35 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { } } +#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ + blendPixelPtr(ptr1 + (y) - (px), color, a); \ + blendPixelPtr(ptr1 + (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (y) - (px), color, a); \ + blendPixelPtr(ptr3 - (y) + (px), color, a); \ + blendPixelPtr(ptr3 - (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (y) + (px), color, a); \ +} + +#define __WU_ALGORITHM() { \ + oldT = T; \ + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ + py += p; \ + if (T < oldT) { \ + x--; px -= p; \ + } \ + a2 = (T >> 8); \ + a1 = ~a2; \ +} + template void VectorRendererAA:: drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { - int x = r; - int y = 0; + int x, y; int p = Base::surfacePitch(), px, py; + int sw = 0, sp = 0, hp = h * p; + uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; @@ -359,137 +472,105 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - Common::set_to(ptr_fill + r, ptr_fill + w - r + 1, color); - Common::set_to(ptr_fill + r + h*p, ptr_fill + w - r + 1 + h*p, color); - - h -= 2*r; - ptr_fill += p*r; - - if (!fill) { - while (h-- >= 0) { - *(ptr_fill) = (PixelType)color; - *(ptr_fill + w) = (PixelType)color; - ptr_fill += p; - } - } else { - while (h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += p; - } - } + int short_h = h - 2 * r; - px = p * x; - py = 0; + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += p; - while (x > y++) - { - oldT = T; - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); - py += p; + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; - if (T < oldT) { - x--; - px -= p; + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } } - a2 = (T >> 8); - a1 = ~a2; + ptr_fill += p * r; + while (short_h-- >= 0) { + Common::set_to(ptr_fill, ptr_fill + _strokeWidth, color); + Common::set_to(ptr_fill + w - _strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += p; + } + } else { + x = r; y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); - if (fill) { Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); - } else { - blendPixelPtr(ptr_tr + y - (px-p), color, a2); - blendPixelPtr(ptr_tr + x - 1 - py, color, a2); - blendPixelPtr(ptr_tl - x + 1 - py, color, a2); - blendPixelPtr(ptr_tl - y - (px-p), color, a2); - - blendPixelPtr(ptr_bl - y + (px-p), color, a2); - blendPixelPtr(ptr_bl - x + 1 + py, color, a2); - - blendPixelPtr(ptr_br + x - 1 + py, color, a2); - blendPixelPtr(ptr_br + y + (px-p), color, a2); - } - - blendPixelPtr(ptr_tr + y - px, color, a1); - blendPixelPtr(ptr_tr + x - py, color, a1); - - blendPixelPtr(ptr_tl - x - py, color, a1); - blendPixelPtr(ptr_tl - y - px, color, a1); - - blendPixelPtr(ptr_bl - y + px, color, a1); - blendPixelPtr(ptr_bl - x + py, color, a1); + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } - blendPixelPtr(ptr_br + x + py, color, a1); - blendPixelPtr(ptr_br + y + px, color, a1); + ptr_fill += p * r; + while (short_h-- >= 0) { + Common::set_to(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += p; + } } } template void VectorRendererAA:: drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { - int x = r; - int y = 0; - int p = Base::surfacePitch(), px = 0, py = 0; + int x, y, sw = 0; + int p = Base::surfacePitch(), px, py; + uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - px = p * x; - py = p * y; - *(ptr + x) = (PixelType)color; - *(ptr - x) = (PixelType)color; - *(ptr + px) = (PixelType)color; - *(ptr - px) = (PixelType)color; - - if (fill) Common::set_to(ptr - x, ptr + x, color); + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; - while (x > y++) - { - oldT = T; - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; + *(ptr + x) = (PixelType)color; + *(ptr - x) = (PixelType)color; + *(ptr + px) = (PixelType)color; + *(ptr - px) = (PixelType)color; - py += p; + while (x > y++) { + __WU_ALGORITHM(); - if (T < oldT) { - x--; - px -= p; + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } } + } else { + Common::set_to(ptr - r, ptr + r + 1, color); + x = r; y = 0; T = 0; + px = p * x; py = 0; - a2 = (T >> 8); - a1 = ~a2; + while (x > y++) { + __WU_ALGORITHM(); - if (fill) { Common::set_to(ptr - x + py, ptr + x + py, color); Common::set_to(ptr - x - py, ptr + x - py, color); Common::set_to(ptr - y + px, ptr + y + px, color); Common::set_to(ptr - y - px, ptr + y - px, color); - } else { - blendPixelPtr(ptr + x - 1 + py, color, a2); - blendPixelPtr(ptr + y - (px-p), color, a2); - blendPixelPtr(ptr - x + 1 - py, color, a2); - blendPixelPtr(ptr - y - (px-p), color, a2); - blendPixelPtr(ptr - y + (px-p), color, a2); - blendPixelPtr(ptr - x + 1 + py, color, a2); - blendPixelPtr(ptr + y + (px-p), color, a2); - blendPixelPtr(ptr + x - 1 - py, color, a2); - } - - blendPixelPtr(ptr + x + py, color, a1); - blendPixelPtr(ptr + y - px, color, a1); - blendPixelPtr(ptr - x - py, color, a1); - blendPixelPtr(ptr - y - px, color, a1); - blendPixelPtr(ptr - y + px, color, a1); - blendPixelPtr(ptr - x + py, color, a1); - blendPixelPtr(ptr + y + px, color, a1); - blendPixelPtr(ptr + x - py, color, a1); + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index bc96299fc2..1cf7337c84 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -53,7 +53,7 @@ void vector_renderer_test(OSystem *_system); class VectorRenderer { public: - VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL) {} + VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1) {} virtual ~VectorRenderer() {} enum FillMode { @@ -87,10 +87,27 @@ public: */ virtual void drawCircle(int x, int y, int r) = 0; - + /** + * Draws a square starting at (x,y) with the given width and height. + * + * @param x Horizontal (X) coordinate for the center of the square + * @param y Vertical (Y) coordinate for the center of the square + * @param w Width of the square. + * @param h Height of the square + */ virtual void drawSquare(int x, int y, int w, int h) = 0; - virtual void drawRoundedSquare(int x1, int y1, int r, int w, int h) = 0; + /** + * Draws a rounded square starting at (x,y) with the given width and height. + * The corners of the square are rounded with the given radius. + * + * @param x Horizontal (X) coordinate for the center of the square + * @param y Vertical (Y) coordinate for the center of the square + * @param w Width of the square. + * @param h Height of the square + * @param r Radius of the corners. + */ + virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -115,15 +132,29 @@ public: } /** - * Set the active painting color for the renderer. - * All the drawing from then on will be done with that color, unless + * Set the active foreground painting color for the renderer. + * All the foreground drawing from then on will be done with that color, unless * specified otherwise. * + * Foreground drawing means all outlines and basic shapes. + * * @param r value of the red color byte * @param g value of the green color byte * @param b value of the blue color byte */ virtual void setFgColor(uint8 r, uint8 g, uint8 b) = 0; + + /** + * Set the active background painting color for the renderer. + * All the background drawing from then on will be done with that color, unless + * specified otherwise. + * + * Background drawing means all the shape filling. + * + * @param r value of the red color byte + * @param g value of the green color byte + * @param b value of the blue color byte + */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; /** @@ -137,7 +168,10 @@ public: } /** - * Fills the active surface with the currently active drawing color. + * Fills the active surface with the specified fg/bg color. + * Defaults to using the active Foreground color for filling. + * + * @param mode Color mode (bg or fg color) used to fill. */ virtual void fillSurface(ColorMode mode = kForegroundColor) = 0; @@ -149,16 +183,46 @@ public: memset(src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel); } + /** + * Sets the active fill mode for all shapes. + * + * @see VectorRenderer::FillMode + * @param mode Specified fill mode. + */ virtual void setFillMode(VectorRenderer::FillMode mode) { _fillMode = mode; } + /** + * Sets the stroke width. All shapes drawn with a stroke will + * have that width. + * + * @param width Witdh of the stroke in pixels. + */ + virtual void setStrokeWidth(int width) { + if (width > 0) _strokeWidth = width; + } + + /** + * Enables adding shadows to all drawn primitives. + * Shadows are drawn automatically under the shapes, at the + * given x/y offsets. + * + * @param x_offset Horizontal offset for the shadows. + * @param y_offset Vertical offset for the shadows. + * @see shadowDisable() + */ virtual void shadowEnable(int x_offset, int y_offset) { _shadows = true; _shadowXOffset = x_offset; _shadowYOffset = y_offset; } + /** + * Disables adding shadows to all drawn primitives. + * + * @see shadowEnable() + */ virtual void shadowDisable() { _shadows = false; } @@ -166,13 +230,14 @@ public: protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ - FillMode _fillMode; + FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ - bool _shadows; - int _shadowXOffset; - int _shadowYOffset; -}; + bool _shadows; /** Defines if shadows are automatically added to drawn shapes */ + int _shadowXOffset; /** Horizontal offset for drawn shadows */ + int _shadowYOffset; /** Vertical offset for drawn shadows */ + int _strokeWidth; /** Width of the stroke of all drawn shapes */ +}; /** @@ -204,86 +269,31 @@ public: */ void drawLine(int x1, int y1, int x2, int y2); - void drawCircle(int x, int y, int r) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawCircleAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawCircleAlg(x, y, r, _fgColor, false); - break; - - case kForegroundFill: - drawCircleAlg(x, y, r, _fgColor, true); - break; - - case kBackgroundFill: - drawCircleAlg(x, y, r - 1, _bgColor, true); - drawCircleAlg(x, y, r, _fgColor, false); - break; - - case kGradientFill: - break; - } - } - - void drawSquare(int x, int y, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawSquareAlg(x + Base::_shadowXOffset , y + h, w, Base::_shadowYOffset, 0, true); - drawSquareAlg(x + w, y + Base::_shadowYOffset, Base::_shadowXOffset, h, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawSquareAlg(x, y, w, h, _fgColor, false); - break; - - case kForegroundFill: - drawSquareAlg(x, y, w, h, _fgColor, true); - break; - - case kBackgroundFill: - drawSquareAlg(x, y, w, h, _bgColor, true); - drawSquareAlg(x, y, w, h, _fgColor, false); - break; - - case kGradientFill: - break; - } - } - - void drawRoundedSquare(int x, int y, int r, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawRoundedSquareAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, w, h, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); - break; - - case kForegroundFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); - break; + /** + * @see VectorRenderer::drawCircle() + */ + void drawCircle(int x, int y, int r); - case kBackgroundFill: - drawRoundedSquareAlg(x, y, r + 1, w, h, _bgColor, true); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); - break; + /** + * @see VectorRenderer::drawSquare() + */ + void drawSquare(int x, int y, int w, int h); - case kGradientFill: - break; - } - } + /** + * @see VectorRenderer::drawRoundedSquare() + */ + void drawRoundedSquare(int x, int y, int r, int w, int h); /** - * @see VectorRenderer::setColor() + * @see VectorRenderer::setFgColor() */ void setFgColor(uint8 r, uint8 g, uint8 b) { this->_fgColor = RGBToColor(r, g, b); } + /** + * @see VectorRenderer::setBgColor() + */ void setBgColor(uint8 r, uint8 g, uint8 b) { this->_bgColor = RGBToColor(r, g, b); } @@ -311,7 +321,7 @@ protected: * @param y Vertical coordinate of the pixel. * @param color Color of the pixel */ - virtual inline void putPixel( int x, int y, PixelType color ) { + virtual inline void putPixel(int x, int y, PixelType color) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); *ptr = color; } @@ -344,8 +354,8 @@ protected: virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false) {} virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill = false); - PixelType _fgColor; /** Color currently being used to draw on the renderer */ - PixelType _bgColor; + PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ + PixelType _bgColor; /** Background color currently being used to draw on the renderer */ }; /** @@ -397,7 +407,7 @@ protected: inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { if (alpha == 255) putPixel(x, y, color); - else if (alpha > 0 ) + else if (alpha > 0) blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } -- cgit v1.2.3 From 82dcbd115a7306dd82020876611877724bb264f5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 10 May 2008 22:03:45 +0000 Subject: - Formating (lol) - Compilation fix for GCC (inheritance) svn-id: r31991 --- graphics/VectorRenderer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index d840b5d35a..1da0125346 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -177,17 +177,17 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { ptr += pitch; } } else { - int sw = _strokeWidth, sp = 0, hp = pitch * (h - 1); + int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1); - while(sw--) { + while (sw--) { Common::set_to(ptr + sp, ptr + w + sp, color); Common::set_to(ptr + hp - sp, ptr + w + hp - sp, color); sp += pitch; } while (h--) { - Common::set_to(ptr, ptr + _strokeWidth, color); - Common::set_to(ptr + w - _strokeWidth, ptr + w, color); + Common::set_to(ptr, ptr + Base::_strokeWidth, color); + Common::set_to(ptr + w - Base::_strokeWidth, ptr + w, color); ptr += pitch; } } @@ -496,7 +496,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool ptr_fill += p * r; while (short_h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + _strokeWidth, color); + Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); Common::set_to(ptr_fill + w - _strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += p; } -- cgit v1.2.3 From 985f073376736e9886d3cc16f546e81217b8d28c Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 11 May 2008 02:44:21 +0000 Subject: Fixing compilation svn-id: r31995 --- graphics/VectorRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 1da0125346..7a3fd7b674 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -497,7 +497,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool ptr_fill += p * r; while (short_h-- >= 0) { Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); - Common::set_to(ptr_fill + w - _strokeWidth + 1, ptr_fill + w + 1, color); + Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += p; } } else { -- cgit v1.2.3 From 373efe438a08113b5f6ba4aec7360b5e17906e40 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 11 May 2008 11:22:58 +0000 Subject: - Stroke on Aliased circles. svn-id: r32015 --- graphics/VectorRenderer.cpp | 97 ++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 7a3fd7b674..83dfdab943 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -35,7 +35,7 @@ namespace Graphics { inline uint32 fp_sqroot(uint32 x); VectorRenderer *createRenderer() { - return new VectorRendererAA >; + return new VectorRendererSpec >; } @@ -64,8 +64,8 @@ void vector_renderer_test(OSystem *_system) { vr->setFgColor(255, 0, 0); vr->setBgColor(25, 25, 175); - vr->setFillMode(VectorRenderer::kBackgroundFill); - vr->setStrokeWidth(3); + vr->setFillMode(VectorRenderer::kForegroundFill); + vr->setStrokeWidth(1); vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); @@ -103,7 +103,7 @@ drawCircle(int x, int y, int r) { break; case kBackgroundFill: - VectorRendererSpec::drawCircleAlg(x, y, r - 1, _bgColor, true); + VectorRendererSpec::drawCircleAlg(x, y, r, _bgColor, true); drawCircleAlg(x, y, r, _fgColor, false); break; @@ -384,52 +384,75 @@ inline uint32 fp_sqroot(uint32 x) { return root; } +#define __BE_ALGORITHM() { \ + if (f >= 0) { \ + y--; \ + ddF_y += 2; \ + f += ddF_y; \ + py -= pitch; \ + } \ + px += pitch; \ + ddF_x += 2; \ + f += ddF_x + 1; \ +} + +#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ + *(ptr1 + x + py) = color; \ + *(ptr1 + y - px) = color; \ + *(ptr1 - x - py) = color; \ + *(ptr1 - y - px) = color; \ + *(ptr1 - y + px) = color; \ + *(ptr1 - x + py) = color; \ + *(ptr1 + y + px) = color; \ + *(ptr1 + x - py) = color; \ +} + +#define __BE_RESET() { \ + f = 1 - r; \ + ddF_x = 0; ddF_y = -2 * r; \ + x = 0; y = r; px = 0; py = pitch * r; \ +} + + template void VectorRendererSpec:: drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { - int f = 1 - r; - int ddF_x = 0, ddF_y = -2 * r; - int x = 0, y = r, px, py; + int f, ddF_x, ddF_y; + int x, y, px, py, sw = 0; int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - px = 0; - py = pitch * y; - - *(ptr + y) = color; - *(ptr - y) = color; - *(ptr + py) = color; - *(ptr - py) = color; - - if (fill) Common::set_to(ptr - r, ptr + r, color); - - while (x++ < y) { - if (f >= 0) { - y--; - ddF_y += 2; - f += ddF_y; - py -= pitch; + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + __BE_RESET(); + r--; + + *(ptr + y) = color; + *(ptr - y) = color; + *(ptr + py) = color; + *(ptr - py) = color; + + while (x++ < y) { + __BE_ALGORITHM(); + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py); + + if (Base::_strokeWidth > 1) { + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py); + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py); + } + } } + } else { + Common::set_to(ptr - r, ptr + r, color); + __BE_RESET(); - px += pitch; - ddF_x += 2; - f += ddF_x + 1; - - if (fill) { + while (x++ < y) { + __BE_ALGORITHM(); Common::set_to(ptr - x + py, ptr + x + py, color); Common::set_to(ptr - x - py, ptr + x - py, color); Common::set_to(ptr - y + px, ptr + y + px, color); Common::set_to(ptr - y - px, ptr + y - px, color); } - - *(ptr + x + py) = color; - *(ptr + y - px) = color; - *(ptr - x - py) = color; - *(ptr - y - px) = color; - *(ptr - y + px) = color; - *(ptr - x + py) = color; - *(ptr + y + px) = color; - *(ptr + x - py) = color; } } -- cgit v1.2.3 From f19480b74090159296be1aa608591123e917dd36 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 11 May 2008 14:05:59 +0000 Subject: - Aliased rounded squares + stroking. svn-id: r32021 --- graphics/VectorRenderer.cpp | 85 +++++++++++++++++++++++++++++++++++++++------ graphics/VectorRenderer.h | 2 +- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 83dfdab943..6f6aa9b125 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -65,7 +65,7 @@ void vector_renderer_test(OSystem *_system) { vr->setFgColor(255, 0, 0); vr->setBgColor(25, 25, 175); vr->setFillMode(VectorRenderer::kForegroundFill); - vr->setStrokeWidth(1); + vr->setStrokeWidth(6); vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); @@ -155,7 +155,7 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { break; case kBackgroundFill: - VectorRendererSpec::drawRoundedSquareAlg(x + 1, y + 1, r, w - 1, h - 1, _bgColor, true); + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, true); drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); break; @@ -397,14 +397,14 @@ inline uint32 fp_sqroot(uint32 x) { } #define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ - *(ptr1 + x + py) = color; \ - *(ptr1 + y - px) = color; \ - *(ptr1 - x - py) = color; \ - *(ptr1 - y - px) = color; \ - *(ptr1 - y + px) = color; \ - *(ptr1 - x + py) = color; \ - *(ptr1 + y + px) = color; \ - *(ptr1 + x - py) = color; \ + *(ptr1 + (y) - (px)) = color; \ + *(ptr1 + (x) - (py)) = color; \ + *(ptr2 - (x) - (py)) = color; \ + *(ptr2 - (y) - (px)) = color; \ + *(ptr3 - (y) + (px)) = color; \ + *(ptr3 - (x) + (py)) = color; \ + *(ptr4 + (x) + (py)) = color; \ + *(ptr4 + (y) + (px)) = color; \ } #define __BE_RESET() { \ @@ -456,6 +456,71 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { } } +template +void VectorRendererSpec:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + int sw = 0, sp = 0, hp = h * pitch; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int short_h = h - (2 * r) + 2; + int real_radius = r; + + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += pitch; + + __BE_RESET(); + r--; + + while (x++ < y) { + __BE_ALGORITHM(); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + + if (Base::_strokeWidth > 1) { + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); + } + } + } + + ptr_fill += pitch * real_radius; + while (short_h--) { + Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); + Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } else { + __BE_RESET(); + while (x++ < y) { + __BE_ALGORITHM(); + + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + + Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } + + ptr_fill += pitch * r; + while (short_h--) { + Common::set_to(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } +} + #define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ blendPixelPtr(ptr1 + (y) - (px), color, a); \ blendPixelPtr(ptr1 + (x) - (py), color, a); \ diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 1cf7337c84..bed1e337ca 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -351,7 +351,7 @@ protected: */ virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false) {} + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill = false); PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ -- cgit v1.2.3 From b999366ae911172b9a8ab8a0e8955b73b055cce2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 16 May 2008 20:40:24 +0000 Subject: - Shadows revisited - Gradients. svn-id: r32145 --- dists/msvc9/scummvm.vcproj | 14 +++ graphics/VectorRenderer.cpp | 202 +++++++++++++++++++++++++++++--------------- graphics/VectorRenderer.h | 45 ++++++++-- 3 files changed, 189 insertions(+), 72 deletions(-) diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 889ea04b75..4877c045e7 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1303,10 +1303,24 @@ + + + + + + > 30); + remLO <<= 2; + root <<= 1; + testDIV = (root << 1) + 1; -inline uint32 fp_sqroot(uint32 x); + if (remHI >= testDIV) { + remHI -= testDIV; + root++; + } + } while (count--); + + return root; +} + +namespace Graphics { VectorRenderer *createRenderer() { - return new VectorRendererSpec >; + return new VectorRendererAA >; } @@ -59,19 +80,20 @@ void vector_renderer_test(OSystem *_system) { _system->showOverlay(); while (true) { // draw!! - vr->setFgColor(255, 255, 255); + vr->setFgColor(255, 0, 206); vr->fillSurface(); - vr->setFgColor(255, 0, 0); + vr->setFgColor(255, 247, 222); vr->setBgColor(25, 25, 175); - vr->setFillMode(VectorRenderer::kForegroundFill); - vr->setStrokeWidth(6); + vr->setGradientColors(206, 121, 99, 173, 40, 8); + vr->setFillMode(VectorRenderer::kGradientFill); + vr->setStrokeWidth(1); vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); vr->drawSquare(150, 25, 100, 75); - vr->drawRoundedSquare(275, 25, 8, 100, 75); + vr->drawRoundedSquare(275, 25, 16, 128, 128); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -90,21 +112,21 @@ template void VectorRendererSpec:: drawCircle(int x, int y, int r) { if (Base::_fillMode != kNoFill && Base::_shadows) { - drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, true); + drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, kForegroundFill); } switch(Base::_fillMode) { case kNoFill: - drawCircleAlg(x, y, r, _fgColor, false); + drawCircleAlg(x, y, r, _fgColor, kNoFill); break; case kForegroundFill: - drawCircleAlg(x, y, r, _fgColor, true); + drawCircleAlg(x, y, r, _fgColor, kForegroundFill); break; case kBackgroundFill: - VectorRendererSpec::drawCircleAlg(x, y, r, _bgColor, true); - drawCircleAlg(x, y, r, _fgColor, false); + drawCircleAlg(x, y, r, _fgColor, kForegroundFill); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill); break; case kGradientFill: @@ -116,24 +138,26 @@ template void VectorRendererSpec:: drawSquare(int x, int y, int w, int h) { if (Base::_fillMode != kNoFill && Base::_shadows) { - drawSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, w, h, 0, true); + drawSquareShadow(x, y, w, h); } switch(Base::_fillMode) { case kNoFill: - drawSquareAlg(x, y, w, h, _fgColor, false); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; case kForegroundFill: - drawSquareAlg(x, y, w, h, _fgColor, true); + drawSquareAlg(x, y, w, h, _fgColor, kForegroundFill); break; case kBackgroundFill: - drawSquareAlg(x, y, w, h, _bgColor, true); - drawSquareAlg(x, y, w, h, _fgColor, false); + drawSquareAlg(x, y, w, h, _bgColor, kBackgroundFill); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; case kGradientFill: + VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kGradientFill); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; } } @@ -142,37 +166,48 @@ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { if (Base::_fillMode != kNoFill && Base::_shadows) { - drawRoundedSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, w, h, 0, true); + drawRoundedSquareShadow(x, y, r, w, h); } switch(Base::_fillMode) { case kNoFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); break; case kForegroundFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); break; case kBackgroundFill: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, true); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kBackgroundFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); break; case kGradientFill: + if (Base::_strokeWidth > 1) { + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); + VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, + r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kGradientFill); + } else { + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kGradientFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + } break; } } template void VectorRendererSpec:: -drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { - +drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int pitch = Base::surfacePitch(); + int max_h = h; - if (fill) { + if (fill_m != kNoFill) { while (h--) { + if (fill_m == kGradientFill) + color = calcGradient(max_h - h, max_h); + Common::set_to(ptr, ptr + w, color); ptr += pitch; } @@ -193,6 +228,43 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { } } +template +void VectorRendererSpec:: +drawSquareShadow(int x, int y, int w, int h) { + int blur = 8; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); + int pitch = Base::surfacePitch(); + int i, j; + + i = h - blur; + + while (i--) { + j = blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); + + while (i++ < blur) { + j = w - blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); + + i = 0; + while (i++ < blur) { + j = blur - 1; + while (j--) + blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); + ptr += pitch; + } +} + template void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { @@ -361,29 +433,6 @@ drawLine(int x1, int y1, int x2, int y2) { } } -inline uint32 fp_sqroot(uint32 x) { - register uint32 root, remHI, remLO, testDIV, count; - - root = 0; - remHI = 0; - remLO = x; - count = 23; - - do { - remHI = (remHI << 2) | (remLO >> 30); - remLO <<= 2; - root <<= 1; - testDIV = (root << 1) + 1; - - if (remHI >= testDIV) { - remHI -= testDIV; - root++; - } - } while (count--); - - return root; -} - #define __BE_ALGORITHM() { \ if (f >= 0) { \ y--; \ @@ -416,13 +465,13 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: -drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { +drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py, sw = 0; int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { __BE_RESET(); r--; @@ -458,7 +507,13 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { template void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { +drawRoundedSquareShadow(int x1, int y1, int r, int w, int h) { + +} + +template +void VectorRendererSpec:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); @@ -470,10 +525,11 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - int short_h = h - (2 * r) + 2; int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -501,20 +557,34 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool } } else { __BE_RESET(); - while (x++ < y) { - __BE_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + if (fill_m == kGradientFill) { + while (x++ < y) { + __BE_ALGORITHM(); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + } + } else { + while (x++ < y) { + __BE_ALGORITHM(); + + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + + Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } } ptr_fill += pitch * r; while (short_h--) { + if (fill_m == kGradientFill) + color = calcGradient(real_radius++, long_h); Common::set_to(ptr_fill, ptr_fill + w + 1, color); ptr_fill += pitch; } @@ -545,7 +615,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0, hp = h * p; @@ -562,7 +632,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool int short_h = h - 2 * r; - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -614,7 +684,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { +drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int x, y, sw = 0; int p = Base::surfacePitch(), px, py; @@ -624,7 +694,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { x = r - (sw - 1); y = 0; T = 0; px = p * x; py = 0; @@ -662,4 +732,4 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { } } -} // end of namespace Graphics +} // end of namespace Graphics \ No newline at end of file diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index bed1e337ca..23653aa5fc 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -157,6 +157,8 @@ public: */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; + virtual void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) = 0; + /** * Sets the active drawing surface. All drawing from this * point on will be done on that surface. @@ -298,6 +300,15 @@ public: this->_bgColor = RGBToColor(r, g, b); } + void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { + _gradientEnd = RGBToColor(r2, g2, b2); + _gradientStart = RGBToColor(r1, g1, b1); + + _gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); + _gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); + _gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); + } + /** * @see VectorRenderer::fillSurface() */ @@ -342,6 +353,10 @@ protected: putPixel(x, y, color); } + virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + *ptr = (PixelType)color; + } + /* * "Bresenham's Line Algorithm", as described in Wikipedia. * Based on the current implementation in "graphics/primitives.cpp". @@ -350,12 +365,30 @@ protected: * floating point operations and direct access to pixel buffer, assumes no special cases. */ virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); - virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false); - virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill = false); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); + virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); + virtual void drawSquareShadow(int x, int y, int w, int h); + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h); + + inline PixelType calcGradient(int pos, int max, int factor = 1) { + PixelType output = 0; + pos = (0x1000 * MIN(pos * factor, max)) / max; + + output |= (_gradientStart + (_gradientBytes[0] * pos >> 12)) & PixelFormat::kRedMask; + output |= (_gradientStart + (_gradientBytes[1] * pos >> 12)) & PixelFormat::kGreenMask; + output |= (_gradientStart + (_gradientBytes[2] * pos >> 12)) & PixelFormat::kBlueMask; + output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask); + + return output; + } PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ + + PixelType _gradientStart; + PixelType _gradientEnd; + int _gradientBytes[3]; }; /** @@ -396,7 +429,7 @@ protected: * @param ptr Pointer to the pixel where we must draw * @param alpha Intensity of the pixel (0-255). */ - inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); + inline virtual void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); /** * @see VectorRenderer::blendPixel() @@ -420,9 +453,9 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); }; } // end of namespace Graphics -- cgit v1.2.3 From 4d439fe4fc19030b5b5a8b5f80b073e5644cab09 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sat, 17 May 2008 16:45:28 +0000 Subject: Fixing compilation svn-id: r32154 --- graphics/VectorRenderer.cpp | 10 +++++----- graphics/VectorRenderer.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index ad2ef2b250..47f46e3bcf 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -615,7 +615,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0, hp = h * p; @@ -632,7 +632,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM int short_h = h - 2 * r; - if (fill_m == kNoFill) { + if (fill_m == VectorRenderer::kNoFill) { while (sw++ < Base::_strokeWidth) { Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -684,7 +684,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { +drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { int x, y, sw = 0; int p = Base::surfacePitch(), px, py; @@ -694,7 +694,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill_m == kNoFill) { + if (fill_m == VectorRenderer::kNoFill) { while (sw++ < Base::_strokeWidth) { x = r - (sw - 1); y = 0; T = 0; px = p * x; py = 0; @@ -732,4 +732,4 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { } } -} // end of namespace Graphics \ No newline at end of file +} // end of namespace Graphics diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 23653aa5fc..b7b19a77e7 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -453,9 +453,9 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); }; } // end of namespace Graphics -- cgit v1.2.3 From 55cfae33e9b54d10b602eb9ecc52aee294408a2f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 18 May 2008 00:18:15 +0000 Subject: - Shadows revisited. - Test rendering... starting to look like a GUI. svn-id: r32164 --- graphics/VectorRenderer.cpp | 120 ++++++++++++++++++++++++++++++++++---------- graphics/VectorRenderer.h | 118 ++++++++++++++++++++----------------------- 2 files changed, 148 insertions(+), 90 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 47f46e3bcf..221f525820 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -81,19 +81,25 @@ void vector_renderer_test(OSystem *_system) { while (true) { // draw!! vr->setFgColor(255, 0, 206); - vr->fillSurface(); + vr->setGradientFactor(1); + vr->setGradientColors(214, 113, 8, 240, 200, 25); + vr->fillSurface(VectorRenderer::kGradientFill); - vr->setFgColor(255, 247, 222); vr->setBgColor(25, 25, 175); - vr->setGradientColors(206, 121, 99, 173, 40, 8); - vr->setFillMode(VectorRenderer::kGradientFill); + vr->shadowEnable(3); + vr->setFgColor(240, 204, 120); vr->setStrokeWidth(1); - vr->shadowEnable(1, 1); + vr->setFillMode(VectorRenderer::kGradientFill); - vr->drawLine(25, 25, 125, 300); - vr->drawCircle(250, 250, 100); - vr->drawSquare(150, 25, 100, 75); - vr->drawRoundedSquare(275, 25, 16, 128, 128); + vr->setGradientFactor(3); + vr->setGradientColors(255, 231, 140, 255, 243, 206); + vr->drawRoundedSquare(25, 95, 18, 465, 290); + + vr->setGradientFactor(1); + vr->setGradientColors(206, 121, 99, 173, 40, 8); + vr->drawRoundedSquare(500, 95, 8, 120, 30); + vr->drawRoundedSquare(500, 135, 8, 120, 30); + vr->drawRoundedSquare(500, 175, 8, 120, 30); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -111,13 +117,14 @@ void vector_renderer_test(OSystem *_system) { template void VectorRendererSpec:: drawCircle(int x, int y, int r) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, kForegroundFill); + if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kForegroundFill); } switch(Base::_fillMode) { case kNoFill: - drawCircleAlg(x, y, r, _fgColor, kNoFill); + if (Base::_strokeWidth) + drawCircleAlg(x, y, r, _fgColor, kNoFill); break; case kForegroundFill: @@ -125,8 +132,13 @@ drawCircle(int x, int y, int r) { break; case kBackgroundFill: - drawCircleAlg(x, y, r, _fgColor, kForegroundFill); - drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill); + if (Base::_strokeWidth > 1) { + drawCircleAlg(x, y, r, _fgColor, kForegroundFill); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill); + } else { + drawCircleAlg(x, y, r, _bgColor, kBackgroundFill); + drawCircleAlg(x, y, r, _fgColor, kNoFill); + } break; case kGradientFill: @@ -137,13 +149,14 @@ drawCircle(int x, int y, int r) { template void VectorRendererSpec:: drawSquare(int x, int y, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawSquareShadow(x, y, w, h); + if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + drawSquareShadow(x, y, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { case kNoFill: - drawSquareAlg(x, y, w, h, _fgColor, kNoFill); + if (Base::_strokeWidth) + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; case kForegroundFill: @@ -157,7 +170,8 @@ drawSquare(int x, int y, int w, int h) { case kGradientFill: VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kGradientFill); - drawSquareAlg(x, y, w, h, _fgColor, kNoFill); + if (Base::_strokeWidth) + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; } } @@ -165,13 +179,14 @@ drawSquare(int x, int y, int w, int h) { template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawRoundedSquareShadow(x, y, r, w, h); + if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { case kNoFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + if (Base::_strokeWidth) + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); break; case kForegroundFill: @@ -190,7 +205,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kGradientFill); } else { VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kGradientFill); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + if (Base::_strokeWidth) + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); } break; } @@ -230,8 +246,7 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { template void VectorRendererSpec:: -drawSquareShadow(int x, int y, int w, int h) { - int blur = 8; +drawSquareShadow(int x, int y, int w, int h, int blur) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); int pitch = Base::surfacePitch(); int i, j; @@ -314,7 +329,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { template -void VectorRendererAA:: +void VectorRendererSpec:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { if (alpha == 255) { *ptr = color; @@ -404,6 +419,9 @@ drawLine(int x1, int y1, int x2, int y2) { if (dy == 0 && dx == 0) return; + if (Base::_strokeWidth == 0) + return; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = Base::surfacePitch(); @@ -507,8 +525,57 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { template void VectorRendererSpec:: -drawRoundedSquareShadow(int x1, int y1, int r, int w, int h) { +drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + int sw = 0, sp = 0, hp = h * pitch; + int alpha = 102; + + x1 += blur; + y1 += blur; + + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r); + + int short_h = h - (2 * r) + 1; + + __BE_RESET(); + + // HACK: As we are drawing circles exploting 8-axis symmetry, + // there are 4 pixels on each circle which are drawn twice. + // this is ok on filled circles, but when blending on surfaces, + // we cannot let it blend twice. awful. + bool *hb = new bool[r]; + int i = 0; + while (i < r) + hb[i++] = false; + + while (x++ < y) { + __BE_ALGORITHM(); + + if (!hb[x]) { + blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); + blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha); + hb[x] = true; + } + + if (!hb[y]) { + blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha); + blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha); + hb[y] = true; + } + } + + delete[] hb; + + while (short_h--) { + blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha); + ptr_fill += pitch; + } } template @@ -577,6 +644,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + // FIXME: maybe not needed at all? __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b7b19a77e7..028b0ba74a 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -53,7 +53,7 @@ void vector_renderer_test(OSystem *_system); class VectorRenderer { public: - VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1) {} + VectorRenderer() : _shadowOffset(0), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} virtual ~VectorRenderer() {} enum FillMode { @@ -63,10 +63,10 @@ public: kGradientFill = 3 }; - enum ColorMode { +/* enum ColorMode { kForegroundColor, kBackgroundColor - }; + }; */ /** * Draws a line by considering the special cases for optimization. @@ -175,7 +175,7 @@ public: * * @param mode Color mode (bg or fg color) used to fill. */ - virtual void fillSurface(ColorMode mode = kForegroundColor) = 0; + virtual void fillSurface(FillMode mode = kForegroundFill) = 0; /** * Clears the active surface. @@ -202,7 +202,7 @@ public: * @param width Witdh of the stroke in pixels. */ virtual void setStrokeWidth(int width) { - if (width > 0) _strokeWidth = width; + _strokeWidth = width; } /** @@ -214,10 +214,9 @@ public: * @param y_offset Vertical offset for the shadows. * @see shadowDisable() */ - virtual void shadowEnable(int x_offset, int y_offset) { - _shadows = true; - _shadowXOffset = x_offset; - _shadowYOffset = y_offset; + virtual void shadowEnable(int offset) { + if (offset > 0) + _shadowOffset = offset; } /** @@ -226,7 +225,12 @@ public: * @see shadowEnable() */ virtual void shadowDisable() { - _shadows = false; + _shadowOffset = 0; + } + + virtual void setGradientFactor(int factor) { + if (factor > 0) + _gradientFactor = factor; } protected: @@ -234,11 +238,11 @@ protected: FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ - bool _shadows; /** Defines if shadows are automatically added to drawn shapes */ - int _shadowXOffset; /** Horizontal offset for drawn shadows */ - int _shadowYOffset; /** Vertical offset for drawn shadows */ - + int _shadowOffset; /** offset for drawn shadows */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ + + int _gradientFactor; + int _gradientBytes[3]; }; @@ -304,22 +308,32 @@ public: _gradientEnd = RGBToColor(r2, g2, b2); _gradientStart = RGBToColor(r1, g1, b1); - _gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); - _gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); - _gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); + Base::_gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); + Base::_gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); + Base::_gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); } /** * @see VectorRenderer::fillSurface() */ - void fillSurface(ColorMode mode = kForegroundColor) { + void fillSurface(FillMode mode = kForegroundFill) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); - int s = _activeSurface->w * _activeSurface->h; - if (mode == kBackgroundColor) - Common::set_to(ptr, ptr + s, _bgColor); - else if (mode == kForegroundColor) - Common::set_to(ptr, ptr + s, _fgColor); + int w = _activeSurface->w; + int h = _activeSurface->h ; + int pitch = surfacePitch(); + + if (mode == kBackgroundFill) + Common::set_to(ptr, ptr + w*h, _bgColor); + else if (mode == kForegroundFill) + Common::set_to(ptr, ptr + w*h, _fgColor); + else if (mode == kGradientFill) { + int i = h; + while (i--) { + Common::set_to(ptr, ptr + w, calcGradient(h - i, h)); + ptr += pitch; + } + } } protected: @@ -341,21 +355,19 @@ protected: * Blends a single pixel on the surface with the given coordinates, color * and Alpha intensity. * - * Note: Pixel blending is currently disabled on the Specialized Renderer - * because of performance issues. - * * @param x Horizontal coordinate of the pixel. * @param y Vertical coordinate of the pixel. * @param color Color of the pixel * @param alpha Alpha intensity of the pixel (0-255) */ virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { - putPixel(x, y, color); + if (alpha == 255) + putPixel(x, y, color); + else if (alpha > 0) + blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } - virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - *ptr = (PixelType)color; - } + virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); /* * "Bresenham's Line Algorithm", as described in Wikipedia. @@ -368,27 +380,31 @@ protected: virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); - virtual void drawSquareShadow(int x, int y, int w, int h); - virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h); + virtual void drawSquareShadow(int x, int y, int w, int h, int blur); + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); - inline PixelType calcGradient(int pos, int max, int factor = 1) { + inline PixelType calcGradient(uint32 pos, uint32 max) { PixelType output = 0; - pos = (0x1000 * MIN(pos * factor, max)) / max; + pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; - output |= (_gradientStart + (_gradientBytes[0] * pos >> 12)) & PixelFormat::kRedMask; - output |= (_gradientStart + (_gradientBytes[1] * pos >> 12)) & PixelFormat::kGreenMask; - output |= (_gradientStart + (_gradientBytes[2] * pos >> 12)) & PixelFormat::kBlueMask; + output |= (_gradientStart + ((Base::_gradientBytes[0] * pos) >> 12)) & PixelFormat::kRedMask; + output |= (_gradientStart + ((Base::_gradientBytes[1] * pos) >> 12)) & PixelFormat::kGreenMask; + output |= (_gradientStart + ((Base::_gradientBytes[2] * pos) >> 12)) & PixelFormat::kBlueMask; output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask); return output; } + inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { + while (first != last) + blendPixelPtr(first++, color, alpha); + } + PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ PixelType _gradientStart; PixelType _gradientEnd; - int _gradientBytes[3]; }; /** @@ -418,32 +434,6 @@ protected: */ void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); - /** - * Perform alpha blending on top of a given pixel, not on a given - * coordinate (just so we don't have to recalculate the surface - * pointer while we are blending consecutive pixels). - * - * Everything from blendPixel() applies here. - * - * @see VectorRenderer::blendPixel() - * @param ptr Pointer to the pixel where we must draw - * @param alpha Intensity of the pixel (0-255). - */ - inline virtual void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); - - /** - * @see VectorRenderer::blendPixel() - * - * The AA renderer does support alpha blending. Special cases are - * handled separately. - */ - inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { - if (alpha == 255) - putPixel(x, y, color); - else if (alpha > 0) - blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); - } - /** * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 * Based on the theoretical concept of the algorithm. -- cgit v1.2.3 From 96dd1cbed3fe31d42e3deec35cace115c077c3ee Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 18 May 2008 13:09:37 +0000 Subject: - Massive cleanup - Documentation update - Boundaries check svn-id: r32169 --- graphics/VectorRenderer.cpp | 591 +++++++++++++++++++++++--------------------- graphics/VectorRenderer.h | 139 +++++++++-- 2 files changed, 423 insertions(+), 307 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 221f525820..d626c2aa51 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -25,38 +25,19 @@ #include "common/util.h" #include "graphics/surface.h" -#include "graphics/VectorRenderer.h" #include "graphics/colormasks.h" #include "common/system.h" #include "common/events.h" -inline uint32 fp_sqroot(uint32 x) { - register uint32 root, remHI, remLO, testDIV, count; - - root = 0; - remHI = 0; - remLO = x; - count = 23; - - do { - remHI = (remHI << 2) | (remLO >> 30); - remLO <<= 2; - root <<= 1; - testDIV = (root << 1) + 1; - - if (remHI >= testDIV) { - remHI -= testDIV; - root++; - } - } while (count--); - - return root; -} +#include "graphics/VectorRenderer.h" namespace Graphics { +/******************************************************************** + * DEBUG FUNCTIONS + ********************************************************************/ VectorRenderer *createRenderer() { - return new VectorRendererAA >; + return new VectorRendererSpec >; } @@ -114,10 +95,153 @@ void vector_renderer_test(OSystem *_system) { _system->hideOverlay(); } +/******************************************************************** + * MISCELANEOUS functions + ********************************************************************/ +/** Fixed point SQUARE ROOT **/ +inline uint32 fp_sqroot(uint32 x) { + register uint32 root, remHI, remLO, testDIV, count; + + root = 0; + remHI = 0; + remLO = x; + count = 23; + + do { + remHI = (remHI << 2) | (remLO >> 30); + remLO <<= 2; + root <<= 1; + testDIV = (root << 1) + 1; + + if (remHI >= testDIV) { + remHI -= testDIV; + root++; + } + } while (count--); + + return root; +} + +/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ +#define __BE_ALGORITHM() { \ + if (f >= 0) { \ + y--; \ + ddF_y += 2; \ + f += ddF_y; \ + py -= pitch; \ + } \ + px += pitch; \ + ddF_x += 2; \ + f += ddF_x + 1; \ +} + +#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ + *(ptr1 + (y) - (px)) = color; \ + *(ptr1 + (x) - (py)) = color; \ + *(ptr2 - (x) - (py)) = color; \ + *(ptr2 - (y) - (px)) = color; \ + *(ptr3 - (y) + (px)) = color; \ + *(ptr3 - (x) + (py)) = color; \ + *(ptr4 + (x) + (py)) = color; \ + *(ptr4 + (y) + (px)) = color; \ +} + +#define __BE_RESET() { \ + f = 1 - r; \ + ddF_x = 0; ddF_y = -2 * r; \ + x = 0; y = r; px = 0; py = pitch * r; \ +} + +/** HELPER MACROS for WU's circle drawing algorithm **/ +#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ + blendPixelPtr(ptr1 + (y) - (px), color, a); \ + blendPixelPtr(ptr1 + (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (y) - (px), color, a); \ + blendPixelPtr(ptr3 - (y) + (px), color, a); \ + blendPixelPtr(ptr3 - (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (y) + (px), color, a); \ +} + +#define __WU_ALGORITHM() { \ + oldT = T; \ + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ + py += p; \ + if (T < oldT) { \ + x--; px -= p; \ + } \ + a2 = (T >> 8); \ + a1 = ~a2; \ +} + +/******************************************************************** + * Primitive shapes drawing - Public API calls - VectorRendererSpec + ********************************************************************/ +/** LINES **/ +template +void VectorRendererSpec:: +drawLine(int x1, int y1, int x2, int y2) { + x1 = CLIP(x1, 0, (int)Base::_activeSurface->w); + x2 = CLIP(x2, 0, (int)Base::_activeSurface->w); + y1 = CLIP(y1, 0, (int)Base::_activeSurface->h); + y2 = CLIP(y2, 0, (int)Base::_activeSurface->h); + + // we draw from top to bottom + if (y2 < y1) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + int dx = ABS(x2 - x1); + int dy = ABS(y2 - y1); + + // this is a point, not a line. stoopid. + if (dy == 0 && dx == 0) + return; + + if (Base::_strokeWidth == 0) + return; + + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = Base::surfacePitch(); + + if (dy == 0) { // horizontal lines + // these can be filled really fast with a single memset. + // TODO: Platform specific ASM in set_to, would make this thing fly + Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor); + + } else if (dx == 0) { // vertical lines + // these ones use a static pitch increase. + while (y1++ <= y2) { + *ptr = (PixelType)_fgColor; + ptr += pitch; + } + + } else if (ABS(dx) == ABS(dy)) { // diagonal lines + // these ones also use a fixed pitch increase + pitch += (x2 > x1) ? 1 : -1; + + while (dy--) { + *ptr = (PixelType)_fgColor; + ptr += pitch; + } + + } else { // generic lines, use the standard algorithm... + drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor); + } +} + +/** CIRCLES **/ template void VectorRendererSpec:: drawCircle(int x, int y, int r) { - if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h) + return; + + if (Base::_fillMode != kNoFill && Base::_shadowOffset + && x + r + Base::_shadowOffset < Base::_activeSurface->w + && y + r + Base::_shadowOffset < Base::_activeSurface->h) { drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kForegroundFill); } @@ -146,10 +270,16 @@ drawCircle(int x, int y, int r) { } } +/** SQUARES **/ template void VectorRendererSpec:: drawSquare(int x, int y, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + return; + + if (Base::_fillMode != kNoFill && Base::_shadowOffset + && x + w + Base::_shadowOffset < Base::_activeSurface->w + && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawSquareShadow(x, y, w, h, Base::_shadowOffset); } @@ -176,10 +306,16 @@ drawSquare(int x, int y, int w, int h) { } } +/** ROUNDED SQUARES **/ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadowOffset) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + return; + + if (Base::_fillMode != kNoFill && Base::_shadowOffset + && x + w + Base::_shadowOffset < Base::_activeSurface->w + && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } @@ -212,6 +348,10 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { } } +/******************************************************************** + * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec + ********************************************************************/ +/** SQUARE ALGORITHM **/ template void VectorRendererSpec:: drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { @@ -244,42 +384,7 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { } } -template -void VectorRendererSpec:: -drawSquareShadow(int x, int y, int w, int h, int blur) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); - int pitch = Base::surfacePitch(); - int i, j; - - i = h - blur; - - while (i--) { - j = blur; - while (j--) - blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); - ptr += pitch; - } - - ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); - - while (i++ < blur) { - j = w - blur; - while (j--) - blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); - ptr += pitch; - } - - ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); - - i = 0; - while (i++ < blur) { - j = blur - 1; - while (j--) - blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); - ptr += pitch; - } -} - +/** GENERIC LINE ALGORITHM **/ template void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { @@ -327,160 +432,89 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { *ptr = (PixelType)color; } - +/** ROUNDED SQUARE ALGORITHM **/ template void VectorRendererSpec:: -blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - if (alpha == 255) { - *ptr = color; - return; - } - - register int idst = *ptr; - register int isrc = color; - - *ptr = (PixelType)( - (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + - ((int)(((int)(isrc & PixelFormat::kRedMask) - - (int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) | - (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + - ((int)(((int)(isrc & PixelFormat::kGreenMask) - - (int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) | - (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + - ((int)(((int)(isrc & PixelFormat::kBlueMask) - - (int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) ); -} - - -template -void VectorRendererAA:: -drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { - - PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { + int f, ddF_x, ddF_y; + int x, y, px, py; int pitch = Base::surfacePitch(); - int xdir = (x2 > x1) ? 1 : -1; - uint16 error_tmp, error_acc, gradient; - uint8 alpha; - - *ptr = (PixelType)color; + int sw = 0, sp = 0, hp = h * pitch; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (dx > dy) { - gradient = (uint32)(dy << 16) / (uint32)dx; - error_acc = 0; + int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; - while (--dx) { - error_tmp = error_acc; - error_acc += gradient; + if (fill_m == kNoFill) { + while (sw++ < Base::_strokeWidth) { + Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += pitch; - if (error_acc <= error_tmp) - ptr += pitch; + __BE_RESET(); + r--; + + while (x++ < y) { + __BE_ALGORITHM(); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - ptr += xdir; - alpha = (error_acc >> 8); + if (Base::_strokeWidth > 1) { + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); + } + } + } - blendPixelPtr(ptr, color, ~alpha); - blendPixelPtr(ptr + pitch, color, alpha); + ptr_fill += pitch * real_radius; + while (short_h--) { + Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); + Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += pitch; } } else { - gradient = (uint32)(dx << 16) / (uint32)dy; - error_acc = 0; + __BE_RESET(); - while (--dy) { - error_tmp = error_acc; - error_acc += gradient; - - if (error_acc <= error_tmp) - ptr += xdir; - - ptr += pitch; - alpha = (error_acc >> 8); - - blendPixelPtr(ptr, color, ~alpha); - blendPixelPtr(ptr + xdir, color, alpha); - } - } - - Base::putPixel(x2, y2, color); -} - -template -void VectorRendererSpec:: -drawLine(int x1, int y1, int x2, int y2) { - // we draw from top to bottom - if (y2 < y1) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - int dx = ABS(x2 - x1); - int dy = ABS(y2 - y1); - - // this is a point, not a line. stoopid. - if (dy == 0 && dx == 0) - return; + if (fill_m == kGradientFill) { + while (x++ < y) { + __BE_ALGORITHM(); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); - if (Base::_strokeWidth == 0) - return; + Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + } + } else { + while (x++ < y) { + __BE_ALGORITHM(); - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = Base::surfacePitch(); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); - if (dy == 0) { // horizontal lines - // these can be filled really fast with a single memset. - // TODO: Platform specific ASM in set_to, would make this thing fly - Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor); + Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); - } else if (dx == 0) { // vertical lines - // these ones use a static pitch increase. - while (y1++ <= y2) { - *ptr = (PixelType)_fgColor; - ptr += pitch; + // FIXME: maybe not needed at all? + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } } - } else if (ABS(dx) == ABS(dy)) { // diagonal lines - // these ones also use a fixed pitch increase - pitch += (x2 > x1) ? 1 : -1; - - while (dy--) { - *ptr = (PixelType)_fgColor; - ptr += pitch; + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kGradientFill) + color = calcGradient(real_radius++, long_h); + Common::set_to(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; } - - } else { // generic lines, use the standard algorithm... - drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor); } } -#define __BE_ALGORITHM() { \ - if (f >= 0) { \ - y--; \ - ddF_y += 2; \ - f += ddF_y; \ - py -= pitch; \ - } \ - px += pitch; \ - ddF_x += 2; \ - f += ddF_x + 1; \ -} - -#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ - *(ptr1 + (y) - (px)) = color; \ - *(ptr1 + (x) - (py)) = color; \ - *(ptr2 - (x) - (py)) = color; \ - *(ptr2 - (y) - (px)) = color; \ - *(ptr3 - (y) + (px)) = color; \ - *(ptr3 - (x) + (py)) = color; \ - *(ptr4 + (x) + (py)) = color; \ - *(ptr4 + (y) + (px)) = color; \ -} - -#define __BE_RESET() { \ - f = 1 - r; \ - ddF_x = 0; ddF_y = -2 * r; \ - x = 0; y = r; px = 0; py = pitch * r; \ -} - - +/** CIRCLE ALGORITHM **/ template void VectorRendererSpec:: drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { @@ -523,6 +557,46 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { } } + +/******************************************************************** + * SHADOW drawing algorithms - VectorRendererSpec + ********************************************************************/ +template +void VectorRendererSpec:: +drawSquareShadow(int x, int y, int w, int h, int blur) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); + int pitch = Base::surfacePitch(); + int i, j; + + i = h - blur; + + while (i--) { + j = blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); + + while (i++ < blur) { + j = w - blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); + + i = 0; + while (i++ < blur) { + j = blur - 1; + while (j--) + blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); + ptr += pitch; + } +} + template void VectorRendererSpec:: drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { @@ -578,109 +652,63 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { } } + +/******************************************************************** + * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA + ********************************************************************/ +/** LINES **/ template -void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { - int f, ddF_x, ddF_y; - int x, y, px, py; +void VectorRendererAA:: +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { + + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); int pitch = Base::surfacePitch(); - int sw = 0, sp = 0, hp = h * pitch; - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + int xdir = (x2 > x1) ? 1 : -1; + uint16 error_tmp, error_acc, gradient; + uint8 alpha; - int real_radius = r; - int short_h = h - (2 * r) + 2; - int long_h = h; + *ptr = (PixelType)color; - if (fill_m == kNoFill) { - while (sw++ < Base::_strokeWidth) { - Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); - sp += pitch; + if (dx > dy) { + gradient = (uint32)(dy << 16) / (uint32)dx; + error_acc = 0; - __BE_RESET(); - r--; - - while (x++ < y) { - __BE_ALGORITHM(); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + while (--dx) { + error_tmp = error_acc; + error_acc += gradient; - if (Base::_strokeWidth > 1) { - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); - } - } - } + if (error_acc <= error_tmp) + ptr += pitch; - ptr_fill += pitch * real_radius; - while (short_h--) { - Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); - Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); - ptr_fill += pitch; + ptr += xdir; + alpha = (error_acc >> 8); + + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + pitch, color, alpha); } } else { - __BE_RESET(); - - if (fill_m == kGradientFill) { - while (x++ < y) { - __BE_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); - - Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); - } - } else { - while (x++ < y) { - __BE_ALGORITHM(); + gradient = (uint32)(dx << 16) / (uint32)dy; + error_acc = 0; - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + while (--dy) { + error_tmp = error_acc; + error_acc += gradient; - Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + if (error_acc <= error_tmp) + ptr += xdir; - // FIXME: maybe not needed at all? - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - } - } + ptr += pitch; + alpha = (error_acc >> 8); - ptr_fill += pitch * r; - while (short_h--) { - if (fill_m == kGradientFill) - color = calcGradient(real_radius++, long_h); - Common::set_to(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + xdir, color, alpha); } } -} -#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ - blendPixelPtr(ptr1 + (y) - (px), color, a); \ - blendPixelPtr(ptr1 + (x) - (py), color, a); \ - blendPixelPtr(ptr2 - (x) - (py), color, a); \ - blendPixelPtr(ptr2 - (y) - (px), color, a); \ - blendPixelPtr(ptr3 - (y) + (px), color, a); \ - blendPixelPtr(ptr3 - (x) + (py), color, a); \ - blendPixelPtr(ptr4 + (x) + (py), color, a); \ - blendPixelPtr(ptr4 + (y) + (px), color, a); \ -} - -#define __WU_ALGORITHM() { \ - oldT = T; \ - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ - py += p; \ - if (T < oldT) { \ - x--; px -= p; \ - } \ - a2 = (T >> 8); \ - a1 = ~a2; \ + Base::putPixel(x2, y2, color); } +/** ROUNDED SQUARES **/ template void VectorRendererAA:: drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { @@ -750,6 +778,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto } } +/** CIRCLES **/ template void VectorRendererAA:: drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 028b0ba74a..def6b1e2be 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -51,23 +51,18 @@ void vector_renderer_test(OSystem *_system); * @see VectorRendererAA */ class VectorRenderer { - public: VectorRenderer() : _shadowOffset(0), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} virtual ~VectorRenderer() {} - enum FillMode { + /** Specified the way in which a shape is filled */ + static enum FillMode { kNoFill = 0, kForegroundFill = 1, kBackgroundFill = 2, kGradientFill = 3 }; -/* enum ColorMode { - kForegroundColor, - kBackgroundColor - }; */ - /** * Draws a line by considering the special cases for optimization. * @@ -157,6 +152,17 @@ public: */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; + /** + * Set the active gradient color. All shapes drawn using kGradientFill + * as their fill mode will use this VERTICAL gradient as their fill color. + * + * @param r1 value of the red color byte for the start color + * @param g1 value of the green color byte for the start color + * @param b1 value of the blue color byte for the start color + * @param r2 value of the red color byte for the end color + * @param g2 value of the green color byte for the end color + * @param b2 value of the blue color byte for the end color + */ virtual void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) = 0; /** @@ -170,10 +176,10 @@ public: } /** - * Fills the active surface with the specified fg/bg color. + * Fills the active surface with the specified fg/bg color or the active gradient. * Defaults to using the active Foreground color for filling. * - * @param mode Color mode (bg or fg color) used to fill. + * @param mode Fill mode (bg, fg or gradient) used to fill the surface */ virtual void fillSurface(FillMode mode = kForegroundFill) = 0; @@ -197,7 +203,7 @@ public: /** * Sets the stroke width. All shapes drawn with a stroke will - * have that width. + * have that width. Pass 0 to disable shape stroking. * * @param width Witdh of the stroke in pixels. */ @@ -207,11 +213,11 @@ public: /** * Enables adding shadows to all drawn primitives. - * Shadows are drawn automatically under the shapes, at the - * given x/y offsets. + * Shadows are drawn automatically under the shapes. The given offset + * controls their intensity and size (the higher the offset, the + * bigger the shadows). * - * @param x_offset Horizontal offset for the shadows. - * @param y_offset Vertical offset for the shadows. + * @param offset Shadow offset. * @see shadowDisable() */ virtual void shadowEnable(int offset) { @@ -228,6 +234,12 @@ public: _shadowOffset = 0; } + /** + * Sets the multiplication factor of the active gradient. + * + * @see _gradientFactor + * @param factor Multiplication factor. + */ virtual void setGradientFactor(int factor) { if (factor > 0) _gradientFactor = factor; @@ -241,8 +253,8 @@ protected: int _shadowOffset; /** offset for drawn shadows */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ - int _gradientFactor; - int _gradientBytes[3]; + int _gradientFactor; /** Multiplication factor of the active gradient */ + int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */ }; @@ -304,6 +316,9 @@ public: this->_bgColor = RGBToColor(r, g, b); } + /** + * @see VectorRenderer::setGradientColors() + */ void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { _gradientEnd = RGBToColor(r2, g2, b2); _gradientStart = RGBToColor(r1, g1, b1); @@ -324,9 +339,9 @@ public: int pitch = surfacePitch(); if (mode == kBackgroundFill) - Common::set_to(ptr, ptr + w*h, _bgColor); + Common::set_to(ptr, ptr + w * h, _bgColor); else if (mode == kForegroundFill) - Common::set_to(ptr, ptr + w*h, _fgColor); + Common::set_to(ptr, ptr + w * h, _fgColor); else if (mode == kGradientFill) { int i = h; while (i--) { @@ -367,22 +382,77 @@ protected: blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } - virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); + /** + * Blends a single pixel on the surface in the given pixel pointer, using supplied color + * and Alpha intensity. + * + * This is implemented to prevent blendPixel() to calculate the surface pointer on each call. + * Optimized drawing algorithms should call this function when possible. + * + * @see blendPixel + * @param ptr Pointer to the pixel to blend on top of + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) + */ + virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + if (alpha == 255) { + *ptr = color; + return; + } + + register int idst = *ptr; + register int isrc = color; + + *ptr = (PixelType)( + (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + + ((int)(((int)(isrc & PixelFormat::kRedMask) - + (int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) | + (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + + ((int)(((int)(isrc & PixelFormat::kGreenMask) - + (int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) | + (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + + ((int)(((int)(isrc & PixelFormat::kBlueMask) - + (int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) ); + } - /* - * "Bresenham's Line Algorithm", as described in Wikipedia. - * Based on the current implementation in "graphics/primitives.cpp". + /** + * PRIMITIVE DRAWING ALGORITHMS + * + * Generic algorithms for drawing all kinds of aliased primitive shapes. + * These may be overloaded in inheriting classes to implement platform-specific + * optimizations or improve looks. * - * Generic line drawing algorithm for the aliased renderer. Optimized with no - * floating point operations and direct access to pixel buffer, assumes no special cases. + * @see VectorRendererAA + * @see VectorRendererAA::drawLineAlg + * @see VectorRendererAA::drawCircleAlg */ virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); + + /** + * SHADOW DRAWING ALGORITHMS + * + * Optimized versions of the primitive drawing algorithms with alpha blending + * for shadow drawing. + * There functions may be overloaded in inheriting classes to improve performance + * in the slowest platforms where pixel alpha blending just doesn't cut it. + * + * @param blur Intensity/size of the shadow. + */ virtual void drawSquareShadow(int x, int y, int w, int h, int blur); virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); + /** + * Calculates the color gradient on a given point. + * This function assumes that the gradient start/end colors have been set + * beforehand from the API function call. + * + * @param pos Progress of the gradient. + * @param max Maximum amount of the progress. + * @return Composite color of the gradient at the given "progress" amount. + */ inline PixelType calcGradient(uint32 pos, uint32 max) { PixelType output = 0; pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; @@ -395,6 +465,16 @@ protected: return output; } + /** + * Fills several pixels in a row with a given color and the specifed alpha blending. + * + * @see blendPixelPtr + * @see blendPixel + * @param first Pointer to the first pixel to fill. + * @param last Pointer to the last pixel to fill. + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) + */ inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { while (first != last) blendPixelPtr(first++, color, alpha); @@ -403,8 +483,8 @@ protected: PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ - PixelType _gradientStart; - PixelType _gradientEnd; + PixelType _gradientStart; /** Start color for the fill gradient */ + PixelType _gradientEnd; /** End color for the fill gradient */ }; /** @@ -445,6 +525,13 @@ protected: */ virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); + /** + * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991, + * modified with corner displacement to allow drawing of squares with rounded + * corners. + * + * @see VectorRenderer::drawRoundedAlg() + */ virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); }; -- cgit v1.2.3 From 985aa6a84617d67e2a2970470b71aff2932288f6 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 18 May 2008 18:02:14 +0000 Subject: Fixing compilation, there's no static for enums svn-id: r32174 --- graphics/VectorRenderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index def6b1e2be..3b5741e83b 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -56,7 +56,7 @@ public: virtual ~VectorRenderer() {} /** Specified the way in which a shape is filled */ - static enum FillMode { + enum FillMode { kNoFill = 0, kForegroundFill = 1, kBackgroundFill = 2, -- cgit v1.2.3 From 40734a8d6c90d02655f6c5b32471eef5c1e44af9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 19 May 2008 15:01:10 +0000 Subject: Made test render function a bit more responsive for backend events. svn-id: r32180 --- graphics/VectorRenderer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index d626c2aa51..9a10428b64 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -60,7 +60,8 @@ void vector_renderer_test(OSystem *_system) { _system->showOverlay(); - while (true) { // draw!! + bool running = true; + while (running) { // draw!! vr->setFgColor(255, 0, 206); vr->setGradientFactor(1); vr->setGradientColors(214, 113, 8, 240, 200, 25); @@ -87,8 +88,9 @@ void vector_renderer_test(OSystem *_system) { Common::Event event; _system->delayMillis(100); - if (eventMan->pollEvent(event) && event.type == Common::EVENT_QUIT) { - break; + while (eventMan->pollEvent(event)) { + if (event.type == Common::EVENT_QUIT) + running = false; } } -- cgit v1.2.3 From 0ea6707dc4ab5858bd048afa75ef6e3fd48f8628 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 21 May 2008 11:21:19 +0000 Subject: - Loop unrolling for color fills. svn-id: r32206 --- graphics/VectorRenderer.cpp | 76 ++++++++++++++++++++++----------------------- graphics/VectorRenderer.h | 47 ++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 44 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 9a10428b64..9dc2fa6ce6 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -211,7 +211,7 @@ drawLine(int x1, int y1, int x2, int y2) { if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. // TODO: Platform specific ASM in set_to, would make this thing fly - Common::set_to(ptr, ptr + dx + 1, (PixelType)_fgColor); + colorFill(ptr, ptr + dx + 1, (PixelType)_fgColor); } else if (dx == 0) { // vertical lines // these ones use a static pitch increase. @@ -366,21 +366,21 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { if (fill_m == kGradientFill) color = calcGradient(max_h - h, max_h); - Common::set_to(ptr, ptr + w, color); + colorFill(ptr, ptr + w, color); ptr += pitch; } } else { int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1); while (sw--) { - Common::set_to(ptr + sp, ptr + w + sp, color); - Common::set_to(ptr + hp - sp, ptr + w + hp - sp, color); + colorFill(ptr + sp, ptr + w + sp, color); + colorFill(ptr + hp - sp, ptr + w + hp - sp, color); sp += pitch; } while (h--) { - Common::set_to(ptr, ptr + Base::_strokeWidth, color); - Common::set_to(ptr + w - Base::_strokeWidth, ptr + w, color); + colorFill(ptr, ptr + Base::_strokeWidth, color); + colorFill(ptr + w - Base::_strokeWidth, ptr + w, color); ptr += pitch; } } @@ -455,8 +455,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { - Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); sp += pitch; __BE_RESET(); @@ -475,8 +475,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM ptr_fill += pitch * real_radius; while (short_h--) { - Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); - Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += pitch; } } else { @@ -485,21 +485,21 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM if (fill_m == kGradientFill) { while (x++ < y) { __BE_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); + colorFill(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); + colorFill(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + colorFill(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); + colorFill(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); } } else { while (x++ < y) { __BE_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + colorFill(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + colorFill(ptr_bl - x + py, ptr_br + x + py, color); + colorFill(ptr_bl - y + px, ptr_br + y + px, color); // FIXME: maybe not needed at all? __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); @@ -510,7 +510,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM while (short_h--) { if (fill_m == kGradientFill) color = calcGradient(real_radius++, long_h); - Common::set_to(ptr_fill, ptr_fill + w + 1, color); + colorFill(ptr_fill, ptr_fill + w + 1, color); ptr_fill += pitch; } } @@ -546,15 +546,15 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { } } } else { - Common::set_to(ptr - r, ptr + r, color); + colorFill(ptr - r, ptr + r, color); __BE_RESET(); while (x++ < y) { __BE_ALGORITHM(); - Common::set_to(ptr - x + py, ptr + x + py, color); - Common::set_to(ptr - x - py, ptr + x - py, color); - Common::set_to(ptr - y + px, ptr + y + px, color); - Common::set_to(ptr - y - px, ptr + y - px, color); + colorFill(ptr - x + py, ptr + x + py, color); + colorFill(ptr - x - py, ptr + x - py, color); + colorFill(ptr - y + px, ptr + y + px, color); + colorFill(ptr - y - px, ptr + y - px, color); } } } @@ -732,8 +732,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto if (fill_m == VectorRenderer::kNoFill) { while (sw++ < Base::_strokeWidth) { - Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); sp += p; x = r - (sw - 1); y = 0; T = 0; @@ -752,8 +752,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto ptr_fill += p * r; while (short_h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + Base::_strokeWidth, color); - Common::set_to(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += p; } } else { @@ -763,18 +763,18 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto while (x > y++) { __WU_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + colorFill(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + colorFill(ptr_bl - x + py, ptr_br + x + py, color); + colorFill(ptr_bl - y + px, ptr_br + y + px, color); __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); } ptr_fill += p * r; while (short_h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + w + 1, color); + colorFill(ptr_fill, ptr_fill + w + 1, color); ptr_fill += p; } } @@ -814,17 +814,17 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f } } } else { - Common::set_to(ptr - r, ptr + r + 1, color); + colorFill(ptr - r, ptr + r + 1, color); x = r; y = 0; T = 0; px = p * x; py = 0; while (x > y++) { __WU_ALGORITHM(); - Common::set_to(ptr - x + py, ptr + x + py, color); - Common::set_to(ptr - x - py, ptr + x - py, color); - Common::set_to(ptr - y + px, ptr + y + px, color); - Common::set_to(ptr - y - px, ptr + y - px, color); + colorFill(ptr - x + py, ptr + x + py, color); + colorFill(ptr - x - py, ptr + x - py, color); + colorFill(ptr - y + px, ptr + y + px, color); + colorFill(ptr - y - px, ptr + y - px, color); __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3b5741e83b..4609d51739 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -339,13 +339,13 @@ public: int pitch = surfacePitch(); if (mode == kBackgroundFill) - Common::set_to(ptr, ptr + w * h, _bgColor); + colorFill(ptr, ptr + w * h, _bgColor); else if (mode == kForegroundFill) - Common::set_to(ptr, ptr + w * h, _fgColor); + colorFill(ptr, ptr + w * h, _fgColor); else if (mode == kGradientFill) { int i = h; while (i--) { - Common::set_to(ptr, ptr + w, calcGradient(h - i, h)); + colorFill(ptr, ptr + w, calcGradient(h - i, h)); ptr += pitch; } } @@ -453,7 +453,7 @@ protected: * @param max Maximum amount of the progress. * @return Composite color of the gradient at the given "progress" amount. */ - inline PixelType calcGradient(uint32 pos, uint32 max) { + virtual inline PixelType calcGradient(uint32 pos, uint32 max) { PixelType output = 0; pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; @@ -475,10 +475,45 @@ protected: * @param color Color of the pixel * @param alpha Alpha intensity of the pixel (0-255) */ - inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { + virtual inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { while (first != last) blendPixelPtr(first++, color, alpha); - } + } + + /** + * Fills several pixels in a row with a given color. + * + * This is a replacement function for Common::set_to, using an unrolled + * loop to maximize performance on most architectures. + * This function may (and should) be overloaded in any child renderers + * for portable platforms with platform-specific assembly code. + * + * This fill operation is extensively used throughout the renderer, so this + * counts as one of the main bottlenecks. Please replace it with assembly + * when possible! + * + * @param first Pointer to the first pixel to fill. + * @param last Pointer to the last pixel to fill. + * @param color Color of the pixel + */ + virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color) { + register PixelType *ptr = first; + register int count = (last - first); + { + register int n = (count + 7) / 8; + switch (count % 8) { + case 0: do { *ptr++ = color; + case 7: *ptr++ = color; + case 6: *ptr++ = color; + case 5: *ptr++ = color; + case 4: *ptr++ = color; + case 3: *ptr++ = color; + case 2: *ptr++ = color; + case 1: *ptr++ = color; + } while (--n > 0); + } + } + } PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ -- cgit v1.2.3 From 0707968a376e90f4719fa7f2f935e252e936a9f8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 21 May 2008 17:44:38 +0000 Subject: Code formatting guidelines svn-id: r32207 --- graphics/VectorRenderer.cpp | 2 -- graphics/VectorRenderer.h | 25 ++++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 9dc2fa6ce6..e2b187a58c 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -210,7 +210,6 @@ drawLine(int x1, int y1, int x2, int y2) { if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. - // TODO: Platform specific ASM in set_to, would make this thing fly colorFill(ptr, ptr + dx + 1, (PixelType)_fgColor); } else if (dx == 0) { // vertical lines @@ -605,7 +604,6 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); - int sw = 0, sp = 0, hp = h * pitch; int alpha = 102; x1 += blur; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 4609d51739..a4ef4b81b1 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -499,19 +499,18 @@ protected: virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color) { register PixelType *ptr = first; register int count = (last - first); - { - register int n = (count + 7) / 8; - switch (count % 8) { - case 0: do { *ptr++ = color; - case 7: *ptr++ = color; - case 6: *ptr++ = color; - case 5: *ptr++ = color; - case 4: *ptr++ = color; - case 3: *ptr++ = color; - case 2: *ptr++ = color; - case 1: *ptr++ = color; - } while (--n > 0); - } + register int n = (count + 7) >> 3; + switch (count % 8) { + case 0: do { + *ptr++ = color; + case 7: *ptr++ = color; + case 6: *ptr++ = color; + case 5: *ptr++ = color; + case 4: *ptr++ = color; + case 3: *ptr++ = color; + case 2: *ptr++ = color; + case 1: *ptr++ = color; + } while (--n > 0); } } -- cgit v1.2.3 From a4df37e325c3e91bb07c017fc2bca126fe97070d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 25 May 2008 11:20:28 +0000 Subject: Interface Manager class svn-id: r32267 --- dists/msvc9/scummvm.vcproj | 15 ++++++------ graphics/VectorRenderer.h | 39 ++++++++++++++++++++++++++++++ gui/InterfaceManager.cpp | 39 ++++++++++++++++++++++++++++++ gui/InterfaceManager.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 gui/InterfaceManager.cpp create mode 100644 gui/InterfaceManager.h diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 4877c045e7..5667763fce 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1080,6 +1080,14 @@ RelativePath="..\..\gui\eval.h" > + + + + @@ -1303,13 +1311,6 @@ - - - x, step->y, step->r); + } + + void drawStep_SQUARE(DrawStep *step) { + drawSquare(step->x, step->y, step->w, step->h); + } + + void drawStep_LINE(DrawStep *step) { + drawLine(step->x, step->y, step->x + step->w, step->y + step->h); + } + + void drawStep_ROUNDEDSQ(DrawStep *step) { + drawRoundedSquare(step->x, step->y, step->r, step->w, step->h); + } + + + virtual void drawStep(DrawStep *step) { + + } + protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp new file mode 100644 index 0000000000..693b36e367 --- /dev/null +++ b/gui/InterfaceManager.cpp @@ -0,0 +1,39 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "graphics/surface.h" +#include "graphics/colormasks.h" +#include "common/system.h" +#include "common/events.h" + +#include "gui/InterfaceManager.h" +#include "graphics/VectorRenderer.h" + +namespace GUI { + + + +} // end of namespace GUI. \ No newline at end of file diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h new file mode 100644 index 0000000000..b65ae36477 --- /dev/null +++ b/gui/InterfaceManager.h @@ -0,0 +1,59 @@ +/* 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 INTERFACE_MANAGER_H +#define INTERFACE_MANAGER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" +#include "graphics/VectorRenderer.h" + +namespace GUI { + +class InterfaceManager { + +public: + InterfaceManager() : _vectorRenderer(NULL) { + _vectorRenderer = createRenderer(); + } + + ~InterfaceManager() { + delete _vectorRenderer; + } + +protected: + Graphics::VectorRenderer *createRenderer() { + // TODO: Find out what pixel format we are using, + // create the renderer accordingly + return new VectorRendererSpec >; + } + + Graphics::VectorRenderer *_vectorRenderer; +}; + +} // end of namespace GUI. + +#endif \ No newline at end of file -- cgit v1.2.3 From ca51f1f24729e8a3b915529483012bbd583574d2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 25 May 2008 11:53:49 +0000 Subject: Add InterfaceManager to makefile. svn-id: r32268 --- gui/module.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/module.mk b/gui/module.mk index c572dcbeea..be6e405b87 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -10,6 +10,7 @@ MODULE_OBJS := \ editable.o \ EditTextWidget.o \ eval.o \ + InterfaceManager.o \ launcher.o \ ListWidget.o \ massadd.o \ -- cgit v1.2.3 From 862a3d575a98a508bc7dc58895fe8825e67d9a70 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 25 May 2008 17:06:10 +0000 Subject: Compilation fixes. Sorry about the mess. svn-id: r32272 --- graphics/VectorRenderer.cpp | 96 ++++++++++++++++++++++----------------------- graphics/VectorRenderer.h | 38 +++++++++--------- gui/InterfaceManager.cpp | 2 +- gui/InterfaceManager.h | 5 ++- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index e2b187a58c..9bd2ca7e01 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -65,13 +65,13 @@ void vector_renderer_test(OSystem *_system) { vr->setFgColor(255, 0, 206); vr->setGradientFactor(1); vr->setGradientColors(214, 113, 8, 240, 200, 25); - vr->fillSurface(VectorRenderer::kGradientFill); + vr->fillSurface(kFillMode_Gradient); vr->setBgColor(25, 25, 175); vr->shadowEnable(3); vr->setFgColor(240, 204, 120); vr->setStrokeWidth(1); - vr->setFillMode(VectorRenderer::kGradientFill); + vr->setFillMode(kFillMode_Gradient); vr->setGradientFactor(3); vr->setGradientColors(255, 231, 140, 255, 243, 206); @@ -240,33 +240,33 @@ drawCircle(int x, int y, int r) { if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h) return; - if (Base::_fillMode != kNoFill && Base::_shadowOffset + if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset && x + r + Base::_shadowOffset < Base::_activeSurface->w && y + r + Base::_shadowOffset < Base::_activeSurface->h) { - drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kForegroundFill); + drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillMode_Foreground); } switch(Base::_fillMode) { - case kNoFill: + case kFillMode_Disabled: if (Base::_strokeWidth) - drawCircleAlg(x, y, r, _fgColor, kNoFill); + drawCircleAlg(x, y, r, _fgColor, kFillMode_Disabled); break; - case kForegroundFill: - drawCircleAlg(x, y, r, _fgColor, kForegroundFill); + case kFillMode_Foreground: + drawCircleAlg(x, y, r, _fgColor, kFillMode_Foreground); break; - case kBackgroundFill: + case kFillMode_Background: if (Base::_strokeWidth > 1) { - drawCircleAlg(x, y, r, _fgColor, kForegroundFill); - drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill); + drawCircleAlg(x, y, r, _fgColor, kFillMode_Foreground); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillMode_Background); } else { - drawCircleAlg(x, y, r, _bgColor, kBackgroundFill); - drawCircleAlg(x, y, r, _fgColor, kNoFill); + drawCircleAlg(x, y, r, _bgColor, kFillMode_Background); + drawCircleAlg(x, y, r, _fgColor, kFillMode_Disabled); } break; - case kGradientFill: + case kFillMode_Gradient: break; } } @@ -278,31 +278,31 @@ drawSquare(int x, int y, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; - if (Base::_fillMode != kNoFill && Base::_shadowOffset + if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawSquareShadow(x, y, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { - case kNoFill: + case kFillMode_Disabled: if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kNoFill); + drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); break; - case kForegroundFill: - drawSquareAlg(x, y, w, h, _fgColor, kForegroundFill); + case kFillMode_Foreground: + drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Foreground); break; - case kBackgroundFill: - drawSquareAlg(x, y, w, h, _bgColor, kBackgroundFill); - drawSquareAlg(x, y, w, h, _fgColor, kNoFill); + case kFillMode_Background: + drawSquareAlg(x, y, w, h, _bgColor, kFillMode_Background); + drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); break; - case kGradientFill: - VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kGradientFill); + case kFillMode_Gradient: + VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillMode_Gradient); if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kNoFill); + drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); break; } } @@ -314,36 +314,36 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; - if (Base::_fillMode != kNoFill && Base::_shadowOffset + if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { - case kNoFill: + case kFillMode_Disabled: if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); break; - case kForegroundFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); + case kFillMode_Foreground: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Foreground); break; - case kBackgroundFill: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kBackgroundFill); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + case kFillMode_Background: + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillMode_Background); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); break; - case kGradientFill: + case kFillMode_Gradient: if (Base::_strokeWidth > 1) { - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Foreground); VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, - r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kGradientFill); + r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillMode_Gradient); } else { - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kGradientFill); + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillMode_Gradient); if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); } break; } @@ -360,9 +360,9 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { int pitch = Base::surfacePitch(); int max_h = h; - if (fill_m != kNoFill) { + if (fill_m != kFillMode_Disabled) { while (h--) { - if (fill_m == kGradientFill) + if (fill_m == kFillMode_Gradient) color = calcGradient(max_h - h, max_h); colorFill(ptr, ptr + w, color); @@ -452,7 +452,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM int short_h = h - (2 * r) + 2; int long_h = h; - if (fill_m == kNoFill) { + if (fill_m == kFillMode_Disabled) { while (sw++ < Base::_strokeWidth) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -481,7 +481,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM } else { __BE_RESET(); - if (fill_m == kGradientFill) { + if (fill_m == kFillMode_Gradient) { while (x++ < y) { __BE_ALGORITHM(); colorFill(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); @@ -507,7 +507,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM ptr_fill += pitch * r; while (short_h--) { - if (fill_m == kGradientFill) + if (fill_m == kFillMode_Gradient) color = calcGradient(real_radius++, long_h); colorFill(ptr_fill, ptr_fill + w + 1, color); ptr_fill += pitch; @@ -524,7 +524,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill_m == kNoFill) { + if (fill_m == kFillMode_Disabled) { while (sw++ < Base::_strokeWidth) { __BE_RESET(); r--; @@ -711,7 +711,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { /** ROUNDED SQUARES **/ template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0, hp = h * p; @@ -728,7 +728,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto int short_h = h - 2 * r; - if (fill_m == VectorRenderer::kNoFill) { + if (fill_m == kFillMode_Disabled) { while (sw++ < Base::_strokeWidth) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -781,7 +781,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto /** CIRCLES **/ template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { +drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int x, y, sw = 0; int p = Base::surfacePitch(), px, py; @@ -791,7 +791,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill_m == VectorRenderer::kNoFill) { + if (fill_m == kFillMode_Disabled) { while (sw++ < Base::_strokeWidth) { x = r - (sw - 1); y = 0; T = 0; px = p * x; py = 0; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 23e5b18593..3cd3a27ca4 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -35,6 +35,14 @@ namespace Graphics { void vector_renderer_test(OSystem *_system); +/** Specified the way in which a shape is filled */ +enum FillMode { + kFillMode_Disabled = 0, + kFillMode_Foreground = 1, + kFillMode_Background = 2, + kFillMode_Gradient = 3 +}; + struct DrawStep { bool set_fg, set_bg, set_grad; @@ -47,7 +55,7 @@ struct DrawStep { uint16 x, y, w, h, r; uint8 shadows, stroke, factor; - Graphics::VectorRenderer::FillMode fill_mode; + FillMode fill_mode; void (*drawing_call)(DrawStep *step); }; @@ -70,17 +78,9 @@ struct DrawStep { */ class VectorRenderer { public: - VectorRenderer() : _shadowOffset(0), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} + VectorRenderer() : _shadowOffset(0), _fillMode(kFillMode_Disabled), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} virtual ~VectorRenderer() {} - /** Specified the way in which a shape is filled */ - enum FillMode { - kNoFill = 0, - kForegroundFill = 1, - kBackgroundFill = 2, - kGradientFill = 3 - }; - /** * Draws a line by considering the special cases for optimization. * @@ -171,7 +171,7 @@ public: virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; /** - * Set the active gradient color. All shapes drawn using kGradientFill + * Set the active gradient color. All shapes drawn using kFillMode_Gradient * as their fill mode will use this VERTICAL gradient as their fill color. * * @param r1 value of the red color byte for the start color @@ -199,7 +199,7 @@ public: * * @param mode Fill mode (bg, fg or gradient) used to fill the surface */ - virtual void fillSurface(FillMode mode = kForegroundFill) = 0; + virtual void fillSurface(FillMode mode = kFillMode_Foreground) = 0; /** * Clears the active surface. @@ -215,7 +215,7 @@ public: * @see VectorRenderer::FillMode * @param mode Specified fill mode. */ - virtual void setFillMode(VectorRenderer::FillMode mode) { + virtual void setFillMode(FillMode mode) { _fillMode = mode; } @@ -370,18 +370,18 @@ public: /** * @see VectorRenderer::fillSurface() */ - void fillSurface(FillMode mode = kForegroundFill) { + void fillSurface(FillMode mode = kFillMode_Foreground) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); int w = _activeSurface->w; int h = _activeSurface->h ; int pitch = surfacePitch(); - if (mode == kBackgroundFill) + if (mode == kFillMode_Background) colorFill(ptr, ptr + w * h, _bgColor); - else if (mode == kForegroundFill) + else if (mode == kFillMode_Foreground) colorFill(ptr, ptr + w * h, _fgColor); - else if (mode == kGradientFill) { + else if (mode == kFillMode_Gradient) { int i = h; while (i--) { colorFill(ptr, ptr + w, calcGradient(h - i, h)); @@ -596,7 +596,7 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); /** * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991, @@ -605,7 +605,7 @@ protected: * * @see VectorRenderer::drawRoundedAlg() */ - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); }; } // end of namespace Graphics diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 693b36e367..f886423e4c 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -36,4 +36,4 @@ namespace GUI { -} // end of namespace GUI. \ No newline at end of file +} // end of namespace GUI. diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index b65ae36477..92f5c570a4 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -29,6 +29,7 @@ #include "common/scummsys.h" #include "graphics/surface.h" #include "common/system.h" + #include "graphics/VectorRenderer.h" namespace GUI { @@ -48,7 +49,7 @@ protected: Graphics::VectorRenderer *createRenderer() { // TODO: Find out what pixel format we are using, // create the renderer accordingly - return new VectorRendererSpec >; + return new Graphics::VectorRendererSpec >; } Graphics::VectorRenderer *_vectorRenderer; @@ -56,4 +57,4 @@ protected: } // end of namespace GUI. -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 4e1aa5328a115150696dfb323a6d6481c2c82c68 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 26 May 2008 18:17:03 +0000 Subject: Draw steps. svn-id: r32296 --- graphics/VectorRenderer.cpp | 103 +++++++++++++++++++++++++++++++++++--------- graphics/VectorRenderer.h | 59 +++++++++++++++---------- 2 files changed, 119 insertions(+), 43 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 9bd2ca7e01..c34b73d4bd 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -60,28 +60,53 @@ void vector_renderer_test(OSystem *_system) { _system->showOverlay(); + DrawStep *steps = new 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 = kFillMode_Gradient; + steps[0].drawing_call = &VectorRenderer::drawCallback_FILLSURFACE; + steps[0].flags = kDrawStep_SetGradient | kDrawStep_SetFillMode; + + 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].x = 500; + steps[1].y = 95; + steps[1].r = 8; + steps[1].w = 120; + steps[1].h = 30; + steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[1].flags = kDrawStep_SetGradient; + + steps[2].x = 500; + steps[2].y = 135; + steps[2].r = 8; + steps[2].w = 120; + steps[2].h = 30; + steps[2].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[2].flags = kDrawStep_CallbackOnly; + + steps[3].x = 500; + steps[3].y = 175; + steps[3].r = 8; + steps[3].w = 120; + steps[3].h = 30; + steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[3].flags = kDrawStep_CallbackOnly; + bool running = true; while (running) { // draw!! - vr->setFgColor(255, 0, 206); - vr->setGradientFactor(1); - vr->setGradientColors(214, 113, 8, 240, 200, 25); - vr->fillSurface(kFillMode_Gradient); - - vr->setBgColor(25, 25, 175); - vr->shadowEnable(3); - vr->setFgColor(240, 204, 120); - vr->setStrokeWidth(1); - vr->setFillMode(kFillMode_Gradient); - - vr->setGradientFactor(3); - vr->setGradientColors(255, 231, 140, 255, 243, 206); - vr->drawRoundedSquare(25, 95, 18, 465, 290); - - vr->setGradientFactor(1); - vr->setGradientColors(206, 121, 99, 173, 40, 8); - vr->drawRoundedSquare(500, 95, 8, 120, 30); - vr->drawRoundedSquare(500, 135, 8, 120, 30); - vr->drawRoundedSquare(500, 175, 8, 120, 30); + + for (int i = 0; i < 4; ++i) + vr->drawStep(&steps[i]); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -97,6 +122,44 @@ void vector_renderer_test(OSystem *_system) { _system->hideOverlay(); } +/******************************************************************** + * DRAWSTEP handling functions + ********************************************************************/ +void VectorRenderer::drawStep(DrawStep *step) { + + if (step->flags & kDrawStep_CallbackOnly) { + (this->*(step->drawing_call))(step); + return; + } + + if (step->flags & kDrawStep_SetBG) + setBgColor(step->color2.r, step->color2.g, step->color2.b); + + if (step->flags & kDrawStep_SetFG) + setFgColor(step->color1.r, step->color1.g, step->color1.b); + + if (step->flags & kDrawStep_SetGradient) + setGradientColors(step->color1.r, step->color1.g, step->color1.b, + step->color2.r, step->color2.g, step->color2.b); + + if (step->flags & kDrawStep_SetShadow) + shadowEnable(step->shadow); + + if (step->flags & kDrawStep_SetGradientFactor) + setGradientFactor(step->factor); + + if (step->flags & kDrawStep_SetStroke) + setStrokeWidth(step->stroke); + + if (step->flags & kDrawStep_SetFillMode) + setFillMode(step->fill_mode); + + if (step->flags & kDrawStep_SettingsOnly) + return; + + (this->*(step->drawing_call))(step); +} + /******************************************************************** * MISCELANEOUS functions ********************************************************************/ diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3cd3a27ca4..1b315f46b4 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -34,8 +34,9 @@ namespace Graphics { void vector_renderer_test(OSystem *_system); +class VectorRenderer; -/** Specified the way in which a shape is filled */ +/** Specifies the way in which a shape is filled */ enum FillMode { kFillMode_Disabled = 0, kFillMode_Foreground = 1, @@ -44,22 +45,33 @@ enum FillMode { }; struct DrawStep { - bool set_fg, set_bg, set_grad; + uint32 flags; /** Step flags, see DrawStepFlags */ - uint8 fg_r, fg_g, fg_b; - uint8 bg_r, bg_g, bg_b; + struct { + uint8 r, g, b; + } + color1, /** Foreground color/gradient start */ + color2; /** Background color/gradient end */ - uint8 grad_r1, grad_g1, grad_b1; - uint8 grad_r2, grad_g2, grad_b2; + uint16 x, y, w, h, r; /** Shape size */ + uint8 shadow, stroke, factor; /** Misc options... */ - uint16 x, y, w, h, r; - uint8 shadows, stroke, factor; + FillMode fill_mode; /** active fill mode */ - FillMode fill_mode; - - void (*drawing_call)(DrawStep *step); + void (VectorRenderer::*drawing_call)(DrawStep*); /** Pointer to drawing function */ }; +enum DrawStepFlags { + kDrawStep_CallbackOnly = (1 << 0), + kDrawStep_SettingsOnly = (1 << 1), + kDrawStep_SetBG = (1 << 2), + kDrawStep_SetFG = (1 << 3), + kDrawStep_SetGradient = (1 << 4), + kDrawStep_SetShadow = (1 << 5), + kDrawStep_SetGradientFactor = (1 << 6), + kDrawStep_SetStroke = (1 << 7), + kDrawStep_SetFillMode = (1 << 8) +}; /** * VectorRenderer: The core Vector Renderer Class @@ -199,7 +211,7 @@ public: * * @param mode Fill mode (bg, fg or gradient) used to fill the surface */ - virtual void fillSurface(FillMode mode = kFillMode_Foreground) = 0; + virtual void fillSurface() = 0; /** * Clears the active surface. @@ -263,27 +275,28 @@ public: _gradientFactor = factor; } - void drawStep_CIRCLE(DrawStep *step) { + void drawCallback_CIRCLE(DrawStep *step) { drawCircle(step->x, step->y, step->r); } - void drawStep_SQUARE(DrawStep *step) { + void drawCallback_SQUARE(DrawStep *step) { drawSquare(step->x, step->y, step->w, step->h); } - void drawStep_LINE(DrawStep *step) { + void drawCallback_LINE(DrawStep *step) { drawLine(step->x, step->y, step->x + step->w, step->y + step->h); } - void drawStep_ROUNDEDSQ(DrawStep *step) { + void drawCallback_ROUNDSQ(DrawStep *step) { drawRoundedSquare(step->x, step->y, step->r, step->w, step->h); } - - virtual void drawStep(DrawStep *step) { - + void drawCallback_FILLSURFACE(DrawStep *step) { + fillSurface(); } + virtual void drawStep(DrawStep *step); + protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -370,18 +383,18 @@ public: /** * @see VectorRenderer::fillSurface() */ - void fillSurface(FillMode mode = kFillMode_Foreground) { + void fillSurface() { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); int w = _activeSurface->w; int h = _activeSurface->h ; int pitch = surfacePitch(); - if (mode == kFillMode_Background) + if (Base::_fillMode == kFillMode_Background) colorFill(ptr, ptr + w * h, _bgColor); - else if (mode == kFillMode_Foreground) + else if (Base::_fillMode == kFillMode_Foreground) colorFill(ptr, ptr + w * h, _fgColor); - else if (mode == kFillMode_Gradient) { + else if (Base::_fillMode == kFillMode_Gradient) { int i = h; while (i--) { colorFill(ptr, ptr + w, calcGradient(h - i, h)); -- cgit v1.2.3 From 119b7126b9162eb0adefaff7a2f002f23472824b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 28 May 2008 14:27:22 +0000 Subject: InterfaceManager core implemented. svn-id: r32339 --- base/main.cpp | 13 +++--- graphics/VectorRenderer.cpp | 98 ++++++--------------------------------------- graphics/VectorRenderer.h | 19 +++++++-- gui/InterfaceManager.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++ gui/InterfaceManager.h | 38 ++++++++++++++++-- 5 files changed, 166 insertions(+), 99 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index a666110b83..51b3451837 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -42,12 +42,9 @@ #include "common/system.h" #include "gui/newgui.h" #include "gui/message.h" +#include "gui/InterfaceManager.h" -#define _VECTOR_RENDERER_DBG 1 - -#if defined(_VECTOR_RENDERER_DBG) -#include "graphics/VectorRenderer.h" -#elif defined(_WIN32_WCE) +#if defined(_WIN32_WCE) #include "backends/platform/wince/CELauncherDialog.h" #elif defined(__DC__) #include "backends/platform/dc/DCLauncherDialog.h" @@ -71,9 +68,11 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); -#if defined(_VECTOR_RENDERER_DBG) +#if 1 + + GUI::InterfaceManager iManager(&system, GUI::InterfaceManager::GFX_Standard_16bit); - Graphics::vector_renderer_test( &system ); + iManager.runGUI(); return true; #else diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index c34b73d4bd..dfb555c20b 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -24,102 +24,28 @@ */ #include "common/util.h" -#include "graphics/surface.h" -#include "graphics/colormasks.h" #include "common/system.h" #include "common/events.h" +#include "graphics/surface.h" +#include "graphics/colormasks.h" + +#include "gui/InterfaceManager.h" #include "graphics/VectorRenderer.h" namespace Graphics { -/******************************************************************** - * DEBUG FUNCTIONS - ********************************************************************/ -VectorRenderer *createRenderer() { - return new VectorRendererSpec >; -} +VectorRenderer *createRenderer(int mode) { + switch (mode) { + case GUI::InterfaceManager::GFX_Standard_16bit: + return new VectorRendererSpec >; + case GUI::InterfaceManager::GFX_Antialias_16bit: + return new VectorRendererAA >; -void vector_renderer_test(OSystem *_system) { - Common::EventManager *eventMan = _system->getEventManager(); - - VectorRenderer *vr = createRenderer(); - - Surface _screen; - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - - if (!_screen.pixels) - return; - - _system->clearOverlay(); - _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); - - vr->setSurface(&_screen); - vr->clearSurface(); - - _system->showOverlay(); - - DrawStep *steps = new 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 = kFillMode_Gradient; - steps[0].drawing_call = &VectorRenderer::drawCallback_FILLSURFACE; - steps[0].flags = kDrawStep_SetGradient | kDrawStep_SetFillMode; - - 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].x = 500; - steps[1].y = 95; - steps[1].r = 8; - steps[1].w = 120; - steps[1].h = 30; - steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; - steps[1].flags = kDrawStep_SetGradient; - - steps[2].x = 500; - steps[2].y = 135; - steps[2].r = 8; - steps[2].w = 120; - steps[2].h = 30; - steps[2].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; - steps[2].flags = kDrawStep_CallbackOnly; - - steps[3].x = 500; - steps[3].y = 175; - steps[3].r = 8; - steps[3].w = 120; - steps[3].h = 30; - steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; - steps[3].flags = kDrawStep_CallbackOnly; - - bool running = true; - while (running) { // draw!! - - for (int i = 0; i < 4; ++i) - vr->drawStep(&steps[i]); - - _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); - _system->updateScreen(); - - Common::Event event; - _system->delayMillis(100); - while (eventMan->pollEvent(event)) { - if (event.type == Common::EVENT_QUIT) - running = false; - } + default: + return NULL; } - - _system->hideOverlay(); } /******************************************************************** diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 1b315f46b4..65d0cce417 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -32,10 +32,10 @@ #include "common/system.h" namespace Graphics { - -void vector_renderer_test(OSystem *_system); class VectorRenderer; +VectorRenderer *createRenderer(int mode); + /** Specifies the way in which a shape is filled */ enum FillMode { kFillMode_Disabled = 0, @@ -297,6 +297,8 @@ public: virtual void drawStep(DrawStep *step); + virtual void copyFrame(OSystem *sys) = 0; + protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -403,6 +405,17 @@ public: } } + virtual void copyFrame(OSystem *sys) { +#ifdef OVERLAY_MULTIPLE_DEPTHS + sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->w); +#else + sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(0, 0), + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->w); +#endif + sys->updateScreen(); + } + protected: /** @@ -598,7 +611,7 @@ protected: * * @see VectorRenderer::drawLineAlg() */ - void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); + virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); /** * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index f886423e4c..8469654657 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -34,6 +34,103 @@ namespace GUI { +template +void InterfaceManager::screenInit() { + freeScreen(); + + _screen = new Graphics::Surface; + _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); + _system->clearOverlay(); +} + +void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { + if (mode == _graphicsMode) + return; + + _graphicsMode = mode; + + switch (mode) { + case GFX_Standard_16bit: + _bytesPerPixel = sizeof(uint16); + screenInit(); + break; + + case GFX_Antialias_16bit: + _bytesPerPixel = sizeof(uint16); + screenInit(); + break; + } + + _vectorRenderer = Graphics::createRenderer(mode); + _vectorRenderer->setSurface(_screen); +} + +int InterfaceManager::runGUI() { + Common::EventManager *eventMan = _system->getEventManager(); + _system->showOverlay(); + + 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 = Graphics::kFillMode_Gradient; + steps[0].drawing_call = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; + steps[0].flags = Graphics::kDrawStep_SetGradient | Graphics::kDrawStep_SetFillMode; + + 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].x = 500; + steps[1].y = 95; + steps[1].r = 8; + steps[1].w = 120; + steps[1].h = 30; + steps[1].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; + steps[1].flags = Graphics::kDrawStep_SetGradient; + + steps[2].x = 500; + steps[2].y = 135; + steps[2].r = 8; + steps[2].w = 120; + steps[2].h = 30; + steps[2].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; + steps[2].flags = Graphics::kDrawStep_CallbackOnly; + + steps[3].x = 500; + steps[3].y = 175; + steps[3].r = 8; + steps[3].w = 120; + steps[3].h = 30; + steps[3].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; + steps[3].flags = Graphics::kDrawStep_CallbackOnly; + + bool running = true; + while (running) { // draw!! + + for (int i = 0; i < 4; ++i) + _vectorRenderer->drawStep(&steps[i]); + + _vectorRenderer->copyFrame(_system); + + Common::Event event; + _system->delayMillis(100); + while (eventMan->pollEvent(event)) { + if (event.type == Common::EVENT_QUIT) + running = false; + } + } + + _system->hideOverlay(); + return 1; +} + } // end of namespace GUI. diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 92f5c570a4..5a5eccff41 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -37,14 +37,26 @@ namespace GUI { class InterfaceManager { public: - InterfaceManager() : _vectorRenderer(NULL) { - _vectorRenderer = createRenderer(); + enum Graphics_Mode { + GFX_Disabled = 0, + GFX_Standard_16bit, + GFX_Antialias_16bit + }; + + InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(NULL), + _system(system), _graphicsMode(GFX_Disabled), _screen(NULL), _bytesPerPixel(0) { + + setGraphicsMode(mode); } ~InterfaceManager() { - delete _vectorRenderer; + freeRenderer(); + freeScreen(); } + void setGraphicsMode(Graphics_Mode mode); + int runGUI(); + protected: Graphics::VectorRenderer *createRenderer() { // TODO: Find out what pixel format we are using, @@ -52,7 +64,27 @@ protected: return new Graphics::VectorRendererSpec >; } + template + void screenInit(); + + void freeRenderer() { + if (_vectorRenderer != NULL) + delete _vectorRenderer; + } + + void freeScreen() { + if (_screen != NULL) { + _screen->free(); + delete _screen; + } + } + + OSystem *_system; Graphics::VectorRenderer *_vectorRenderer; + Graphics::Surface *_screen; + + int _bytesPerPixel; + Graphics_Mode _graphicsMode; }; } // end of namespace GUI. -- cgit v1.2.3 From 426c36992dd23647b7316de9ba2aeb12a4d8d94c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 28 May 2008 14:30:51 +0000 Subject: Bugfixes: Discarded function, switch fix. svn-id: r32340 --- gui/InterfaceManager.cpp | 3 +++ gui/InterfaceManager.h | 9 +-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 8469654657..6aa5bac733 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -59,6 +59,9 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { _bytesPerPixel = sizeof(uint16); screenInit(); break; + + default: + return; } _vectorRenderer = Graphics::createRenderer(mode); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 5a5eccff41..4e98fbc692 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -58,14 +58,7 @@ public: int runGUI(); protected: - Graphics::VectorRenderer *createRenderer() { - // TODO: Find out what pixel format we are using, - // create the renderer accordingly - return new Graphics::VectorRendererSpec >; - } - - template - void screenInit(); + template void screenInit(); void freeRenderer() { if (_vectorRenderer != NULL) -- cgit v1.2.3 From 74c458153e5674758e8bd425c9205beb6412726b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 28 May 2008 14:37:29 +0000 Subject: Cleanup. svn-id: r32341 --- gui/InterfaceManager.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 4e98fbc692..1da9fdc566 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -43,8 +43,8 @@ public: GFX_Antialias_16bit }; - InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(NULL), - _system(system), _graphicsMode(GFX_Disabled), _screen(NULL), _bytesPerPixel(0) { + InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(0), + _system(system), _graphicsMode(GFX_Disabled), _screen(0), _bytesPerPixel(0) { setGraphicsMode(mode); } @@ -61,14 +61,15 @@ protected: template void screenInit(); void freeRenderer() { - if (_vectorRenderer != NULL) - delete _vectorRenderer; + delete _vectorRenderer; + _vectorRenderer = 0; } void freeScreen() { - if (_screen != NULL) { + if (_screen != 0) { _screen->free(); delete _screen; + _screen = 0; } } -- cgit v1.2.3 From 8a83eafbf3119c4acec8e294b883da4c500efeeb Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 28 May 2008 15:03:30 +0000 Subject: Misc fixes. Constant naming fixes. svn-id: r32342 --- base/main.cpp | 2 +- graphics/VectorRenderer.cpp | 124 ++++++++++++++++++++++---------------------- graphics/VectorRenderer.h | 65 ++++++++++++----------- gui/InterfaceManager.cpp | 28 +++++----- gui/InterfaceManager.h | 8 +-- 5 files changed, 116 insertions(+), 111 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 51b3451837..be0c84bb1c 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -70,7 +70,7 @@ static bool launcherDialog(OSystem &system) { #if 1 - GUI::InterfaceManager iManager(&system, GUI::InterfaceManager::GFX_Standard_16bit); + GUI::InterfaceManager iManager(&system, GUI::InterfaceManager::kGfxStandard16bit); iManager.runGUI(); return true; diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index dfb555c20b..aba940e386 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -37,14 +37,14 @@ namespace Graphics { VectorRenderer *createRenderer(int mode) { switch (mode) { - case GUI::InterfaceManager::GFX_Standard_16bit: + case GUI::InterfaceManager::kGfxStandard16bit: return new VectorRendererSpec >; - case GUI::InterfaceManager::GFX_Antialias_16bit: + case GUI::InterfaceManager::kGfxAntialias16bit: return new VectorRendererAA >; default: - return NULL; + return 0; } } @@ -53,34 +53,34 @@ VectorRenderer *createRenderer(int mode) { ********************************************************************/ void VectorRenderer::drawStep(DrawStep *step) { - if (step->flags & kDrawStep_CallbackOnly) { + if (step->flags & DrawStep::kStepCallbackOnly) { (this->*(step->drawing_call))(step); return; } - if (step->flags & kDrawStep_SetBG) + if (step->flags & DrawStep::kStepSetBG) setBgColor(step->color2.r, step->color2.g, step->color2.b); - if (step->flags & kDrawStep_SetFG) + if (step->flags & DrawStep::kStepSetFG) setFgColor(step->color1.r, step->color1.g, step->color1.b); - if (step->flags & kDrawStep_SetGradient) + if (step->flags & DrawStep::kStepSetGradient) setGradientColors(step->color1.r, step->color1.g, step->color1.b, step->color2.r, step->color2.g, step->color2.b); - if (step->flags & kDrawStep_SetShadow) + if (step->flags & DrawStep::kStepSetShadow) shadowEnable(step->shadow); - if (step->flags & kDrawStep_SetGradientFactor) + if (step->flags & DrawStep::kStepSetGradientFactor) setGradientFactor(step->factor); - if (step->flags & kDrawStep_SetStroke) + if (step->flags & DrawStep::kStepSetStroke) setStrokeWidth(step->stroke); - if (step->flags & kDrawStep_SetFillMode) - setFillMode(step->fill_mode); + if (step->flags & DrawStep::kStepSetFillMode) + setFillMode((FillMode)step->fill_mode); - if (step->flags & kDrawStep_SettingsOnly) + if (step->flags & DrawStep::kStepSettingsOnly) return; (this->*(step->drawing_call))(step); @@ -229,33 +229,33 @@ drawCircle(int x, int y, int r) { if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h) return; - if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + r + Base::_shadowOffset < Base::_activeSurface->w && y + r + Base::_shadowOffset < Base::_activeSurface->h) { - drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillMode_Foreground); + drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground); } switch(Base::_fillMode) { - case kFillMode_Disabled: + case kFillDisabled: if (Base::_strokeWidth) - drawCircleAlg(x, y, r, _fgColor, kFillMode_Disabled); + drawCircleAlg(x, y, r, _fgColor, kFillDisabled); break; - case kFillMode_Foreground: - drawCircleAlg(x, y, r, _fgColor, kFillMode_Foreground); + case kFillForeground: + drawCircleAlg(x, y, r, _fgColor, kFillForeground); break; - case kFillMode_Background: + case kFillBackground: if (Base::_strokeWidth > 1) { - drawCircleAlg(x, y, r, _fgColor, kFillMode_Foreground); - drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillMode_Background); + drawCircleAlg(x, y, r, _fgColor, kFillForeground); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground); } else { - drawCircleAlg(x, y, r, _bgColor, kFillMode_Background); - drawCircleAlg(x, y, r, _fgColor, kFillMode_Disabled); + drawCircleAlg(x, y, r, _bgColor, kFillBackground); + drawCircleAlg(x, y, r, _fgColor, kFillDisabled); } break; - case kFillMode_Gradient: + case kFillGradient: break; } } @@ -267,31 +267,31 @@ drawSquare(int x, int y, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; - if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawSquareShadow(x, y, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { - case kFillMode_Disabled: + case kFillDisabled: if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); break; - case kFillMode_Foreground: - drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Foreground); + case kFillForeground: + drawSquareAlg(x, y, w, h, _fgColor, kFillForeground); break; - case kFillMode_Background: - drawSquareAlg(x, y, w, h, _bgColor, kFillMode_Background); - drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); + case kFillBackground: + drawSquareAlg(x, y, w, h, _bgColor, kFillBackground); + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); break; - case kFillMode_Gradient: - VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillMode_Gradient); + case kFillGradient: + VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient); if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kFillMode_Disabled); + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); break; } } @@ -303,36 +303,36 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; - if (Base::_fillMode != kFillMode_Disabled && Base::_shadowOffset + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w && y + h + Base::_shadowOffset < Base::_activeSurface->h) { drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } switch(Base::_fillMode) { - case kFillMode_Disabled: + case kFillDisabled: if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); break; - case kFillMode_Foreground: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Foreground); + case kFillForeground: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); break; - case kFillMode_Background: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillMode_Background); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); + case kFillBackground: + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillBackground); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); break; - case kFillMode_Gradient: + case kFillGradient: if (Base::_strokeWidth > 1) { - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Foreground); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, - r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillMode_Gradient); + r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillGradient); } else { - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillMode_Gradient); + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillGradient); if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillMode_Disabled); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); } break; } @@ -344,14 +344,14 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { /** SQUARE ALGORITHM **/ template void VectorRendererSpec:: -drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { +drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int pitch = Base::surfacePitch(); int max_h = h; - if (fill_m != kFillMode_Disabled) { + if (fill_m != kFillDisabled) { while (h--) { - if (fill_m == kFillMode_Gradient) + if (fill_m == kFillGradient) color = calcGradient(max_h - h, max_h); colorFill(ptr, ptr + w, color); @@ -425,7 +425,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { /** ROUNDED SQUARE ALGORITHM **/ template void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); @@ -441,7 +441,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM int short_h = h - (2 * r) + 2; int long_h = h; - if (fill_m == kFillMode_Disabled) { + if (fill_m == kFillDisabled) { while (sw++ < Base::_strokeWidth) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -470,7 +470,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM } else { __BE_RESET(); - if (fill_m == kFillMode_Gradient) { + if (fill_m == kFillGradient) { while (x++ < y) { __BE_ALGORITHM(); colorFill(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); @@ -496,7 +496,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM ptr_fill += pitch * r; while (short_h--) { - if (fill_m == kFillMode_Gradient) + if (fill_m == kFillGradient) color = calcGradient(real_radius++, long_h); colorFill(ptr_fill, ptr_fill + w + 1, color); ptr_fill += pitch; @@ -507,13 +507,13 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM /** CIRCLE ALGORITHM **/ template void VectorRendererSpec:: -drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { +drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py, sw = 0; int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill_m == kFillMode_Disabled) { + if (fill_m == kFillDisabled) { while (sw++ < Base::_strokeWidth) { __BE_RESET(); r--; @@ -700,7 +700,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { /** ROUNDED SQUARES **/ template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0, hp = h * p; @@ -717,7 +717,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM int short_h = h - 2 * r; - if (fill_m == kFillMode_Disabled) { + if (fill_m == VectorRenderer::kFillDisabled) { while (sw++ < Base::_strokeWidth) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -770,7 +770,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM /** CIRCLES **/ template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { +drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { int x, y, sw = 0; int p = Base::surfacePitch(), px, py; @@ -780,7 +780,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill_m == kFillMode_Disabled) { + if (fill_m == VectorRenderer::kFillDisabled) { while (sw++ < Base::_strokeWidth) { x = r - (sw - 1); y = 0; T = 0; px = p * x; py = 0; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 65d0cce417..98bb25a2cb 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -27,22 +27,16 @@ #define VECTOR_RENDERER_H #include "common/scummsys.h" +#include "common/system.h" + #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "common/system.h" -namespace Graphics { -class VectorRenderer; +#include "gui/InterfaceManager.h" -VectorRenderer *createRenderer(int mode); -/** Specifies the way in which a shape is filled */ -enum FillMode { - kFillMode_Disabled = 0, - kFillMode_Foreground = 1, - kFillMode_Background = 2, - kFillMode_Gradient = 3 -}; +namespace Graphics { +class VectorRenderer; struct DrawStep { uint32 flags; /** Step flags, see DrawStepFlags */ @@ -56,23 +50,25 @@ struct DrawStep { uint16 x, y, w, h, r; /** Shape size */ uint8 shadow, stroke, factor; /** Misc options... */ - FillMode fill_mode; /** active fill mode */ + int fill_mode; /** active fill mode */ void (VectorRenderer::*drawing_call)(DrawStep*); /** Pointer to drawing function */ -}; -enum DrawStepFlags { - kDrawStep_CallbackOnly = (1 << 0), - kDrawStep_SettingsOnly = (1 << 1), - kDrawStep_SetBG = (1 << 2), - kDrawStep_SetFG = (1 << 3), - kDrawStep_SetGradient = (1 << 4), - kDrawStep_SetShadow = (1 << 5), - kDrawStep_SetGradientFactor = (1 << 6), - kDrawStep_SetStroke = (1 << 7), - kDrawStep_SetFillMode = (1 << 8) + enum DrawStepFlags { + kStepCallbackOnly = (1 << 0), + kStepSettingsOnly = (1 << 1), + kStepSetBG = (1 << 2), + kStepSetFG = (1 << 3), + kStepSetGradient = (1 << 4), + kStepSetShadow = (1 << 5), + kStepSetGradientFactor = (1 << 6), + kStepSetStroke = (1 << 7), + kStepSetFillMode = (1 << 8) + }; }; +VectorRenderer *createRenderer(int mode); + /** * VectorRenderer: The core Vector Renderer Class * @@ -90,9 +86,17 @@ enum DrawStepFlags { */ class VectorRenderer { public: - VectorRenderer() : _shadowOffset(0), _fillMode(kFillMode_Disabled), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} + VectorRenderer() : _shadowOffset(0), _fillMode(kFillDisabled), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} virtual ~VectorRenderer() {} + /** Specifies the way in which a shape is filled */ + enum FillMode { + kFillDisabled = 0, + kFillForeground = 1, + kFillBackground = 2, + kFillGradient = 3 + }; + /** * Draws a line by considering the special cases for optimization. * @@ -183,7 +187,7 @@ public: virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; /** - * Set the active gradient color. All shapes drawn using kFillMode_Gradient + * Set the active gradient color. All shapes drawn using kFillGradient * as their fill mode will use this VERTICAL gradient as their fill color. * * @param r1 value of the red color byte for the start color @@ -311,7 +315,6 @@ protected: int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */ }; - /** * VectorRendererSpec: Specialized Vector Renderer Class * @@ -392,11 +395,11 @@ public: int h = _activeSurface->h ; int pitch = surfacePitch(); - if (Base::_fillMode == kFillMode_Background) + if (Base::_fillMode == kFillBackground) colorFill(ptr, ptr + w * h, _bgColor); - else if (Base::_fillMode == kFillMode_Foreground) + else if (Base::_fillMode == kFillForeground) colorFill(ptr, ptr + w * h, _fgColor); - else if (Base::_fillMode == kFillMode_Gradient) { + else if (Base::_fillMode == kFillGradient) { int i = h; while (i--) { colorFill(ptr, ptr + w, calcGradient(h - i, h)); @@ -622,7 +625,7 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); /** * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991, @@ -631,7 +634,7 @@ protected: * * @see VectorRenderer::drawRoundedAlg() */ - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); }; } // end of namespace Graphics diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 6aa5bac733..cccf7a2be5 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -34,11 +34,13 @@ namespace GUI { +using namespace Graphics; + template void InterfaceManager::screenInit() { freeScreen(); - _screen = new Graphics::Surface; + _screen = new Surface; _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); _system->clearOverlay(); } @@ -50,12 +52,12 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { _graphicsMode = mode; switch (mode) { - case GFX_Standard_16bit: + case kGfxStandard16bit: _bytesPerPixel = sizeof(uint16); screenInit(); break; - case GFX_Antialias_16bit: + case kGfxAntialias16bit: _bytesPerPixel = sizeof(uint16); screenInit(); break; @@ -64,7 +66,7 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { return; } - _vectorRenderer = Graphics::createRenderer(mode); + _vectorRenderer = createRenderer(mode); _vectorRenderer->setSurface(_screen); } @@ -80,9 +82,9 @@ int InterfaceManager::runGUI() { steps[0].color2.r = 240; steps[0].color2.g = 200; steps[0].color2.b = 25; - steps[0].fill_mode = Graphics::kFillMode_Gradient; - steps[0].drawing_call = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; - steps[0].flags = Graphics::kDrawStep_SetGradient | Graphics::kDrawStep_SetFillMode; + steps[0].fill_mode = VectorRenderer::kFillGradient; + steps[0].drawing_call = &VectorRenderer::drawCallback_FILLSURFACE; + steps[0].flags = DrawStep::kStepSetGradient | DrawStep::kStepSetFillMode; steps[1].color1.r = 206; steps[1].color1.g = 121; @@ -95,24 +97,24 @@ int InterfaceManager::runGUI() { steps[1].r = 8; steps[1].w = 120; steps[1].h = 30; - steps[1].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; - steps[1].flags = Graphics::kDrawStep_SetGradient; + steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[1].flags = DrawStep::kStepSetGradient; steps[2].x = 500; steps[2].y = 135; steps[2].r = 8; steps[2].w = 120; steps[2].h = 30; - steps[2].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; - steps[2].flags = Graphics::kDrawStep_CallbackOnly; + steps[2].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[2].flags = DrawStep::kStepCallbackOnly; steps[3].x = 500; steps[3].y = 175; steps[3].r = 8; steps[3].w = 120; steps[3].h = 30; - steps[3].drawing_call = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; - steps[3].flags = Graphics::kDrawStep_CallbackOnly; + steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; + steps[3].flags = DrawStep::kStepCallbackOnly; bool running = true; while (running) { // draw!! diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 1da9fdc566..f3f1784b0c 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -38,13 +38,13 @@ class InterfaceManager { public: enum Graphics_Mode { - GFX_Disabled = 0, - GFX_Standard_16bit, - GFX_Antialias_16bit + kGfxDisabled = 0, + kGfxStandard16bit, + kGfxAntialias16bit }; InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(0), - _system(system), _graphicsMode(GFX_Disabled), _screen(0), _bytesPerPixel(0) { + _system(system), _graphicsMode(kGfxDisabled), _screen(0), _bytesPerPixel(0) { setGraphicsMode(mode); } -- cgit v1.2.3 From 5d2d18421386021eb7754684edf908e02276add5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 1 Jun 2008 00:28:16 +0000 Subject: - Triangles! svn-id: r32451 --- graphics/VectorRenderer.cpp | 145 +++++++++++++++++++++++++++++++++++++++++++- graphics/VectorRenderer.h | 20 ++++++ 2 files changed, 162 insertions(+), 3 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index aba940e386..b9d44a224e 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -166,6 +166,28 @@ inline uint32 fp_sqroot(uint32 x) { a1 = ~a2; \ } +#define __TRIANGLE_MAINX() \ + if (error_term >= 0) { \ + ptr_right += pitch; \ + ptr_left += pitch; \ + error_term += dysub; \ + } else { \ + error_term += ddy; \ + } \ + ptr_right++; \ + ptr_left--; + +#define __TRIANGLE_MAINY() \ + if (error_term >= 0) { \ + ptr_right++; \ + ptr_left--; \ + error_term += dxsub; \ + } else { \ + error_term += ddx; \ + } \ + ptr_right += pitch; \ + ptr_left += pitch; + /******************************************************************** * Primitive shapes drawing - Public API calls - VectorRendererSpec ********************************************************************/ @@ -235,7 +257,7 @@ drawCircle(int x, int y, int r) { drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground); } - switch(Base::_fillMode) { + switch (Base::_fillMode) { case kFillDisabled: if (Base::_strokeWidth) drawCircleAlg(x, y, r, _fgColor, kFillDisabled); @@ -273,7 +295,7 @@ drawSquare(int x, int y, int w, int h) { drawSquareShadow(x, y, w, h, Base::_shadowOffset); } - switch(Base::_fillMode) { + switch (Base::_fillMode) { case kFillDisabled: if (Base::_strokeWidth) drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); @@ -309,7 +331,7 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } - switch(Base::_fillMode) { + switch (Base::_fillMode) { case kFillDisabled: if (Base::_strokeWidth) drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); @@ -338,6 +360,41 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { } } +template +void VectorRendererSpec:: +drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + return; + + PixelType color = 0; + + if (Base::_strokeWidth <= 1) { + if (Base::_fillMode == kFillForeground) + color = _fgColor; + else if (Base::_fillMode == kFillBackground) + color = _bgColor; + } else { + if (Base::_fillMode == kFillDisabled) + return; + color = _fgColor; + } + + switch(orient) { + case kTriangleUp: + case kTriangleDown: + drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); + break; + + case kTriangleLeft: + case kTriangleRight: + break; + } + + if (Base::_strokeWidth > 0) + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) + drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), _fgColor, kFillDisabled); +} + /******************************************************************** * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec ********************************************************************/ @@ -422,6 +479,88 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { *ptr = (PixelType)color; } +/** VERTICAL TRIANGLE DRAWING ALGORITHM **/ +template +void VectorRendererSpec:: +drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { + int dx = w >> 1, dy = h, gradient_h = 0; + int pitch = Base::surfacePitch(); + PixelType *ptr_right = 0, *ptr_left = 0; + + if (inverted) { + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); + } else { + ptr_right = ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + dx, y1); + } + + if (dx > dy) { + int ddy = dy * 2; + int dysub = ddy - (dx * 2); + int error_term = ddy - dx; + + switch(fill_m) { + case kFillDisabled: + while (dx--) { + __TRIANGLE_MAINX(); + *ptr_right = color; + *ptr_left = color; + } + colorFill(ptr_left, ptr_right, color); + break; + + case kFillForeground: + case kFillBackground: + while (dx--) { + __TRIANGLE_MAINX(); + if (inverted) colorFill(ptr_right, ptr_left, color); + else colorFill(ptr_left, ptr_right, color); + } + break; + + case kFillGradient: + while (dx--) { + __TRIANGLE_MAINX(); + if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + } + break; + } + } else { + int ddx = dx * 2; + int dxsub = ddx - (dy * 2); + int error_term = ddx - dy; + + switch(fill_m) { + case kFillDisabled: + while (dy--) { + __TRIANGLE_MAINY(); + *ptr_right = color; + *ptr_left = color; + } + colorFill(ptr_left, ptr_right, color); + break; + + case kFillForeground: + case kFillBackground: + while (dy--) { + __TRIANGLE_MAINY(); + if (inverted) colorFill(ptr_right, ptr_left, color); + else colorFill(ptr_left, ptr_right, color); + } + break; + case kFillGradient: + while (dy--) { + __TRIANGLE_MAINY(); + if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + } + break; + } + } +} + + /** ROUNDED SQUARE ALGORITHM **/ template void VectorRendererSpec:: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 98bb25a2cb..b6c72425d7 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -97,6 +97,13 @@ public: kFillGradient = 3 }; + enum TriangleOrientation { + kTriangleUp, + kTriangleDown, + kTriangleLeft, + kTriangleRight + }; + /** * Draws a line by considering the special cases for optimization. * @@ -138,6 +145,8 @@ public: */ virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0; + virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0; + /** * Gets the pixel pitch for the current drawing surface. * Note: This is a real pixel-pitch, not a byte-pitch. @@ -359,6 +368,11 @@ public: */ void drawRoundedSquare(int x, int y, int r, int w, int h); + /** + * @see VectorRenderer::drawTriangle() + */ + void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); + /** * @see VectorRenderer::setFgColor() */ @@ -498,6 +512,7 @@ protected: virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); + virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); /** * SHADOW DRAWING ALGORITHMS @@ -565,6 +580,11 @@ protected: * @param color Color of the pixel */ virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color) { + if (first == last) { + *first = color; + return; + } + register PixelType *ptr = first; register int count = (last - first); register int n = (count + 7) >> 3; -- cgit v1.2.3 From 934f4fd17f92804b2b1bf1244e8e8ac162de0e4a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 2 Jun 2008 21:38:28 +0000 Subject: Beveled squares for Classic GUI imitation svn-id: r32506 --- graphics/VectorRenderer.cpp | 38 ++++++++++++++++++++++++++++++++++++++ graphics/VectorRenderer.h | 6 ++++++ 2 files changed, 44 insertions(+) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index b9d44a224e..43046bafdf 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -431,6 +431,44 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillM } } +/** SQUARE ALGORITHM **/ +template +void VectorRendererSpec:: +drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color) { + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + int pitch = Base::surfacePitch(); + int i, j; + + i = bevel; + while (i--) { + colorFill(ptr_left, ptr_left + w, top_color); + ptr_left += pitch; + } + + i = h - bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel); + while (i--) { + colorFill(ptr_left, ptr_left + bevel, top_color); + ptr_left += pitch; + } + + i = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel); + while (i--) { + colorFill(ptr_left + i, ptr_left + w, bottom_color); + ptr_left += pitch; + } + + i = h - bevel; + j = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); + while (i--) { + colorFill(ptr_left + j, ptr_left + bevel, bottom_color); + if (j > 0) j--; + ptr_left += pitch; + } +} + /** GENERIC LINE ALGORITHM **/ template void VectorRendererSpec:: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b6c72425d7..ed000a9215 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -146,6 +146,7 @@ public: virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0; virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0; + virtual void drawBeveledSquare(int x, int y, int w, int h, int bevel) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -373,6 +374,10 @@ public: */ void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); + void drawBeveledSquare(int x, int y, int w, int h, int bevel) { + drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); + } + /** * @see VectorRenderer::setFgColor() */ @@ -513,6 +518,7 @@ protected: virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); + virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color); /** * SHADOW DRAWING ALGORITHMS -- cgit v1.2.3 From 18d5678e7bba24abb4ec98f4b82636fcc728092c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 6 Jun 2008 13:38:44 +0000 Subject: Documentation update. More drawing steps. svn-id: r32576 --- graphics/VectorRenderer.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index ed000a9215..0c476d3e27 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -51,6 +51,7 @@ struct DrawStep { uint8 shadow, stroke, factor; /** Misc options... */ int fill_mode; /** active fill mode */ + int extra; /** Generic parameter for extra options */ void (VectorRenderer::*drawing_call)(DrawStep*); /** Pointer to drawing function */ @@ -145,7 +146,30 @@ public: */ virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0; + /** + * Draws a triangle starting at (x,y) with the given base and height. + * The triangle will always be isosceles, with the given base and height. + * The orientation parameter controls the position of the base of the triangle. + * + * @param x Horizontal (X) coordinate for the top left corner of the triangle + * @param y Vertical (Y) coordinate for the top left corner of the triangle + * @param base Width of the base of the triangle + * @param h Height of the triangle + * @param orient Orientation of the triangle. + */ virtual void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient) = 0; + + /** + * Draws a beveled square like the ones in the Classic GUI themes. + * Beveled squares are always drawn with a transparent background. Draw them on top + * of a standard square to fill it. + * + * @param x Horizontal (X) coordinate for the center of the square + * @param y Vertical (Y) coordinate for the center of the square + * @param w Width of the square. + * @param h Height of the square + * @param bevel Amount of bevel. Must be positive. + */ virtual void drawBeveledSquare(int x, int y, int w, int h, int bevel) = 0; /** @@ -289,6 +313,9 @@ public: _gradientFactor = factor; } + /** + * DrawStep callback functions for each drawing feature + */ void drawCallback_CIRCLE(DrawStep *step) { drawCircle(step->x, step->y, step->r); } @@ -309,8 +336,27 @@ public: fillSurface(); } + void drawCallback_TRIANGLE(DrawStep *step) { + drawTriangle(step->x, step->y, step->w, step->h, (TriangleOrientation)step->extra); + } + + void drawCallback_BEVELSQ(DrawStep *step) { + drawBeveledSquare(step->x, step->y, step->w, step->h, step->extra); + } + + /** + * Draws the specified draw step on the screen. + * + * @see DrawStep + * @param step Pointer to a DrawStep struct. + */ virtual void drawStep(DrawStep *step); + /** + * Copies the current surface to the system overlay + * + * @param sys Pointer to the global System class + */ virtual void copyFrame(OSystem *sys) = 0; protected: @@ -427,6 +473,9 @@ public: } } + /** + * @see VectorRenderer::copyFrame() + */ virtual void copyFrame(OSystem *sys) { #ifdef OVERLAY_MULTIPLE_DEPTHS sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), -- cgit v1.2.3 From 69694c72f658cedde9a03235ccdaf20982b3980f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 7 Jun 2008 20:50:39 +0000 Subject: Expanded the InterfaceManager skeleton quite a bit. svn-id: r32604 --- graphics/VectorRenderer.h | 43 +++++++++++++++---- gui/InterfaceManager.cpp | 50 +++++++++++++++++++++++ gui/InterfaceManager.h | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 7 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0c476d3e27..2226907670 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -48,6 +48,7 @@ struct DrawStep { color2; /** Background color/gradient end */ uint16 x, y, w, h, r; /** Shape size */ + uint16 offset_x, offset_y; /** Offset when drawing directly to the whole screen */ uint8 shadow, stroke, factor; /** Misc options... */ int fill_mode; /** active fill mode */ @@ -87,7 +88,12 @@ VectorRenderer *createRenderer(int mode); */ class VectorRenderer { public: - VectorRenderer() : _shadowOffset(0), _fillMode(kFillDisabled), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {} + VectorRenderer() : _shadowOffset(0), _fillMode(kFillDisabled), + _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1), + _stepOffsetX(0), _stepOffsetY(0) { + + } + virtual ~VectorRenderer() {} /** Specifies the way in which a shape is filled */ @@ -317,19 +323,19 @@ public: * DrawStep callback functions for each drawing feature */ void drawCallback_CIRCLE(DrawStep *step) { - drawCircle(step->x, step->y, step->r); + drawCircle(_stepOffsetX + step->x, _stepOffsetY + step->y, step->r); } void drawCallback_SQUARE(DrawStep *step) { - drawSquare(step->x, step->y, step->w, step->h); + drawSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h); } void drawCallback_LINE(DrawStep *step) { - drawLine(step->x, step->y, step->x + step->w, step->y + step->h); + drawLine(_stepOffsetX + step->x, _stepOffsetY + step->y, step->x + step->w, step->y + step->h); } void drawCallback_ROUNDSQ(DrawStep *step) { - drawRoundedSquare(step->x, step->y, step->r, step->w, step->h); + drawRoundedSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->r, step->w, step->h); } void drawCallback_FILLSURFACE(DrawStep *step) { @@ -337,11 +343,11 @@ public: } void drawCallback_TRIANGLE(DrawStep *step) { - drawTriangle(step->x, step->y, step->w, step->h, (TriangleOrientation)step->extra); + drawTriangle(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h, (TriangleOrientation)step->extra); } void drawCallback_BEVELSQ(DrawStep *step) { - drawBeveledSquare(step->x, step->y, step->w, step->h, step->extra); + drawBeveledSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h, step->extra); } /** @@ -359,9 +365,32 @@ public: */ virtual void copyFrame(OSystem *sys) = 0; + /** + * Enables drawing offset for all the Draw Step operations, + * i.e. when we are drawing widgets directly on a whole screen + * instead of individual surfaces for caching/blitting. + * + * @param x Horizontal drawing offset. + * @param y Veritcal drawing offset. + */ + void setDrawOffset(int x, int y) { + _stepOffsetX = x; + _stepOffsetY = y; + } + + /** + * Disables the drawing offset for draw step operations. + */ + void disableDrawOffset() { + _stepOffsetX = _stepOffsetY = 0; + } + protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ + int _stepOffsetX; /** Offset for all the drawing steps */ + int _stepOffsetY; /** Offset for all the drawing steps */ + FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index cccf7a2be5..822b7094b3 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -70,6 +70,50 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { _vectorRenderer->setSurface(_screen); } +void InterfaceManager::init() { + +} + +void InterfaceManager::drawWidgetBackground(int x, int y, uint16 hints, WidgetBackground background, WidgetStateInfo state, float scale){ + +} + +void InterfaceManager::drawButton(int x, int y, const Common::String &str, WidgetStateInfo state, uint16 hints, float scale) { + +} + +void InterfaceManager::drawSurface(int x, int y, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans, float scale) { + +} + +void InterfaceManager::drawSlider(int x, int y, int width, WidgetStateInfo state, float scale) { + +} + +void InterfaceManager::drawCheckbox(int x, int y, const Common::String &str, bool checked, WidgetStateInfo state, float scale) { + +} + +void InterfaceManager::drawTab(int x, int y, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state, float scale) { + +} + +void InterfaceManager::drawScrollbar(int x, int y, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state, float scale) { + +} + +void InterfaceManager::drawPopUpWidget(int x, int y, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align, float scale) { + +} + +void InterfaceManager::drawCaret(int x, int y, bool erase, WidgetStateInfo state, float scale) { + +} + +void InterfaceManager::drawLineSeparator(int x, int y, WidgetStateInfo state, float scale) { + +} + int InterfaceManager::runGUI() { Common::EventManager *eventMan = _system->getEventManager(); _system->showOverlay(); @@ -122,6 +166,12 @@ int InterfaceManager::runGUI() { for (int i = 0; i < 4; ++i) _vectorRenderer->drawStep(&steps[i]); + _vectorRenderer->setFillMode(VectorRenderer::kFillGradient); + _vectorRenderer->setFgColor(0, 0, 0); + _vectorRenderer->drawTriangle(32, 32, 64, 64, VectorRenderer::kTriangleUp); + + _vectorRenderer->drawBeveledSquare(128, 128, 256, 64, 4); + _vectorRenderer->copyFrame(_system); Common::Event event; diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index f3f1784b0c..c7e96103c0 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -30,10 +30,16 @@ #include "graphics/surface.h" #include "common/system.h" +#include "graphics/surface.h" +#include "graphics/fontman.h" + #include "graphics/VectorRenderer.h" namespace GUI { +struct WidgetDrawData; +class InterfaceManager; + class InterfaceManager { public: @@ -43,6 +49,65 @@ public: kGfxAntialias16bit }; + enum DrawData { + kDrawDataBackground, + kDrawDataButton, + kDrawDataSurface, + kDrawDataSlider, + kDrawDataCheckbox, + kDrawDataTab, + kDrawDataScrollBar, + kDrawDataPopUp, + kDrawDataCaret, + kDrawDataSeparator, + kDrawDataMAX + }; + + enum FontStyle { + kFontStyleBold = 0, //! A bold font. This is also the default font. + kFontStyleNormal = 1, //! A normal font. + kFontStyleItalic = 2, //! Italic styled font. + kFontStyleFixedNormal = 3, //! Fixed size font. + kFontStyleFixedBold = 4, //! Fixed size bold font. + kFontStyleFixedItalic = 5, //! Fixed size italic font. + kFontStyleMax + }; + + enum State { + kStateDisabled, //! Indicates that the widget is disabled, that does NOT include that it is invisible + kStateEnabled, //! Indicates that the widget is enabled + kStateHighlight //! Indicates that the widget is highlighted by the user + }; + + //! Widget background type + enum WidgetBackground { + kWidgetBackgroundNo, //! No background at all + kWidgetBackgroundPlain, //! Simple background, this may not include borders + kWidgetBackgroundBorder, //! Same as kWidgetBackgroundPlain just with a border + kWidgetBackgroundBorderSmall, //! Same as kWidgetBackgroundPlain just with a small border + kWidgetBackgroundEditText, //! Background used for edit text fields + kWidgetBackgroundSlider //! Background used for sliders + }; + + typedef State WidgetStateInfo; + + //! State of the scrollbar + enum ScrollbarState { + kScrollbarStateNo, + kScrollbarStateUp, + kScrollbarStateDown, + kScrollbarStateSlider, + kScrollbarStateSinglePage + }; + + //! Defined the align of the text + enum TextAlign { + kTextAlignLeft, //! Text should be aligned to the left + kTextAlignCenter, //! Text should be centered + kTextAlignRight //! Text should be aligned to the right + }; + + InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(0), _system(system), _graphicsMode(kGfxDisabled), _screen(0), _bytesPerPixel(0) { @@ -56,6 +121,25 @@ public: void setGraphicsMode(Graphics_Mode mode); int runGUI(); + void init(); + + /** Font management */ + const Graphics::Font *getFont(FontStyle font) const { return _font; } + int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } + int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } + int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } + + /** Widget drawing */ + void drawWidgetBackground(int x, int y, uint16 hints, WidgetBackground background, WidgetStateInfo state, float scale = 1.0f); + void drawButton(int x, int y, const Common::String &str, WidgetStateInfo state, uint16 hints, float scale = 1.0f); + void drawSurface(int x, int y, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans, float scale = 1.0f); + void drawSlider(int x, int y, int width, WidgetStateInfo state, float scale = 1.0f); + void drawCheckbox(int x, int y, const Common::String &str, bool checked, WidgetStateInfo state, float scale = 1.0f); + void drawTab(int x, int y, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state, float scale = 1.0f); + void drawScrollbar(int x, int y, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state, float scale = 1.0f); + void drawPopUpWidget(int x, int y, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align, float scale = 1.0f); + void drawCaret(int x, int y, bool erase, WidgetStateInfo state, float scale = 1.0f); + void drawLineSeparator(int x, int y, WidgetStateInfo state, float scale = 1.0f); protected: template void screenInit(); @@ -79,6 +163,24 @@ protected: int _bytesPerPixel; Graphics_Mode _graphicsMode; + + Common::String _fontName; + const Graphics::Font *_font; + + WidgetDrawData *_widgets[kDrawDataMAX]; + + bool _initOk; + bool _caching; +}; + +struct WidgetDrawData { + Graphics::DrawStep **_steps; + int _stepCount; + + bool _cached; + Graphics::Surface *_surfaceCache; + + InterfaceManager::DrawData _type; }; } // end of namespace GUI. -- cgit v1.2.3 From da757aa2ca1c086ae2f123dc6636d17655b512c7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 9 Jun 2008 21:16:26 +0000 Subject: InterfaceManager is now a singleton svn-id: r32640 --- base/main.cpp | 4 +--- gui/InterfaceManager.cpp | 19 +++++++++++++------ gui/InterfaceManager.h | 21 +++++++++++++++------ 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index be0c84bb1c..45e0aef728 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -70,9 +70,7 @@ static bool launcherDialog(OSystem &system) { #if 1 - GUI::InterfaceManager iManager(&system, GUI::InterfaceManager::kGfxStandard16bit); - - iManager.runGUI(); + g_InterfaceManager.runGUI(); return true; #else diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 822b7094b3..ffe19dbe9c 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -32,10 +32,20 @@ #include "gui/InterfaceManager.h" #include "graphics/VectorRenderer.h" +DECLARE_SINGLETON(GUI::InterfaceManager); + namespace GUI { using namespace Graphics; +InterfaceManager::InterfaceManager() : + _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), + _screen(0), _bytesPerPixel(0) { + _system = g_system; + + setGraphicsMode(kGfxStandard16bit); +} + template void InterfaceManager::screenInit() { freeScreen(); @@ -53,10 +63,6 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { switch (mode) { case kGfxStandard16bit: - _bytesPerPixel = sizeof(uint16); - screenInit(); - break; - case kGfxAntialias16bit: _bytesPerPixel = sizeof(uint16); screenInit(); @@ -70,8 +76,8 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { _vectorRenderer->setSurface(_screen); } -void InterfaceManager::init() { - +bool InterfaceManager::init() { + return false; } void InterfaceManager::drawWidgetBackground(int x, int y, uint16 hints, WidgetBackground background, WidgetStateInfo state, float scale){ @@ -168,6 +174,7 @@ int InterfaceManager::runGUI() { _vectorRenderer->setFillMode(VectorRenderer::kFillGradient); _vectorRenderer->setFgColor(0, 0, 0); + _vectorRenderer->setBgColor(128, 64, 255); _vectorRenderer->drawTriangle(32, 32, 64, 64, VectorRenderer::kTriangleUp); _vectorRenderer->drawBeveledSquare(128, 128, 256, 64, 4); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index c7e96103c0..ff8eee3de0 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -37,10 +37,14 @@ namespace GUI { +#define g_InterfaceManager (GUI::InterfaceManager::instance()) + struct WidgetDrawData; class InterfaceManager; -class InterfaceManager { +class InterfaceManager : public Common::Singleton { + + friend class Common::Singleton; public: enum Graphics_Mode { @@ -107,12 +111,15 @@ public: kTextAlignRight //! Text should be aligned to the right }; + //! Function used to process areas other than the current dialog + enum ShadingStyle { + kShadingNone, //! No special post processing + kShadingDim, //! Dimming unused areas + kShadingLuminance //! Converting colors to luminance for unused areas + }; - InterfaceManager(OSystem *system, Graphics_Mode mode) : _vectorRenderer(0), - _system(system), _graphicsMode(kGfxDisabled), _screen(0), _bytesPerPixel(0) { - setGraphicsMode(mode); - } + InterfaceManager(); ~InterfaceManager() { freeRenderer(); @@ -121,7 +128,9 @@ public: void setGraphicsMode(Graphics_Mode mode); int runGUI(); - void init(); + + bool init(); + bool deinit(); /** Font management */ const Graphics::Font *getFont(FontStyle font) const { return _font; } -- cgit v1.2.3 From 29c4308c420722088f47b5724d176a3c2e4ef290 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 10 Jun 2008 11:25:00 +0000 Subject: Changed DrawStep for dynamic surface drawing. svn-id: r32643 --- graphics/VectorRenderer.cpp | 15 ++++++---- graphics/VectorRenderer.h | 61 ++++++++++++-------------------------- gui/InterfaceManager.cpp | 71 +++++---------------------------------------- gui/InterfaceManager.h | 24 ++++++++------- 4 files changed, 48 insertions(+), 123 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 43046bafdf..109ae24f03 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -51,10 +51,10 @@ VectorRenderer *createRenderer(int mode) { /******************************************************************** * DRAWSTEP handling functions ********************************************************************/ -void VectorRenderer::drawStep(DrawStep *step) { +void VectorRenderer::drawStep(Common::Rect area, DrawStep *step) { if (step->flags & DrawStep::kStepCallbackOnly) { - (this->*(step->drawing_call))(step); + (this->*(step->drawing_call))(&area, step->extra_data); return; } @@ -83,7 +83,7 @@ void VectorRenderer::drawStep(DrawStep *step) { if (step->flags & DrawStep::kStepSettingsOnly) return; - (this->*(step->drawing_call))(step); + (this->*(step->drawing_call))(&area, step->extra_data); } /******************************************************************** @@ -248,7 +248,8 @@ drawLine(int x1, int y1, int x2, int y2) { template void VectorRendererSpec:: drawCircle(int x, int y, int r) { - if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h) + if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h || + x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0) return; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset @@ -286,7 +287,8 @@ drawCircle(int x, int y, int r) { template void VectorRendererSpec:: drawSquare(int x, int y, int w, int h) { - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0) return; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset @@ -322,7 +324,8 @@ drawSquare(int x, int y, int w, int h) { template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0 || r > 128) return; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 2226907670..9958714df6 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -47,14 +47,12 @@ struct DrawStep { color1, /** Foreground color/gradient start */ color2; /** Background color/gradient end */ - uint16 x, y, w, h, r; /** Shape size */ - uint16 offset_x, offset_y; /** Offset when drawing directly to the whole screen */ uint8 shadow, stroke, factor; /** Misc options... */ int fill_mode; /** active fill mode */ - int extra; /** Generic parameter for extra options */ + int extra_data; /** Generic parameter for extra options (radius/orientation/bevel) */ - void (VectorRenderer::*drawing_call)(DrawStep*); /** Pointer to drawing function */ + void (VectorRenderer::*drawing_call)(Common::Rect*, int); /** Pointer to drawing function */ enum DrawStepFlags { kStepCallbackOnly = (1 << 0), @@ -89,8 +87,7 @@ VectorRenderer *createRenderer(int mode); class VectorRenderer { public: VectorRenderer() : _shadowOffset(0), _fillMode(kFillDisabled), - _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1), - _stepOffsetX(0), _stepOffsetY(0) { + _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) { } @@ -322,41 +319,42 @@ public: /** * DrawStep callback functions for each drawing feature */ - void drawCallback_CIRCLE(DrawStep *step) { - drawCircle(_stepOffsetX + step->x, _stepOffsetY + step->y, step->r); + void drawCallback_CIRCLE(Common::Rect *area, int data) { + drawCircle(area->left + data, area->top + data, data); } - void drawCallback_SQUARE(DrawStep *step) { - drawSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h); + void drawCallback_SQUARE(Common::Rect *area, int data) { + drawSquare(area->left, area->top, area->width(), area->height()); } - void drawCallback_LINE(DrawStep *step) { - drawLine(_stepOffsetX + step->x, _stepOffsetY + step->y, step->x + step->w, step->y + step->h); + void drawCallback_LINE(Common::Rect *area, int data) { + drawLine(area->left, area->top, area->right, area->bottom); } - void drawCallback_ROUNDSQ(DrawStep *step) { - drawRoundedSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->r, step->w, step->h); + void drawCallback_ROUNDSQ(Common::Rect *area, int data) { + drawRoundedSquare(area->left, area->top, data, area->width(), area->height()); } - void drawCallback_FILLSURFACE(DrawStep *step) { + void drawCallback_FILLSURFACE(Common::Rect *area, int data) { fillSurface(); } - void drawCallback_TRIANGLE(DrawStep *step) { - drawTriangle(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h, (TriangleOrientation)step->extra); + void drawCallback_TRIANGLE(Common::Rect *area, int data) { + drawTriangle(area->top, area->left, area->width(), area->height(), (TriangleOrientation)data); } - void drawCallback_BEVELSQ(DrawStep *step) { - drawBeveledSquare(_stepOffsetX + step->x, _stepOffsetY + step->y, step->w, step->h, step->extra); + void drawCallback_BEVELSQ(Common::Rect *area, int data) { + drawBeveledSquare(area->left, area->top, area->width(), area->height(), data); } /** * Draws the specified draw step on the screen. * * @see DrawStep + * @param area Zone to paint on * @param step Pointer to a DrawStep struct. */ - virtual void drawStep(DrawStep *step); + virtual void drawStep(Common::Rect area, DrawStep *step); /** * Copies the current surface to the system overlay @@ -365,32 +363,9 @@ public: */ virtual void copyFrame(OSystem *sys) = 0; - /** - * Enables drawing offset for all the Draw Step operations, - * i.e. when we are drawing widgets directly on a whole screen - * instead of individual surfaces for caching/blitting. - * - * @param x Horizontal drawing offset. - * @param y Veritcal drawing offset. - */ - void setDrawOffset(int x, int y) { - _stepOffsetX = x; - _stepOffsetY = y; - } - - /** - * Disables the drawing offset for draw step operations. - */ - void disableDrawOffset() { - _stepOffsetX = _stepOffsetY = 0; - } - protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ - int _stepOffsetX; /** Offset for all the drawing steps */ - int _stepOffsetY; /** Offset for all the drawing steps */ - FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index ffe19dbe9c..ef7fa31a46 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -72,6 +72,7 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { return; } + freeRenderer(); _vectorRenderer = createRenderer(mode); _vectorRenderer->setSurface(_screen); } @@ -80,46 +81,6 @@ bool InterfaceManager::init() { return false; } -void InterfaceManager::drawWidgetBackground(int x, int y, uint16 hints, WidgetBackground background, WidgetStateInfo state, float scale){ - -} - -void InterfaceManager::drawButton(int x, int y, const Common::String &str, WidgetStateInfo state, uint16 hints, float scale) { - -} - -void InterfaceManager::drawSurface(int x, int y, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans, float scale) { - -} - -void InterfaceManager::drawSlider(int x, int y, int width, WidgetStateInfo state, float scale) { - -} - -void InterfaceManager::drawCheckbox(int x, int y, const Common::String &str, bool checked, WidgetStateInfo state, float scale) { - -} - -void InterfaceManager::drawTab(int x, int y, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state, float scale) { - -} - -void InterfaceManager::drawScrollbar(int x, int y, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state, float scale) { - -} - -void InterfaceManager::drawPopUpWidget(int x, int y, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align, float scale) { - -} - -void InterfaceManager::drawCaret(int x, int y, bool erase, WidgetStateInfo state, float scale) { - -} - -void InterfaceManager::drawLineSeparator(int x, int y, WidgetStateInfo state, float scale) { - -} - int InterfaceManager::runGUI() { Common::EventManager *eventMan = _system->getEventManager(); _system->showOverlay(); @@ -142,42 +103,24 @@ int InterfaceManager::runGUI() { steps[1].color2.r = 173; steps[1].color2.g = 40; steps[1].color2.b = 8; - steps[1].x = 500; - steps[1].y = 95; - steps[1].r = 8; - steps[1].w = 120; - steps[1].h = 30; + steps[1].extra_data = 8; // radius steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; steps[1].flags = DrawStep::kStepSetGradient; - steps[2].x = 500; - steps[2].y = 135; - steps[2].r = 8; - steps[2].w = 120; - steps[2].h = 30; + steps[2].extra_data = 8; // radius steps[2].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; steps[2].flags = DrawStep::kStepCallbackOnly; - steps[3].x = 500; - steps[3].y = 175; - steps[3].r = 8; - steps[3].w = 120; - steps[3].h = 30; steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; steps[3].flags = DrawStep::kStepCallbackOnly; bool running = true; while (running) { // draw!! - for (int i = 0; i < 4; ++i) - _vectorRenderer->drawStep(&steps[i]); - - _vectorRenderer->setFillMode(VectorRenderer::kFillGradient); - _vectorRenderer->setFgColor(0, 0, 0); - _vectorRenderer->setBgColor(128, 64, 255); - _vectorRenderer->drawTriangle(32, 32, 64, 64, VectorRenderer::kTriangleUp); - - _vectorRenderer->drawBeveledSquare(128, 128, 256, 64, 4); + _vectorRenderer->drawStep(Common::Rect(), &steps[0]); + _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[1]); + _vectorRenderer->drawStep(Common::Rect(128, 128, 512, 190), &steps[2]); +// _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[3]); _vectorRenderer->copyFrame(_system); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index ff8eee3de0..7820abd6c7 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -45,6 +45,7 @@ class InterfaceManager; class InterfaceManager : public Common::Singleton { friend class Common::Singleton; + typedef Common::String String; public: enum Graphics_Mode { @@ -139,16 +140,16 @@ public: int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } /** Widget drawing */ - void drawWidgetBackground(int x, int y, uint16 hints, WidgetBackground background, WidgetStateInfo state, float scale = 1.0f); - void drawButton(int x, int y, const Common::String &str, WidgetStateInfo state, uint16 hints, float scale = 1.0f); - void drawSurface(int x, int y, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans, float scale = 1.0f); - void drawSlider(int x, int y, int width, WidgetStateInfo state, float scale = 1.0f); - void drawCheckbox(int x, int y, const Common::String &str, bool checked, WidgetStateInfo state, float scale = 1.0f); - void drawTab(int x, int y, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state, float scale = 1.0f); - void drawScrollbar(int x, int y, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state, float scale = 1.0f); - void drawPopUpWidget(int x, int y, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align, float scale = 1.0f); - void drawCaret(int x, int y, bool erase, WidgetStateInfo state, float scale = 1.0f); - void drawLineSeparator(int x, int y, WidgetStateInfo state, float scale = 1.0f); + void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} + void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0) {} + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} + void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled) {} + void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled) {} + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled) {} + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled) {} + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} + void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled) {} protected: template void screenInit(); @@ -183,6 +184,9 @@ protected: }; struct WidgetDrawData { + Common::Rect _realSize; + bool _scaled; + Graphics::DrawStep **_steps; int _stepCount; -- cgit v1.2.3 From da6e5c46607f733154f1f932a158678f5293c884 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 10 Jun 2008 19:57:38 +0000 Subject: Another redesign on the Draw Steps. This time it's for real. svn-id: r32647 --- graphics/VectorRenderer.cpp | 4 +- graphics/VectorRenderer.h | 91 ++++++++++++++++++++++++++++++++++++--------- gui/InterfaceManager.cpp | 22 ++++++++--- 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 109ae24f03..2c50ddd0ec 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -54,7 +54,7 @@ VectorRenderer *createRenderer(int mode) { void VectorRenderer::drawStep(Common::Rect area, DrawStep *step) { if (step->flags & DrawStep::kStepCallbackOnly) { - (this->*(step->drawing_call))(&area, step->extra_data); + (this->*(step->drawing_call))(&area, step); return; } @@ -83,7 +83,7 @@ void VectorRenderer::drawStep(Common::Rect area, DrawStep *step) { if (step->flags & DrawStep::kStepSettingsOnly) return; - (this->*(step->drawing_call))(&area, step->extra_data); + (this->*(step->drawing_call))(&area, step); } /******************************************************************** diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 9958714df6..3a2d98a376 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -47,12 +47,24 @@ struct DrawStep { color1, /** Foreground color/gradient start */ color2; /** Background color/gradient end */ - uint8 shadow, stroke, factor; /** Misc options... */ + bool fill_area; /** If enabled, the draw step occupies the whole drawing area */ - int fill_mode; /** active fill mode */ - int extra_data; /** Generic parameter for extra options (radius/orientation/bevel) */ + struct { + uint16 pos; + bool relative; + } x, y; /** Horizontal and vertical coordinates. Relative specifies if they are + measured from the opposite direction of the drawing area */ - void (VectorRenderer::*drawing_call)(Common::Rect*, int); /** Pointer to drawing function */ + uint16 w, h; /** width and height */ + + uint8 shadow, stroke, factor, radius; /** Misc options... */ + + uint8 fill_mode; /** active fill mode */ + uint8 extra_data; /** 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)(Common::Rect*, DrawStep*); /** Pointer to drawing function */ enum DrawStepFlags { kStepCallbackOnly = (1 << 0), @@ -65,6 +77,38 @@ struct DrawStep { kStepSetStroke = (1 << 7), kStepSetFillMode = (1 << 8) }; + + void getPositions(Common::Rect *area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { + if (fill_area) { + in_x = area->left; + in_y = area->top; + in_w = area->width(); + in_h = area->height(); + } else { + if (!x.relative) in_x = area->left + x.pos; + else in_x = area->left + area->width() - x.pos; + + if (!y.relative) in_y = area->top + y.pos; + else in_y = area->top + area->height() - y.pos; + + if (in_x + w > area->right) in_w = area->right - in_x; + else in_w = w; + + if (in_y + h > area->bottom) in_h = area->bottom - in_y; + else in_h = h; + } + + if (scale != (1 << 16) && scale != 0) { + in_x = (in_x * scale) >> 16; + in_y = (in_y * scale) >> 16; + in_w = (in_w * scale) >> 16; + in_h = (in_h * scale) >> 16; + } + } + + uint8 getRadius() { + return (((uint32)radius * scale) >> 16); + } }; VectorRenderer *createRenderer(int mode); @@ -319,32 +363,45 @@ public: /** * DrawStep callback functions for each drawing feature */ - void drawCallback_CIRCLE(Common::Rect *area, int data) { - drawCircle(area->left + data, area->top + data, data); + void drawCallback_CIRCLE(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + drawCircle(x, y, step->getRadius()); } - void drawCallback_SQUARE(Common::Rect *area, int data) { - drawSquare(area->left, area->top, area->width(), area->height()); + void drawCallback_SQUARE(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + drawSquare(x, y, w, h); } - void drawCallback_LINE(Common::Rect *area, int data) { - drawLine(area->left, area->top, area->right, area->bottom); + void drawCallback_LINE(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + drawLine(x, y, x + w, y + w); } - void drawCallback_ROUNDSQ(Common::Rect *area, int data) { - drawRoundedSquare(area->left, area->top, data, area->width(), area->height()); + void drawCallback_ROUNDSQ(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + /* HACK! Radius of the rounded squares isn't scaled */ + drawRoundedSquare(x, y, step->radius, w, h); } - void drawCallback_FILLSURFACE(Common::Rect *area, int data) { + void drawCallback_FILLSURFACE(Common::Rect *area, DrawStep *step) { fillSurface(); } - void drawCallback_TRIANGLE(Common::Rect *area, int data) { - drawTriangle(area->top, area->left, area->width(), area->height(), (TriangleOrientation)data); + void drawCallback_TRIANGLE(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + drawTriangle(x, y, w, h, (TriangleOrientation)step->extra_data); } - void drawCallback_BEVELSQ(Common::Rect *area, int data) { - drawBeveledSquare(area->left, area->top, area->width(), area->height(), data); + void drawCallback_BEVELSQ(Common::Rect *area, DrawStep *step) { + uint16 x, y, w, h; + step->getPositions(area, x, y, w, h); + drawBeveledSquare(x, y, w, h, step->extra_data); } /** diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index ef7fa31a46..613a445fa3 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -103,23 +103,35 @@ int InterfaceManager::runGUI() { steps[1].color2.r = 173; steps[1].color2.g = 40; steps[1].color2.b = 8; - steps[1].extra_data = 8; // radius + steps[1].radius = 8; // radius + steps[1].fill_area = true; steps[1].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; steps[1].flags = DrawStep::kStepSetGradient; - - steps[2].extra_data = 8; // radius + steps[1].scale = (1 << 16); + + steps[2].radius = 8; // radius + steps[2].fill_area = 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].flags = DrawStep::kStepCallbackOnly; + steps[2].scale = (1 << 16); steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; steps[3].flags = DrawStep::kStepCallbackOnly; + Common::Rect area = Common::Rect(32, 32, 256, 256); + bool running = true; while (running) { // draw!! _vectorRenderer->drawStep(Common::Rect(), &steps[0]); - _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[1]); - _vectorRenderer->drawStep(Common::Rect(128, 128, 512, 190), &steps[2]); + _vectorRenderer->drawStep(area, &steps[1]); + _vectorRenderer->drawStep(area, &steps[2]); // _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[3]); _vectorRenderer->copyFrame(_system); -- cgit v1.2.3 From 5dd77ea8203c7d63848b0423fbc3c9bfbb8987b5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 12 Jun 2008 11:26:11 +0000 Subject: - Widget caching for Interface manager. - Expanded theme Interface - Surface blitting for VectorRenderer svn-id: r32670 --- graphics/VectorRenderer.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++ gui/InterfaceManager.cpp | 42 ++++++++++++++++++++++++++++++++++++++ gui/InterfaceManager.h | 44 ++++++++++++++++++++++++++++----------- 3 files changed, 126 insertions(+), 12 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3a2d98a376..918ed1c39e 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -420,6 +420,14 @@ public: */ virtual void copyFrame(OSystem *sys) = 0; + /** + * Blits a given graphics surface on top of the current drawing surface. + * + * @param source Surface to blit into the drawing surface. + * @param r Position in the active drawing surface to do the blitting. + */ + virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; + protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -548,6 +556,25 @@ public: sys->updateScreen(); } + /** + * @see VectorRenderer::blitSurface() + */ + virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) { + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.top, r.left); + PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int h = r.height(), w = r.width(); + + while (h--) { + colorCopy(src_ptr, dst_ptr, w); + dst_ptr += dst_pitch; + src_ptr += src_pitch; + } + } + protected: /** @@ -718,6 +745,31 @@ protected: } } + /** + * Copies several pixes in a row from a surface to another one. + * Used for surface blitting. + * See colorFill() for optimization guidelines. + * + * @param src Source surface. + * @param dst Destination surface. + * @param count Amount of pixels to copy over. + */ + virtual inline void colorCopy(PixelType *src, PixelType *dst, int count) { + register int n = (count + 7) >> 3; + switch (count % 8) { + case 0: do { + *dst++ = *src++; + case 7: *dst++ = *src++; + case 6: *dst++ = *src++; + case 5: *dst++ = *src++; + case 4: *dst++ = *src++; + case 3: *dst++ = *src++; + case 2: *dst++ = *src++; + case 1: *dst++ = *src++; + } while (--n > 0); + } + } + PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 613a445fa3..e64d292e16 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -81,6 +81,48 @@ bool InterfaceManager::init() { return false; } +bool InterfaceManager::isWidgetCached(DrawData type, const Common::Rect &r) { + return _widgets[type] && _widgets[type]->_cached && + _widgets[type]->_surfaceCache->w == r.width() && + _widgets[type]->_surfaceCache->h == r.height(); +} + +void InterfaceManager::drawCached(DrawData type, const Common::Rect &r) { + assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); + _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); +} + +void InterfaceManager::drawDD(DrawData type, const Common::Rect &r) { + if (isWidgetCached(type, r)) { + drawCached(type, r); + } else { + for (int i = 0; i < _widgets[type]->_stepCount; ++i) + _vectorRenderer->drawStep(r, _widgets[type]->_steps[i]); + } +} + +void InterfaceManager::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { + if (!_initOk) + return; + + if (state == kStateEnabled) + drawDD(kDDButtonIdle, r); + else if (state == kStateHighlight) + drawDD(kDDButtonHover, r); + + // TODO: Add text drawing. + + addDirtyRect(r); +} + +void InterfaceManager::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { + if (!_initOk) + return; + + drawDD(kDDSeparator, r); + addDirtyRect(r); +} + int InterfaceManager::runGUI() { Common::EventManager *eventMan = _system->getEventManager(); _system->showOverlay(); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 7820abd6c7..05f95ee435 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -55,16 +55,30 @@ public: }; enum DrawData { - kDrawDataBackground, - kDrawDataButton, - kDrawDataSurface, - kDrawDataSlider, - kDrawDataCheckbox, - kDrawDataTab, - kDrawDataScrollBar, - kDrawDataPopUp, - kDrawDataCaret, - kDrawDataSeparator, + kDDMainDialogBackground, + kDDSpecialColorBackground, + kDDPlainColorBackground, + kDDDefaulBackground, + + kDDButtonIdle, + kDDButtonHover, + + kDDSurface, + + kDDSliderFull, + kDDSliderEmpty, + + kDDCheckboxEnabled, + kDDCheckboxDisabled, + + kDDTab, + + kDDScrollBarBase, + kDDScrollBarHandle, + + kDDPopUp, + kDDCaret, + kDDSeparator, kDrawDataMAX }; @@ -141,7 +155,7 @@ public: /** Widget drawing */ void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0) {} + void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); // {} void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled) {} void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled) {} @@ -149,7 +163,7 @@ public: void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled) {} void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled) {} + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); protected: template void screenInit(); @@ -167,6 +181,12 @@ protected: } } + bool isWidgetCached(DrawData type, const Common::Rect &r); + void drawCached(DrawData type, const Common::Rect &r); + + inline void drawDD(DrawData type, const Common::Rect &r); + void addDirtyRect(const Common::Rect &r) {} + OSystem *_system; Graphics::VectorRenderer *_vectorRenderer; Graphics::Surface *_screen; -- cgit v1.2.3 From 7a9a74691fef580467d93c713c03be613a6d289b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 12 Jun 2008 19:06:37 +0000 Subject: Parser skeleton Expanded drawing interface svn-id: r32678 --- dists/msvc9/scummvm.vcproj | 8 ++++ gui/InterfaceManager.cpp | 34 ++++++++++++++ gui/InterfaceManager.h | 14 +++--- gui/ThemeParser.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++++ gui/ThemeParser.h | 64 ++++++++++++++++++++++++++ gui/module.mk | 1 + 6 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 gui/ThemeParser.cpp create mode 100644 gui/ThemeParser.h diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 5667763fce..a0cc2c6e91 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1204,6 +1204,14 @@ RelativePath="..\..\gui\ThemeModern.cpp" > + + + + diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index e64d292e16..a1eaa71c52 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -123,6 +123,40 @@ void InterfaceManager::drawLineSeparator(const Common::Rect &r, WidgetStateInfo addDirtyRect(r); } +void InterfaceManager::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { + if (!_initOk) + return; + + drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r); + + Common::Rect r2 = r; + r2.left += 16; // TODO: add variable for checkbox text offset. + + // TODO: text drawing +// getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); + + addDirtyRect(r); +} + +void InterfaceManager::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { + if (!_initOk) + return; + + drawDD(kDDSliderEmpty, r); + + Common::Rect r2 = r; + r2.setWidth(MIN((int16)width, r.width())); + + drawDD(kDDSliderFull, r2); + + addDirtyRect(r); +} + +void InterfaceManager::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { + if (!_initOk) + return; +} + int InterfaceManager::runGUI() { Common::EventManager *eventMan = _system->getEventManager(); _system->showOverlay(); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 05f95ee435..7ab3f4c9db 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -73,8 +73,10 @@ public: kDDTab, - kDDScrollBarBase, - kDDScrollBarHandle, + kDDScrollbarBase, + kDDScrollbarButtonTop, + kDDScrollbarButtonBottom, + kDDScrollbarHandle, kDDPopUp, kDDCaret, @@ -155,12 +157,12 @@ public: /** Widget drawing */ void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); // {} + void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled) {} - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled) {} + void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled); + void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled) {} - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled) {} + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled); void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp new file mode 100644 index 0000000000..26745ac5a6 --- /dev/null +++ b/gui/ThemeParser.cpp @@ -0,0 +1,111 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" + +#include "gui/ThemeParser.h" + +/** + + + + + + +*/ + +namespace GUI { + +inline bool isValidNameChar(char c) { + return !isspace(c) && c != '/' && c != '*' && c != '\\' && + c != '|' && c != '"' && c != '\'' && c != ',' && + c != '<' && c != '>' && c != '='; +} + +void ThemeParser::parserError(const char *error_string) { + _state = kParserError; +} + +bool ThemeParser::parseDrawData() { + + _state = kParserNeedKey; + + while (_text[_pos++]) { + + while (isspace(_text[_pos])) + _pos++; + + // comment handling: skip everything between /* and */ + if (_text[_pos] == '/') { + if (_text[++_pos] != '*') { + parserError("Malformed comment string."); + return false; + } + + _pos++; + + while (_text[_pos] != '*' && _text[_pos + 1] != '/') + _pos++; + } + + switch (_state) { + case kParserNeedKey: + if (_text[_pos] != '<') { + parserError("Expecting key start."); + return false; + } + + _state = kParserKeyNeedName; + break; + + case kParserKeyNeedName: + _token.clear(); + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + if (!isspace(_text[_pos])) { + parserError("Invalid character in token name."); + return false; + } + + _state = kParserKeyNeedToken; + break; + + case kParserKeyNeedToken: + _token.clear(); + break; + + default: + return false; + } + } + + return true; +} + +} + diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h new file mode 100644 index 0000000000..c43088c36e --- /dev/null +++ b/gui/ThemeParser.h @@ -0,0 +1,64 @@ +/* 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" + +namespace GUI { + +class ThemeParser { + + ThemeParser() {} + ~ThemeParser() {} + + enum ParserState { + kParserKeyNeedName, + kParserKeyNeedToken, + kParserKeyNeedSubkey, + kParserNeedKey, + kParserInComment, + kParserError + }; + + bool parseDrawData(); + void parserError(const char *error_string); + +protected: + int _pos; + char *_text; + + ParserState _state; + + Common::String _error; + Common::String _token; +}; + +} + +#endif \ No newline at end of file diff --git a/gui/module.mk b/gui/module.mk index be6e405b87..eecf9a093d 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -26,6 +26,7 @@ MODULE_OBJS := \ theme.o \ ThemeClassic.o \ ThemeModern.o \ + ThemeParser.o \ theme-config.o # Include common rules -- cgit v1.2.3 From ace171e22f98f9f9195447893b12fcf4ea79561c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 12 Jun 2008 23:13:58 +0000 Subject: Parser update. svn-id: r32686 --- base/main.cpp | 3 ++ gui/ThemeParser.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++++++------ gui/ThemeParser.h | 17 +++++++- 3 files changed, 124 insertions(+), 15 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 45e0aef728..d0da338e2a 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -43,6 +43,7 @@ #include "gui/newgui.h" #include "gui/message.h" #include "gui/InterfaceManager.h" +#include "gui/ThemeParser.h" #if defined(_WIN32_WCE) #include "backends/platform/wince/CELauncherDialog.h" @@ -70,6 +71,8 @@ static bool launcherDialog(OSystem &system) { #if 1 + GUI::ThemeParser parser; + parser.debug_testEval(); g_InterfaceManager.runGUI(); return true; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 26745ac5a6..73086e942c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -26,6 +26,8 @@ #include "common/util.h" #include "common/system.h" #include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" #include "gui/ThemeParser.h" @@ -46,39 +48,104 @@ inline bool isValidNameChar(char c) { c != '<' && c != '>' && c != '='; } +void ThemeParser::debug_testEval() { + static const char *debug_config_text = + "" + "" + "/**/" + "/* lol this is just a simple test*/"; + + _text = strdup(debug_config_text); + parseDrawData(); +} + + void ThemeParser::parserError(const char *error_string) { _state = kParserError; + printf("PARSER ERROR: %s\n", error_string); +} + +void ThemeParser::parseActiveKey(bool closed) { + printf("Parsed key %s.\n", _activeKey.top().c_str()); + + for (Common::StringMap::const_iterator t = _keyValues.begin(); t != _keyValues.end(); ++t) + printf(" Key %s = %s\n", t->_key.c_str(), t->_value.c_str()); + + if (closed) + _activeKey.pop(); + + _keyValues.clear(); +} + +void ThemeParser::parseKeyValue(Common::String &key_name) { + assert(_text[_pos++] == '='); + + while (isspace(_text[_pos])) + _pos++; + + Common::String data; + + if (_text[_pos] == '"') { + data += _text[_pos++]; + + while (_text[_pos] != '"') + data += _text[_pos++]; + + data += _text[_pos++]; + } else { + while (isValidNameChar(_text[_pos])) + data += _text[_pos++]; + } + + _keyValues[key_name] = data; } bool ThemeParser::parseDrawData() { _state = kParserNeedKey; + _pos = 0; + _keyValues.clear(); - while (_text[_pos++]) { - + while (_text[_pos]) { while (isspace(_text[_pos])) _pos++; // comment handling: skip everything between /* and */ - if (_text[_pos] == '/') { - if (_text[++_pos] != '*') { - parserError("Malformed comment string."); - return false; + if (_text[_pos] == '/' && _text[_pos + 1] == '*') { + _pos += 2; + while (_text[_pos++]) { + if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') + break; } - - _pos++; - - while (_text[_pos] != '*' && _text[_pos + 1] != '/') - _pos++; + continue; } switch (_state) { case kParserNeedKey: - if (_text[_pos] != '<') { + if (_text[_pos++] != '<') { parserError("Expecting key start."); return false; } + if (_text[_pos] == '/') { + _pos++; + _token.clear(); + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + if (_token == _activeKey.top()) { + _activeKey.pop(); + + while (isspace(_text[_pos]) || _text[_pos] == '>') + _pos++; + + break; + } else { + parserError("Unexpected closure."); + return false; + } + } + _state = kParserKeyNeedName; break; @@ -87,16 +154,38 @@ bool ThemeParser::parseDrawData() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - if (!isspace(_text[_pos])) { + if (!isspace(_text[_pos]) && _text[_pos] != '>') { parserError("Invalid character in token name."); return false; } _state = kParserKeyNeedToken; + _activeKey.push(_token); break; case kParserKeyNeedToken: _token.clear(); + + if ((_text[_pos] == '/' && _text[_pos + 1] == '>') || _text[_pos] == '>') { + bool closed = _text[_pos] == '/'; + parseActiveKey(closed); + _pos += closed ? 2 : 1; + _state = kParserNeedKey; + break; + } + + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + while (isspace(_text[_pos])) + _pos++; + + if (_text[_pos] != '=') { + parserError("Unexpected character after key name."); + return false; + } + + parseKeyValue(_token); break; default: @@ -104,6 +193,10 @@ bool ThemeParser::parseDrawData() { } } + if (_state != kParserNeedKey || !_activeKey.empty()) { + parserError("Unexpected end of file."); + } + return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c43088c36e..527d911620 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -30,10 +30,15 @@ #include "graphics/surface.h" #include "common/system.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/stack.h" + namespace GUI { class ThemeParser { +public: ThemeParser() {} ~ThemeParser() {} @@ -43,11 +48,16 @@ class ThemeParser { kParserKeyNeedSubkey, kParserNeedKey, kParserInComment, - kParserError + kParserError, + kParserSuccess }; bool parseDrawData(); + void parseKeyValue(Common::String &key_name); + void parseActiveKey(bool closed); void parserError(const char *error_string); + + void debug_testEval(); protected: int _pos; @@ -57,8 +67,11 @@ protected: Common::String _error; Common::String _token; + + Common::FixedStack _activeKey; + Common::StringMap _keyValues; }; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From e0d7301cb04a99927091fdf51cec2d88fb68ad52 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 13 Jun 2008 09:24:41 +0000 Subject: Parser update. Variable depth. svn-id: r32690 --- gui/ThemeParser.cpp | 64 +++++++++++++++++++++++++++++++++++++++-------------- gui/ThemeParser.h | 21 ++++++++++++++---- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 73086e942c..c75340ada2 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -43,20 +43,18 @@ namespace GUI { inline bool isValidNameChar(char c) { - return !isspace(c) && c != '/' && c != '*' && c != '\\' && - c != '|' && c != '"' && c != '\'' && c != ',' && - c != '<' && c != '>' && c != '='; + return isalnum(c) || c == '_'; } void ThemeParser::debug_testEval() { static const char *debug_config_text = "" "" - "/**/" + "" "/* lol this is just a simple test*/"; _text = strdup(debug_config_text); - parseDrawData(); + parse(); } @@ -65,20 +63,42 @@ void ThemeParser::parserError(const char *error_string) { printf("PARSER ERROR: %s\n", error_string); } +void ThemeParser::parserCallback_DRAW() { + printf("Draw callback!\n"); +} + +void ThemeParser::parserCallback_DRAWDATA() { + printf("Drawdata callback!\n"); +} + void ThemeParser::parseActiveKey(bool closed) { printf("Parsed key %s.\n", _activeKey.top().c_str()); - for (Common::StringMap::const_iterator t = _keyValues.begin(); t != _keyValues.end(); ++t) + if (!_callbacks.contains(_activeKey.top())) { + parserError("Unhandled value inside key."); + return; + } + + // Don't you just love C++ syntax? Water clear. + (this->*(_callbacks[_activeKey.top()]))(); + + for (Common::StringMap::const_iterator t = _keyValues.top().begin(); t != _keyValues.top().end(); ++t) printf(" Key %s = %s\n", t->_key.c_str(), t->_value.c_str()); - if (closed) + if (closed) { + _keyValues.pop(); _activeKey.pop(); - - _keyValues.clear(); + } } void ThemeParser::parseKeyValue(Common::String &key_name) { assert(_text[_pos++] == '='); + assert(_keyValues.empty() == false); + + if (_keyValues.top().contains(key_name)) { + parserError("Repeated value inside key."); + return; + } while (isspace(_text[_pos])) _pos++; @@ -97,16 +117,20 @@ void ThemeParser::parseKeyValue(Common::String &key_name) { data += _text[_pos++]; } - _keyValues[key_name] = data; + _keyValues.top()[key_name] = data; } -bool ThemeParser::parseDrawData() { +bool ThemeParser::parse() { _state = kParserNeedKey; _pos = 0; _keyValues.clear(); + _activeKey.clear(); while (_text[_pos]) { + if (_state == kParserError) + break; + while (isspace(_text[_pos])) _pos++; @@ -124,7 +148,7 @@ bool ThemeParser::parseDrawData() { case kParserNeedKey: if (_text[_pos++] != '<') { parserError("Expecting key start."); - return false; + break; } if (_text[_pos] == '/') { @@ -133,8 +157,9 @@ bool ThemeParser::parseDrawData() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - if (_token == _activeKey.top()) { + if (!_activeKey.empty() && _token == _activeKey.top()) { _activeKey.pop(); + _keyValues.pop(); while (isspace(_text[_pos]) || _text[_pos] == '>') _pos++; @@ -142,10 +167,11 @@ bool ThemeParser::parseDrawData() { break; } else { parserError("Unexpected closure."); - return false; + break; } } + _keyValues.push(Common::StringMap()); _state = kParserKeyNeedName; break; @@ -156,7 +182,7 @@ bool ThemeParser::parseDrawData() { if (!isspace(_text[_pos]) && _text[_pos] != '>') { parserError("Invalid character in token name."); - return false; + break; } _state = kParserKeyNeedToken; @@ -182,17 +208,21 @@ bool ThemeParser::parseDrawData() { if (_text[_pos] != '=') { parserError("Unexpected character after key name."); - return false; + break; } parseKeyValue(_token); break; default: - return false; + break; } } + if (_state == kParserError) { + return false; + } + if (_state != kParserNeedKey || !_activeKey.empty()) { parserError("Unexpected end of file."); } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 527d911620..22ad50a333 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -38,8 +38,15 @@ namespace GUI { class ThemeParser { + static const int PARSER_MAX_DEPTH = 4; + typedef void (ThemeParser::*PARSER_CALLBACK)(); + public: - ThemeParser() {} + ThemeParser() { + _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; + _callbacks["draw"] = &ThemeParser::parserCallback_DRAW; + } + ~ThemeParser() {} enum ParserState { @@ -52,14 +59,18 @@ public: kParserSuccess }; - bool parseDrawData(); + bool parse(); void parseKeyValue(Common::String &key_name); void parseActiveKey(bool closed); + void parserError(const char *error_string); void debug_testEval(); protected: + void parserCallback_DRAW(); + void parserCallback_DRAWDATA(); + int _pos; char *_text; @@ -68,8 +79,10 @@ protected: Common::String _error; Common::String _token; - Common::FixedStack _activeKey; - Common::StringMap _keyValues; + Common::FixedStack _activeKey; + Common::FixedStack _keyValues; + + Common::HashMap _callbacks; }; } -- cgit v1.2.3 From 5d92e2710a85f998f1f7bfbf4705880921d904e7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 13 Jun 2008 09:39:13 +0000 Subject: Parser cleanup. svn-id: r32691 --- gui/ThemeParser.cpp | 43 ++++++++++++++++--------------------------- gui/ThemeParser.h | 25 +++++++++++++++++++------ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index c75340ada2..fc960ca4d7 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -100,8 +100,7 @@ void ThemeParser::parseKeyValue(Common::String &key_name) { return; } - while (isspace(_text[_pos])) - _pos++; + skipSpaces(); Common::String data; @@ -131,18 +130,8 @@ bool ThemeParser::parse() { if (_state == kParserError) break; - while (isspace(_text[_pos])) - _pos++; - - // comment handling: skip everything between /* and */ - if (_text[_pos] == '/' && _text[_pos + 1] == '*') { - _pos += 2; - while (_text[_pos++]) { - if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') - break; - } - continue; - } + skipSpaces(); + skipComments(); switch (_state) { case kParserNeedKey: @@ -157,25 +146,26 @@ bool ThemeParser::parse() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - if (!_activeKey.empty() && _token == _activeKey.top()) { + if (_activeKey.empty() || _token != _activeKey.top()) + parserError("Unexpected closure."); + else { _activeKey.pop(); _keyValues.pop(); - while (isspace(_text[_pos]) || _text[_pos] == '>') - _pos++; + skipSpaces(); - break; - } else { - parserError("Unexpected closure."); - break; + if (_text[_pos++] != '>') + parserError("Malformed tag closure."); } + + break; } _keyValues.push(Common::StringMap()); - _state = kParserKeyNeedName; + _state = kParserNeedKeyName; break; - case kParserKeyNeedName: + case kParserNeedKeyName: _token.clear(); while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; @@ -185,11 +175,11 @@ bool ThemeParser::parse() { break; } - _state = kParserKeyNeedToken; + _state = kParserNeedKeyValues; _activeKey.push(_token); break; - case kParserKeyNeedToken: + case kParserNeedKeyValues: _token.clear(); if ((_text[_pos] == '/' && _text[_pos + 1] == '>') || _text[_pos] == '>') { @@ -203,8 +193,7 @@ bool ThemeParser::parse() { while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - while (isspace(_text[_pos])) - _pos++; + skipSpaces(); if (_text[_pos] != '=') { parserError("Unexpected character after key name."); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 22ad50a333..f87708e3f2 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -50,13 +50,10 @@ public: ~ThemeParser() {} enum ParserState { - kParserKeyNeedName, - kParserKeyNeedToken, - kParserKeyNeedSubkey, kParserNeedKey, - kParserInComment, - kParserError, - kParserSuccess + kParserNeedKeyName, + kParserNeedKeyValues, + kParserError }; bool parse(); @@ -71,6 +68,22 @@ protected: void parserCallback_DRAW(); void parserCallback_DRAWDATA(); + inline void skipSpaces() { + while (isspace(_text[_pos])) + _pos++; + } + + inline void skipComments() { + if (_text[_pos] == '/' && _text[_pos + 1] == '*') { + _pos += 2; + while (_text[_pos++]) { + if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') + break; + } + skipSpaces(); + } + } + int _pos; char *_text; -- cgit v1.2.3 From 04b36a12e17252aa3f27392b334b053406847d8f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 13 Jun 2008 17:47:56 +0000 Subject: Formating conventions. Function parameter fixes. Parser fixes. svn-id: r32696 --- graphics/VectorRenderer.cpp | 40 +++++++++--------- graphics/VectorRenderer.h | 99 ++++++++++++++++++++++----------------------- gui/InterfaceManager.cpp | 8 ++-- gui/ThemeParser.cpp | 13 +++--- gui/ThemeParser.h | 15 +++---- 5 files changed, 88 insertions(+), 87 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 2c50ddd0ec..abfd53edcd 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -51,39 +51,39 @@ VectorRenderer *createRenderer(int mode) { /******************************************************************** * DRAWSTEP handling functions ********************************************************************/ -void VectorRenderer::drawStep(Common::Rect area, DrawStep *step) { +void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { - if (step->flags & DrawStep::kStepCallbackOnly) { - (this->*(step->drawing_call))(&area, step); + if (step.flags & DrawStep::kStepCallbackOnly) { + (this->*(step.drawing_call))(area, step); return; } - if (step->flags & DrawStep::kStepSetBG) - setBgColor(step->color2.r, step->color2.g, step->color2.b); + if (step.flags & DrawStep::kStepSetBG) + setBgColor(step.color2.r, step.color2.g, step.color2.b); - if (step->flags & DrawStep::kStepSetFG) - setFgColor(step->color1.r, step->color1.g, step->color1.b); + if (step.flags & DrawStep::kStepSetFG) + setFgColor(step.color1.r, step.color1.g, step.color1.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); + if (step.flags & DrawStep::kStepSetGradient) + setGradientColors(step.color1.r, step.color1.g, step.color1.b, + step.color2.r, step.color2.g, step.color2.b); - if (step->flags & DrawStep::kStepSetShadow) - shadowEnable(step->shadow); + if (step.flags & DrawStep::kStepSetShadow) + shadowEnable(step.shadow); - if (step->flags & DrawStep::kStepSetGradientFactor) - setGradientFactor(step->factor); + if (step.flags & DrawStep::kStepSetGradientFactor) + setGradientFactor(step.factor); - if (step->flags & DrawStep::kStepSetStroke) - setStrokeWidth(step->stroke); + if (step.flags & DrawStep::kStepSetStroke) + setStrokeWidth(step.stroke); - if (step->flags & DrawStep::kStepSetFillMode) - setFillMode((FillMode)step->fill_mode); + if (step.flags & DrawStep::kStepSetFillMode) + setFillMode((FillMode)step.fill_mode); - if (step->flags & DrawStep::kStepSettingsOnly) + if (step.flags & DrawStep::kStepSettingsOnly) return; - (this->*(step->drawing_call))(&area, step); + (this->*(step.drawing_call))(area, step); } /******************************************************************** diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 918ed1c39e..310f32f856 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -37,6 +37,7 @@ namespace Graphics { class VectorRenderer; +struct DrawStep; struct DrawStep { uint32 flags; /** Step flags, see DrawStepFlags */ @@ -64,7 +65,7 @@ struct DrawStep { uint32 scale; /** scale of all the coordinates in FIXED POINT with 16 bits mantissa */ - void (VectorRenderer::*drawing_call)(Common::Rect*, DrawStep*); /** Pointer to drawing function */ + void (VectorRenderer::*drawing_call)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ enum DrawStepFlags { kStepCallbackOnly = (1 << 0), @@ -77,38 +78,6 @@ struct DrawStep { kStepSetStroke = (1 << 7), kStepSetFillMode = (1 << 8) }; - - void getPositions(Common::Rect *area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { - if (fill_area) { - in_x = area->left; - in_y = area->top; - in_w = area->width(); - in_h = area->height(); - } else { - if (!x.relative) in_x = area->left + x.pos; - else in_x = area->left + area->width() - x.pos; - - if (!y.relative) in_y = area->top + y.pos; - else in_y = area->top + area->height() - y.pos; - - if (in_x + w > area->right) in_w = area->right - in_x; - else in_w = w; - - if (in_y + h > area->bottom) in_h = area->bottom - in_y; - else in_h = h; - } - - if (scale != (1 << 16) && scale != 0) { - in_x = (in_x * scale) >> 16; - in_y = (in_y * scale) >> 16; - in_w = (in_w * scale) >> 16; - in_h = (in_h * scale) >> 16; - } - } - - uint8 getRadius() { - return (((uint32)radius * scale) >> 16); - } }; VectorRenderer *createRenderer(int mode); @@ -360,48 +329,76 @@ public: _gradientFactor = factor; } + 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) { + in_x = area.left; + in_y = area.top; + in_w = area.width(); + in_h = area.height(); + } else { + if (!step.x.relative) in_x = area.left + step.x.pos; + else in_x = area.left + area.width() - step.x.pos; + + if (!step.y.relative) in_y = area.top + step.y.pos; + else in_y = area.top + area.height() - step.y.pos; + + if (in_x + step.w > area.right) in_w = area.right - in_x; + else in_w = step.w; + + if (in_y + step.h > area.bottom) in_h = area.bottom - in_y; + else in_h = step.h; + } + + if (step.scale != (1 << 16) && step.scale != 0) { + in_x = (in_x * step.scale) >> 16; + in_y = (in_y * step.scale) >> 16; + in_w = (in_w * step.scale) >> 16; + in_h = (in_h * step.scale) >> 16; + } + } + /** * DrawStep callback functions for each drawing feature */ - void drawCallback_CIRCLE(Common::Rect *area, DrawStep *step) { + void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); - drawCircle(x, y, step->getRadius()); + stepGetPositions(step, area, x, y, w, h); + drawCircle(x, y, (step.radius * step.scale) >> 16); } - void drawCallback_SQUARE(Common::Rect *area, DrawStep *step) { + void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); + stepGetPositions(step, area, x, y, w, h); drawSquare(x, y, w, h); } - void drawCallback_LINE(Common::Rect *area, DrawStep *step) { + void drawCallback_LINE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); + stepGetPositions(step, area, x, y, w, h); drawLine(x, y, x + w, y + w); } - void drawCallback_ROUNDSQ(Common::Rect *area, DrawStep *step) { + void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); + stepGetPositions(step, area, x, y, w, h); /* HACK! Radius of the rounded squares isn't scaled */ - drawRoundedSquare(x, y, step->radius, w, h); + drawRoundedSquare(x, y, step.radius, w, h); } - void drawCallback_FILLSURFACE(Common::Rect *area, DrawStep *step) { + void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step) { fillSurface(); } - void drawCallback_TRIANGLE(Common::Rect *area, DrawStep *step) { + void drawCallback_TRIANGLE(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); - drawTriangle(x, y, w, h, (TriangleOrientation)step->extra_data); + stepGetPositions(step, area, x, y, w, h); + drawTriangle(x, y, w, h, (TriangleOrientation)step.extra_data); } - void drawCallback_BEVELSQ(Common::Rect *area, DrawStep *step) { + void drawCallback_BEVELSQ(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; - step->getPositions(area, x, y, w, h); - drawBeveledSquare(x, y, w, h, step->extra_data); + stepGetPositions(step, area, x, y, w, h); + drawBeveledSquare(x, y, w, h, step.extra_data); } /** @@ -411,7 +408,7 @@ public: * @param area Zone to paint on * @param step Pointer to a DrawStep struct. */ - virtual void drawStep(Common::Rect area, DrawStep *step); + virtual void drawStep(const Common::Rect &area, const DrawStep &step); /** * Copies the current surface to the system overlay diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index a1eaa71c52..f0874393f0 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -97,7 +97,7 @@ void InterfaceManager::drawDD(DrawData type, const Common::Rect &r) { drawCached(type, r); } else { for (int i = 0; i < _widgets[type]->_stepCount; ++i) - _vectorRenderer->drawStep(r, _widgets[type]->_steps[i]); + _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); } } @@ -205,9 +205,9 @@ int InterfaceManager::runGUI() { bool running = true; while (running) { // draw!! - _vectorRenderer->drawStep(Common::Rect(), &steps[0]); - _vectorRenderer->drawStep(area, &steps[1]); - _vectorRenderer->drawStep(area, &steps[2]); + _vectorRenderer->drawStep(Common::Rect(), steps[0]); + _vectorRenderer->drawStep(area, steps[1]); + _vectorRenderer->drawStep(area, steps[2]); // _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[3]); _vectorRenderer->copyFrame(_system); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index fc960ca4d7..cd77b4a5e1 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -103,14 +103,15 @@ void ThemeParser::parseKeyValue(Common::String &key_name) { skipSpaces(); Common::String data; + char string_start; - if (_text[_pos] == '"') { - data += _text[_pos++]; + if (_text[_pos] == '"' || _text[_pos] == '\'') { + string_start = _text[_pos++]; - while (_text[_pos] != '"') + while (_text[_pos] != string_start) data += _text[_pos++]; - data += _text[_pos++]; + _pos++; } else { while (isValidNameChar(_text[_pos])) data += _text[_pos++]; @@ -131,7 +132,9 @@ bool ThemeParser::parse() { break; skipSpaces(); - skipComments(); + + if (skipComments()) + continue; switch (_state) { case kParserNeedKey: diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index f87708e3f2..762baefd7f 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -38,8 +38,8 @@ namespace GUI { class ThemeParser { - static const int PARSER_MAX_DEPTH = 4; - typedef void (ThemeParser::*PARSER_CALLBACK)(); + static const int kParserMaxDepth = 4; + typedef void (ThemeParser::*ParserCallback)(); public: ThemeParser() { @@ -73,15 +73,16 @@ protected: _pos++; } - inline void skipComments() { + inline bool skipComments() { if (_text[_pos] == '/' && _text[_pos + 1] == '*') { _pos += 2; while (_text[_pos++]) { if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') break; } - skipSpaces(); + return true; } + return false; } int _pos; @@ -92,10 +93,10 @@ protected: Common::String _error; Common::String _token; - Common::FixedStack _activeKey; - Common::FixedStack _keyValues; + Common::FixedStack _activeKey; + Common::FixedStack _keyValues; - Common::HashMap _callbacks; + Common::HashMap _callbacks; }; } -- cgit v1.2.3 From d51a0cab3fe494698f001d81d5d86cea7cd0395b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 13 Jun 2008 22:05:21 +0000 Subject: Parser redesign. Fixed most possible overflows. svn-id: r32697 --- gui/ThemeParser.cpp | 127 +++++++++++++++++++++++++--------------------------- gui/ThemeParser.h | 36 +++++++++++---- 2 files changed, 88 insertions(+), 75 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index cd77b4a5e1..260e3911a1 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -42,15 +42,11 @@ namespace GUI { -inline bool isValidNameChar(char c) { - return isalnum(c) || c == '_'; -} - void ThemeParser::debug_testEval() { static const char *debug_config_text = "" "" - "" + "" "/* lol this is just a simple test*/"; _text = strdup(debug_config_text); @@ -91,37 +87,38 @@ void ThemeParser::parseActiveKey(bool closed) { } } -void ThemeParser::parseKeyValue(Common::String &key_name) { - assert(_text[_pos++] == '='); +bool ThemeParser::parseKeyValue(Common::String &key_name) { assert(_keyValues.empty() == false); - if (_keyValues.top().contains(key_name)) { - parserError("Repeated value inside key."); - return; - } - - skipSpaces(); + if (_keyValues.top().contains(key_name)) + return false; - Common::String data; + Common::String name = key_name; + _token.clear(); char string_start; if (_text[_pos] == '"' || _text[_pos] == '\'') { string_start = _text[_pos++]; - while (_text[_pos] != string_start) - data += _text[_pos++]; + while (_text[_pos] && _text[_pos] != string_start) + _token += _text[_pos++]; - _pos++; - } else { - while (isValidNameChar(_text[_pos])) - data += _text[_pos++]; + if (_text[_pos++] == 0) + return false; + + } else if (!parseToken()) { + return false; } - _keyValues.top()[key_name] = data; + _keyValues.top()[name] = _token; + return true; } bool ThemeParser::parse() { + bool active_closure = false; + bool self_closure = false; + _state = kParserNeedKey; _pos = 0; _keyValues.clear(); @@ -131,79 +128,74 @@ bool ThemeParser::parse() { if (_state == kParserError) break; - skipSpaces(); + if (skipSpaces()) + continue; if (skipComments()) continue; switch (_state) { case kParserNeedKey: - if (_text[_pos++] != '<') { - parserError("Expecting key start."); - break; - } + if (_text[_pos++] != '<') parserError("Expecting key start."); + else _state = kParserNeedKeyName; + break; + case kParserNeedKeyName: if (_text[_pos] == '/') { _pos++; - _token.clear(); - while (isValidNameChar(_text[_pos])) - _token += _text[_pos++]; + active_closure = true; + } + + if (!parseToken()) { + parserError("Unexpected end of file while parsing token."); + break; + } + if (active_closure) { if (_activeKey.empty() || _token != _activeKey.top()) parserError("Unexpected closure."); - else { - _activeKey.pop(); - _keyValues.pop(); - - skipSpaces(); - - if (_text[_pos++] != '>') - parserError("Malformed tag closure."); - } - - break; + } else { + _keyValues.push(Common::StringMap()); + _activeKey.push(_token); } - _keyValues.push(Common::StringMap()); - _state = kParserNeedKeyName; + _state = kParserNeedPropertyName; break; - case kParserNeedKeyName: - _token.clear(); - while (isValidNameChar(_text[_pos])) - _token += _text[_pos++]; + case kParserNeedPropertyName: + if (active_closure) { + active_closure = false; + _activeKey.pop(); + _keyValues.pop(); - if (!isspace(_text[_pos]) && _text[_pos] != '>') { - parserError("Invalid character in token name."); + if (_text[_pos++] != '>') + parserError("Invalid syntax in key closure."); + + _state = kParserNeedKey; break; } - _state = kParserNeedKeyValues; - _activeKey.push(_token); - break; - - case kParserNeedKeyValues: - _token.clear(); + self_closure = (_text[_pos] == '/'); - if ((_text[_pos] == '/' && _text[_pos + 1] == '>') || _text[_pos] == '>') { - bool closed = _text[_pos] == '/'; - parseActiveKey(closed); - _pos += closed ? 2 : 1; + if ((self_closure && _text[_pos + 1] == '>') || _text[_pos] == '>') { + parseActiveKey(self_closure); + _pos += self_closure ? 2 : 1; _state = kParserNeedKey; break; } - while (isValidNameChar(_text[_pos])) - _token += _text[_pos++]; - - skipSpaces(); + if (!parseToken()) parserError("Error when parsing key value."); + else _state = kParserNeedPropertyOperator; + break; - if (_text[_pos] != '=') { - parserError("Unexpected character after key name."); - break; - } + case kParserNeedPropertyOperator: + if (_text[_pos++] != '=') parserError("Unexpected character after key name."); + else _state = kParserNeedPropertyValue; + break; - parseKeyValue(_token); + case kParserNeedPropertyValue: + if (!parseKeyValue(_token)) parserError("Unable to parse key value."); + else _state = kParserNeedPropertyName; break; default: @@ -217,6 +209,7 @@ bool ThemeParser::parse() { if (_state != kParserNeedKey || !_activeKey.empty()) { parserError("Unexpected end of file."); + return false; } return true; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 762baefd7f..df99893d58 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -52,25 +52,33 @@ public: enum ParserState { kParserNeedKey, kParserNeedKeyName, - kParserNeedKeyValues, + + kParserNeedPropertyName, + kParserNeedPropertyOperator, + kParserNeedPropertyValue, + kParserError }; bool parse(); - void parseKeyValue(Common::String &key_name); - void parseActiveKey(bool closed); - - void parserError(const char *error_string); - void debug_testEval(); protected: void parserCallback_DRAW(); void parserCallback_DRAWDATA(); - inline void skipSpaces() { - while (isspace(_text[_pos])) + bool parseKeyValue(Common::String &key_name); + void parseActiveKey(bool closed); + void parserError(const char *error_string); + + inline bool skipSpaces() { + if (!isspace(_text[_pos])) + return false; + + while (_text[_pos] && isspace(_text[_pos])) _pos++; + + return true; } inline bool skipComments() { @@ -85,6 +93,18 @@ protected: return false; } + inline bool isValidNameChar(char c) { + return isalnum(c) || c == '_'; + } + + inline bool parseToken() { + _token.clear(); + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + return (_text[_pos] != 0); + } + int _pos; char *_text; -- cgit v1.2.3 From 8e2601d1954a758f535181ca418a2309dc58f8e4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 14 Jun 2008 16:14:50 +0000 Subject: Parser fixes. svn-id: r32703 --- gui/ThemeParser.cpp | 49 ++++++++++++++++++++++++++++++------------------- gui/ThemeParser.h | 2 +- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 260e3911a1..bac7565773 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -44,10 +44,10 @@ namespace GUI { void ThemeParser::debug_testEval() { static const char *debug_config_text = - "" + "" "" "" - "/* lol this is just a simple test*/"; + "/* lol this is just a simple test*/"; _text = strdup(debug_config_text); parse(); @@ -136,18 +136,22 @@ bool ThemeParser::parse() { switch (_state) { case kParserNeedKey: - if (_text[_pos++] != '<') parserError("Expecting key start."); - else _state = kParserNeedKeyName; - break; + if (_text[_pos++] != '<' || _text[_pos] == 0) { + parserError("Expecting key start."); + break; + } - case kParserNeedKeyName: - if (_text[_pos] == '/') { + if (_text[_pos] == '/' && _text[_pos + 1] != '*') { _pos++; active_closure = true; } - + + _state = kParserNeedKeyName; + break; + + case kParserNeedKeyName: if (!parseToken()) { - parserError("Unexpected end of file while parsing token."); + parserError("Invalid key name."); break; } @@ -170,8 +174,9 @@ bool ThemeParser::parse() { if (_text[_pos++] != '>') parserError("Invalid syntax in key closure."); - - _state = kParserNeedKey; + else + _state = kParserNeedKey; + break; } @@ -184,21 +189,27 @@ bool ThemeParser::parse() { break; } - if (!parseToken()) parserError("Error when parsing key value."); - else _state = kParserNeedPropertyOperator; + if (!parseToken()) + parserError("Error when parsing key value."); + else + _state = kParserNeedPropertyOperator; + break; case kParserNeedPropertyOperator: - if (_text[_pos++] != '=') parserError("Unexpected character after key name."); - else _state = kParserNeedPropertyValue; + if (_text[_pos++] != '=') + parserError("Unexpected character after key name."); + else + _state = kParserNeedPropertyValue; + break; case kParserNeedPropertyValue: - if (!parseKeyValue(_token)) parserError("Unable to parse key value."); - else _state = kParserNeedPropertyName; - break; + if (!parseKeyValue(_token)) + parserError("Unable to parse key value."); + else + _state = kParserNeedPropertyName; - default: break; } } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index df99893d58..0ddc111af5 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -102,7 +102,7 @@ protected: while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - return (_text[_pos] != 0); + return isspace(_text[_pos]) != 0 || _text[_pos] == '>'; } int _pos; -- cgit v1.2.3 From cb6cb1361b742ae274c5cd6584ad69b0f3d61db8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 14 Jun 2008 17:45:26 +0000 Subject: Code formating conventions. Fix in test drawing code. svn-id: r32704 --- gui/InterfaceManager.cpp | 7 +++++-- gui/ThemeParser.cpp | 44 ++++++++++++++++++++++++-------------------- gui/ThemeParser.h | 4 ++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index f0874393f0..380f1d4644 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -197,8 +197,10 @@ int InterfaceManager::runGUI() { steps[2].flags = DrawStep::kStepCallbackOnly; steps[2].scale = (1 << 16); - steps[3].drawing_call = &VectorRenderer::drawCallback_ROUNDSQ; - steps[3].flags = DrawStep::kStepCallbackOnly; + steps[3].color1.r = 255; + steps[3].color1.g = 255; + steps[3].color1.b = 255; + steps[3].flags = DrawStep::kStepSettingsOnly | DrawStep::kStepSetFG; Common::Rect area = Common::Rect(32, 32, 256, 256); @@ -206,6 +208,7 @@ int InterfaceManager::runGUI() { while (running) { // draw!! _vectorRenderer->drawStep(Common::Rect(), steps[0]); + _vectorRenderer->drawStep(Common::Rect(), steps[3]); _vectorRenderer->drawStep(area, steps[1]); _vectorRenderer->drawStep(area, steps[2]); // _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[3]); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index bac7565773..498679c88f 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -43,13 +43,13 @@ namespace GUI { void ThemeParser::debug_testEval() { - static const char *debug_config_text = + static const char *debugConfigText = "" "" "" "/* lol this is just a simple test*/"; - _text = strdup(debug_config_text); + _text = strdup(debugConfigText); parse(); } @@ -87,20 +87,19 @@ void ThemeParser::parseActiveKey(bool closed) { } } -bool ThemeParser::parseKeyValue(Common::String &key_name) { +bool ThemeParser::parseKeyValue(Common::String keyName) { assert(_keyValues.empty() == false); - if (_keyValues.top().contains(key_name)) + if (_keyValues.top().contains(keyName)) return false; - Common::String name = key_name; _token.clear(); - char string_start; + char stringStart; if (_text[_pos] == '"' || _text[_pos] == '\'') { - string_start = _text[_pos++]; + stringStart = _text[_pos++]; - while (_text[_pos] && _text[_pos] != string_start) + while (_text[_pos] && _text[_pos] != stringStart) _token += _text[_pos++]; if (_text[_pos++] == 0) @@ -110,14 +109,14 @@ bool ThemeParser::parseKeyValue(Common::String &key_name) { return false; } - _keyValues.top()[name] = _token; + _keyValues.top()[keyName] = _token; return true; } bool ThemeParser::parse() { - bool active_closure = false; - bool self_closure = false; + bool activeClosure = false; + bool selfClosure = false; _state = kParserNeedKey; _pos = 0; @@ -136,14 +135,19 @@ bool ThemeParser::parse() { switch (_state) { case kParserNeedKey: - if (_text[_pos++] != '<' || _text[_pos] == 0) { + if (_text[_pos++] != '<') { parserError("Expecting key start."); break; } + if (_text[_pos] == 0) { + parserError("Unexpected end of file."); + break; + } + if (_text[_pos] == '/' && _text[_pos + 1] != '*') { _pos++; - active_closure = true; + activeClosure = true; } _state = kParserNeedKeyName; @@ -155,7 +159,7 @@ bool ThemeParser::parse() { break; } - if (active_closure) { + if (activeClosure) { if (_activeKey.empty() || _token != _activeKey.top()) parserError("Unexpected closure."); } else { @@ -167,8 +171,8 @@ bool ThemeParser::parse() { break; case kParserNeedPropertyName: - if (active_closure) { - active_closure = false; + if (activeClosure) { + activeClosure = false; _activeKey.pop(); _keyValues.pop(); @@ -180,11 +184,11 @@ bool ThemeParser::parse() { break; } - self_closure = (_text[_pos] == '/'); + selfClosure = (_text[_pos] == '/'); - if ((self_closure && _text[_pos + 1] == '>') || _text[_pos] == '>') { - parseActiveKey(self_closure); - _pos += self_closure ? 2 : 1; + if ((selfClosure && _text[_pos + 1] == '>') || _text[_pos] == '>') { + parseActiveKey(selfClosure); + _pos += selfClosure ? 2 : 1; _state = kParserNeedKey; break; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 0ddc111af5..334677fd39 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -67,9 +67,9 @@ protected: void parserCallback_DRAW(); void parserCallback_DRAWDATA(); - bool parseKeyValue(Common::String &key_name); + bool parseKeyValue(Common::String keyName); void parseActiveKey(bool closed); - void parserError(const char *error_string); + void parserError(const char *errorString); inline bool skipSpaces() { if (!isspace(_text[_pos])) -- cgit v1.2.3 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 From 42036e7fd332a25cb902a220aa020e82cb0794ef Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 18 Jun 2008 00:15:21 +0000 Subject: Expanded parser. Added regex support for Common::String Changed drawstep state saving. svn-id: r32729 --- common/str.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++ common/str.h | 17 ++++++++ graphics/VectorRenderer.cpp | 29 ++++--------- graphics/VectorRenderer.h | 19 ++------- gui/InterfaceManager.cpp | 12 +++--- gui/InterfaceManager.h | 9 ++++- gui/ThemeParser.cpp | 66 ++++++++++++++++++++++++++++-- gui/ThemeParser.h | 9 +++++ 8 files changed, 213 insertions(+), 47 deletions(-) diff --git a/common/str.cpp b/common/str.cpp index ad48ef6087..e849cb042d 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -283,6 +283,105 @@ void String::toUppercase() { _str[i] = toupper(_str[i]); } +bool String::regexMatch(const char *regex, bool skipSpaces) { + int pos = 0; + + if (regex[0] == '^') + return regexMatchPos(1, regex, 1, skipSpaces); + + do { + if (regexMatchPos(pos, regex, 0, skipSpaces)) + return true; + } while (_str[pos++]); + + return false; +} + +bool String::regexMatchCharacter(RegexMatchType type, char regexChar, char strChar) { + switch (type) { + case kRegexMatchAny: + return true; + + case kRegexMatchDigit: + return isdigit(strChar) != 0; + + case kRegexMatchSpace: + return isspace(strChar) != 0; + + case kRegexMatchAlphanum: + return isalnum(strChar) != 0; + + case kRegexMatchAlpha: + return isalpha(strChar) != 0; + + case kRegexMatchWord: + return isalnum(strChar) != 0 || strChar == '_'; + + case kRegexMatchCharacter: + return regexChar == strChar; + + default: + return false; + } +} + +bool String::regexMatchStar(RegexMatchType type, char regexChar, const char *regex, int regexPos, int strPos, bool skipSpaces) { + + do { + if (regexMatchPos(strPos, regex, regexPos, skipSpaces)) + return true; + } while (_str[strPos] && regexMatchCharacter(type, regexChar, _str[strPos++])); + + return false; +} + +bool String::regexMatchPos(int strPos, const char *regex, int regexPos, bool skipSpaces) { + RegexMatchType matchT = kRegexMatchCharacter; + + if (skipSpaces) { + while (isspace(_str[strPos])) + strPos++; + + while (isspace(regex[regexPos])) + regexPos++; + } + + if (regex[regexPos] == '\0') + return true; + + if (regex[regexPos] == '.') + matchT = kRegexMatchAny; + else if (regex[regexPos] == '[') { + String group; + while (regex[regexPos - 1] != ']') + group += regex[regexPos++]; + + regexPos--; + + if (group == "[digit]" || group == "[d]") + matchT = kRegexMatchDigit; + else if (group == "[space]" || group == "[s]") + matchT = kRegexMatchSpace; + else if (group == "[alnum]") + matchT = kRegexMatchAlphanum; + else if (group == "[alpha]") + matchT = kRegexMatchAlpha; + else if (group == "[word]") + matchT = kRegexMatchWord; + } + + if (regex[regexPos + 1] == '*') + return regexMatchStar(matchT, regex[regexPos], regex, regexPos + 2, strPos, skipSpaces); + + if (regex[regexPos] == '$' && regex[regexPos + 1] == 0) + return _str[strPos] == 0; + + if (_str[strPos] && regexMatchCharacter(matchT, regex[regexPos], _str[strPos])) + return regexMatchPos(strPos + 1, regex, regexPos + 1, skipSpaces); + + return false; +} + /** * Ensure that enough storage is available to store at least new_len * characters plus a null byte. In addition, if we currently share diff --git a/common/str.h b/common/str.h index a92ec34fff..2ea151ba96 100644 --- a/common/str.h +++ b/common/str.h @@ -165,6 +165,9 @@ public: uint hash() const; + // Tanoku: Regular expression support for the String class + bool regexMatch(const char *regex, bool skipSpaces = false); + public: typedef char * iterator; typedef const char * const_iterator; @@ -189,6 +192,20 @@ protected: void ensureCapacity(uint32 new_len, bool keep_old); void incRefCount() const; void decRefCount(int *oldRefCount); + + enum RegexMatchType { + kRegexMatchAny, + kRegexMatchDigit, + kRegexMatchSpace, + kRegexMatchAlphanum, + kRegexMatchAlpha, + kRegexMatchWord, + kRegexMatchCharacter + }; + + bool regexMatchStar(RegexMatchType type, char regexChar, const char *regex, int regexPos, int strPos, bool skipSpaces); + bool regexMatchCharacter(RegexMatchType type, char regexChar, char strChar); + bool regexMatchPos(int strPos, const char *regex, int regexPos, bool skipSpaces); }; // Append two strings to form a new (temp) string diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0194231427..1f8ec3c397 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -53,35 +53,20 @@ VectorRenderer *createRenderer(int mode) { ********************************************************************/ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { - if (step.flags & DrawStep::kStepCallbackOnly) { - (this->*(step.drawingCall))(area, step); - return; - } - - if (step.flags & DrawStep::kStepSetBG) + if (step.bgColor.set) setBgColor(step.bgColor.r, step.bgColor.g, step.bgColor.b); - if (step.flags & DrawStep::kStepSetFG) + if (step.fgColor.set) setFgColor(step.fgColor.r, step.fgColor.g, step.fgColor.b); - if (step.flags & DrawStep::kStepSetGradient) + if (step.gradColor1.set && step.gradColor2.set) 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); - - if (step.flags & DrawStep::kStepSetGradientFactor) - setGradientFactor(step.factor); - - if (step.flags & DrawStep::kStepSetStroke) - setStrokeWidth(step.stroke); - - if (step.flags & DrawStep::kStepSetFillMode) - setFillMode((FillMode)step.fillMode); - - if (step.flags & DrawStep::kStepSettingsOnly) - return; + shadowEnable(step.shadow); + setGradientFactor(step.factor); + setStrokeWidth(step.stroke); + setFillMode((FillMode)step.fillMode); (this->*(step.drawingCall))(area, step); } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b4c4bb656d..d989781d5c 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -40,10 +40,9 @@ class VectorRenderer; struct DrawStep; struct DrawStep { - uint32 flags; /** Step flags, see DrawStepFlags */ - struct { - uint8 r, g, b; + uint8 r, g, b; + bool set; } fgColor, /** Foreground color */ bgColor, /** backgroudn color */ @@ -68,18 +67,6 @@ struct DrawStep { uint32 scale; /** scale of all the coordinates in FIXED POINT with 16 bits mantissa */ void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ - - enum DrawStepFlags { - kStepCallbackOnly = (1 << 0), - kStepSettingsOnly = (1 << 1), - kStepSetBG = (1 << 2), - kStepSetFG = (1 << 3), - kStepSetGradient = (1 << 4), - kStepSetShadow = (1 << 5), - kStepSetGradientFactor = (1 << 6), - kStepSetStroke = (1 << 7), - kStepSetFillMode = (1 << 8) - }; }; VectorRenderer *createRenderer(int mode); @@ -403,6 +390,8 @@ public: drawBeveledSquare(x, y, w, h, step.extraData); } + void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {} + /** * Draws the specified draw step on the screen. * diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index ae52387502..dc2250a2bd 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -77,6 +77,11 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { _vectorRenderer->setSurface(_screen); } +void InterfaceManager::addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step) { + _widgets[getDrawDataId(drawDataId)]->_steps.push_back(step); +} + + bool InterfaceManager::init() { return false; } @@ -96,7 +101,7 @@ void InterfaceManager::drawDD(DrawData type, const Common::Rect &r) { if (isWidgetCached(type, r)) { drawCached(type, r); } else { - for (int i = 0; i < _widgets[type]->_stepCount; ++i) + for (uint i = 0; i < _widgets[type]->_steps.size(); ++i) _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); } } @@ -171,7 +176,6 @@ int InterfaceManager::runGUI() { 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].gradColor1.r = 206; steps[1].gradColor1.g = 121; @@ -182,7 +186,6 @@ int InterfaceManager::runGUI() { steps[1].radius = 8; // radius 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 @@ -194,13 +197,12 @@ int InterfaceManager::runGUI() { steps[2].w = 128; steps[2].h = 32; steps[2].drawingCall = &VectorRenderer::drawCallback_ROUNDSQ; - steps[2].flags = DrawStep::kStepCallbackOnly; steps[2].scale = (1 << 16); steps[3].fgColor.r = 255; steps[3].fgColor.g = 255; steps[3].fgColor.b = 255; - steps[3].flags = DrawStep::kStepSettingsOnly | DrawStep::kStepSetFG; + steps[3].drawingCall = &VectorRenderer::drawCallback_VOID; Common::Rect area = Common::Rect(32, 32, 256, 256); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 7ab3f4c9db..f5efb105ec 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -167,6 +167,12 @@ public: void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); + DrawData getDrawDataId(Common::String &name) { + return (DrawData)0; + } + + void addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step); + protected: template void screenInit(); @@ -209,8 +215,7 @@ struct WidgetDrawData { Common::Rect _realSize; bool _scaled; - Graphics::DrawStep **_steps; - int _stepCount; + Common::Array _steps; bool _cached; Graphics::Surface *_surfaceCache; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 267efba371..287805b0b6 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -29,7 +29,9 @@ #include "common/hashmap.h" #include "common/hash-str.h" +#include "gui/InterfaceManager.h" #include "gui/ThemeParser.h" +#include "graphics/VectorRenderer.h" /** @@ -42,6 +44,8 @@ namespace GUI { +using namespace Graphics; + void ThemeParser::debug_testEval() { static const char *debugConfigText = "\n" @@ -50,6 +54,11 @@ void ThemeParser::debug_testEval() { "/* lol this is just a simple test*/\n"; _text = strdup(debugConfigText); + + Common::String test = "12, 125, 125"; + + printf("\n\nRegex result: %s.\n\n", test.regexMatch("^[d]*,[d]*,[d]*$", true) ? "Success." : "Fail"); + parse(); } @@ -59,8 +68,59 @@ void ThemeParser::parserError(const char *error_string) { printf("PARSER ERROR: %s\n", error_string); } +Graphics::DrawStep *ThemeParser::newDrawStep() { + + Graphics::DrawStep *step = new DrawStep; + + step->fgColor.set = false; + step->bgColor.set = false; + step->gradColor1.set = false; + step->gradColor2.set = false; + + step->extraData = 0; + step->factor = 1; + step->fillArea = false; + step->fillMode = Graphics::VectorRenderer::kFillDisabled; + step->scale = (1 << 16); + step->shadow = 0; + step->stroke = 1; + + return step; +} + void ThemeParser::parserCallback_DRAWSTEP() { - printf("Draw callback!\n"); + ParserNode *stepNode = _activeKey.pop(); + ParserNode *drawdataNode = _activeKey.pop(); + + 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) { + parserError("Invalid drawing function in draw step."); + _activeKey.push(drawdataNode); + _activeKey.push(stepNode); + return; + } + + drawstep->drawingCall = _drawFunctions[functionName]; + + if (stepNode->values.contains("stroke")) { + + } + + if (functionName == "roundedsq") { + + } + + g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep); + + _activeKey.push(drawdataNode); + _activeKey.push(stepNode); } void ThemeParser::parserCallback_DRAWDATA() { @@ -78,8 +138,8 @@ void ThemeParser::parseActiveKey(bool closed) { // Don't you just love C++ syntax? Water clear. (this->*(_callbacks[_activeKey.top()->name]))(); - 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()); +// 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) { delete _activeKey.pop(); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 956a6d1df2..c5ee55dbbf 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -34,6 +34,8 @@ #include "common/hash-str.h" #include "common/stack.h" +#include "graphics/VectorRenderer.h" + /** ********************************************* ** Theme Description File format overview. ** @@ -302,10 +304,13 @@ func = "fill" namespace GUI { +using namespace Graphics; + class ThemeParser { static const int kParserMaxDepth = 4; typedef void (ThemeParser::*ParserCallback)(); + typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); public: ThemeParser() { @@ -337,6 +342,8 @@ protected: void parseActiveKey(bool closed); void parserError(const char *errorString); + Graphics::DrawStep *newDrawStep(); + inline bool skipSpaces() { if (!isspace(_text[_pos])) return false; @@ -395,7 +402,9 @@ protected: }; Common::FixedStack _activeKey; + Common::HashMap _callbacks; + Common::HashMap _drawFunctions; }; } -- cgit v1.2.3 From a4b4534a66bb6f24a66a27e28f7df0d390e1eea8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 18 Jun 2008 23:49:47 +0000 Subject: Split ThemeParser into XMLParser and ThemeParser as child class to have a common XML Parser. svn-id: r32734 --- common/module.mk | 1 + common/xmlparser.cpp | 216 +++++++++++++++++++++++++++++++++++++++++++++ common/xmlparser.h | 208 +++++++++++++++++++++++++++++++++++++++++++ dists/msvc9/scummvm.vcproj | 22 +++++ gui/ThemeParser.cpp | 207 ++++--------------------------------------- gui/ThemeParser.h | 98 ++------------------ 6 files changed, 471 insertions(+), 281 deletions(-) create mode 100644 common/xmlparser.cpp create mode 100644 common/xmlparser.h diff --git a/common/module.mk b/common/module.mk index c3f2a38c3f..ed15bf75ea 100644 --- a/common/module.mk +++ b/common/module.mk @@ -16,6 +16,7 @@ MODULE_OBJS := \ system.o \ unarj.o \ unzip.o \ + xmlparser.o \ zlib.o # Include common rules diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp new file mode 100644 index 0000000000..7728d90d48 --- /dev/null +++ b/common/xmlparser.cpp @@ -0,0 +1,216 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +namespace Common { + +using namespace Graphics; + +void XMLParser::debug_testEval() { + static const char *debugConfigText = + "\n" + "\n" + "//\n" + "/* lol this is just a simple test*/\n"; + + _text = strdup(debugConfigText); + + 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) { + _state = kParserError; + printf("PARSER ERROR: %s\n", error_string); +} + +void XMLParser::parseActiveKey(bool closed) { + if (keyCallback(_activeKey.top()->name) == false) { + parserError("Unhandled value inside key."); + return; + } + + if (closed) { + delete _activeKey.pop(); + } +} + +bool XMLParser::parseKeyValue(Common::String keyName) { + assert(_activeKey.empty() == false); + + if (_activeKey.top()->values.contains(keyName)) + return false; + + _token.clear(); + char stringStart; + + if (_text[_pos] == '"' || _text[_pos] == '\'') { + stringStart = _text[_pos++]; + + while (_text[_pos] && _text[_pos] != stringStart) + _token += _text[_pos++]; + + if (_text[_pos++] == 0) + return false; + + } else if (!parseToken()) { + return false; + } + + _activeKey.top()->values[keyName] = _token; + return true; +} + +bool XMLParser::parse() { + + bool activeClosure = false; + bool selfClosure = false; + + _state = kParserNeedKey; + _pos = 0; + _activeKey.clear(); + + while (_text[_pos]) { + if (_state == kParserError) + break; + + if (skipSpaces()) + continue; + + if (skipComments()) + continue; + + switch (_state) { + case kParserNeedKey: + if (_text[_pos++] != '<') { + parserError("Expecting key start."); + break; + } + + if (_text[_pos] == 0) { + parserError("Unexpected end of file."); + break; + } + + if (_text[_pos] == '/' && _text[_pos + 1] != '*') { + _pos++; + activeClosure = true; + } + + _state = kParserNeedKeyName; + break; + + case kParserNeedKeyName: + if (!parseToken()) { + parserError("Invalid key name."); + break; + } + + if (activeClosure) { + if (_activeKey.empty() || _token != _activeKey.top()->name) + parserError("Unexpected closure."); + } else { + ParserNode *node = new ParserNode; + node->name = _token; + _activeKey.push(node); + } + + _state = kParserNeedPropertyName; + break; + + case kParserNeedPropertyName: + if (activeClosure) { + activeClosure = false; + delete _activeKey.pop(); + + if (_text[_pos++] != '>') + parserError("Invalid syntax in key closure."); + else + _state = kParserNeedKey; + + break; + } + + selfClosure = (_text[_pos] == '/'); + + if ((selfClosure && _text[_pos + 1] == '>') || _text[_pos] == '>') { + parseActiveKey(selfClosure); + _pos += selfClosure ? 2 : 1; + _state = kParserNeedKey; + break; + } + + if (!parseToken()) + parserError("Error when parsing key value."); + else + _state = kParserNeedPropertyOperator; + + break; + + case kParserNeedPropertyOperator: + if (_text[_pos++] != '=') + parserError("Unexpected character after key name."); + else + _state = kParserNeedPropertyValue; + + break; + + case kParserNeedPropertyValue: + if (!parseKeyValue(_token)) + parserError("Unable to parse key value."); + else + _state = kParserNeedPropertyName; + + break; + + default: + break; + } + } + + if (_state == kParserError) { + return false; + } + + if (_state != kParserNeedKey || !_activeKey.empty()) { + parserError("Unexpected end of file."); + return false; + } + + return true; +} + +} + diff --git a/common/xmlparser.h b/common/xmlparser.h new file mode 100644 index 0000000000..3edc2b31e1 --- /dev/null +++ b/common/xmlparser.h @@ -0,0 +1,208 @@ +/* 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 XML_PARSER_H +#define XML_PARSER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" +#include "common/xmlparser.h" + +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/stack.h" + +namespace Common { + +/** + * The base XMLParser class implements generic functionality for parsing + * XML-like files. + * + * In order to use it, it must be inherited with a child class that implements + * the XMLParser::keyCallback() function. + * + * @see XMLParser::keyCallback() + */ +class XMLParser { + /** Maximum depth for nested keys that the parser supports */ + static const int kParserMaxDepth = 4; + +public: + /** + * Parser constructor. + */ + XMLParser() {} + + virtual ~XMLParser() {} + + /** Active state for the parser */ + enum ParserState { + kParserNeedKey, + kParserNeedKeyName, + + kParserNeedPropertyName, + kParserNeedPropertyOperator, + kParserNeedPropertyValue, + + kParserError + }; + + /** Struct representing a parsed node */ + struct ParserNode { + Common::String name; + Common::StringMap values; + }; + + virtual bool parse(); + void debug_testEval(); + + /** + * Returns the active node being parsed (the one on top of + * the node stack). + */ + ParserNode *activeNode() { + if (!_activeKey.empty()) + return _activeKey.top(); + + return 0; + } + +protected: + /** + * The keycallback function must be overloaded by inheriting classes + * to implement parser-specific functions. + * + * This function is called everytime a key has successfully been parsed. + * The keyName parameter contains the name of the key that has just been + * parsed; this same key is still on top of the Node Stack. + * + * Access the node stack to view this key's properties and its parents. + * 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. + * See the sample implementation in GUI::ThemeParser. + */ + virtual bool keyCallback(Common::String keyName) { + return false; + } + + /** + * Parses the value of a given key. There's no reason to overload this. + */ + virtual bool parseKeyValue(Common::String keyName); + + /** + * Called once a key has been parsed. It handles the closing/cleanup of the + * node stack and calls the keyCallback. + * There's no reason to overload this. + */ + virtual void 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); + + /** + * Skips spaces/whitelines etc. Returns true if any spaces were skipped. + * Overload this if you want to make your parser depend on newlines or + * whatever. + */ + virtual bool skipSpaces() { + if (!isspace(_text[_pos])) + return false; + + while (_text[_pos] && isspace(_text[_pos])) + _pos++; + + return true; + } + + /** + * Skips comment blocks and comment lines. + * Returns true if any comments were skipped. + * Overload this if you want to disable comments on your XML syntax + * or to change the commenting syntax. + */ + virtual bool skipComments() { + if (_text[_pos] == '/' && _text[_pos + 1] == '*') { + _pos += 2; + 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; + } + + /** + * Check if a given character can be part of a KEY or VALUE name. + * Overload this if you want to support keys with strange characters + * in their name. + */ + virtual bool isValidNameChar(char c) { + return isalnum(c) || c == '_'; + } + + /** + * Parses a the first textual token found. + * There's no reason to overload this. + */ + virtual bool parseToken() { + _token.clear(); + while (isValidNameChar(_text[_pos])) + _token += _text[_pos++]; + + return isspace(_text[_pos]) != 0 || _text[_pos] == '>'; + } + + int _pos; /** Current position on the XML buffer. */ + char *_text; /** Buffer with the text being parsed */ + + ParserState _state; /** Internal state of the parser */ + + Common::String _error; /** Current error message */ + Common::String _token; /** Current text token */ + + Common::FixedStack _activeKey; /** Node stack of the parsed keys */ +}; + +} + +#endif diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index bc88e6fc66..57ee62e358 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -453,6 +453,14 @@ RelativePath="..\..\common\util.h" > + + + + @@ -1223,10 +1231,24 @@ + + + + + + - - - - -*/ - namespace GUI { using namespace Graphics; +using namespace Common; -void ThemeParser::debug_testEval() { - static const char *debugConfigText = - "\n" - "\n" - "//\n" - "/* lol this is just a simple test*/\n"; - - _text = strdup(debugConfigText); - - Common::String test = "12, 125, 125"; - - printf("\n\nRegex result: %s.\n\n", test.regexMatch("^[d]*,[d]*,[d]*$", true) ? "Success." : "Fail"); - - parse(); +ThemeParser::ThemeParser() : XMLParser() { + _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; + _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; } - -void ThemeParser::parserError(const char *error_string) { - _state = kParserError; - printf("PARSER ERROR: %s\n", error_string); +bool ThemeParser::keyCallback(Common::String keyName) { + // automatically handle with a function from the hash table. + if (!_callbacks.contains(_activeKey.top()->name)) + return false; + + return (this->*(_callbacks[_activeKey.top()->name]))(); } Graphics::DrawStep *ThemeParser::newDrawStep() { @@ -88,7 +72,7 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { return step; } -void ThemeParser::parserCallback_DRAWSTEP() { +bool ThemeParser::parserCallback_DRAWSTEP() { ParserNode *stepNode = _activeKey.pop(); ParserNode *drawdataNode = _activeKey.pop(); @@ -104,7 +88,7 @@ void ThemeParser::parserCallback_DRAWSTEP() { parserError("Invalid drawing function in draw step."); _activeKey.push(drawdataNode); _activeKey.push(stepNode); - return; + return false; } drawstep->drawingCall = _drawFunctions[functionName]; @@ -121,173 +105,12 @@ void ThemeParser::parserCallback_DRAWSTEP() { _activeKey.push(drawdataNode); _activeKey.push(stepNode); -} - -void ThemeParser::parserCallback_DRAWDATA() { - printf("Drawdata callback!\n"); -} - -void ThemeParser::parseActiveKey(bool closed) { - printf("Parsed key %s.\n", _activeKey.top()->name.c_str()); - - 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()->name]))(); - -// 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) { - delete _activeKey.pop(); - } -} - -bool ThemeParser::parseKeyValue(Common::String keyName) { - assert(_activeKey.empty() == false); - - if (_activeKey.top()->values.contains(keyName)) - return false; - - _token.clear(); - char stringStart; - - if (_text[_pos] == '"' || _text[_pos] == '\'') { - stringStart = _text[_pos++]; - - while (_text[_pos] && _text[_pos] != stringStart) - _token += _text[_pos++]; - - if (_text[_pos++] == 0) - return false; - - } else if (!parseToken()) { - return false; - } - _activeKey.top()->values[keyName] = _token; return true; } -bool ThemeParser::parse() { - - bool activeClosure = false; - bool selfClosure = false; - - _state = kParserNeedKey; - _pos = 0; - _activeKey.clear(); - - while (_text[_pos]) { - if (_state == kParserError) - break; - - if (skipSpaces()) - continue; - - if (skipComments()) - continue; - - switch (_state) { - case kParserNeedKey: - if (_text[_pos++] != '<') { - parserError("Expecting key start."); - break; - } - - if (_text[_pos] == 0) { - parserError("Unexpected end of file."); - break; - } - - if (_text[_pos] == '/' && _text[_pos + 1] != '*') { - _pos++; - activeClosure = true; - } - - _state = kParserNeedKeyName; - break; - - case kParserNeedKeyName: - if (!parseToken()) { - parserError("Invalid key name."); - break; - } - - if (activeClosure) { - if (_activeKey.empty() || _token != _activeKey.top()->name) - parserError("Unexpected closure."); - } else { - ParserNode *node = new ParserNode; - node->name = _token; - _activeKey.push(node); - } - - _state = kParserNeedPropertyName; - break; - - case kParserNeedPropertyName: - if (activeClosure) { - activeClosure = false; - delete _activeKey.pop(); - - if (_text[_pos++] != '>') - parserError("Invalid syntax in key closure."); - else - _state = kParserNeedKey; - - break; - } - - selfClosure = (_text[_pos] == '/'); - - if ((selfClosure && _text[_pos + 1] == '>') || _text[_pos] == '>') { - parseActiveKey(selfClosure); - _pos += selfClosure ? 2 : 1; - _state = kParserNeedKey; - break; - } - - if (!parseToken()) - parserError("Error when parsing key value."); - else - _state = kParserNeedPropertyOperator; - - break; - - case kParserNeedPropertyOperator: - if (_text[_pos++] != '=') - parserError("Unexpected character after key name."); - else - _state = kParserNeedPropertyValue; - - break; - - case kParserNeedPropertyValue: - if (!parseKeyValue(_token)) - parserError("Unable to parse key value."); - else - _state = kParserNeedPropertyName; - - break; - - default: - break; - } - } - - if (_state == kParserError) { - return false; - } - - if (_state != kParserNeedKey || !_activeKey.empty()) { - parserError("Unexpected end of file."); - return false; - } - +bool ThemeParser::parserCallback_DRAWDATA() { + printf("Drawdata callback!\n"); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c5ee55dbbf..108a7263ba 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -33,6 +33,7 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "common/stack.h" +#include "common/xmlparser.h" #include "graphics/VectorRenderer.h" @@ -305,106 +306,25 @@ func = "fill" namespace GUI { using namespace Graphics; +using namespace Common; -class ThemeParser { - - static const int kParserMaxDepth = 4; - typedef void (ThemeParser::*ParserCallback)(); +class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); + typedef bool (ThemeParser::*ParserCallback)(); public: - ThemeParser() { - _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; - _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; - } - - ~ThemeParser() {} - - enum ParserState { - kParserNeedKey, - kParserNeedKeyName, + ThemeParser(); - kParserNeedPropertyName, - kParserNeedPropertyOperator, - kParserNeedPropertyValue, - - kParserError - }; - - bool parse(); - void debug_testEval(); - protected: - void parserCallback_DRAWSTEP(); - void parserCallback_DRAWDATA(); + bool keyCallback(Common::String keyName); - bool parseKeyValue(Common::String keyName); - void parseActiveKey(bool closed); - void parserError(const char *errorString); + bool parserCallback_DRAWSTEP(); + bool parserCallback_DRAWDATA(); Graphics::DrawStep *newDrawStep(); - inline bool skipSpaces() { - if (!isspace(_text[_pos])) - return false; - - while (_text[_pos] && isspace(_text[_pos])) - _pos++; - - return true; - } - - inline bool skipComments() { - if (_text[_pos] == '/' && _text[_pos + 1] == '*') { - _pos += 2; - 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; - } - - inline bool isValidNameChar(char c) { - return isalnum(c) || c == '_'; - } - - inline bool parseToken() { - _token.clear(); - while (isValidNameChar(_text[_pos])) - _token += _text[_pos++]; - - return isspace(_text[_pos]) != 0 || _text[_pos] == '>'; - } - - int _pos; - char *_text; - - ParserState _state; - - Common::String _error; - Common::String _token; - - struct ParserNode { - Common::String name; - Common::StringMap values; - }; - - Common::FixedStack _activeKey; - - Common::HashMap _callbacks; Common::HashMap _drawFunctions; + Common::HashMap _callbacks; }; } -- cgit v1.2.3 From 8caa7d3f8b1146fafc6dff6de4f801eb2e8b61ae Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 24 Jun 2008 19:48:01 +0000 Subject: 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. svn-id: r32768 --- common/util.cpp | 29 +++++++++++++ common/util.h | 7 +++ common/xmlparser.cpp | 85 +++++++++++++++++++++++++++++------- common/xmlparser.h | 17 +++++--- gui/InterfaceManager.cpp | 51 +++++++++++++++++++++- gui/InterfaceManager.h | 9 +++- gui/ThemeParser.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++----- gui/ThemeParser.h | 18 ++++++++ 8 files changed, 293 insertions(+), 34 deletions(-) diff --git a/common/util.cpp b/common/util.cpp index 6f0fdcb233..51bd8bcad6 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -481,6 +481,34 @@ uint32 getEnabledSpecialDebugLevels() { 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 @@ Common::String tag2string(uint32 tag) { str[4] = '\0'; return Common::String(str); } + diff --git a/common/util.h b/common/util.h index c23513596c..c4cbf35212 100644 --- a/common/util.h +++ b/common/util.h @@ -323,6 +323,13 @@ const DebugLevelContainer &listSpecialDebugLevels(); 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 diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 7728d90d48..de10269cdb 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -36,35 +36,86 @@ using namespace Graphics; void XMLParser::debug_testEval() { static const char *debugConfigText = - "\n" - "\n" + "\n" + "\n" "//\n" "/* 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 @@ bool XMLParser::parse() { switch (_state) { case kParserNeedKey: if (_text[_pos++] != '<') { - parserError("Expecting key start."); + parserError("Parser expecting key start."); break; } @@ -144,6 +195,7 @@ bool XMLParser::parse() { } else { ParserNode *node = new ParserNode; node->name = _token; + node->ignore = false; _activeKey.push(node); } @@ -166,9 +218,10 @@ bool XMLParser::parse() { 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 @@ bool XMLParser::parse() { case kParserNeedPropertyOperator: if (_text[_pos++] != '=') - parserError("Unexpected character after key name."); + parserError("Syntax error after key name."); else _state = kParserNeedPropertyValue; @@ -189,7 +242,7 @@ bool XMLParser::parse() { case kParserNeedPropertyValue: if (!parseKeyValue(_token)) - parserError("Unable to parse key value."); + parserError("Invalid key value."); else _state = kParserNeedPropertyName; diff --git a/common/xmlparser.h b/common/xmlparser.h index 3edc2b31e1..c7f7218857 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -74,6 +74,7 @@ public: struct ParserNode { Common::String name; Common::StringMap values; + bool ignore; }; virtual bool parse(); @@ -103,7 +104,13 @@ protected: * 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 @@ protected: * 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 @@ protected: 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 @@ protected: 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 */ diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index dc2250a2bd..5ee3a014ed 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -38,11 +38,44 @@ namespace GUI { 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,9 +111,25 @@ void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { } 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; diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index f5efb105ec..00441a9efc 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -47,6 +47,8 @@ class InterfaceManager : public Common::Singleton { friend class Common::Singleton; typedef Common::String String; + static const char *kDrawDataStrings[]; + public: enum Graphics_Mode { kGfxDisabled = 0, @@ -168,10 +170,15 @@ public: 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 void screenInit(); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 9f029a874e..afc623c3d8 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -42,6 +42,15 @@ using namespace Common; 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,8 +82,12 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { } 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"); @@ -85,32 +98,108 @@ bool ThemeParser::parserCallback_DRAWSTEP() { 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()); \ + } + +/** + * 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; \ } - if (functionName == "roundedsq") { + __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; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 108a7263ba..4103098a63 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -321,6 +321,24 @@ protected: 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 _drawFunctions; -- cgit v1.2.3 From f0e63a49e38d635d70869f6eb1cda42c684fee8b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 25 Jun 2008 11:34:58 +0000 Subject: - Reverted getHostPlatformString() from util.cpp (Yeah, Max was right) - XMLParser now supports streams! - Added remaining key values for DrawStep parsing. - XMLParser parserError() bugfixes. svn-id: r32782 --- common/xmlparser.cpp | 51 ++++++++++++++++------------------ common/xmlparser.h | 42 ++++++++++++++++++++++++++-- gui/ThemeParser.cpp | 77 +++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 124 insertions(+), 46 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index de10269cdb..4c2c4b58f1 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -36,12 +36,13 @@ using namespace Graphics; void XMLParser::debug_testEval() { static const char *debugConfigText = - "\n" - "\n" - "//\n" - "/* lol this is just a simple test*/\n"; + "\n" + "\n" + "\n" + "/* lol this is just a simple test*/\n" + "I loled"; - _text = strdup(debugConfigText); + _text.fillFromMem(strdup(debugConfigText)); _fileName = strdup("test_parse.xml"); Common::String test = "12, 125, 125"; @@ -50,48 +51,42 @@ void XMLParser::debug_testEval() { } -void XMLParser::parserError(const char *error_string, ...) { +void XMLParser::parserError(const char *errorString, ...) { _state = kParserError; int pos = _pos; - int line_count = 1; - int line_start = -1; - int line_width = 1; + int lineCount = 1; + int lineStart = -1; do { if (_text[pos] == '\n' || _text[pos] == '\r') { - line_count++; + lineCount++; - if (line_start == -1) - line_start = pos; + if (lineStart == -1) + lineStart = MAX(pos + 1, _pos - 60); } } while (pos-- > 0); - line_start = MAX(line_start, _pos - 80); + char lineStr[70]; + _text.stream()->seek(lineStart, SEEK_SET); + _text.stream()->readLine(lineStr, 70); - 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, lineCount); - printf(" File <%s>, line %d:\n", _fileName, line_count); + printf("%s%s%s\n", + lineStr[0] == '<' ? "" : "...", + lineStr[strlen(lineStr) - 1] == '>' ? "" : "...", + lineStr); - printf("%s\n", linestr); - for (int i = 1; i < _pos - line_start; ++i) + for (int i = 0; i < _pos - lineStart + 3; ++i) printf(" "); printf("^\n"); printf("Parser error: "); va_list args; - va_start(args, error_string); - vprintf(error_string, args); + va_start(args, errorString); + vprintf(errorString, args); va_end(args); printf("\n"); diff --git a/common/xmlparser.h b/common/xmlparser.h index c7f7218857..d7d929cb9a 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -30,6 +30,7 @@ #include "graphics/surface.h" #include "common/system.h" #include "common/xmlparser.h" +#include "common/stream.h" #include "common/hashmap.h" #include "common/hash-str.h" @@ -37,6 +38,43 @@ namespace Common { +class XMLStream { +protected: + SeekableReadStream *_stream; + int _pos; + +public: + XMLStream() : _stream(0), _pos(0) {} + + ~XMLStream() { + delete _stream; + } + + SeekableReadStream *stream() { + return _stream; + } + + const char operator [](int idx) { + assert(_stream && idx >= 0); + + if (_pos + 1 != idx) + _stream->seek(idx, SEEK_SET); + + _pos = idx; + + return _stream->readSByte(); + } + + void fillFromMem(const char *buffer, bool dispose = false) { + delete _stream; + _stream = new MemoryReadStream((const byte*)buffer, strlen(buffer), dispose); + } + + void fillFromFile(const char *filename) { + + } +}; + /** * The base XMLParser class implements generic functionality for parsing * XML-like files. @@ -132,7 +170,7 @@ protected: /** * Prints an error message when parsing fails and stops the parser. */ - virtual void parserError(const char *errorString, ...); + virtual void parserError(const char *errorString, ...) GCC_PRINTF(1, 2); /** * Skips spaces/whitelines etc. Returns true if any spaces were skipped. @@ -199,7 +237,7 @@ protected: } int _pos; /** Current position on the XML buffer. */ - char *_text; /** Buffer with the text being parsed */ + XMLStream _text; /** Buffer with the text being parsed */ char *_fileName; ParserState _state; /** Internal state of the parser */ diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index afc623c3d8..26701fd96a 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -55,8 +55,10 @@ ThemeParser::ThemeParser() : XMLParser() { bool ThemeParser::keyCallback(Common::String keyName) { // automatically handle with a function from the hash table. - if (!_callbacks.contains(_activeKey.top()->name)) + if (!_callbacks.contains(_activeKey.top()->name)) { + parserError("%s is not a valid key name.", keyName.c_str()); return false; + } return (this->*(_callbacks[_activeKey.top()->name]))(); } @@ -72,7 +74,7 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { step->extraData = 0; step->factor = 1; - step->fillArea = false; + step->fillArea = true; step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; @@ -104,7 +106,7 @@ bool ThemeParser::parserCallback_DRAWSTEP() { drawstep->drawingCall = _drawFunctions[functionName]; - uint32 red, green, blue; + uint32 red, green, blue, w, h; /** * Helper macro to sanitize and assign an integer value from a key @@ -114,13 +116,18 @@ bool ThemeParser::parserCallback_DRAWSTEP() { * 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) \ +#define __PARSER_ASSIGN_INT(struct_name, key_name, force) \ if (stepNode->values.contains(key_name)) { \ - if (!validateKeyInt(stepNode->values[key_name].c_str())) \ + if (!validateKeyInt(stepNode->values[key_name].c_str())) {\ + parserError("Error when parsing key value for '%s'.", key_name); \ return false; \ - \ + } \ drawstep->struct_name = atoi(stepNode->values[key_name].c_str()); \ + } else if (force) { \ + parserError("Missing necessary key '%s'.", key_name); \ + return false; \ } /** @@ -136,17 +143,20 @@ 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) \ - return false; \ - \ + if (sscanf(stepNode->values[key_name].c_str(), "%d, %d, %d", &red, &green, &blue) != 3 || \ + red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {\ + parserError("Error when parsing color struct '%s'", stepNode->values[key_name].c_str());\ + return false; \ + }\ 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"); - __PARSER_ASSIGN_INT(shadow, "shadow"); - __PARSER_ASSIGN_INT(factor, "gradient_factor"); + __PARSER_ASSIGN_INT(stroke, "stroke", 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"); @@ -154,11 +164,43 @@ bool ThemeParser::parserCallback_DRAWSTEP() { __PARSER_ASSIGN_RGB(gradColor2, "gradient_end"); if (functionName == "roundedsq" || functionName == "circle") { - __PARSER_ASSIGN_INT(radius, "radius"); + __PARSER_ASSIGN_INT(radius, "radius", true) } if (functionName == "bevelsq") { - __PARSER_ASSIGN_INT(extraData, "bevel"); + __PARSER_ASSIGN_INT(extraData, "bevel", true); + } + + if (functionName == "triangle") { + + } + + if (stepNode->values.contains("size")) { + if (stepNode->values["size"] == "auto") { + drawstep->fillArea = true; + } else if (sscanf(stepNode->values["size"].c_str(), "%d, %d", &w, &h) == 2) { + drawstep->fillArea = false; + drawstep->w = w; + drawstep->h = h; + } else { + parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); + return false; + } + } + + if (stepNode->values.contains("fill")) { + if (stepNode->values["fill"] == "none") + drawstep->fillMode = VectorRenderer::kFillDisabled; + else if (stepNode->values["fill"] == "foreground") + drawstep->fillMode = VectorRenderer::kFillForeground; + else if (stepNode->values["fill"] == "background") + drawstep->fillMode = VectorRenderer::kFillBackground; + else if (stepNode->values["fill"] == "gradient") + drawstep->fillMode = VectorRenderer::kFillGradient; + else { + parserError("'%s' is not a valid fill mode for a shape.", stepNode->values["fill"].c_str()); + return false; + } } #undef __PARSER_ASSIGN_INT @@ -188,12 +230,15 @@ bool ThemeParser::parserCallback_DRAWDATA() { cached = true; } - if (drawdataNode->values.contains("platform")) { + // Both Max and Johannes suggest using a non-platform specfic approach based on available + // resources and active resolution. getHostPlatformString() has been removed, so fix this. + +/* 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."); -- cgit v1.2.3 From 2fcbb970056c9b596699f22d949fe17f9df791d3 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 25 Jun 2008 14:19:56 +0000 Subject: XMLParser: - Cleanup. - Support for file/buffer loading. ThemeParser: - Triangle orientation. svn-id: r32784 --- common/xmlparser.cpp | 17 +++++------ common/xmlparser.h | 33 ++++++++++++++++----- gui/ThemeParser.cpp | 83 ++++++++++++++++++++++++++-------------------------- 3 files changed, 74 insertions(+), 59 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 4c2c4b58f1..bb8754d480 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -42,16 +42,14 @@ void XMLParser::debug_testEval() { "/* lol this is just a simple test*/\n" "I loled"; - _text.fillFromMem(strdup(debugConfigText)); + loadBuffer(debugConfigText); _fileName = strdup("test_parse.xml"); - Common::String test = "12, 125, 125"; - parse(); } -void XMLParser::parserError(const char *errorString, ...) { +bool XMLParser::parserError(const char *errorString, ...) { _state = kParserError; int pos = _pos; @@ -90,6 +88,8 @@ void XMLParser::parserError(const char *errorString, ...) { va_end(args); printf("\n"); + + return false; } bool XMLParser::parseActiveKey(bool closed) { @@ -248,14 +248,11 @@ bool XMLParser::parse() { } } - if (_state == kParserError) { + if (_state == kParserError) return false; - } - if (_state != kParserNeedKey || !_activeKey.empty()) { - parserError("Unexpected end of file."); - return false; - } + if (_state != kParserNeedKey || !_activeKey.empty()) + return parserError("Unexpected end of file."); return true; } diff --git a/common/xmlparser.h b/common/xmlparser.h index d7d929cb9a..5b03f54b9d 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -31,6 +31,7 @@ #include "common/system.h" #include "common/xmlparser.h" #include "common/stream.h" +#include "common/file.h" #include "common/hashmap.h" #include "common/hash-str.h" @@ -65,13 +66,9 @@ public: return _stream->readSByte(); } - void fillFromMem(const char *buffer, bool dispose = false) { + void loadStream(SeekableReadStream *stream) { delete _stream; - _stream = new MemoryReadStream((const byte*)buffer, strlen(buffer), dispose); - } - - void fillFromFile(const char *filename) { - + _stream = stream; } }; @@ -94,7 +91,10 @@ public: */ XMLParser() {} - virtual ~XMLParser() {} + virtual ~XMLParser() { + while (!_activeKey.empty()) + delete _activeKey.pop(); + } /** Active state for the parser */ enum ParserState { @@ -115,6 +115,21 @@ public: bool ignore; }; + virtual bool loadFile(const char *filename) { + Common::File *f = new Common::File; + + if (!f->open(filename, Common::File::kFileReadMode)) + return false; + + _text.loadStream(f); + return true; + } + + virtual bool loadBuffer(const char *buffer, bool disposable = false) { + _text.loadStream(new MemoryReadStream((const byte*)buffer, strlen(buffer), disposable)); + return true; + } + virtual bool parse(); void debug_testEval(); @@ -169,8 +184,10 @@ protected: /** * Prints an error message when parsing fails and stops the parser. + * Parser error always returns "false" so we can pass the return value directly + * and break down the parsing. */ - virtual void parserError(const char *errorString, ...) GCC_PRINTF(1, 2); + virtual bool parserError(const char *errorString, ...) GCC_PRINTF(1, 2); /** * Skips spaces/whitelines etc. Returns true if any spaces were skipped. diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 26701fd96a..03feaaa96d 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -55,10 +55,8 @@ ThemeParser::ThemeParser() : XMLParser() { bool ThemeParser::keyCallback(Common::String keyName) { // automatically handle with a function from the hash table. - if (!_callbacks.contains(_activeKey.top()->name)) { - parserError("%s is not a valid key name.", keyName.c_str()); - return false; - } + if (!_callbacks.contains(_activeKey.top()->name)) + return parserError("%s is not a valid key name.", keyName.c_str()); return (this->*(_callbacks[_activeKey.top()->name]))(); } @@ -99,14 +97,13 @@ bool ThemeParser::parserCallback_DRAWSTEP() { Common::String functionName = stepNode->values["func"]; - if (_drawFunctions.contains(functionName) == false) { - parserError("%s is not a valid drawing function name", functionName.c_str()); - return false; - } + if (_drawFunctions.contains(functionName) == false) + return parserError("%s is not a valid drawing function name", functionName.c_str()); drawstep->drawingCall = _drawFunctions[functionName]; uint32 red, green, blue, w, h; + Common::String val; /** * Helper macro to sanitize and assign an integer value from a key @@ -120,14 +117,12 @@ bool ThemeParser::parserCallback_DRAWSTEP() { */ #define __PARSER_ASSIGN_INT(struct_name, key_name, force) \ if (stepNode->values.contains(key_name)) { \ - if (!validateKeyInt(stepNode->values[key_name].c_str())) {\ - parserError("Error when parsing key value for '%s'.", key_name); \ - return false; \ - } \ + if (!validateKeyInt(stepNode->values[key_name].c_str()))\ + return parserError("Error when parsing key value for '%s'.", key_name); \ + \ drawstep->struct_name = atoi(stepNode->values[key_name].c_str()); \ } else if (force) { \ - parserError("Missing necessary key '%s'.", key_name); \ - return false; \ + return parserError("Missing necessary key '%s'.", key_name); \ } /** @@ -144,10 +139,9 @@ 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 || \ - red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {\ - parserError("Error when parsing color struct '%s'", stepNode->values[key_name].c_str());\ - return false; \ - }\ + 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());\ + \ drawstep->struct_name.r = red; \ drawstep->struct_name.g = green; \ drawstep->struct_name.b = blue; \ @@ -172,7 +166,22 @@ bool ThemeParser::parserCallback_DRAWSTEP() { } if (functionName == "triangle") { - + drawstep->extraData = VectorRenderer::kTriangleUp; + + if (stepNode->values.contains("orientation")) { + val = stepNode->values["orientation"]; + + if ( val == "top") + drawstep->extraData = VectorRenderer::kTriangleUp; + else if (val == "bottom") + drawstep->extraData = VectorRenderer::kTriangleDown; + else if (val == "left") + drawstep->extraData = VectorRenderer::kTriangleLeft; + else if (val == "right") + drawstep->extraData = VectorRenderer::kTriangleRight; + else + return parserError("'%s' is not a valid value for triangle orientation.", stepNode->values["orientation"].c_str()); + } } if (stepNode->values.contains("size")) { @@ -183,24 +192,22 @@ bool ThemeParser::parserCallback_DRAWSTEP() { drawstep->w = w; drawstep->h = h; } else { - parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); - return false; + return parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); } } if (stepNode->values.contains("fill")) { - if (stepNode->values["fill"] == "none") + val = stepNode->values["fill"]; + if (val == "none") drawstep->fillMode = VectorRenderer::kFillDisabled; - else if (stepNode->values["fill"] == "foreground") + else if (val == "foreground") drawstep->fillMode = VectorRenderer::kFillForeground; - else if (stepNode->values["fill"] == "background") + else if (val == "background") drawstep->fillMode = VectorRenderer::kFillBackground; - else if (stepNode->values["fill"] == "gradient") + else if (val == "gradient") drawstep->fillMode = VectorRenderer::kFillGradient; - else { - parserError("'%s' is not a valid fill mode for a shape.", stepNode->values["fill"].c_str()); - return false; - } + else + return parserError("'%s' is not a valid fill mode for a shape.", stepNode->values["fill"].c_str()); } #undef __PARSER_ASSIGN_INT @@ -214,17 +221,13 @@ bool ThemeParser::parserCallback_DRAWDATA() { ParserNode *drawdataNode = _activeKey.top(); bool cached = false; - if (drawdataNode->values.contains("id") == false) { - parserError("DrawData notes must contain an identifier."); - return false; - } + if (drawdataNode->values.contains("id") == false) + return parserError("DrawData notes must contain an identifier."); 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 (id == -1) + return parserError("%d is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") { cached = true; @@ -240,10 +243,8 @@ bool ThemeParser::parserCallback_DRAWDATA() { } }*/ - 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; - } + if (g_InterfaceManager.addDrawData(id, cached) == false) + return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); return true; } -- cgit v1.2.3 From 917b750839282f768178d8436d54deda3078a1f6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 25 Jun 2008 17:56:00 +0000 Subject: XMLParser: - Bug fixes. ThemeParser: - Support for palette colors. - Expanded theme syntax. svn-id: r32787 --- common/xmlparser.cpp | 40 +++++++++++++++---------- common/xmlparser.h | 12 ++++++-- gui/ThemeParser.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++------- 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 = - "\n" - "\n" - "\n" - "/* lol this is just a simple test*/\n" - "I loled"; + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "/* lol this is just a simple test*/\n" + ""; 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(" 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 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 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 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 _drawFunctions; Common::HashMap _callbacks; + + struct PaletteColor { + uint8 r, g, b; + }; + + Common::HashMap _palette; }; } -- cgit v1.2.3 From 7fd6b3916fce8a61b2235ad720bd7fa7b40a7914 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 25 Jun 2008 18:11:17 +0000 Subject: GCC Fixes svn-id: r32788 --- common/xmlparser.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 548b9cf3e2..bfbc03b97b 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -66,9 +66,9 @@ public: return _stream->readSByte(); } - void loadStream(SeekableReadStream *stream) { + void loadStream(SeekableReadStream *s) { delete _stream; - _stream = stream; + _stream = s; } }; @@ -195,7 +195,7 @@ protected: * Parser error always returns "false" so we can pass the return value directly * and break down the parsing. */ - virtual bool parserError(const char *errorString, ...) GCC_PRINTF(1, 2); + virtual bool parserError(const char *errorString, ...) GCC_PRINTF(2, 3); /** * Skips spaces/whitelines etc. Returns true if any spaces were skipped. -- cgit v1.2.3 From 73d5715a799f393e8b2611f2deff1b7f90f6130a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 25 Jun 2008 22:30:28 +0000 Subject: - XMLParser: Improved file stream support - InterfaceManager: Config file loading/parsing added. - ThemeParser: Fixed GCC warnings/various bugs. svn-id: r32792 --- common/xmlparser.cpp | 3 +++ common/xmlparser.h | 6 +++++- gui/InterfaceManager.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++-- gui/InterfaceManager.h | 20 +++++++++++++++++--- gui/ThemeParser.cpp | 4 ++-- 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index b2178afbd0..6cb3a8a441 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -148,6 +148,9 @@ bool XMLParser::parseKeyValue(Common::String keyName) { bool XMLParser::parse() { + if (_text.ready() == false) + return parserError("XML stream not ready for reading."); + bool activeClosure = false; bool selfClosure = false; diff --git a/common/xmlparser.h b/common/xmlparser.h index bfbc03b97b..3eb87efd31 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -70,6 +70,10 @@ public: delete _stream; _stream = s; } + + bool ready() { + return _stream != 0; + } }; /** @@ -116,7 +120,7 @@ public: int depth; }; - virtual bool loadFile(const char *filename) { + virtual bool loadFile(Common::String filename) { Common::File *f = new Common::File; if (!f->open(filename, Common::File::kFileReadMode)) diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 5ee3a014ed..0afb71bfd5 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -28,6 +28,7 @@ #include "graphics/colormasks.h" #include "common/system.h" #include "common/events.h" +#include "common/config-manager.h" #include "gui/InterfaceManager.h" #include "graphics/VectorRenderer.h" @@ -69,8 +70,9 @@ const char *InterfaceManager::kDrawDataStrings[] = { InterfaceManager::InterfaceManager() : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _bytesPerPixel(0) { + _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false) { _system = g_system; + _parser = new ThemeParser(); for (int i = 0; i < kDrawDataMAX; ++i) { _widgets[i] = 0; @@ -126,11 +128,50 @@ bool InterfaceManager::addDrawData(DrawData data_id, bool cached) { _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::loadTheme(Common::String &themeName) { + if (!loadThemeXML(themeName)) { + warning("Could not parse custom theme '%s'.", themeName.c_str()); + return false; + } + + for (int i = 0; i < kDrawDataMAX; ++i) { + if (_widgets[i] == 0) { +#ifdef REQUIRE_ALL_DD_SETS + warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str()); + return false; +#endif + } else if (_widgets[i]->_cached) { + // draw the cached widget to the cache surface + } + } + + _themeOk = true; + return true; +} + +bool InterfaceManager::loadThemeXML(Common::String &themeName) { + assert(_parser); + + if (ConfMan.hasKey("themepath")) + Common::File::addDefaultDirectory(ConfMan.get("themepath")); + +#ifdef DATA_PATH + Common::File::addDefaultDirectoryRecursive(DATA_PATH); +#endif + + if (ConfMan.hasKey("extrapath")) + Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + + if (!parser()->loadFile(themeName + ".xml")) + return false; + + return parser()->parse(); +} + bool InterfaceManager::init() { return false; } diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 00441a9efc..97af6732e0 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -33,6 +33,7 @@ #include "graphics/surface.h" #include "graphics/fontman.h" +#include "gui/ThemeParser.h" #include "graphics/VectorRenderer.h" namespace GUI { @@ -143,6 +144,7 @@ public: ~InterfaceManager() { freeRenderer(); freeScreen(); + delete _parser; } void setGraphicsMode(Graphics_Mode mode); @@ -180,9 +182,21 @@ public: void addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step); bool addDrawData(DrawData data_id, bool cached); + ThemeParser *parser() { + return _parser; + } + + bool ready() { + return _initOk && _themeOk; + } + + bool loadTheme(Common::String &themeName); + protected: template void screenInit(); + bool loadThemeXML(Common::String &themeName); + void freeRenderer() { delete _vectorRenderer; _vectorRenderer = 0; @@ -205,6 +219,7 @@ protected: OSystem *_system; Graphics::VectorRenderer *_vectorRenderer; Graphics::Surface *_screen; + GUI::ThemeParser *_parser; int _bytesPerPixel; Graphics_Mode _graphicsMode; @@ -215,17 +230,16 @@ protected: WidgetDrawData *_widgets[kDrawDataMAX]; bool _initOk; + bool _themeOk; bool _caching; }; struct WidgetDrawData { - Common::Rect _realSize; - bool _scaled; - Common::Array _steps; bool _cached; Graphics::Surface *_surfaceCache; + uint32 _cachedW, _cachedH; InterfaceManager::DrawData _type; }; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index d9d8c9cd7c..6e60d8a499 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -237,7 +237,7 @@ bool ThemeParser::parserCallback_DRAWSTEP() { else if (val == "right") drawstep->extraData = VectorRenderer::kTriangleRight; else - return parserError("'%s' is not a valid value for triangle orientation.", stepNode->values["orientation"].c_str()); + return parserError("'%s' is not a valid value for triangle orientation.", val.c_str()); } } @@ -289,7 +289,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]); if (id == -1) - return parserError("%d is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); + return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") { cached = true; -- cgit v1.2.3 From 3ae28530ef1807d3b99c462ab3f53acbe3153b12 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 26 Jun 2008 09:18:41 +0000 Subject: Actually reverted stupid changes in Common::String and Util.cpp regarding Regex and the platform function. svn-id: r32797 --- common/str.cpp | 99 --------------------------------------------------------- common/str.h | 17 ---------- common/util.cpp | 29 ----------------- common/util.h | 7 ---- 4 files changed, 152 deletions(-) diff --git a/common/str.cpp b/common/str.cpp index e849cb042d..ad48ef6087 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -283,105 +283,6 @@ void String::toUppercase() { _str[i] = toupper(_str[i]); } -bool String::regexMatch(const char *regex, bool skipSpaces) { - int pos = 0; - - if (regex[0] == '^') - return regexMatchPos(1, regex, 1, skipSpaces); - - do { - if (regexMatchPos(pos, regex, 0, skipSpaces)) - return true; - } while (_str[pos++]); - - return false; -} - -bool String::regexMatchCharacter(RegexMatchType type, char regexChar, char strChar) { - switch (type) { - case kRegexMatchAny: - return true; - - case kRegexMatchDigit: - return isdigit(strChar) != 0; - - case kRegexMatchSpace: - return isspace(strChar) != 0; - - case kRegexMatchAlphanum: - return isalnum(strChar) != 0; - - case kRegexMatchAlpha: - return isalpha(strChar) != 0; - - case kRegexMatchWord: - return isalnum(strChar) != 0 || strChar == '_'; - - case kRegexMatchCharacter: - return regexChar == strChar; - - default: - return false; - } -} - -bool String::regexMatchStar(RegexMatchType type, char regexChar, const char *regex, int regexPos, int strPos, bool skipSpaces) { - - do { - if (regexMatchPos(strPos, regex, regexPos, skipSpaces)) - return true; - } while (_str[strPos] && regexMatchCharacter(type, regexChar, _str[strPos++])); - - return false; -} - -bool String::regexMatchPos(int strPos, const char *regex, int regexPos, bool skipSpaces) { - RegexMatchType matchT = kRegexMatchCharacter; - - if (skipSpaces) { - while (isspace(_str[strPos])) - strPos++; - - while (isspace(regex[regexPos])) - regexPos++; - } - - if (regex[regexPos] == '\0') - return true; - - if (regex[regexPos] == '.') - matchT = kRegexMatchAny; - else if (regex[regexPos] == '[') { - String group; - while (regex[regexPos - 1] != ']') - group += regex[regexPos++]; - - regexPos--; - - if (group == "[digit]" || group == "[d]") - matchT = kRegexMatchDigit; - else if (group == "[space]" || group == "[s]") - matchT = kRegexMatchSpace; - else if (group == "[alnum]") - matchT = kRegexMatchAlphanum; - else if (group == "[alpha]") - matchT = kRegexMatchAlpha; - else if (group == "[word]") - matchT = kRegexMatchWord; - } - - if (regex[regexPos + 1] == '*') - return regexMatchStar(matchT, regex[regexPos], regex, regexPos + 2, strPos, skipSpaces); - - if (regex[regexPos] == '$' && regex[regexPos + 1] == 0) - return _str[strPos] == 0; - - if (_str[strPos] && regexMatchCharacter(matchT, regex[regexPos], _str[strPos])) - return regexMatchPos(strPos + 1, regex, regexPos + 1, skipSpaces); - - return false; -} - /** * Ensure that enough storage is available to store at least new_len * characters plus a null byte. In addition, if we currently share diff --git a/common/str.h b/common/str.h index 2ea151ba96..a92ec34fff 100644 --- a/common/str.h +++ b/common/str.h @@ -165,9 +165,6 @@ public: uint hash() const; - // Tanoku: Regular expression support for the String class - bool regexMatch(const char *regex, bool skipSpaces = false); - public: typedef char * iterator; typedef const char * const_iterator; @@ -192,20 +189,6 @@ protected: void ensureCapacity(uint32 new_len, bool keep_old); void incRefCount() const; void decRefCount(int *oldRefCount); - - enum RegexMatchType { - kRegexMatchAny, - kRegexMatchDigit, - kRegexMatchSpace, - kRegexMatchAlphanum, - kRegexMatchAlpha, - kRegexMatchWord, - kRegexMatchCharacter - }; - - bool regexMatchStar(RegexMatchType type, char regexChar, const char *regex, int regexPos, int strPos, bool skipSpaces); - bool regexMatchCharacter(RegexMatchType type, char regexChar, char strChar); - bool regexMatchPos(int strPos, const char *regex, int regexPos, bool skipSpaces); }; // Append two strings to form a new (temp) string diff --git a/common/util.cpp b/common/util.cpp index 51bd8bcad6..6f0fdcb233 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -481,34 +481,6 @@ uint32 getEnabledSpecialDebugLevels() { 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 @@ -722,4 +694,3 @@ Common::String tag2string(uint32 tag) { str[4] = '\0'; return Common::String(str); } - diff --git a/common/util.h b/common/util.h index c4cbf35212..c23513596c 100644 --- a/common/util.h +++ b/common/util.h @@ -323,13 +323,6 @@ const DebugLevelContainer &listSpecialDebugLevels(); 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 -- cgit v1.2.3 From 0cd183b94b7d24f9df8453ee126bceddc1dfd857 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 26 Jun 2008 13:50:16 +0000 Subject: InterfaceManager now loads themes. svn-id: r32800 --- base/main.cpp | 2 -- common/xmlparser.cpp | 19 ---------------- common/xmlparser.h | 24 ++++++++++++++++++- dists/msvc9/scummvm.vcproj | 11 ++++----- gui/InterfaceManager.cpp | 51 ++++++++++------------------------------- gui/InterfaceManager.h | 7 ++++-- gui/ThemeDefaultXML.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++ gui/ThemeParser.cpp | 12 ++++++++++ gui/ThemeParser.h | 2 ++ gui/module.mk | 1 + 10 files changed, 116 insertions(+), 70 deletions(-) create mode 100644 gui/ThemeDefaultXML.cpp diff --git a/base/main.cpp b/base/main.cpp index 20775f24db..53b4cb7cf4 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -72,8 +72,6 @@ static bool launcherDialog(OSystem &system) { #if 1 - GUI::ThemeParser parser; - parser.debug_testEval(); g_InterfaceManager.runGUI(); return true; diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 6cb3a8a441..22b8b22e48 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -34,25 +34,6 @@ namespace Common { using namespace Graphics; -void XMLParser::debug_testEval() { - static const char *debugConfigText = - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "/* lol this is just a simple test*/\n" - ""; - - loadBuffer(debugConfigText); - _fileName = "test_parse.xml"; - - parse(); -} - - bool XMLParser::parserError(const char *errorString, ...) { _state = kParserError; diff --git a/common/xmlparser.h b/common/xmlparser.h index 3eb87efd31..4c8e1b986f 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -120,23 +120,45 @@ public: int depth; }; + /** + * Loads a file into the parser. + * Used for the loading of Theme Description files + * straight from the filesystem. + * + * @param filename Name of the file to load. + */ virtual bool loadFile(Common::String filename) { Common::File *f = new Common::File; if (!f->open(filename, Common::File::kFileReadMode)) return false; + _fileName = filename; _text.loadStream(f); return true; } + /** + * Loads a memory buffer into the parser. + * Used for loading the default theme fallback directly + * from memory if no themes can be found. + * + * @param buffer Pointer to the buffer. + * @param disposable Sets if the XMLParser owns the buffer, + * i.e. if it can be freed safely after it's + * no longer needed by the parser. + */ virtual bool loadBuffer(const char *buffer, bool disposable = false) { _text.loadStream(new MemoryReadStream((const byte*)buffer, strlen(buffer), disposable)); + _fileName = "Memory Stream"; return true; } + /** + * The actual parsing function. + * Parses the loaded data stream, returns true if successful. + */ virtual bool parse(); - void debug_testEval(); /** * Returns the active node being parsed (the one on top of diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 57ee62e358..cd502b3ca8 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1224,6 +1224,10 @@ RelativePath="..\..\gui\ThemeClassic.cpp" > + + @@ -1231,13 +1235,6 @@ - - - getEventManager(); + + loadTheme("modern_theme.xml"); + _system->showOverlay(); - Graphics::DrawStep *steps = new Graphics::DrawStep[5]; + Graphics::DrawStep *steps = new Graphics::DrawStep[2]; steps[0].gradColor1.r = 214; steps[0].gradColor1.g = 113; steps[0].gradColor1.b = 8; + steps[0].gradColor1.set = true; steps[0].gradColor2.r = 240; steps[0].gradColor2.g = 200; steps[0].gradColor2.b = 25; + steps[0].gradColor2.set = true; steps[0].fillMode = VectorRenderer::kFillGradient; steps[0].drawingCall = &VectorRenderer::drawCallback_FILLSURFACE; - 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].fillArea = true; - steps[1].drawingCall = &VectorRenderer::drawCallback_ROUNDSQ; - steps[1].scale = (1 << 16); - - steps[2].radius = 8; // radius - 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].drawingCall = &VectorRenderer::drawCallback_ROUNDSQ; - steps[2].scale = (1 << 16); - - steps[3].fgColor.r = 255; - steps[3].fgColor.g = 255; - steps[3].fgColor.b = 255; - steps[3].drawingCall = &VectorRenderer::drawCallback_VOID; - - Common::Rect area = Common::Rect(32, 32, 256, 256); - bool running = true; while (running) { // draw!! _vectorRenderer->drawStep(Common::Rect(), steps[0]); - _vectorRenderer->drawStep(Common::Rect(), steps[3]); - _vectorRenderer->drawStep(area, steps[1]); - _vectorRenderer->drawStep(area, steps[2]); -// _vectorRenderer->drawStep(Common::Rect(32, 32, 256, 256), &steps[3]); - _vectorRenderer->copyFrame(_system); Common::Event event; diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 97af6732e0..906c5173e1 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -190,12 +190,13 @@ public: return _initOk && _themeOk; } - bool loadTheme(Common::String &themeName); + bool loadTheme(Common::String themeName); protected: template void screenInit(); - bool loadThemeXML(Common::String &themeName); + bool loadThemeXML(Common::String themeName); + bool loadDefaultXML(); void freeRenderer() { delete _vectorRenderer; @@ -232,6 +233,8 @@ protected: bool _initOk; bool _themeOk; bool _caching; + + static const char *_defaultXML; }; struct WidgetDrawData { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp new file mode 100644 index 0000000000..406e05badf --- /dev/null +++ b/gui/ThemeDefaultXML.cpp @@ -0,0 +1,57 @@ +/* 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$ + * + */ + +#include "common/system.h" +#include "gui/InterfaceManager.h" + +namespace GUI { + +bool InterfaceManager::loadDefaultXML() { + const char *defaultXML = +/** + * Default theme description file. Work in progress. + * Newlines are not necessary, parser ignores them. + * You may use single quotes (') instead of scaped double quotes. + * Remember to indent properly the XML so it's easier to read and + * to maintain! + */ +"" + "" + "" + "" + "" + "" + "" + "" + "" +""; + + if (!parser()->loadBuffer(defaultXML, true)) + return false; + + return parser()->parse(); +} + +} diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 6e60d8a499..5c0d1cbbdc 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -45,6 +45,7 @@ ThemeParser::ThemeParser() : XMLParser() { _callbacks["palette"] = &ThemeParser::parserCallback_palette; _callbacks["color"] = &ThemeParser::parserCallback_color; _callbacks["render_info"] = &ThemeParser::parserCallback_renderInfo; + _callbacks["layout_info"] = &ThemeParser::parserCallback_layoutInfo; _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; @@ -97,6 +98,17 @@ bool ThemeParser::parserCallback_renderInfo() { return true; } +bool ThemeParser::parserCallback_layoutInfo() { + ParserNode *layoutNode = getActiveNode(); + + assert(layoutNode->name == "layout_info"); + + if (getParentNode(layoutNode) != 0) + return parserError(" keys must be root elements."); + + return true; +} + bool ThemeParser::parserCallback_palette() { ParserNode *paletteNode = getActiveNode(); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c012e4fb45..95d9135e12 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -323,6 +323,8 @@ protected: bool parserCallback_palette(); bool parserCallback_color(); bool parserCallback_renderInfo(); + bool parserCallback_layoutInfo(); + bool validateKeyIntSigned(const char *key) { if (!isdigit(*key) && *key != '+' && *key != '-') diff --git a/gui/module.mk b/gui/module.mk index eecf9a093d..81be839777 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -25,6 +25,7 @@ MODULE_OBJS := \ widget.o \ theme.o \ ThemeClassic.o \ + ThemeDefaultXML.o \ ThemeModern.o \ ThemeParser.o \ theme-config.o -- cgit v1.2.3 From 5534ce68a17aeeb0e1dff74297d85ff7af1b9f9e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 26 Jun 2008 19:54:55 +0000 Subject: - MILESTONE: A widget is drawn on screen loaded straight from its XML description. Yippie. - XMLParser: Bugfixes. - ThemeParser: Support for default color values. svn-id: r32808 --- common/xmlparser.cpp | 6 +- gui/InterfaceManager.cpp | 17 +--- gui/ThemeDefaultXML.cpp | 6 +- gui/ThemeParser.cpp | 204 ++++++++++++++++++++++++++++++----------------- gui/ThemeParser.h | 6 ++ 5 files changed, 150 insertions(+), 89 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 22b8b22e48..8ff93a4c59 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -61,10 +61,12 @@ bool XMLParser::parserError(const char *errorString, ...) { printf("%s%s%s\n", startFull ? "" : "...", endFull ? "" : "...", lineStr); + int cursor = MIN(_pos - lineStart, 70); + if (!startFull) - lineStart -= 3; + cursor += 3; - for (int i = 0; i < _pos - lineStart; ++i) + while (cursor--) printf(" "); printf("^\n"); diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index ac04e56bc0..43d2aa7864 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -261,23 +261,12 @@ int InterfaceManager::runGUI() { _system->showOverlay(); - Graphics::DrawStep *steps = new Graphics::DrawStep[2]; - - steps[0].gradColor1.r = 214; - steps[0].gradColor1.g = 113; - steps[0].gradColor1.b = 8; - steps[0].gradColor1.set = true; - steps[0].gradColor2.r = 240; - steps[0].gradColor2.g = 200; - steps[0].gradColor2.b = 25; - steps[0].gradColor2.set = true; - steps[0].fillMode = VectorRenderer::kFillGradient; - steps[0].drawingCall = &VectorRenderer::drawCallback_FILLSURFACE; - bool running = true; while (running) { // draw!! - _vectorRenderer->drawStep(Common::Rect(), steps[0]); + drawDD(kDDMainDialogBackground, Common::Rect()); + drawDD(kDDButtonIdle, Common::Rect(32, 32, 128, 128)); + _vectorRenderer->copyFrame(_system); Common::Event event; diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 406e05badf..6067a44545 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -43,8 +43,12 @@ bool InterfaceManager::loadDefaultXML() { "" "" "" + "" "" - "" + "" + "" + "" + "" "" ""; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 5c0d1cbbdc..6665154cd2 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -46,6 +46,7 @@ ThemeParser::ThemeParser() : XMLParser() { _callbacks["color"] = &ThemeParser::parserCallback_color; _callbacks["render_info"] = &ThemeParser::parserCallback_renderInfo; _callbacks["layout_info"] = &ThemeParser::parserCallback_layoutInfo; + _callbacks["default"] = &ThemeParser::parserCallback_defaultSet; _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; @@ -55,6 +56,9 @@ ThemeParser::ThemeParser() : XMLParser() { _drawFunctions["triangle"] = &Graphics::VectorRenderer::drawCallback_TRIANGLE; _drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; + + _defaultStepGlobal = defaultDrawStep(); + _defaultStepLocal = 0; } bool ThemeParser::keyCallback(Common::String keyName) { @@ -65,8 +69,7 @@ bool ThemeParser::keyCallback(Common::String keyName) { return (this->*(_callbacks[_activeKey.top()->name]))(); } -Graphics::DrawStep *ThemeParser::newDrawStep() { - +Graphics::DrawStep *ThemeParser::defaultDrawStep() { Graphics::DrawStep *step = new DrawStep; step->fgColor.set = false; @@ -85,6 +88,42 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { return step; } +Graphics::DrawStep *ThemeParser::newDrawStep() { + assert(_defaultStepGlobal); + Graphics::DrawStep *step = new DrawStep; + + if (_defaultStepLocal) { + memcpy(step, _defaultStepLocal, sizeof(DrawStep)); + } else { + memcpy(step, _defaultStepGlobal, sizeof(DrawStep)); + } + + return step; +} + +bool ThemeParser::parserCallback_defaultSet() { + ParserNode *defNode = getActiveNode(); + ParserNode *parentNode = getParentNode(defNode); + Graphics::DrawStep *step = 0; + + if (parentNode == 0) + return parserError("The key must be contained inside keys."); + + if (parentNode->name == "render_info") { + step = _defaultStepGlobal; + } else if (parentNode->name == "drawdata") { + if (_defaultStepLocal == 0) + _defaultStepLocal = new DrawStep; + + memcpy(_defaultStepLocal, _defaultStepGlobal, sizeof(DrawStep)); + step = _defaultStepLocal; + } else { + return parserError(" key out of scope. Must be inside or keys."); + } + + return parseDrawStep(defNode, step, false); +} + bool ThemeParser::parserCallback_renderInfo() { ParserNode *infoNode = getActiveNode(); @@ -159,6 +198,10 @@ bool ThemeParser::parserCallback_DRAWSTEP() { assert(drawdataNode->values.contains("id")); Graphics::DrawStep *drawstep = newDrawStep(); + + if (!stepNode->values.contains("func")) + return parserError("All Draw Steps must contain a 'func' definition."); + Common::String functionName = stepNode->values["func"]; if (_drawFunctions.contains(functionName) == false) @@ -166,6 +209,56 @@ bool ThemeParser::parserCallback_DRAWSTEP() { drawstep->drawingCall = _drawFunctions[functionName]; + if (!parseDrawStep(stepNode, drawstep, true)) + return false; + + g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep); + return true; +} + +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 section."); + + if (drawdataNode->values.contains("id") == false) + return parserError("DrawData keys must contain an identifier."); + + InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]); + + if (id == -1) + return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); + + if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") { + cached = true; + } + + // Both Max and Johannes suggest using a non-platform specfic approach based on available + // resources and active resolution. getHostPlatformString() has been removed, so fix this. + +/* 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) + return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); + + if (_defaultStepLocal) { + delete _defaultStepLocal; + _defaultStepLocal = 0; + } + + return true; +} + +bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific) { int red, green, blue, w, h; Common::String val; @@ -226,42 +319,47 @@ bool ThemeParser::parserCallback_DRAWSTEP() { __PARSER_ASSIGN_RGB(gradColor1, "gradient_start"); __PARSER_ASSIGN_RGB(gradColor2, "gradient_end"); - if (functionName == "roundedsq" || functionName == "circle") { - __PARSER_ASSIGN_INT(radius, "radius", true) - } + if (functionSpecific) { + assert(stepNode->values.contains("func")); + Common::String functionName = stepNode->values["func"]; - if (functionName == "bevelsq") { - __PARSER_ASSIGN_INT(extraData, "bevel", true); - } + if (functionName == "roundedsq" || functionName == "circle") { + __PARSER_ASSIGN_INT(radius, "radius", true) + } - if (functionName == "triangle") { - drawstep->extraData = VectorRenderer::kTriangleUp; - - if (stepNode->values.contains("orientation")) { - val = stepNode->values["orientation"]; - - if ( val == "top") - drawstep->extraData = VectorRenderer::kTriangleUp; - else if (val == "bottom") - drawstep->extraData = VectorRenderer::kTriangleDown; - else if (val == "left") - drawstep->extraData = VectorRenderer::kTriangleLeft; - else if (val == "right") - drawstep->extraData = VectorRenderer::kTriangleRight; - else - return parserError("'%s' is not a valid value for triangle orientation.", val.c_str()); + if (functionName == "bevelsq") { + __PARSER_ASSIGN_INT(extraData, "bevel", true); } - } - if (stepNode->values.contains("size")) { - if (stepNode->values["size"] == "auto") { - drawstep->fillArea = true; - } else if (sscanf(stepNode->values["size"].c_str(), "%d, %d", &w, &h) == 2) { - drawstep->fillArea = false; - drawstep->w = w; - drawstep->h = h; - } else { - return parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); + if (functionName == "triangle") { + drawstep->extraData = VectorRenderer::kTriangleUp; + + if (stepNode->values.contains("orientation")) { + val = stepNode->values["orientation"]; + + if ( val == "top") + drawstep->extraData = VectorRenderer::kTriangleUp; + else if (val == "bottom") + drawstep->extraData = VectorRenderer::kTriangleDown; + else if (val == "left") + drawstep->extraData = VectorRenderer::kTriangleLeft; + else if (val == "right") + drawstep->extraData = VectorRenderer::kTriangleRight; + else + return parserError("'%s' is not a valid value for triangle orientation.", val.c_str()); + } + } + + if (stepNode->values.contains("size")) { + if (stepNode->values["size"] == "auto") { + drawstep->fillArea = true; + } else if (sscanf(stepNode->values["size"].c_str(), "%d, %d", &w, &h) == 2) { + drawstep->fillArea = false; + drawstep->w = w; + drawstep->h = h; + } else { + return parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); + } } } @@ -282,44 +380,6 @@ bool ThemeParser::parserCallback_DRAWSTEP() { #undef __PARSER_ASSIGN_INT #undef __PARSER_ASSIGN_RGB - g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep); - return true; -} - -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 section."); - - if (drawdataNode->values.contains("id") == false) - return parserError("DrawData keys must contain an identifier."); - - InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]); - - if (id == -1) - return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); - - if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") { - cached = true; - } - - // Both Max and Johannes suggest using a non-platform specfic approach based on available - // resources and active resolution. getHostPlatformString() has been removed, so fix this. - -/* 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) - return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); - return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 95d9135e12..2a7e0999d5 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -324,6 +324,7 @@ protected: bool parserCallback_color(); bool parserCallback_renderInfo(); bool parserCallback_layoutInfo(); + bool parserCallback_defaultSet(); bool validateKeyIntSigned(const char *key) { @@ -345,6 +346,11 @@ protected: } Graphics::DrawStep *newDrawStep(); + Graphics::DrawStep *defaultDrawStep(); + bool parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific); + + Graphics::DrawStep *_defaultStepGlobal; + Graphics::DrawStep *_defaultStepLocal; Common::HashMap _drawFunctions; Common::HashMap _callbacks; -- cgit v1.2.3 From 8d696760b37e1dd36191a7403d44d4de105bd7de Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 26 Jun 2008 23:15:34 +0000 Subject: Bugfixes svn-id: r32814 --- gui/InterfaceManager.cpp | 3 ++- gui/ThemeDefaultXML.cpp | 8 +++++++- gui/ThemeParser.cpp | 8 ++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 43d2aa7864..cbaf1bbf5b 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -257,7 +257,8 @@ void InterfaceManager::drawScrollbar(const Common::Rect &r, int sliderY, int sli int InterfaceManager::runGUI() { Common::EventManager *eventMan = _system->getEventManager(); - loadTheme("modern_theme.xml"); + if (!loadTheme("modern_theme.xml")) + return 0; _system->showOverlay(); diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 6067a44545..0d9faf0768 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -43,14 +43,20 @@ bool InterfaceManager::loadDefaultXML() { "" "" "" + "" + "" "" "" + "" "" "" -""; +"" + +"" +""; if (!parser()->loadBuffer(defaultXML, true)) return false; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 6665154cd2..671a4a543e 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -233,8 +233,12 @@ bool ThemeParser::parserCallback_DRAWDATA() { if (id == -1) return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); - if (drawdataNode->values.contains("cached") && drawdataNode->values["cached"] == "true") { - cached = true; + if (drawdataNode->values.contains("cache")) { + if (drawdataNode->values["cache"] == "true") + cached = true; + else if (drawdataNode->values["cache"] == "false") + cached = false; + else return parserError("'Parsed' value must be either true or false."); } // Both Max and Johannes suggest using a non-platform specfic approach based on available -- cgit v1.2.3 From 3f0f7fa08bea272fa61b0fde5d7783aa44b1ff25 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 28 Jun 2008 00:02:54 +0000 Subject: Improved support for parsing integers in the XML parser. Bug fixes. svn-id: r32818 --- common/xmlparser.h | 47 ++++++++++++++++++++++++++++++++++++++++++++++- gui/InterfaceManager.cpp | 2 +- gui/ThemeDefaultXML.cpp | 2 +- gui/ThemeParser.cpp | 10 +++++----- gui/ThemeParser.h | 19 ------------------- 5 files changed, 53 insertions(+), 27 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 4c8e1b986f..c3cdbc3e02 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -55,7 +55,7 @@ public: return _stream; } - const char operator [](int idx) { + char operator [](int idx) { assert(_stream && idx >= 0); if (_pos + 1 != idx) @@ -287,6 +287,51 @@ protected: return isspace(_text[_pos]) != 0 || _text[_pos] == '>'; } + /** + * Parses the values inside an integer key. + * The count parameter specifies the number of values inside + * the key, which are expected to be separated with commas. + * + * Sample usage: + * parseIntegerKey("255, 255, 255", 3, &red, &green, &blue); + * [will parse each field into its own integer] + * + * parseIntegerKey("1234", 1, &number); + * [will parse the single number into the variable] + * + * @param key String containing the integers to be parsed. + * @param count Number of comma-separated ints in the string. + * @param ... Integer variables to store the parsed ints, passed + * by reference. + * @returns True if the parsing succeeded. + */ + virtual bool parseIntegerKey(const char *key, int count, ...) { + char *parseEnd = 0; + int *num_ptr; + + va_list args; + va_start(args, count); + + while (count--) { + while (isspace(*key)) + key++; + + num_ptr = va_arg(args, int*); + *num_ptr = strtol(key, &parseEnd, 10); + + while (isspace(*parseEnd)) + parseEnd++; + + if (count && *parseEnd++ != ',') + return false; + + key = parseEnd; + } + + va_end(args); + return (*parseEnd == 0); + } + int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index cbaf1bbf5b..7a779df593 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -137,7 +137,7 @@ bool InterfaceManager::loadTheme(Common::String themeName) { warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure - error("Could not load default embeded theme."); + error("Could not load default embeded theme"); } for (int i = 0; i < kDrawDataMAX; ++i) { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 0d9faf0768..cd571e680e 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -51,7 +51,7 @@ bool InterfaceManager::loadDefaultXML() { "" "" - "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 671a4a543e..8dc02297b7 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -175,7 +175,7 @@ bool ThemeParser::parserCallback_color() { int red, green, blue; - if (sscanf(colorNode->values["rgb"].c_str(), "%d, %d, %d", &red, &green, &blue) != 3 || + if (parseIntegerKey(colorNode->values["rgb"].c_str(), 3, &red, &green, &blue) == false || 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());\ @@ -263,7 +263,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { } bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific) { - int red, green, blue, w, h; + int red, green, blue, w, h, x; Common::String val; /** @@ -278,10 +278,10 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst */ #define __PARSER_ASSIGN_INT(struct_name, key_name, force) \ if (stepNode->values.contains(key_name)) { \ - if (!validateKeyInt(stepNode->values[key_name].c_str()))\ + if (!parseIntegerKey(stepNode->values[key_name].c_str(), 1, &x)) \ return parserError("Error when parsing key value for '%s'.", key_name); \ \ - drawstep->struct_name = atoi(stepNode->values[key_name].c_str()); \ + drawstep->struct_name = x; \ } else if (force) { \ return parserError("Missing necessary key '%s'.", key_name); \ } @@ -304,7 +304,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst 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 || \ + } 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 when parsing color struct '%s'", val.c_str());\ \ diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 2a7e0999d5..55f39d8a44 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -325,25 +325,6 @@ protected: bool parserCallback_renderInfo(); bool parserCallback_layoutInfo(); bool parserCallback_defaultSet(); - - - 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(); Graphics::DrawStep *defaultDrawStep(); -- cgit v1.2.3 From 2f5319e7507d1ac5733a7d0a5b9021465c7eda19 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 28 Jun 2008 13:44:10 +0000 Subject: Bugfix: Empty integer key parsing. svn-id: r32822 --- common/xmlparser.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index c3cdbc3e02..4850dc5113 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -306,7 +306,7 @@ protected: * @returns True if the parsing succeeded. */ virtual bool parseIntegerKey(const char *key, int count, ...) { - char *parseEnd = 0; + char *parseEnd; int *num_ptr; va_list args; @@ -319,17 +319,17 @@ protected: num_ptr = va_arg(args, int*); *num_ptr = strtol(key, &parseEnd, 10); - while (isspace(*parseEnd)) - parseEnd++; + key = parseEnd; - if (count && *parseEnd++ != ',') - return false; + while (isspace(*key)) + key++; - key = parseEnd; + if (count && *key++ != ',') + return false; } va_end(args); - return (*parseEnd == 0); + return (*key == 0); } int _pos; /** Current position on the XML buffer. */ -- cgit v1.2.3 From 0e4cd6fc8ea9d72f4d07dbfeabcabf50d6d1c2bd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 28 Jun 2008 16:49:39 +0000 Subject: Expanded InterfaceManager API to mimic NewGUI. (WIP) svn-id: r32831 --- base/main.cpp | 2 +- gui/InterfaceManager.cpp | 119 ++++++++++++++++++++++++++++++++++++-------- gui/InterfaceManager.h | 127 ++++++++++++++++++++++++++++++++++++++++------- gui/dialog.h | 2 + 4 files changed, 211 insertions(+), 39 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 53b4cb7cf4..72766292b3 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -70,7 +70,7 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); -#if 1 +#if defined LOL g_InterfaceManager.runGUI(); return true; diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index 7a779df593..f7a197f2fb 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -70,7 +70,8 @@ const char *InterfaceManager::kDrawDataStrings[] = { InterfaceManager::InterfaceManager() : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false) { + _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), + _needThemeLoad(false), _enabled(false) { _system = g_system; _parser = new ThemeParser(); @@ -78,7 +79,11 @@ InterfaceManager::InterfaceManager() : _widgets[i] = 0; } - setGraphicsMode(kGfxStandard16bit); + _graphicsMode = kGfxAntialias16bit; // default GFX mode + // TODO: load this from a config file + +// setGraphicsMode(kGfxStandard16bit); +// printf("Singleton init!"); } template @@ -91,11 +96,6 @@ void InterfaceManager::screenInit() { } void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { - if (mode == _graphicsMode) - return; - - _graphicsMode = mode; - switch (mode) { case kGfxStandard16bit: case kGfxAntialias16bit: @@ -127,7 +127,6 @@ bool InterfaceManager::addDrawData(DrawData data_id, bool cached) { _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; - _widgets[data_id]->_type = data_id; return true; } @@ -174,8 +173,15 @@ bool InterfaceManager::loadThemeXML(Common::String themeName) { return parser()->parse(); } -bool InterfaceManager::init() { - return false; +void InterfaceManager::init() { + if (!_screen || _system->getOverlayWidth() != _screen->w || + _system->getOverlayHeight() != _screen->h ) + setGraphicsMode(_graphicsMode); + + if (needThemeReload()) + loadTheme(); + + _initOk = true; } bool InterfaceManager::isWidgetCached(DrawData type, const Common::Rect &r) { @@ -199,7 +205,7 @@ void InterfaceManager::drawDD(DrawData type, const Common::Rect &r) { } void InterfaceManager::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!_initOk) + if (!ready()) return; if (state == kStateEnabled) @@ -213,7 +219,7 @@ void InterfaceManager::drawButton(const Common::Rect &r, const Common::String &s } void InterfaceManager::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!_initOk) + if (!ready()) return; drawDD(kDDSeparator, r); @@ -221,7 +227,7 @@ void InterfaceManager::drawLineSeparator(const Common::Rect &r, WidgetStateInfo } void InterfaceManager::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!_initOk) + if (!ready()) return; drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r); @@ -236,7 +242,7 @@ void InterfaceManager::drawCheckbox(const Common::Rect &r, const Common::String } void InterfaceManager::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { - if (!_initOk) + if (!ready()) return; drawDD(kDDSliderEmpty, r); @@ -250,20 +256,27 @@ void InterfaceManager::drawSlider(const Common::Rect &r, int width, WidgetStateI } void InterfaceManager::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { - if (!_initOk) + if (!ready()) return; } int InterfaceManager::runGUI() { + if (!ready()) + return 0; + Common::EventManager *eventMan = _system->getEventManager(); + Dialog *activeDialog = getTopDialog(); - if (!loadTheme("modern_theme.xml")) + if (!activeDialog) return 0; - _system->showOverlay(); - + bool didSaveState = false; bool running = true; - while (running) { // draw!! + + int button; + uint32 time; + + while (!_dialogStack.empty() && activeDialog == getTopDialog()) { // draw!! drawDD(kDDMainDialogBackground, Common::Rect()); drawDD(kDDButtonIdle, Common::Rect(32, 32, 128, 128)); @@ -272,10 +285,74 @@ int InterfaceManager::runGUI() { Common::Event event; _system->delayMillis(100); + while (eventMan->pollEvent(event)) { - if (event.type == Common::EVENT_QUIT) - running = false; + + if (activeDialog != getTopDialog() && + event.type != Common::EVENT_QUIT && + event.type != Common::EVENT_SCREEN_CHANGED) + continue; + + Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); + + switch (event.type) { + case Common::EVENT_KEYDOWN: + activeDialog->handleKeyDown(event.kbd); + break; + + case Common::EVENT_KEYUP: + activeDialog->handleKeyUp(event.kbd); + break; + + case Common::EVENT_MOUSEMOVE: + activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); + break; + + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2); + time = _system->getMillis(); + if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay) + && ABS(_lastClick.x - event.mouse.x) < 3 + && ABS(_lastClick.y - event.mouse.y) < 3) { + _lastClick.count++; + } else { + _lastClick.x = event.mouse.x; + _lastClick.y = event.mouse.y; + _lastClick.count = 1; + } + _lastClick.time = time; + activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count); + break; + + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2); + activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count); + break; + + case Common::EVENT_WHEELUP: + activeDialog->handleMouseWheel(mouse.x, mouse.y, -1); + break; + + case Common::EVENT_WHEELDOWN: + activeDialog->handleMouseWheel(mouse.x, mouse.y, 1); + break; + + case Common::EVENT_QUIT: + _system->quit(); + return 1; + + case Common::EVENT_SCREEN_CHANGED: + screenChange(); + break; + + default: + break; + } } + + _system->delayMillis(10); } _system->hideOverlay(); diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 906c5173e1..779f9aab57 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -33,6 +33,7 @@ #include "graphics/surface.h" #include "graphics/fontman.h" +#include "gui/dialog.h" #include "gui/ThemeParser.h" #include "graphics/VectorRenderer.h" @@ -43,12 +44,37 @@ namespace GUI { struct WidgetDrawData; class InterfaceManager; +struct WidgetDrawData { + Common::Array _steps; + + bool _cached; + Graphics::Surface *_surfaceCache; + uint32 _cachedW, _cachedH; + + ~WidgetDrawData() { + for (uint i = 0; i < _steps.size(); ++i) + delete _steps[i]; + + _steps.clear(); + + if (_surfaceCache) { + _surfaceCache->free(); + delete _surfaceCache; + } + } +}; + class InterfaceManager : public Common::Singleton { - friend class Common::Singleton; typedef Common::String String; + typedef GUI::Dialog Dialog; + + friend class GUI::Dialog; + friend class GUI::GuiObject; + friend class Common::Singleton; static const char *kDrawDataStrings[]; + static const int kMaxDialogDepth = 4; public: enum Graphics_Mode { @@ -57,6 +83,11 @@ public: kGfxAntialias16bit }; + enum { + kDoubleClickDelay = 500, // milliseconds + kCursorAnimateDelay = 250 + }; + enum DrawData { kDDMainDialogBackground, kDDSpecialColorBackground, @@ -150,8 +181,7 @@ public: void setGraphicsMode(Graphics_Mode mode); int runGUI(); - bool init(); - bool deinit(); + void init(); /** Font management */ const Graphics::Font *getFont(FontStyle font) const { return _font; } @@ -190,6 +220,43 @@ public: return _initOk && _themeOk; } + void refresh() { + init(); + if (_enabled) { + _system->showOverlay(); +// CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); +// CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + } + } + + void enable() { + init(); + _system->showOverlay(); + _enabled = true; + } + + void disable() { + _system->hideOverlay(); + _enabled = false; + } + + void deinit() { + if (_initOk) { + _system->hideOverlay(); + _initOk = false; + } + } + + bool loadTheme() { + ConfMan.registerDefault("gui_theme", "default"); + Common::String style(ConfMan.get("gui_theme")); + + if (style.compareToIgnoreCase("default") == 0) + style = "modern"; + + return loadTheme(style); + } + bool loadTheme(Common::String themeName); protected: @@ -198,6 +265,18 @@ protected: bool loadThemeXML(Common::String themeName); bool loadDefaultXML(); + void unloadTheme() { + if (!_themeOk) + return; + + for (int i = 0; i < kDrawDataMAX; ++i) { + delete _widgets[i]; + _widgets[i] = 0; + } + } + + void screenChange() {} + void freeRenderer() { delete _vectorRenderer; _vectorRenderer = 0; @@ -211,17 +290,33 @@ protected: } } + Dialog *getTopDialog() const { + if (_dialogStack.empty()) + return 0; + return _dialogStack.top(); + } + + bool needThemeReload() { + return (_themeOk == false || _needThemeLoad == true); + } + + bool isWidgetCached(DrawData type, const Common::Rect &r); void drawCached(DrawData type, const Common::Rect &r); inline void drawDD(DrawData type, const Common::Rect &r); - void addDirtyRect(const Common::Rect &r) {} + + void addDirtyRect(const Common::Rect &r) { + _dirtyScreen.extend(r); + } OSystem *_system; Graphics::VectorRenderer *_vectorRenderer; - Graphics::Surface *_screen; GUI::ThemeParser *_parser; + Graphics::Surface *_screen; + Graphics::Surface *_screenCache; + int _bytesPerPixel; Graphics_Mode _graphicsMode; @@ -229,22 +324,20 @@ protected: const Graphics::Font *_font; WidgetDrawData *_widgets[kDrawDataMAX]; + Common::FixedStack _dialogStack; + Common::Rect _dirtyScreen; bool _initOk; bool _themeOk; bool _caching; - - static const char *_defaultXML; -}; - -struct WidgetDrawData { - Common::Array _steps; - - bool _cached; - Graphics::Surface *_surfaceCache; - uint32 _cachedW, _cachedH; - - InterfaceManager::DrawData _type; + bool _needThemeLoad; + bool _enabled; + + struct { + int16 x, y; // Position of mouse when the click occured + uint32 time; // Time + int count; // How often was it already pressed? + } _lastClick; }; } // end of namespace GUI. diff --git a/gui/dialog.h b/gui/dialog.h index d17d3a5ad1..f34e9d2e0d 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -42,7 +42,9 @@ enum { }; class Dialog : public GuiObject { + // TANOKU-TODO: remove newgui from here friend class NewGui; + friend class InterfaceManager; protected: Widget *_mouseWidget; Widget *_focusedWidget; -- cgit v1.2.3 From f1173f52a24de56fd7ad91e5806917db8c11ee63 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 29 Jun 2008 12:08:53 +0000 Subject: Changes to rendering pipeline. WIP. svn-id: r32837 --- graphics/VectorRenderer.h | 15 +++++++------- gui/InterfaceManager.cpp | 52 ++++++++++++++++++++++++++++++++++------------- gui/InterfaceManager.h | 36 +++++++------------------------- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index d989781d5c..9b2e6cd383 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -406,7 +406,7 @@ public: * * @param sys Pointer to the global System class */ - virtual void copyFrame(OSystem *sys) = 0; + virtual void copyFrame(OSystem *sys, Common::Rect &r) = 0; /** * Blits a given graphics surface on top of the current drawing surface. @@ -533,15 +533,14 @@ public: /** * @see VectorRenderer::copyFrame() */ - virtual void copyFrame(OSystem *sys) { -#ifdef OVERLAY_MULTIPLE_DEPTHS - sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->w); + virtual void copyFrame(OSystem *sys, Common::Rect &r) { +#ifdef OVERLAY_MULTIPLE_DEPTHS // TODO: change OSystem to support templated copyRectToOverlay + sys->copyRectToOverlay((const PixelType*)_activeSurface->pixels, + _activeSurface->pitch, r.top, r.left, r.width(), r.height()); #else - sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->w); + sys->copyRectToOverlay((const OverlayColor*)_activeSurface->pixels, + _activeSurface->pitch, r.top, r.left, r.width(), r.height()); #endif - sys->updateScreen(); } /** diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index f7a197f2fb..d4a0a167ff 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -81,9 +81,6 @@ InterfaceManager::InterfaceManager() : _graphicsMode = kGfxAntialias16bit; // default GFX mode // TODO: load this from a config file - -// setGraphicsMode(kGfxStandard16bit); -// printf("Singleton init!"); } template @@ -96,6 +93,15 @@ void InterfaceManager::screenInit() { } void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { + + // FIXME: reload theme everytime we change resolution... + // what if we change the renderer too? + // ...We may need to reload it to re-cache the widget + // surfaces + if (_system->getOverlayWidth() != _screen->w || + _system->getOverlayHeight() != _screen->h) + _needThemeLoad = true; + switch (mode) { case kGfxStandard16bit: case kGfxAntialias16bit: @@ -132,6 +138,8 @@ bool InterfaceManager::addDrawData(DrawData data_id, bool cached) { } bool InterfaceManager::loadTheme(Common::String themeName) { + unloadTheme(); + if (!loadThemeXML(themeName)) { warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); @@ -150,6 +158,7 @@ bool InterfaceManager::loadTheme(Common::String themeName) { } } + _needThemeLoad = false; _themeOk = true; return true; } @@ -260,38 +269,52 @@ void InterfaceManager::drawScrollbar(const Common::Rect &r, int sliderY, int sli return; } +void InterfaceManager::redrawDialogStack() { + _vectorRenderer->clearSurface(); + + for (int i = 0; i < _dialogStack.size(); ++i) + _dialogStack[i]->draw(); +} + int InterfaceManager::runGUI() { + init(); + if (!ready()) return 0; Common::EventManager *eventMan = _system->getEventManager(); Dialog *activeDialog = getTopDialog(); + Dialog *lastDialog = 0; if (!activeDialog) return 0; bool didSaveState = false; - bool running = true; + bool stackChange = true; int button; uint32 time; - while (!_dialogStack.empty() && activeDialog == getTopDialog()) { // draw!! + _system->showOverlay(); - drawDD(kDDMainDialogBackground, Common::Rect()); - drawDD(kDDButtonIdle, Common::Rect(32, 32, 128, 128)); + while (activeDialog) { // draw!! + stackChange = (activeDialog != lastDialog); + lastDialog = activeDialog; - _vectorRenderer->copyFrame(_system); + if (stackChange || needRedraw()) + redrawDialogStack(); + + if (!_dirtyScreen.empty()) { + for (uint i = 0; i < _dirtyScreen.size(); ++i) + _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); + _system->updateScreen(); + _dirtyScreen.clear(); + } Common::Event event; - _system->delayMillis(100); while (eventMan->pollEvent(event)) { - - if (activeDialog != getTopDialog() && - event.type != Common::EVENT_QUIT && - event.type != Common::EVENT_SCREEN_CHANGED) - continue; + activeDialog->handleTickle(); Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); @@ -352,6 +375,7 @@ int InterfaceManager::runGUI() { } } + activeDialog = getTopDialog(); _system->delayMillis(10); } diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 779f9aab57..07fa0ea24e 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -220,33 +220,6 @@ public: return _initOk && _themeOk; } - void refresh() { - init(); - if (_enabled) { - _system->showOverlay(); -// CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); -// CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - } - } - - void enable() { - init(); - _system->showOverlay(); - _enabled = true; - } - - void disable() { - _system->hideOverlay(); - _enabled = false; - } - - void deinit() { - if (_initOk) { - _system->hideOverlay(); - _initOk = false; - } - } - bool loadTheme() { ConfMan.registerDefault("gui_theme", "default"); Common::String style(ConfMan.get("gui_theme")); @@ -300,6 +273,11 @@ protected: return (_themeOk == false || _needThemeLoad == true); } + bool needRedraw() { + return true; + } + + void redrawDialogStack(); bool isWidgetCached(DrawData type, const Common::Rect &r); void drawCached(DrawData type, const Common::Rect &r); @@ -307,7 +285,7 @@ protected: inline void drawDD(DrawData type, const Common::Rect &r); void addDirtyRect(const Common::Rect &r) { - _dirtyScreen.extend(r); + _dirtyScreen.push_back(r); } OSystem *_system; @@ -325,7 +303,7 @@ protected: WidgetDrawData *_widgets[kDrawDataMAX]; Common::FixedStack _dialogStack; - Common::Rect _dirtyScreen; + Common::Array _dirtyScreen; bool _initOk; bool _themeOk; -- cgit v1.2.3 From e44505cda44d091d43eeea4bc05a7eb1919ec63a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 29 Jun 2008 19:59:16 +0000 Subject: Rendering pipeline. WIP. svn-id: r32845 --- gui/InterfaceManager.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 07fa0ea24e..0a0c62c9f8 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -175,7 +175,11 @@ public: ~InterfaceManager() { freeRenderer(); freeScreen(); + unloadTheme(); delete _parser; + + while (!_dialogStack.empty()) + delete _dialogStack.pop(); } void setGraphicsMode(Graphics_Mode mode); @@ -269,6 +273,10 @@ protected: return _dialogStack.top(); } + void openDialog(Dialog *dlg) { + _dialogStack.push(dlg); + } + bool needThemeReload() { return (_themeOk == false || _needThemeLoad == true); } @@ -293,7 +301,6 @@ protected: GUI::ThemeParser *_parser; Graphics::Surface *_screen; - Graphics::Surface *_screenCache; int _bytesPerPixel; Graphics_Mode _graphicsMode; -- cgit v1.2.3 From 6c85e960b202ea8cb3af87c7d3c644690f51e511 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 1 Jul 2008 15:57:30 +0000 Subject: Rendering pipeline. WIP. svn-id: r32869 --- base/main.cpp | 6 ++++-- gui/InterfaceManager.cpp | 23 ++++++++++++++++++++--- gui/InterfaceManager.h | 20 ++++++++++++-------- gui/ThemeParser.cpp | 9 +++++---- gui/ThemeParser.h | 6 +++++- gui/object.h | 3 +++ 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 72766292b3..f69b8399e6 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -72,8 +72,10 @@ static bool launcherDialog(OSystem &system) { #if defined LOL - g_InterfaceManager.runGUI(); - return true; +// g_InterfaceManager.runGUI(); + InterfaceManager *manager = new InterfaceManager(); + manager->openDialog(kDialogLauncher); + return (manager.runGUI() != -1); #else diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp index d4a0a167ff..80fa0d33db 100644 --- a/gui/InterfaceManager.cpp +++ b/gui/InterfaceManager.cpp @@ -30,6 +30,8 @@ #include "common/events.h" #include "common/config-manager.h" +#include "gui/launcher.h" + #include "gui/InterfaceManager.h" #include "graphics/VectorRenderer.h" @@ -73,7 +75,7 @@ InterfaceManager::InterfaceManager() : _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _needThemeLoad(false), _enabled(false) { _system = g_system; - _parser = new ThemeParser(); + _parser = new ThemeParser(this); for (int i = 0; i < kDrawDataMAX; ++i) { _widgets[i] = 0; @@ -276,6 +278,22 @@ void InterfaceManager::redrawDialogStack() { _dialogStack[i]->draw(); } +void InterfaceManager::openDialog(Dialogs dname, Dialog *parent) { + Dialog *dlg = 0; + switch (dname) { + case kDialogLauncher: + dlg = new GUI::LauncherDialog; + break; + + default: + error("Unhandled dialog opening"); + break; + } + + if (dlg) + _dialogStack.push(dlg); +} + int InterfaceManager::runGUI() { init(); @@ -289,8 +307,7 @@ int InterfaceManager::runGUI() { if (!activeDialog) return 0; - bool didSaveState = false; - bool stackChange = true; + bool stackChange; int button; uint32 time; diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h index 0a0c62c9f8..ac612e0c52 100644 --- a/gui/InterfaceManager.h +++ b/gui/InterfaceManager.h @@ -39,8 +39,6 @@ namespace GUI { -#define g_InterfaceManager (GUI::InterfaceManager::instance()) - struct WidgetDrawData; class InterfaceManager; @@ -64,14 +62,13 @@ struct WidgetDrawData { } }; -class InterfaceManager : public Common::Singleton { +class InterfaceManager { typedef Common::String String; typedef GUI::Dialog Dialog; friend class GUI::Dialog; friend class GUI::GuiObject; - friend class Common::Singleton; static const char *kDrawDataStrings[]; static const int kMaxDialogDepth = 4; @@ -82,6 +79,11 @@ public: kGfxStandard16bit, kGfxAntialias16bit }; + + enum Dialogs { + kDialogLauncher, + kDialogMAX + }; enum { kDoubleClickDelay = 500, // milliseconds @@ -235,6 +237,12 @@ public: } bool loadTheme(Common::String themeName); + void openDialog(Dialogs dname, Dialog *parent); + + void closeTopDialog() { + assert(_dialogStack.empty() == false); + delete _dialogStack.pop(); + } protected: template void screenInit(); @@ -273,10 +281,6 @@ protected: return _dialogStack.top(); } - void openDialog(Dialog *dlg) { - _dialogStack.push(dlg); - } - bool needThemeReload() { return (_themeOk == false || _needThemeLoad == true); } diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 8dc02297b7..07789ebee3 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -39,7 +39,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -ThemeParser::ThemeParser() : XMLParser() { +ThemeParser::ThemeParser(InterfaceManager *parent) : XMLParser() { _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; _callbacks["palette"] = &ThemeParser::parserCallback_palette; @@ -59,6 +59,7 @@ ThemeParser::ThemeParser() : XMLParser() { _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; + _GUI = parent; } bool ThemeParser::keyCallback(Common::String keyName) { @@ -212,7 +213,7 @@ bool ThemeParser::parserCallback_DRAWSTEP() { if (!parseDrawStep(stepNode, drawstep, true)) return false; - g_InterfaceManager.addDrawStep(drawdataNode->values["id"], drawstep); + _GUI->addDrawStep(drawdataNode->values["id"], drawstep); return true; } @@ -228,7 +229,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { if (drawdataNode->values.contains("id") == false) return parserError("DrawData keys must contain an identifier."); - InterfaceManager::DrawData id = g_InterfaceManager.getDrawDataId(drawdataNode->values["id"]); + InterfaceManager::DrawData id = _GUI->getDrawDataId(drawdataNode->values["id"]); if (id == -1) return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); @@ -251,7 +252,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { } }*/ - if (g_InterfaceManager.addDrawData(id, cached) == false) + if (_GUI->addDrawData(id, cached) == false) return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); if (_defaultStepLocal) { diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 55f39d8a44..68e8272b80 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -36,6 +36,7 @@ #include "common/xmlparser.h" #include "graphics/VectorRenderer.h" +#include "gui/InterfaceManager.h" /** ********************************************* @@ -307,15 +308,18 @@ namespace GUI { using namespace Graphics; using namespace Common; +class InterfaceManager; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); typedef bool (ThemeParser::*ParserCallback)(); + typedef GUI::InterfaceManager InterfaceManager; public: - ThemeParser(); + ThemeParser(InterfaceManager *parent); protected: + InterfaceManager *_GUI; bool keyCallback(Common::String keyName); bool parserCallback_DRAWSTEP(); diff --git a/gui/object.h b/gui/object.h index 01046bd668..2bdff3f76c 100644 --- a/gui/object.h +++ b/gui/object.h @@ -29,6 +29,7 @@ namespace GUI { class CommandReceiver; class CommandSender; +class InterfaceManager; class CommandReceiver { friend class CommandSender; @@ -65,6 +66,7 @@ protected: Common::String _name; Widget *_firstWidget; + InterfaceManager *_GUI; public: GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _name(""), _firstWidget(0) { } @@ -83,6 +85,7 @@ public: virtual void draw() = 0; virtual void reflowLayout(); + virtual void setInterfaceManager(InterfaceManager *manager) { _GUI = manager; } protected: virtual void releaseFocus() = 0; -- cgit v1.2.3 From d385c34dd0c52ccc4c7fff50e88361dbb2cd588d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jul 2008 18:11:41 +0000 Subject: InterfaceManager functionality translated into a Theme subclass "ThemeRenderer" to easen integration with the current GUI. svn-id: r32876 --- base/main.cpp | 4 +- dists/msvc9/scummvm.vcproj | 16 +- graphics/VectorRenderer.cpp | 6 +- graphics/VectorRenderer.h | 2 +- gui/InterfaceManager.cpp | 405 -------------------------------------------- gui/InterfaceManager.h | 334 ------------------------------------ gui/ThemeDefaultXML.cpp | 4 +- gui/ThemeParser.cpp | 13 +- gui/ThemeParser.h | 8 +- gui/ThemeRenderer.cpp | 286 +++++++++++++++++++++++++++++++ gui/ThemeRenderer.h | 297 ++++++++++++++++++++++++++++++++ gui/object.h | 3 - gui/theme.h | 4 + 13 files changed, 615 insertions(+), 767 deletions(-) delete mode 100644 gui/InterfaceManager.cpp delete mode 100644 gui/InterfaceManager.h create mode 100644 gui/ThemeRenderer.cpp create mode 100644 gui/ThemeRenderer.h diff --git a/base/main.cpp b/base/main.cpp index f69b8399e6..9b76e0514a 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -43,7 +43,7 @@ #include "common/system.h" #include "gui/newgui.h" #include "gui/message.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" #include "gui/ThemeParser.h" #if defined(_WIN32_WCE) @@ -70,6 +70,8 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); + GUI::ThemeRenderer *test = new GUI::ThemeRenderer; + #if defined LOL // g_InterfaceManager.runGUI(); diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index cd502b3ca8..a901a0c277 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1104,14 +1104,6 @@ RelativePath="..\..\gui\eval.h" > - - - - @@ -1247,6 +1239,14 @@ /> + + + + diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 1f8ec3c397..f679d2fe67 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -30,17 +30,17 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" #include "graphics/VectorRenderer.h" namespace Graphics { VectorRenderer *createRenderer(int mode) { switch (mode) { - case GUI::InterfaceManager::kGfxStandard16bit: + case GUI::ThemeRenderer::kGfxStandard16bit: return new VectorRendererSpec >; - case GUI::InterfaceManager::kGfxAntialias16bit: + case GUI::ThemeRenderer::kGfxAntialias16bit: return new VectorRendererAA >; default: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 9b2e6cd383..3267d44687 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -32,7 +32,7 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" namespace Graphics { diff --git a/gui/InterfaceManager.cpp b/gui/InterfaceManager.cpp deleted file mode 100644 index 80fa0d33db..0000000000 --- a/gui/InterfaceManager.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* 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$ - * - */ - -#include "common/util.h" -#include "graphics/surface.h" -#include "graphics/colormasks.h" -#include "common/system.h" -#include "common/events.h" -#include "common/config-manager.h" - -#include "gui/launcher.h" - -#include "gui/InterfaceManager.h" -#include "graphics/VectorRenderer.h" - -DECLARE_SINGLETON(GUI::InterfaceManager); - -namespace GUI { - -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), _initOk(false), _themeOk(false), - _needThemeLoad(false), _enabled(false) { - _system = g_system; - _parser = new ThemeParser(this); - - for (int i = 0; i < kDrawDataMAX; ++i) { - _widgets[i] = 0; - } - - _graphicsMode = kGfxAntialias16bit; // default GFX mode - // TODO: load this from a config file -} - -template -void InterfaceManager::screenInit() { - freeScreen(); - - _screen = new Surface; - _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); - _system->clearOverlay(); -} - -void InterfaceManager::setGraphicsMode(Graphics_Mode mode) { - - // FIXME: reload theme everytime we change resolution... - // what if we change the renderer too? - // ...We may need to reload it to re-cache the widget - // surfaces - if (_system->getOverlayWidth() != _screen->w || - _system->getOverlayHeight() != _screen->h) - _needThemeLoad = true; - - switch (mode) { - case kGfxStandard16bit: - case kGfxAntialias16bit: - _bytesPerPixel = sizeof(uint16); - screenInit(); - break; - - default: - return; - } - - freeRenderer(); - _vectorRenderer = createRenderer(mode); - _vectorRenderer->setSurface(_screen); -} - -void InterfaceManager::addDrawStep(Common::String &drawDataId, Graphics::DrawStep *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; - - return true; -} - -bool InterfaceManager::loadTheme(Common::String themeName) { - unloadTheme(); - - if (!loadThemeXML(themeName)) { - warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); - - if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure - error("Could not load default embeded theme"); - } - - for (int i = 0; i < kDrawDataMAX; ++i) { - if (_widgets[i] == 0) { -#ifdef REQUIRE_ALL_DD_SETS - warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str()); - return false; -#endif - } else if (_widgets[i]->_cached) { - // draw the cached widget to the cache surface - } - } - - _needThemeLoad = false; - _themeOk = true; - return true; -} - -bool InterfaceManager::loadThemeXML(Common::String themeName) { - assert(_parser); - - if (ConfMan.hasKey("themepath")) - Common::File::addDefaultDirectory(ConfMan.get("themepath")); - -#ifdef DATA_PATH - Common::File::addDefaultDirectoryRecursive(DATA_PATH); -#endif - - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - - if (!parser()->loadFile(themeName + ".xml")) - return false; - - return parser()->parse(); -} - -void InterfaceManager::init() { - if (!_screen || _system->getOverlayWidth() != _screen->w || - _system->getOverlayHeight() != _screen->h ) - setGraphicsMode(_graphicsMode); - - if (needThemeReload()) - loadTheme(); - - _initOk = true; -} - -bool InterfaceManager::isWidgetCached(DrawData type, const Common::Rect &r) { - return _widgets[type] && _widgets[type]->_cached && - _widgets[type]->_surfaceCache->w == r.width() && - _widgets[type]->_surfaceCache->h == r.height(); -} - -void InterfaceManager::drawCached(DrawData type, const Common::Rect &r) { - assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); - _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); -} - -void InterfaceManager::drawDD(DrawData type, const Common::Rect &r) { - if (isWidgetCached(type, r)) { - drawCached(type, r); - } else { - for (uint i = 0; i < _widgets[type]->_steps.size(); ++i) - _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); - } -} - -void InterfaceManager::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!ready()) - return; - - if (state == kStateEnabled) - drawDD(kDDButtonIdle, r); - else if (state == kStateHighlight) - drawDD(kDDButtonHover, r); - - // TODO: Add text drawing. - - addDirtyRect(r); -} - -void InterfaceManager::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!ready()) - return; - - drawDD(kDDSeparator, r); - addDirtyRect(r); -} - -void InterfaceManager::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!ready()) - return; - - drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r); - - Common::Rect r2 = r; - r2.left += 16; // TODO: add variable for checkbox text offset. - - // TODO: text drawing -// getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); - - addDirtyRect(r); -} - -void InterfaceManager::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { - if (!ready()) - return; - - drawDD(kDDSliderEmpty, r); - - Common::Rect r2 = r; - r2.setWidth(MIN((int16)width, r.width())); - - drawDD(kDDSliderFull, r2); - - addDirtyRect(r); -} - -void InterfaceManager::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { - if (!ready()) - return; -} - -void InterfaceManager::redrawDialogStack() { - _vectorRenderer->clearSurface(); - - for (int i = 0; i < _dialogStack.size(); ++i) - _dialogStack[i]->draw(); -} - -void InterfaceManager::openDialog(Dialogs dname, Dialog *parent) { - Dialog *dlg = 0; - switch (dname) { - case kDialogLauncher: - dlg = new GUI::LauncherDialog; - break; - - default: - error("Unhandled dialog opening"); - break; - } - - if (dlg) - _dialogStack.push(dlg); -} - -int InterfaceManager::runGUI() { - init(); - - if (!ready()) - return 0; - - Common::EventManager *eventMan = _system->getEventManager(); - Dialog *activeDialog = getTopDialog(); - Dialog *lastDialog = 0; - - if (!activeDialog) - return 0; - - bool stackChange; - - int button; - uint32 time; - - _system->showOverlay(); - - while (activeDialog) { // draw!! - stackChange = (activeDialog != lastDialog); - lastDialog = activeDialog; - - if (stackChange || needRedraw()) - redrawDialogStack(); - - if (!_dirtyScreen.empty()) { - for (uint i = 0; i < _dirtyScreen.size(); ++i) - _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); - _system->updateScreen(); - _dirtyScreen.clear(); - } - - Common::Event event; - - while (eventMan->pollEvent(event)) { - activeDialog->handleTickle(); - - Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); - - switch (event.type) { - case Common::EVENT_KEYDOWN: - activeDialog->handleKeyDown(event.kbd); - break; - - case Common::EVENT_KEYUP: - activeDialog->handleKeyUp(event.kbd); - break; - - case Common::EVENT_MOUSEMOVE: - activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); - break; - - case Common::EVENT_LBUTTONDOWN: - case Common::EVENT_RBUTTONDOWN: - button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2); - time = _system->getMillis(); - if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay) - && ABS(_lastClick.x - event.mouse.x) < 3 - && ABS(_lastClick.y - event.mouse.y) < 3) { - _lastClick.count++; - } else { - _lastClick.x = event.mouse.x; - _lastClick.y = event.mouse.y; - _lastClick.count = 1; - } - _lastClick.time = time; - activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count); - break; - - case Common::EVENT_LBUTTONUP: - case Common::EVENT_RBUTTONUP: - button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2); - activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count); - break; - - case Common::EVENT_WHEELUP: - activeDialog->handleMouseWheel(mouse.x, mouse.y, -1); - break; - - case Common::EVENT_WHEELDOWN: - activeDialog->handleMouseWheel(mouse.x, mouse.y, 1); - break; - - case Common::EVENT_QUIT: - _system->quit(); - return 1; - - case Common::EVENT_SCREEN_CHANGED: - screenChange(); - break; - - default: - break; - } - } - - activeDialog = getTopDialog(); - _system->delayMillis(10); - } - - _system->hideOverlay(); - return 1; -} - - - -} // end of namespace GUI. diff --git a/gui/InterfaceManager.h b/gui/InterfaceManager.h deleted file mode 100644 index ac612e0c52..0000000000 --- a/gui/InterfaceManager.h +++ /dev/null @@ -1,334 +0,0 @@ -/* 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 INTERFACE_MANAGER_H -#define INTERFACE_MANAGER_H - -#include "common/scummsys.h" -#include "graphics/surface.h" -#include "common/system.h" - -#include "graphics/surface.h" -#include "graphics/fontman.h" - -#include "gui/dialog.h" -#include "gui/ThemeParser.h" -#include "graphics/VectorRenderer.h" - -namespace GUI { - -struct WidgetDrawData; -class InterfaceManager; - -struct WidgetDrawData { - Common::Array _steps; - - bool _cached; - Graphics::Surface *_surfaceCache; - uint32 _cachedW, _cachedH; - - ~WidgetDrawData() { - for (uint i = 0; i < _steps.size(); ++i) - delete _steps[i]; - - _steps.clear(); - - if (_surfaceCache) { - _surfaceCache->free(); - delete _surfaceCache; - } - } -}; - -class InterfaceManager { - - typedef Common::String String; - typedef GUI::Dialog Dialog; - - friend class GUI::Dialog; - friend class GUI::GuiObject; - - static const char *kDrawDataStrings[]; - static const int kMaxDialogDepth = 4; - -public: - enum Graphics_Mode { - kGfxDisabled = 0, - kGfxStandard16bit, - kGfxAntialias16bit - }; - - enum Dialogs { - kDialogLauncher, - kDialogMAX - }; - - enum { - kDoubleClickDelay = 500, // milliseconds - kCursorAnimateDelay = 250 - }; - - enum DrawData { - kDDMainDialogBackground, - kDDSpecialColorBackground, - kDDPlainColorBackground, - kDDDefaulBackground, - - kDDButtonIdle, - kDDButtonHover, - - kDDSurface, - - kDDSliderFull, - kDDSliderEmpty, - - kDDCheckboxEnabled, - kDDCheckboxDisabled, - - kDDTab, - - kDDScrollbarBase, - kDDScrollbarButtonTop, - kDDScrollbarButtonBottom, - kDDScrollbarHandle, - - kDDPopUp, - kDDCaret, - kDDSeparator, - kDrawDataMAX - }; - - enum FontStyle { - kFontStyleBold = 0, //! A bold font. This is also the default font. - kFontStyleNormal = 1, //! A normal font. - kFontStyleItalic = 2, //! Italic styled font. - kFontStyleFixedNormal = 3, //! Fixed size font. - kFontStyleFixedBold = 4, //! Fixed size bold font. - kFontStyleFixedItalic = 5, //! Fixed size italic font. - kFontStyleMax - }; - - enum State { - kStateDisabled, //! Indicates that the widget is disabled, that does NOT include that it is invisible - kStateEnabled, //! Indicates that the widget is enabled - kStateHighlight //! Indicates that the widget is highlighted by the user - }; - - //! Widget background type - enum WidgetBackground { - kWidgetBackgroundNo, //! No background at all - kWidgetBackgroundPlain, //! Simple background, this may not include borders - kWidgetBackgroundBorder, //! Same as kWidgetBackgroundPlain just with a border - kWidgetBackgroundBorderSmall, //! Same as kWidgetBackgroundPlain just with a small border - kWidgetBackgroundEditText, //! Background used for edit text fields - kWidgetBackgroundSlider //! Background used for sliders - }; - - typedef State WidgetStateInfo; - - //! State of the scrollbar - enum ScrollbarState { - kScrollbarStateNo, - kScrollbarStateUp, - kScrollbarStateDown, - kScrollbarStateSlider, - kScrollbarStateSinglePage - }; - - //! Defined the align of the text - enum TextAlign { - kTextAlignLeft, //! Text should be aligned to the left - kTextAlignCenter, //! Text should be centered - kTextAlignRight //! Text should be aligned to the right - }; - - //! Function used to process areas other than the current dialog - enum ShadingStyle { - kShadingNone, //! No special post processing - kShadingDim, //! Dimming unused areas - kShadingLuminance //! Converting colors to luminance for unused areas - }; - - - InterfaceManager(); - - ~InterfaceManager() { - freeRenderer(); - freeScreen(); - unloadTheme(); - delete _parser; - - while (!_dialogStack.empty()) - delete _dialogStack.pop(); - } - - void setGraphicsMode(Graphics_Mode mode); - int runGUI(); - - void init(); - - /** Font management */ - const Graphics::Font *getFont(FontStyle font) const { return _font; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } - - /** Widget drawing */ - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled) {} - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); - - DrawData getDrawDataId(Common::String &name) { - 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); - - ThemeParser *parser() { - return _parser; - } - - bool ready() { - return _initOk && _themeOk; - } - - bool loadTheme() { - ConfMan.registerDefault("gui_theme", "default"); - Common::String style(ConfMan.get("gui_theme")); - - if (style.compareToIgnoreCase("default") == 0) - style = "modern"; - - return loadTheme(style); - } - - bool loadTheme(Common::String themeName); - void openDialog(Dialogs dname, Dialog *parent); - - void closeTopDialog() { - assert(_dialogStack.empty() == false); - delete _dialogStack.pop(); - } - -protected: - template void screenInit(); - - bool loadThemeXML(Common::String themeName); - bool loadDefaultXML(); - - void unloadTheme() { - if (!_themeOk) - return; - - for (int i = 0; i < kDrawDataMAX; ++i) { - delete _widgets[i]; - _widgets[i] = 0; - } - } - - void screenChange() {} - - void freeRenderer() { - delete _vectorRenderer; - _vectorRenderer = 0; - } - - void freeScreen() { - if (_screen != 0) { - _screen->free(); - delete _screen; - _screen = 0; - } - } - - Dialog *getTopDialog() const { - if (_dialogStack.empty()) - return 0; - return _dialogStack.top(); - } - - bool needThemeReload() { - return (_themeOk == false || _needThemeLoad == true); - } - - bool needRedraw() { - return true; - } - - void redrawDialogStack(); - - bool isWidgetCached(DrawData type, const Common::Rect &r); - void drawCached(DrawData type, const Common::Rect &r); - - inline void drawDD(DrawData type, const Common::Rect &r); - - void addDirtyRect(const Common::Rect &r) { - _dirtyScreen.push_back(r); - } - - OSystem *_system; - Graphics::VectorRenderer *_vectorRenderer; - GUI::ThemeParser *_parser; - - Graphics::Surface *_screen; - - int _bytesPerPixel; - Graphics_Mode _graphicsMode; - - Common::String _fontName; - const Graphics::Font *_font; - - WidgetDrawData *_widgets[kDrawDataMAX]; - Common::FixedStack _dialogStack; - Common::Array _dirtyScreen; - - bool _initOk; - bool _themeOk; - bool _caching; - bool _needThemeLoad; - bool _enabled; - - struct { - int16 x, y; // Position of mouse when the click occured - uint32 time; // Time - int count; // How often was it already pressed? - } _lastClick; -}; - -} // end of namespace GUI. - -#endif diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index cd571e680e..4b48e11991 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -24,11 +24,11 @@ */ #include "common/system.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" namespace GUI { -bool InterfaceManager::loadDefaultXML() { +bool ThemeRenderer::loadDefaultXML() { const char *defaultXML = /** * Default theme description file. Work in progress. diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 07789ebee3..eac8c20978 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -30,8 +30,9 @@ #include "common/hash-str.h" #include "common/xmlparser.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" #include "gui/ThemeParser.h" +#include "gui/NewGui.h" #include "graphics/VectorRenderer.h" namespace GUI { @@ -39,7 +40,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -ThemeParser::ThemeParser(InterfaceManager *parent) : XMLParser() { +ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _callbacks["drawstep"] = &ThemeParser::parserCallback_DRAWSTEP; _callbacks["drawdata"] = &ThemeParser::parserCallback_DRAWDATA; _callbacks["palette"] = &ThemeParser::parserCallback_palette; @@ -59,7 +60,7 @@ ThemeParser::ThemeParser(InterfaceManager *parent) : XMLParser() { _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; - _GUI = parent; + _theme = parent; } bool ThemeParser::keyCallback(Common::String keyName) { @@ -213,7 +214,7 @@ bool ThemeParser::parserCallback_DRAWSTEP() { if (!parseDrawStep(stepNode, drawstep, true)) return false; - _GUI->addDrawStep(drawdataNode->values["id"], drawstep); + _theme->addDrawStep(drawdataNode->values["id"], drawstep); return true; } @@ -229,7 +230,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { if (drawdataNode->values.contains("id") == false) return parserError("DrawData keys must contain an identifier."); - InterfaceManager::DrawData id = _GUI->getDrawDataId(drawdataNode->values["id"]); + ThemeRenderer::DrawData id = _theme->getDrawDataId(drawdataNode->values["id"]); if (id == -1) return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); @@ -252,7 +253,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { } }*/ - if (_GUI->addDrawData(id, cached) == false) + if (_theme->addDrawData(id, cached) == false) return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); if (_defaultStepLocal) { diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 68e8272b80..56d45eb802 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -36,7 +36,7 @@ #include "common/xmlparser.h" #include "graphics/VectorRenderer.h" -#include "gui/InterfaceManager.h" +#include "gui/ThemeRenderer.h" /** ********************************************* @@ -308,7 +308,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -class InterfaceManager; +class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); @@ -316,10 +316,10 @@ class ThemeParser : public XMLParser { typedef GUI::InterfaceManager InterfaceManager; public: - ThemeParser(InterfaceManager *parent); + ThemeParser(GUI::ThemeRenderer *parent); protected: - InterfaceManager *_GUI; + ThemeRenderer *_theme; bool keyCallback(Common::String keyName); bool parserCallback_DRAWSTEP(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp new file mode 100644 index 0000000000..283860341b --- /dev/null +++ b/gui/ThemeRenderer.cpp @@ -0,0 +1,286 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "graphics/surface.h" +#include "graphics/colormasks.h" +#include "common/system.h" +#include "common/events.h" +#include "common/config-manager.h" + +#include "gui/launcher.h" + +#include "gui/ThemeRenderer.h" +#include "graphics/VectorRenderer.h" + +namespace GUI { + +using namespace Graphics; + +const char *ThemeRenderer::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" +}; + +ThemeRenderer::ThemeRenderer() : + _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), + _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), + _needThemeLoad(false), _enabled(false) { + _system = g_system; + _parser = new ThemeParser(this); + + for (int i = 0; i < kDrawDataMAX; ++i) { + _widgets[i] = 0; + } + + _graphicsMode = kGfxAntialias16bit; // default GFX mode + // TODO: load this from a config file +} + +template +void ThemeRenderer::screenInit() { + freeScreen(); + + _screen = new Surface; + _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); + _system->clearOverlay(); +} + +void ThemeRenderer::setGraphicsMode(Graphics_Mode mode) { + + // FIXME: reload theme everytime we change resolution... + // what if we change the renderer too? + // ...We may need to reload it to re-cache the widget + // surfaces + if (_system->getOverlayWidth() != _screen->w || + _system->getOverlayHeight() != _screen->h) + _needThemeLoad = true; + + switch (mode) { + case kGfxStandard16bit: + case kGfxAntialias16bit: + _bytesPerPixel = sizeof(uint16); + screenInit(); + break; + + default: + return; + } + + freeRenderer(); + _vectorRenderer = createRenderer(mode); + _vectorRenderer->setSurface(_screen); +} + +void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step) { + DrawData id = getDrawDataId(drawDataId); + + assert(_widgets[id] != 0); + _widgets[id]->_steps.push_back(step); +} + +bool ThemeRenderer::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; + + return true; +} + +bool ThemeRenderer::loadTheme(Common::String themeName) { + unloadTheme(); + + if (!loadThemeXML(themeName)) { + warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); + + if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure + error("Could not load default embeded theme"); + } + + for (int i = 0; i < kDrawDataMAX; ++i) { + if (_widgets[i] == 0) { +#ifdef REQUIRE_ALL_DD_SETS + warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str()); + return false; +#endif + } else if (_widgets[i]->_cached) { + // draw the cached widget to the cache surface + } + } + + _needThemeLoad = false; + _themeOk = true; + return true; +} + +bool ThemeRenderer::loadThemeXML(Common::String themeName) { + assert(_parser); + + if (ConfMan.hasKey("themepath")) + Common::File::addDefaultDirectory(ConfMan.get("themepath")); + +#ifdef DATA_PATH + Common::File::addDefaultDirectoryRecursive(DATA_PATH); +#endif + + if (ConfMan.hasKey("extrapath")) + Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + + if (!parser()->loadFile(themeName + ".xml")) + return false; + + return parser()->parse(); +} + +bool ThemeRenderer::init() { + if (!_screen || _system->getOverlayWidth() != _screen->w || + _system->getOverlayHeight() != _screen->h ) + setGraphicsMode(_graphicsMode); + + if (needThemeReload()) + loadTheme(); + + _initOk = true; + return true; +} + +bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { + return _widgets[type] && _widgets[type]->_cached && + _widgets[type]->_surfaceCache->w == r.width() && + _widgets[type]->_surfaceCache->h == r.height(); +} + +void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { + assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); + _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); +} + +void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { + if (isWidgetCached(type, r)) { + drawCached(type, r); + } else { + for (uint i = 0; i < _widgets[type]->_steps.size(); ++i) + _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); + } +} + +void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { + if (!ready()) + return; + + if (state == kStateEnabled) + drawDD(kDDButtonIdle, r); + else if (state == kStateHighlight) + drawDD(kDDButtonHover, r); + + // TODO: Add text drawing. + + addDirtyRect(r); +} + +void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { + if (!ready()) + return; + + drawDD(kDDSeparator, r); + addDirtyRect(r); +} + +void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { + if (!ready()) + return; + + drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r); + + Common::Rect r2 = r; + r2.left += 16; // TODO: add variable for checkbox text offset. + + // TODO: text drawing +// getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); + + addDirtyRect(r); +} + +void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { + if (!ready()) + return; + + drawDD(kDDSliderEmpty, r); + + Common::Rect r2 = r; + r2.setWidth(MIN((int16)width, r.width())); + + drawDD(kDDSliderFull, r2); + + addDirtyRect(r); +} + +void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { + if (!ready()) + return; +} + +void ThemeRenderer::renderDirtyScreen() { + // TODO: This isn't really optimized. Check dirty squares for collisions + // and all that. + if (_dirtyScreen.empty()) + return; + + for (uint i = 0; i < _dirtyScreen.size(); ++i) + _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); + + _system->updateScreen(); + _dirtyScreen.clear(); +} + +} // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h new file mode 100644 index 0000000000..e9904d8ae3 --- /dev/null +++ b/gui/ThemeRenderer.h @@ -0,0 +1,297 @@ +/* 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 INTERFACE_MANAGER_H +#define INTERFACE_MANAGER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" + +#include "graphics/surface.h" +#include "graphics/fontman.h" + +#include "gui/dialog.h" +#include "gui/ThemeParser.h" +#include "graphics/VectorRenderer.h" + +namespace GUI { + +struct WidgetDrawData; +class InterfaceManager; + +struct WidgetDrawData { + Common::Array _steps; + + bool _cached; + Graphics::Surface *_surfaceCache; + uint32 _cachedW, _cachedH; + + ~WidgetDrawData() { + for (uint i = 0; i < _steps.size(); ++i) + delete _steps[i]; + + _steps.clear(); + + if (_surfaceCache) { + _surfaceCache->free(); + delete _surfaceCache; + } + } +}; + +class ThemeRenderer : public Theme { + + typedef Common::String String; + typedef GUI::Dialog Dialog; + + friend class GUI::Dialog; + friend class GUI::GuiObject; + + static const char *kDrawDataStrings[]; + static const int kMaxDialogDepth = 4; + +public: + enum Graphics_Mode { + kGfxDisabled = 0, + kGfxStandard16bit, + kGfxAntialias16bit + }; + + enum DrawData { + kDDMainDialogBackground, + kDDSpecialColorBackground, + kDDPlainColorBackground, + kDDDefaulBackground, + + kDDButtonIdle, + kDDButtonHover, + + kDDSurface, + + kDDSliderFull, + kDDSliderEmpty, + + kDDCheckboxEnabled, + kDDCheckboxDisabled, + + kDDTab, + + kDDScrollbarBase, + kDDScrollbarButtonTop, + kDDScrollbarButtonBottom, + kDDScrollbarHandle, + + kDDPopUp, + kDDCaret, + kDDSeparator, + kDrawDataMAX + }; + + ThemeRenderer(); + + ~ThemeRenderer() { + freeRenderer(); + freeScreen(); + unloadTheme(); + delete _parser; + + while (!_dialogStack.empty()) + delete _dialogStack.pop(); + } + + // virtual methods from Theme + bool init(); + void deinit() {} + void refresh() {} + void enable() {} + void disable() {} + void openDialog() {} + void closeAllDialogs() {} + void clearAll() {} + void updateScreen() {} + void resetDrawArea() {} + void openDialog(bool top) {} + + virtual bool isDynamic() { + return true; + } + + /** Font management */ + const Graphics::Font *getFont(FontStyle font) const { return _font; } + int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } + int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } + int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } + + /** Widget drawing */ + void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} + void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} + void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled); + void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled) {} + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled); + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} + void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); + + void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) {} + void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {} + void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} + + bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { + _dirtyScreen.push_back(r); + return true; + } + + // custom stuff - tanoku + DrawData getDrawDataId(Common::String &name) { + 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); + + ThemeParser *parser() { + return _parser; + } + + bool ready() { + return _initOk && _themeOk; + } + + bool loadTheme() { + ConfMan.registerDefault("gui_theme", "default"); + Common::String style(ConfMan.get("gui_theme")); + + if (style.compareToIgnoreCase("default") == 0) + style = "modern"; + + return loadTheme(style); + } + + bool loadTheme(Common::String themeName); + + void closeTopDialog() { + assert(_dialogStack.empty() == false); + delete _dialogStack.pop(); + } + + void setGraphicsMode(Graphics_Mode mode); + +protected: + template void screenInit(); + + bool loadThemeXML(Common::String themeName); + bool loadDefaultXML(); + + void unloadTheme() { + if (!_themeOk) + return; + + for (int i = 0; i < kDrawDataMAX; ++i) { + delete _widgets[i]; + _widgets[i] = 0; + } + } + + void screenChange() {} + void renderDirtyScreen(); + + void freeRenderer() { + delete _vectorRenderer; + _vectorRenderer = 0; + } + + void freeScreen() { + if (_screen != 0) { + _screen->free(); + delete _screen; + _screen = 0; + } + } + + Dialog *getTopDialog() const { + if (_dialogStack.empty()) + return 0; + return _dialogStack.top(); + } + + bool needThemeReload() { + return (_themeOk == false || _needThemeLoad == true); + } + + bool needRedraw() { + return true; + } + + void redrawDialogStack(); + + bool isWidgetCached(DrawData type, const Common::Rect &r); + void drawCached(DrawData type, const Common::Rect &r); + + inline void drawDD(DrawData type, const Common::Rect &r); + + // TODO + void restoreBackground(Common::Rect r, bool special = false) {} + + int getTabSpacing() const { + return 0; + } + + int getTabPadding() const { + return 3; + } + + OSystem *_system; + Graphics::VectorRenderer *_vectorRenderer; + GUI::ThemeParser *_parser; + + Graphics::Surface *_screen; + + int _bytesPerPixel; + Graphics_Mode _graphicsMode; + + Common::String _fontName; + const Graphics::Font *_font; + + WidgetDrawData *_widgets[kDrawDataMAX]; + Common::FixedStack _dialogStack; + Common::Array _dirtyScreen; + + bool _initOk; + bool _themeOk; + bool _caching; + bool _needThemeLoad; + bool _enabled; +}; + +} // end of namespace GUI. + +#endif diff --git a/gui/object.h b/gui/object.h index 2bdff3f76c..01046bd668 100644 --- a/gui/object.h +++ b/gui/object.h @@ -29,7 +29,6 @@ namespace GUI { class CommandReceiver; class CommandSender; -class InterfaceManager; class CommandReceiver { friend class CommandSender; @@ -66,7 +65,6 @@ protected: Common::String _name; Widget *_firstWidget; - InterfaceManager *_GUI; public: GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _name(""), _firstWidget(0) { } @@ -85,7 +83,6 @@ public: virtual void draw() = 0; virtual void reflowLayout(); - virtual void setInterfaceManager(InterfaceManager *manager) { _GUI = manager; } protected: virtual void releaseFocus() = 0; diff --git a/gui/theme.h b/gui/theme.h index 4f61609fbd..320d2544e0 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -348,6 +348,10 @@ public: const Common::String &getStylefileName() const { return _stylefile; } const Common::String &getThemeName() const { return _stylename; } + virtual bool isDynamic() { + return false; + } + /** * Checks if the theme renderer supports drawing of images. * -- cgit v1.2.3 From 2d87b29058ef84f482550fc0f002d9805fc53b87 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jul 2008 18:43:17 +0000 Subject: GCC compiling fixes. svn-id: r32877 --- gui/ThemeParser.h | 1 - gui/ThemeRenderer.h | 1 - gui/dialog.h | 1 - gui/module.mk | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 56d45eb802..d3a9503b8d 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -313,7 +313,6 @@ class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); typedef bool (ThemeParser::*ParserCallback)(); - typedef GUI::InterfaceManager InterfaceManager; public: ThemeParser(GUI::ThemeRenderer *parent); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index e9904d8ae3..af89bd6732 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -40,7 +40,6 @@ namespace GUI { struct WidgetDrawData; -class InterfaceManager; struct WidgetDrawData { Common::Array _steps; diff --git a/gui/dialog.h b/gui/dialog.h index f34e9d2e0d..553a63d1a9 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -44,7 +44,6 @@ enum { class Dialog : public GuiObject { // TANOKU-TODO: remove newgui from here friend class NewGui; - friend class InterfaceManager; protected: Widget *_mouseWidget; Widget *_focusedWidget; diff --git a/gui/module.mk b/gui/module.mk index 81be839777..6ff74641b8 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -10,7 +10,7 @@ MODULE_OBJS := \ editable.o \ EditTextWidget.o \ eval.o \ - InterfaceManager.o \ + ThemeRenderer.o \ launcher.o \ ListWidget.o \ massadd.o \ -- cgit v1.2.3 From 8dbec866d6350c044297e16aa8ede432a3bd174b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 2 Jul 2008 18:49:58 +0000 Subject: GCC fix again, case mismatch in Linux. svn-id: r32878 --- gui/ThemeParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index eac8c20978..1bdf1c487c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -32,7 +32,7 @@ #include "gui/ThemeRenderer.h" #include "gui/ThemeParser.h" -#include "gui/NewGui.h" +#include "gui/newgui.h" #include "graphics/VectorRenderer.h" namespace GUI { -- cgit v1.2.3 From 48fd843e759ab3a8a23ba2be902a8a815a41e8f8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jul 2008 10:26:55 +0000 Subject: Rendering pipeline. WIP. svn-id: r32882 --- base/main.cpp | 2 +- common/xmlparser.cpp | 2 ++ common/xmlparser.h | 8 +++++ graphics/VectorRenderer.h | 15 ++++++++-- gui/ThemeDefaultXML.cpp | 2 +- gui/ThemeParser.cpp | 9 ++++++ gui/ThemeParser.h | 2 ++ gui/ThemeRenderer.cpp | 76 ++++++++++++++++++++++++++++++----------------- gui/ThemeRenderer.h | 49 ++++++++++-------------------- gui/newgui.cpp | 7 +++-- 10 files changed, 104 insertions(+), 68 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index 9b76e0514a..b7d30d30f8 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -70,7 +70,7 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); - GUI::ThemeRenderer *test = new GUI::ThemeRenderer; +// GUI::ThemeRenderer *test = new GUI::ThemeRenderer("modern", GUI::ThemeRenderer::kGfxAntialias16bit); #if defined LOL diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 8ff93a4c59..3452db9e00 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -134,6 +134,8 @@ bool XMLParser::parse() { if (_text.ready() == false) return parserError("XML stream not ready for reading."); + cleanup(); + bool activeClosure = false; bool selfClosure = false; diff --git a/common/xmlparser.h b/common/xmlparser.h index 4850dc5113..d31c69ebee 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -332,6 +332,14 @@ protected: return (*key == 0); } + /** + * Internal state cleanup. Overload this if your parser needs + * to clean itself up before doing a second parse. + * E.g. the Theme Parser cleans the color palette after parsing + * a theme. + */ + virtual void cleanup() {} + int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3267d44687..0b9ccc4836 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -406,7 +406,8 @@ public: * * @param sys Pointer to the global System class */ - virtual void copyFrame(OSystem *sys, Common::Rect &r) = 0; + virtual void copyFrame(OSystem *sys, const Common::Rect &r) = 0; + virtual void copyWholeFrame(OSystem *sys) = 0; /** * Blits a given graphics surface on top of the current drawing surface. @@ -533,7 +534,7 @@ public: /** * @see VectorRenderer::copyFrame() */ - virtual void copyFrame(OSystem *sys, Common::Rect &r) { + virtual void copyFrame(OSystem *sys, const Common::Rect &r) { #ifdef OVERLAY_MULTIPLE_DEPTHS // TODO: change OSystem to support templated copyRectToOverlay sys->copyRectToOverlay((const PixelType*)_activeSurface->pixels, _activeSurface->pitch, r.top, r.left, r.width(), r.height()); @@ -543,6 +544,16 @@ public: #endif } + virtual void copyWholeFrame(OSystem *sys) { +#ifdef OVERLAY_MULTIPLE_DEPTHS + sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); +#else + sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(0, 0), + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); +#endif + } + /** * @see VectorRenderer::blitSurface() */ diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 4b48e11991..43b3e249a0 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -58,7 +58,7 @@ bool ThemeRenderer::loadDefaultXML() { "" ""; - if (!parser()->loadBuffer(defaultXML, true)) + if (!parser()->loadBuffer(defaultXML, false)) return false; return parser()->parse(); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 1bdf1c487c..cd9ebc83a4 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -63,6 +63,15 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _theme = parent; } +void ThemeParser::cleanup() { + delete _defaultStepGlobal; + delete _defaultStepLocal; + + _defaultStepGlobal = defaultDrawStep(); + _defaultStepLocal = 0; + _palette.clear(); +} + bool ThemeParser::keyCallback(Common::String keyName) { // automatically handle with a function from the hash table. if (!_callbacks.contains(_activeKey.top()->name)) diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index d3a9503b8d..cddb91b21e 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -329,6 +329,8 @@ protected: bool parserCallback_layoutInfo(); bool parserCallback_defaultSet(); + void cleanup(); + Graphics::DrawStep *newDrawStep(); Graphics::DrawStep *defaultDrawStep(); bool parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 283860341b..7b14b93b23 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -68,10 +68,9 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "separator" }; -ThemeRenderer::ThemeRenderer() : +ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), - _needThemeLoad(false), _enabled(false) { + _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false) { _system = g_system; _parser = new ThemeParser(this); @@ -79,8 +78,50 @@ ThemeRenderer::ThemeRenderer() : _widgets[i] = 0; } - _graphicsMode = kGfxAntialias16bit; // default GFX mode - // TODO: load this from a config file + _graphicsMode = mode; + setGraphicsMode(_graphicsMode); + + if (isThemeLoadingRequired()) + loadTheme(themeName); + + _initOk = true; + _themeName = themeName; +} + +bool ThemeRenderer::init() { + // reset everything and reload the graphics + deinit(); + setGraphicsMode(_graphicsMode); + + if (_screen->pixels) { + _initOk = true; + clearAll(); + resetDrawArea(); + } + + if (isThemeLoadingRequired()) + loadTheme(_themeName); + + return true; +} + +void ThemeRenderer::deinit() { + if (_initOk) { + _system->hideOverlay(); + freeRenderer(); + freeScreen(); + unloadTheme(); + _initOk = false; + } +} + +void ThemeRenderer::clearAll() { + if (!_initOk) + return; + + _vectorRenderer->clearSurface(); + _vectorRenderer->copyWholeFrame(_system); + _system->updateScreen(); } template @@ -92,16 +133,7 @@ void ThemeRenderer::screenInit() { _system->clearOverlay(); } -void ThemeRenderer::setGraphicsMode(Graphics_Mode mode) { - - // FIXME: reload theme everytime we change resolution... - // what if we change the renderer too? - // ...We may need to reload it to re-cache the widget - // surfaces - if (_system->getOverlayWidth() != _screen->w || - _system->getOverlayHeight() != _screen->h) - _needThemeLoad = true; - +void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { switch (mode) { case kGfxStandard16bit: case kGfxAntialias16bit: @@ -133,6 +165,7 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; + _widgets[data_id]->_surfaceCache = 0; return true; } @@ -158,7 +191,6 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { } } - _needThemeLoad = false; _themeOk = true; return true; } @@ -182,18 +214,6 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { return parser()->parse(); } -bool ThemeRenderer::init() { - if (!_screen || _system->getOverlayWidth() != _screen->w || - _system->getOverlayHeight() != _screen->h ) - setGraphicsMode(_graphicsMode); - - if (needThemeReload()) - loadTheme(); - - _initOk = true; - return true; -} - bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { return _widgets[type] && _widgets[type]->_cached && _widgets[type]->_surfaceCache->w == r.width() && diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index af89bd6732..8d3f57b547 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -73,7 +73,7 @@ class ThemeRenderer : public Theme { static const int kMaxDialogDepth = 4; public: - enum Graphics_Mode { + enum GraphicsMode { kGfxDisabled = 0, kGfxStandard16bit, kGfxAntialias16bit @@ -109,34 +109,31 @@ public: kDrawDataMAX }; - ThemeRenderer(); + ThemeRenderer(Common::String themeName, GraphicsMode mode); ~ThemeRenderer() { freeRenderer(); freeScreen(); unloadTheme(); delete _parser; - - while (!_dialogStack.empty()) - delete _dialogStack.pop(); } // virtual methods from Theme bool init(); - void deinit() {} + void deinit(); + void clearAll(); + void refresh() {} void enable() {} void disable() {} void openDialog() {} void closeAllDialogs() {} - void clearAll() {} + + void updateScreen() {} void resetDrawArea() {} - void openDialog(bool top) {} - virtual bool isDynamic() { - return true; - } + void openDialog(bool top) {} /** Font management */ const Graphics::Font *getFont(FontStyle font) const { return _font; } @@ -185,7 +182,8 @@ public: return _initOk && _themeOk; } - bool loadTheme() { + // REMOVED: theme name is looked up in NewGUI and passed to the constructor +/* bool loadTheme() { ConfMan.registerDefault("gui_theme", "default"); Common::String style(ConfMan.get("gui_theme")); @@ -193,16 +191,10 @@ public: style = "modern"; return loadTheme(style); - } + } */ bool loadTheme(Common::String themeName); - - void closeTopDialog() { - assert(_dialogStack.empty() == false); - delete _dialogStack.pop(); - } - - void setGraphicsMode(Graphics_Mode mode); + void setGraphicsMode(GraphicsMode mode); protected: template void screenInit(); @@ -236,16 +228,6 @@ protected: } } - Dialog *getTopDialog() const { - if (_dialogStack.empty()) - return 0; - return _dialogStack.top(); - } - - bool needThemeReload() { - return (_themeOk == false || _needThemeLoad == true); - } - bool needRedraw() { return true; } @@ -275,20 +257,19 @@ protected: Graphics::Surface *_screen; int _bytesPerPixel; - Graphics_Mode _graphicsMode; + GraphicsMode _graphicsMode; Common::String _fontName; const Graphics::Font *_font; WidgetDrawData *_widgets[kDrawDataMAX]; - Common::FixedStack _dialogStack; Common::Array _dirtyScreen; bool _initOk; bool _themeOk; bool _caching; - bool _needThemeLoad; - bool _enabled; + + Common::String _themeName; }; } // end of namespace GUI. diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 0bf61d084f..4d0b3905b9 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -31,6 +31,7 @@ #include "gui/eval.h" #include "gui/ThemeModern.h" #include "gui/ThemeClassic.h" +#include "gui/ThemeRenderer.h" #include "common/config-manager.h" @@ -142,7 +143,7 @@ bool NewGui::loadNewTheme(const Common::String &style) { delete _theme; _theme = 0; - if (style.compareToIgnoreCase("classic (builtin)") == 0 || +/* if (style.compareToIgnoreCase("classic (builtin)") == 0 || style.compareToIgnoreCase("classic") == 0) { _theme = new ThemeClassic(_system, style); } else { @@ -159,7 +160,9 @@ bool NewGui::loadNewTheme(const Common::String &style) { warning("Config '%s' is NOT usable for themes or not found", style.c_str()); } } - cfg.clear(); + cfg.clear(); */ + + _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxAntialias16bit); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); -- cgit v1.2.3 From 52aba6b6daa020808f2b124ac83cf7d8fffa0ed4 Mon Sep 17 00:00:00 2001 From: Stephen Kennedy Date: Thu, 3 Jul 2008 16:09:54 +0000 Subject: changed loadBuffer to use byte* rather than char* svn-id: r32894 --- common/xmlparser.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index d31c69ebee..94512c3ab7 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -144,12 +144,13 @@ public: * from memory if no themes can be found. * * @param buffer Pointer to the buffer. + * @param size Size of the buffer * @param disposable Sets if the XMLParser owns the buffer, * i.e. if it can be freed safely after it's * no longer needed by the parser. */ - virtual bool loadBuffer(const char *buffer, bool disposable = false) { - _text.loadStream(new MemoryReadStream((const byte*)buffer, strlen(buffer), disposable)); + virtual bool loadBuffer(const byte *buffer, uint32 size, bool disposable = false) { + _text.loadStream(new MemoryReadStream(buffer, size, disposable)); _fileName = "Memory Stream"; return true; } -- cgit v1.2.3 From 919d81f03be0d3f03cb1fdca0735a9b3ae563af2 Mon Sep 17 00:00:00 2001 From: Stephen Kennedy Date: Thu, 3 Jul 2008 19:32:57 +0000 Subject: Changed XMLParser to internally use a Stack rather than a FixedStack svn-id: r32897 --- common/xmlparser.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 94512c3ab7..fa1f10061a 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -86,8 +86,6 @@ public: * @see XMLParser::keyCallback() */ class XMLParser { - /** Maximum depth for nested keys that the parser supports */ - static const int kParserMaxDepth = 4; public: /** @@ -333,14 +331,6 @@ protected: return (*key == 0); } - /** - * Internal state cleanup. Overload this if your parser needs - * to clean itself up before doing a second parse. - * E.g. the Theme Parser cleans the color palette after parsing - * a theme. - */ - virtual void cleanup() {} - int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; @@ -350,7 +340,7 @@ protected: Common::String _error; /** Current error message */ Common::String _token; /** Current text token */ - Common::FixedStack _activeKey; /** Node stack of the parsed keys */ + Common::Stack _activeKey; /** Node stack of the parsed keys */ }; } -- cgit v1.2.3 From 8240e5b96d072fda2f84abdf84c27cf90ee891a5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 3 Jul 2008 19:42:04 +0000 Subject: Rendering pipeline. WIP. (I see working buttons) svn-id: r32898 --- common/xmlparser.h | 9 ++++++++- graphics/VectorRenderer.h | 8 ++++---- gui/ThemeDefaultXML.cpp | 2 +- gui/ThemeRenderer.cpp | 50 +++++++++++++++++++++++++++++++++++++---------- gui/ThemeRenderer.h | 10 +++++++--- gui/newgui.cpp | 2 +- 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index fa1f10061a..167d04249c 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -63,7 +63,7 @@ public: _pos = idx; - return _stream->readSByte(); + return _stream->readByte(); } void loadStream(SeekableReadStream *s) { @@ -331,6 +331,13 @@ protected: return (*key == 0); } + /** + * Overload if your parser needs to support parsing the same file + * several times, so you can clean up the internal state of the + * parser before each parse. + */ + virtual void cleanup() {} + int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0b9ccc4836..0e679663d9 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -536,11 +536,11 @@ public: */ virtual void copyFrame(OSystem *sys, const Common::Rect &r) { #ifdef OVERLAY_MULTIPLE_DEPTHS // TODO: change OSystem to support templated copyRectToOverlay - sys->copyRectToOverlay((const PixelType*)_activeSurface->pixels, - _activeSurface->pitch, r.top, r.left, r.width(), r.height()); + sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(r.left, r.top), + _activeSurface->w, r.top, r.left, r.width(), r.height()); #else - sys->copyRectToOverlay((const OverlayColor*)_activeSurface->pixels, - _activeSurface->pitch, r.top, r.left, r.width(), r.height()); + sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(r.left, r.top), + _activeSurface->w, r.top, r.left, r.width(), r.height()); #endif } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 43b3e249a0..11ef1b58b0 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -58,7 +58,7 @@ bool ThemeRenderer::loadDefaultXML() { "" ""; - if (!parser()->loadBuffer(defaultXML, false)) + if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) return false; return parser()->parse(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 7b14b93b23..a5a1625fb6 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -47,6 +47,7 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "button_idle", "button_hover", + "button_disabled", "surface", @@ -70,7 +71,7 @@ const char *ThemeRenderer::kDrawDataStrings[] = { ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false) { + _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false) { _system = g_system; _parser = new ThemeParser(this); @@ -81,8 +82,7 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _graphicsMode = mode; setGraphicsMode(_graphicsMode); - if (isThemeLoadingRequired()) - loadTheme(themeName); + loadConfigFile("classic"); _initOk = true; _themeName = themeName; @@ -99,9 +99,21 @@ bool ThemeRenderer::init() { resetDrawArea(); } - if (isThemeLoadingRequired()) + if (!_themeOk || isThemeLoadingRequired()) { loadTheme(_themeName); + Theme::loadTheme(_defaultConfig); + Theme::loadTheme(_configFile, false, true); + } + + if (_fontName.empty()) { + if (_screen->w >= 400 && _screen->h >= 300) { + _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + } else { + _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + } + } + return true; } @@ -110,7 +122,6 @@ void ThemeRenderer::deinit() { _system->hideOverlay(); freeRenderer(); freeScreen(); - unloadTheme(); _initOk = false; } } @@ -119,9 +130,21 @@ void ThemeRenderer::clearAll() { if (!_initOk) return; - _vectorRenderer->clearSurface(); - _vectorRenderer->copyWholeFrame(_system); - _system->updateScreen(); + _system->clearOverlay(); + _system->grabOverlay((OverlayColor*)_screen->pixels, _screen->w); +} + +void ThemeRenderer::enable() { + init(); + resetDrawArea(); + _system->showOverlay(); + clearAll(); + _enabled = true; +} + +void ThemeRenderer::disable() { + _system->hideOverlay(); + _enabled = false; } template @@ -228,7 +251,7 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { if (isWidgetCached(type, r)) { drawCached(type, r); - } else { + } else if (_widgets[type] != 0) { for (uint i = 0; i < _widgets[type]->_steps.size(); ++i) _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); } @@ -242,6 +265,8 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, drawDD(kDDButtonIdle, r); else if (state == kStateHighlight) drawDD(kDDButtonHover, r); + else if (state == kStateDisabled) + drawDD(kDDButtonDisabled, r); // TODO: Add text drawing. @@ -290,6 +315,11 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider return; } +void ThemeRenderer::updateScreen() { +// renderDirtyScreen(); + _vectorRenderer->copyWholeFrame(_system); +} + void ThemeRenderer::renderDirtyScreen() { // TODO: This isn't really optimized. Check dirty squares for collisions // and all that. @@ -299,7 +329,7 @@ void ThemeRenderer::renderDirtyScreen() { for (uint i = 0; i < _dirtyScreen.size(); ++i) _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); - _system->updateScreen(); +// _system->updateScreen(); _dirtyScreen.clear(); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 8d3f57b547..3ce17c25b0 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -87,6 +87,7 @@ public: kDDButtonIdle, kDDButtonHover, + kDDButtonDisabled, kDDSurface, @@ -124,13 +125,13 @@ public: void clearAll(); void refresh() {} - void enable() {} - void disable() {} + void enable(); + void disable(); void openDialog() {} void closeAllDialogs() {} - void updateScreen() {} + void updateScreen(); //{} void resetDrawArea() {} void openDialog(bool top) {} @@ -210,6 +211,8 @@ protected: delete _widgets[i]; _widgets[i] = 0; } + + _themeOk = false; } void screenChange() {} @@ -268,6 +271,7 @@ protected: bool _initOk; bool _themeOk; bool _caching; + bool _enabled; Common::String _themeName; }; diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 4d0b3905b9..efa7a910e2 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -242,7 +242,7 @@ void NewGui::runLoop() { while (!_dialogStack.empty() && activeDialog == getTopDialog()) { if (_needRedraw) { redraw(); - _needRedraw = false; +// _needRedraw = false; } // Don't "tickle" the dialog until the theme has had a chance -- cgit v1.2.3 From 3b73b199a6006a84df06453335354e4e6728f6af Mon Sep 17 00:00:00 2001 From: Stephen Kennedy Date: Fri, 4 Jul 2008 11:56:31 +0000 Subject: - XMLParser - small improvement to allow "key=value" syntax as well as "key = value" syntax svn-id: r32906 --- common/xmlparser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 167d04249c..3738b69b7b 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -283,7 +283,7 @@ protected: while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - return isspace(_text[_pos]) != 0 || _text[_pos] == '>'; + return isspace(_text[_pos]) != 0 || _text[_pos] == '>' || _text[_pos] == '='; } /** -- cgit v1.2.3 From 96f2d9ca18eea27eaffda76fbce2168cddebbfb1 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 4 Jul 2008 20:05:30 +0000 Subject: Memory leaks. Bug fixes. svn-id: r32908 --- common/xmlparser.cpp | 5 +---- graphics/VectorRenderer.h | 13 ++++--------- gui/ThemeParser.cpp | 4 +++- gui/ThemeRenderer.cpp | 13 ++++++------- gui/ThemeRenderer.h | 13 +++++++------ gui/newgui.cpp | 2 +- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 3452db9e00..d5c8535932 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -143,10 +143,7 @@ bool XMLParser::parse() { _pos = 0; _activeKey.clear(); - while (_text[_pos]) { - if (_state == kParserError) - break; - + while (_text[_pos] && _state != kParserError) { if (skipSpaces()) continue; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0e679663d9..d6b315d2b3 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -535,22 +535,17 @@ public: * @see VectorRenderer::copyFrame() */ virtual void copyFrame(OSystem *sys, const Common::Rect &r) { -#ifdef OVERLAY_MULTIPLE_DEPTHS // TODO: change OSystem to support templated copyRectToOverlay - sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(r.left, r.top), - _activeSurface->w, r.top, r.left, r.width(), r.height()); -#else - sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(r.left, r.top), - _activeSurface->w, r.top, r.left, r.width(), r.height()); -#endif + sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(r.left, r.top), + _activeSurface->w, r.left, r.top, r.width(), r.height()); } virtual void copyWholeFrame(OSystem *sys) { #ifdef OVERLAY_MULTIPLE_DEPTHS sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); #else sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); + _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); #endif } diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index cd9ebc83a4..2726e15587 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -223,7 +223,9 @@ bool ThemeParser::parserCallback_DRAWSTEP() { if (!parseDrawStep(stepNode, drawstep, true)) return false; - _theme->addDrawStep(drawdataNode->values["id"], drawstep); + _theme->addDrawStep(drawdataNode->values["id"], *drawstep); + delete drawstep; + return true; } diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index a5a1625fb6..d17698c9c1 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -99,7 +99,7 @@ bool ThemeRenderer::init() { resetDrawArea(); } - if (!_themeOk || isThemeLoadingRequired()) { + if (isThemeLoadingRequired() || !_themeOk) { loadTheme(_themeName); Theme::loadTheme(_defaultConfig); @@ -173,7 +173,7 @@ void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { _vectorRenderer->setSurface(_screen); } -void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step) { +void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep step) { DrawData id = getDrawDataId(drawDataId); assert(_widgets[id] != 0); @@ -252,8 +252,9 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { if (isWidgetCached(type, r)) { drawCached(type, r); } else if (_widgets[type] != 0) { - for (uint i = 0; i < _widgets[type]->_steps.size(); ++i) - _vectorRenderer->drawStep(r, *_widgets[type]->_steps[i]); + for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); + step != _widgets[type]->_steps.end(); ++step) + _vectorRenderer->drawStep(r, *step); } } @@ -316,8 +317,7 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider } void ThemeRenderer::updateScreen() { -// renderDirtyScreen(); - _vectorRenderer->copyWholeFrame(_system); + renderDirtyScreen(); } void ThemeRenderer::renderDirtyScreen() { @@ -329,7 +329,6 @@ void ThemeRenderer::renderDirtyScreen() { for (uint i = 0; i < _dirtyScreen.size(); ++i) _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); -// _system->updateScreen(); _dirtyScreen.clear(); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 3ce17c25b0..56b81b21fc 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -42,16 +42,13 @@ namespace GUI { struct WidgetDrawData; struct WidgetDrawData { - Common::Array _steps; + Common::List _steps; bool _cached; Graphics::Surface *_surfaceCache; uint32 _cachedW, _cachedH; ~WidgetDrawData() { - for (uint i = 0; i < _steps.size(); ++i) - delete _steps[i]; - _steps.clear(); if (_surfaceCache) { @@ -69,8 +66,11 @@ class ThemeRenderer : public Theme { friend class GUI::Dialog; friend class GUI::GuiObject; + /** Strings representing each value in the DrawData enum */ static const char *kDrawDataStrings[]; - static const int kMaxDialogDepth = 4; + + /** Constant value to expand dirty rectangles, to make sure they are fully copied */ + static const int kDirtyRectangleThreshold = 2; public: enum GraphicsMode { @@ -159,6 +159,7 @@ public: void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { + r.grow(kDirtyRectangleThreshold); _dirtyScreen.push_back(r); return true; } @@ -172,7 +173,7 @@ public: return (DrawData)-1; } - void addDrawStep(Common::String &drawDataId, Graphics::DrawStep *step); + void addDrawStep(Common::String &drawDataId, Graphics::DrawStep step); bool addDrawData(DrawData data_id, bool cached); ThemeParser *parser() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index efa7a910e2..4d0b3905b9 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -242,7 +242,7 @@ void NewGui::runLoop() { while (!_dialogStack.empty() && activeDialog == getTopDialog()) { if (_needRedraw) { redraw(); -// _needRedraw = false; + _needRedraw = false; } // Don't "tickle" the dialog until the theme has had a chance -- cgit v1.2.3 From 40bf717d3ba7974d95414bf8c8cf1abe34de288d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 4 Jul 2008 23:51:23 +0000 Subject: closedKeyCallback on XMLParser (as asked by Kenny) svn-id: r32909 --- common/xmlparser.cpp | 5 +++++ common/xmlparser.h | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index d5c8535932..d0c89a9d3e 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -194,6 +194,11 @@ bool XMLParser::parse() { case kParserNeedPropertyName: if (activeClosure) { + if (!closedKeyCallback(_activeKey.top()->name)) { + parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str()); + break; + } + activeClosure = false; delete _activeKey.pop(); diff --git a/common/xmlparser.h b/common/xmlparser.h index 3738b69b7b..4c77696482 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -203,6 +203,20 @@ protected: return false; } + /** + * The closed key callback function must be overloaded by inheriting classes to + * implement parser-specific functions. + * + * The closedKeyCallback is issued once a key has been finished parsing, to let + * the parser verify that all the required subkeys, etc, were included. + * + * Returns true if the key was properly closed, false otherwise. + * By default, all keys are properly closed. + */ + virtual bool closedKeyCallback(Common::String keyName) { + return true; + } + /** * Parses the value of a given key. There's no reason to overload this. */ -- cgit v1.2.3 From 9b7faedb0de9f9c3bc18bff5bfc0a629142806b5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 6 Jul 2008 21:38:26 +0000 Subject: Bug fixes for "judgement day" (yay). svn-id: r32932 --- graphics/VectorRenderer.h | 5 +++++ gui/ThemeDefaultXML.cpp | 4 ++++ gui/ThemeRenderer.cpp | 3 +++ 3 files changed, 12 insertions(+) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index d6b315d2b3..08c8a8435d 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -535,8 +535,13 @@ public: * @see VectorRenderer::copyFrame() */ virtual void copyFrame(OSystem *sys, const Common::Rect &r) { +#ifdef OVERLAY_MULTIPLE_DEPTHS + sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(r.left, r.top), + _activeSurface->w, r.left, r.top, r.width(), r.height()); +#else sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(r.left, r.top), _activeSurface->w, r.left, r.top, r.width(), r.height()); +#endif } virtual void copyWholeFrame(OSystem *sys) { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 11ef1b58b0..182535a9c6 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -51,6 +51,10 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" + "" + + "" "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index d17698c9c1..281c02f8f4 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -196,6 +196,9 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { bool ThemeRenderer::loadTheme(Common::String themeName) { unloadTheme(); + if (themeName == "builtin" && !loadDefaultXML()) + error("Could not load default embeded theme."); + if (!loadThemeXML(themeName)) { warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); -- cgit v1.2.3 From 92ef8dd7502eb86185989a9e2e2b9d722930ec1e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 7 Jul 2008 18:37:22 +0000 Subject: Rendering pipeline. Bugfixes / debug widgets. svn-id: r32946 --- graphics/VectorRenderer.h | 36 ++++++++++++++++++++---- gui/ThemeDefaultXML.cpp | 9 ++++++ gui/ThemeParser.cpp | 7 ++++- gui/ThemeRenderer.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++--- gui/ThemeRenderer.h | 24 +++++----------- 5 files changed, 120 insertions(+), 27 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 08c8a8435d..7b04191f91 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -39,6 +39,16 @@ namespace Graphics { class VectorRenderer; struct DrawStep; +struct TextStep { + struct { + uint8 r, g, b; + bool set; + } + color; /** text color */ + + GUI::Theme::TextAlign align; +}; + struct DrawStep { struct { uint8 r, g, b; @@ -294,7 +304,7 @@ public: * @see shadowDisable() */ virtual void shadowEnable(int offset) { - if (offset > 0) + if (offset >= 0) _shadowOffset = offset; } @@ -346,13 +356,30 @@ public: } } + int stepGetRadius(const DrawStep &step, const Common::Rect &area) { + int radius = 0; + + if (step.radius == 0xFF) + radius = MIN(area.width(), area.height()) / 2; + else + radius = step.radius; + + if (step.scale != (1 << 16) && step.scale != 0) + radius = (radius * step.scale) >> 16; + + return radius; + } + /** * DrawStep callback functions for each drawing feature */ void drawCallback_CIRCLE(const Common::Rect &area, const DrawStep &step) { - uint16 x, y, w, h; + uint16 x, y, w, h, radius; + + radius = stepGetRadius(step, area); stepGetPositions(step, area, x, y, w, h); - drawCircle(x, y, (step.radius * step.scale) >> 16); + + drawCircle(x + radius, y + radius, radius); } void drawCallback_SQUARE(const Common::Rect &area, const DrawStep &step) { @@ -370,8 +397,7 @@ public: void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; stepGetPositions(step, area, x, y, w, h); - /* HACK! Radius of the rounded squares isn't scaled */ - drawRoundedSquare(x, y, step.radius, w, h); + drawRoundedSquare(x, y, stepGetRadius(step, area), w, h); } void drawCallback_FILLSURFACE(const Common::Rect &area, const DrawStep &step) { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 182535a9c6..fe14fbb403 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -57,6 +57,15 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" + + "" + "" + "" + + "" + "" + "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 2726e15587..463e8c81ea 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -95,6 +95,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->scale = (1 << 16); step->shadow = 0; step->stroke = 1; + step->radius = 0xFF; return step; } @@ -341,7 +342,11 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst Common::String functionName = stepNode->values["func"]; if (functionName == "roundedsq" || functionName == "circle") { - __PARSER_ASSIGN_INT(radius, "radius", true) + if (stepNode->values.contains("radius") && stepNode->values["radius"] == "auto") { + drawstep->radius = 0xFF; + } else { + __PARSER_ASSIGN_INT(radius, "radius", true); + } } if (functionName == "bevelsq") { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 281c02f8f4..bf481fabb8 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -275,6 +275,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, // TODO: Add text drawing. addDirtyRect(r); + debugWidgetPosition(r); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -283,21 +284,30 @@ void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo sta drawDD(kDDSeparator, r); addDirtyRect(r); + + debugWidgetPosition(r); } void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { if (!ready()) return; - drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r); - Common::Rect r2 = r; - r2.left += 16; // TODO: add variable for checkbox text offset. + int checkBoxSize = getFontHeight(); + + if (checkBoxSize > r.height()) + checkBoxSize = r.height(); + + r2.bottom = r2.top + checkBoxSize; + r2.right = r2.left + checkBoxSize; + + drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); // TODO: text drawing // getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); addDirtyRect(r); + debugWidgetPosition(r); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -312,15 +322,68 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo drawDD(kDDSliderFull, r2); addDirtyRect(r); + debugWidgetPosition(r); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { if (!ready()) return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { + if (!ready()) + return; + + debugWidgetPosition(r); +} + +void ThemeRenderer::debugWidgetPosition(const Common::Rect &r) { + _screen->hLine(r.left, r.top, r.right, 0xFFFF); + _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); + _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); + _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); } void ThemeRenderer::updateScreen() { - renderDirtyScreen(); +// renderDirtyScreen(); + _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 56b81b21fc..21fd53bf1d 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -143,18 +143,18 @@ public: int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } /** Widget drawing */ - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled) {} + void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false) {} + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled); void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled) {} + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled); void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft) {} - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled) {} + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); + void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled); void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) {} + void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {} void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} @@ -184,17 +184,6 @@ public: return _initOk && _themeOk; } - // REMOVED: theme name is looked up in NewGUI and passed to the constructor -/* bool loadTheme() { - ConfMan.registerDefault("gui_theme", "default"); - Common::String style(ConfMan.get("gui_theme")); - - if (style.compareToIgnoreCase("default") == 0) - style = "modern"; - - return loadTheme(style); - } */ - bool loadTheme(Common::String themeName); void setGraphicsMode(GraphicsMode mode); @@ -242,6 +231,7 @@ protected: void drawCached(DrawData type, const Common::Rect &r); inline void drawDD(DrawData type, const Common::Rect &r); + inline void ThemeRenderer::debugWidgetPosition(const Common::Rect &r); // TODO void restoreBackground(Common::Rect r, bool special = false) {} -- cgit v1.2.3 From 24a8fb1820ab27c050ff65f8447f3680d9e8064a Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Mon, 7 Jul 2008 18:42:57 +0000 Subject: Fixing compilation svn-id: r32947 --- gui/ThemeRenderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 21fd53bf1d..9450186b34 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -231,7 +231,7 @@ protected: void drawCached(DrawData type, const Common::Rect &r); inline void drawDD(DrawData type, const Common::Rect &r); - inline void ThemeRenderer::debugWidgetPosition(const Common::Rect &r); + inline void debugWidgetPosition(const Common::Rect &r); // TODO void restoreBackground(Common::Rect r, bool special = false) {} -- cgit v1.2.3 From ccf9368c533110a5c72df3607466a16651ec6497 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 10 Jul 2008 15:50:44 +0000 Subject: Added support for Text Steps in the Vector Renderer. svn-id: r32991 --- graphics/VectorRenderer.cpp | 14 ++++++++++++ graphics/VectorRenderer.h | 7 ++++++ gui/ThemeDefaultXML.cpp | 3 +++ gui/ThemeParser.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++- gui/ThemeParser.h | 1 + gui/ThemeRenderer.cpp | 32 ++++++++++++++++++++++----- gui/ThemeRenderer.h | 7 ++++++ 7 files changed, 111 insertions(+), 6 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index f679d2fe67..daeeb43f69 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -71,6 +71,14 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { (this->*(step.drawingCall))(area, step); } +void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step) { + if (step.color.set) + setFgColor(step.color.r, step.color.g, step.color.b); + + assert(step.font); + drawString(step.font, text.c_str(), area, step.align); +} + /******************************************************************** * MISCELANEOUS functions ********************************************************************/ @@ -176,6 +184,12 @@ inline uint32 fp_sqroot(uint32 x) { /******************************************************************** * Primitive shapes drawing - Public API calls - VectorRendererSpec ********************************************************************/ +template +void VectorRendererSpec:: +drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) { + font->drawString(_activeSurface, text, area.left, area.top, area.width(), _fgColor, (Graphics::TextAlignment)align, 0, false); +} + /** LINES **/ template void VectorRendererSpec:: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 7b04191f91..402c76a55c 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -47,6 +47,8 @@ struct TextStep { color; /** text color */ GUI::Theme::TextAlign align; + char *text; + Graphics::Font *font; }; struct DrawStep { @@ -426,6 +428,7 @@ public: * @param step Pointer to a DrawStep struct. */ virtual void drawStep(const Common::Rect &area, const DrawStep &step); + virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step); /** * Copies the current surface to the system overlay @@ -442,6 +445,8 @@ public: * @param r Position in the active drawing surface to do the blitting. */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; + + virtual void drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) = 0; protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -507,6 +512,8 @@ public: void drawBeveledSquare(int x, int y, int w, int h, int bevel) { drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); } + + void drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align); /** * @see VectorRenderer::setFgColor() diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index fe14fbb403..3793fcc82b 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -51,14 +51,17 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" "" "" "" + "" "" "" "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 463e8c81ea..eae131af50 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -48,7 +48,8 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _callbacks["render_info"] = &ThemeParser::parserCallback_renderInfo; _callbacks["layout_info"] = &ThemeParser::parserCallback_layoutInfo; _callbacks["default"] = &ThemeParser::parserCallback_defaultSet; - + _callbacks["text"] = &ThemeParser::parserCallback_text; + _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; _drawFunctions["roundedsq"] = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; @@ -136,6 +137,56 @@ bool ThemeParser::parserCallback_defaultSet() { return parseDrawStep(defNode, step, false); } +bool ThemeParser::parserCallback_text() { + ParserNode *tNode = getActiveNode(); + ParserNode *parentNode = getParentNode(tNode); + + if (parentNode == 0 || parentNode->name != "drawdata") + return parserError("Text Steps must be contained inside keys."); + + Graphics::TextStep step; + + if (tNode->values.contains("align") == false) + return parserError("Text inside widgets requires an alignement key."); + + if (tNode->values["align"] == "left") + step.align = GUI::Theme::kTextAlignLeft; + else if (tNode->values["align"] == "right") + step.align = GUI::Theme::kTextAlignRight; + else if (tNode->values["align"] == "center") + step.align = GUI::Theme::kTextAlignCenter; + else return parserError("Invalid value for text alignment."); + + + if (tNode->values.contains("color")) { + int red, green, blue; + + if (parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue) == false || + red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) + return parserError("Error when parsing color value for text definition"); + + step.color.r = red; + step.color.g = green; + step.color.b = blue; + step.color.set = true; + } else if (_defaultStepLocal && _defaultStepLocal->fgColor.set) { + step.color.r = _defaultStepLocal->fgColor.r; + step.color.g = _defaultStepLocal->fgColor.g; + step.color.b = _defaultStepLocal->fgColor.b; + step.color.set = true; + } else if (_defaultStepGlobal && _defaultStepGlobal->fgColor.set) { + step.color.r = _defaultStepGlobal->fgColor.r; + step.color.g = _defaultStepGlobal->fgColor.g; + step.color.b = _defaultStepGlobal->fgColor.b; + step.color.set = true; + } else { + return parserError("Cannot assign color for text drawing."); + } + + _theme->addTextStep(parentNode->values["id"], step); + return true; +} + bool ThemeParser::parserCallback_renderInfo() { ParserNode *infoNode = getActiveNode(); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index cddb91b21e..778158bff0 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -328,6 +328,7 @@ protected: bool parserCallback_renderInfo(); bool parserCallback_layoutInfo(); bool parserCallback_defaultSet(); + bool parserCallback_text(); void cleanup(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index bf481fabb8..71943e2586 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -180,6 +180,19 @@ void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep s _widgets[id]->_steps.push_back(step); } +bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep step) { + DrawData id = getDrawDataId(drawDataId); + + assert(_widgets[id] != 0); + if (_widgets[id]->_hasText == true) + return false; + + _widgets[id]->_textStep = step; + _widgets[id]->_hasText = true; + + return true; +} + bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { assert(data_id >= 0 && data_id < kDrawDataMAX); @@ -189,6 +202,7 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; _widgets[data_id]->_surfaceCache = 0; + _widgets[data_id]->_hasText = false; return true; } @@ -252,9 +266,12 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { } void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { + if (_widgets[type] == 0) + return; + if (isWidgetCached(type, r)) { drawCached(type, r); - } else if (_widgets[type] != 0) { + } else { for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); step != _widgets[type]->_steps.end(); ++step) _vectorRenderer->drawStep(r, *step); @@ -264,15 +281,20 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { if (!ready()) return; + + DrawData dd; if (state == kStateEnabled) - drawDD(kDDButtonIdle, r); + dd = kDDButtonIdle; else if (state == kStateHighlight) - drawDD(kDDButtonHover, r); + dd = kDDButtonHover; else if (state == kStateDisabled) - drawDD(kDDButtonDisabled, r); + dd = kDDButtonDisabled; - // TODO: Add text drawing. + drawDD(dd, r); + if (hasWidgetText(dd)) + _vectorRenderer->textStep(str, r, _widgets[dd]->_textStep); + addDirtyRect(r); debugWidgetPosition(r); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 9450186b34..74225d035c 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -43,6 +43,8 @@ struct WidgetDrawData; struct WidgetDrawData { Common::List _steps; + Graphics::TextStep _textStep; + bool _hasText; bool _cached; Graphics::Surface *_surfaceCache; @@ -175,6 +177,7 @@ public: void addDrawStep(Common::String &drawDataId, Graphics::DrawStep step); bool addDrawData(DrawData data_id, bool cached); + bool addTextStep(Common::String &drawDataId, Graphics::TextStep step); ThemeParser *parser() { return _parser; @@ -227,6 +230,10 @@ protected: void redrawDialogStack(); + bool hasWidgetText(DrawData type) { + return (_widgets[type] != 0 && _widgets[type]->_hasText); + } + bool isWidgetCached(DrawData type, const Common::Rect &r); void drawCached(DrawData type, const Common::Rect &r); -- cgit v1.2.3 From e0aad7f4be66a9e30f0226c17c9d2bd0a8138898 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 10 Jul 2008 16:37:45 +0000 Subject: Bugfix: Delayed loading of fonts svn-id: r32993 --- graphics/VectorRenderer.cpp | 3 +-- graphics/VectorRenderer.h | 6 +++--- gui/ThemeRenderer.cpp | 13 ++++++++++++- gui/ThemeRenderer.h | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index daeeb43f69..0c1d01213d 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -75,7 +75,6 @@ void VectorRenderer::textStep(const Common::String &text, const Common::Rect &ar if (step.color.set) setFgColor(step.color.r, step.color.g, step.color.b); - assert(step.font); drawString(step.font, text.c_str(), area, step.align); } @@ -186,7 +185,7 @@ inline uint32 fp_sqroot(uint32 x) { ********************************************************************/ template void VectorRendererSpec:: -drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) { +drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) { font->drawString(_activeSurface, text, area.left, area.top, area.width(), _fgColor, (Graphics::TextAlignment)align, 0, false); } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 402c76a55c..9b5481cddf 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -48,7 +48,7 @@ struct TextStep { GUI::Theme::TextAlign align; char *text; - Graphics::Font *font; + const Graphics::Font *font; }; struct DrawStep { @@ -446,7 +446,7 @@ public: */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; - virtual void drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) = 0; protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -513,7 +513,7 @@ public: drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); } - void drawString(Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align); + void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align); /** * @see VectorRenderer::setFgColor() diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 71943e2586..ca686b8583 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -188,6 +188,7 @@ bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep s return false; _widgets[id]->_textStep = step; + _widgets[id]->_textStep.font = 0; _widgets[id]->_hasText = true; return true; @@ -278,11 +279,20 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { } } +void ThemeRenderer::drawDDText(DrawData type, const Common::Rect &r, const Common::String &text) { + if (hasWidgetText(type)) { + if (_widgets[type]->_textStep.font == 0) + _widgets[type]->_textStep.font = _font; + + _vectorRenderer->textStep(text, r, _widgets[type]->_textStep); + } +} + void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { if (!ready()) return; - DrawData dd; + DrawData dd = kDDButtonIdle; if (state == kStateEnabled) dd = kDDButtonIdle; @@ -292,6 +302,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, dd = kDDButtonDisabled; drawDD(dd, r); + drawDDText(dd, r, str); if (hasWidgetText(dd)) _vectorRenderer->textStep(str, r, _widgets[dd]->_textStep); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 74225d035c..f2e30bae09 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -238,6 +238,7 @@ protected: void drawCached(DrawData type, const Common::Rect &r); inline void drawDD(DrawData type, const Common::Rect &r); + inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text); inline void debugWidgetPosition(const Common::Rect &r); // TODO -- cgit v1.2.3 From a90be07c3e93014174a3b4f3fa0be25aad227859 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 10 Jul 2008 20:36:02 +0000 Subject: Support for Vertical text alignement. svn-id: r32995 --- graphics/VectorRenderer.cpp | 22 +++++++++++++++++++--- graphics/VectorRenderer.h | 9 ++++++--- gui/ThemeDefaultXML.cpp | 6 +++--- gui/ThemeParser.cpp | 23 +++++++++++++++-------- gui/ThemeRenderer.cpp | 5 +---- gui/theme.h | 7 +++++++ 6 files changed, 51 insertions(+), 21 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0c1d01213d..8856386819 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -75,7 +75,7 @@ void VectorRenderer::textStep(const Common::String &text, const Common::Rect &ar if (step.color.set) setFgColor(step.color.r, step.color.g, step.color.b); - drawString(step.font, text.c_str(), area, step.align); + drawString(step.font, text.c_str(), area, step.alignHorizontal, step.alignVertical); } /******************************************************************** @@ -185,8 +185,24 @@ inline uint32 fp_sqroot(uint32 x) { ********************************************************************/ template void VectorRendererSpec:: -drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) { - font->drawString(_activeSurface, text, area.left, area.top, area.width(), _fgColor, (Graphics::TextAlignment)align, 0, false); +drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, + GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) { + + int offset = 0; + + switch (alignV) { + case GUI::Theme::kTextAlignVCenter: + offset = area.top + (area.height() - font->getFontHeight()) / 2; + break; + case GUI::Theme::kTextAlignVBottom: + offset = area.bottom - font->getFontHeight(); + break; + case GUI::Theme::kTextAlignVTop: + offset = area.top; + break; + } + + font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, 0, false); } /** LINES **/ diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 9b5481cddf..01fccb8c30 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -46,7 +46,8 @@ struct TextStep { } color; /** text color */ - GUI::Theme::TextAlign align; + GUI::Theme::TextAlign alignHorizontal; + GUI::Theme::TextAlignVertical alignVertical; char *text; const Graphics::Font *font; }; @@ -446,7 +447,7 @@ public: */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; - virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -513,7 +514,9 @@ public: drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); } - void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign align); + void drawString(const Graphics::Font *font, const Common::String &text, + const Common::Rect &area, GUI::Theme::TextAlign alignH, + GUI::Theme::TextAlignVertical alignV); /** * @see VectorRenderer::setFgColor() diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 3793fcc82b..da40d64731 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -51,17 +51,17 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index eae131af50..7f02c1eb57 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -146,17 +146,24 @@ bool ThemeParser::parserCallback_text() { Graphics::TextStep step; - if (tNode->values.contains("align") == false) - return parserError("Text inside widgets requires an alignement key."); + if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false) + return parserError("Text inside widgets requires proper alignment keys."); - if (tNode->values["align"] == "left") - step.align = GUI::Theme::kTextAlignLeft; - else if (tNode->values["align"] == "right") - step.align = GUI::Theme::kTextAlignRight; - else if (tNode->values["align"] == "center") - step.align = GUI::Theme::kTextAlignCenter; + if (tNode->values["horizontal_align"] == "left") + step.alignHorizontal = GUI::Theme::kTextAlignLeft; + else if (tNode->values["horizontal_align"] == "right") + step.alignHorizontal = GUI::Theme::kTextAlignRight; + else if (tNode->values["horizontal_align"] == "center") + step.alignHorizontal = GUI::Theme::kTextAlignCenter; else return parserError("Invalid value for text alignment."); + if (tNode->values["vertical_align"] == "top") + step.alignVertical = GUI::Theme::kTextAlignVTop; + else if (tNode->values["vertical_align"] == "center") + step.alignVertical = GUI::Theme::kTextAlignVCenter; + else if (tNode->values["vertical_align"] == "bottom") + step.alignVertical = GUI::Theme::kTextAlignVBottom; + else return parserError("Invalid value for text alignment."); if (tNode->values.contains("color")) { int red, green, blue; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index ca686b8583..0fd7afbaf5 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -302,10 +302,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, dd = kDDButtonDisabled; drawDD(dd, r); - drawDDText(dd, r, str); - if (hasWidgetText(dd)) - _vectorRenderer->textStep(str, r, _widgets[dd]->_textStep); - + drawDDText(dd, r, str); addDirtyRect(r); debugWidgetPosition(r); diff --git a/gui/theme.h b/gui/theme.h index 320d2544e0..e9ce8bb01d 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -92,6 +92,13 @@ public: kTextAlignCenter, //! Text should be centered kTextAlignRight //! Text should be aligned to the right }; + + //! Vertical alignment of the text. + enum TextAlignVertical { + kTextAlignVBottom, + kTextAlignVCenter, + kTextAlignVTop + }; //! Widget background type enum WidgetBackground { -- cgit v1.2.3 From e64711378eb19dc6474249bc83033087edd4d7d7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 11 Jul 2008 13:25:23 +0000 Subject: Widget backgrounds svn-id: r33005 --- gui/ThemeDefaultXML.cpp | 3 ++- gui/ThemeRenderer.cpp | 24 ++++++++++++++++-------- gui/ThemeRenderer.h | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index da40d64731..95b425e700 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -61,11 +61,12 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" + "" "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 0fd7afbaf5..ff3a63b8b8 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -323,18 +323,17 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st return; Common::Rect r2 = r; - int checkBoxSize = getFontHeight(); - - if (checkBoxSize > r.height()) - checkBoxSize = r.height(); + const int checkBoxSize = MIN((int)r.height(), getFontHeight()); r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); - - // TODO: text drawing -// getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); + + r2.left = r2.right + checkBoxSize; + r2.right = r.right; + + drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); addDirtyRect(r); debugWidgetPosition(r); @@ -365,7 +364,16 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { if (!ready()) return; - + + if (hints & THEME_HINT_MAIN_DIALOG) + drawDD(kDDMainDialogBackground, r); + else if (hints & THEME_HINT_SPECIAL_COLOR) + drawDD(kDDSpecialColorBackground, r); + else if (hints & THEME_HINT_PLAIN_COLOR) + drawDD(kDDPlainColorBackground, r); + else + drawDD(kDDDefaultBackground, r); + debugWidgetPosition(r); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index f2e30bae09..0e7f651904 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -85,7 +85,7 @@ public: kDDMainDialogBackground, kDDSpecialColorBackground, kDDPlainColorBackground, - kDDDefaulBackground, + kDDDefaultBackground, kDDButtonIdle, kDDButtonHover, -- cgit v1.2.3 From db932dce89eac7664eb9fc654f87ba89576da66f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 12 Jul 2008 01:59:33 +0000 Subject: Debug widgets. Added dialog backgrounds. svn-id: r33011 --- gui/ThemeDefaultXML.cpp | 4 ++++ gui/ThemeRenderer.cpp | 34 ++++++++++++++++++---------------- gui/ThemeRenderer.h | 2 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 95b425e700..9227514a66 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -49,6 +49,10 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" + + "" + "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index ff3a63b8b8..1587a356e4 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -305,7 +305,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, drawDDText(dd, r, str); addDirtyRect(r); - debugWidgetPosition(r); + debugWidgetPosition("BTN", r); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -315,7 +315,7 @@ void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo sta drawDD(kDDSeparator, r); addDirtyRect(r); - debugWidgetPosition(r); + debugWidgetPosition("Separator", r); } void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { @@ -336,7 +336,7 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); addDirtyRect(r); - debugWidgetPosition(r); + debugWidgetPosition("Checkbox", r); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -351,68 +351,70 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo drawDD(kDDSliderFull, r2); addDirtyRect(r); - debugWidgetPosition(r); + debugWidgetPosition("Slider", r); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("SCB", r); } void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { if (!ready()) return; - if (hints & THEME_HINT_MAIN_DIALOG) + if (hints & THEME_HINT_MAIN_DIALOG) { drawDD(kDDMainDialogBackground, r); - else if (hints & THEME_HINT_SPECIAL_COLOR) + } else if (hints & THEME_HINT_SPECIAL_COLOR) { drawDD(kDDSpecialColorBackground, r); - else if (hints & THEME_HINT_PLAIN_COLOR) + } else if (hints & THEME_HINT_PLAIN_COLOR) { drawDD(kDDPlainColorBackground, r); - else + } else { drawDD(kDDDefaultBackground, r); + } - debugWidgetPosition(r); + debugWidgetPosition("Background", r); } void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("Caret", r); } void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("Popup Widget", r); } void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("Surface", r); } void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("Widget Background", r); } void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { if (!ready()) return; - debugWidgetPosition(r); + debugWidgetPosition("Tab widget", r); } -void ThemeRenderer::debugWidgetPosition(const Common::Rect &r) { +void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { + _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignLeft, 0, true); _screen->hLine(r.left, r.top, r.right, 0xFFFF); _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 0e7f651904..6e9866d653 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -239,7 +239,7 @@ protected: inline void drawDD(DrawData type, const Common::Rect &r); inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text); - inline void debugWidgetPosition(const Common::Rect &r); + inline void debugWidgetPosition(const char *name, const Common::Rect &r); // TODO void restoreBackground(Common::Rect r, bool special = false) {} -- cgit v1.2.3 From 4539cdf2188d6461ecdc2fbc485d49eab1fb7311 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 12 Jul 2008 18:17:11 +0000 Subject: - Better support for relative positions in Vector Renderer. - More widgets. svn-id: r33016 --- graphics/VectorRenderer.h | 39 ++++++++++++++++----------------------- gui/ThemeDefaultXML.cpp | 15 ++++++++++----- gui/ThemeParser.cpp | 30 +++++++++++++++++------------- gui/ThemeRenderer.cpp | 4 +++- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 01fccb8c30..4dcef24e31 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -62,15 +62,9 @@ struct DrawStep { gradColor1, /** gradient start*/ gradColor2; /** gradient end */ - bool fillArea; /** If enabled, the draw step occupies the whole drawing area */ - - struct { - uint16 pos; - bool relative; - } x, y; /** Horizontal and vertical coordinates. Relative specifies if they are - measured from the opposite direction of the drawing area */ - - uint16 w, h; /** width and height */ + bool autoWidth, autoHeight; + int16 x, y, w, h; /** width, height and position, if not measured automatically. + negative values mean counting from the opposite direction */ uint8 shadow, stroke, factor, radius; /** Misc options... */ @@ -332,23 +326,22 @@ public: } void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { - if (step.fillArea) { + if (!step.autoWidth) { + in_w = step.w; + if (step.x >= 0) in_x = area.left + step.x; + else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. + } else { in_x = area.left; - in_y = area.top; in_w = area.width(); - in_h = area.height(); + } + + if (!step.autoHeight) { + in_h = step.h; + if (step.y >= 0) in_y = area.top + step.y; + else in_y = area.top + area.height() + step.y; // relative } else { - if (!step.x.relative) in_x = area.left + step.x.pos; - else in_x = area.left + area.width() - step.x.pos; - - if (!step.y.relative) in_y = area.top + step.y.pos; - else in_y = area.top + area.height() - step.y.pos; - - if (in_x + step.w > area.right) in_w = area.right - in_x; - else in_w = step.w; - - if (in_y + step.h > area.bottom) in_h = area.bottom - in_y; - else in_h = step.h; + in_y = area.top; + in_h = area.height(); } if (step.scale != (1 << 16) && step.scale != 0) { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 9227514a66..0c35fa1e1f 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -50,28 +50,33 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" + "" + "/* */" + "" + "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 7f02c1eb57..e882945ff1 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -91,7 +91,8 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->extraData = 0; step->factor = 1; - step->fillArea = true; + step->autoWidth = true; + step->autoHeight = true; step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; @@ -335,7 +336,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { } bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific) { - int red, green, blue, w, h, x; + int red, green, blue, x; Common::String val; /** @@ -362,8 +363,6 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst * 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 @@ -431,16 +430,21 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } if (stepNode->values.contains("size")) { - if (stepNode->values["size"] == "auto") { - drawstep->fillArea = true; - } else if (sscanf(stepNode->values["size"].c_str(), "%d, %d", &w, &h) == 2) { - drawstep->fillArea = false; - drawstep->w = w; - drawstep->h = h; - } else { - return parserError("Invalid value in 'size' subkey: Valid options are 'auto' or 'X, X' to define width and height."); - } + warning("The keyword has been deprecated. Use and instead"); + } + + if (stepNode->values.contains("width")) { + drawstep->autoWidth = false; + __PARSER_ASSIGN_INT(x, "xpos", true); + } + + if (stepNode->values.contains("height")) { + drawstep->autoHeight = false; + __PARSER_ASSIGN_INT(y, "ypos", true); } + + __PARSER_ASSIGN_INT(w, "width", false); + __PARSER_ASSIGN_INT(h, "height", false); } if (stepNode->values.contains("fill")) { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1587a356e4..2df58ed343 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -388,6 +388,8 @@ void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { if (!ready()) return; + + drawDD(kDDPopUp, r); debugWidgetPosition("Popup Widget", r); } @@ -414,7 +416,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, } void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { - _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignLeft, 0, true); + _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); _screen->hLine(r.left, r.top, r.right, 0xFFFF); _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); -- cgit v1.2.3 From 4cb2b8c3c43d26569960e271ac35e0dd9f4de5b4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 13 Jul 2008 10:50:57 +0000 Subject: Improved support for graphics positioning. More widgets. New triangle drawing function. svn-id: r33027 --- base/main.cpp | 13 --------- graphics/VectorRenderer.cpp | 46 +++++++++++++++++++++++++++++-- graphics/VectorRenderer.h | 62 +++++++++++++++++++++++++++++++++++++---- gui/ThemeDefaultXML.cpp | 6 ++-- gui/ThemeParser.cpp | 67 ++++++++++++++++++++++++++++++++++++++++----- gui/ThemeRenderer.cpp | 10 +++---- 6 files changed, 167 insertions(+), 37 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index b7d30d30f8..219fa0cdc5 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -70,17 +70,6 @@ static bool launcherDialog(OSystem &system) { // Clear the main screen system.clearScreen(); -// GUI::ThemeRenderer *test = new GUI::ThemeRenderer("modern", GUI::ThemeRenderer::kGfxAntialias16bit); - -#if defined LOL - -// g_InterfaceManager.runGUI(); - InterfaceManager *manager = new InterfaceManager(); - manager->openDialog(kDialogLauncher); - return (manager.runGUI() != -1); - -#else - #if defined(_WIN32_WCE) CELauncherDialog dlg; #elif defined(__DC__) @@ -89,8 +78,6 @@ static bool launcherDialog(OSystem &system) { GUI::LauncherDialog dlg; #endif return (dlg.runModal() != -1); - -#endif // vector renderer debug } static const EnginePlugin *detectPlugin() { diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 8856386819..efdaea80c8 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -399,7 +399,12 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { switch(orient) { case kTriangleUp: case kTriangleDown: - drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); +#ifdef VECTOR_RENDERER_FAST_TRIANGLES + if (w == h) + drawTriangleFast(x, y, w, (orient == kTriangleDown), color, Base::_fillMode); + else +#endif + drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); break; case kTriangleLeft: @@ -408,8 +413,14 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { } if (Base::_strokeWidth > 0) - if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) - drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), _fgColor, kFillDisabled); + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { +#ifdef VECTOR_RENDERER_FAST_TRIANGLES + if (w == h) + drawTriangleFast(x, y, w, (orient == kTriangleDown), _fgColor, kFillDisabled); + else +#endif + drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), _fgColor, kFillDisabled); + } } /******************************************************************** @@ -616,6 +627,35 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color } +/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */ +template +void VectorRendererSpec:: +drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { + int pitch = Base::surfacePitch(); + int hstep = 0; + + PixelType *ptr_right = 0, *ptr_left = 0; + + if (inverted) { + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1); + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); + } else { + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1 + size); + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1 + size); + pitch = -pitch; + } + + while (ptr_left != ptr_right) { + colorFill(ptr_left, ptr_right, color); + ptr_left += pitch; + ptr_right += pitch; + if (hstep++ % 3) { + ptr_left++; + ptr_right--; + } + } +} + /** ROUNDED SQUARE ALGORITHM **/ template void VectorRendererSpec:: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 4dcef24e31..3af682953d 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -65,6 +65,15 @@ struct DrawStep { bool autoWidth, autoHeight; int16 x, y, w, h; /** width, height and position, if not measured automatically. negative values mean counting from the opposite direction */ + + enum VectorAlignment { + kVectorAlignManual, + kVectorAlignLeft, + kVectorAlignRight, + kVectorAlignBottom, + kVectorAlignTop, + kVectorAlignCenter + } xAlign, yAlign; uint8 shadow, stroke, factor, radius; /** Misc options... */ @@ -327,18 +336,58 @@ public: void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { if (!step.autoWidth) { - in_w = step.w; - if (step.x >= 0) in_x = area.left + step.x; - else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. + in_w = step.w == -1 ? area.height() : step.w; + + switch(step.xAlign) { + case Graphics::DrawStep::kVectorAlignManual: + if (step.x >= 0) in_x = area.left + step.x; + else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. + break; + + case Graphics::DrawStep::kVectorAlignCenter: + in_x = area.left + (area.width() / 2) - (in_w / 2); + break; + + case Graphics::DrawStep::kVectorAlignLeft: + in_x = area.left; + break; + + case Graphics::DrawStep::kVectorAlignRight: + in_x = area.left + area.width() - in_w; + break; + + default: + error("Vertical alignment in horizontal data."); + } } else { in_x = area.left; in_w = area.width(); } if (!step.autoHeight) { - in_h = step.h; - if (step.y >= 0) in_y = area.top + step.y; - else in_y = area.top + area.height() + step.y; // relative + in_h = step.h == -1 ? area.width() : step.h; + + switch(step.yAlign) { + case Graphics::DrawStep::kVectorAlignManual: + if (step.y >= 0) in_y = area.top + step.y; + else in_y = area.top + area.height() + step.y; // relative + break; + + case Graphics::DrawStep::kVectorAlignCenter: + in_y = area.top + (area.height() / 2) - (in_h / 2); + break; + + case Graphics::DrawStep::kVectorAlignTop: + in_y = area.top; + break; + + case Graphics::DrawStep::kVectorAlignBottom: + in_y = area.top + area.height() - in_h; + break; + + default: + error("Horizontal alignment in vertical data."); + } } else { in_y = area.top; in_h = area.height(); @@ -682,6 +731,7 @@ protected: virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); + virtual void drawTriangleFast(int x, int y, int size, bool inverted, PixelType color, FillMode fill_m); virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color); /** diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 0c35fa1e1f..3cd2d735d2 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -51,12 +51,12 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" - "/* */" + "" + "" "" "" - "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index e882945ff1..eec9801b59 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -89,6 +89,13 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->gradColor1.set = false; step->gradColor2.set = false; + step->xAlign = Graphics::DrawStep::kVectorAlignManual; + step->yAlign = Graphics::DrawStep::kVectorAlignManual; + step->x = 0; + step->y = 0; + step->w = 0; + step->h = 0; + step->extraData = 0; step->factor = 1; step->autoWidth = true; @@ -433,18 +440,64 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst warning("The keyword has been deprecated. Use and instead"); } - if (stepNode->values.contains("width")) { + if (stepNode->values.contains("width") && stepNode->values["width"] != "auto") { drawstep->autoWidth = false; - __PARSER_ASSIGN_INT(x, "xpos", true); + + 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 tag must be included."); + } } - if (stepNode->values.contains("height")) { + if (stepNode->values.contains("height") && stepNode->values["height"] != "auto") { drawstep->autoHeight = false; - __PARSER_ASSIGN_INT(y, "ypos", true); - } - __PARSER_ASSIGN_INT(w, "width", false); - __PARSER_ASSIGN_INT(h, "height", 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 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")) { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 2df58ed343..ce9e94faa2 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -416,11 +416,11 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, } void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { - _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); - _screen->hLine(r.left, r.top, r.right, 0xFFFF); - _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); - _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); - _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); + // _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); + // _screen->hLine(r.left, r.top, r.right, 0xFFFF); + // _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); + // _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); + // _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); } void ThemeRenderer::updateScreen() { -- cgit v1.2.3 From 9a4992cc37252eb7162aafa72c868558d1b328f1 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 13 Jul 2008 11:07:56 +0000 Subject: More widgets. svn-id: r33029 --- gui/ThemeDefaultXML.cpp | 4 ++++ gui/ThemeRenderer.cpp | 29 ++++++++++++++++++++++++----- gui/ThemeRenderer.h | 9 +++++---- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 3cd2d735d2..932c239f37 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -79,6 +79,10 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" + + "" + "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index ce9e94faa2..5f4c43dc79 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -44,13 +44,16 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "special_bg", "plain_bg", "default_bg", + + "widget_default", + "widget_small", + "widget_textedit", + "widget_slider", "button_idle", "button_hover", "button_disabled", - "surface", - "slider_full", "slider_empty", @@ -60,8 +63,6 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "tab", "scrollbar_base", - "scrollbar_top", - "scrollbar_bottom", "scrollbar_handle", "popup", @@ -404,7 +405,25 @@ void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface & void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { if (!ready()) return; - + + switch (background) { + case kWidgetBackgroundBorderSmall: + drawDD(kDDWidgetBackgroundSmall, r); + break; + + case kWidgetBackgroundEditText: + drawDD(kDDWidgetBackgroundEditText, r); + break; + + case kWidgetBackgroundSlider: + drawDD(kDDWidgetBackgroundSlider, r); + break; + + default: + drawDD(kDDWidgetBackgroundDefault, r); + break; + } + debugWidgetPosition("Widget Background", r); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 6e9866d653..aa4008c0e8 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -86,13 +86,16 @@ public: kDDSpecialColorBackground, kDDPlainColorBackground, kDDDefaultBackground, + + kDDWidgetBackgroundDefault, + kDDWidgetBackgroundSmall, + kDDWidgetBackgroundEditText, + kDDWidgetBackgroundSlider, kDDButtonIdle, kDDButtonHover, kDDButtonDisabled, - kDDSurface, - kDDSliderFull, kDDSliderEmpty, @@ -102,8 +105,6 @@ public: kDDTab, kDDScrollbarBase, - kDDScrollbarButtonTop, - kDDScrollbarButtonBottom, kDDScrollbarHandle, kDDPopUp, -- cgit v1.2.3 From a95c6fc76d58d3225e4f31e45ea9d686c79def84 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 13 Jul 2008 16:41:44 +0000 Subject: Bugfix: Strange behaviour in rounded square corners. svn-id: r33039 --- graphics/VectorRenderer.cpp | 6 ++++-- gui/ThemeDefaultXML.cpp | 6 +++--- gui/ThemeParser.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index efdaea80c8..1827d71024 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -339,7 +339,7 @@ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0 || r > 128) + w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0 || r > 128 || (r << 1) > w || (r << 1) > h) return; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset @@ -712,6 +712,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto colorFill(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); colorFill(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + +// __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } else { while (x++ < y) { @@ -724,7 +726,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto colorFill(ptr_bl - y + px, ptr_br + y + px, color); // FIXME: maybe not needed at all? - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); +// __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 932c239f37..68c87c6f2c 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -60,13 +60,13 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" - "" + "" + "" "" "" "" - "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index eec9801b59..398eab010a 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -103,7 +103,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; - step->stroke = 1; + step->stroke = 0; step->radius = 0xFF; return step; -- cgit v1.2.3 From e7e7ff9b344356c0a9ffed2998b597328eb1331f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 13 Jul 2008 17:08:44 +0000 Subject: Bugfix of the bugfix. Rounded squares work now on all resolutions. svn-id: r33040 --- graphics/VectorRenderer.cpp | 34 ++++++++++++++++++++++++++-------- gui/ThemeDefaultXML.cpp | 2 +- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 1827d71024..19a4f75058 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -129,6 +129,17 @@ inline uint32 fp_sqroot(uint32 x) { *(ptr4 + (y) + (px)) = color; \ } +#define __BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ + *(ptr1 + (y) - (px)) = color1; \ + *(ptr1 + (x) - (py)) = color2; \ + *(ptr2 - (x) - (py)) = color2; \ + *(ptr2 - (y) - (px)) = color1; \ + *(ptr3 - (y) + (px)) = color3; \ + *(ptr3 - (x) + (py)) = color4; \ + *(ptr4 + (x) + (py)) = color4; \ + *(ptr4 + (y) + (px)) = color3; \ +} + #define __BE_RESET() { \ f = 1 - r; \ ddF_x = 0; ddF_y = -2 * r; \ @@ -703,17 +714,24 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto } } else { __BE_RESET(); - + PixelType color1, color2, color3, color4; + if (fill_m == kFillGradient) { while (x++ < y) { __BE_ALGORITHM(); - colorFill(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); - colorFill(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); + + color1 = calcGradient(real_radius - x, long_h); + color2 = calcGradient(real_radius - y, long_h); + color3 = calcGradient(long_h - r + x, long_h); + color4 = calcGradient(long_h - r + y, long_h); + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); - colorFill(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); - colorFill(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + colorFill(ptr_bl - x + py, ptr_br + x + py, color4); + colorFill(ptr_bl - y + px, ptr_br + y + px, color3); -// __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + __BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } else { while (x++ < y) { @@ -725,8 +743,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto colorFill(ptr_bl - x + py, ptr_br + x + py, color); colorFill(ptr_bl - y + px, ptr_br + y + px, color); - // FIXME: maybe not needed at all? -// __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + // do not remove - messes up the drawing at lower resolutions + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 68c87c6f2c..be2a9df8b6 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -60,7 +60,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" -- cgit v1.2.3 From 23101e3dee59ee6f1e8604a06985a683b81acaf6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 13 Jul 2008 22:25:11 +0000 Subject: Bugfix: Triangle AA at low resolutions. svn-id: r33047 --- graphics/VectorRenderer.cpp | 42 ++++++++++++++++++++++++++++++++---------- gui/ThemeDefaultXML.cpp | 4 ++-- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 19a4f75058..b5722c2f64 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -33,6 +33,8 @@ #include "gui/ThemeRenderer.h" #include "graphics/VectorRenderer.h" +#define VECTOR_RENDERER_FAST_TRIANGLES + namespace Graphics { VectorRenderer *createRenderer(int mode) { @@ -391,6 +393,12 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { template void VectorRendererSpec:: drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { + // Awesome hack: the AA messes up the last pixel triangles if their width is even + // ...fix the width instead of fixing the AA :p + if (w % 2 == 0) { + w++; h++; + } + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; @@ -643,7 +651,8 @@ template void VectorRendererSpec:: drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { int pitch = Base::surfacePitch(); - int hstep = 0; + int hstep = 0, dy = size; + bool grad = (fill_m == kFillGradient); PixelType *ptr_right = 0, *ptr_left = 0; @@ -656,15 +665,28 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto pitch = -pitch; } - while (ptr_left != ptr_right) { - colorFill(ptr_left, ptr_right, color); - ptr_left += pitch; - ptr_right += pitch; - if (hstep++ % 3) { - ptr_left++; - ptr_right--; - } - } + if (fill_m == kFillDisabled) { + while (ptr_left < ptr_right) { + *ptr_left = color; + *ptr_right = color; + ptr_left += pitch; + ptr_right += pitch; + if (hstep++ % 2) { + ptr_left++; + ptr_right--; + } + } + } else { + while (ptr_left < ptr_right) { + colorFill(ptr_left, ptr_right, grad ? calcGradient(dy--, size) : color); + ptr_left += pitch; + ptr_right += pitch; + if (hstep++ % 2) { + ptr_left++; + ptr_right--; + } + } + } } /** ROUNDED SQUARE ALGORITHM **/ diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index be2a9df8b6..dc26920b48 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -70,12 +70,12 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" + "" "" "" "" -- cgit v1.2.3 From d3d34ef2959c6cf77dcf71689a747d6167a0873f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 14 Jul 2008 18:42:38 +0000 Subject: Popup widget, separator widget. svn-id: r33059 --- gui/ThemeDefaultXML.cpp | 14 +++++++++++++- gui/ThemeRenderer.cpp | 15 ++++++++++++--- gui/ThemeRenderer.h | 4 +++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index dc26920b48..ace3debfc2 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -50,9 +50,21 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" + "" + "" + + "" + "" + "" + "" + "" + + + "" "" "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 5f4c43dc79..15d8b7d67b 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -65,7 +65,9 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "scrollbar_base", "scrollbar_handle", - "popup", + "popup_idle", + "popup_hover", + "caret", "separator" }; @@ -390,8 +392,15 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String if (!ready()) return; - drawDD(kDDPopUp, r); - + DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle; + + drawDD(dd, r); + + if (!sel.empty()) { + Common::Rect text(r.left, r.top, r.right - 16, r.bottom); + drawDDText(dd, text, sel); + } + debugWidgetPosition("Popup Widget", r); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index aa4008c0e8..a9c597f60f 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -107,7 +107,9 @@ public: kDDScrollbarBase, kDDScrollbarHandle, - kDDPopUp, + kDDPopUpIdle, + kDDPopUpHover, + kDDCaret, kDDSeparator, kDrawDataMAX -- cgit v1.2.3 From b44b37d4ca4f0bbfe2b578dc72d84ba71286cc92 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 15 Jul 2008 10:50:31 +0000 Subject: More widgets. svn-id: r33071 --- graphics/VectorRenderer.h | 6 ++++++ gui/ThemeDefaultXML.cpp | 11 +++++++++-- gui/ThemeParser.cpp | 38 ++++++++++++++++++++------------------ gui/ThemeParser.h | 11 +++++++++++ gui/ThemeRenderer.cpp | 30 ++++++++++++++++++++++++++++-- gui/ThemeRenderer.h | 25 ++++++++++++++++++++++++- 6 files changed, 98 insertions(+), 23 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3af682953d..f1009ea2de 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -489,6 +489,8 @@ public: */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; + virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; protected: @@ -650,6 +652,10 @@ public: src_ptr += src_pitch; } } + + virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) { + return RGBToColor(r, g, b); + } protected: diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index ace3debfc2..db01adb7c3 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -12,7 +12,7 @@ * 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. + * 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 @@ -41,7 +41,10 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" - "" + "" + "" + "" + "" "" "" @@ -54,6 +57,10 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" + "" + "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 398eab010a..fda291fb04 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -173,30 +173,32 @@ bool ThemeParser::parserCallback_text() { step.alignVertical = GUI::Theme::kTextAlignVBottom; else return parserError("Invalid value for text alignment."); + Common::String paletteColor = "text_default"; + int red, green, blue; + + if (tNode->name.contains("hover")) + paletteColor = "text_hover"; + + if (tNode->name.contains("disabled")) + paletteColor = "text_disabled"; + if (tNode->values.contains("color")) { - int red, green, blue; - if (parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue) == false || - red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) - return parserError("Error when parsing color value for text definition"); + if (_palette.contains(tNode->values["color"])) + getPaletteColor(tNode->values["color"], red, green, blue); + else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue)) + return parserError("Error when parsing color value for text definition"); - step.color.r = red; - step.color.g = green; - step.color.b = blue; - step.color.set = true; - } else if (_defaultStepLocal && _defaultStepLocal->fgColor.set) { - step.color.r = _defaultStepLocal->fgColor.r; - step.color.g = _defaultStepLocal->fgColor.g; - step.color.b = _defaultStepLocal->fgColor.b; - step.color.set = true; - } else if (_defaultStepGlobal && _defaultStepGlobal->fgColor.set) { - step.color.r = _defaultStepGlobal->fgColor.r; - step.color.g = _defaultStepGlobal->fgColor.g; - step.color.b = _defaultStepGlobal->fgColor.b; - step.color.set = true; + } else if (_palette.contains(paletteColor)) { + getPaletteColor(paletteColor, red, green, blue); } else { return parserError("Cannot assign color for text drawing."); } + + step.color.r = red; + step.color.g = green; + step.color.b = blue; + step.color.set = true; _theme->addTextStep(parentNode->values["id"], step); return true; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 778158bff0..1e365a9433 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -316,6 +316,17 @@ class ThemeParser : public XMLParser { 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; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 15d8b7d67b..0b3fbe1064 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -69,7 +69,8 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "popup_hover", "caret", - "separator" + "separator", + "default_text" }; ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : @@ -234,7 +235,20 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { // draw the cached widget to the cache surface } } + + int r, g, b; + +#define __LOAD_COLOR(id, name) { \ + if (parser()->getPaletteColor(name, r, g, b))\ + _textColors[id] = _vectorRenderer->buildColor(r, g, b); \ +} + + __LOAD_COLOR(kTextColorDefault, "text_default"); + __LOAD_COLOR(kTextColorHover, "text_hover"); + __LOAD_COLOR(kTextColorDisabled, "text_disabled"); +#undef __LOAD_COLOR + _themeOk = true; return true; } @@ -360,6 +374,9 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { if (!ready()) return; + + drawDD(kDDScrollbarBase, r); + debugWidgetPosition("SCB", r); } @@ -399,7 +416,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String if (!sel.empty()) { Common::Rect text(r.left, r.top, r.right - 16, r.bottom); drawDDText(dd, text, sel); - } + } debugWidgetPosition("Popup Widget", r); } @@ -443,6 +460,15 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, debugWidgetPosition("Tab widget", r); } +void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { + if (!_initOk) + return; + + getFont(font)->drawString(_screen, str, r.left, r.top, r.width(), getTextColor(state), convertAligment(align), deltax, useEllipsis); + addDirtyRect(r); +} + + void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { // _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); // _screen->hLine(r.left, r.top, r.right, 0xFFFF); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index a9c597f60f..ba6cf633b0 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -112,8 +112,17 @@ public: kDDCaret, kDDSeparator, + kDDDefaultText, kDrawDataMAX }; + + enum TextColor { + kTextColorDefault, + kTextColorHover, + kTextColorDisabled, + kTextColorInverted, + kTextColorMAX + }; ThemeRenderer(Common::String themeName, GraphicsMode mode); @@ -160,7 +169,7 @@ public: void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {} + void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { @@ -254,6 +263,19 @@ protected: int getTabPadding() const { return 3; } + + uint32 getTextColor(WidgetStateInfo state) { + switch (state) { + case kStateDisabled: + return _textColors[kTextColorDisabled]; + + case kStateHighlight: + return _textColors[kTextColorHover]; + + default: + return _textColors[kTextColorDefault]; + } + } OSystem *_system; Graphics::VectorRenderer *_vectorRenderer; @@ -266,6 +288,7 @@ protected: Common::String _fontName; const Graphics::Font *_font; + uint32 _textColors[kTextColorMAX]; WidgetDrawData *_widgets[kDrawDataMAX]; Common::Array _dirtyScreen; -- cgit v1.2.3 From 47119ee8b136184c39cc6ce1a4b7248702f4c16f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 15 Jul 2008 18:53:22 +0000 Subject: Tab widget / tab drawing for the renderer. Improved text handling. svn-id: r33076 --- graphics/VectorRenderer.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++-- graphics/VectorRenderer.h | 25 ++++++++++++++++ gui/ThemeDefaultXML.cpp | 18 ++++++++++++ gui/ThemeParser.cpp | 5 ++-- gui/ThemeRenderer.cpp | 46 ++++++++++++++++++----------- gui/ThemeRenderer.h | 3 +- 6 files changed, 146 insertions(+), 22 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index b5722c2f64..a95564789e 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -352,7 +352,7 @@ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0 || r > 128 || (r << 1) > w || (r << 1) > h) + w <= 0 || h <= 0 || x < 0 || y < 0 || (r << 1) > w || (r << 1) > h) return; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset @@ -390,6 +390,25 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { } } +template +void VectorRendererSpec:: +drawTab(int x, int y, int r, int w, int h) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0 || (r << 1) > w || (r << 1) > h) + return; + + switch (Base::_fillMode) { + case kFillDisabled: + return; + + case kFillGradient: + case kFillForeground: + case kFillBackground: + drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + break; + } +} + template void VectorRendererSpec:: drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { @@ -421,7 +440,7 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { #ifdef VECTOR_RENDERER_FAST_TRIANGLES if (w == h) drawTriangleFast(x, y, w, (orient == kTriangleDown), color, Base::_fillMode); - else + else #endif drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); break; @@ -445,6 +464,54 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { /******************************************************************** * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec ********************************************************************/ +/** TAB ALGORITHM - NON AA */ +template +void VectorRendererSpec:: +drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int real_radius = r; + int short_h = h - (r) + 2; + int long_h = h; + + __BE_RESET(); + PixelType color1, color2; + + if (fill_m == kFillForeground || fill_m == kFillBackground) + color1 = color2 = color; + + while (x++ < y) { + __BE_ALGORITHM(); + + if (fill_m == kFillGradient) { + color1 = calcGradient(real_radius - x, long_h); + color2 = calcGradient(real_radius - y, long_h); + } + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); + + *(ptr_tr + (y) - (px)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px)) = color; + } + + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kFillGradient) + color = calcGradient(real_radius++, long_h); + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } +} + /** SQUARE ALGORITHM **/ template void VectorRendererSpec:: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index f1009ea2de..60cc20ac5a 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -192,6 +192,19 @@ public: * @param bevel Amount of bevel. Must be positive. */ virtual void drawBeveledSquare(int x, int y, int w, int h, int bevel) = 0; + + /** + * Draws a tab-like shape, specially thought for the Tab widget. + * If a radius is given, the tab will have rounded corners. Otherwise, + * the tab will be squared. + * + * @param x Horizontal (X) coordinate for the tab + * @param y Vertical (Y) coordinate for the tab + * @param w Width of the tab + * @param h Height of the tab + * @param r Radius of the corners of the tab (0 for squared tabs). + */ + virtual void drawTab(int x, int y, int r, int w, int h) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -460,6 +473,12 @@ public: stepGetPositions(step, area, x, y, w, h); drawBeveledSquare(x, y, w, h, step.extraData); } + + void drawCallback_TAB(const Common::Rect &area, const DrawStep &step) { + uint16 x, y, w, h; + stepGetPositions(step, area, x, y, w, h); + drawTab(x, y, stepGetRadius(step, area), w, h); + } void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {} @@ -553,6 +572,11 @@ public: * @see VectorRenderer::drawTriangle() */ void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); + + /** + * @see VectorRenderer::drawTab() + */ + void drawTab(int x, int y, int r, int w, int h); void drawBeveledSquare(int x, int y, int w, int h, int bevel) { drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); @@ -739,6 +763,7 @@ protected: virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); virtual void drawTriangleFast(int x, int y, int size, bool inverted, PixelType color, FillMode fill_m); virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color); + virtual void drawTabAlg(int x, int y, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m); /** * SHADOW DRAWING ALGORITHMS diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index db01adb7c3..0561f4b8d1 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -61,6 +61,24 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + "" + + "" + "" + "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index fda291fb04..014ed1fce9 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -57,6 +57,7 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _drawFunctions["line"] = &Graphics::VectorRenderer::drawCallback_LINE; _drawFunctions["triangle"] = &Graphics::VectorRenderer::drawCallback_TRIANGLE; _drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; + _drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB; _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; _defaultStepGlobal = defaultDrawStep(); @@ -199,7 +200,7 @@ bool ThemeParser::parserCallback_text() { step.color.g = green; step.color.b = blue; step.color.set = true; - + _theme->addTextStep(parentNode->values["id"], step); return true; } @@ -407,7 +408,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst assert(stepNode->values.contains("func")); Common::String functionName = stepNode->values["func"]; - if (functionName == "roundedsq" || functionName == "circle") { + if (functionName == "roundedsq" || functionName == "circle" || functionName == "tab") { if (stepNode->values.contains("radius") && stepNode->values["radius"] == "auto") { drawstep->radius = 0xFF; } else { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 0b3fbe1064..7995c34a40 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -60,7 +60,8 @@ const char *ThemeRenderer::kDrawDataStrings[] = { "checkbox_enabled", "checkbox_disabled", - "tab", + "tab_active", + "tab_inactive", "scrollbar_base", "scrollbar_handle", @@ -322,7 +323,6 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, drawDDText(dd, r, str); addDirtyRect(r); - debugWidgetPosition("BTN", r); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -331,8 +331,6 @@ void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo sta drawDD(kDDSeparator, r); addDirtyRect(r); - - debugWidgetPosition("Separator", r); } void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { @@ -353,7 +351,6 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); addDirtyRect(r); - debugWidgetPosition("Checkbox", r); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -368,7 +365,6 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo drawDD(kDDSliderFull, r2); addDirtyRect(r); - debugWidgetPosition("Slider", r); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { @@ -376,9 +372,9 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider return; drawDD(kDDScrollbarBase, r); + // TODO: Need to find a scrollbar in the GUI for testing... :p - - debugWidgetPosition("SCB", r); + addDirtyRect(r); } void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { @@ -395,7 +391,7 @@ void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, Wi drawDD(kDDDefaultBackground, r); } - debugWidgetPosition("Background", r); + addDirtyRect(r); } void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { @@ -403,6 +399,7 @@ void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo return; debugWidgetPosition("Caret", r); + addDirtyRect(r); } void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { @@ -418,7 +415,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String drawDDText(dd, text, sel); } - debugWidgetPosition("Popup Widget", r); + addDirtyRect(r); } void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { @@ -450,14 +447,29 @@ void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, Wi break; } - debugWidgetPosition("Widget Background", r); + addDirtyRect(r); } void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { if (!ready()) return; + + const int tabOffset = 1; + + for (int i = 0; i < (int)tabs.size(); ++i) { + if (i == active) + continue; - debugWidgetPosition("Tab widget", r); + Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + drawDD(kDDTabInactive, tabRect); + drawDDText(kDDTabInactive, tabRect, tabs[i]); + } + + if (active >= 0) { + Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + drawDD(kDDTabActive, tabRect); + drawDDText(kDDTabActive, tabRect, tabs[active]); + } } void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { @@ -470,11 +482,11 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { - // _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); - // _screen->hLine(r.left, r.top, r.right, 0xFFFF); - // _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); - // _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); - // _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); + _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); + _screen->hLine(r.left, r.top, r.right, 0xFFFF); + _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); + _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); + _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); } void ThemeRenderer::updateScreen() { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index ba6cf633b0..3addda17a7 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -102,7 +102,8 @@ public: kDDCheckboxEnabled, kDDCheckboxDisabled, - kDDTab, + kDDTabActive, + kDDTabInactive, kDDScrollbarBase, kDDScrollbarHandle, -- cgit v1.2.3 From 14c8d5d6c3d70cfa4f3229e3cd7c76771f566f9c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 16 Jul 2008 10:48:14 +0000 Subject: Stroking on tab widgets. Basic support for backcaching. svn-id: r33084 --- graphics/VectorRenderer.cpp | 93 +++++++++++++++++++++++++++++++++------------ gui/ThemeDefaultXML.cpp | 2 +- gui/ThemeRenderer.cpp | 14 +++++-- gui/ThemeRenderer.h | 14 ++++++- 4 files changed, 92 insertions(+), 31 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index a95564789e..aa0fad36c8 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -402,8 +402,13 @@ drawTab(int x, int y, int r, int w, int h) { return; case kFillGradient: - case kFillForeground: case kFillBackground: + drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + if (Base::_strokeWidth) + drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled); + break; + + case kFillForeground: drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); break; } @@ -471,44 +476,82 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); + int sw = 0, sp = 0, hp = 0; PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); int real_radius = r; - int short_h = h - (r) + 2; + int short_h = h - r + 2; int long_h = h; - - __BE_RESET(); PixelType color1, color2; if (fill_m == kFillForeground || fill_m == kFillBackground) color1 = color2 = color; - - while (x++ < y) { - __BE_ALGORITHM(); - if (fill_m == kFillGradient) { - color1 = calcGradient(real_radius - x, long_h); - color2 = calcGradient(real_radius - y, long_h); + if (fill_m == kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += pitch; + + __BE_RESET(); + r--; + + while (x++ < y) { + __BE_ALGORITHM(); + *(ptr_tr + (y) - (px)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px)) = color; + + if (Base::_strokeWidth > 1) { + *(ptr_tr + (y) - (px)) = color; + *(ptr_tr + (x - 1) - (py)) = color; + *(ptr_tl - (x - 1) - (py)) = color; + *(ptr_tl - (y) - (px)) = color; + *(ptr_tr + (y) - (px - pitch)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px - pitch)) = color; + } + } } + + ptr_fill += pitch * real_radius; + while (short_h--) { + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } else { + __BE_RESET(); - colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); - - *(ptr_tr + (y) - (px)) = color; - *(ptr_tr + (x) - (py)) = color; - *(ptr_tl - (x) - (py)) = color; - *(ptr_tl - (y) - (px)) = color; - } - - ptr_fill += pitch * r; - while (short_h--) { - if (fill_m == kFillGradient) - color = calcGradient(real_radius++, long_h); - colorFill(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; + while (x++ < y) { + __BE_ALGORITHM(); + + if (fill_m == kFillGradient) { + color1 = calcGradient(real_radius - x, long_h); + color2 = calcGradient(real_radius - y, long_h); + } + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); + + *(ptr_tr + (y) - (px)) = color1; + *(ptr_tr + (x) - (py)) = color2; + *(ptr_tl - (x) - (py)) = color2; + *(ptr_tl - (y) - (px)) = color1; + } + + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kFillGradient) + color = calcGradient(real_radius++, long_h); + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } } } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 0561f4b8d1..bbd18fce5c 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -63,7 +63,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 7995c34a40..4b56eba4a2 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -76,7 +76,7 @@ const char *ThemeRenderer::kDrawDataStrings[] = { ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false) { + _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false) { _system = g_system; _parser = new ThemeParser(this); @@ -153,9 +153,15 @@ void ThemeRenderer::disable() { } template -void ThemeRenderer::screenInit() { +void ThemeRenderer::screenInit(bool backBuffer) { freeScreen(); - + freeBackbuffer(); + + if (backBuffer) { + _backBuffer = new Surface; + _backBuffer->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); + } + _screen = new Surface; _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); _system->clearOverlay(); @@ -166,7 +172,7 @@ void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { case kGfxStandard16bit: case kGfxAntialias16bit: _bytesPerPixel = sizeof(uint16); - screenInit(); + screenInit(kEnableBackCaching); break; default: diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 3addda17a7..e7e320d048 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -73,6 +73,9 @@ class ThemeRenderer : public Theme { /** Constant value to expand dirty rectangles, to make sure they are fully copied */ static const int kDirtyRectangleThreshold = 2; + + /** Sets whether backcaching is enabled */ + static const bool kEnableBackCaching = true; public: enum GraphicsMode { @@ -204,7 +207,7 @@ public: void setGraphicsMode(GraphicsMode mode); protected: - template void screenInit(); + template void screenInit(bool backBuffer); bool loadThemeXML(Common::String themeName); bool loadDefaultXML(); @@ -228,6 +231,14 @@ protected: delete _vectorRenderer; _vectorRenderer = 0; } + + void freeBackbuffer() { + if (_backBuffer != 0) { + _backBuffer->free(); + delete _backBuffer; + _backBuffer = 0; + } + } void freeScreen() { if (_screen != 0) { @@ -283,6 +294,7 @@ protected: GUI::ThemeParser *_parser; Graphics::Surface *_screen; + Graphics::Surface *_backBuffer; int _bytesPerPixel; GraphicsMode _graphicsMode; -- cgit v1.2.3 From 6214815e6eff5b91887e5e1dd4d6463c2000f024 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Jul 2008 08:36:16 +0000 Subject: Finished tabs drawing. Added support for dynamic parameters in the Vector Renderer. svn-id: r33088 --- graphics/VectorRenderer.cpp | 36 ++++++++++++++++++++++++++---------- graphics/VectorRenderer.h | 7 ++++--- gui/ThemeDefaultXML.cpp | 10 +++++----- gui/ThemeRenderer.cpp | 8 +++++--- gui/ThemeRenderer.h | 2 +- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index aa0fad36c8..a8915eb0a6 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -53,7 +53,7 @@ VectorRenderer *createRenderer(int mode) { /******************************************************************** * DRAWSTEP handling functions ********************************************************************/ -void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { +void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra) { if (step.bgColor.set) setBgColor(step.bgColor.r, step.bgColor.g, step.bgColor.b); @@ -69,8 +69,10 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step) { setGradientFactor(step.factor); setStrokeWidth(step.stroke); setFillMode((FillMode)step.fillMode); + + _dynamicData = extra; - (this->*(step.drawingCall))(area, step); + (this->*(step.drawingCall))(area, step); } void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step) { @@ -405,7 +407,7 @@ drawTab(int x, int y, int r, int w, int h) { case kFillBackground: drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); if (Base::_strokeWidth) - drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled); + drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); break; case kFillForeground: @@ -472,7 +474,7 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { /** TAB ALGORITHM - NON AA */ template void VectorRendererSpec:: -drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m) { +drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) { int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); @@ -507,10 +509,6 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: *(ptr_tl - (y) - (px)) = color; if (Base::_strokeWidth > 1) { - *(ptr_tr + (y) - (px)) = color; - *(ptr_tr + (x - 1) - (py)) = color; - *(ptr_tl - (x - 1) - (py)) = color; - *(ptr_tl - (y) - (px)) = color; *(ptr_tr + (y) - (px - pitch)) = color; *(ptr_tr + (x) - (py)) = color; *(ptr_tl - (x) - (py)) = color; @@ -521,10 +519,28 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: ptr_fill += pitch * real_radius; while (short_h--) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); - colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth - 1, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 2, ptr_fill + w, color); ptr_fill += pitch; } + + if (baseLeft) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h); + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill - baseLeft, ptr_fill, color); + ptr_fill += pitch; + } + } + + if (baseRight) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h); + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill, ptr_fill + baseRight, color); + ptr_fill += pitch; + } + } } else { __BE_RESET(); diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 60cc20ac5a..e5fedd8ef5 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -78,7 +78,7 @@ struct DrawStep { uint8 shadow, stroke, factor, radius; /** Misc options... */ uint8 fillMode; /** active fill mode */ - uint8 extraData; /** Generic parameter for extra options (orientation/bevel) */ + uint32 extraData; /** Generic parameter for extra options (orientation/bevel) */ uint32 scale; /** scale of all the coordinates in FIXED POINT with 16 bits mantissa */ @@ -489,7 +489,7 @@ public: * @param area Zone to paint on * @param step Pointer to a DrawStep struct. */ - virtual void drawStep(const Common::Rect &area, const DrawStep &step); + virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0); virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step); /** @@ -519,6 +519,7 @@ protected: int _shadowOffset; /** offset for drawn shadows */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ + uint32 _dynamicData; /** Dynamic data from the GUI Theme that modifies the drawing of the current shape */ int _gradientFactor; /** Multiplication factor of the active gradient */ int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */ @@ -763,7 +764,7 @@ protected: virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); virtual void drawTriangleFast(int x, int y, int size, bool inverted, PixelType color, FillMode fill_m); virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color); - virtual void drawTabAlg(int x, int y, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m); + virtual void drawTabAlg(int x, int y, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft = 0, int baseRight = 0); /** * SHADOW DRAWING ALGORITHMS diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index bbd18fce5c..8c8f46d2ec 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -62,13 +62,13 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" - "" + "" + "" "" "" - "" - "" + "" + "" "" "" @@ -93,7 +93,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 4b56eba4a2..7b64baba11 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -290,7 +290,7 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); } -void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { +void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData) { if (_widgets[type] == 0) return; @@ -299,7 +299,7 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r) { } else { for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); step != _widgets[type]->_steps.end(); ++step) - _vectorRenderer->drawStep(r, *step); + _vectorRenderer->drawStep(r, *step, dynamicData); } } @@ -473,7 +473,9 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, if (active >= 0) { Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - drawDD(kDDTabActive, tabRect); + const uint16 tabLeft = active * (tabWidth + tabOffset); + const uint16 tabRight = r.right - tabRect.right; + drawDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); drawDDText(kDDTabActive, tabRect, tabs[active]); } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index e7e320d048..a5fccd8163 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -261,7 +261,7 @@ protected: bool isWidgetCached(DrawData type, const Common::Rect &r); void drawCached(DrawData type, const Common::Rect &r); - inline void drawDD(DrawData type, const Common::Rect &r); + inline void drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData = 0); inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text); inline void debugWidgetPosition(const char *name, const Common::Rect &r); -- cgit v1.2.3 From 4645e706a8c62fb291efb987dca9fa82394139ee Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 17 Jul 2008 21:58:43 +0000 Subject: Rendering pipeline (almost) fixed. This time for real. svn-id: r33092 --- graphics/VectorRenderer.cpp | 9 +++-- gui/ThemeRenderer.cpp | 81 ++++++++++++++++++++++++++++++++++----------- gui/ThemeRenderer.h | 29 ++++++++++++---- gui/dialog.cpp | 6 +++- gui/newgui.cpp | 69 ++++++++++++++++++++++---------------- gui/newgui.h | 11 +++++- gui/theme.h | 14 ++++++++ 7 files changed, 159 insertions(+), 60 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index a8915eb0a6..f2ce0e26b8 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -487,11 +487,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: int real_radius = r; int short_h = h - r + 2; int long_h = h; - PixelType color1, color2; - - if (fill_m == kFillForeground || fill_m == kFillBackground) - color1 = color2 = color; - + if (fill_m == kFillDisabled) { while (sw++ < Base::_strokeWidth) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); @@ -543,6 +539,9 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } } else { __BE_RESET(); + + PixelType color1, color2; + color1 = color2 = color; while (x++ < y) { __BE_ALGORITHM(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 7b64baba11..9b3d115576 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -76,7 +76,8 @@ const char *ThemeRenderer::kDrawDataStrings[] = { ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), - _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false) { + _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), + _themeOk(false), _enabled(false), _dialogCount(0), _cachedDialog(0) { _system = g_system; _parser = new ThemeParser(this); @@ -238,8 +239,11 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str()); return false; #endif - } else if (_widgets[i]->_cached) { - // draw the cached widget to the cache surface + } else { + calcBackgroundOffset((DrawData)i); + + // TODO: draw the cached widget to the cache surface + if (_widgets[i]->_cached) {} } } @@ -293,6 +297,14 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData) { if (_widgets[type] == 0) return; + + Common::Rect extendedRect = r; + extendedRect.grow(kDirtyRectangleThreshold); + extendedRect.right += _widgets[type]->_backgroundOffset; + extendedRect.bottom += _widgets[type]->_backgroundOffset; + + restoreBackground(extendedRect); + addDirtyRect(extendedRect); if (isWidgetCached(type, r)) { drawCached(type, r); @@ -312,6 +324,33 @@ void ThemeRenderer::drawDDText(DrawData type, const Common::Rect &r, const Commo } } +void ThemeRenderer::calcBackgroundOffset(DrawData type) { + uint maxShadow = 0; + for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); + step != _widgets[type]->_steps.end(); ++step) { + if (((*step).autoWidth || (*step).autoHeight) && (*step).shadow > maxShadow) + maxShadow = (*step).shadow; + } + + _widgets[type]->_backgroundOffset = maxShadow; +} + +void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { +/* const OverlayColor *src = (const OverlayColor*)_backBuffer->getBasePtr(r.left, r.top); + OverlayColor *dst = (OverlayColor*)_screen->getBasePtr(r.left, r.top); + + int h = r.height(); + int w = r.width(); + while (h--) { + memcpy(dst, src, w * sizeof(OverlayColor)); + src += _backBuffer->w; + dst += _screen->w; + }*/ + + debugWidgetPosition("", r); + printf(" BG_RESTORE "); +} + void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { if (!ready()) return; @@ -327,8 +366,6 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, drawDD(dd, r); drawDDText(dd, r, str); - - addDirtyRect(r); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -336,7 +373,6 @@ void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo sta return; drawDD(kDDSeparator, r); - addDirtyRect(r); } void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { @@ -355,8 +391,6 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st r2.right = r.right; drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); - - addDirtyRect(r); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -369,8 +403,6 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo r2.setWidth(MIN((int16)width, r.width())); drawDD(kDDSliderFull, r2); - - addDirtyRect(r); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { @@ -379,8 +411,6 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider drawDD(kDDScrollbarBase, r); // TODO: Need to find a scrollbar in the GUI for testing... :p - - addDirtyRect(r); } void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { @@ -396,8 +426,6 @@ void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, Wi } else { drawDD(kDDDefaultBackground, r); } - - addDirtyRect(r); } void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { @@ -405,7 +433,6 @@ void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo return; debugWidgetPosition("Caret", r); - addDirtyRect(r); } void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { @@ -420,8 +447,6 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String Common::Rect text(r.left, r.top, r.right - 16, r.bottom); drawDDText(dd, text, sel); } - - addDirtyRect(r); } void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { @@ -452,8 +477,6 @@ void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, Wi drawDD(kDDWidgetBackgroundDefault, r); break; } - - addDirtyRect(r); } void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { @@ -514,4 +537,24 @@ void ThemeRenderer::renderDirtyScreen() { _dirtyScreen.clear(); } +void ThemeRenderer::openDialog(bool top) { + if (_dialogCount++ == 0) + return; + + _cachedDialog = _dialogCount - 1; + memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); +} + +bool ThemeRenderer::closeDialog() { + assert(_dialogCount); + + _dialogCount--; + + if (_dialogCount != _cachedDialog) + return false; + + memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); + return true; +} + } // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index a5fccd8163..11728f8e6e 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -42,13 +42,23 @@ namespace GUI { struct WidgetDrawData; struct WidgetDrawData { + /** List of all the steps needed to draw this widget */ Common::List _steps; + + /** Single step that defines the text shown inside the widget */ Graphics::TextStep _textStep; bool _hasText; + /** Extra space that the widget occupies when it's drawn. + E.g. when taking into account rounded corners, drop shadows, etc + Used when restoring the widget background */ + uint16 _backgroundOffset; + + /** Sets whether the widget is cached beforehand. */ bool _cached; + + /** Texture where the cached widget is stored. */ Graphics::Surface *_surfaceCache; - uint32 _cachedW, _cachedH; ~WidgetDrawData() { _steps.clear(); @@ -145,14 +155,18 @@ public: void refresh() {} void enable(); void disable(); - void openDialog() {} - void closeAllDialogs() {} + + void closeAllDialogs() { + _dialogCount = 0; + _cachedDialog = 0; + } void updateScreen(); //{} void resetDrawArea() {} - void openDialog(bool top) {} + void openDialog(bool top);// {} + bool closeDialog();// {} /** Font management */ const Graphics::Font *getFont(FontStyle font) const { return _font; } @@ -177,7 +191,7 @@ public: void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { - r.grow(kDirtyRectangleThreshold); +// r.grow(kDirtyRectangleThreshold); _dirtyScreen.push_back(r); return true; } @@ -260,13 +274,14 @@ protected: bool isWidgetCached(DrawData type, const Common::Rect &r); void drawCached(DrawData type, const Common::Rect &r); + void calcBackgroundOffset(DrawData type); inline void drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData = 0); inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text); inline void debugWidgetPosition(const char *name, const Common::Rect &r); // TODO - void restoreBackground(Common::Rect r, bool special = false) {} + void restoreBackground(Common::Rect r, bool special = false); int getTabSpacing() const { return 0; @@ -295,6 +310,8 @@ protected: Graphics::Surface *_screen; Graphics::Surface *_backBuffer; + uint32 _dialogCount; + uint32 _cachedDialog; int _bytesPerPixel; GraphicsMode _graphicsMode; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index ef396301be..0594941d65 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -132,7 +132,11 @@ void Dialog::releaseFocus() { } void Dialog::draw() { - g_gui._needRedraw = true; + //TANOKU - FIXME when is this enabled? what does this do? + // Update: called on tab drawing, mainly... + // we can pass this as open a new dialog or something +// g_gui._needRedraw = true; + g_gui._redrawStatus = GUI::NewGui::kRedrawTopDialog; } void Dialog::drawDialog() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 4d0b3905b9..f3734c6ee0 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -81,7 +81,7 @@ void GuiObject::reflowLayout() { } // Constructor -NewGui::NewGui() : _needRedraw(false), +NewGui::NewGui() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { _theme = 0; _useStdCursor = false; @@ -187,29 +187,48 @@ bool NewGui::loadNewTheme(const Common::String &style) { void NewGui::redraw() { int i; - // Restore the overlay to its initial state, then draw all dialogs. - // This is necessary to get the blending right. - _theme->clearAll(); + if (_redrawStatus == kRedrawDisabled) + return; - _theme->closeAllDialogs(); - //for (i = 0; i < _dialogStack.size(); ++i) - // _theme->closeDialog(); + switch (_redrawStatus) { + case kRedrawCloseDialog: + printf("Dialog closed!\n"); + if (_theme->closeDialog()) + break; - for (i = 0; i < _dialogStack.size(); i++) { - // Special treatment when topmost dialog has dimsInactive() set to false - // This is the case for PopUpWidget which should not dim a dialog - // which it belongs to - if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive()) - _theme->openDialog(true); - else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive()) - _theme->openDialog(false); - else + case kRedrawFull: + _theme->clearAll(); + _theme->closeAllDialogs(); + + for (i = 0; i < _dialogStack.size(); i++) { + if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive()) + _theme->openDialog(true); + else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive()) + _theme->openDialog(false); + else + _theme->openDialog(true); + + _dialogStack[i]->drawDialog(); + } + break; + + case kRedrawTopDialog: + _dialogStack.top()->drawDialog(); + printf("Top dialog redraw!\n"); + break; + + case kRedrawOpenDialog: _theme->openDialog(true); + _dialogStack.top()->drawDialog(); + printf("Dialog opened!\n"); + break; - _dialogStack[i]->drawDialog(); + default: + return; } _theme->updateScreen(); + _redrawStatus = kRedrawDisabled; } Dialog *NewGui::getTopDialog() const { @@ -240,10 +259,7 @@ void NewGui::runLoop() { Common::EventManager *eventMan = _system->getEventManager(); while (!_dialogStack.empty() && activeDialog == getTopDialog()) { - if (_needRedraw) { - redraw(); - _needRedraw = false; - } + redraw(); // Don't "tickle" the dialog until the theme has had a chance // to re-allocate buffers in case of a scaler change. @@ -274,6 +290,7 @@ void NewGui::runLoop() { _theme->refresh(); _themeChange = false; + _redrawStatus = kRedrawFull; redraw(); } @@ -330,11 +347,6 @@ void NewGui::runLoop() { _system->delayMillis(10); } - // HACK: since we reopen all dialogs anyway on redraw - // we for now use Theme::closeAllDialogs here, until - // we properly add (and implement) Theme::closeDialog - _theme->closeAllDialogs(); - if (didSaveState) { _theme->disable(); restoreState(); @@ -366,7 +378,7 @@ void NewGui::restoreState() { void NewGui::openDialog(Dialog *dialog) { _dialogStack.push(dialog); - _needRedraw = true; + _redrawStatus = kRedrawOpenDialog; // We reflow the dialog just before opening it. If the screen changed // since the last time we looked, also refresh the loaded theme, @@ -393,7 +405,7 @@ void NewGui::closeTopDialog() { // Remove the dialog from the stack _dialogStack.pop(); - _needRedraw = true; + _redrawStatus = kRedrawCloseDialog; } void NewGui::setupCursor() { @@ -451,6 +463,7 @@ void NewGui::screenChange() { // We need to redraw immediately. Otherwise // some other event may cause a widget to be // redrawn before redraw() has been called. + _redrawStatus = kRedrawFull; redraw(); } diff --git a/gui/newgui.h b/gui/newgui.h index 4cf082c877..ae58b2efe8 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -90,12 +90,21 @@ public: void screenChange(); + enum RedrawStatus { + kRedrawDisabled = 0, + kRedrawOpenDialog, + kRedrawCloseDialog, + kRedrawTopDialog, + kRedrawFull + }; + protected: OSystem *_system; Theme *_theme; - bool _needRedraw; +// bool _needRedraw; + RedrawStatus _redrawStatus; int _lastScreenChangeID; DialogStack _dialogStack; diff --git a/gui/theme.h b/gui/theme.h index e9ce8bb01d..91f59d961c 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -238,6 +238,20 @@ public: */ virtual void closeAllDialogs() = 0; + /** + * Closes the topmost dialog, and redraws the screen + * accordingly. + * + * TODO: Make this purely virtual by making ThemeClassic + * and ThemeModern implement it too. + * + * @returns True if the dialog was sucessfully closed. + * If we weren't able to restore the screen after closing + * the dialog, we return false, which means we need to redraw + * the dialog stack from scratch. + */ + virtual bool closeDialog() { return false; } + /** * Clear the complete GUI screen. */ -- cgit v1.2.3 From cf3832fccefc00bcac4bc4d355568a66479fc926 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 18 Jul 2008 16:44:42 +0000 Subject: Background restoration in rendering pipeline. WIP. svn-id: r33097 --- gui/ThemeRenderer.cpp | 47 +++++++++++++++++++++++++---------------------- gui/ThemeRenderer.h | 19 +++++++++---------- gui/newgui.cpp | 23 +++++++---------------- gui/theme.h | 1 + 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 9b3d115576..10736a033f 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -77,7 +77,7 @@ const char *ThemeRenderer::kDrawDataStrings[] = { ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), - _themeOk(false), _enabled(false), _dialogCount(0), _cachedDialog(0) { + _themeOk(false), _enabled(false), _buffering(false) { _system = g_system; _parser = new ThemeParser(this); @@ -214,9 +214,16 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; + _widgets[data_id]->_buffer = false; _widgets[data_id]->_surfaceCache = 0; _widgets[data_id]->_hasText = false; + // TODO: set this only when needed + // possibly add an option to the parser to set this + // on each drawdata... + if (data_id >= kDDMainDialogBackground && data_id <= kDDWidgetBackgroundSlider) + _widgets[data_id]->_buffer = true; + return true; } @@ -303,7 +310,11 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicD extendedRect.right += _widgets[type]->_backgroundOffset; extendedRect.bottom += _widgets[type]->_backgroundOffset; - restoreBackground(extendedRect); + if (_buffering && _widgets[type]->_buffer) + _vectorRenderer->setSurface(_backBuffer); + else + restoreBackground(extendedRect); + addDirtyRect(extendedRect); if (isWidgetCached(type, r)) { @@ -313,6 +324,11 @@ void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicD step != _widgets[type]->_steps.end(); ++step) _vectorRenderer->drawStep(r, *step, dynamicData); } + + if (_buffering && _widgets[type]->_buffer) { + _vectorRenderer->setSurface(_screen); + memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); + } } void ThemeRenderer::drawDDText(DrawData type, const Common::Rect &r, const Common::String &text) { @@ -336,7 +352,7 @@ void ThemeRenderer::calcBackgroundOffset(DrawData type) { } void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { -/* const OverlayColor *src = (const OverlayColor*)_backBuffer->getBasePtr(r.left, r.top); + const OverlayColor *src = (const OverlayColor*)_backBuffer->getBasePtr(r.left, r.top); OverlayColor *dst = (OverlayColor*)_screen->getBasePtr(r.left, r.top); int h = r.height(); @@ -345,10 +361,10 @@ void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { memcpy(dst, src, w * sizeof(OverlayColor)); src += _backBuffer->w; dst += _screen->w; - }*/ + } - debugWidgetPosition("", r); - printf(" BG_RESTORE "); +// debugWidgetPosition("", r); +// printf(" BG_RESTORE "); } void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { @@ -537,24 +553,11 @@ void ThemeRenderer::renderDirtyScreen() { _dirtyScreen.clear(); } -void ThemeRenderer::openDialog(bool top) { - if (_dialogCount++ == 0) - return; +void ThemeRenderer::openDialog(bool doBuffer) { + if (doBuffer) + _buffering = true; - _cachedDialog = _dialogCount - 1; memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); } -bool ThemeRenderer::closeDialog() { - assert(_dialogCount); - - _dialogCount--; - - if (_dialogCount != _cachedDialog) - return false; - - memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); - return true; -} - } // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 11728f8e6e..347cbafcc9 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -56,6 +56,7 @@ struct WidgetDrawData { /** Sets whether the widget is cached beforehand. */ bool _cached; + bool _buffer; /** Texture where the cached widget is stored. */ Graphics::Surface *_surfaceCache; @@ -156,17 +157,12 @@ public: void enable(); void disable(); - void closeAllDialogs() { - _dialogCount = 0; - _cachedDialog = 0; - } + void closeAllDialogs() {} - - void updateScreen(); //{} + void updateScreen(); void resetDrawArea() {} - void openDialog(bool top);// {} - bool closeDialog();// {} + void openDialog(bool top); /** Font management */ const Graphics::Font *getFont(FontStyle font) const { return _font; } @@ -220,6 +216,10 @@ public: bool loadTheme(Common::String themeName); void setGraphicsMode(GraphicsMode mode); + void finishBuffering() { + _buffering = false; + } + protected: template void screenInit(bool backBuffer); @@ -310,8 +310,7 @@ protected: Graphics::Surface *_screen; Graphics::Surface *_backBuffer; - uint32 _dialogCount; - uint32 _cachedDialog; + bool _buffering; int _bytesPerPixel; GraphicsMode _graphicsMode; diff --git a/gui/newgui.cpp b/gui/newgui.cpp index f3734c6ee0..c4fafe7e22 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -192,37 +192,28 @@ void NewGui::redraw() { switch (_redrawStatus) { case kRedrawCloseDialog: - printf("Dialog closed!\n"); - if (_theme->closeDialog()) - break; - case kRedrawFull: _theme->clearAll(); _theme->closeAllDialogs(); for (i = 0; i < _dialogStack.size(); i++) { - if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive()) - _theme->openDialog(true); - else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive()) - _theme->openDialog(false); - else - _theme->openDialog(true); - + _theme->openDialog(true); _dialogStack[i]->drawDialog(); } break; - case kRedrawTopDialog: - _dialogStack.top()->drawDialog(); - printf("Top dialog redraw!\n"); - break; - case kRedrawOpenDialog: _theme->openDialog(true); _dialogStack.top()->drawDialog(); + _theme->finishBuffering(); printf("Dialog opened!\n"); break; + case kRedrawTopDialog: + _dialogStack.top()->drawDialog(); + printf("Top dialog redraw!\n"); + break; + default: return; } diff --git a/gui/theme.h b/gui/theme.h index 91f59d961c..a55f04b115 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -251,6 +251,7 @@ public: * the dialog stack from scratch. */ virtual bool closeDialog() { return false; } + virtual void finishBuffering() {} /** * Clear the complete GUI screen. -- cgit v1.2.3 From b5081a02ec1d72e14ced116246545e1210b8b86f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 19 Jul 2008 15:49:08 +0000 Subject: Changed drawdata names to a struct. Fixed text drawing. svn-id: r33112 --- gui/ThemeRenderer.cpp | 56 ++++++++++++++++++++++++++------------------------- gui/ThemeRenderer.h | 15 ++++++++++---- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 10736a033f..abc05e63ab 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -39,41 +39,42 @@ namespace GUI { using namespace Graphics; -const char *ThemeRenderer::kDrawDataStrings[] = { - "mainmenu_bg", - "special_bg", - "plain_bg", - "default_bg", - - "widget_default", - "widget_small", - "widget_textedit", - "widget_slider", +const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawData[] = { + {kDDMainDialogBackground, "mainmenu_bg", true}, + {kDDSpecialColorBackground, "special_bg", true}, + {kDDPlainColorBackground, "plain_bg", true}, + {kDDDefaultBackground, "default_bg", true}, - "button_idle", - "button_hover", - "button_disabled", + {kDDWidgetBackgroundDefault, "widget_default", true}, + {kDDWidgetBackgroundSmall, "widget_small", true}, + {kDDWidgetBackgroundEditText, "widget_textedit", true}, + {kDDWidgetBackgroundSlider, "widget_slider", true}, - "slider_full", - "slider_empty", + {kDDButtonIdle, "button_idle", true}, + {kDDButtonHover, "button_hover", false}, + {kDDButtonDisabled, "button_disabled", true}, - "checkbox_enabled", - "checkbox_disabled", + {kDDSliderFull,"slider_full", false}, + {kDDSliderEmpty, "slider_empty", true}, - "tab_active", - "tab_inactive", + {kDDCheckboxEnabled, "checkbox_enabled", false}, + {kDDCheckboxDisabled, "checkbox_disabled", true}, - "scrollbar_base", - "scrollbar_handle", + {kDDTabActive, "tab_active", false}, + {kDDTabInactive, "tab_inactive", true}, - "popup_idle", - "popup_hover", - - "caret", - "separator", - "default_text" + {kDDScrollbarBase, "scrollbar_base", true}, + {kDDScrollbarHandle, "scrollbar_handle", false}, + + {kDDPopUpIdle, "popup_idle", true}, + {kDDPopUpHover, "popup_hover", false}, + + {kDDCaret, "caret", false}, + {kDDSeparator, "separator", true}, + {kDDDefaultText, "default_text", false} }; + ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), @@ -523,6 +524,7 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W if (!_initOk) return; + restoreBackground(r); getFont(font)->drawString(_screen, str, r.left, r.top, r.width(), getTextColor(state), convertAligment(align), deltax, useEllipsis); addDirtyRect(r); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 347cbafcc9..e01d31e00f 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -40,6 +40,7 @@ namespace GUI { struct WidgetDrawData; +struct DrawDataInfo; struct WidgetDrawData { /** List of all the steps needed to draw this widget */ @@ -80,7 +81,6 @@ class ThemeRenderer : public Theme { friend class GUI::GuiObject; /** Strings representing each value in the DrawData enum */ - static const char *kDrawDataStrings[]; /** Constant value to expand dirty rectangles, to make sure they are fully copied */ static const int kDirtyRectangleThreshold = 2; @@ -138,7 +138,14 @@ public: kTextColorInverted, kTextColorMAX }; - + + struct DrawDataInfo { + DrawData id; + const char *name; + bool buffer; + }; + + static const DrawDataInfo kDrawData[]; ThemeRenderer(Common::String themeName, GraphicsMode mode); ~ThemeRenderer() { @@ -195,8 +202,8 @@ public: // custom stuff - tanoku DrawData getDrawDataId(Common::String &name) { for (int i = 0; i < kDrawDataMAX; ++i) - if (name.compareToIgnoreCase(kDrawDataStrings[i]) == 0) - return (DrawData)i; + if (name.compareToIgnoreCase(kDrawData[i].name) == 0) + return kDrawData[i].id; return (DrawData)-1; } -- cgit v1.2.3 From 9aa07d206e679179f939e9beb0d441eb0c1a1fcb Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 20 Jul 2008 21:47:28 +0000 Subject: Rendering pipeline. Broken WIP. svn-id: r33152 --- graphics/VectorRenderer.cpp | 8 +- graphics/VectorRenderer.h | 23 ++-- gui/ThemeDefaultXML.cpp | 17 ++- gui/ThemeParser.cpp | 73 ++++++++++--- gui/ThemeParser.h | 2 + gui/ThemeRenderer.cpp | 259 +++++++++++++++++++++++++++----------------- gui/ThemeRenderer.h | 45 ++++++-- gui/newgui.cpp | 15 +-- gui/theme.h | 1 + 9 files changed, 292 insertions(+), 151 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index f2ce0e26b8..70bcc1b2c3 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -65,7 +65,7 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui setGradientColors(step.gradColor1.r, step.gradColor1.g, step.gradColor1.b, step.gradColor2.r, step.gradColor2.g, step.gradColor2.b); - shadowEnable(step.shadow); + setShadowOffset(_disableShadows ? 0 : step.shadow); setGradientFactor(step.factor); setStrokeWidth(step.stroke); setFillMode((FillMode)step.fillMode); @@ -75,11 +75,13 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui (this->*(step.drawingCall))(area, step); } -void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step) { +void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH) { if (step.color.set) setFgColor(step.color.r, step.color.g, step.color.b); - drawString(step.font, text.c_str(), area, step.alignHorizontal, step.alignVertical); + drawString(step.font, text.c_str(), area, + !step.hasAlign ? alignH : step.alignHorizontal, + !step.hasAlign ? GUI::Theme::kTextAlignVTop : step.alignVertical); } /******************************************************************** diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index e5fedd8ef5..c7ba0676b3 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -48,6 +48,7 @@ struct TextStep { GUI::Theme::TextAlign alignHorizontal; GUI::Theme::TextAlignVertical alignVertical; + bool hasAlign; char *text; const Graphics::Font *font; }; @@ -105,7 +106,7 @@ VectorRenderer *createRenderer(int mode); class VectorRenderer { public: VectorRenderer() : _shadowOffset(0), _fillMode(kFillDisabled), - _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) { + _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1), _disableShadows(false) { } @@ -317,25 +318,15 @@ public: * Enables adding shadows to all drawn primitives. * Shadows are drawn automatically under the shapes. The given offset * controls their intensity and size (the higher the offset, the - * bigger the shadows). + * bigger the shadows). If the offset is 0, no shadows are drawn. * * @param offset Shadow offset. - * @see shadowDisable() */ - virtual void shadowEnable(int offset) { + virtual void setShadowOffset(int offset) { if (offset >= 0) _shadowOffset = offset; } - /** - * Disables adding shadows to all drawn primitives. - * - * @see shadowEnable() - */ - virtual void shadowDisable() { - _shadowOffset = 0; - } - /** * Sets the multiplication factor of the active gradient. * @@ -490,7 +481,7 @@ public: * @param step Pointer to a DrawStep struct. */ virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0); - virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step); + virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH = GUI::Theme::kTextAlignLeft); /** * Copies the current surface to the system overlay @@ -511,6 +502,9 @@ public: virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) = 0; virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; + + virtual void disableShadows() { _disableShadows = true; } + virtual void enableShadows() { _disableShadows = false; } protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -518,6 +512,7 @@ protected: FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ + bool _disableShadows; /** Disables temporarily shadow drawing for overlayed images. */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ uint32 _dynamicData; /** Dynamic data from the GUI Theme that modifies the drawing of the current shape */ diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 8c8f46d2ec..afb559f950 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -46,8 +46,14 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" + + "" + "" + "" + "" + "" - "" + "" "" "" @@ -71,7 +77,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" @@ -98,13 +104,18 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" "" "" + + "" + "" + "" + "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 014ed1fce9..c43da99ac1 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -47,8 +47,10 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _callbacks["color"] = &ThemeParser::parserCallback_color; _callbacks["render_info"] = &ThemeParser::parserCallback_renderInfo; _callbacks["layout_info"] = &ThemeParser::parserCallback_layoutInfo; - _callbacks["default"] = &ThemeParser::parserCallback_defaultSet; + _callbacks["defaults"] = &ThemeParser::parserCallback_defaultSet; _callbacks["text"] = &ThemeParser::parserCallback_text; + _callbacks["fonts"] = &ThemeParser::parserCallback_fonts; + _callbacks["font"] = &ThemeParser::parserCallback_font; _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; @@ -146,6 +148,60 @@ bool ThemeParser::parserCallback_defaultSet() { return parseDrawStep(defNode, step, false); } +bool ThemeParser::parserCallback_font() { + ParserNode *tNode = getActiveNode(); + ParserNode *parentNode = getParentNode(tNode); + + if (parentNode == 0 || parentNode->name != "fonts") + return parserError("Text Steps must be contained inside keys."); + + if (!tNode->values.contains("id")) + return parserError("Font definitions need a valid identifier."); + + if (!tNode->values.contains("type")) + return parserError("Font definitions need a valid typename."); + + // TODO: set typename on the drawstep. + + Graphics::TextStep step; + + if (tNode->values.contains("horizontal_align") || tNode->values.contains("vertical_align")) + return parserError("Font definitions cannot contain alignments."); + + int red, green, blue; + + if (tNode->values.contains("color")) { + + if (_palette.contains(tNode->values["color"])) + getPaletteColor(tNode->values["color"], red, green, blue); + else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue)) + return parserError("Error when parsing color value for font definition."); + + } else { + return parserError("Cannot assign color in font definition."); + } + + step.color.r = red; + step.color.g = green; + step.color.b = blue; + step.color.set = true; + step.hasAlign = false; + + if (!_theme->addTextStep(tNode->values["id"], step)) + return parserError("Error when loading Font in theme engine."); + + return true; +} + +bool ThemeParser::parserCallback_fonts() { + ParserNode *tNode = getActiveNode(); + + if (getParentNode(tNode) == 0 || getParentNode(tNode)->name != "render_info") + return parserError("Font definition keys must be contained inside a section."); + + return true; +} + bool ThemeParser::parserCallback_text() { ParserNode *tNode = getActiveNode(); ParserNode *parentNode = getParentNode(tNode); @@ -174,24 +230,15 @@ bool ThemeParser::parserCallback_text() { step.alignVertical = GUI::Theme::kTextAlignVBottom; else return parserError("Invalid value for text alignment."); - Common::String paletteColor = "text_default"; int red, green, blue; - if (tNode->name.contains("hover")) - paletteColor = "text_hover"; - - if (tNode->name.contains("disabled")) - paletteColor = "text_disabled"; - if (tNode->values.contains("color")) { if (_palette.contains(tNode->values["color"])) getPaletteColor(tNode->values["color"], red, green, blue); else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue)) - return parserError("Error when parsing color value for text definition"); + return parserError("Error when parsing color value for text definition"); - } else if (_palette.contains(paletteColor)) { - getPaletteColor(paletteColor, red, green, blue); } else { return parserError("Cannot assign color for text drawing."); } @@ -200,9 +247,9 @@ bool ThemeParser::parserCallback_text() { step.color.g = green; step.color.b = blue; step.color.set = true; + step.hasAlign = true; - _theme->addTextStep(parentNode->values["id"], step); - return true; + return _theme->addTextStep(parentNode->values["id"], step); } bool ThemeParser::parserCallback_renderInfo() { diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 1e365a9433..59ba188fc1 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -340,6 +340,8 @@ protected: bool parserCallback_layoutInfo(); bool parserCallback_defaultSet(); bool parserCallback_text(); + bool parserCallback_fonts(); + bool parserCallback_font(); void cleanup(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index abc05e63ab..6c31dcf7a0 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -40,38 +40,36 @@ namespace GUI { using namespace Graphics; const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawData[] = { - {kDDMainDialogBackground, "mainmenu_bg", true}, - {kDDSpecialColorBackground, "special_bg", true}, - {kDDPlainColorBackground, "plain_bg", true}, - {kDDDefaultBackground, "default_bg", true}, + {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, + {kDDSpecialColorBackground, "special_bg", true, kDDNone}, + {kDDPlainColorBackground, "plain_bg", true, kDDNone}, + {kDDDefaultBackground, "default_bg", true, kDDNone}, - {kDDWidgetBackgroundDefault, "widget_default", true}, - {kDDWidgetBackgroundSmall, "widget_small", true}, - {kDDWidgetBackgroundEditText, "widget_textedit", true}, - {kDDWidgetBackgroundSlider, "widget_slider", true}, + {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, + {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, + {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, + {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, - {kDDButtonIdle, "button_idle", true}, - {kDDButtonHover, "button_hover", false}, - {kDDButtonDisabled, "button_disabled", true}, + {kDDButtonIdle, "button_idle", true, kDDNone}, + {kDDButtonHover, "button_hover", false, kDDButtonIdle}, + {kDDButtonDisabled, "button_disabled", true, kDDNone}, - {kDDSliderFull,"slider_full", false}, - {kDDSliderEmpty, "slider_empty", true}, + {kDDSliderFull, "slider_full", false, kDDWidgetBackgroundSlider}, - {kDDCheckboxEnabled, "checkbox_enabled", false}, - {kDDCheckboxDisabled, "checkbox_disabled", true}, + {kDDCheckboxEnabled, "checkbox_enabled", false, kDDCheckboxDisabled}, + {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, - {kDDTabActive, "tab_active", false}, - {kDDTabInactive, "tab_inactive", true}, + {kDDTabActive, "tab_active", false, kDDTabInactive}, + {kDDTabInactive, "tab_inactive", true, kDDNone}, - {kDDScrollbarBase, "scrollbar_base", true}, - {kDDScrollbarHandle, "scrollbar_handle", false}, + {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, + {kDDScrollbarHandle, "scrollbar_handle", false, kDDScrollbarBase}, - {kDDPopUpIdle, "popup_idle", true}, - {kDDPopUpHover, "popup_hover", false}, + {kDDPopUpIdle, "popup_idle", true, kDDNone}, + {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, - {kDDCaret, "caret", false}, - {kDDSeparator, "separator", true}, - {kDDDefaultText, "default_text", false} + {kDDCaret, "caret", false, kDDNone}, + {kDDSeparator, "separator", true, kDDNone}, }; @@ -196,13 +194,23 @@ void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep s bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep step) { DrawData id = getDrawDataId(drawDataId); - assert(_widgets[id] != 0); - if (_widgets[id]->_hasText == true) - return false; - - _widgets[id]->_textStep = step; - _widgets[id]->_textStep.font = 0; - _widgets[id]->_hasText = true; + if (id != -1) { + assert(_widgets[id] != 0); + if (_widgets[id]->_hasText == true) + return false; + + _widgets[id]->_textStep = step; + _widgets[id]->_textStep.font = 0; + _widgets[id]->_hasText = true; + } else { + if (drawDataId == "default") { + _texts[kTextColorDefault] = step; + } else if (drawDataId == "hover") { + _texts[kTextColorHover] = step; + } else if (drawDataId == "disabled") { + _texts[kTextColorDisabled] = step; + } else return false; + } return true; } @@ -215,15 +223,15 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; - _widgets[data_id]->_buffer = false; + _widgets[data_id]->_buffer = kDrawData[data_id].buffer; _widgets[data_id]->_surfaceCache = 0; _widgets[data_id]->_hasText = false; // TODO: set this only when needed // possibly add an option to the parser to set this // on each drawdata... - if (data_id >= kDDMainDialogBackground && data_id <= kDDWidgetBackgroundSlider) - _widgets[data_id]->_buffer = true; +// if (data_id >= kDDMainDialogBackground && data_id <= kDDWidgetBackgroundSlider) +// _widgets[data_id]->_buffer = true; return true; } @@ -255,19 +263,6 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { } } - int r, g, b; - -#define __LOAD_COLOR(id, name) { \ - if (parser()->getPaletteColor(name, r, g, b))\ - _textColors[id] = _vectorRenderer->buildColor(r, g, b); \ -} - - __LOAD_COLOR(kTextColorDefault, "text_default"); - __LOAD_COLOR(kTextColorHover, "text_hover"); - __LOAD_COLOR(kTextColorDisabled, "text_disabled"); - -#undef __LOAD_COLOR - _themeOk = true; return true; } @@ -302,42 +297,82 @@ void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); } -void ThemeRenderer::drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData) { +void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) { if (_widgets[type] == 0) return; + + DrawQueue q; + q.type = type; + q.area = r; + q.dynData = dynamic; + + if (_buffering) { + warning("Queued up a '%s' for the %s", kDrawData[type].name, _widgets[type]->_buffer ? "buffer" : "screen"); + + if (_widgets[type]->_buffer) + _bufferQueue.push_back(q); + else { + if (kDrawData[type].parent != kDDNone) + queueDD(kDrawData[type].parent, r); - Common::Rect extendedRect = r; - extendedRect.grow(kDirtyRectangleThreshold); - extendedRect.right += _widgets[type]->_backgroundOffset; - extendedRect.bottom += _widgets[type]->_backgroundOffset; - - if (_buffering && _widgets[type]->_buffer) - _vectorRenderer->setSurface(_backBuffer); - else - restoreBackground(extendedRect); + _screenQueue.push_back(q); + } + } else { + warning("Drawing a '%s' directly!", kDrawData[type].name); + drawDD(q, !_widgets[type]->_buffer, _widgets[type]->_buffer); + } +} - addDirtyRect(extendedRect); +void ThemeRenderer::queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, TextColor colorId, TextAlign align) { + if (!hasWidgetText(type)) + return; - if (isWidgetCached(type, r)) { - drawCached(type, r); + DrawQueueText q; + q.type = type; + q.area = r; + q.text = text; + q.colorId = colorId; + q.align = align; + + if (_buffering) { + _textQueue.push_back(q); } else { - for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); - step != _widgets[type]->_steps.end(); ++step) - _vectorRenderer->drawStep(r, *step, dynamicData); + drawDDText(q); } +} - if (_buffering && _widgets[type]->_buffer) { - _vectorRenderer->setSurface(_screen); - memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); +void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { + Common::Rect extendedRect = q.area; + extendedRect.grow(kDirtyRectangleThreshold); + extendedRect.right += _widgets[q.type]->_backgroundOffset; + extendedRect.bottom += _widgets[q.type]->_backgroundOffset; + + if (restore) + restoreBackground(extendedRect); + + if (draw) { + if (isWidgetCached(q.type, q.area)) { + drawCached(q.type, q.area); + } else { + for (Common::List::const_iterator step = _widgets[q.type]->_steps.begin(); + step != _widgets[q.type]->_steps.end(); ++step) + _vectorRenderer->drawStep(q.area, *step, q.dynData); + } } + + addDirtyRect(extendedRect); } -void ThemeRenderer::drawDDText(DrawData type, const Common::Rect &r, const Common::String &text) { - if (hasWidgetText(type)) { - if (_widgets[type]->_textStep.font == 0) - _widgets[type]->_textStep.font = _font; +void ThemeRenderer::drawDDText(const DrawQueueText &q) { + restoreBackground(q.area); + + if (q.type == kDDNone) { + _vectorRenderer->textStep(q.text, q.area, _texts[q.colorId], q.align); + } else { + if (_widgets[q.type]->_textStep.font == 0) + _widgets[q.type]->_textStep.font = _font; - _vectorRenderer->textStep(text, r, _widgets[type]->_textStep); + _vectorRenderer->textStep(q.text, q.area, _widgets[q.type]->_textStep); } } @@ -381,15 +416,15 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, else if (state == kStateDisabled) dd = kDDButtonDisabled; - drawDD(dd, r); - drawDDText(dd, r, str); + queueDD(dd, r); + queueDDText(dd, r, str); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { if (!ready()) return; - drawDD(kDDSeparator, r); + queueDD(kDDSeparator, r); } void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { @@ -402,31 +437,29 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - drawDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); + queueDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); r2.left = r2.right + checkBoxSize; r2.right = r.right; - drawDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); + queueDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { if (!ready()) return; - drawDD(kDDSliderEmpty, r); - Common::Rect r2 = r; r2.setWidth(MIN((int16)width, r.width())); - drawDD(kDDSliderFull, r2); + queueDD(kDDSliderFull, r2); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { if (!ready()) return; - drawDD(kDDScrollbarBase, r); + queueDD(kDDScrollbarBase, r); // TODO: Need to find a scrollbar in the GUI for testing... :p } @@ -435,13 +468,13 @@ void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, Wi return; if (hints & THEME_HINT_MAIN_DIALOG) { - drawDD(kDDMainDialogBackground, r); + queueDD(kDDMainDialogBackground, r); } else if (hints & THEME_HINT_SPECIAL_COLOR) { - drawDD(kDDSpecialColorBackground, r); + queueDD(kDDSpecialColorBackground, r); } else if (hints & THEME_HINT_PLAIN_COLOR) { - drawDD(kDDPlainColorBackground, r); + queueDD(kDDPlainColorBackground, r); } else { - drawDD(kDDDefaultBackground, r); + queueDD(kDDDefaultBackground, r); } } @@ -458,11 +491,11 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle; - drawDD(dd, r); + queueDD(dd, r); if (!sel.empty()) { Common::Rect text(r.left, r.top, r.right - 16, r.bottom); - drawDDText(dd, text, sel); + queueDDText(dd, text, sel); } } @@ -479,19 +512,19 @@ void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, Wi switch (background) { case kWidgetBackgroundBorderSmall: - drawDD(kDDWidgetBackgroundSmall, r); + queueDD(kDDWidgetBackgroundSmall, r); break; case kWidgetBackgroundEditText: - drawDD(kDDWidgetBackgroundEditText, r); + queueDD(kDDWidgetBackgroundEditText, r); break; case kWidgetBackgroundSlider: - drawDD(kDDWidgetBackgroundSlider, r); + queueDD(kDDWidgetBackgroundSlider, r); break; default: - drawDD(kDDWidgetBackgroundDefault, r); + queueDD(kDDWidgetBackgroundDefault, r); break; } } @@ -507,16 +540,16 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, continue; Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - drawDD(kDDTabInactive, tabRect); - drawDDText(kDDTabInactive, tabRect, tabs[i]); + queueDD(kDDTabInactive, tabRect); + queueDDText(kDDTabInactive, tabRect, tabs[i]); } if (active >= 0) { Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); const uint16 tabLeft = active * (tabWidth + tabOffset); const uint16 tabRight = r.right - tabRect.right; - drawDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); - drawDDText(kDDTabActive, tabRect, tabs[active]); + queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); + queueDDText(kDDTabActive, tabRect, tabs[active]); } } @@ -524,12 +557,14 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W if (!_initOk) return; - restoreBackground(r); - getFont(font)->drawString(_screen, str, r.left, r.top, r.width(), getTextColor(state), convertAligment(align), deltax, useEllipsis); - addDirtyRect(r); + // TODO: Queue this up too! + // restoreBackground(r); + // getFont(font)->drawString(_screen, str, r.left, r.top, r.width(), getTextColor(state), convertAligment(align), deltax, useEllipsis); + // addDirtyRect(r); + + queueDDText(kDDNone, r, str, getTextColor(state), align); } - void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); _screen->hLine(r.left, r.top, r.right, 0xFFFF); @@ -540,6 +575,34 @@ void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) void ThemeRenderer::updateScreen() { // renderDirtyScreen(); + + if (!_bufferQueue.empty()) { + _vectorRenderer->setSurface(_backBuffer); + + for (Common::List::const_iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) + drawDD(*q, true, false); + + _vectorRenderer->setSurface(_screen); + _bufferQueue.clear(); + memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); + } + + if (!_screenQueue.empty()) { + _vectorRenderer->disableShadows(); + for (Common::List::const_iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) + drawDD(*q, true, false); + + _vectorRenderer->enableShadows(); + _screenQueue.clear(); + } + + if (!_textQueue.empty()) { + for (Common::List::const_iterator q = _textQueue.begin(); q != _textQueue.end(); ++q) + drawDDText(*q); + + _textQueue.clear(); + } + _vectorRenderer->copyWholeFrame(_system); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index e01d31e00f..74b9cb0f5b 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -111,7 +111,6 @@ public: kDDButtonDisabled, kDDSliderFull, - kDDSliderEmpty, kDDCheckboxEnabled, kDDCheckboxDisabled, @@ -127,11 +126,12 @@ public: kDDCaret, kDDSeparator, - kDDDefaultText, - kDrawDataMAX + kDrawDataMAX, + kDDNone = -1 }; enum TextColor { + kTextColorNone = -1, kTextColorDefault, kTextColorHover, kTextColorDisabled, @@ -143,6 +143,21 @@ public: DrawData id; const char *name; bool buffer; + DrawData parent; + }; + + struct DrawQueue { + DrawData type; + Common::Rect area; + uint32 dynData; + }; + + struct DrawQueueText { + DrawData type; + Common::Rect area; + Common::String text; + TextColor colorId; + TextAlign align; }; static const DrawDataInfo kDrawData[]; @@ -205,7 +220,7 @@ public: if (name.compareToIgnoreCase(kDrawData[i].name) == 0) return kDrawData[i].id; - return (DrawData)-1; + return kDDNone; } void addDrawStep(Common::String &drawDataId, Graphics::DrawStep step); @@ -283,8 +298,12 @@ protected: void drawCached(DrawData type, const Common::Rect &r); void calcBackgroundOffset(DrawData type); - inline void drawDD(DrawData type, const Common::Rect &r, uint32 dynamicData = 0); - inline void drawDDText(DrawData type, const Common::Rect &r, const Common::String &text); + inline void drawDD(const DrawQueue &q, bool draw = true, bool restore = false); + inline void drawDDText(const DrawQueueText &q); + inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); + inline void queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, + TextColor colorId = kTextColorNone, TextAlign align = kTextAlignLeft); + inline void debugWidgetPosition(const char *name, const Common::Rect &r); // TODO @@ -298,16 +317,16 @@ protected: return 3; } - uint32 getTextColor(WidgetStateInfo state) { + TextColor getTextColor(WidgetStateInfo state) { switch (state) { case kStateDisabled: - return _textColors[kTextColorDisabled]; + return kTextColorDisabled; case kStateHighlight: - return _textColors[kTextColorHover]; + return kTextColorHover; default: - return _textColors[kTextColorDefault]; + return kTextColorDefault; } } @@ -324,10 +343,14 @@ protected: Common::String _fontName; const Graphics::Font *_font; - uint32 _textColors[kTextColorMAX]; WidgetDrawData *_widgets[kDrawDataMAX]; + Graphics::TextStep _texts[kTextColorMAX]; Common::Array _dirtyScreen; + + Common::List _bufferQueue; + Common::List _screenQueue; + Common::List _textQueue; bool _initOk; bool _themeOk; diff --git a/gui/newgui.cpp b/gui/newgui.cpp index c4fafe7e22..e689617418 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -193,25 +193,22 @@ void NewGui::redraw() { switch (_redrawStatus) { case kRedrawCloseDialog: case kRedrawFull: + case kRedrawTopDialog: + warning("Full screen redraw. Oops"); _theme->clearAll(); _theme->closeAllDialogs(); - for (i = 0; i < _dialogStack.size(); i++) { - _theme->openDialog(true); + for (i = 0; i < _dialogStack.size() - 1; i++) { _dialogStack[i]->drawDialog(); } - break; case kRedrawOpenDialog: _theme->openDialog(true); + //_theme->startBuffering(); _dialogStack.top()->drawDialog(); _theme->finishBuffering(); - printf("Dialog opened!\n"); - break; - - case kRedrawTopDialog: - _dialogStack.top()->drawDialog(); - printf("Top dialog redraw!\n"); + + warning("Dialog opened"); break; default: diff --git a/gui/theme.h b/gui/theme.h index a55f04b115..e2b0d39fd3 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -251,6 +251,7 @@ public: * the dialog stack from scratch. */ virtual bool closeDialog() { return false; } + virtual void startBuffering() {} virtual void finishBuffering() {} /** -- cgit v1.2.3 From 4e7b9f287ea7ce65ad2d59ca538b6520f81c4765 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 20 Jul 2008 22:23:35 +0000 Subject: Fixed: Text/button drawing svn-id: r33154 --- gui/ThemeRenderer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 6c31dcf7a0..35d984b17c 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -193,6 +193,8 @@ void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep s bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep step) { DrawData id = getDrawDataId(drawDataId); + + step.font = 0; if (id != -1) { assert(_widgets[id] != 0); @@ -200,7 +202,6 @@ bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep s return false; _widgets[id]->_textStep = step; - _widgets[id]->_textStep.font = 0; _widgets[id]->_hasText = true; } else { if (drawDataId == "default") { @@ -324,9 +325,6 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } void ThemeRenderer::queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, TextColor colorId, TextAlign align) { - if (!hasWidgetText(type)) - return; - DrawQueueText q; q.type = type; q.area = r; @@ -363,10 +361,12 @@ void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { addDirtyRect(extendedRect); } -void ThemeRenderer::drawDDText(const DrawQueueText &q) { - restoreBackground(q.area); - +void ThemeRenderer::drawDDText(const DrawQueueText &q) { if (q.type == kDDNone) { + restoreBackground(q.area); + if (_texts[q.colorId].font == 0) + _texts[q.colorId].font = _font; + _vectorRenderer->textStep(q.text, q.area, _texts[q.colorId], q.align); } else { if (_widgets[q.type]->_textStep.font == 0) @@ -622,7 +622,7 @@ void ThemeRenderer::openDialog(bool doBuffer) { if (doBuffer) _buffering = true; - memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); +// memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); } } // end of namespace GUI. -- cgit v1.2.3 From b7edb14e55fd300c8db35d87d690e9f44763c662 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 20 Jul 2008 22:49:24 +0000 Subject: Fixed: Backbuffer blitting svn-id: r33155 --- gui/ThemeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 35d984b17c..b287406ba5 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -622,7 +622,7 @@ void ThemeRenderer::openDialog(bool doBuffer) { if (doBuffer) _buffering = true; -// memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); + memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); } } // end of namespace GUI. -- cgit v1.2.3 From 5a4fcb83e24829334f12b046c120f200792f0ea9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 09:19:57 +0000 Subject: Valgrind fix: Invalid write in rounded square shadows svn-id: r33164 --- graphics/VectorRenderer.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 70bcc1b2c3..baadd3ae41 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -1014,30 +1014,24 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { // there are 4 pixels on each circle which are drawn twice. // this is ok on filled circles, but when blending on surfaces, // we cannot let it blend twice. awful. - bool *hb = new bool[r]; - - int i = 0; - while (i < r) - hb[i++] = false; + uint32 hb = 0; while (x++ < y) { __BE_ALGORITHM(); - if (!hb[x]) { + if ((1 << x) & hb == 0) { blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha); - hb[x] = true; + hb |= (1 << x); } - if (!hb[y]) { + if ((1 << y) & hb == 0) { blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha); blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha); - hb[y] = true; + hb |= (1 << y); } } - delete[] hb; - while (short_h--) { blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha); ptr_fill += pitch; -- cgit v1.2.3 From 89a21f1613cfe9ded3de22c5d4261ed40a39a1c3 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 09:53:06 +0000 Subject: Valgrind fix: Invalid read/write while restoring background svn-id: r33166 --- graphics/VectorRenderer.cpp | 4 ++-- graphics/VectorRenderer.h | 4 ++-- gui/ThemeRenderer.cpp | 14 +------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index baadd3ae41..190bbbb40a 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -1019,13 +1019,13 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { while (x++ < y) { __BE_ALGORITHM(); - if ((1 << x) & hb == 0) { + if (((1 << x) & hb) == 0) { blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha); hb |= (1 << x); } - if ((1 << y) & hb == 0) { + if (((1 << y) & hb) == 0) { blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha); blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha); hb |= (1 << y); diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index c7ba0676b3..ee8129bd67 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -658,8 +658,8 @@ public: * @see VectorRenderer::blitSurface() */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) { - PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.top, r.left); - PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); + PixelType *src_ptr = (PixelType *)source->getBasePtr(r.left, r.top); int dst_pitch = surfacePitch(); int src_pitch = source->pitch / source->bytesPerPixel; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index b287406ba5..b7483b810d 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -388,19 +388,7 @@ void ThemeRenderer::calcBackgroundOffset(DrawData type) { } void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { - const OverlayColor *src = (const OverlayColor*)_backBuffer->getBasePtr(r.left, r.top); - OverlayColor *dst = (OverlayColor*)_screen->getBasePtr(r.left, r.top); - - int h = r.height(); - int w = r.width(); - while (h--) { - memcpy(dst, src, w * sizeof(OverlayColor)); - src += _backBuffer->w; - dst += _screen->w; - } - -// debugWidgetPosition("", r); -// printf(" BG_RESTORE "); + _vectorRenderer->blitSurface(_backBuffer, r); } void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { -- cgit v1.2.3 From f218ab3a9d52de69518c8a7f809ae858f04e4a49 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 14:03:37 +0000 Subject: Milestone: Rendering pipeline is fully working. 'Yay...' svn-id: r33172 --- gui/ThemeRenderer.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index b7483b810d..5b1e919f56 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -98,7 +98,7 @@ bool ThemeRenderer::init() { deinit(); setGraphicsMode(_graphicsMode); - if (_screen->pixels) { + if (_screen->pixels && _backBuffer->pixels) { _initOk = true; clearAll(); resetDrawArea(); @@ -127,6 +127,7 @@ void ThemeRenderer::deinit() { _system->hideOverlay(); freeRenderer(); freeScreen(); + freeBackbuffer(); _initOk = false; } } @@ -156,14 +157,17 @@ template void ThemeRenderer::screenInit(bool backBuffer) { freeScreen(); freeBackbuffer(); + + uint32 width = _system->getOverlayWidth(); + uint32 height = _system->getOverlayHeight(); if (backBuffer) { _backBuffer = new Surface; - _backBuffer->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); + _backBuffer->create(width, height, sizeof(PixelType)); } _screen = new Surface; - _screen->create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(PixelType)); + _screen->create(width, height, sizeof(PixelType)); _system->clearOverlay(); } @@ -228,12 +232,6 @@ bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { _widgets[data_id]->_surfaceCache = 0; _widgets[data_id]->_hasText = false; - // TODO: set this only when needed - // possibly add an option to the parser to set this - // on each drawdata... -// if (data_id >= kDDMainDialogBackground && data_id <= kDDWidgetBackgroundSlider) -// _widgets[data_id]->_buffer = true; - return true; } @@ -388,6 +386,7 @@ void ThemeRenderer::calcBackgroundOffset(DrawData type) { } void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { + r.clip(_screen->w, _screen->h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( _vectorRenderer->blitSurface(_backBuffer, r); } @@ -544,11 +543,6 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { if (!_initOk) return; - - // TODO: Queue this up too! - // restoreBackground(r); - // getFont(font)->drawString(_screen, str, r.left, r.top, r.width(), getTextColor(state), convertAligment(align), deltax, useEllipsis); - // addDirtyRect(r); queueDDText(kDDNone, r, str, getTextColor(state), align); } @@ -571,8 +565,8 @@ void ThemeRenderer::updateScreen() { drawDD(*q, true, false); _vectorRenderer->setSurface(_screen); + _vectorRenderer->blitSurface(_backBuffer, Common::Rect(0, 0, _screen->w, _screen->h)); _bufferQueue.clear(); - memcpy(_screen->pixels, _backBuffer->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); } if (!_screenQueue.empty()) { @@ -610,7 +604,9 @@ void ThemeRenderer::openDialog(bool doBuffer) { if (doBuffer) _buffering = true; - memcpy(_backBuffer->pixels, _screen->pixels, _screen->w * _screen->h * _screen->bytesPerPixel); + _vectorRenderer->setSurface(_backBuffer); + _vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h)); + _vectorRenderer->setSurface(_screen); } } // end of namespace GUI. -- cgit v1.2.3 From 8bfaacf587016e4dd58c0938fca0c9a7520f2bcd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 16:14:06 +0000 Subject: Cleanup. Fix: Scroll widget background. svn-id: r33174 --- gui/ThemeDefaultXML.cpp | 4 ++-- gui/ThemeRenderer.cpp | 14 ++++++-------- gui/newgui.cpp | 3 --- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index afb559f950..77a65cfdc6 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -93,7 +93,7 @@ bool ThemeRenderer::loadDefaultXML() { "" - "" + "" "" "" "" @@ -109,7 +109,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 5b1e919f56..d2956c8a22 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -54,7 +54,7 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawData[] = { {kDDButtonHover, "button_hover", false, kDDButtonIdle}, {kDDButtonDisabled, "button_disabled", true, kDDNone}, - {kDDSliderFull, "slider_full", false, kDDWidgetBackgroundSlider}, + {kDDSliderFull, "slider_full", false, kDDNone}, {kDDCheckboxEnabled, "checkbox_enabled", false, kDDCheckboxDisabled}, {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, @@ -306,18 +306,15 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic q.dynData = dynamic; if (_buffering) { - warning("Queued up a '%s' for the %s", kDrawData[type].name, _widgets[type]->_buffer ? "buffer" : "screen"); - - if (_widgets[type]->_buffer) - _bufferQueue.push_back(q); - else { - if (kDrawData[type].parent != kDDNone) + if (_widgets[type]->_buffer) { + _bufferQueue.push_back(q); + } else { + if (kDrawData[type].parent != kDDNone && kDrawData[type].parent != type) queueDD(kDrawData[type].parent, r); _screenQueue.push_back(q); } } else { - warning("Drawing a '%s' directly!", kDrawData[type].name); drawDD(q, !_widgets[type]->_buffer, _widgets[type]->_buffer); } } @@ -439,6 +436,7 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo Common::Rect r2 = r; r2.setWidth(MIN((int16)width, r.width())); + drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); queueDD(kDDSliderFull, r2); } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index e689617418..acbf14cae2 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -194,7 +194,6 @@ void NewGui::redraw() { case kRedrawCloseDialog: case kRedrawFull: case kRedrawTopDialog: - warning("Full screen redraw. Oops"); _theme->clearAll(); _theme->closeAllDialogs(); @@ -207,8 +206,6 @@ void NewGui::redraw() { //_theme->startBuffering(); _dialogStack.top()->drawDialog(); _theme->finishBuffering(); - - warning("Dialog opened"); break; default: -- cgit v1.2.3 From 0883615a23d4ecb3fcc6296668a6c86173617810 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 19:15:59 +0000 Subject: Cleanup. Massive documentation update. (zzzzz) svn-id: r33177 --- gui/ThemeParser.cpp | 9 +- gui/ThemeRenderer.cpp | 18 +-- gui/ThemeRenderer.h | 407 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 345 insertions(+), 89 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index c43da99ac1..5a5a6e8af8 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -358,11 +358,6 @@ bool ThemeParser::parserCallback_DRAWDATA() { if (drawdataNode->values.contains("id") == false) return parserError("DrawData keys must contain an identifier."); - ThemeRenderer::DrawData id = _theme->getDrawDataId(drawdataNode->values["id"]); - - if (id == -1) - return parserError("%s is not a valid DrawData set identifier.", drawdataNode->values["id"].c_str()); - if (drawdataNode->values.contains("cache")) { if (drawdataNode->values["cache"] == "true") cached = true; @@ -381,8 +376,8 @@ bool ThemeParser::parserCallback_DRAWDATA() { } }*/ - if (_theme->addDrawData(id, cached) == false) - return parserError("Repeated DrawData: Only one set of Drawing Data for a widget may be specified on each platform."); + if (_theme->addDrawData(drawdataNode->values["id"], cached) == false) + return parserError("Error when adding Draw Data set: Invalid DrawData name."); if (_defaultStepLocal) { delete _defaultStepLocal; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index d2956c8a22..84366a6f4a 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -39,7 +39,7 @@ namespace GUI { using namespace Graphics; -const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawData[] = { +const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, {kDDSpecialColorBackground, "special_bg", true, kDDNone}, {kDDPlainColorBackground, "plain_bg", true, kDDNone}, @@ -188,14 +188,14 @@ void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { _vectorRenderer->setSurface(_screen); } -void ThemeRenderer::addDrawStep(Common::String &drawDataId, Graphics::DrawStep step) { +void ThemeRenderer::addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step) { DrawData id = getDrawDataId(drawDataId); assert(_widgets[id] != 0); _widgets[id]->_steps.push_back(step); } -bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep step) { +bool ThemeRenderer::addTextStep(const Common::String &drawDataId, Graphics::TextStep step) { DrawData id = getDrawDataId(drawDataId); step.font = 0; @@ -220,15 +220,15 @@ bool ThemeRenderer::addTextStep(Common::String &drawDataId, Graphics::TextStep s return true; } -bool ThemeRenderer::addDrawData(DrawData data_id, bool cached) { - assert(data_id >= 0 && data_id < kDrawDataMAX); +bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { + DrawData data_id = getDrawDataId(data); - if (_widgets[data_id] != 0) + if (data_id == -1 || _widgets[data_id] != 0) return false; _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; - _widgets[data_id]->_buffer = kDrawData[data_id].buffer; + _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; _widgets[data_id]->_surfaceCache = 0; _widgets[data_id]->_hasText = false; @@ -309,8 +309,8 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic if (_widgets[type]->_buffer) { _bufferQueue.push_back(q); } else { - if (kDrawData[type].parent != kDDNone && kDrawData[type].parent != type) - queueDD(kDrawData[type].parent, r); + if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) + queueDD(kDrawDataDefaults[type].parent, r); _screenQueue.push_back(q); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 74b9cb0f5b..abaff44c55 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -73,28 +73,25 @@ struct WidgetDrawData { }; class ThemeRenderer : public Theme { - + +protected: typedef Common::String String; typedef GUI::Dialog Dialog; friend class GUI::Dialog; friend class GUI::GuiObject; - /** Strings representing each value in the DrawData enum */ - /** Constant value to expand dirty rectangles, to make sure they are fully copied */ static const int kDirtyRectangleThreshold = 2; /** Sets whether backcaching is enabled */ static const bool kEnableBackCaching = true; -public: - enum GraphicsMode { - kGfxDisabled = 0, - kGfxStandard16bit, - kGfxAntialias16bit - }; - + /** + * DrawData sets enumeration. + * Each DD set corresponds to the actual looks + * of a widget in a given state. + */ enum DrawData { kDDMainDialogBackground, kDDSpecialColorBackground, @@ -130,6 +127,28 @@ public: kDDNone = -1 }; + /** + * Default values for each DrawData item. + * @see kDrawDataDefaults[] for implementation. + */ + static const struct DrawDataInfo { + DrawData id; /** The actual ID of the DrawData item. */ + const char *name; /** The name of the DrawData item as it appears in the Theme Description files */ + bool buffer; /** Sets whether this item is buffered on the backbuffer or drawn directly to the screen. */ + DrawData parent; /** Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover */ + } kDrawDataDefaults[]; + + /** + * Queue Node for the drawing queue. + * Specifies the exact drawing to be done when processing + * the drawing queues. + */ + struct DrawQueue { + DrawData type; /** DrawData item to draw. */ + Common::Rect area; /** Place on screen to draw it. */ + uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/ + }; + enum TextColor { kTextColorNone = -1, kTextColorDefault, @@ -139,19 +158,6 @@ public: kTextColorMAX }; - struct DrawDataInfo { - DrawData id; - const char *name; - bool buffer; - DrawData parent; - }; - - struct DrawQueue { - DrawData type; - Common::Rect area; - uint32 dynData; - }; - struct DrawQueueText { DrawData type; Common::Rect area; @@ -160,9 +166,21 @@ public: TextAlign align; }; - static const DrawDataInfo kDrawData[]; +public: + /** Graphics mode enumeration. + * Each item represents a set of BPP and Renderer modes for a given + * surface. + */ + enum GraphicsMode { + kGfxDisabled = 0, /** No GFX */ + kGfxStandard16bit, /** 2BPP with the standard (aliased) renderer. */ + kGfxAntialias16bit /** 2BPP with the optimized AA renderer. */ + }; + + /** Default constructor */ ThemeRenderer(Common::String themeName, GraphicsMode mode); + /** Default destructor */ ~ThemeRenderer() { freeRenderer(); freeScreen(); @@ -170,7 +188,13 @@ public: delete _parser; } - // virtual methods from Theme + /** + * VIRTUAL METHODS + * This is the implementation of the GUI::Theme API to allow + * the ThemeRenderer class to be plugged in as any other GUI + * theme. In fact, the renderer works like any other GUI theme, + * but supports extensive customization of the drawn widgets. + */ bool init(); void deinit(); void clearAll(); @@ -178,76 +202,210 @@ public: void refresh() {} void enable(); void disable(); + + /** + * Implementation of the GUI::Theme API. Called when a + * new dialog is opened. Note that the boolean parameter + * meaning has been changed. + * + * @param enableBuffering If set to true, buffering is enabled for + * drawing this dialog, and will continue enabled + * until disabled. + */ + void openDialog(bool enableBuffering); + + /** + * The updateScreen() method is called every frame. + * It processes all the drawing queues and then copies dirty rects + * in the current Screen surface to the overlay. + */ + void updateScreen(); + /** Since the rendering pipeline changes, closing all dialogs causes no effect + TODO: remove this from the original GUI::Theme API */ void closeAllDialogs() {} - void updateScreen(); + /** Drawing area has been removed: it was too hackish. A workaround is on the works. + TODO: finish the workaround for the credits dialog + TODO: remove this from the original GUI::Theme API */ void resetDrawArea() {} - void openDialog(bool top); - - /** Font management */ + + /** + * FONT MANAGEMENT METHODS + */ const Graphics::Font *getFont(FontStyle font) const { return _font; } int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } - /** Widget drawing */ - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, uint16 hints = 0); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled); - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state = kStateEnabled); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state = kStateEnabled); + + /** + * WIDGET DRAWING METHODS + */ + void drawWidgetBackground(const Common::Rect &r, uint16 hints, + WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); + + void drawButton(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state = kStateEnabled, uint16 hints = 0); + + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, + WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); + + void drawSlider(const Common::Rect &r, int width, + WidgetStateInfo state = kStateEnabled); + + void drawCheckbox(const Common::Rect &r, const Common::String &str, + bool checked, WidgetStateInfo state = kStateEnabled); + + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, + const Common::Array &tabs, int active, uint16 hints, + int titleVPad, WidgetStateInfo state = kStateEnabled); + + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, + ScrollbarState, WidgetStateInfo state = kStateEnabled); + + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, + int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); + + void drawCaret(const Common::Rect &r, bool erase, + WidgetStateInfo state = kStateEnabled); + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {} - + + void drawText(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); + + void drawChar(const Common::Rect &r, byte ch, + const Graphics::Font *font, WidgetStateInfo state) {} + + /** + * Actual implementation of a Dirty Rect drawing routine. + * Dirty rectangles are queued on a list and are later merged/calculated + * before the actual drawing. + * + * @param r Area of the dirty rect. + * @param backup Deprecated. + * @param special Deprecated. + */ bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { -// r.grow(kDirtyRectangleThreshold); _dirtyScreen.push_back(r); return true; } - // custom stuff - tanoku - DrawData getDrawDataId(Common::String &name) { + + /** + * Returns the DrawData enumeration value that represents the given string + * in the DrawDataDefaults enumeration. + * It's slow, but called sparsely. + * + * @returns The drawdata enum value, or -1 if not found. + * @param name The representing name, as found on Theme Description XML files. + * @see kDrawDataDefaults[] + */ + DrawData getDrawDataId(const Common::String &name) { for (int i = 0; i < kDrawDataMAX; ++i) - if (name.compareToIgnoreCase(kDrawData[i].name) == 0) - return kDrawData[i].id; + if (name.compareToIgnoreCase(kDrawDataDefaults[i].name) == 0) + return kDrawDataDefaults[i].id; return kDDNone; } - void addDrawStep(Common::String &drawDataId, Graphics::DrawStep step); - bool addDrawData(DrawData data_id, bool cached); - bool addTextStep(Common::String &drawDataId, Graphics::TextStep step); + /** + * Interface for ThemeParser class: Parsed DrawSteps are added via this function. + * There is no return type because DrawSteps can always be added, unless something + * goes horribly wrong. + * The specified step will be added to the Steps list of the given DrawData id. + * + * @param drawDataId The representing DrawData name, as found on Theme Description XML files. + * @param step The actual DrawStep struct to be added. + */ + void addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step); + + /** + * Interfacefor the ThemeParser class: Parsed DrawData sets are added via this function. + * The goal of the function is to initialize each DrawData set before their DrawSteps can + * be added, hence this must be called for each DD set before addDrawStep() can be called + * for that given set. + * + * @param data The representing DrawData name, as found on Theme Description XML files. + * @param cached Whether this DD set will be cached beforehand. + */ + bool addDrawData(const Common::String &data, bool cached); + + /** + * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the + * new Font API is in place. + */ + bool addTextStep(const Common::String &drawDataId, Graphics::TextStep step); + /** Interface to the new Theme XML parser */ ThemeParser *parser() { return _parser; } + /** + * Returns if the Theme is ready to draw stuff on screen. + * Must be called instead of just checking _initOk, because + * this checks if the renderer is initialized AND if the theme + * is loaded. + */ bool ready() { return _initOk && _themeOk; } + /** Custom implementation of the GUI::Theme API, changed to use the XML parser. */ bool loadTheme(Common::String themeName); + + /** + * Changes the active graphics mode of the GUI; may be used to either + * initialize the GUI or to change the mode while the GUI is already running. + */ void setGraphicsMode(GraphicsMode mode); + + /** + * Finishes buffering: widgets from there one will be drawn straight on the screen + * without drawing queues. + */ void finishBuffering() { _buffering = false; } protected: - template void screenInit(bool backBuffer); - + + /** + * Initializes the drawing screen surfaces, _screen and _backBuffer. + * If the surfaces already exist, they are cleared and re-initialized. + * + * @param backBuffer Sets whether the _backBuffer surface should be initialized. + * @template PixelType C type which specifies the size of each pixel. + * Defaults to uint16 (2 BPP for the surfaces) + */ + template void screenInit(bool backBuffer = true); + + /** + * Loads the given theme into the ThemeRenderer. + * Note that ThemeName is an identifier, not a filename. + * + * @param ThemeName Theme identifier. + * @returns True if the theme was succesfully loaded. + */ bool loadThemeXML(Common::String themeName); + + /** + * Loads the default theme file (the embeded XML file found + * in ThemeDefaultXML.cpp). + * Called only when no other themes are available. + */ bool loadDefaultXML(); + /** + * Unloads the currently loaded theme so another one can + * be loaded. + */ void unloadTheme() { if (!_themeOk) return; @@ -260,14 +418,34 @@ protected: _themeOk = false; } + /** + * Not implemented yet. + * TODO: reload themes, reload the renderer, recheck everything + */ void screenChange() {} + + /** + * Actual Dirty Screen handling function. + * Handles all the dirty squares in the list, merges and optimizes + * them when possible and draws them to the screen. + * Called from updateScreen() + * + * TODO: This function is partly implemented, but currently not used. + * Currently the whole frame is drawn to the screen. + */ void renderDirtyScreen(); + /** + * Frees the vector renderer. + */ void freeRenderer() { delete _vectorRenderer; _vectorRenderer = 0; } + /** + * Frees the Back buffer surface, only if it's available. + */ void freeBackbuffer() { if (_backBuffer != 0) { _backBuffer->free(); @@ -276,6 +454,9 @@ protected: } } + /** + * Frees the main screen drawing surface, only if it's available. + */ void freeScreen() { if (_screen != 0) { _screen->free(); @@ -284,39 +465,95 @@ protected: } } - bool needRedraw() { - return true; - } - - void redrawDialogStack(); - + /** + * Checks if the given widget type has a Text drawing step associated to it. + * + * @param type DrawData type of the widget. + */ bool hasWidgetText(DrawData type) { return (_widgets[type] != 0 && _widgets[type]->_hasText); } + /** + * Checks if a given DrawData set for a widget has been cached beforehand + * and is ready to be blit into the screen. + * + * @param type DrawData type of the widget. + * @param r Size of the widget which is expected to be cached. + */ bool isWidgetCached(DrawData type, const Common::Rect &r); + + /** + * Draws a cached widget directly on the screen. Currently deprecated. + * + * @param type DrawData type of the widget. + * @param r Position on screen to draw the widget. + */ void drawCached(DrawData type, const Common::Rect &r); + + /** + * Calculates the background threshold offset of a given DrawData item. + * After fully loading all DrawSteps of a DrawData item, this function must be + * called in order to calculate if such draw steps would be drawn outside of + * the actual widget drawing zone (e.g. shadows). If this is the case, a constant + * value will be added when restoring the background of the widget. + * + * @param type DrawData type of the widget. + */ void calcBackgroundOffset(DrawData type); + /** + * Draws a DrawQueue item (which contains DrawData information and a screen + * position) into the screen. + * + * This is the only way the Theme has to drawn on the screen. + * + * @param draw Sets if the DrawData info will be actually drawn. + * @param restore Sets if the background behind the widget will be restored before drawing. + */ inline void drawDD(const DrawQueue &q, bool draw = true, bool restore = false); inline void drawDDText(const DrawQueueText &q); + + /** + * Generates a DrawQueue item and enqueues it so it's drawn to the screen + * when the drawing queue is processed. + * + * If Buffering is enabled, the DrawQueue item will be automatically placed + * on its corresponding queue. + * If Buffering is disabled, the DrawQueue item will be processed immediately + * and drawn to the screen. + * + * This function is called from all the Widget Drawing methods. + */ inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); inline void queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, TextColor colorId = kTextColorNone, TextAlign align = kTextAlignLeft); + /** + * DEBUG: Draws a white square around the given position and writes the given next to it. + */ inline void debugWidgetPosition(const char *name, const Common::Rect &r); - // TODO - void restoreBackground(Common::Rect r, bool special = false); - int getTabSpacing() const { - return 0; - } + /** + * Wrapper for restoring data from the Back Buffer to the screen. + * The actual processing is done in the VectorRenderer. + * + * @param r Area to restore. + * @param special Deprecated. + */ + void restoreBackground(Common::Rect r, bool special = false); - int getTabPadding() const { - return 3; - } + /** + * Default values from GUI::Theme + */ + int getTabSpacing() const { return 0; } + int getTabPadding() const { return 3; } + + /** + * Translates a WidgetStateInfo of a Text widget to the actual font color value. + */ TextColor getTextColor(WidgetStateInfo state) { switch (state) { case kStateDisabled: @@ -330,34 +567,58 @@ protected: } } - OSystem *_system; + OSystem *_system; /** Global system object. */ + + /** Vector Renderer object, does the actual drawing on screen */ Graphics::VectorRenderer *_vectorRenderer; + + /** XML Parser, does the Theme parsing instead of the default parser */ GUI::ThemeParser *_parser; + /** Main screen surface. This is blitted straight into the overlay. */ Graphics::Surface *_screen; + + /** Backbuffer surface. Stores previous states of the screen to blit back */ Graphics::Surface *_backBuffer; - bool _buffering; + + /** Sets whether the current drawing is being buffered (stored for later + processing) or drawn directly to the screen. */ + bool _buffering; + /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ int _bytesPerPixel; + + /** Current graphics mode */ GraphicsMode _graphicsMode; + /** Font info. */ Common::String _fontName; const Graphics::Font *_font; + /** Array of all the DrawData elements than can be drawn to the screen. + Must be full so the renderer can work. */ WidgetDrawData *_widgets[kDrawDataMAX]; + + /** Array of all the text fonts that can be drawn. */ Graphics::TextStep _texts[kTextColorMAX]; + + /** List of all the dirty screens that must be blitted to the overlay. */ Common::Array _dirtyScreen; + /** Queue with all the drawing that must be done to the Back Buffer */ Common::List _bufferQueue; + + /** Queue with all the drawing that must be done to the screen */ Common::List _screenQueue; + + /** Queue with all the text drawing that must be done to the screen */ Common::List _textQueue; - bool _initOk; - bool _themeOk; - bool _caching; - bool _enabled; + bool _initOk; /** Class and renderer properly initialized */ + bool _themeOk; /** Theme data successfully loaded. */ + bool _enabled; /** Whether the Theme is currently shown on the overlay */ - Common::String _themeName; + Common::String _themeName; /** Name of the currently loaded theme */ }; } // end of namespace GUI. -- cgit v1.2.3 From c7b624d91eaa0444fdc454dfb5c5dd7beaa56bcc Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 19:42:35 +0000 Subject: Bugfix: Rounded squares at low resolutions were not drawn. Cleanup. svn-id: r33179 --- graphics/VectorRenderer.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++- graphics/VectorRenderer.h | 81 ++---------------------------------------- gui/ThemeRenderer.h | 5 ++- 3 files changed, 91 insertions(+), 81 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 190bbbb40a..9b460e1ac0 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -84,6 +84,87 @@ void VectorRenderer::textStep(const Common::String &text, const Common::Rect &ar !step.hasAlign ? GUI::Theme::kTextAlignVTop : step.alignVertical); } +int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) { + int radius = 0; + + if (step.radius == 0xFF) + radius = MIN(area.width(), area.height()) / 2; + else + radius = step.radius; + + if (step.scale != (1 << 16) && step.scale != 0) + radius = (radius * step.scale) >> 16; + + return radius; +} + +void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { + if (!step.autoWidth) { + in_w = step.w == -1 ? area.height() : step.w; + + switch(step.xAlign) { + case Graphics::DrawStep::kVectorAlignManual: + if (step.x >= 0) in_x = area.left + step.x; + else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. + break; + + case Graphics::DrawStep::kVectorAlignCenter: + in_x = area.left + (area.width() / 2) - (in_w / 2); + break; + + case Graphics::DrawStep::kVectorAlignLeft: + in_x = area.left; + break; + + case Graphics::DrawStep::kVectorAlignRight: + in_x = area.left + area.width() - in_w; + break; + + default: + error("Vertical alignment in horizontal data."); + } + } else { + in_x = area.left; + in_w = area.width(); + } + + if (!step.autoHeight) { + in_h = step.h == -1 ? area.width() : step.h; + + switch(step.yAlign) { + case Graphics::DrawStep::kVectorAlignManual: + if (step.y >= 0) in_y = area.top + step.y; + else in_y = area.top + area.height() + step.y; // relative + break; + + case Graphics::DrawStep::kVectorAlignCenter: + in_y = area.top + (area.height() / 2) - (in_h / 2); + break; + + case Graphics::DrawStep::kVectorAlignTop: + in_y = area.top; + break; + + case Graphics::DrawStep::kVectorAlignBottom: + in_y = area.top + area.height() - in_h; + break; + + default: + error("Horizontal alignment in vertical data."); + } + } else { + in_y = area.top; + in_h = area.height(); + } + + if (step.scale != (1 << 16) && step.scale != 0) { + in_x = (in_x * step.scale) >> 16; + in_y = (in_y * step.scale) >> 16; + in_w = (in_w * step.scale) >> 16; + in_h = (in_h * step.scale) >> 16; + } +} + /******************************************************************** * MISCELANEOUS functions ********************************************************************/ @@ -356,8 +437,11 @@ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || (r << 1) > w || (r << 1) > h) + w <= 0 || h <= 0 || x < 0 || y < 0) return; + + while ((r << 1) > w || (r << 1) > h) + r <<= 1; if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index ee8129bd67..a5e80164be 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -338,86 +338,9 @@ public: _gradientFactor = factor; } - void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h) { - if (!step.autoWidth) { - in_w = step.w == -1 ? area.height() : step.w; - - switch(step.xAlign) { - case Graphics::DrawStep::kVectorAlignManual: - if (step.x >= 0) in_x = area.left + step.x; - else in_x = area.left + area.width() + step.x; // value relative to the opposite corner. - break; - - case Graphics::DrawStep::kVectorAlignCenter: - in_x = area.left + (area.width() / 2) - (in_w / 2); - break; - - case Graphics::DrawStep::kVectorAlignLeft: - in_x = area.left; - break; - - case Graphics::DrawStep::kVectorAlignRight: - in_x = area.left + area.width() - in_w; - break; - - default: - error("Vertical alignment in horizontal data."); - } - } else { - in_x = area.left; - in_w = area.width(); - } - - if (!step.autoHeight) { - in_h = step.h == -1 ? area.width() : step.h; - - switch(step.yAlign) { - case Graphics::DrawStep::kVectorAlignManual: - if (step.y >= 0) in_y = area.top + step.y; - else in_y = area.top + area.height() + step.y; // relative - break; - - case Graphics::DrawStep::kVectorAlignCenter: - in_y = area.top + (area.height() / 2) - (in_h / 2); - break; - - case Graphics::DrawStep::kVectorAlignTop: - in_y = area.top; - break; - - case Graphics::DrawStep::kVectorAlignBottom: - in_y = area.top + area.height() - in_h; - break; - - default: - error("Horizontal alignment in vertical data."); - } - } else { - in_y = area.top; - in_h = area.height(); - } - - if (step.scale != (1 << 16) && step.scale != 0) { - in_x = (in_x * step.scale) >> 16; - in_y = (in_y * step.scale) >> 16; - in_w = (in_w * step.scale) >> 16; - in_h = (in_h * step.scale) >> 16; - } - } - - int stepGetRadius(const DrawStep &step, const Common::Rect &area) { - int radius = 0; + void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h); - if (step.radius == 0xFF) - radius = MIN(area.width(), area.height()) / 2; - else - radius = step.radius; - - if (step.scale != (1 << 16) && step.scale != 0) - radius = (radius * step.scale) >> 16; - - return radius; - } + int stepGetRadius(const DrawStep &step, const Common::Rect &area); /** * DrawStep callback functions for each drawing feature diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index abaff44c55..134e6fba87 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -223,7 +223,10 @@ public: /** Since the rendering pipeline changes, closing all dialogs causes no effect TODO: remove this from the original GUI::Theme API */ - void closeAllDialogs() {} + void closeAllDialogs() { + memset(_backBuffer->pixels, 0, _backBuffer->w * _backBuffer->h * _backBuffer->bytesPerPixel); + + } /** Drawing area has been removed: it was too hackish. A workaround is on the works. TODO: finish the workaround for the credits dialog -- cgit v1.2.3 From 7071a95a5753861bce494f1e7906e033ce8bd7c4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 21 Jul 2008 21:23:23 +0000 Subject: Fixed several segfaults and graphical glitches when drawing at low resolutions. Fixed dialog stack redrawing. svn-id: r33182 --- graphics/VectorRenderer.cpp | 4 ++-- gui/ThemeRenderer.h | 5 +---- gui/newgui.cpp | 8 +++++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 9b460e1ac0..639039fe28 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -440,8 +440,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { w <= 0 || h <= 0 || x < 0 || y < 0) return; - while ((r << 1) > w || (r << 1) > h) - r <<= 1; + if ((r << 1) > w || (r << 1) > h) + r = MIN(w >> 1, h >> 1); if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + w + Base::_shadowOffset < Base::_activeSurface->w diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 134e6fba87..abaff44c55 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -223,10 +223,7 @@ public: /** Since the rendering pipeline changes, closing all dialogs causes no effect TODO: remove this from the original GUI::Theme API */ - void closeAllDialogs() { - memset(_backBuffer->pixels, 0, _backBuffer->w * _backBuffer->h * _backBuffer->bytesPerPixel); - - } + void closeAllDialogs() {} /** Drawing area has been removed: it was too hackish. A workaround is on the works. TODO: finish the workaround for the credits dialog diff --git a/gui/newgui.cpp b/gui/newgui.cpp index acbf14cae2..b9b4fa028f 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -195,15 +195,17 @@ void NewGui::redraw() { case kRedrawFull: case kRedrawTopDialog: _theme->clearAll(); - _theme->closeAllDialogs(); + _theme->openDialog(true); for (i = 0; i < _dialogStack.size() - 1; i++) { - _dialogStack[i]->drawDialog(); + _dialogStack[i]->drawDialog(); } + _theme->finishBuffering(); + _theme->updateScreen(); + case kRedrawOpenDialog: _theme->openDialog(true); - //_theme->startBuffering(); _dialogStack.top()->drawDialog(); _theme->finishBuffering(); break; -- cgit v1.2.3 From 7f3b60e2dae633dc08db7b99b5c27101e1712ae4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 09:23:37 +0000 Subject: Dirty screen handling! svn-id: r33190 --- gui/ThemeRenderer.cpp | 41 ++++++++++++++++++++++++++++++++--------- gui/ThemeRenderer.h | 2 +- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 84366a6f4a..c434a4a38b 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -369,6 +369,8 @@ void ThemeRenderer::drawDDText(const DrawQueueText &q) { _vectorRenderer->textStep(q.text, q.area, _widgets[q.type]->_textStep); } + + addDirtyRect(q.area); } void ThemeRenderer::calcBackgroundOffset(DrawData type) { @@ -554,8 +556,6 @@ void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) } void ThemeRenderer::updateScreen() { -// renderDirtyScreen(); - if (!_bufferQueue.empty()) { _vectorRenderer->setSurface(_backBuffer); @@ -583,18 +583,41 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } - _vectorRenderer->copyWholeFrame(_system); + renderDirtyScreen(); } void ThemeRenderer::renderDirtyScreen() { - // TODO: This isn't really optimized. Check dirty squares for collisions - // and all that. if (_dirtyScreen.empty()) return; - - for (uint i = 0; i < _dirtyScreen.size(); ++i) - _vectorRenderer->copyFrame(_system, _dirtyScreen[i]); - + + Common::List::iterator cur; + for (Common::List::iterator d = _dirtyScreen.begin(); d != _dirtyScreen.end(); ++d) { + cur = d; + do { + ++d; + if (cur->intersects(*d)) + _dirtyScreen.erase(d); + } while (d != _dirtyScreen.end()); + + + // FIXME: this square-merging algorithm can be rather slow, and I don't think it + // benefits us *that* much. Maybe we should just stick to finding dirty squares that overlap. + + // d = cur; + // + // do { + // ++d; + // if ((cur->top == d->top && cur->bottom == d->bottom && (ABS(cur->left - d->right) < 10 || ABS(cur->right - d->left) < 10)) || + // (cur->left == d->left && cur->right == d->right && (ABS(cur->top - d->bottom) < 10 || ABS(cur->bottom - d->top) < 10))) { + // cur->extend(*d); + // _dirtyScreen.erase(d); + // } + // } while (d != _dirtyScreen.end()); + + d = cur; + _vectorRenderer->copyFrame(_system, *d); + } + _dirtyScreen.clear(); } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index abaff44c55..c54eaf3a1e 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -603,7 +603,7 @@ protected: Graphics::TextStep _texts[kTextColorMAX]; /** List of all the dirty screens that must be blitted to the overlay. */ - Common::Array _dirtyScreen; + Common::List _dirtyScreen; /** Queue with all the drawing that must be done to the Back Buffer */ Common::List _bufferQueue; -- cgit v1.2.3 From 1558fdb9186fd131d40a92b83c38d5dd76a3b353 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 12:07:03 +0000 Subject: Bugfix: Segmentation fault when removing unused dirty rects. svn-id: r33195 --- gui/ThemeRenderer.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index c434a4a38b..2fb0f955ac 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -589,31 +589,17 @@ void ThemeRenderer::updateScreen() { void ThemeRenderer::renderDirtyScreen() { if (_dirtyScreen.empty()) return; - + Common::List::iterator cur; for (Common::List::iterator d = _dirtyScreen.begin(); d != _dirtyScreen.end(); ++d) { - cur = d; + cur = d++; + do { - ++d; if (cur->intersects(*d)) - _dirtyScreen.erase(d); + d = _dirtyScreen.erase(d); + else ++d; } while (d != _dirtyScreen.end()); - - - // FIXME: this square-merging algorithm can be rather slow, and I don't think it - // benefits us *that* much. Maybe we should just stick to finding dirty squares that overlap. - - // d = cur; - // - // do { - // ++d; - // if ((cur->top == d->top && cur->bottom == d->bottom && (ABS(cur->left - d->right) < 10 || ABS(cur->right - d->left) < 10)) || - // (cur->left == d->left && cur->right == d->right && (ABS(cur->top - d->bottom) < 10 || ABS(cur->bottom - d->top) < 10))) { - // cur->extend(*d); - // _dirtyScreen.erase(d); - // } - // } while (d != _dirtyScreen.end()); - + d = cur; _vectorRenderer->copyFrame(_system, *d); } -- cgit v1.2.3 From daa32f77f87439e592105c21c5b6e80c2fadac62 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 13:32:18 +0000 Subject: Segfault in dirty rectangles is no longer a 'feature'. Fixed segfault with the last tab in config dialogs. svn-id: r33200 --- gui/ThemeRenderer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 2fb0f955ac..277adc8438 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -534,7 +534,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, if (active >= 0) { Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); const uint16 tabLeft = active * (tabWidth + tabOffset); - const uint16 tabRight = r.right - tabRect.right; + const uint16 tabRight = MAX(r.right - tabRect.right, 0); queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); queueDDText(kDDTabActive, tabRect, tabs[active]); } @@ -592,12 +592,12 @@ void ThemeRenderer::renderDirtyScreen() { Common::List::iterator cur; for (Common::List::iterator d = _dirtyScreen.begin(); d != _dirtyScreen.end(); ++d) { - cur = d++; + cur = d; do { + ++d; if (cur->intersects(*d)) - d = _dirtyScreen.erase(d); - else ++d; + d = _dirtyScreen.reverse_erase(d); } while (d != _dirtyScreen.end()); d = cur; -- cgit v1.2.3 From a9ab9c0189906229b7ec730fa78eeb18e966a9e1 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 13:33:32 +0000 Subject: Cleanup. svn-id: r33201 --- gui/ThemeRenderer.cpp | 2 ++ gui/ThemeRenderer.h | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 277adc8438..d31067fbfd 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -303,6 +303,7 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic DrawQueue q; q.type = type; q.area = r; + q.area.clip(_screen->w, _screen->h); q.dynData = dynamic; if (_buffering) { @@ -323,6 +324,7 @@ void ThemeRenderer::queueDDText(DrawData type, const Common::Rect &r, const Comm DrawQueueText q; q.type = type; q.area = r; + q.area.clip(_screen->w, _screen->h); q.text = text; q.colorId = colorId; q.align = align; diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index c54eaf3a1e..a43d13b6e3 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -429,9 +429,6 @@ protected: * Handles all the dirty squares in the list, merges and optimizes * them when possible and draws them to the screen. * Called from updateScreen() - * - * TODO: This function is partly implemented, but currently not used. - * Currently the whole frame is drawn to the screen. */ void renderDirtyScreen(); -- cgit v1.2.3 From 10dff40de64b9c9e8b136a556a3a4bb6f69bc098 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 17:39:30 +0000 Subject: Dirty screen handling, round three. svn-id: r33209 --- gui/ThemeRenderer.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index d31067fbfd..1ca3d4fcc4 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -592,18 +592,13 @@ void ThemeRenderer::renderDirtyScreen() { if (_dirtyScreen.empty()) return; - Common::List::iterator cur; - for (Common::List::iterator d = _dirtyScreen.begin(); d != _dirtyScreen.end(); ++d) { - cur = d; - - do { - ++d; - if (cur->intersects(*d)) - d = _dirtyScreen.reverse_erase(d); - } while (d != _dirtyScreen.end()); - - d = cur; - _vectorRenderer->copyFrame(_system, *d); + Common::List::const_iterator i, j; + for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) { + for (j = i; j != _dirtyScreen.end(); ++j) + if (j != i && i->intersects(*j)) + j = _dirtyScreen.reverse_erase(j); + + _vectorRenderer->copyFrame(_system, *i); } _dirtyScreen.clear(); -- cgit v1.2.3 From c5d673801177a6905114f724c229f802ca2756f3 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Jul 2008 20:07:53 +0000 Subject: Dirty rectangle handling, round four. :/ svn-id: r33216 --- common/rect.h | 10 ++++++++++ engines/drascula/talk.cpp | 2 +- engines/m4/converse.cpp | 4 ++-- engines/m4/resource.cpp | 2 +- engines/parallaction/objects.h | 2 +- gui/ThemeRenderer.cpp | 3 ++- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/common/rect.h b/common/rect.h index f71124434a..01a0a0d431 100644 --- a/common/rect.h +++ b/common/rect.h @@ -124,6 +124,16 @@ struct Rect { return contains(p.x, p.y); } + /*! @brief check if the given rect is _fully_ contained inside this rectangle + + @param r The rectangle to check + + @retur true if the given rect is inside, false otherwise + */ + bool contains(const Rect &r) const { + return (left < r.left) && (right > r.right) && (top < r.top) && (bottom > r.bottom); + } + /*! @brief check if given rectangle intersects with this rectangle @param r the rectangle to check diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 4d3187a0fd..a89c5ff734 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -60,7 +60,7 @@ void DrasculaEngine::talk_igor(int index, int talkerType) { int x_talk1[8] = { 56, 86, 116, 146, 176, 206, 236, 266 }; int x_talk3[4] = { 80, 102, 124, 146 }; int x_talk4[4] = { 119, 158, 197, 236 }; - int face; + int face = 0; int length = strlen(said); color_abc(kColorWhite); diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index 729af6c40f..024cd591f5 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -379,8 +379,8 @@ void Converse::loadConversation(const char *convName) { uint32 header = convS->readUint32LE(); uint32 size; uint32 chunk; - uint32 data; - uint32 i; + uint32 data = 0; + uint32 i = 0; ConvEntry* curEntry = NULL; ConvEntry* replyEntry = NULL; int32 currentWeightedEntry = -1; diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp index 57816b6600..5070a2b79c 100644 --- a/engines/m4/resource.cpp +++ b/engines/m4/resource.cpp @@ -310,7 +310,7 @@ const char *MADSResourceManager::getResourceFilename(const char *resourceName) { Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) { Common::File hagFile; - uint32 offset, size; + uint32 offset = 0, size = 0; // If the first character is a '@' then look for an external file diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h index afa6cc5ed5..c2c2c154b5 100644 --- a/engines/parallaction/objects.h +++ b/engines/parallaction/objects.h @@ -94,7 +94,7 @@ enum ZoneFlags { enum CommandFlags { - kFlagsAll = 0xFFFFFFFFU, + kFlagsAll = 0x7FFFFFFFU, kFlagsVisited = 1, kFlagsExit = 0x10000000, diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1ca3d4fcc4..0b02f88a2c 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -586,6 +586,7 @@ void ThemeRenderer::updateScreen() { } renderDirtyScreen(); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { @@ -595,7 +596,7 @@ void ThemeRenderer::renderDirtyScreen() { Common::List::const_iterator i, j; for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) { for (j = i; j != _dirtyScreen.end(); ++j) - if (j != i && i->intersects(*j)) + if (j != i && i->contains(*j)) j = _dirtyScreen.reverse_erase(j); _vectorRenderer->copyFrame(_system, *i); -- cgit v1.2.3 From b5086559b816f68506d33362566377443a1ff1d8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 23 Jul 2008 16:38:39 +0000 Subject: Font rendering overhaul. Work in progress. svn-id: r33247 --- graphics/VectorRenderer.cpp | 9 ---- graphics/VectorRenderer.h | 21 -------- gui/ThemeDefaultXML.cpp | 30 ++++++----- gui/ThemeParser.cpp | 48 ++++------------- gui/ThemeRenderer.cpp | 125 +++++++++++++++++++++++++++----------------- gui/ThemeRenderer.h | 91 +++++++++++++++++--------------- 6 files changed, 154 insertions(+), 170 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 639039fe28..adcd299811 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -75,15 +75,6 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui (this->*(step.drawingCall))(area, step); } -void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH) { - if (step.color.set) - setFgColor(step.color.r, step.color.g, step.color.b); - - drawString(step.font, text.c_str(), area, - !step.hasAlign ? alignH : step.alignHorizontal, - !step.hasAlign ? GUI::Theme::kTextAlignVTop : step.alignVertical); -} - int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) { int radius = 0; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index a5e80164be..8a020ebfad 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -39,20 +39,6 @@ namespace Graphics { class VectorRenderer; struct DrawStep; -struct TextStep { - struct { - uint8 r, g, b; - bool set; - } - color; /** text color */ - - GUI::Theme::TextAlign alignHorizontal; - GUI::Theme::TextAlignVertical alignVertical; - bool hasAlign; - char *text; - const Graphics::Font *font; -}; - struct DrawStep { struct { uint8 r, g, b; @@ -404,7 +390,6 @@ public: * @param step Pointer to a DrawStep struct. */ virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0); - virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH = GUI::Theme::kTextAlignLeft); /** * Copies the current surface to the system overlay @@ -422,8 +407,6 @@ public: */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; - virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) = 0; - virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; virtual void disableShadows() { _disableShadows = true; } @@ -595,10 +578,6 @@ public: src_ptr += src_pitch; } } - - virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) { - return RGBToColor(r, g, b); - } protected: diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 77a65cfdc6..d294f6b708 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -42,18 +42,20 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" - "" - "" - "" "" "" - "" - "" - "" + "" + "" + "" + "" "" "" + + "" + "" + "" "" "" @@ -68,12 +70,12 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" + "" "" "" @@ -95,7 +97,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" - "" + "" "" "" @@ -103,27 +105,27 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" - "" + "" "" "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 5a5a6e8af8..89f0595c67 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -160,10 +160,6 @@ bool ThemeParser::parserCallback_font() { if (!tNode->values.contains("type")) return parserError("Font definitions need a valid typename."); - - // TODO: set typename on the drawstep. - - Graphics::TextStep step; if (tNode->values.contains("horizontal_align") || tNode->values.contains("vertical_align")) return parserError("Font definitions cannot contain alignments."); @@ -181,13 +177,7 @@ bool ThemeParser::parserCallback_font() { return parserError("Cannot assign color in font definition."); } - step.color.r = red; - step.color.g = green; - step.color.b = blue; - step.color.set = true; - step.hasAlign = false; - - if (!_theme->addTextStep(tNode->values["id"], step)) + if (!_theme->addFont(tNode->values["id"], red, green, blue)) return parserError("Error when loading Font in theme engine."); return true; @@ -209,47 +199,29 @@ bool ThemeParser::parserCallback_text() { if (parentNode == 0 || parentNode->name != "drawdata") return parserError("Text Steps must be contained inside keys."); - Graphics::TextStep step; + GUI::Theme::TextAlign alignH; + GUI::Theme::TextAlignVertical alignV; if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false) return parserError("Text inside widgets requires proper alignment keys."); if (tNode->values["horizontal_align"] == "left") - step.alignHorizontal = GUI::Theme::kTextAlignLeft; + alignH = GUI::Theme::kTextAlignLeft; else if (tNode->values["horizontal_align"] == "right") - step.alignHorizontal = GUI::Theme::kTextAlignRight; + alignH = GUI::Theme::kTextAlignRight; else if (tNode->values["horizontal_align"] == "center") - step.alignHorizontal = GUI::Theme::kTextAlignCenter; + alignH = GUI::Theme::kTextAlignCenter; else return parserError("Invalid value for text alignment."); if (tNode->values["vertical_align"] == "top") - step.alignVertical = GUI::Theme::kTextAlignVTop; + alignV = GUI::Theme::kTextAlignVTop; else if (tNode->values["vertical_align"] == "center") - step.alignVertical = GUI::Theme::kTextAlignVCenter; + alignV = GUI::Theme::kTextAlignVCenter; else if (tNode->values["vertical_align"] == "bottom") - step.alignVertical = GUI::Theme::kTextAlignVBottom; + alignV = GUI::Theme::kTextAlignVBottom; else return parserError("Invalid value for text alignment."); - int red, green, blue; - - if (tNode->values.contains("color")) { - - if (_palette.contains(tNode->values["color"])) - getPaletteColor(tNode->values["color"], red, green, blue); - else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue)) - return parserError("Error when parsing color value for text definition"); - - } else { - return parserError("Cannot assign color for text drawing."); - } - - step.color.r = red; - step.color.g = green; - step.color.b = blue; - step.color.set = true; - step.hasAlign = true; - - return _theme->addTextStep(parentNode->values["id"], step); + return _theme->addTextData(parentNode->values["id"], tNode->values["font"], alignH, alignV); } bool ThemeParser::parserCallback_renderInfo() { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 0b02f88a2c..1123bf1816 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -44,6 +44,7 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDSpecialColorBackground, "special_bg", true, kDDNone}, {kDDPlainColorBackground, "plain_bg", true, kDDNone}, {kDDDefaultBackground, "default_bg", true, kDDNone}, + {kDDTextSelectionBackground, "text_selection", false, kDDNone}, {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, @@ -72,6 +73,13 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDSeparator, "separator", true, kDDNone}, }; +const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { + {kTextDataDefault, "text_default"}, + {kTextDataHover, "text_hover"}, + {kTextDataDisabled, "text_disabled"}, + {kTextDataInverted, "text_inverted"} +}; + ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), @@ -83,6 +91,10 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : for (int i = 0; i < kDrawDataMAX; ++i) { _widgets[i] = 0; } + + for (int i = 0; i < kTextDataMAX; ++i) { + _texts[i] = 0; + } _graphicsMode = mode; setGraphicsMode(_graphicsMode); @@ -111,14 +123,6 @@ bool ThemeRenderer::init() { Theme::loadTheme(_configFile, false, true); } - if (_fontName.empty()) { - if (_screen->w >= 400 && _screen->h >= 300) { - _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } - } - return true; } @@ -195,29 +199,43 @@ void ThemeRenderer::addDrawStep(const Common::String &drawDataId, Graphics::Draw _widgets[id]->_steps.push_back(step); } -bool ThemeRenderer::addTextStep(const Common::String &drawDataId, Graphics::TextStep step) { +bool ThemeRenderer::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) { DrawData id = getDrawDataId(drawDataId); + TextData textId = getTextDataId(textDataId); - step.font = 0; + if (id == -1 || textId == -1 || !_widgets[id]) + return false; - if (id != -1) { - assert(_widgets[id] != 0); - if (_widgets[id]->_hasText == true) - return false; + _widgets[id]->_textDataId = textId; + _widgets[id]->_textAlignH = alignH; + _widgets[id]->_textAlignV = alignV; - _widgets[id]->_textStep = step; - _widgets[id]->_hasText = true; + return true; +} + +bool ThemeRenderer::addFont(const Common::String &fontId, int r, int g, int b) { + TextData textId = getTextDataId(fontId); + + if (textId == -1) + return false; + + if (_texts[textId] != 0) + return false; + + _texts[textId] = new TextDrawData; + + // TODO: Allow the user to specify the font he wants, instead of choosing based on resolution + if (_screen->w >= 400 && _screen->h >= 300) { + _texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); } else { - if (drawDataId == "default") { - _texts[kTextColorDefault] = step; - } else if (drawDataId == "hover") { - _texts[kTextColorHover] = step; - } else if (drawDataId == "disabled") { - _texts[kTextColorDisabled] = step; - } else return false; + _texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); } - + + _texts[textId]->_color.r = r; + _texts[textId]->_color.g = g; + _texts[textId]->_color.b = b; return true; + } bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { @@ -230,7 +248,7 @@ bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { _widgets[data_id]->_cached = cached; _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; _widgets[data_id]->_surfaceCache = 0; - _widgets[data_id]->_hasText = false; + _widgets[data_id]->_textDataId = -1; return true; } @@ -320,14 +338,19 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } } -void ThemeRenderer::queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, TextColor colorId, TextAlign align) { +void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, + bool elipsis, TextAlign alignH, TextAlignVertical alignV) { + + if (_texts[type] == 0) + return; + DrawQueueText q; q.type = type; q.area = r; q.area.clip(_screen->w, _screen->h); q.text = text; - q.colorId = colorId; - q.align = align; + q.alignH = alignH; + q.alignV = alignV; if (_buffering) { _textQueue.push_back(q); @@ -359,19 +382,11 @@ void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { } void ThemeRenderer::drawDDText(const DrawQueueText &q) { - if (q.type == kDDNone) { + if (q.type != kTextDataInverted) restoreBackground(q.area); - if (_texts[q.colorId].font == 0) - _texts[q.colorId].font = _font; - - _vectorRenderer->textStep(q.text, q.area, _texts[q.colorId], q.align); - } else { - if (_widgets[q.type]->_textStep.font == 0) - _widgets[q.type]->_textStep.font = _font; - - _vectorRenderer->textStep(q.text, q.area, _widgets[q.type]->_textStep); - } + _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); + _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV); addDirtyRect(q.area); } @@ -405,7 +420,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, dd = kDDButtonDisabled; queueDD(dd, r); - queueDDText(dd, r, str); + queueDDText(getTextData(dd), r, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -420,17 +435,18 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st return; Common::Rect r2 = r; + DrawData dd = checked ? kDDCheckboxEnabled : kDDCheckboxDisabled; const int checkBoxSize = MIN((int)r.height(), getFontHeight()); r2.bottom = r2.top + checkBoxSize; r2.right = r2.left + checkBoxSize; - queueDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); + queueDD(dd, r2); r2.left = r2.right + checkBoxSize; r2.right = r.right; - queueDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); + queueDDText(getTextData(dd), r2, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -484,7 +500,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String if (!sel.empty()) { Common::Rect text(r.left, r.top, r.right - 16, r.bottom); - queueDDText(dd, text, sel); + queueDDText(getTextData(dd), text, sel, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } } @@ -530,7 +546,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); queueDD(kDDTabInactive, tabRect); - queueDDText(kDDTabInactive, tabRect, tabs[i]); + queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); } if (active >= 0) { @@ -538,15 +554,30 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const uint16 tabLeft = active * (tabWidth + tabOffset); const uint16 tabRight = MAX(r.right - tabRect.right, 0); queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); - queueDDText(kDDTabActive, tabRect, tabs[active]); + queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); } } void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { if (!_initOk) return; - - queueDDText(kDDNone, r, str, getTextColor(state), align); + + if (inverted) + queueDD(kDDTextSelectionBackground, r); + + switch (state) { + case kStateDisabled: + queueDDText(inverted ? kTextDataInverted : kTextDataDisabled, r, str, useEllipsis); + break; + + case kStateHighlight: + queueDDText(inverted ? kTextDataInverted : kTextDataHover, r, str, useEllipsis); + break; + + case kStateEnabled: + queueDDText(inverted ? kTextDataInverted : kTextDataDefault, r, str, useEllipsis); + break; + } } void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index a43d13b6e3..ab4f5cb890 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -42,13 +42,21 @@ namespace GUI { struct WidgetDrawData; struct DrawDataInfo; +struct TextDrawData { + const Graphics::Font *_fontPtr; + + struct { + uint8 r, g, b; + } _color; +}; + struct WidgetDrawData { /** List of all the steps needed to draw this widget */ Common::List _steps; - /** Single step that defines the text shown inside the widget */ - Graphics::TextStep _textStep; - bool _hasText; + int _textDataId; + GUI::Theme::TextAlign _textAlignH; + GUI::Theme::TextAlignVertical _textAlignV; /** Extra space that the widget occupies when it's drawn. E.g. when taking into account rounded corners, drop shadows, etc @@ -97,6 +105,7 @@ protected: kDDSpecialColorBackground, kDDPlainColorBackground, kDDDefaultBackground, + kDDTextSelectionBackground, kDDWidgetBackgroundDefault, kDDWidgetBackgroundSmall, @@ -149,21 +158,28 @@ protected: uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/ }; - enum TextColor { - kTextColorNone = -1, - kTextColorDefault, - kTextColorHover, - kTextColorDisabled, - kTextColorInverted, - kTextColorMAX + enum TextData { + kTextDataNone = -1, + kTextDataDefault = 0, + kTextDataHover, + kTextDataDisabled, + kTextDataInverted, + kTextDataMAX }; + static const struct TextDataInfo { + TextData id; + const char *name; + } kTextDataDefaults[]; + struct DrawQueueText { - DrawData type; + TextData type; Common::Rect area; Common::String text; - TextColor colorId; - TextAlign align; + + GUI::Theme::TextAlign alignH; + GUI::Theme::TextAlignVertical alignV; + bool elipsis; }; public: @@ -312,6 +328,14 @@ public: return kDDNone; } + + TextData getTextDataId(const Common::String &name) { + for (int i = 0; i < kTextDataMAX; ++i) + if (name.compareToIgnoreCase(kTextDataDefaults[i].name) == 0) + return kTextDataDefaults[i].id; + + return kTextDataNone; + } /** * Interface for ThemeParser class: Parsed DrawSteps are added via this function. @@ -334,12 +358,13 @@ public: * @param cached Whether this DD set will be cached beforehand. */ bool addDrawData(const Common::String &data, bool cached); + bool addFont(const Common::String &fontName, int r, int g, int b); /** * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the * new Font API is in place. */ - bool addTextStep(const Common::String &drawDataId, Graphics::TextStep step); + bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV); /** Interface to the new Theme XML parser */ ThemeParser *parser() { @@ -414,6 +439,11 @@ protected: delete _widgets[i]; _widgets[i] = 0; } + + for (int i = 0; i < kTextDataMAX; ++i) { + delete _texts[i]; + _texts[i] = 0; + } _themeOk = false; } @@ -461,14 +491,9 @@ protected: _screen = 0; } } - - /** - * Checks if the given widget type has a Text drawing step associated to it. - * - * @param type DrawData type of the widget. - */ - bool hasWidgetText(DrawData type) { - return (_widgets[type] != 0 && _widgets[type]->_hasText); + + TextData getTextData(DrawData ddId) { + return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone; } /** @@ -523,8 +548,8 @@ protected: * This function is called from all the Widget Drawing methods. */ inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); - inline void queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, - TextColor colorId = kTextColorNone, TextAlign align = kTextAlignLeft); + inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, + bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop); /** * DEBUG: Draws a white square around the given position and writes the given next to it. @@ -547,22 +572,6 @@ protected: */ int getTabSpacing() const { return 0; } int getTabPadding() const { return 3; } - - /** - * Translates a WidgetStateInfo of a Text widget to the actual font color value. - */ - TextColor getTextColor(WidgetStateInfo state) { - switch (state) { - case kStateDisabled: - return kTextColorDisabled; - - case kStateHighlight: - return kTextColorHover; - - default: - return kTextColorDefault; - } - } OSystem *_system; /** Global system object. */ @@ -597,7 +606,7 @@ protected: WidgetDrawData *_widgets[kDrawDataMAX]; /** Array of all the text fonts that can be drawn. */ - Graphics::TextStep _texts[kTextColorMAX]; + TextDrawData *_texts[kTextDataMAX]; /** List of all the dirty screens that must be blitted to the overlay. */ Common::List _dirtyScreen; -- cgit v1.2.3 From 4135134aea6dd03dcd3c327fb7001d24dbbd4f49 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 23 Jul 2008 17:57:11 +0000 Subject: Text renderin overhaul finished. svn-id: r33251 --- gui/ThemeDefaultXML.cpp | 6 +++--- gui/ThemeParser.cpp | 8 +++++++- gui/ThemeRenderer.cpp | 42 ++++++++++++++++++++++++------------------ gui/ThemeRenderer.h | 3 ++- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index d294f6b708..ba7689567e 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -48,13 +48,13 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" - "" + "" "" "" "" - "" + "" "" "" @@ -90,7 +90,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" "" - "" + "" "" diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 89f0595c67..66750b8c1a 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -204,6 +204,9 @@ bool ThemeParser::parserCallback_text() { if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false) return parserError("Text inside widgets requires proper alignment keys."); + + if (tNode->values.contains("font") == false) + return parserError("Text definitions must include a valid Font identifier."); if (tNode->values["horizontal_align"] == "left") alignH = GUI::Theme::kTextAlignLeft; @@ -221,7 +224,10 @@ bool ThemeParser::parserCallback_text() { alignV = GUI::Theme::kTextAlignVBottom; else return parserError("Invalid value for text alignment."); - return _theme->addTextData(parentNode->values["id"], tNode->values["font"], alignH, alignV); + if (!_theme->addTextData(parentNode->values["id"], tNode->values["font"], alignH, alignV)) + return parserError("Error when adding Text Data for '%s'.", parentNode->values["id"].c_str()); + + return true; } bool ThemeParser::parserCallback_renderInfo() { diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1123bf1816..df21769b8b 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -101,6 +101,12 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : loadConfigFile("classic"); + if (_screen->w >= 400 && _screen->h >= 300) { + _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + } else { + _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + } + _initOk = true; _themeName = themeName; } @@ -225,11 +231,7 @@ bool ThemeRenderer::addFont(const Common::String &fontId, int r, int g, int b) { _texts[textId] = new TextDrawData; // TODO: Allow the user to specify the font he wants, instead of choosing based on resolution - if (_screen->w >= 400 && _screen->h >= 300) { - _texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } + _texts[textId]->_fontPtr = _font; _texts[textId]->_color.r = r; _texts[textId]->_color.g = g; @@ -338,7 +340,7 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } } -void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, +void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, bool elipsis, TextAlign alignH, TextAlignVertical alignV) { if (_texts[type] == 0) @@ -351,6 +353,7 @@ void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Comm q.text = text; q.alignH = alignH; q.alignV = alignV; + q.restoreBg = restoreBg; if (_buffering) { _textQueue.push_back(q); @@ -382,7 +385,7 @@ void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { } void ThemeRenderer::drawDDText(const DrawQueueText &q) { - if (q.type != kTextDataInverted) + if (q.restoreBg) restoreBackground(q.area); _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); @@ -420,7 +423,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, dd = kDDButtonDisabled; queueDD(dd, r); - queueDDText(getTextData(dd), r, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { @@ -446,7 +449,7 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st r2.left = r2.right + checkBoxSize; r2.right = r.right; - queueDDText(getTextData(dd), r2, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + queueDDText(getTextData(dd), r2, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -500,7 +503,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String if (!sel.empty()) { Common::Rect text(r.left, r.top, r.right - 16, r.bottom); - queueDDText(getTextData(dd), text, sel, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); } } @@ -546,7 +549,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); queueDD(kDDTabInactive, tabRect); - queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); + queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); } if (active >= 0) { @@ -554,28 +557,31 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const uint16 tabLeft = active * (tabWidth + tabOffset); const uint16 tabRight = MAX(r.right - tabRect.right, 0); queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); - queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); + queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); } } void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!_initOk) + if (!ready()) return; - if (inverted) + if (inverted) { queueDD(kDDTextSelectionBackground, r); - + queueDDText(kTextDataInverted, r, str, false, useEllipsis); + return; + } + switch (state) { case kStateDisabled: - queueDDText(inverted ? kTextDataInverted : kTextDataDisabled, r, str, useEllipsis); + queueDDText(kTextDataDisabled, r, str, true, useEllipsis); break; case kStateHighlight: - queueDDText(inverted ? kTextDataInverted : kTextDataHover, r, str, useEllipsis); + queueDDText(kTextDataHover, r, str, true, useEllipsis); break; case kStateEnabled: - queueDDText(inverted ? kTextDataInverted : kTextDataDefault, r, str, useEllipsis); + queueDDText(kTextDataDefault, r, str, true, useEllipsis); break; } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index ab4f5cb890..6c4067e00f 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -180,6 +180,7 @@ protected: GUI::Theme::TextAlign alignH; GUI::Theme::TextAlignVertical alignV; bool elipsis; + bool restoreBg; }; public: @@ -548,7 +549,7 @@ protected: * This function is called from all the Widget Drawing methods. */ inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); - inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, + inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop); /** -- cgit v1.2.3 From 7f0aa32d51878f83d0af941561408b4b727a4a5e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 23 Jul 2008 22:32:00 +0000 Subject: Improved text handling. Fixed About dialog scroll-out text. svn-id: r33257 --- graphics/VectorRenderer.cpp | 4 ++-- graphics/VectorRenderer.h | 4 ++-- gui/ThemeRenderer.cpp | 18 ++++++++---------- gui/ThemeRenderer.h | 3 ++- gui/about.cpp | 6 +++--- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index adcd299811..178f760751 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -275,7 +275,7 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, - GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) { + GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax) { int offset = 0; @@ -291,7 +291,7 @@ drawString(const Graphics::Font *font, const Common::String &text, const Common: break; } - font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, 0, false); + font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, deltax, false); } /** LINES **/ diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 8a020ebfad..f659626bbf 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -407,7 +407,7 @@ public: */ virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; - virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax) = 0; virtual void disableShadows() { _disableShadows = true; } virtual void enableShadows() { _disableShadows = false; } @@ -486,7 +486,7 @@ public: void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, - GUI::Theme::TextAlignVertical alignV); + GUI::Theme::TextAlignVertical alignV, int deltax); /** * @see VectorRenderer::setFgColor() diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index df21769b8b..8c111741b9 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -270,10 +270,7 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { for (int i = 0; i < kDrawDataMAX; ++i) { if (_widgets[i] == 0) { -#ifdef REQUIRE_ALL_DD_SETS - warning("Error when parsing custom theme '%s': Missing data assets.", themeName.c_str()); - return false; -#endif + warning("Missing data asset: '%s'", kDrawDataDefaults[i].name); } else { calcBackgroundOffset((DrawData)i); @@ -341,7 +338,7 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, TextAlign alignH, TextAlignVertical alignV) { + bool elipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { if (_texts[type] == 0) return; @@ -354,6 +351,7 @@ void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Comm q.alignH = alignH; q.alignV = alignV; q.restoreBg = restoreBg; + q.deltax = deltax; if (_buffering) { _textQueue.push_back(q); @@ -389,7 +387,7 @@ void ThemeRenderer::drawDDText(const DrawQueueText &q) { restoreBackground(q.area); _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); - _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV); + _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax); addDirtyRect(q.area); } @@ -567,21 +565,21 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W if (inverted) { queueDD(kDDTextSelectionBackground, r); - queueDDText(kTextDataInverted, r, str, false, useEllipsis); + queueDDText(kTextDataInverted, r, str, false, useEllipsis, align); return; } switch (state) { case kStateDisabled: - queueDDText(kTextDataDisabled, r, str, true, useEllipsis); + queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align); break; case kStateHighlight: - queueDDText(kTextDataHover, r, str, true, useEllipsis); + queueDDText(kTextDataHover, r, str, true, useEllipsis, align); break; case kStateEnabled: - queueDDText(kTextDataDefault, r, str, true, useEllipsis); + queueDDText(kTextDataDefault, r, str, true, useEllipsis, align); break; } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 6c4067e00f..1e3bec55b1 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -181,6 +181,7 @@ protected: GUI::Theme::TextAlignVertical alignV; bool elipsis; bool restoreBg; + int deltax; }; public: @@ -550,7 +551,7 @@ protected: */ inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop); + bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); /** * DEBUG: Draws a white square around the given position and writes the given next to it. diff --git a/gui/about.cpp b/gui/about.cpp index 758f3ee6a7..71bf877d21 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -203,7 +203,7 @@ void AboutDialog::close() { } void AboutDialog::drawDialog() { - g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h)); +// g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h)); Dialog::drawDialog(); // Draw text @@ -265,10 +265,10 @@ void AboutDialog::drawDialog() { while (*str && *str == ' ') str++; - g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, false, 0, false); + if (y > _y && y + g_gui.theme()->getFontHeight() < _y + _h) + g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, false, 0, false); y += _lineHeight; } - g_gui.theme()->resetDrawArea(); } void AboutDialog::handleTickle() { -- cgit v1.2.3 From 7c562788968060e7fe764b9946384fa88cdd4de4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 24 Jul 2008 18:40:36 +0000 Subject: Scrollbars. Work in progress. svn-id: r33264 --- gui/ThemeDefaultXML.cpp | 22 ++++++++++++++++++++-- gui/ThemeRenderer.cpp | 26 +++++++++++++++++++++++--- gui/ThemeRenderer.h | 5 ++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index ba7689567e..64641b13a3 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -54,7 +54,7 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" @@ -66,7 +66,25 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" + "" + + "" + "" + "" + + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 8c111741b9..52c4e895a6 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -64,7 +64,12 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDTabInactive, "tab_inactive", true, kDDNone}, {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, - {kDDScrollbarHandle, "scrollbar_handle", false, kDDScrollbarBase}, + + {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone}, + {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle}, + + {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone}, + {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase}, {kDDPopUpIdle, "popup_idle", true, kDDNone}, {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, @@ -461,12 +466,27 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo queueDD(kDDSliderFull, r2); } -void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState sb_state, WidgetStateInfo state) { +void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { if (!ready()) return; queueDD(kDDScrollbarBase, r); - // TODO: Need to find a scrollbar in the GUI for testing... :p + + Common::Rect r2 = r; + const int buttonExtra = (r.width() * 120) / 100; + + r2.bottom = r2.top + buttonExtra; + queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2); + + r2.translate(0, r.height() - r2.height()); + queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2); + + r2 = r; + r2.left += 1; + r2.right -= 1; + r2.top += sliderY; + r2.bottom = r2.top + sliderHeight - 1; + queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); } void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 1e3bec55b1..836f7d05fd 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -125,7 +125,10 @@ protected: kDDTabInactive, kDDScrollbarBase, - kDDScrollbarHandle, + kDDScrollbarButtonIdle, + kDDScrollbarButtonHover, + kDDScrollbarHandleIdle, + kDDScrollbarHandleHover, kDDPopUpIdle, kDDPopUpHover, -- cgit v1.2.3 From 49b4df308ff7beb771531598c074535241e547ca Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 25 Jul 2008 00:59:53 +0000 Subject: Fixed triangle drawing. A bit. svn-id: r33268 --- graphics/VectorRenderer.cpp | 24 +++++++++++++++--------- graphics/VectorRenderer.h | 1 + gui/ThemeDefaultXML.cpp | 4 ++-- gui/ThemeRenderer.cpp | 4 ++-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 178f760751..6bbb84acaa 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -498,9 +498,9 @@ void VectorRendererSpec:: drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { // Awesome hack: the AA messes up the last pixel triangles if their width is even // ...fix the width instead of fixing the AA :p - if (w % 2 == 0) { - w++; h++; - } + // if (w % 2 == 0) { + // w++; h++; + // } if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) return; @@ -517,16 +517,22 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { return; color = _fgColor; } + + if (Base::_dynamicData != 0) + orient = (TriangleOrientation)Base::_dynamicData; + + int newW = w * 3 / 4; + if (newW % 2) newW++; switch(orient) { case kTriangleUp: case kTriangleDown: -#ifdef VECTOR_RENDERER_FAST_TRIANGLES - if (w == h) - drawTriangleFast(x, y, w, (orient == kTriangleDown), color, Base::_fillMode); - else -#endif - drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); +// #ifdef VECTOR_RENDERER_FAST_TRIANGLES + // if (w == h) + drawTriangleFast(x + (w / 2) - w * 3 / 8, y + w / 4, newW, (orient == kTriangleDown), color, Base::_fillMode); + // else +// #endif + // drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); break; case kTriangleLeft: diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index f659626bbf..88072da923 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -107,6 +107,7 @@ public: }; enum TriangleOrientation { + kTriangleAuto = 0, kTriangleUp, kTriangleDown, kTriangleLeft, diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 64641b13a3..2e3c3b1270 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -79,12 +79,12 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" + "" "" "" diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 52c4e895a6..403fecf12e 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -476,10 +476,10 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider const int buttonExtra = (r.width() * 120) / 100; r2.bottom = r2.top + buttonExtra; - queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2); + queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); r2.translate(0, r.height() - r2.height()); - queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2); + queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); r2 = r; r2.left += 1; -- cgit v1.2.3 From 1c0bceecd583efd3f852213916fdec832fa5e5c4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 25 Jul 2008 01:14:38 +0000 Subject: Fixed warning: kTriangleAuto not handled in switch svn-id: r33269 --- graphics/VectorRenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 6bbb84acaa..ce8868241b 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -537,6 +537,7 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { case kTriangleLeft: case kTriangleRight: + case kTriangleAuto: break; } -- cgit v1.2.3 From 078ac062e764b9b6a46110861f924e3df6328f20 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 25 Jul 2008 11:13:47 +0000 Subject: More triangle work svn-id: r33286 --- graphics/VectorRenderer.cpp | 16 +++------------- gui/ThemeDefaultXML.cpp | 4 ++-- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index ce8868241b..352ab971a3 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -521,18 +521,13 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { if (Base::_dynamicData != 0) orient = (TriangleOrientation)Base::_dynamicData; - int newW = w * 3 / 4; + int newW = w / 2; if (newW % 2) newW++; switch(orient) { case kTriangleUp: case kTriangleDown: -// #ifdef VECTOR_RENDERER_FAST_TRIANGLES - // if (w == h) - drawTriangleFast(x + (w / 2) - w * 3 / 8, y + w / 4, newW, (orient == kTriangleDown), color, Base::_fillMode); - // else -// #endif - // drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), color, Base::_fillMode); + drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), color, Base::_fillMode); break; case kTriangleLeft: @@ -543,12 +538,7 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { if (Base::_strokeWidth > 0) if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { -#ifdef VECTOR_RENDERER_FAST_TRIANGLES - if (w == h) - drawTriangleFast(x, y, w, (orient == kTriangleDown), _fgColor, kFillDisabled); - else -#endif - drawTriangleVertAlg(x, y, w, h, (orient == kTriangleDown), _fgColor, kFillDisabled); + drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), _fgColor, kFillDisabled); } } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 2e3c3b1270..97880dbdb2 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -107,14 +107,14 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" "" - "" + "" "" "" -- cgit v1.2.3 From e8d15277465c850fbad56b7ee3757e7b5cee0b2a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 26 Jul 2008 22:58:02 +0000 Subject: Convolution filters for the vector renderer. Pretty cool. svn-id: r33319 --- graphics/VectorRenderer.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ graphics/VectorRenderer.h | 26 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 352ab971a3..a708d5ac1f 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -50,6 +50,15 @@ VectorRenderer *createRenderer(int mode) { } } +const VectorRenderer::ConvolutionDataSet VectorRenderer::_convolutionData[VectorRenderer::kConvolutionMAX] = { + { {{1, 1, 1}, {1, 8, 1}, {1, 1, 1}}, 16, 0 }, // soft blur matrix + { {{2, 2, 2}, {2, 2, 2}, {2, 2, 2}}, 18, 0 }, // hard blur matrix + { {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}}, 16, 0 }, // gaussian blur matrix + { {{2, 0, 0}, {0, -1, 0}, {0, 0, -1}}, 1, 127}, // emboss matrix + { {{-1, -1, -1}, {-1, 9, -1}, {-1, -1, -1}}, 1, 0}, // sharpen matrix + { {{1, 1, 1}, {1, -7, 1}, {1, 1, 1}}, 1, 0} // edge find matrix +}; + /******************************************************************** * DRAWSTEP handling functions ********************************************************************/ @@ -159,6 +168,39 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & /******************************************************************** * MISCELANEOUS functions ********************************************************************/ +template +void VectorRendererSpec:: +areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset) { + PixelType *ptr = 0; + int newR, newG, newB; + uint8 r, g, b; + int yVal; + + for (int y = area.top; y < area.bottom; ++y) { + for (int x = area.left; x < area.right; ++x) { + for (int j = 0; j < 3; ++j) { + yVal = MIN(MAX(y - 1 + j, 0), area.bottom - 1); + + for (int i = 0; i < 3; ++i) { + ptr = (PixelType *)Base::_activeSurface->getBasePtr(MIN(MAX(x - 1 + j, 0), area.right - 1), yVal); + colorToRGB((uint32)*ptr, r, g, b); + + newR += r * filter[j][i]; + newG += g * filter[j][i]; + newB += b * filter[j][i]; + } + } + + newR = (newR / filterDiv) + offset; + newG = (newG / filterDiv) + offset; + newB = (newB / filterDiv) + offset; + + ptr = (PixelType *)Base::_activeSurface->getBasePtr(x, y); + *ptr = RGBToColor(CLIP(newR, 0, 255), CLIP(newG, 0, 255), CLIP(newB, 0, 255)); + } + } +} + /** Fixed point SQUARE ROOT **/ inline uint32 fp_sqroot(uint32 x) { register uint32 root, remHI, remLO, testDIV, count; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 88072da923..8a02d7fc21 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -113,6 +113,22 @@ public: kTriangleLeft, kTriangleRight }; + + enum ConvolutionData { + kConvolutionSoftBlur, + kConvolutionHardBlur, + kConvolutionGaussianBlur, + kConvolutionEmboss, + kConvolutionSharpen, + kConvolutionEdgeDetect, + kConvolutionMAX + }; + + struct ConvolutionDataSet { + int matrix[3][3]; + int divisor; + int offset; + }; /** * Draws a line by considering the special cases for optimization. @@ -412,6 +428,12 @@ public: virtual void disableShadows() { _disableShadows = true; } virtual void enableShadows() { _disableShadows = false; } + + virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset) = 0; + + virtual void applyConvolutionMatrix(const ConvolutionData id, const Common::Rect &area) { + areaConvolution(area, _convolutionData[id].matrix, _convolutionData[id].divisor, _convolutionData[id].offset); + } protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -425,6 +447,8 @@ protected: int _gradientFactor; /** Multiplication factor of the active gradient */ int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */ + + static const ConvolutionDataSet _convolutionData[kConvolutionMAX]; }; /** @@ -776,6 +800,8 @@ protected: } while (--n > 0); } } + + virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ -- cgit v1.2.3 From e7959952bbd2256fc83f0ca2f1c0b498e313617e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Jul 2008 13:33:32 +0000 Subject: Rewrote most of the XML parser class. Added support for defining the XML layout when parsing, allows for safer parsing. Updated all the documentation regarding the usage of the XMLParser class. svn-id: r33447 --- common/xmlparser.cpp | 35 +++++++++- common/xmlparser.h | 186 ++++++++++++++++++++++++++++++++++++++++++++------- gui/ThemeParser.cpp | 182 ++++++++++--------------------------------------- gui/ThemeParser.h | 109 +++++++++++++++++++++++++----- 4 files changed, 326 insertions(+), 186 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index d0c89a9d3e..030b5b9491 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -84,6 +84,27 @@ bool XMLParser::parserError(const char *errorString, ...) { bool XMLParser::parseActiveKey(bool closed) { bool ignore = false; + assert(_activeKey.empty() == false); + + ParserNode *key = _activeKey.top(); + XMLKeyLayout *layout = (_activeKey.size() == 1) ? _XMLkeys : getParentNode(key)->layout; + + if (layout->children.contains(key->name) == false) + return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str()); + + key->layout = layout->children[key->name]; + + Common::StringMap localMap = key->values; + + for (Common::List::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) { + if (localMap.contains(i->name)) + localMap.erase(i->name); + else if (i->required) + return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); + } + + if (localMap.empty() == false) + return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); // check if any of the parents must be ignored. // if a parent is ignored, all children are too. @@ -92,7 +113,13 @@ bool XMLParser::parseActiveKey(bool closed) { ignore = true; } - if (ignore == false && keyCallback(_activeKey.top()->name) == false) { + if (ignore == false && keyCallback(key) == false) { + // HACK: People may be stupid and overlook the fact that + // when keyCallback() fails, a parserError() must be set. + // We set it manually in that case. + if (_state != kParserError) + parserError("Unhandled exception when parsing '%s' key.", key->name.c_str()); + return false; } @@ -133,6 +160,9 @@ bool XMLParser::parse() { if (_text.ready() == false) return parserError("XML stream not ready for reading."); + + if (_XMLkeys == 0) + buildLayout(); cleanup(); @@ -186,6 +216,7 @@ bool XMLParser::parse() { node->name = _token; node->ignore = false; node->depth = _activeKey.size(); + node->layout = 0; _activeKey.push(node); } @@ -194,7 +225,7 @@ bool XMLParser::parse() { case kParserNeedPropertyName: if (activeClosure) { - if (!closedKeyCallback(_activeKey.top()->name)) { + if (!closedKeyCallback(_activeKey.top())) { parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str()); break; } diff --git a/common/xmlparser.h b/common/xmlparser.h index 4c77696482..221d382a70 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -38,6 +38,125 @@ #include "common/stack.h" namespace Common { + +/*********************************************** + **** XMLParser.cpp/h -- Generic XML Parser **** + *********************************************** + + This is a simple implementation of a generic parser which is able to + interpret a subset of the XML language. + + The XMLParser class is virtual, and must be derived into a child class, + called a Custom Parser Class, which will manage the parsed data for your + specific needs. + + Custom Parser Classes have two basic requirements: + They must inherit directly the XMLParser class, and they must define the + parsing layout of the XML file. + + Declaring the XML layout is done with the help of the CUSTOM_XML_PARSER() + macro: this macro must appear once inside the Custom Parser Class declaration, + and takes a single parameter, the name of the Custom Parser Class. + + The macro must be followed by the actual layout of the XML files to be parsed, + and closed with the PARSER_END() macro. The layout of XML files is defined by + the use of 3 helper macros: XML_KEY(), KEY_END() and XML_PROP(). + + Here's a sample of its usage: + + =========== =========== =========== =========== =========== =========== + + 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() + KEY_END() + } PARSER_END() + + =========== =========== =========== =========== =========== =========== + + The XML_KEY() macro takes a single argument, the name of the expected key. + Inside the scope of each key, you may define properties for the given key + with the XML_PROP() macro, which takes as parameters the name of the property + and whether it's optional or required. You might also define the contained + children keys, using the XML_KEY() macro again. + The scope of a XML key is closed with the KEY_END() macro. + + As an example, the following XML layout: + + XML_KEY(palette) + XML_KEY(color) + XML_PROP(name, true) + XML_PROP(rgb, true) + XML_PROP(optional_param, false) + KEY_END() + KEY_END() + + will expect to parse a syntax like this: + + + + + + + TODO: documentation on callbacks + + Note that the XML parser doesn't take into account the actual order of the keys and + properties in the XML layout definition, only its layout and relationships. +*/ + +#define XML_KEY(keyName) {\ + lay = new XMLKeyLayout; \ + lay->custom = new kLocalParserName::CustomParserCallback; \ + ((kLocalParserName::CustomParserCallback*)(lay->custom))->callback = (&kLocalParserName::parserCallback_##keyName); \ + layout.top()->children[#keyName] = lay; \ + layout.push(lay); + +#define KEY_END() layout.pop(); } + +#define XML_PROP(propName, req) {\ + prop.name = #propName; \ + prop.required = req; \ + layout.top()->properties.push_back(prop); }\ + +#define CUSTOM_XML_PARSER(parserName) \ + protected: \ + typedef bool (parserName::*ParserCallback)(ParserNode *node); \ + typedef parserName kLocalParserName; \ + struct CustomParserCallback { ParserCallback callback; }; \ + bool keyCallback(ParserNode *node) {return (this->*(((parserName::CustomParserCallback*)(node->layout->custom))->callback))(node);}\ + virtual void buildLayout() { \ + Common::Stack layout; \ + XMLKeyLayout *lay = 0; \ + XMLKeyLayout::XMLKeyProperty prop; \ + _XMLkeys = new XMLKeyLayout; \ + layout.push(_XMLkeys); + +#define PARSER_END() layout.clear(); } class XMLStream { protected: @@ -91,7 +210,7 @@ public: /** * Parser constructor. */ - XMLParser() {} + XMLParser() : _XMLkeys(0) {} virtual ~XMLParser() { while (!_activeKey.empty()) @@ -109,6 +228,22 @@ public: kParserError }; + + struct XMLKeyLayout; + + typedef Common::HashMap ChildMap; + + /** nested struct representing the layout of the XML file */ + struct XMLKeyLayout { + void *custom; + struct XMLKeyProperty { + Common::String name; + bool required; + }; + + Common::List properties; + ChildMap children; + } *_XMLkeys; /** Struct representing a parsed node */ struct ParserNode { @@ -116,6 +251,7 @@ public: Common::StringMap values; bool ignore; int depth; + XMLKeyLayout *layout; }; /** @@ -178,33 +314,38 @@ public: } protected: + /** - * The keycallback function must be overloaded by inheriting classes - * to implement parser-specific functions. + * The buildLayout function builds the layout for the parser to use + * based on a series of helper macros. This function is automatically + * generated by the CUSTOM_XML_PARSER() macro on custom parsers. * - * This function is called everytime a key has successfully been parsed. - * The keyName parameter contains the name of the key that has just been - * parsed; this same key is still on top of the Node Stack. + * See the documentation regarding XML layouts. + */ + virtual void buildLayout() = 0; + + /** + * The keycallback function is automatically overloaded on custom parsers + * when using the CUSTOM_XML_PARSER() macro. * - * Access the node stack to view this key's properties and its parents. - * Remember to leave the node stack _UNCHANGED_ in your own function. Removal - * of closed keys is done automatically. + * Its job is to call the corresponding Callback function for the given node. + * A function for each key type must be declared separately. See the custom + * parser creation instructions. * - * When parsing a key, one may chose to skip it, e.g. because it's not needed + * When parsing a key in such function, 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. + * The callback function must return true if the key was properly handled (this includes the case when the + * key is being ignored). False otherwise. The return of keyCallback() is the same as + * the callback function's. * See the sample implementation in GUI::ThemeParser. */ - virtual bool keyCallback(Common::String keyName) { - return false; - } + virtual bool keyCallback(ParserNode *node) = 0; /** - * The closed key callback function must be overloaded by inheriting classes to + * The closed key callback function MAY be overloaded by inheriting classes to * implement parser-specific functions. * * The closedKeyCallback is issued once a key has been finished parsing, to let @@ -213,28 +354,27 @@ protected: * Returns true if the key was properly closed, false otherwise. * By default, all keys are properly closed. */ - virtual bool closedKeyCallback(Common::String keyName) { + virtual bool closedKeyCallback(ParserNode *node) { return true; } /** * Parses the value of a given key. There's no reason to overload this. */ - virtual bool parseKeyValue(Common::String keyName); + bool parseKeyValue(Common::String keyName); /** * Called once a key has been parsed. It handles the closing/cleanup of the * node stack and calls the keyCallback. - * There's no reason to overload this. */ - virtual bool parseActiveKey(bool closed); + bool parseActiveKey(bool closed); /** * Prints an error message when parsing fails and stops the parser. * Parser error always returns "false" so we can pass the return value directly * and break down the parsing. */ - virtual bool parserError(const char *errorString, ...) GCC_PRINTF(2, 3); + bool parserError(const char *errorString, ...) GCC_PRINTF(2, 3); /** * Skips spaces/whitelines etc. Returns true if any spaces were skipped. @@ -292,7 +432,7 @@ protected: * Parses a the first textual token found. * There's no reason to overload this. */ - virtual bool parseToken() { + bool parseToken() { _token.clear(); while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; @@ -318,7 +458,7 @@ protected: * by reference. * @returns True if the parsing succeeded. */ - virtual bool parseIntegerKey(const char *key, int count, ...) { + bool parseIntegerKey(const char *key, int count, ...) { char *parseEnd; int *num_ptr; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 66750b8c1a..9733be4125 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -40,17 +40,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -ThemeParser::ThemeParser(ThemeRenderer *parent) : 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; - _callbacks["layout_info"] = &ThemeParser::parserCallback_layoutInfo; - _callbacks["defaults"] = &ThemeParser::parserCallback_defaultSet; - _callbacks["text"] = &ThemeParser::parserCallback_text; - _callbacks["fonts"] = &ThemeParser::parserCallback_fonts; - _callbacks["font"] = &ThemeParser::parserCallback_font; +ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; @@ -76,14 +66,6 @@ void ThemeParser::cleanup() { _palette.clear(); } -bool ThemeParser::keyCallback(Common::String keyName) { - // automatically handle with a function from the hash table. - if (!_callbacks.contains(_activeKey.top()->name)) - return parserError("%s is not a valid key name.", keyName.c_str()); - - return (this->*(_callbacks[_activeKey.top()->name]))(); -} - Graphics::DrawStep *ThemeParser::defaultDrawStep() { Graphics::DrawStep *step = new DrawStep; @@ -125,14 +107,10 @@ Graphics::DrawStep *ThemeParser::newDrawStep() { return step; } -bool ThemeParser::parserCallback_defaultSet() { - ParserNode *defNode = getActiveNode(); - ParserNode *parentNode = getParentNode(defNode); +bool ThemeParser::parserCallback_defaults(ParserNode *node) { + ParserNode *parentNode = getParentNode(node); Graphics::DrawStep *step = 0; - if (parentNode == 0) - return parserError("The key must be contained inside keys."); - if (parentNode->name == "render_info") { step = _defaultStepGlobal; } else if (parentNode->name == "drawdata") { @@ -145,143 +123,76 @@ bool ThemeParser::parserCallback_defaultSet() { return parserError(" key out of scope. Must be inside or keys."); } - return parseDrawStep(defNode, step, false); + return parseDrawStep(node, step, false); } -bool ThemeParser::parserCallback_font() { - ParserNode *tNode = getActiveNode(); - ParserNode *parentNode = getParentNode(tNode); - - if (parentNode == 0 || parentNode->name != "fonts") - return parserError("Text Steps must be contained inside keys."); - - if (!tNode->values.contains("id")) - return parserError("Font definitions need a valid identifier."); - - if (!tNode->values.contains("type")) - return parserError("Font definitions need a valid typename."); - - if (tNode->values.contains("horizontal_align") || tNode->values.contains("vertical_align")) - return parserError("Font definitions cannot contain alignments."); - +bool ThemeParser::parserCallback_font(ParserNode *node) { int red, green, blue; - if (tNode->values.contains("color")) { - - if (_palette.contains(tNode->values["color"])) - getPaletteColor(tNode->values["color"], red, green, blue); - else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue)) - return parserError("Error when parsing color value for font definition."); - - } else { - return parserError("Cannot assign color in font definition."); - } + 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 when parsing color value for font definition."); - if (!_theme->addFont(tNode->values["id"], red, green, blue)) + if (!_theme->addFont(node->values["id"], red, green, blue)) return parserError("Error when loading Font in theme engine."); return true; } -bool ThemeParser::parserCallback_fonts() { - ParserNode *tNode = getActiveNode(); - - if (getParentNode(tNode) == 0 || getParentNode(tNode)->name != "render_info") - return parserError("Font definition keys must be contained inside a section."); - +bool ThemeParser::parserCallback_fonts(ParserNode *node) { return true; } -bool ThemeParser::parserCallback_text() { - ParserNode *tNode = getActiveNode(); - ParserNode *parentNode = getParentNode(tNode); - - if (parentNode == 0 || parentNode->name != "drawdata") - return parserError("Text Steps must be contained inside keys."); - +bool ThemeParser::parserCallback_text(ParserNode *node) { GUI::Theme::TextAlign alignH; GUI::Theme::TextAlignVertical alignV; - - if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false) - return parserError("Text inside widgets requires proper alignment keys."); - - if (tNode->values.contains("font") == false) - return parserError("Text definitions must include a valid Font identifier."); - if (tNode->values["horizontal_align"] == "left") + if (node->values["horizontal_align"] == "left") alignH = GUI::Theme::kTextAlignLeft; - else if (tNode->values["horizontal_align"] == "right") + else if (node->values["horizontal_align"] == "right") alignH = GUI::Theme::kTextAlignRight; - else if (tNode->values["horizontal_align"] == "center") + else if (node->values["horizontal_align"] == "center") alignH = GUI::Theme::kTextAlignCenter; else return parserError("Invalid value for text alignment."); - if (tNode->values["vertical_align"] == "top") + if (node->values["vertical_align"] == "top") alignV = GUI::Theme::kTextAlignVTop; - else if (tNode->values["vertical_align"] == "center") + else if (node->values["vertical_align"] == "center") alignV = GUI::Theme::kTextAlignVCenter; - else if (tNode->values["vertical_align"] == "bottom") + else if (node->values["vertical_align"] == "bottom") alignV = GUI::Theme::kTextAlignVBottom; else return parserError("Invalid value for text alignment."); - if (!_theme->addTextData(parentNode->values["id"], tNode->values["font"], alignH, alignV)) - return parserError("Error when adding Text Data for '%s'.", parentNode->values["id"].c_str()); + if (!_theme->addTextData(getParentNode(node)->values["id"], node->values["font"], alignH, alignV)) + return parserError("Error when adding Text Data for '%s'.", getParentNode(node)->values["id"].c_str()); return true; } -bool ThemeParser::parserCallback_renderInfo() { - ParserNode *infoNode = getActiveNode(); - - assert(infoNode->name == "render_info"); - - if (getParentNode(infoNode) != 0) - return parserError(" keys must be root elements."); - +bool ThemeParser::parserCallback_render_info(ParserNode *node) { // TODO: Skip key if it's not for this platform. - return true; } -bool ThemeParser::parserCallback_layoutInfo() { - ParserNode *layoutNode = getActiveNode(); - - assert(layoutNode->name == "layout_info"); - - if (getParentNode(layoutNode) != 0) - return parserError(" keys must be root elements."); - +bool ThemeParser::parserCallback_layout_info(ParserNode *node) { + // TODO: skip key 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 section."); - +bool ThemeParser::parserCallback_palette(ParserNode *node) { return true; } -bool ThemeParser::parserCallback_color() { - ParserNode *colorNode = getActiveNode(); - - if (getParentNode(colorNode) == 0 || getParentNode(colorNode)->name != "palette") - return parserError("Colors must be specified inside 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"]; +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(colorNode->values["rgb"].c_str(), 3, &red, &green, &blue) == false || + 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 when parsing RGB values for palette color '%s'", name.c_str());\ @@ -293,53 +204,32 @@ bool ThemeParser::parserCallback_color() { } -bool ThemeParser::parserCallback_DRAWSTEP() { - ParserNode *stepNode = _activeKey.top(); - ParserNode *drawdataNode = getParentNode(stepNode); - - if (!drawdataNode || drawdataNode->name != "drawdata") - return parserError("DrawStep keys must be located inside a DrawData set."); - - assert(stepNode->name == "drawstep"); - assert(drawdataNode->values.contains("id")); - +bool ThemeParser::parserCallback_drawstep(ParserNode *node) { Graphics::DrawStep *drawstep = newDrawStep(); - if (!stepNode->values.contains("func")) - return parserError("All Draw Steps must contain a 'func' definition."); - - Common::String functionName = stepNode->values["func"]; + Common::String functionName = node->values["func"]; if (_drawFunctions.contains(functionName) == false) return parserError("%s is not a valid drawing function name", functionName.c_str()); drawstep->drawingCall = _drawFunctions[functionName]; - if (!parseDrawStep(stepNode, drawstep, true)) + if (!parseDrawStep(node, drawstep, true)) return false; - _theme->addDrawStep(drawdataNode->values["id"], *drawstep); + _theme->addDrawStep(getParentNode(node)->values["id"], *drawstep); delete drawstep; return true; } -bool ThemeParser::parserCallback_DRAWDATA() { - ParserNode *drawdataNode = _activeKey.top(); +bool ThemeParser::parserCallback_drawdata(ParserNode *node) { 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 section."); - - if (drawdataNode->values.contains("id") == false) - return parserError("DrawData keys must contain an identifier."); - - if (drawdataNode->values.contains("cache")) { - if (drawdataNode->values["cache"] == "true") + if (node->values.contains("cache")) { + if (node->values["cache"] == "true") cached = true; - else if (drawdataNode->values["cache"] == "false") + else if (node->values["cache"] == "false") cached = false; else return parserError("'Parsed' value must be either true or false."); } @@ -354,7 +244,7 @@ bool ThemeParser::parserCallback_DRAWDATA() { } }*/ - if (_theme->addDrawData(drawdataNode->values["id"], cached) == false) + if (_theme->addDrawData(node->values["id"], cached) == false) return parserError("Error when adding Draw Data set: Invalid DrawData name."); if (_defaultStepLocal) { diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 59ba188fc1..485cc135bc 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -312,7 +312,6 @@ class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); - typedef bool (ThemeParser::*ParserCallback)(); public: ThemeParser(GUI::ThemeRenderer *parent); @@ -330,19 +329,98 @@ public: protected: ThemeRenderer *_theme; - bool keyCallback(Common::String keyName); - - bool parserCallback_DRAWSTEP(); - bool parserCallback_DRAWDATA(); - bool parserCallback_palette(); - bool parserCallback_color(); - bool parserCallback_renderInfo(); - bool parserCallback_layoutInfo(); - bool parserCallback_defaultSet(); - bool parserCallback_text(); - bool parserCallback_fonts(); - bool parserCallback_font(); - + + 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) + KEY_END() + + } PARSER_END(); + + bool parserCallback_defaults(ParserNode *node); + bool parserCallback_font(ParserNode *node); + bool parserCallback_fonts(ParserNode *node); + bool parserCallback_text(ParserNode *node); + bool parserCallback_render_info(ParserNode *node); + bool parserCallback_layout_info(ParserNode *node); + bool parserCallback_palette(ParserNode *node); + bool parserCallback_color(ParserNode *node); + bool parserCallback_drawstep(ParserNode *node); + bool parserCallback_drawdata(ParserNode *node); + void cleanup(); Graphics::DrawStep *newDrawStep(); @@ -353,7 +431,6 @@ protected: Graphics::DrawStep *_defaultStepLocal; Common::HashMap _drawFunctions; - Common::HashMap _callbacks; struct PaletteColor { uint8 r, g, b; @@ -362,6 +439,8 @@ protected: Common::HashMap _palette; }; + + } #endif -- cgit v1.2.3 From f930bbac59c6216169d6cc8b4926792ae4b0e976 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Jul 2008 14:08:07 +0000 Subject: Finished documentation. svn-id: r33449 --- common/xmlparser.h | 89 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 221d382a70..8b2d2ee956 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -55,12 +55,14 @@ namespace Common { parsing layout of the XML file. Declaring the XML layout is done with the help of the CUSTOM_XML_PARSER() - macro: this macro must appear once inside the Custom Parser Class declaration, - and takes a single parameter, the name of the Custom Parser Class. + macro: this macro must appear once inside the Custom Parser Class + declaration, and takes a single parameter, the name of the Custom Parser + Class. - The macro must be followed by the actual layout of the XML files to be parsed, - and closed with the PARSER_END() macro. The layout of XML files is defined by - the use of 3 helper macros: XML_KEY(), KEY_END() and XML_PROP(). + The macro must be followed by the actual layout of the XML files to be + parsed, and closed with the PARSER_END() macro. The layout of XML files + is defined by the use of 3 helper macros: XML_KEY(), KEY_END() and + XML_PROP(). Here's a sample of its usage: @@ -101,9 +103,9 @@ namespace Common { The XML_KEY() macro takes a single argument, the name of the expected key. Inside the scope of each key, you may define properties for the given key - with the XML_PROP() macro, which takes as parameters the name of the property - and whether it's optional or required. You might also define the contained - children keys, using the XML_KEY() macro again. + with the XML_PROP() macro, which takes as parameters the name of the + property and whether it's optional or required. You might also define the + contained children keys, using the XML_KEY() macro again. The scope of a XML key is closed with the KEY_END() macro. As an example, the following XML layout: @@ -123,10 +125,55 @@ namespace Common { - TODO: documentation on callbacks + Once a layout has been defined, everytime a XML node (that is, a key and + all its properties) has been parsed, a specific callback funcion is called, + which should take care of managing the parsed data for the node. - Note that the XML parser doesn't take into account the actual order of the keys and - properties in the XML layout definition, only its layout and relationships. + Callback functions must be explicitly declared with the following syntax: + + bool parserCallback_KEYNAME(ParserNode *node); + + A callback function is needed for each key that can be parsed, since they + are called automatically; the function will receive a pointer to the XML + Node that has been parsed. This XML Node has the following properties: + + - It's assured to be expected in the layout of the XML file (i.e. + has the proper position and depth in the XML tree). + + - It's assured to contain all the required Properties that have + been declared in the XML layout. + + - It's assured to contain NO unexpected properties (i.e. properties + which haven't been declared in the XML layout). + + Further validation of the Node's data may be performed inside the callback + function. Once the node has been validated and its data has been parsed/ + managed, the callback function is expected to return true. + + If the data in the XML Node is corrupted or there was a problem when + parsing it, the callback function is expected to return false or, + preferably, to throw a parserError() using the following syntax: + + return parserError("There was a problem in key '%s'.", arg1, ...); + + Also, note that the XML parser doesn't take into account the actual order + of the keys and properties in the XML layout definition, only its layout + and relationships. + + Lastly, when defining your own Custom XML Parser, further customization + may be accomplished _optionally_ by overloading several virtual functions + of the XMLParser class. + + Check the API documentation of the following functions for more info: + + virtual bool closedKeyCallback(ParserNode *node); + virtual bool skipComments(); + virtual bool isValidNameChar(char c); + virtual void cleanup(); + + Check the sample implementation of the GUI::ThemeParser custom parser + for a working sample of a Custom XML Parser. + */ #define XML_KEY(keyName) {\ @@ -215,6 +262,8 @@ public: virtual ~XMLParser() { while (!_activeKey.empty()) delete _activeKey.pop(); + + delete _XMLkeys; } /** Active state for the parser */ @@ -243,6 +292,12 @@ public: Common::List properties; ChildMap children; + + ~XMLKeyLayout() { + properties.clear(); + children.clear(); +// delete custom; + } } *_XMLkeys; /** Struct representing a parsed node */ @@ -261,7 +316,7 @@ public: * * @param filename Name of the file to load. */ - virtual bool loadFile(Common::String filename) { + bool loadFile(Common::String filename) { Common::File *f = new Common::File; if (!f->open(filename, Common::File::kFileReadMode)) @@ -283,7 +338,7 @@ public: * i.e. if it can be freed safely after it's * no longer needed by the parser. */ - virtual bool loadBuffer(const byte *buffer, uint32 size, bool disposable = false) { + bool loadBuffer(const byte *buffer, uint32 size, bool disposable = false) { _text.loadStream(new MemoryReadStream(buffer, size, disposable)); _fileName = "Memory Stream"; return true; @@ -293,7 +348,7 @@ public: * The actual parsing function. * Parses the loaded data stream, returns true if successful. */ - virtual bool parse(); + bool parse(); /** * Returns the active node being parsed (the one on top of @@ -378,10 +433,8 @@ protected: /** * Skips spaces/whitelines etc. Returns true if any spaces were skipped. - * Overload this if you want to make your parser depend on newlines or - * whatever. */ - virtual bool skipSpaces() { + bool skipSpaces() { if (!isspace(_text[_pos])) return false; @@ -492,6 +545,8 @@ protected: */ virtual void cleanup() {} + +private: int _pos; /** Current position on the XML buffer. */ XMLStream _text; /** Buffer with the text being parsed */ Common::String _fileName; -- cgit v1.2.3 From c84386b4be4a0d8b9d8cd901e3d4bcbb67481832 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Jul 2008 15:19:29 +0000 Subject: Layout XML format. WIP. svn-id: r33454 --- gui/ThemeDefaultXML.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 97880dbdb2..7a5065afa9 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -154,6 +154,16 @@ bool ThemeRenderer::loadDefaultXML() { "" "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" ""; if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) -- cgit v1.2.3 From 01cf9174b1ea896b5dc7ddc8ec560ca1bd4de4f4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Jul 2008 16:59:49 +0000 Subject: Bugfix: Pixel init in Conolution mappings svn-id: r33460 --- graphics/VectorRenderer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index a708d5ac1f..5ac976c251 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -178,6 +178,8 @@ areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, for (int y = area.top; y < area.bottom; ++y) { for (int x = area.left; x < area.right; ++x) { + newR = newG = newB = 0; + for (int j = 0; j < 3; ++j) { yVal = MIN(MAX(y - 1 + j, 0), area.bottom - 1); -- cgit v1.2.3 From e8278c4c6891b8b3b2ef95f2f55e4730d76234ba Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 31 Jul 2008 17:23:38 +0000 Subject: GUI Layout parsing. Work in progress. svn-id: r33475 --- common/xmlparser.cpp | 34 +++++++++++++-------- gui/ThemeDefaultXML.cpp | 33 ++++++++++++++------ gui/ThemeEval.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ gui/ThemeParser.cpp | 50 ++++++++++++++++++++++++++++++ gui/ThemeParser.h | 48 +++++++++++++++++++++++++++-- gui/ThemeRenderer.cpp | 5 +++ gui/ThemeRenderer.h | 6 ++++ 7 files changed, 231 insertions(+), 26 deletions(-) create mode 100644 gui/ThemeEval.h diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 030b5b9491..89dd5d7e32 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -41,25 +41,34 @@ bool XMLParser::parserError(const char *errorString, ...) { int lineCount = 1; int lineStart = 0; - do { - if (_text[pos] == '\n' || _text[pos] == '\r') { - lineCount++; - - if (lineStart == 0) - lineStart = MAX(pos + 1, _pos - 60); - } - } while (pos-- > 0); + if (_fileName == "Memory Stream") { + lineStart = MAX(0, _pos - 35); + lineCount = 0; + } else { + do { + if (_text[pos] == '\n' || _text[pos] == '\r') { + lineCount++; + + if (lineStart == 0) + lineStart = MAX(pos + 1, _pos - 60); + } + } while (pos-- > 0); + } char lineStr[70]; _text.stream()->seek(lineStart, SEEK_SET); _text.stream()->readLine(lineStr, 70); + + for (int i = 0; i < 70; ++i) + if (lineStr[i] == '\n') + lineStr[i] = ' '; - printf(" File <%s>, line %d:\n", _fileName.c_str(), lineCount); + printf("\n File <%s>, line %d:\n", _fileName.c_str(), lineCount); bool startFull = lineStr[0] == '<'; bool endFull = lineStr[strlen(lineStr) - 1] == '>'; - printf("%s%s%s\n", startFull ? "" : "...", endFull ? "" : "...", lineStr); + printf("%s%s%s\n", startFull ? "" : "...", lineStr, endFull ? "" : "..."); int cursor = MIN(_pos - lineStart, 70); @@ -77,7 +86,7 @@ bool XMLParser::parserError(const char *errorString, ...) { vprintf(errorString, args); va_end(args); - printf("\n"); + printf("\n\n"); return false; } @@ -123,9 +132,8 @@ bool XMLParser::parseActiveKey(bool closed) { return false; } - if (closed) { + if (closed) delete _activeKey.pop(); - } return true; } diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 7a5065afa9..4fdcbc8d58 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -154,16 +154,29 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + "" + "" + "" + + "" + "" + "" ""; if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h new file mode 100644 index 0000000000..4f08148c7b --- /dev/null +++ b/gui/ThemeEval.h @@ -0,0 +1,81 @@ +/* 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 GUI_THEME_EVAL +#define GUI_THEME_EVAL + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" + +namespace GUI { + +class ThemeEval { + + typedef Common::HashMap VariablesMap; + +public: + ThemeEval() {} + ~ThemeEval() {} + + int getVar(const Common::String &s) { + if (!_vars.contains(s)) { + warning("Missing variable: '%s'", s.c_str()); + return -1; + } + + return _vars[s]; + } + + int getVar(const Common::String &s, int def) { + return (_vars.contains(s)) ? _vars[s] : def; + } + + void setVar(const String &name, int val) { _vars[name] = val; } + + void debugPrint() { + printf("Debug variable list:\n"); + + VariablesMap::const_iterator i; + for (i = _vars.begin(); i != _vars.end(); ++i) { + printf(" '%s' = %d\n", i->_key.c_str(), i->_value); + } + } + +private: + VariablesMap _vars; +}; + + +} + +#endif diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 9733be4125..a12aac68bd 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -433,5 +433,55 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst return true; } +bool ThemeParser::parserCallback_def(ParserNode *node) { + Common::String var = "Globals." + node->values["var"]; + int value; + + if (!parseIntegerKey(node->values["value"].c_str(), 1, &value)) + return parserError("Invalid definition for '%s'.", var.c_str()); + + _theme->themeEval()->setVar(var, value); + return true; +} + +bool ThemeParser::parserCallback_widget(ParserNode *node) { + Common::String var; + int width, height, x, y, paddingL, paddingR, paddingT, paddingB; + + if (getParentNode(node)->name == "globals") + var = "Globals." + node->values["name"] + "."; + else if (getParentNode(node)->name == "dialog") + var = "Dialog." + getParentNode(node)->values["name"] + "." + node->values["name"] + "."; + else + assert(!"Corruption in XML parser."); + + if (node->values.contains("size")) { + if (!parseIntegerKey(node->values["size"].c_str(), 2, &width, &height)) + return parserError("Invalid definition for '%sSize'.", var.c_str()); + + _theme->themeEval()->setVar(var + "Width", width); + _theme->themeEval()->setVar(var + "Height", height); + } + + if (node->values.contains("pos")) { + if (!parseIntegerKey(node->values["pos"].c_str(), 2, &x, &y)) + return parserError("Invalid definition for '%sPosition'.", var.c_str()); + + _theme->themeEval()->setVar(var + "X", x); + _theme->themeEval()->setVar(var + "Y", y); + } + + if (node->values.contains("padding")) { + if (!parseIntegerKey(node->values["padding"].c_str(), 4, &paddingL, &paddingR, &paddingT, &paddingB)) + return parserError("Invalid definition for '%sPadding'.", var.c_str()); + + _theme->themeEval()->setVar(var + "Padding.Left", paddingL); + _theme->themeEval()->setVar(var + "Padding.Right", paddingR); + _theme->themeEval()->setVar(var + "Padding.Top", paddingT); + _theme->themeEval()->setVar(var + "Padding.Bottom", paddingB); + } + + return true; } +} \ No newline at end of file diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 485cc135bc..c9483fcc8d 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -406,21 +406,63 @@ protected: KEY_END() // render_info end XML_KEY(layout_info) - KEY_END() + 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_render_info(ParserNode *node); - bool parserCallback_layout_info(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) { return true; } + bool parserCallback_child(ParserNode *node) { return true; } + void cleanup(); Graphics::DrawStep *newDrawStep(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 403fecf12e..48c5eaf7f3 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -33,6 +33,7 @@ #include "gui/launcher.h" #include "gui/ThemeRenderer.h" +#include "gui/ThemeEval.h" #include "graphics/VectorRenderer.h" namespace GUI { @@ -92,6 +93,7 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _themeOk(false), _enabled(false), _buffering(false) { _system = g_system; _parser = new ThemeParser(this); + _themeEval = new GUI::ThemeEval(); for (int i = 0; i < kDrawDataMAX; ++i) { _widgets[i] = 0; @@ -284,6 +286,9 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { } } + // Debug print all the parsed variables. remove + _themeEval->debugPrint(); + _themeOk = true; return true; } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 836f7d05fd..2b15d7dfa8 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -35,6 +35,7 @@ #include "gui/dialog.h" #include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" #include "graphics/VectorRenderer.h" namespace GUI { @@ -208,6 +209,8 @@ public: unloadTheme(); delete _parser; } + + GUI::ThemeEval *themeEval() { return _themeEval; } /** * VIRTUAL METHODS @@ -585,6 +588,9 @@ protected: /** XML Parser, does the Theme parsing instead of the default parser */ GUI::ThemeParser *_parser; + + /** Theme evaluator (changed from GUI::Eval to add functionality) */ + GUI::ThemeEval *_themeEval; /** Main screen surface. This is blitted straight into the overlay. */ Graphics::Surface *_screen; -- cgit v1.2.3 From 661378918eb94c77d20942139aff26d0813e37d8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 31 Jul 2008 20:23:01 +0000 Subject: Fixed SVNMerge trash which got commited in last fix. svn-id: r33479 --- gui/ThemeEval.h | 81 --------------------------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 gui/ThemeEval.h diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h deleted file mode 100644 index 4f08148c7b..0000000000 --- a/gui/ThemeEval.h +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 GUI_THEME_EVAL -#define GUI_THEME_EVAL - -#include "common/util.h" -#include "common/system.h" -#include "common/events.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/xmlparser.h" - -#include "gui/ThemeRenderer.h" -#include "gui/ThemeParser.h" -#include "gui/ThemeEval.h" - -namespace GUI { - -class ThemeEval { - - typedef Common::HashMap VariablesMap; - -public: - ThemeEval() {} - ~ThemeEval() {} - - int getVar(const Common::String &s) { - if (!_vars.contains(s)) { - warning("Missing variable: '%s'", s.c_str()); - return -1; - } - - return _vars[s]; - } - - int getVar(const Common::String &s, int def) { - return (_vars.contains(s)) ? _vars[s] : def; - } - - void setVar(const String &name, int val) { _vars[name] = val; } - - void debugPrint() { - printf("Debug variable list:\n"); - - VariablesMap::const_iterator i; - for (i = _vars.begin(); i != _vars.end(); ++i) { - printf(" '%s' = %d\n", i->_key.c_str(), i->_value); - } - } - -private: - VariablesMap _vars; -}; - - -} - -#endif -- cgit v1.2.3 From 1cee289fbc0567ecc7bb1bb132b85054790f2ead Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 31 Jul 2008 20:26:40 +0000 Subject: Added missing ThemeEval header. svn-id: r33480 --- gui/ThemeEval.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 gui/ThemeEval.h diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h new file mode 100644 index 0000000000..4f08148c7b --- /dev/null +++ b/gui/ThemeEval.h @@ -0,0 +1,81 @@ +/* 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 GUI_THEME_EVAL +#define GUI_THEME_EVAL + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" + +namespace GUI { + +class ThemeEval { + + typedef Common::HashMap VariablesMap; + +public: + ThemeEval() {} + ~ThemeEval() {} + + int getVar(const Common::String &s) { + if (!_vars.contains(s)) { + warning("Missing variable: '%s'", s.c_str()); + return -1; + } + + return _vars[s]; + } + + int getVar(const Common::String &s, int def) { + return (_vars.contains(s)) ? _vars[s] : def; + } + + void setVar(const String &name, int val) { _vars[name] = val; } + + void debugPrint() { + printf("Debug variable list:\n"); + + VariablesMap::const_iterator i; + for (i = _vars.begin(); i != _vars.end(); ++i) { + printf(" '%s' = %d\n", i->_key.c_str(), i->_value); + } + } + +private: + VariablesMap _vars; +}; + + +} + +#endif -- cgit v1.2.3 From 169c4442d1264c0e807ae7bdccde928fb9e2e9b5 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 31 Jul 2008 20:37:34 +0000 Subject: Silencing a compiler warning by adding a newline at the end of the file svn-id: r33481 --- gui/ThemeParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index a12aac68bd..a7c310b5bc 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -484,4 +484,4 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return true; } -} \ No newline at end of file +} -- cgit v1.2.3 From 9bd3b07647bfbd5016f06a4f055a4310b3269587 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Aug 2008 10:18:47 +0000 Subject: Support for XML layout with unspecified keys. XML Layout parsing. WIP. svn-id: r33488 --- common/xmlparser.cpp | 2 +- common/xmlparser.h | 9 +++++++++ gui/ThemeParser.cpp | 20 ++++++++++++++++---- gui/ThemeParser.h | 1 + 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 89dd5d7e32..25c79e65c0 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -112,7 +112,7 @@ bool XMLParser::parseActiveKey(bool closed) { return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); } - if (localMap.empty() == false) + if (key->layout.anyProps == false && localMap.empty() == false) return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); // check if any of the parents must be ignored. diff --git a/common/xmlparser.h b/common/xmlparser.h index 11028dbaa8..9308524388 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -108,6 +108,10 @@ namespace Common { contained children keys, using the XML_KEY() macro again. The scope of a XML key is closed with the KEY_END() macro. + Keys which may contain any kind of Property names may be defined with the + XML_PROP_ANY() macro instead of the XML_PROP() macro. This macro takes no + arguments. + As an example, the following XML layout: XML_KEY(palette) @@ -178,6 +182,7 @@ namespace Common { #define XML_KEY(keyName) {\ lay = new XMLKeyLayout; \ + lay->anyProps = false; \ lay->custom = new kLocalParserName::CustomParserCallback; \ ((kLocalParserName::CustomParserCallback*)(lay->custom))->callback = (&kLocalParserName::parserCallback_##keyName); \ layout.top()->children[#keyName] = lay; \ @@ -189,6 +194,9 @@ namespace Common { prop.name = #propName; \ prop.required = req; \ layout.top()->properties.push_back(prop); }\ + +#define XML_PROP_ANY() {\ + layout.top()->anyProps = true; } #define CUSTOM_XML_PARSER(parserName) \ protected: \ @@ -291,6 +299,7 @@ public: }; Common::List properties; + bool anyProps; ChildMap children; ~XMLKeyLayout() { diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index a7c310b5bc..4ac6a65932 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -446,7 +446,6 @@ bool ThemeParser::parserCallback_def(ParserNode *node) { bool ThemeParser::parserCallback_widget(ParserNode *node) { Common::String var; - int width, height, x, y, paddingL, paddingR, paddingT, paddingB; if (getParentNode(node)->name == "globals") var = "Globals." + node->values["name"] + "."; @@ -455,25 +454,38 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { else assert(!"Corruption in XML parser."); + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + return true; +} + +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)) - return parserError("Invalid definition for '%sSize'.", var.c_str()); + return false; _theme->themeEval()->setVar(var + "Width", width); _theme->themeEval()->setVar(var + "Height", height); } if (node->values.contains("pos")) { + int x, y; + if (!parseIntegerKey(node->values["pos"].c_str(), 2, &x, &y)) - return parserError("Invalid definition for '%sPosition'.", var.c_str()); + return false; _theme->themeEval()->setVar(var + "X", x); _theme->themeEval()->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 parserError("Invalid definition for '%sPadding'.", var.c_str()); + return false; _theme->themeEval()->setVar(var + "Padding.Left", paddingL); _theme->themeEval()->setVar(var + "Padding.Right", paddingR); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c9483fcc8d..c4e744c44c 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -468,6 +468,7 @@ protected: 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; -- cgit v1.2.3 From 262cc33dc7c883e8071e6913f71d02eab443d63c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Aug 2008 10:29:27 +0000 Subject: Fixed compiler problem with anyProp var. svn-id: r33489 --- common/xmlparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 25c79e65c0..5ea10f2278 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -112,7 +112,7 @@ bool XMLParser::parseActiveKey(bool closed) { return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); } - if (key->layout.anyProps == false && localMap.empty() == false) + if (key->layout->anyProps == false && localMap.empty() == false) return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); // check if any of the parents must be ignored. -- cgit v1.2.3 From a15ebfb73a1863636ed2ab6aba000118cfb6af54 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Aug 2008 15:45:02 +0000 Subject: Theme Layout parsing, WIP. svn-id: r33494 --- gui/ThemeDefaultXML.cpp | 16 ++++++-- gui/ThemeEval.h | 2 + gui/ThemeParser.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++-- gui/ThemeParser.h | 6 +-- 4 files changed, 121 insertions(+), 10 deletions(-) diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 4fdcbc8d58..630445a6fd 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -169,13 +169,23 @@ bool ThemeRenderer::loadDefaultXML() { "" "" - "" + "" "" "" "" - "" - "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" "" ""; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 4f08148c7b..c5471bb10d 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -62,6 +62,8 @@ public: void setVar(const String &name, int val) { _vars[name] = val; } + bool hasVar(const Common::String &name) { return _vars.contains(name); } + void debugPrint() { printf("Debug variable list:\n"); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 4ac6a65932..ab4ca8e553 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -460,12 +460,65 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return true; } +bool ThemeParser::parserCallback_child(ParserNode *node) { + Common::String var = "Globals." + getParentNode(node)->values["name"] + "." + node->values["name"] + "."; + + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + return true; +} + +bool ThemeParser::parserCallback_dialog(ParserNode *node) { + Common::String var = "Dialog." + node->values["name"] + "."; + + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + return true; +} + 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)) - return false; + 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->themeEval()->hasVar(wtoken)) { + width = _theme->themeEval()->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->themeEval()->hasVar(htoken)) { + height = _theme->themeEval()->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->themeEval()->setVar(var + "Width", width); _theme->themeEval()->setVar(var + "Height", height); @@ -474,8 +527,54 @@ bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String if (node->values.contains("pos")) { int x, y; - if (!parseIntegerKey(node->values["pos"].c_str(), 2, &x, &y)) - return false; + 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->themeEval()->hasVar(var + "Width")) + return false; + + x = (g_system->getOverlayWidth() / 2) - (_theme->themeEval()->getVar(var + "Width") / 2); + + } else if (_theme->themeEval()->hasVar(xpos)) { + x = _theme->themeEval()->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->themeEval()->hasVar(var + "Height")) + return false; + + y = (g_system->getOverlayHeight() / 2) - (_theme->themeEval()->getVar(var + "Height") / 2); + + } else if (_theme->themeEval()->hasVar(ypos)) { + y = _theme->themeEval()->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->themeEval()->setVar(var + "X", x); _theme->themeEval()->setVar(var + "Y", y); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index c4e744c44c..6f1f8477ae 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -312,7 +312,7 @@ class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); - + public: ThemeParser(GUI::ThemeRenderer *parent); @@ -460,8 +460,8 @@ protected: bool parserCallback_globals(ParserNode *node) { return true; } bool parserCallback_def(ParserNode *node); bool parserCallback_widget(ParserNode *node); - bool parserCallback_dialog(ParserNode *node) { return true; } - bool parserCallback_child(ParserNode *node) { return true; } + bool parserCallback_dialog(ParserNode *node); + bool parserCallback_child(ParserNode *node); void cleanup(); -- cgit v1.2.3 From 44d91bfa81d638a75b81a079edaa046ff4778194 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Aug 2008 20:19:37 +0000 Subject: Massive changes to the renderer in order to replicate the current GUI theme, as requested by Eugene svn-id: r33507 --- graphics/VectorRenderer.cpp | 2 +- gui/ThemeDefaultXML.cpp | 599 +++++++++++++++++++++++++++++++++----------- gui/ThemeRenderer.cpp | 26 +- gui/ThemeRenderer.h | 6 +- gui/theme-config.cpp | 4 +- 5 files changed, 476 insertions(+), 161 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 5ac976c251..3bd3b86cf8 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -517,7 +517,7 @@ template void VectorRendererSpec:: drawTab(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || (r << 1) > w || (r << 1) > h) + w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h) return; switch (Base::_fillMode) { diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 630445a6fd..298f26e782 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -36,158 +36,455 @@ bool ThemeRenderer::loadDefaultXML() { * You may use single quotes (') instead of scaped double quotes. * Remember to indent properly the XML so it's easier to read and * to maintain! + * Also remember to scape the end of each line. :p */ -"" - "" - "" - "" - "" - "" - - "" - "" - "" - "" - "" - "" - - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - "" - "" - - - "" - "" - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - "" - - "" - "" - "" -"" - -"" - "" - "" - "" - "" - - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - "" - "" - "" - "" -""; +" \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +"; if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) return false; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 48c5eaf7f3..a81f46cf8e 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -58,11 +58,13 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDSliderFull, "slider_full", false, kDDNone}, - {kDDCheckboxEnabled, "checkbox_enabled", false, kDDCheckboxDisabled}, + {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, + {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, {kDDTabActive, "tab_active", false, kDDTabInactive}, {kDDTabInactive, "tab_inactive", true, kDDNone}, + {kDDTabBackground, "tab_background", true, kDDNone}, {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, @@ -83,7 +85,9 @@ const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { {kTextDataDefault, "text_default"}, {kTextDataHover, "text_hover"}, {kTextDataDisabled, "text_disabled"}, - {kTextDataInverted, "text_inverted"} + {kTextDataInverted, "text_inverted"}, + {kTextDataButton, "text_button"}, + {kTextDataButtonHover, "text_button_hover"} }; @@ -446,7 +450,15 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st return; Common::Rect r2 = r; - DrawData dd = checked ? kDDCheckboxEnabled : kDDCheckboxDisabled; + DrawData dd = kDDCheckboxDefault; + + if (checked) + dd = kDDCheckboxSelected; + + if (state == kStateDisabled) + dd = kDDCheckboxDisabled; + + TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd); const int checkBoxSize = MIN((int)r.height(), getFontHeight()); r2.bottom = r2.top + checkBoxSize; @@ -457,7 +469,7 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st r2.left = r2.right + checkBoxSize; r2.right = r.right; - queueDDText(getTextData(dd), r2, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); } void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { @@ -564,12 +576,14 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, if (!ready()) return; - const int tabOffset = 1; + const int tabOffset = 3; + + queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); for (int i = 0; i < (int)tabs.size(); ++i) { if (i == active) continue; - + Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); queueDD(kDDTabInactive, tabRect); queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 2b15d7dfa8..2a0f059d41 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -119,11 +119,13 @@ protected: kDDSliderFull, - kDDCheckboxEnabled, + kDDCheckboxDefault, kDDCheckboxDisabled, + kDDCheckboxSelected, kDDTabActive, kDDTabInactive, + kDDTabBackground, kDDScrollbarBase, kDDScrollbarButtonIdle, @@ -168,6 +170,8 @@ protected: kTextDataHover, kTextDataDisabled, kTextDataInverted, + kTextDataButton, + kTextDataButtonHover, kTextDataMAX }; diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp index 47f60d3d7b..1f52567e3e 100644 --- a/gui/theme-config.cpp +++ b/gui/theme-config.cpp @@ -138,7 +138,7 @@ const char *Theme::_defaultConfigINI = "PopUpWidget.leftPadding=4\n" "PopUpWidget.rightPadding=0\n" "TabWidget.tabWidth=70\n" -"TabWidget.tabHeight=21\n" +"TabWidget.tabHeight=22\n" "TabWidget.titleVPad=2\n" "\n" "###### chooser\n" @@ -183,7 +183,7 @@ const char *Theme::_defaultConfigINI = "globaloptions=insetX insetY insetW insetH\n" "set_parent=globaloptions\n" "vBorder=5\n" -"globaloptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" +"globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" "\n" "# graphics tab\n" "opYoffset=vBorder\n" -- cgit v1.2.3 From 01b7d26956fddc58a4471516efc44596a19ccc50 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Aug 2008 21:51:30 +0000 Subject: Replicating the trunk GUI theme. WIP. svn-id: r33508 --- graphics/VectorRenderer.h | 5 +++++ gui/ThemeDefaultXML.cpp | 25 ++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 8a02d7fc21..60ab8797ef 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -856,6 +856,11 @@ protected: * @see VectorRenderer::drawRoundedAlg() */ virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); + + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) { + Base::drawRoundedSquareShadow(x, y, r, w, h, blur); + VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur, Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2)); + } }; } // end of namespace Graphics diff --git a/gui/ThemeDefaultXML.cpp b/gui/ThemeDefaultXML.cpp index 298f26e782..42a6efa7c3 100644 --- a/gui/ThemeDefaultXML.cpp +++ b/gui/ThemeDefaultXML.cpp @@ -248,16 +248,15 @@ bool ThemeRenderer::loadDefaultXML() { \ \ \ - \ \ - \ + /> \ \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ -"; - - if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) - return false; - - return parser()->parse(); -} - -} diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index a81f46cf8e..b4d68df4be 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -57,6 +57,8 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDButtonDisabled, "button_disabled", true, kDDNone}, {kDDSliderFull, "slider_full", false, kDDNone}, + {kDDSliderHover, "slider_hover", false, kDDNone}, + {kDDSliderDisabled, "slider_disabled", true, kDDNone}, {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, @@ -110,7 +112,7 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _graphicsMode = mode; setGraphicsMode(_graphicsMode); - loadConfigFile("classic"); + loadConfigFile("modern"); if (_screen->w >= 400 && _screen->h >= 300) { _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); @@ -297,6 +299,22 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { return true; } +bool ThemeRenderer::loadDefaultXML() { + + // The default XML theme is included on runtime from a pregenerated + // file inside the themes directory. + // Use the Python script "makedeftheme.py" to convert a normal XML theme + // into the "default.inc" file, which is ready to be included in the code. + const char *defaultXML = +#include "themes/default.inc" + ; + + if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) + return false; + + return parser()->parse(); +} + bool ThemeRenderer::loadThemeXML(Common::String themeName) { assert(_parser); @@ -475,12 +493,22 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { if (!ready()) return; + + DrawData dd = kDDSliderFull; + + if (state == kStateHighlight) + dd = kDDSliderHover; + else if (state == kStateDisabled) + dd = kDDSliderDisabled; Common::Rect r2 = r; r2.setWidth(MIN((int16)width, r.width())); + r2.top++; r2.bottom--; r2.left++; r2.right--; drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); - queueDD(kDDSliderFull, r2); + + if (width > r.width() * 5 / 100) + queueDD(dd, r2); } void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { @@ -576,7 +604,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, if (!ready()) return; - const int tabOffset = 3; + const int tabOffset = 1; queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 2a0f059d41..240bf28e10 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -118,6 +118,8 @@ protected: kDDButtonDisabled, kDDSliderFull, + kDDSliderHover, + kDDSliderDisabled, kDDCheckboxDefault, kDDCheckboxDisabled, diff --git a/gui/module.mk b/gui/module.mk index 6ff74641b8..4afe11201a 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -25,7 +25,6 @@ MODULE_OBJS := \ widget.o \ theme.o \ ThemeClassic.o \ - ThemeDefaultXML.o \ ThemeModern.o \ ThemeParser.o \ theme-config.o diff --git a/gui/themes/default.inc b/gui/themes/default.inc new file mode 100644 index 0000000000..ef3120df44 --- /dev/null +++ b/gui/themes/default.inc @@ -0,0 +1 @@ +" " diff --git a/gui/themes/makedeftheme.py b/gui/themes/makedeftheme.py new file mode 100644 index 0000000000..fc09e6b1f0 --- /dev/null +++ b/gui/themes/makedeftheme.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# encoding: utf-8 +import sys +import re + +def main(): + theme_file = open(sys.argv[1], "r") + def_file = open("default.inc", "w") + comment = re.compile("\/\*(.*)\*\/") + + try: + output = "\"" + for line in theme_file: + output += (line.rstrip("\n\r ").lstrip() + " ") + + output = re.sub("\/\*(.*)\*\/", "", output) + def_file.write(output + "\"\n") + finally: + theme_file.close() + def_file.close() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx new file mode 100644 index 0000000000..978db1e44f --- /dev/null +++ b/gui/themes/modern.stx @@ -0,0 +1,483 @@ +/* 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$ + * + */ + +/* ScummVM Theme XML file */ +/* Modern Theme */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From c5980b6211bdb11c144c23f71470f4dde5ace3a9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 2 Aug 2008 16:23:58 +0000 Subject: Screen/dialog dimming. svn-id: r33532 --- graphics/VectorRenderer.h | 27 +++++++++++++++++++++++++++ gui/ThemeClassic.cpp | 2 +- gui/ThemeClassic.h | 2 +- gui/ThemeModern.cpp | 2 +- gui/ThemeModern.h | 2 +- gui/ThemeRenderer.cpp | 10 ++++++++-- gui/ThemeRenderer.h | 2 +- gui/newgui.cpp | 2 +- gui/theme.h | 2 +- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 2 +- 11 files changed, 44 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index fa986e2f08..b85ad8a9c9 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -436,6 +436,8 @@ public: areaConvolution(area, _convolutionData[id].matrix, _convolutionData[id].divisor, _convolutionData[id].offset); #endif } + + virtual void applyScreenShading(GUI::Theme::ShadingStyle) = 0; protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ @@ -451,6 +453,8 @@ protected: int _gradientBytes[3]; /** Color bytes of the active gradient, used to speed up calculation */ static const ConvolutionDataSet _convolutionData[kConvolutionMAX]; + + static const int _dimPercentValue = 256 * 50 / 100; }; /** @@ -605,6 +609,29 @@ public: src_ptr += src_pitch; } } + + virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { + int pixels = _activeSurface->w * _activeSurface->h; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); + uint8 r, g, b; + uint lum; + + if (shadingStyle == GUI::Theme::kShadingDim) { + while (pixels--) { + colorToRGB(*ptr, r, g, b); + r = r * _dimPercentValue >> 8; + g = g * _dimPercentValue >> 8; + b = b * _dimPercentValue >> 8; + *ptr++ = RGBToColor(r, g, b); + } + } else if (shadingStyle == GUI::Theme::kShadingLuminance) { + while (pixels--) { + colorToRGB(*ptr, r, g, b); + lum = (r >> 2) + (g >> 1) + (b >> 3); + *ptr++ = RGBToColor(lum, lum, lum); + } + } + } protected: diff --git a/gui/ThemeClassic.cpp b/gui/ThemeClassic.cpp index be17cf0d09..eaf86d1cbb 100644 --- a/gui/ThemeClassic.cpp +++ b/gui/ThemeClassic.cpp @@ -118,7 +118,7 @@ void ThemeClassic::disable() { _enabled = false; } -void ThemeClassic::openDialog(bool topDialog) { +void ThemeClassic::openDialog(bool topDialog, ShadingStyle shading) { #ifndef CT_NO_TRANSPARENCY if (!_dialog) { _dialog = new DialogState; diff --git a/gui/ThemeClassic.h b/gui/ThemeClassic.h index 12dc8d8068..28c522b906 100644 --- a/gui/ThemeClassic.h +++ b/gui/ThemeClassic.h @@ -45,7 +45,7 @@ public: void enable(); void disable(); - void openDialog(bool topDialog); + void openDialog(bool topDialog, ShadingStyle = kShadingNone); void closeAllDialogs(); void clearAll(); diff --git a/gui/ThemeModern.cpp b/gui/ThemeModern.cpp index 177171b40c..45a454e00e 100644 --- a/gui/ThemeModern.cpp +++ b/gui/ThemeModern.cpp @@ -189,7 +189,7 @@ void ThemeModern::disable() { _enabled = false; } -void ThemeModern::openDialog(bool topDialog) { +void ThemeModern::openDialog(bool topDialog, ShadingStyle shading) { if (!_dialog) { _dialog = new DialogState; assert(_dialog); diff --git a/gui/ThemeModern.h b/gui/ThemeModern.h index a3cb71510c..29843a73e0 100644 --- a/gui/ThemeModern.h +++ b/gui/ThemeModern.h @@ -46,7 +46,7 @@ public: void enable(); void disable(); - void openDialog(bool topDialog); + void openDialog(bool topDialog, ShadingStyle = kShadingNone); void closeAllDialogs(); void clearAll(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index b4d68df4be..c7b0817110 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -604,7 +604,8 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, if (!ready()) return; - const int tabOffset = 1; + const int tabOffset = 2; + tabWidth -= tabOffset; queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); @@ -707,9 +708,14 @@ void ThemeRenderer::renderDirtyScreen() { _dirtyScreen.clear(); } -void ThemeRenderer::openDialog(bool doBuffer) { +void ThemeRenderer::openDialog(bool doBuffer, ShadingStyle style) { if (doBuffer) _buffering = true; + + if (style != kShadingNone) { + _vectorRenderer->applyScreenShading(style); + addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h)); + } _vectorRenderer->setSurface(_backBuffer); _vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h)); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 240bf28e10..7c18f73fea 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -242,7 +242,7 @@ public: * drawing this dialog, and will continue enabled * until disabled. */ - void openDialog(bool enableBuffering); + void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); /** * The updateScreen() method is called every frame. diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 1c90c70f4b..b2e9cf43b0 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -205,7 +205,7 @@ void NewGui::redraw() { _theme->updateScreen(); case kRedrawOpenDialog: - _theme->openDialog(true); + _theme->openDialog(true, GUI::Theme::kShadingDim); _dialogStack.top()->drawDialog(); _theme->finishBuffering(); break; diff --git a/gui/theme.h b/gui/theme.h index e2b0d39fd3..f8a4946a6b 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -229,7 +229,7 @@ public: * * @see closeAllDialogs */ - virtual void openDialog(bool topDialog) = 0; + virtual void openDialog(bool topDialog, ShadingStyle shading = kShadingNone) = 0; /** * This indicates that all dialogs have been closed. diff --git a/gui/themes/default.inc b/gui/themes/default.inc index ef3120df44..12817685bb 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 978db1e44f..0cabb97845 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -207,7 +207,7 @@ _buffer, _widgets[type]->_buffer); -- cgit v1.2.3 From a3f85956ff851321495404030146c5f60bf1018d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 2 Aug 2008 22:11:57 +0000 Subject: Added basic support for inner shadows. Made sliders look pretty much like the current GUI. svn-id: r33548 --- graphics/VectorRenderer.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++- graphics/VectorRenderer.h | 11 +++++++- gui/ThemeParser.cpp | 2 ++ gui/ThemeParser.h | 3 +++ gui/ThemeRenderer.cpp | 2 +- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 15 ++++++----- 7 files changed, 87 insertions(+), 10 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 3bd3b86cf8..db9b774857 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -75,6 +75,7 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui step.gradColor2.r, step.gradColor2.g, step.gradColor2.b); setShadowOffset(_disableShadows ? 0 : step.shadow); + setInnerShadowOffset(_disableShadows ? 0 : step.innerShadow); setGradientFactor(step.factor); setStrokeWidth(step.stroke); setFillMode((FillMode)step.fillMode); @@ -511,6 +512,9 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { } break; } + + if (Base::_innerShadowOffset) + drawRoundedSquareInnerShadow(x, y, r, w, h, Base::_innerShadowOffset); } template @@ -1154,6 +1158,62 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { } } +template +void VectorRendererSpec:: +drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { + int x, y; + int p = Base::surfacePitch(), px, py; + int sw = 0, sp = 0; + + uint32 rsq = (r * r) << 16; + uint32 T = 0, oldT; + uint8 a1, a2; + + PixelType color = RGBToColor(63, 60, 17); + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int short_h = h - 2 * r; + + while (sw++ < blur) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + sp += p; + + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); + + a1 = a1 * 3 / 4; + a2 = a2 * 3 / 4; + + blendPixelPtr(ptr_tr + (y) - (px - p), color, a2); + blendPixelPtr(ptr_tr + (x - 1) - (py), color, a2); + blendPixelPtr(ptr_tl - (x - 1) - (py), color, a2); + blendPixelPtr(ptr_tl - (y) - (px - p), color, a2); + blendPixelPtr(ptr_bl - (y) + (px - p), color, a2); + blendPixelPtr(ptr_bl - (x - 1) + (py), color, a2); + + blendPixelPtr(ptr_tr + (y) - (px), color, a1); + blendPixelPtr(ptr_tr + (x) - (py), color, a1); + blendPixelPtr(ptr_tl - (x) - (py), color, a1); + blendPixelPtr(ptr_tl - (y) - (px), color, a1); + blendPixelPtr(ptr_bl - (y) + (px), color, a1); + blendPixelPtr(ptr_bl - (x) + (py), color, a1); + } + } + + ptr_fill += p * r; + while (short_h-- >= 0) { + colorFill(ptr_fill, ptr_fill + blur, color); + ptr_fill += p; + } +} + /******************************************************************** * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA @@ -1255,7 +1315,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += p; - } + } } else { x = r; y = 0; T = 0; px = p * x; py = 0; diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index b85ad8a9c9..3756730720 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -62,7 +62,7 @@ struct DrawStep { kVectorAlignCenter } xAlign, yAlign; - uint8 shadow, stroke, factor, radius; /** Misc options... */ + uint8 shadow, stroke, factor, radius, innerShadow; /** Misc options... */ uint8 fillMode; /** active fill mode */ uint32 extraData; /** Generic parameter for extra options (orientation/bevel) */ @@ -329,6 +329,11 @@ public: if (offset >= 0) _shadowOffset = offset; } + + virtual void setInnerShadowOffset(int offset) { + if (offset >= 0) + _innerShadowOffset = offset; + } /** * Sets the multiplication factor of the active gradient. @@ -445,6 +450,7 @@ protected: FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ + int _innerShadowOffset; bool _disableShadows; /** Disables temporarily shadow drawing for overlayed images. */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ uint32 _dynamicData; /** Dynamic data from the GUI Theme that modifies the drawing of the current shape */ @@ -677,6 +683,8 @@ protected: * @param alpha Alpha intensity of the pixel (0-255) */ virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + if (!ptr) return; + if (alpha == 255) { *ptr = color; return; @@ -729,6 +737,7 @@ protected: */ virtual void drawSquareShadow(int x, int y, int w, int h, int blur); virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); + virtual void drawRoundedSquareInnerShadow(int x, int y, int r, int w, int h, int bur); /** * Calculates the color gradient on a given point. diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index ab4ca8e553..310d3d880d 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -88,6 +88,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; + step->innerShadow = 0; step->stroke = 0; step->radius = 0xFF; @@ -306,6 +307,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } __PARSER_ASSIGN_INT(stroke, "stroke", false); + __PARSER_ASSIGN_INT(innerShadow, "inner_shadow", false); __PARSER_ASSIGN_INT(shadow, "shadow", false); __PARSER_ASSIGN_INT(factor, "gradient_factor", false); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 6f1f8477ae..ec7f494735 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -351,6 +351,7 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) + XML_PROP(inner_shadow, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) @@ -367,6 +368,7 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) + XML_PROP(inner_shadow, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) @@ -380,6 +382,7 @@ protected: XML_PROP(func, true) XML_PROP(stroke, false) XML_PROP(shadow, false) + XML_PROP(inner_shadow, false) XML_PROP(factor, false) XML_PROP(fg_color, false) XML_PROP(bg_color, false) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1aca311f58..9a01b18299 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -508,7 +508,7 @@ void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo Common::Rect r2 = r; r2.setWidth(MIN((int16)width, r.width())); - r2.top++; r2.bottom--; r2.left++; r2.right--; +// r2.top++; r2.bottom--; r2.left++; r2.right--; drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 12817685bb..076f0d5c37 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 0cabb97845..18684e6647 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -217,18 +217,20 @@ @@ -236,9 +238,10 @@ -- cgit v1.2.3 From 461e2f42149e3b1914b3c7b392d076c186c6d0a1 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 2 Aug 2008 22:20:31 +0000 Subject: Checkboxes looking good. svn-id: r33549 --- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 076f0d5c37..20d3e3869f 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 18684e6647..dce8495ff8 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -358,9 +358,10 @@ /> @@ -369,15 +370,15 @@ vertical_align = 'top' horizontal_align = 'left' /> - - @@ -386,11 +387,12 @@ vertical_align = 'top' horizontal_align = 'left' /> - -- cgit v1.2.3 From 85c36885f5bbf2d47276c7702f1b8ccbf22ecc34 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 4 Aug 2008 16:59:55 +0000 Subject: Theme layout parsing. Work in progress. svn-id: r33613 --- common/xmlparser.cpp | 27 ++-- common/xmlparser.h | 12 ++ dists/msvc9/scummvm.vcproj | 4 - graphics/VectorRenderer.cpp | 22 ++-- graphics/VectorRenderer.h | 23 ++-- gui/ThemeEval.h | 291 ++++++++++++++++++++++++++++++++++++++++++++ gui/ThemeParser.cpp | 73 +++++++++-- gui/ThemeParser.h | 37 ++++-- gui/ThemeRenderer.cpp | 7 +- gui/newgui.cpp | 21 +++- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 115 ++++++++++------- 12 files changed, 524 insertions(+), 110 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 5ea10f2278..526e6e6fb1 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -98,22 +98,23 @@ bool XMLParser::parseActiveKey(bool closed) { ParserNode *key = _activeKey.top(); XMLKeyLayout *layout = (_activeKey.size() == 1) ? _XMLkeys : getParentNode(key)->layout; - if (layout->children.contains(key->name) == false) - return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str()); - - key->layout = layout->children[key->name]; + if (layout->children.contains(key->name)) { + key->layout = layout->children[key->name]; - Common::StringMap localMap = key->values; + Common::StringMap localMap = key->values; - for (Common::List::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) { - if (localMap.contains(i->name)) - localMap.erase(i->name); - else if (i->required) - return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); - } + for (Common::List::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) { + if (localMap.contains(i->name)) + localMap.erase(i->name); + else if (i->required) + return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); + } - if (key->layout->anyProps == false && localMap.empty() == false) - return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); + if (key->layout->anyProps == false && localMap.empty() == false) + return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); + } else if (layout->anyKeys == false) { + return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str()); + } // check if any of the parents must be ignored. // if a parent is ignored, all children are too. diff --git a/common/xmlparser.h b/common/xmlparser.h index 031ee2be14..0510ec0ab6 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -183,10 +183,16 @@ namespace Common { #define XML_KEY(keyName) {\ lay = new XMLKeyLayout; \ lay->anyProps = false; \ + lay->anyKeys = false; \ lay->custom = new kLocalParserName::CustomParserCallback; \ ((kLocalParserName::CustomParserCallback*)(lay->custom))->callback = (&kLocalParserName::parserCallback_##keyName); \ layout.top()->children[#keyName] = lay; \ layout.push(lay); + +#define XML_KEY_RECURSIVE(keyName) {\ + layout.top()->children[#keyName] = layout.top();\ + layout.push(layout.top());\ + } #define KEY_END() layout.pop(); } @@ -197,6 +203,9 @@ namespace Common { #define XML_PROP_ANY() {\ layout.top()->anyProps = true; } + +#define XML_KEY_ANY() {\ + layout.top()->anyKeys = true; } #define CUSTOM_XML_PARSER(parserName) \ protected: \ @@ -209,6 +218,8 @@ namespace Common { XMLKeyLayout *lay = 0; \ XMLKeyLayout::XMLKeyProperty prop; \ _XMLkeys = new XMLKeyLayout; \ + _XMLkeys->anyProps = false; \ + _XMLkeys->anyKeys = false; \ layout.push(_XMLkeys); #define PARSER_END() layout.clear(); } @@ -300,6 +311,7 @@ public: Common::List properties; bool anyProps; + bool anyKeys; ChildMap children; ~XMLKeyLayout() { diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 3fecfefb90..5da3451ded 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1220,10 +1220,6 @@ RelativePath="..\..\gui\ThemeClassic.cpp" > - - diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index db9b774857..e3e7174d90 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -69,13 +69,16 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui if (step.fgColor.set) setFgColor(step.fgColor.r, step.fgColor.g, step.fgColor.b); + + if (step.bevelColor.set) + setBevelColor(step.bevelColor.r, step.bevelColor.g, step.bevelColor.b); if (step.gradColor1.set && step.gradColor2.set) setGradientColors(step.gradColor1.r, step.gradColor1.g, step.gradColor1.b, step.gradColor2.r, step.gradColor2.g, step.gradColor2.b); setShadowOffset(_disableShadows ? 0 : step.shadow); - setInnerShadowOffset(_disableShadows ? 0 : step.innerShadow); + setBevel(step.bevel); setGradientFactor(step.factor); setStrokeWidth(step.stroke); setFillMode((FillMode)step.fillMode); @@ -513,8 +516,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { break; } - if (Base::_innerShadowOffset) - drawRoundedSquareInnerShadow(x, y, r, w, h, Base::_innerShadowOffset); + if (Base::_bevel) + drawRoundedSquareFakeBevel(x, y, r, w, h, Base::_bevel); } template @@ -945,6 +948,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto int pitch = Base::surfacePitch(); int sw = 0, sp = 0, hp = h * pitch; +// if (r < 8) r = 3; + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); @@ -1160,7 +1165,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { template void VectorRendererSpec:: -drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { +drawRoundedSquareFakeBevel(int x1, int y1, int r, int w, int h, int amount) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0; @@ -1169,7 +1174,7 @@ drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { uint32 T = 0, oldT; uint8 a1, a2; - PixelType color = RGBToColor(63, 60, 17); + PixelType color = _bevelColor; //RGBToColor(63, 60, 17); PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); @@ -1178,7 +1183,7 @@ drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { int short_h = h - 2 * r; - while (sw++ < blur) { + while (sw++ < amount) { colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); sp += p; @@ -1188,9 +1193,6 @@ drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { while (x > y++) { __WU_ALGORITHM(); - a1 = a1 * 3 / 4; - a2 = a2 * 3 / 4; - blendPixelPtr(ptr_tr + (y) - (px - p), color, a2); blendPixelPtr(ptr_tr + (x - 1) - (py), color, a2); blendPixelPtr(ptr_tl - (x - 1) - (py), color, a2); @@ -1209,7 +1211,7 @@ drawRoundedSquareInnerShadow(int x1, int y1, int r, int w, int h, int blur) { ptr_fill += p * r; while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + blur, color); + colorFill(ptr_fill, ptr_fill + amount, color); ptr_fill += p; } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 3756730720..2c5530c07c 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -47,7 +47,8 @@ struct DrawStep { fgColor, /** Foreground color */ bgColor, /** backgroudn color */ gradColor1, /** gradient start*/ - gradColor2; /** gradient end */ + gradColor2, /** gradient end */ + bevelColor; bool autoWidth, autoHeight; int16 x, y, w, h; /** width, height and position, if not measured automatically. @@ -62,7 +63,7 @@ struct DrawStep { kVectorAlignCenter } xAlign, yAlign; - uint8 shadow, stroke, factor, radius, innerShadow; /** Misc options... */ + uint8 shadow, stroke, factor, radius, bevel; /** Misc options... */ uint8 fillMode; /** active fill mode */ uint32 extraData; /** Generic parameter for extra options (orientation/bevel) */ @@ -257,6 +258,8 @@ public: * @param b value of the blue color byte */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; + + virtual void setBevelColor(uint8 r, uint8 g, uint8 b) = 0; /** * Set the active gradient color. All shapes drawn using kFillGradient @@ -330,9 +333,9 @@ public: _shadowOffset = offset; } - virtual void setInnerShadowOffset(int offset) { - if (offset >= 0) - _innerShadowOffset = offset; + virtual void setBevel(int amount) { + if (amount >= 0) + _bevel = amount; } /** @@ -450,7 +453,7 @@ protected: FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ - int _innerShadowOffset; + int _bevel; bool _disableShadows; /** Disables temporarily shadow drawing for overlayed images. */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ uint32 _dynamicData; /** Dynamic data from the GUI Theme that modifies the drawing of the current shape */ @@ -538,6 +541,10 @@ public: void setBgColor(uint8 r, uint8 g, uint8 b) { this->_bgColor = RGBToColor(r, g, b); } + + void setBevelColor(uint8 r, uint8 g, uint8 b) { + this->_bevelColor = RGBToColor(r, g, b); + } /** * @see VectorRenderer::setGradientColors() @@ -737,7 +744,7 @@ protected: */ virtual void drawSquareShadow(int x, int y, int w, int h, int blur); virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); - virtual void drawRoundedSquareInnerShadow(int x, int y, int r, int w, int h, int bur); + virtual void drawRoundedSquareFakeBevel(int x, int y, int r, int w, int h, int amount); /** * Calculates the color gradient on a given point. @@ -846,6 +853,8 @@ protected: PixelType _gradientStart; /** Start color for the fill gradient */ PixelType _gradientEnd; /** End color for the fill gradient */ + + PixelType _bevelColor; }; /** diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index c5471bb10d..f53dfe2cd1 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -39,9 +39,233 @@ namespace GUI { +class ThemeLayout { +public: + int16 x, y, w, h; + int paddingTop, paddingBottom, paddingLeft, paddingRight; + int spacing; + Common::Array children; + ThemeLayout *parent; + + uint16 debugcolor; + + enum LayoutType { + kLayoutNone, + kLayoutVertical, + kLayoutHorizontal, + kLayoutWidget + }; + + enum LayoutParsing { + kLayoutParseDefault, + kLayoutParseTop2Bottom, + kLayoutParseBottom2Top, + kLayoutParseLeft2Right, + kLayoutParseRight2Left + } parsingMode; + + virtual LayoutType getLayoutType() { return kLayoutNone; } + virtual void reflowLayout() { + assert(children.size() <= 1); + + if (children.size()) { + children[0]->w = w; + children[0]->h = h; + children[0]->reflowLayout(); + children[0]->setX(0); + children[0]->setY(0); + } + } + + virtual const char *getName() { return "Global Layout"; } + + int16 getParentW() { return parent ? parent->w : g_system->getOverlayWidth(); } + int16 getParentH() { return parent ? parent->w : g_system->getOverlayHeight(); } + int16 getParentX() { return parent ? parent->x : 0; } + int16 getParentY() { return parent ? parent->y : 0; } + + void setX(int newX) { + x += newX; + for (uint i = 0; i < children.size(); ++i) + children[i]->setX(newX); + } + + void setY(int newY) { + y += newY; + for (uint i = 0; i < children.size(); ++i) + children[i]->setY(newY); + } + + ThemeLayout(ThemeLayout *p) : parent(p), x(0), y(0), w(-1), h(-1) { debugcolor = rand() % 0xFFFF; } + + virtual void debugPrintIndent(int indent) { + while (indent--) + printf(" "); + } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + uint16 color = debugcolor; + font->drawString(screen, getName(), x, y, w, color, Graphics::kTextAlignRight, 0, true); + screen->hLine(x, y, x + w, color); + screen->hLine(x, y + h, x + w, color); + screen->vLine(x, y, y + h, color); + screen->vLine(x + w, y, y + h, color); + + for (uint i = 0; i < children.size(); ++i) + children[i]->debugDraw(screen, font); + } + + virtual void debugPrint(int indent = 0) { + debugPrintIndent(indent); + switch (getLayoutType()) { + case kLayoutNone: + printf("Dialog Layout :: "); + break; + + case kLayoutVertical: + printf("Vertical Layout :: "); + break; + + case kLayoutHorizontal: + printf("Horizontal Layout :: "); + break; + + case kLayoutWidget: + printf("WIDGET (%s) :: ", getName()); + break; + } + + printf("X: %d / Y: %d / W: %d / H: %d\n", x, y, w, h); + + for (uint i = 0; i < children.size(); ++i) + children[i]->debugPrint(indent + 1); + } + + virtual ~ThemeLayout() { + children.clear(); + } +}; + +class ThemeLayoutVertical : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutVertical; } + + ThemeLayoutVertical(ThemeLayout *p) : ThemeLayout(p) {} + + const char *getName() { return "Vertical Layout"; } + + void reflowLayout() { + int curX, curY, mul; + + if (parsingMode == kLayoutParseTop2Bottom) { + curX = paddingLeft; + curY = paddingTop; + mul = 1; + } else { + curX = paddingLeft; + curY = getParentH() - paddingBottom; + mul = -1; + } + + h = paddingTop + paddingBottom; + + for (uint i = 0; i < children.size(); ++i) { + assert(children[i]->getLayoutType() != kLayoutVertical); + + children[i]->reflowLayout(); + + if (i != children.size() - 1) + assert(children[i]->h != -1); + + if (i == 0) + assert(children[i]->w != -1); + + children[i]->setX(curX); + children[i]->setY((parsingMode == kLayoutParseBottom2Top) ? curY - children[i]->h : curY); + + if (children[i]->w == -1) + children[i]->w = w - paddingLeft - paddingRight; + + w = MAX(w, (int16)(children[i]->w + paddingLeft + paddingRight)); + + if (children[i]->h == -1) + children[i]->h = 32; + + h += children[i]->h + spacing; + + curY += (children[i]->h + spacing) * mul; + } + + + } +}; + +class ThemeLayoutHorizontal : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutHorizontal; } + + ThemeLayoutHorizontal(ThemeLayout *p) : ThemeLayout(p) {} + + const char *getName() { return "Horizontal Layout"; } + + void reflowLayout() { + int curX, curY, mul; + + if (parsingMode == kLayoutParseLeft2Right) { + curX = paddingLeft; + curY = paddingTop; + mul = 1; + } else { + curX = getParentW() - paddingRight; + curY = paddingTop; + mul = -1; + } + + w = paddingLeft + paddingRight; + + for (uint i = 0; i < children.size(); ++i) { + assert(children[i]->getLayoutType() != kLayoutHorizontal); + + children[i]->reflowLayout(); + + if (i != children.size() - 1) + assert(children[i]->w != -1); + + if (i == 0) + assert(children[i]->h != -1); + + + children[i]->setX((parsingMode == kLayoutParseRight2Left) ? (curX - children[i]->w) : (curX)); + children[i]->setY(curY); + + if (children[i]->h == -1) + children[i]->h = h - paddingTop - paddingBottom; + + h = MAX(h, (int16)(children[i]->h + paddingTop + paddingBottom)); + + curX += (children[i]->w + spacing) * mul; + w += children[i]->w + spacing; + } + } +}; + +class ThemeLayoutWidget : public ThemeLayout { +public: + LayoutType getLayoutType() { return kLayoutWidget; } + void reflowLayout() { + + } + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p), widgetName(name) {} + + const char *getName() { return widgetName.c_str(); } + + Common::String widgetName; +}; + class ThemeEval { typedef Common::HashMap VariablesMap; + typedef Common::HashMap LayoutsMap; public: ThemeEval() {} @@ -64,6 +288,67 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } + void addDialog(const Common::String &name) { + ThemeLayout *layout = new ThemeLayout(0); + _layouts[name] = layout; + + layout->x = 0; + layout->y = 0; + layout->w = g_system->getOverlayWidth(); + layout->h = g_system->getOverlayHeight(); + + layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); + layout->paddingTop = getVar("Globals.Padding.Top", 0); + layout->paddingRight = getVar("Globals.Padding.Right", 0); + layout->paddingLeft = getVar("Globals.Padding.Left", 0); + + _curLayout.push(layout); + } + + void addLayout(ThemeLayout::LayoutType type, ThemeLayout::LayoutParsing parsingMode) { + ThemeLayout *layout = 0; + ThemeLayout::LayoutParsing def = ThemeLayout::kLayoutParseDefault; + + if (type == ThemeLayout::kLayoutVertical) { + layout = new ThemeLayoutVertical(_curLayout.top()); + def = ThemeLayout::kLayoutParseTop2Bottom; + } else if (type == ThemeLayout::kLayoutHorizontal) { + layout = new ThemeLayoutHorizontal(_curLayout.top()); + def = ThemeLayout::kLayoutParseLeft2Right; + } + + layout->parsingMode = (parsingMode == ThemeLayout::kLayoutParseDefault) ? def : parsingMode; + layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); + layout->paddingTop = getVar("Globals.Padding.Top", 0); + layout->paddingRight = getVar("Globals.Padding.Right", 0); + layout->paddingLeft = getVar("Globals.Padding.Left", 0); + + layout->spacing = 4; + + _curLayout.top()->children.push_back(layout); + _curLayout.push(layout); + } + + void closeLayout() { + _curLayout.pop(); + } + + void closeDialog() { + _curLayout.top()->reflowLayout(); + printf("DEBUG LAYOUT PRINT:\n"); + + _curLayout.top()->debugPrint(); + } + + void addWidget(const Common::String &name, int w, int h) { + ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name); + + widget->w = w; + widget->h = h; + + _curLayout.top()->children.push_back(widget); + } + void debugPrint() { printf("Debug variable list:\n"); @@ -72,9 +357,15 @@ public: printf(" '%s' = %d\n", i->_key.c_str(), i->_value); } } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + _curLayout.top()->debugDraw(screen, font); + } private: VariablesMap _vars; + LayoutsMap _layouts; + Common::Stack _curLayout; }; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 310d3d880d..530f613fdb 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -88,7 +88,7 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { step->fillMode = Graphics::VectorRenderer::kFillDisabled; step->scale = (1 << 16); step->shadow = 0; - step->innerShadow = 0; + step->bevel = 0; step->stroke = 0; step->radius = 0xFF; @@ -307,7 +307,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } __PARSER_ASSIGN_INT(stroke, "stroke", false); - __PARSER_ASSIGN_INT(innerShadow, "inner_shadow", false); + __PARSER_ASSIGN_INT(bevel, "bevel", false); __PARSER_ASSIGN_INT(shadow, "shadow", false); __PARSER_ASSIGN_INT(factor, "gradient_factor", false); @@ -315,6 +315,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst __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")); @@ -449,16 +450,35 @@ bool ThemeParser::parserCallback_def(ParserNode *node) { bool ThemeParser::parserCallback_widget(ParserNode *node) { Common::String var; - if (getParentNode(node)->name == "globals") + if (getParentNode(node)->name == "globals") { var = "Globals." + node->values["name"] + "."; - else if (getParentNode(node)->name == "dialog") - var = "Dialog." + getParentNode(node)->values["name"] + "." + node->values["name"] + "."; - else - assert(!"Corruption in XML parser."); - - if (!parseCommonLayoutProps(node, var)) - return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); - + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + } else { + var = node->values["name"]; + int width = -1; + int height = -1; + + if (node->values.contains("width")) { + if (_theme->themeEval()->hasVar(node->values["width"]) == true) + width = _theme->themeEval()->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->themeEval()->hasVar(node->values["height"]) == true) + height = _theme->themeEval()->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()); + } + + _theme->themeEval()->addWidget(var, width, height); + + } + return true; } @@ -474,8 +494,35 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"] + "."; - if (!parseCommonLayoutProps(node, var)) - return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); +// if (!parseCommonLayoutProps(node, var)) +// return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + _theme->themeEval()->addDialog(var); + + return true; +} + +bool ThemeParser::parserCallback_layout(ParserNode *node) { + + if (!node->values.contains("type")) + return parserError("Layouts need a specific type (vertical or horizontal)."); + + GUI::ThemeLayout::LayoutType type = GUI::ThemeLayout::kLayoutNone; + + if (node->values["type"] == "vertical") + type = GUI::ThemeLayout::kLayoutVertical; + else if (node->values["type"] == "horizontal") + type = GUI::ThemeLayout::kLayoutHorizontal; + + _theme->themeEval()->addLayout(type, GUI::ThemeLayout::kLayoutParseDefault); + return true; +} + +bool ThemeParser::closedKeyCallback(ParserNode *node) { + if (node->name == "layout") + _theme->themeEval()->closeLayout(); + else if (node->name == "dialog") + _theme->themeEval()->closeDialog(); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index ec7f494735..07bb530894 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -351,12 +351,13 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, 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(bevel_color, false) XML_PROP(gradient_factor, false) XML_PROP(fill, false) KEY_END() @@ -368,12 +369,13 @@ protected: XML_KEY(defaults) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, 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(bevel_color, false) XML_PROP(gradient_factor, false) XML_PROP(fill, false) KEY_END() @@ -382,13 +384,14 @@ protected: XML_PROP(func, true) XML_PROP(stroke, false) XML_PROP(shadow, false) - XML_PROP(inner_shadow, false) + XML_PROP(bevel, 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(bevel_color, false) XML_PROP(fill, false) XML_PROP(bevel, false) XML_PROP(radius, false) @@ -432,15 +435,21 @@ protected: 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) + XML_KEY(layout) + XML_PROP(type, true) + XML_PROP(align, false) + XML_PROP(direction, false) + XML_KEY(widget) + XML_PROP(name, true) + XML_PROP(width, false) + XML_PROP(height, false) + KEY_END() + + XML_KEY(space) + XML_PROP(size, true) + KEY_END() + + XML_KEY_RECURSIVE(layout) KEY_END() KEY_END() KEY_END() @@ -465,6 +474,10 @@ protected: bool parserCallback_widget(ParserNode *node); bool parserCallback_dialog(ParserNode *node); bool parserCallback_child(ParserNode *node); + bool parserCallback_layout(ParserNode *node); + bool parserCallback_space(ParserNode *node) { return true; } + + bool closedKeyCallback(ParserNode *node); void cleanup(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 9a01b18299..f154f018b9 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -693,8 +693,11 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } - renderDirtyScreen(); -// _vectorRenderer->copyWholeFrame(_system); +// renderDirtyScreen(); + + _vectorRenderer->fillSurface(); + themeEval()->debugDraw(_screen, _font); + _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index b2e9cf43b0..3c58633923 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -163,6 +163,7 @@ bool NewGui::loadNewTheme(const Common::String &style) { cfg.clear(); */ _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxAntialias16bit); +// _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxStandard16bit); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); @@ -244,6 +245,8 @@ void NewGui::runLoop() { } Common::EventManager *eventMan = _system->getEventManager(); + uint32 lastRedraw = 0; + const uint32 waitTime = 1000 / 45; while (!_dialogStack.empty() && activeDialog == getTopDialog()) { redraw(); @@ -255,9 +258,15 @@ void NewGui::runLoop() { if (_useStdCursor) animateCursor(); - _theme->updateScreen(); - _system->updateScreen(); - +// _theme->updateScreen(); +// _system->updateScreen(); + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } + Common::Event event; while (eventMan->pollEvent(event)) { @@ -280,6 +289,12 @@ void NewGui::runLoop() { _redrawStatus = kRedrawFull; redraw(); } + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } switch (event.type) { case Common::EVENT_KEYDOWN: diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 20d3e3869f..fb5bd8dcf3 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index dce8495ff8..c26a7856af 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -52,6 +52,9 @@ + @@ -81,7 +84,7 @@ /> - + @@ -314,10 +318,11 @@ radius = '6' stroke = 1 fill = 'gradient' - shadow = 2 - fg_color = 'blandyellow' + shadow = 0 + fg_color = 'shadowcolor' gradient_start = 'brightred' gradient_end = 'darkred' + bevel = 1 /> @@ -329,11 +334,14 @@ @@ -361,7 +369,8 @@ radius = 4 fg_color = 'black' shadow = 0 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -377,8 +386,8 @@ gradient_start = 'brightred' gradient_end = 'darkred' shadow = 0 - stroke = 1 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -392,7 +401,8 @@ radius = 4 fg_color = 'blandyellow' shadow = 0 - inner_shadow = 1 + bevel = 1 + bevel_color = 'shadowcolor' /> @@ -410,9 +420,14 @@ - + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From dd46f8305e5c430b3af5511e81f621262149380d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 4 Aug 2008 17:44:18 +0000 Subject: Layout parsing. Work in progress. Looks like a GUI! svn-id: r33616 --- gui/ThemeEval.h | 35 ++++++++++++++++++----------------- gui/ThemeParser.cpp | 8 +++++++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index f53dfe2cd1..2c57e2732c 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -79,8 +79,8 @@ public: virtual const char *getName() { return "Global Layout"; } - int16 getParentW() { return parent ? parent->w : g_system->getOverlayWidth(); } - int16 getParentH() { return parent ? parent->w : g_system->getOverlayHeight(); } + int16 getParentW() { return parent ? parent->w - parent->paddingLeft - parent->paddingRight : g_system->getOverlayWidth(); } + int16 getParentH() { return parent ? parent->h - parent->paddingTop - parent->paddingBottom : g_system->getOverlayHeight(); } int16 getParentX() { return parent ? parent->x : 0; } int16 getParentY() { return parent ? parent->y : 0; } @@ -209,18 +209,10 @@ public: const char *getName() { return "Horizontal Layout"; } void reflowLayout() { - int curX, curY, mul; - - if (parsingMode == kLayoutParseLeft2Right) { - curX = paddingLeft; - curY = paddingTop; - mul = 1; - } else { - curX = getParentW() - paddingRight; - curY = paddingTop; - mul = -1; - } - + int curX, curY; + + curX = paddingLeft; + curY = paddingTop; w = paddingLeft + paddingRight; for (uint i = 0; i < children.size(); ++i) { @@ -235,15 +227,24 @@ public: assert(children[i]->h != -1); - children[i]->setX((parsingMode == kLayoutParseRight2Left) ? (curX - children[i]->w) : (curX)); + children[i]->setX(curX); children[i]->setY(curY); if (children[i]->h == -1) children[i]->h = h - paddingTop - paddingBottom; + + if (children[i]->w == -1) + children[i]->w = getParentW() - w - spacing; h = MAX(h, (int16)(children[i]->h + paddingTop + paddingBottom)); - - curX += (children[i]->w + spacing) * mul; + + if (parsingMode == kLayoutParseRight2Left) { + for (int j = i - 1; j >= 0; --j) + children[j]->setX(children[i]->w + spacing); + } else { + curX += (children[i]->w + spacing); + } + w += children[i]->w + spacing; } } diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 530f613fdb..982a2b59ae 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -508,13 +508,19 @@ bool ThemeParser::parserCallback_layout(ParserNode *node) { return parserError("Layouts need a specific type (vertical or horizontal)."); GUI::ThemeLayout::LayoutType type = GUI::ThemeLayout::kLayoutNone; + GUI::ThemeLayout::LayoutParsing parsing = GUI::ThemeLayout::kLayoutParseDefault; if (node->values["type"] == "vertical") type = GUI::ThemeLayout::kLayoutVertical; else if (node->values["type"] == "horizontal") type = GUI::ThemeLayout::kLayoutHorizontal; + + if (node->values.contains("direction")) { + if (node->values["direction"] == "right2left") + parsing = GUI::ThemeLayout::kLayoutParseRight2Left; + } - _theme->themeEval()->addLayout(type, GUI::ThemeLayout::kLayoutParseDefault); + _theme->themeEval()->addLayout(type, parsing); return true; } -- cgit v1.2.3 From 70ef50343499ee6736389a0cad006ea6eeeca5bd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Aug 2008 09:54:36 +0000 Subject: Massive refactoring on the layout parsing API. Added support for layout spacings. Fixed bug in theme conversion python script. svn-id: r33630 --- common/xmlparser.h | 2 +- dists/msvc9/scummvm.vcproj | 4 + gui/ThemeEval.h | 373 +++++++++++++++++---------------------------- gui/ThemeParser.cpp | 33 ++-- gui/ThemeParser.h | 6 +- gui/ThemeRenderer.h | 2 + gui/module.mk | 1 + gui/newgui.h | 3 + gui/theme.h | 2 + gui/themes/default.inc | 2 +- gui/themes/makedeftheme.py | 3 +- gui/themes/modern.stx | 2 +- 12 files changed, 171 insertions(+), 262 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index 0510ec0ab6..2f73b5905d 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -504,7 +504,7 @@ protected: while (isValidNameChar(_text[_pos])) _token += _text[_pos++]; - return isspace(_text[_pos]) != 0 || _text[_pos] == '>' || _text[_pos] == '='; + return isspace(_text[_pos]) != 0 || _text[_pos] == '>' || _text[_pos] == '=' || _text[_pos] == '/'; } /** diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 5da3451ded..1a6d3519c8 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1243,6 +1243,10 @@ RelativePath="..\..\gui\ThemeRenderer.cpp" > + + diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 2c57e2732c..87af99c944 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -40,227 +40,179 @@ namespace GUI { class ThemeLayout { -public: - int16 x, y, w, h; - int paddingTop, paddingBottom, paddingLeft, paddingRight; - int spacing; - Common::Array children; - ThemeLayout *parent; - uint16 debugcolor; - +public: enum LayoutType { - kLayoutNone, + kLayoutMain, kLayoutVertical, kLayoutHorizontal, kLayoutWidget }; - enum LayoutParsing { - kLayoutParseDefault, - kLayoutParseTop2Bottom, - kLayoutParseBottom2Top, - kLayoutParseLeft2Right, - kLayoutParseRight2Left - } parsingMode; + ThemeLayout(ThemeLayout *p, const Common::String &name) : + _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), _reverse(false), + _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0) { } + + virtual ~ThemeLayout() { + _children.clear(); + } + + virtual void reflowLayout() = 0; + + void addChild(ThemeLayout *child) { _children.push_back(child); } + + void setPadding(int8 left, int8 right, int8 top, int8 bottom) { + _paddingLeft = left; + _paddingRight = right; + _paddingTop = top; + _paddingBottom = bottom; + } - virtual LayoutType getLayoutType() { return kLayoutNone; } - virtual void reflowLayout() { - assert(children.size() <= 1); + void setSpacing(int8 spacing) { + _spacing = spacing; + } + + int16 getParentX() { return _parent ? _parent->_x : 0; } + int16 getParentY() { return _parent ? _parent->_y : 0; } + + int16 getParentW() { + ThemeLayout *p = _parent; + int width = 0; - if (children.size()) { - children[0]->w = w; - children[0]->h = h; - children[0]->reflowLayout(); - children[0]->setX(0); - children[0]->setY(0); + while (p && p->getLayoutType() != kLayoutMain) { + width += p->_paddingRight + p->_paddingLeft; + if (p->getLayoutType() == kLayoutHorizontal) { + for (uint i = 0; i < p->_children.size(); ++i) + if (p->_children[i]->getLayoutType() == kLayoutWidget) + width += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; } + + return p->getWidth() - width; } - virtual const char *getName() { return "Global Layout"; } + int16 getParentH() { + ThemeLayout *p = _parent; + int height = 0; + + while (p && p->getLayoutType() != kLayoutMain) { + height += p->_paddingBottom + p->_paddingTop; + if (p->getLayoutType() == kLayoutVertical) { + for (uint i = 0; i < p->_children.size(); ++i) + if (p->_children[i]->getLayoutType() == kLayoutWidget) + height += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; + } + + return p->getHeight() - height; + } - int16 getParentW() { return parent ? parent->w - parent->paddingLeft - parent->paddingRight : g_system->getOverlayWidth(); } - int16 getParentH() { return parent ? parent->h - parent->paddingTop - parent->paddingBottom : g_system->getOverlayHeight(); } - int16 getParentX() { return parent ? parent->x : 0; } - int16 getParentY() { return parent ? parent->y : 0; } + int16 getX() { return _x; } + int16 getY() { return _y; } + int16 getWidth() { return _w; } + int16 getHeight() { return _h; } void setX(int newX) { - x += newX; - for (uint i = 0; i < children.size(); ++i) - children[i]->setX(newX); + _x += newX; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setX(newX); } void setY(int newY) { - y += newY; - for (uint i = 0; i < children.size(); ++i) - children[i]->setY(newY); + _y += newY; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setY(newY); } - ThemeLayout(ThemeLayout *p) : parent(p), x(0), y(0), w(-1), h(-1) { debugcolor = rand() % 0xFFFF; } + void setWidth(int16 width) { _w = width; } + void setHeight(int16 height) { _h = height; } - virtual void debugPrintIndent(int indent) { - while (indent--) - printf(" "); - } - void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - uint16 color = debugcolor; - font->drawString(screen, getName(), x, y, w, color, Graphics::kTextAlignRight, 0, true); - screen->hLine(x, y, x + w, color); - screen->hLine(x, y + h, x + w, color); - screen->vLine(x, y, y + h, color); - screen->vLine(x + w, y, y + h, color); + uint16 color = 0xFFFF; + font->drawString(screen, getName(), _x, _y, _w, color, Graphics::kTextAlignRight, 0, true); + screen->hLine(_x, _y, _x + _w, color); + screen->hLine(_x, _y + _h, _x + _w , color); + screen->vLine(_x, _y, _y + _h, color); + screen->vLine(_x + _w, _y, _y + _h, color); - for (uint i = 0; i < children.size(); ++i) - children[i]->debugDraw(screen, font); + for (uint i = 0; i < _children.size(); ++i) + _children[i]->debugDraw(screen, font); } - virtual void debugPrint(int indent = 0) { - debugPrintIndent(indent); - switch (getLayoutType()) { - case kLayoutNone: - printf("Dialog Layout :: "); - break; - - case kLayoutVertical: - printf("Vertical Layout :: "); - break; - - case kLayoutHorizontal: - printf("Horizontal Layout :: "); - break; - - case kLayoutWidget: - printf("WIDGET (%s) :: ", getName()); - break; - } + virtual LayoutType getLayoutType() = 0; + virtual const char *getName() { return _name.c_str(); } - printf("X: %d / Y: %d / W: %d / H: %d\n", x, y, w, h); - - for (uint i = 0; i < children.size(); ++i) - children[i]->debugPrint(indent + 1); - } + virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h); - virtual ~ThemeLayout() { - children.clear(); - } +protected: + int16 _x, _y, _w, _h; + int8 _paddingTop, _paddingBottom, _paddingLeft, _paddingRight; + int8 _spacing; + Common::Array _children; + ThemeLayout *_parent; + bool _reverse; + Common::String _name; }; -class ThemeLayoutVertical : public ThemeLayout { +class ThemeLayoutMain : public ThemeLayout { public: - LayoutType getLayoutType() { return kLayoutVertical; } - - ThemeLayoutVertical(ThemeLayout *p) : ThemeLayout(p) {} - - const char *getName() { return "Vertical Layout"; } - - void reflowLayout() { - int curX, curY, mul; - - if (parsingMode == kLayoutParseTop2Bottom) { - curX = paddingLeft; - curY = paddingTop; - mul = 1; - } else { - curX = paddingLeft; - curY = getParentH() - paddingBottom; - mul = -1; - } + ThemeLayoutMain() : ThemeLayout(0, "") {} + void reflowLayout(); + const char *getName() { return "Global Layout"; } + LayoutType getLayoutType() { return kLayoutMain; } +}; - h = paddingTop + paddingBottom; - - for (uint i = 0; i < children.size(); ++i) { - assert(children[i]->getLayoutType() != kLayoutVertical); - - children[i]->reflowLayout(); - - if (i != children.size() - 1) - assert(children[i]->h != -1); - - if (i == 0) - assert(children[i]->w != -1); - - children[i]->setX(curX); - children[i]->setY((parsingMode == kLayoutParseBottom2Top) ? curY - children[i]->h : curY); - - if (children[i]->w == -1) - children[i]->w = w - paddingLeft - paddingRight; - - w = MAX(w, (int16)(children[i]->w + paddingLeft + paddingRight)); - - if (children[i]->h == -1) - children[i]->h = 32; - - h += children[i]->h + spacing; - - curY += (children[i]->h + spacing) * mul; - } - - +class ThemeLayoutVertical : public ThemeLayout { +public: + ThemeLayoutVertical(ThemeLayout *p, int spacing, bool reverse) : ThemeLayout(p, "") { + _spacing = spacing; + _reverse = reverse; } + + void reflowLayout(); + const char *getName() { return "Vertical Layout"; } + LayoutType getLayoutType() { return kLayoutVertical; } }; class ThemeLayoutHorizontal : public ThemeLayout { public: - LayoutType getLayoutType() { return kLayoutHorizontal; } - - ThemeLayoutHorizontal(ThemeLayout *p) : ThemeLayout(p) {} - - const char *getName() { return "Horizontal Layout"; } - - void reflowLayout() { - int curX, curY; - - curX = paddingLeft; - curY = paddingTop; - w = paddingLeft + paddingRight; - - for (uint i = 0; i < children.size(); ++i) { - assert(children[i]->getLayoutType() != kLayoutHorizontal); - - children[i]->reflowLayout(); - - if (i != children.size() - 1) - assert(children[i]->w != -1); - - if (i == 0) - assert(children[i]->h != -1); - - - children[i]->setX(curX); - children[i]->setY(curY); - - if (children[i]->h == -1) - children[i]->h = h - paddingTop - paddingBottom; - - if (children[i]->w == -1) - children[i]->w = getParentW() - w - spacing; - - h = MAX(h, (int16)(children[i]->h + paddingTop + paddingBottom)); - - if (parsingMode == kLayoutParseRight2Left) { - for (int j = i - 1; j >= 0; --j) - children[j]->setX(children[i]->w + spacing); - } else { - curX += (children[i]->w + spacing); - } - - w += children[i]->w + spacing; - } + ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool reverse) : + ThemeLayout(p, "") { + _spacing = spacing; + _reverse = reverse; } + + void reflowLayout(); + const char *getName() { return "Horizontal Layout"; } + LayoutType getLayoutType() { return kLayoutHorizontal; } }; class ThemeLayoutWidget : public ThemeLayout { public: + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p, name) {} + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h); + void reflowLayout() {} LayoutType getLayoutType() { return kLayoutWidget; } - void reflowLayout() { - +}; + +class ThemeLayoutSpacing : public ThemeLayout { +public: + ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p, "") { + if (p->getLayoutType() == kLayoutHorizontal) { + _w = size; + _h = 1; + } else if (p->getLayoutType() == kLayoutVertical) { + _w = 1; + _h = size; + } } - ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p), widgetName(name) {} - const char *getName() { return widgetName.c_str(); } - - Common::String widgetName; + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { return false; } + void reflowLayout() {} + LayoutType getLayoutType() { return kLayoutWidget; } + const char *getName() { return "SPACE"; } }; class ThemeEval { @@ -275,7 +227,7 @@ public: int getVar(const Common::String &s) { if (!_vars.contains(s)) { warning("Missing variable: '%s'", s.c_str()); - return -1; + return -13375; //EVAL_UNDEF_VAR } return _vars[s]; @@ -289,66 +241,15 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } - void addDialog(const Common::String &name) { - ThemeLayout *layout = new ThemeLayout(0); - _layouts[name] = layout; - - layout->x = 0; - layout->y = 0; - layout->w = g_system->getOverlayWidth(); - layout->h = g_system->getOverlayHeight(); - - layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); - layout->paddingTop = getVar("Globals.Padding.Top", 0); - layout->paddingRight = getVar("Globals.Padding.Right", 0); - layout->paddingLeft = getVar("Globals.Padding.Left", 0); - - _curLayout.push(layout); - } - - void addLayout(ThemeLayout::LayoutType type, ThemeLayout::LayoutParsing parsingMode) { - ThemeLayout *layout = 0; - ThemeLayout::LayoutParsing def = ThemeLayout::kLayoutParseDefault; - - if (type == ThemeLayout::kLayoutVertical) { - layout = new ThemeLayoutVertical(_curLayout.top()); - def = ThemeLayout::kLayoutParseTop2Bottom; - } else if (type == ThemeLayout::kLayoutHorizontal) { - layout = new ThemeLayoutHorizontal(_curLayout.top()); - def = ThemeLayout::kLayoutParseLeft2Right; - } - - layout->parsingMode = (parsingMode == ThemeLayout::kLayoutParseDefault) ? def : parsingMode; - layout->paddingBottom = getVar("Globals.Padding.Bottom", 0); - layout->paddingTop = getVar("Globals.Padding.Top", 0); - layout->paddingRight = getVar("Globals.Padding.Right", 0); - layout->paddingLeft = getVar("Globals.Padding.Left", 0); - - layout->spacing = 4; - - _curLayout.top()->children.push_back(layout); - _curLayout.push(layout); - } + void addDialog(const Common::String &name); + void addLayout(ThemeLayout::LayoutType type, bool reverse); + void addWidget(const Common::String &name, int w, int h); + void addSpacing(int size); - void closeLayout() { - _curLayout.pop(); - } + void closeLayout() { _curLayout.pop(); } + void closeDialog() { _curLayout.pop()->reflowLayout(); } - void closeDialog() { - _curLayout.top()->reflowLayout(); - printf("DEBUG LAYOUT PRINT:\n"); - - _curLayout.top()->debugPrint(); - } - void addWidget(const Common::String &name, int w, int h) { - ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name); - - widget->w = w; - widget->h = h; - - _curLayout.top()->children.push_back(widget); - } void debugPrint() { printf("Debug variable list:\n"); @@ -360,7 +261,7 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _curLayout.top()->debugDraw(screen, font); + _layouts["Dialog.Launcher"]->debugDraw(screen, font); } private: diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 982a2b59ae..889acfedba 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -492,11 +492,7 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { } bool ThemeParser::parserCallback_dialog(ParserNode *node) { - Common::String var = "Dialog." + node->values["name"] + "."; - -// if (!parseCommonLayoutProps(node, var)) -// return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); - + Common::String var = "Dialog." + node->values["name"]; _theme->themeEval()->addDialog(var); return true; @@ -504,23 +500,22 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { bool ThemeParser::parserCallback_layout(ParserNode *node) { - if (!node->values.contains("type")) - return parserError("Layouts need a specific type (vertical or horizontal)."); - - GUI::ThemeLayout::LayoutType type = GUI::ThemeLayout::kLayoutNone; - GUI::ThemeLayout::LayoutParsing parsing = GUI::ThemeLayout::kLayoutParseDefault; - if (node->values["type"] == "vertical") - type = GUI::ThemeLayout::kLayoutVertical; + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, node->values["direction"] == "bottom2top"); else if (node->values["type"] == "horizontal") - type = GUI::ThemeLayout::kLayoutHorizontal; + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, node->values["direction"] == "right2left"); - if (node->values.contains("direction")) { - if (node->values["direction"] == "right2left") - parsing = GUI::ThemeLayout::kLayoutParseRight2Left; - } - - _theme->themeEval()->addLayout(type, parsing); + return true; +} + +bool ThemeParser::parserCallback_space(ParserNode *node) { + int size = -1; + + if (node->values.contains("size")) + if (!parseIntegerKey(node->values["size"].c_str(), 1, &size)) + return parserError("Invalid value for Spacing size."); + + _theme->themeEval()->addSpacing(size); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 07bb530894..e94e8cbc8e 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -439,6 +439,8 @@ protected: XML_PROP(type, true) XML_PROP(align, false) XML_PROP(direction, false) + XML_PROP(padding, false) + XML_PROP(spacing, false) XML_KEY(widget) XML_PROP(name, true) XML_PROP(width, false) @@ -446,7 +448,7 @@ protected: KEY_END() XML_KEY(space) - XML_PROP(size, true) + XML_PROP(size, false) KEY_END() XML_KEY_RECURSIVE(layout) @@ -475,7 +477,7 @@ protected: bool parserCallback_dialog(ParserNode *node); bool parserCallback_child(ParserNode *node); bool parserCallback_layout(ParserNode *node); - bool parserCallback_space(ParserNode *node) { return true; } + bool parserCallback_space(ParserNode *node); bool closedKeyCallback(ParserNode *node); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 7c18f73fea..35d2f31d40 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -412,6 +412,8 @@ public: void finishBuffering() { _buffering = false; } + + void *evaluator() { return _themeEval; } protected: diff --git a/gui/module.mk b/gui/module.mk index 4afe11201a..0711f236a4 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -24,6 +24,7 @@ MODULE_OBJS := \ themebrowser.o \ widget.o \ theme.o \ + ThemeEval.o \ ThemeClassic.o \ ThemeModern.o \ ThemeParser.o \ diff --git a/gui/newgui.h b/gui/newgui.h index ae58b2efe8..5fabe4ea1f 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -39,6 +39,7 @@ namespace GUI { class Dialog; class Eval; +class ThemeEval; #define g_gui (GUI::NewGui::instance()) @@ -77,7 +78,9 @@ public: bool loadNewTheme(const Common::String &file); Theme *theme() { return _theme; } + Eval *evaluator() { return _theme->_evaluator; } + ThemeEval *xmlEval() { return (ThemeEval*)_theme->evaluator(); } const Graphics::Font &getFont(Theme::FontStyle style = Theme::kFontStyleBold) const { return *(_theme->getFont(style)); } int getFontHeight(Theme::FontStyle style = Theme::kFontStyleBold) const { return _theme->getFontHeight(style); } diff --git a/gui/theme.h b/gui/theme.h index f8a4946a6b..0d0fadb8ad 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -365,6 +365,8 @@ public: void loadTheme(Common::ConfigFile &config, bool reset = true); void loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing); Eval *_evaluator; + + virtual void *evaluator() { return (void*)_evaluator; } static bool themeConfigUseable(const Common::String &file, const Common::String &style="", Common::String *cStyle=0, Common::ConfigFile *cfg=0); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index fb5bd8dcf3..04fd941819 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/makedeftheme.py b/gui/themes/makedeftheme.py index fc09e6b1f0..f347516fff 100644 --- a/gui/themes/makedeftheme.py +++ b/gui/themes/makedeftheme.py @@ -6,14 +6,13 @@ import re def main(): theme_file = open(sys.argv[1], "r") def_file = open("default.inc", "w") - comment = re.compile("\/\*(.*)\*\/") try: output = "\"" for line in theme_file: output += (line.rstrip("\n\r ").lstrip() + " ") - output = re.sub("\/\*(.*)\*\/", "", output) + output = re.sub("\/\*(.*?)\*\/", "", output) def_file.write(output + "\"\n") finally: theme_file.close() diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index c26a7856af..b13dc1fc98 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -480,7 +480,6 @@ width = 'Globals.Button.Width' height = 'Globals.Button.Height' /> - + -- cgit v1.2.3 From fdf485ea9bd84e07c8af1f2741af9078b6a9fcf6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Aug 2008 10:03:53 +0000 Subject: Missing file in last commit. svn-id: r33631 --- gui/ThemeEval.cpp | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 gui/ThemeEval.cpp diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp new file mode 100644 index 0000000000..ec5c1e6abd --- /dev/null +++ b/gui/ThemeEval.cpp @@ -0,0 +1,201 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" + +namespace GUI { + +bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { + if (name == _name) { + x = _x; y = _y; + w = _w; h = _h; + return true; + } + + return false; +} + +bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { + for (uint i = 0; i < _children.size(); ++i) { + if (_children[i]->getWidgetData(name, x, y, w, h)) + return true; + } + + return false; +} + +void ThemeLayoutMain::reflowLayout() { + assert(_children.size() <= 1); + + if (_children.size()) { + _children[0]->setWidth(_w); + _children[0]->setHeight(_h); + _children[0]->reflowLayout(); + } +} + +void ThemeLayoutVertical::reflowLayout() { + int curX, curY; + + curX = _paddingLeft; + curY = _paddingTop; + _h = _paddingTop + _paddingBottom; + + for (uint i = 0; i < _children.size(); ++i) { + assert(_children[i]->getLayoutType() != kLayoutVertical); + + _children[i]->reflowLayout(); + + if (i != _children.size() - 1) + assert(_children[i]->getHeight() != -1); + + if (i == 0) + assert(_children[i]->getWidth() != -1); + + _children[i]->setX(curX); + _children[i]->setY(curY); + + if (_children[i]->getWidth() == -1) + _children[i]->setWidth(_w - _paddingLeft - _paddingRight); + + if (_children[i]->getHeight() == -1) + _children[i]->setHeight(getParentH() - _h - _spacing); + + if (_reverse) { + for (int j = i - 1; j >= 0; --j) + _children[j]->setY(_children[i]->getHeight() + _spacing); + } else { + curY += _children[i]->getHeight() + _spacing; + } + + _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); + _h += _children[i]->getHeight() + _spacing; + } +} + +void ThemeLayoutHorizontal::reflowLayout() { + int curX, curY; + + curX = _paddingLeft; + curY = _paddingTop; + _w = _paddingLeft + _paddingRight; + + for (uint i = 0; i < _children.size(); ++i) { + assert(_children[i]->getLayoutType() != kLayoutHorizontal); + + _children[i]->reflowLayout(); + + if (i != _children.size() - 1) + assert(_children[i]->getWidth() != -1); + + if (i == 0) + assert(_children[i]->getHeight() != -1); + + _children[i]->setX(curX); + _children[i]->setY(curY); + + if (_children[i]->getHeight() == -1) + _children[i]->setHeight(_h - _paddingTop - _paddingBottom); + + if (_children[i]->getWidth() == -1) + _children[i]->setWidth(getParentW() - _w - _spacing); + + if (_reverse) { + for (int j = i - 1; j >= 0; --j) + _children[j]->setX(_children[i]->getWidth() + _spacing); + } else { + curX += (_children[i]->getWidth() + _spacing); + } + + _w += _children[i]->getWidth() + _spacing; + _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); + } +} + + +void ThemeEval::addWidget(const Common::String &name, int w, int h) { + ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name); + + widget->setWidth(w); + widget->setHeight(h); + + _curLayout.top()->addChild(widget); +} + +void ThemeEval::addDialog(const Common::String &name) { + ThemeLayout *layout = new ThemeLayoutMain(); + _layouts[name] = layout; + + layout->setX(0); + layout->setY(0); + layout->setWidth(g_system->getOverlayWidth()); + layout->setHeight(g_system->getOverlayHeight()); + + layout->setPadding( + getVar("Globals.Padding.Left", 0), + getVar("Globals.Padding.Right", 0), + getVar("Globals.Padding.Top", 0), + getVar("Globals.Padding.Bottom", 0) + ); + + _curLayout.push(layout); +} + +void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse) { + ThemeLayout *layout = 0; + + if (type == ThemeLayout::kLayoutVertical) + layout = new ThemeLayoutVertical(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse); + else if (type == ThemeLayout::kLayoutHorizontal) + layout = new ThemeLayoutHorizontal(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse); + + layout->setPadding( + getVar("Globals.Padding.Left", 0), + getVar("Globals.Padding.Right", 0), + getVar("Globals.Padding.Top", 0), + getVar("Globals.Padding.Bottom", 0) + ); + + layout->setSpacing(4); + + _curLayout.top()->addChild(layout); + _curLayout.push(layout); +} + +void ThemeEval::addSpacing(int size) { + ThemeLayout *space = new ThemeLayoutSpacing(_curLayout.top(), size); + _curLayout.top()->addChild(space); +} + +} -- cgit v1.2.3 From eb3d163439455fb941be0de73c1b3d28f3414c20 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Aug 2008 16:23:17 +0000 Subject: Look, the launcher is rendered with the new layout parser. svn-id: r33641 --- gui/ThemeEval.cpp | 28 +++++++++++++++------------- gui/ThemeEval.h | 34 ++++++++++++++++++++++++++-------- gui/ThemeParser.cpp | 18 ++++++++++++++++-- gui/ThemeParser.h | 2 +- gui/ThemeRenderer.cpp | 8 ++++---- gui/launcher.cpp | 24 ++++++++++++------------ gui/newgui.cpp | 10 +++------- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 11 +++++++---- 9 files changed, 85 insertions(+), 52 deletions(-) diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index ec5c1e6abd..e13ccc0176 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -36,7 +36,7 @@ namespace GUI { -bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { +bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { if (name == _name) { x = _x; y = _y; w = _w; h = _h; @@ -46,7 +46,7 @@ bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int1 return false; } -bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { +bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { for (uint i = 0; i < _children.size(); ++i) { if (_children[i]->getWidgetData(name, x, y, w, h)) return true; @@ -82,15 +82,19 @@ void ThemeLayoutVertical::reflowLayout() { if (i == 0) assert(_children[i]->getWidth() != -1); - - _children[i]->setX(curX); - _children[i]->setY(curY); if (_children[i]->getWidth() == -1) _children[i]->setWidth(_w - _paddingLeft - _paddingRight); if (_children[i]->getHeight() == -1) _children[i]->setHeight(getParentH() - _h - _spacing); + + _children[i]->setY(curY); + + if (_centered) + _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); + else + _children[i]->setX(curX); if (_reverse) { for (int j = i - 1; j >= 0; --j) @@ -121,9 +125,6 @@ void ThemeLayoutHorizontal::reflowLayout() { if (i == 0) assert(_children[i]->getHeight() != -1); - - _children[i]->setX(curX); - _children[i]->setY(curY); if (_children[i]->getHeight() == -1) _children[i]->setHeight(_h - _paddingTop - _paddingBottom); @@ -131,6 +132,9 @@ void ThemeLayoutHorizontal::reflowLayout() { if (_children[i]->getWidth() == -1) _children[i]->setWidth(getParentW() - _w - _spacing); + _children[i]->setX(curX); + _children[i]->setY(curY); + if (_reverse) { for (int j = i - 1; j >= 0; --j) _children[j]->setX(_children[i]->getWidth() + _spacing); @@ -172,13 +176,13 @@ void ThemeEval::addDialog(const Common::String &name) { _curLayout.push(layout); } -void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse) { +void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse, bool center) { ThemeLayout *layout = 0; if (type == ThemeLayout::kLayoutVertical) - layout = new ThemeLayoutVertical(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse); + layout = new ThemeLayoutVertical(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse, center); else if (type == ThemeLayout::kLayoutHorizontal) - layout = new ThemeLayoutHorizontal(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse); + layout = new ThemeLayoutHorizontal(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse, center); layout->setPadding( getVar("Globals.Padding.Left", 0), @@ -187,8 +191,6 @@ void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse) { getVar("Globals.Padding.Bottom", 0) ); - layout->setSpacing(4); - _curLayout.top()->addChild(layout); _curLayout.push(layout); } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 87af99c944..b412ba6798 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -51,7 +51,8 @@ public: ThemeLayout(ThemeLayout *p, const Common::String &name) : _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), _reverse(false), - _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0) { } + _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), + _centered(false) { } virtual ~ThemeLayout() { _children.clear(); @@ -144,7 +145,7 @@ public: virtual LayoutType getLayoutType() = 0; virtual const char *getName() { return _name.c_str(); } - virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h); + virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); protected: int16 _x, _y, _w, _h; @@ -153,6 +154,7 @@ protected: Common::Array _children; ThemeLayout *_parent; bool _reverse; + bool _centered; Common::String _name; }; @@ -166,9 +168,11 @@ public: class ThemeLayoutVertical : public ThemeLayout { public: - ThemeLayoutVertical(ThemeLayout *p, int spacing, bool reverse) : ThemeLayout(p, "") { + ThemeLayoutVertical(ThemeLayout *p, int spacing, bool reverse, bool center) : + ThemeLayout(p, "") { _spacing = spacing; _reverse = reverse; + _centered = center; } void reflowLayout(); @@ -178,10 +182,11 @@ public: class ThemeLayoutHorizontal : public ThemeLayout { public: - ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool reverse) : + ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool reverse, bool center) : ThemeLayout(p, "") { _spacing = spacing; _reverse = reverse; + _centered = center; } void reflowLayout(); @@ -192,7 +197,7 @@ public: class ThemeLayoutWidget : public ThemeLayout { public: ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p, name) {} - bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h); + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); void reflowLayout() {} LayoutType getLayoutType() { return kLayoutWidget; } }; @@ -209,7 +214,7 @@ public: } } - bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h) { return false; } + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { return false; } void reflowLayout() {} LayoutType getLayoutType() { return kLayoutWidget; } const char *getName() { return "SPACE"; } @@ -242,14 +247,27 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } void addDialog(const Common::String &name); - void addLayout(ThemeLayout::LayoutType type, bool reverse); + void addLayout(ThemeLayout::LayoutType type, bool reverse, bool center = false); void addWidget(const Common::String &name, int w, int h); void addSpacing(int size); + void addPadding(int16 l, int16 r, int16 t, int16 b) { + _curLayout.top()->setPadding(l, r, t, b); + } + void closeLayout() { _curLayout.pop(); } void closeDialog() { _curLayout.pop()->reflowLayout(); } - + bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { + Common::StringTokenizer tokenizer(widget, "."); + Common::String dialogName = "Dialog." + tokenizer.nextToken(); + Common::String widgetName = tokenizer.nextToken(); + + if (!_layouts.contains(dialogName)) + return false; + + return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); + } void debugPrint() { printf("Debug variable list:\n"); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 889acfedba..6c5c900f50 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -501,9 +501,23 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { bool ThemeParser::parserCallback_layout(ParserNode *node) { if (node->values["type"] == "vertical") - _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, node->values["direction"] == "bottom2top"); + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, + node->values["direction"] == "bottom2top", + node->values["center"] == "true"); + else if (node->values["type"] == "horizontal") - _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, node->values["direction"] == "right2left"); + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, + node->values["direction"] == "right2left", + node->values["center"] == "true"); + + 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->themeEval()->addPadding(paddingL, paddingR, paddingT, paddingB); + } return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index e94e8cbc8e..61d7262946 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -437,7 +437,7 @@ protected: XML_PROP(name, true) XML_KEY(layout) XML_PROP(type, true) - XML_PROP(align, false) + XML_PROP(center, false) XML_PROP(direction, false) XML_PROP(padding, false) XML_PROP(spacing, false) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index f154f018b9..4a83982c8c 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -693,11 +693,11 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } -// renderDirtyScreen(); + renderDirtyScreen(); - _vectorRenderer->fillSurface(); - themeEval()->debugDraw(_screen, _font); - _vectorRenderer->copyWholeFrame(_system); +// _vectorRenderer->fillSurface(); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 34c4ebf474..451c089d3a 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -481,35 +481,35 @@ LauncherDialog::LauncherDialog() #ifndef DISABLE_FANCY_THEMES _logo = 0; if (g_gui.evaluator()->getVar("launcher_logo.visible") == 1 && g_gui.theme()->supportsImages()) { - _logo = new GraphicsWidget(this, "launcher_logo"); + _logo = new GraphicsWidget(this, "Launcher.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(Theme::kImageLogo)); - new StaticTextWidget(this, "launcher_version", gScummVMVersionDate); + new StaticTextWidget(this, "Launcher.Version", gScummVMVersionDate); } else - new StaticTextWidget(this, "launcher_version", gScummVMFullVersion); + new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #else // Show ScummVM version - new StaticTextWidget(this, "launcher_version", gScummVMFullVersion); + new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #endif - new ButtonWidget(this, "launcher_quit_button", "Quit", kQuitCmd, 'Q'); - new ButtonWidget(this, "launcher_about_button", "About", kAboutCmd, 'B'); - new ButtonWidget(this, "launcher_options_button", "Options", kOptionsCmd, 'O'); + new ButtonWidget(this, "Launcher.QuitButton", "Quit", kQuitCmd, 'Q'); + new ButtonWidget(this, "Launcher.AboutButton", "About", kAboutCmd, 'B'); + new ButtonWidget(this, "Launcher.OptionsButton", "Options", kOptionsCmd, 'O'); _startButton = - new ButtonWidget(this, "launcher_start_button", "Start", kStartCmd, 'S'); + new ButtonWidget(this, "Launcher.StartButton", "Start", kStartCmd, 'S'); // Above the lowest button rows: two more buttons (directly below the list box) _addButton = - new ButtonWidget(this, "launcher_addGame_button", "Add Game...", kAddGameCmd, 'A'); + new ButtonWidget(this, "Launcher.AddGameButton", "Add Game...", kAddGameCmd, 'A'); _editButton = - new ButtonWidget(this, "launcher_editGame_button", "Edit Game...", kEditGameCmd, 'E'); + new ButtonWidget(this, "Launcher.EditGameButton", "Edit Game...", kEditGameCmd, 'E'); _removeButton = - new ButtonWidget(this, "launcher_removeGame_button", "Remove Game", kRemoveGameCmd, 'R'); + new ButtonWidget(this, "Launcher.RemoveGameButton", "Remove Game", kRemoveGameCmd, 'R'); // Add list with game titles - _list = new ListWidget(this, "launcher_list"); + _list = new ListWidget(this, "Launcher.GameList"); _list->setEditable(false); _list->setNumberingMode(kListNumberingOff); diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 3c58633923..e829a2c6f5 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -58,15 +58,11 @@ enum { void GuiObject::reflowLayout() { if (!_name.empty()) { - if ((_x = g_gui.evaluator()->getVar(_name + ".x")) == EVAL_UNDEF_VAR) - error("Undefined variable %s.x", _name.c_str()); - if ((_y = g_gui.evaluator()->getVar(_name + ".y")) == EVAL_UNDEF_VAR) - error("Undefined variable %s.y", _name.c_str()); - _w = g_gui.evaluator()->getVar(_name + ".w"); - _h = g_gui.evaluator()->getVar(_name + ".h"); + if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) + error("Could not load widget position for '%s'", _name.c_str()); if (_x < 0) - error("Widget <%s> has x < 0", _name.c_str()); + error("Widget <%s> has x < 0: %d", _name.c_str(), _x); if (_x >= g_system->getOverlayWidth()) error("Widget <%s> has x > %d", _name.c_str(), g_system->getOverlayWidth()); if (_x + _w > g_system->getOverlayWidth()) diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 04fd941819..d5ee4cc8b3 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index b13dc1fc98..e4fc5d5c3e 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -465,7 +465,7 @@ - + - - + + + + - + -- cgit v1.2.3 From 4256c357912bd9c2b554c22f09a2d0304e9de9a2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Aug 2008 23:58:45 +0000 Subject: Options menu layout parsing, featuring the brand new FATPOPUPS. svn-id: r33651 --- gui/ThemeEval.cpp | 21 ++++++++++++++++----- gui/ThemeEval.h | 19 +++++++++++++++++-- gui/ThemeParser.cpp | 2 +- gui/ThemeParser.h | 1 + gui/ThemeRenderer.cpp | 6 +++--- gui/dialog.cpp | 2 +- gui/newgui.cpp | 16 ++++++++++++++-- gui/object.h | 3 +++ gui/options.cpp | 42 +++++++++++++++++++++--------------------- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 40 +++++++++++++++++++++++++++++++++++++++- 11 files changed, 117 insertions(+), 37 deletions(-) diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index e13ccc0176..e2c34d8128 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -157,15 +157,26 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h) { _curLayout.top()->addChild(widget); } -void ThemeEval::addDialog(const Common::String &name) { +void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays) { ThemeLayout *layout = new ThemeLayoutMain(); _layouts[name] = layout; + + int16 x, y; + uint16 w, h; - layout->setX(0); - layout->setY(0); - layout->setWidth(g_system->getOverlayWidth()); - layout->setHeight(g_system->getOverlayHeight()); + if (overlays == "screen" || overlays.empty()) { + x = y = 0; + w = g_system->getOverlayWidth(); + h = g_system->getOverlayHeight(); + } else if (!getWidgetData(overlays, x, y, w, h)) { + error("Error when loading dialog position for '%s'", overlays.c_str()); + } + layout->setX(x); + layout->setY(y); + layout->setWidth(w); + layout->setHeight(h); + layout->setPadding( getVar("Globals.Padding.Left", 0), getVar("Globals.Padding.Right", 0), diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index b412ba6798..671a737336 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -146,6 +146,13 @@ public: virtual const char *getName() { return _name.c_str(); } virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + + virtual bool getDialogData(int16 &x, int16 &y, uint16 &w, uint16 &h) { + assert(getLayoutType() == kLayoutMain); + x = _x; y = _y; + w = _w; h = _h; + return true; + } protected: int16 _x, _y, _w, _h; @@ -246,7 +253,7 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } - void addDialog(const Common::String &name); + void addDialog(const Common::String &name, const Common::String &overlays); void addLayout(ThemeLayout::LayoutType type, bool reverse, bool center = false); void addWidget(const Common::String &name, int w, int h); void addSpacing(int size); @@ -261,10 +268,17 @@ public: bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { Common::StringTokenizer tokenizer(widget, "."); Common::String dialogName = "Dialog." + tokenizer.nextToken(); + + if (dialogName == "Dialog.Dialog") + dialogName = "Dialog." + tokenizer.nextToken(); + Common::String widgetName = tokenizer.nextToken(); if (!_layouts.contains(dialogName)) return false; + + if (widgetName.empty()) + return _layouts[dialogName]->getDialogData(x, y, w, h); return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); } @@ -279,7 +293,8 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.Launcher"]->debugDraw(screen, font); + _layouts["Dialog.GlobalOptions"]->debugDraw(screen, font); + _layouts["Dialog.GlobalOptions_Graphics"]->debugDraw(screen, font); } private: diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 6c5c900f50..fafe2ccad7 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -493,7 +493,7 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"]; - _theme->themeEval()->addDialog(var); + _theme->themeEval()->addDialog(var, node->values["overlays"]); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 61d7262946..e26a841fe6 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -435,6 +435,7 @@ protected: XML_KEY(dialog) XML_PROP(name, true) + XML_PROP(overlays, true) XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 4a83982c8c..474b927845 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -695,9 +695,9 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); -// _vectorRenderer->fillSurface(); -// themeEval()->debugDraw(_screen, _font); -// _vectorRenderer->copyWholeFrame(_system); +// _vectorRenderer->fillSurface(); + // themeEval()->debugDraw(_screen, _font); + // _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 0594941d65..ac9d0dbb4d 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -150,7 +150,7 @@ void Dialog::drawDialog() { // Draw all children Widget *w = _firstWidget; while (w) { - w->draw(); + if (w->_debugVisible) w->draw(); w = w->_next; } } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index e829a2c6f5..b8c953619c 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -58,8 +58,20 @@ enum { void GuiObject::reflowLayout() { if (!_name.empty()) { - if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) - error("Could not load widget position for '%s'", _name.c_str()); + if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { + warning("Could not load widget position for '%s'", _name.c_str()); + +// if ((_x = g_gui.evaluator()->getVar(_name + ".x")) == EVAL_UNDEF_VAR) +// error("Undefined variable %s.x", _name.c_str()); +// if ((_y = g_gui.evaluator()->getVar(_name + ".y")) == EVAL_UNDEF_VAR) +// error("Undefined variable %s.y", _name.c_str()); +// _w = g_gui.evaluator()->getVar(_name + ".w"); +// _h = g_gui.evaluator()->getVar(_name + ".h"); + _w = _x = _y = _h = 32; + _debugVisible = false; + } + + _debugVisible = true; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); diff --git a/gui/object.h b/gui/object.h index 01046bd668..9e5ea5fa60 100644 --- a/gui/object.h +++ b/gui/object.h @@ -78,7 +78,10 @@ public: virtual uint16 getWidth() const { return _w; } virtual uint16 getHeight() const { return _h; } +// Tanoku-TODO: fix this back virtual bool isVisible() const = 0; + bool _debugVisible; + virtual void draw() = 0; diff --git a/gui/options.cpp b/gui/options.cpp index d6f5306ce2..76c9f8ab82 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -659,27 +659,27 @@ void OptionsDialog::reflowLayout() { GlobalOptionsDialog::GlobalOptionsDialog() - : OptionsDialog(Common::ConfigManager::kApplicationDomain, "globaloptions") { + : OptionsDialog(Common::ConfigManager::kApplicationDomain, "GlobalOptions") { // The tab widget - TabWidget *tab = new TabWidget(this, "globaloptions_tabwidget"); + TabWidget *tab = new TabWidget(this, "GlobalOptions.TabWidget"); tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); // // 1) The graphics tab // tab->addTab("Graphics"); - addGraphicControls(tab, "globaloptions_"); + addGraphicControls(tab, "GlobalOptions_Graphics."); // // 2) The audio tab // tab->addTab("Audio"); - addAudioControls(tab, "globaloptions_"); - addSubtitleControls(tab, "globaloptions_"); + addAudioControls(tab, "GlobalOptions."); + addSubtitleControls(tab, "GlobalOptions_Audio."); tab->addTab("Volume"); - addVolumeControls(tab, "globaloptions_"); + addVolumeControls(tab, "GlobalOptions_Volume."); // TODO: cd drive setting @@ -687,7 +687,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // 3) The MIDI tab // tab->addTab("MIDI"); - addMIDIControls(tab, "globaloptions_"); + addMIDIControls(tab, "GlobalOptions_MIDI."); // // 4) The miscellaneous tab @@ -699,33 +699,33 @@ GlobalOptionsDialog::GlobalOptionsDialog() // truncated in the small version of the GUI. // Save game path - new ButtonWidget(tab, "globaloptions_savebutton", "Save Path: ", kChooseSaveDirCmd, 0); - _savePath = new StaticTextWidget(tab, "globaloptions_savepath", "/foo/bar"); + new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", "Save Path: ", kChooseSaveDirCmd, 0); + _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar"); - new ButtonWidget(tab, "globaloptions_themebutton", "Theme Path:", kChooseThemeDirCmd, 0); - _themePath = new StaticTextWidget(tab, "globaloptions_themepath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", "Theme Path:", kChooseThemeDirCmd, 0); + _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", "None"); - new ButtonWidget(tab, "globaloptions_extrabutton", "Extra Path:", kChooseExtraDirCmd, 0); - _extraPath = new StaticTextWidget(tab, "globaloptions_extrapath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", "Extra Path:", kChooseExtraDirCmd, 0); + _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", "None"); #ifdef DYNAMIC_MODULES - new ButtonWidget(tab, "globaloptions_pluginsbutton", "Plugins Path:", kChoosePluginsDirCmd, 0); - _pluginsPath = new StaticTextWidget(tab, "globaloptions_pluginspath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", "Plugins Path:", kChoosePluginsDirCmd, 0); + _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", "None"); #endif #endif #ifdef SMALL_SCREEN_DEVICE - new ButtonWidget(tab, "globaloptions_keysbutton", "Keys", kChooseKeyMappingCmd, 0); + new ButtonWidget(tab, "GlobalOptions.KeysButton", "Keys", kChooseKeyMappingCmd, 0); #endif tab->addTab("Misc"); - new ButtonWidget(tab, "globaloptions_themebutton2", "Theme:", kChooseThemeCmd, 0); - _curTheme = new StaticTextWidget(tab, "globaloptions_curtheme", g_gui.theme()->getThemeName()); + new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0); + _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); - _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave:", labelWidth); + _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth); for (int i = 0; savePeriodLabels[i]; i++) { _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]); @@ -738,8 +738,8 @@ GlobalOptionsDialog::GlobalOptionsDialog() tab->setActiveTab(0); // Add OK & Cancel buttons - new ButtonWidget(this, "globaloptions_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "globaloptions_ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "GlobalOptions.Ok", "OK", kOKCmd, 0); #ifdef SMALL_SCREEN_DEVICE _keysDialog = new KeysDialog(); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index d5ee4cc8b3..7ba64bbb83 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index e4fc5d5c3e..8d0e91ea0c 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -464,7 +464,7 @@ - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From ef7a14dbe257da2a07464d566070f7a339b42f63 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 6 Aug 2008 10:50:28 +0000 Subject: Options menu fully parsed. Needs tweaking. svn-id: r33657 --- gui/ThemeEval.cpp | 18 ++--- gui/ThemeEval.h | 12 +-- gui/ThemeParser.cpp | 14 +++- gui/options.cpp | 2 +- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 200 +++++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 215 insertions(+), 33 deletions(-) diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index e2c34d8128..48629c306b 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -79,12 +79,9 @@ void ThemeLayoutVertical::reflowLayout() { if (i != _children.size() - 1) assert(_children[i]->getHeight() != -1); - - if (i == 0) - assert(_children[i]->getWidth() != -1); - + if (_children[i]->getWidth() == -1) - _children[i]->setWidth(_w - _paddingLeft - _paddingRight); + _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); if (_children[i]->getHeight() == -1) _children[i]->setHeight(getParentH() - _h - _spacing); @@ -187,13 +184,16 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over _curLayout.push(layout); } -void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse, bool center) { +void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center) { ThemeLayout *layout = 0; + if (spacing == -1) + spacing = getVar("Globals.Layout.Spacing", 4); + if (type == ThemeLayout::kLayoutVertical) - layout = new ThemeLayoutVertical(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse, center); + layout = new ThemeLayoutVertical(_curLayout.top(), spacing, reverse, center); else if (type == ThemeLayout::kLayoutHorizontal) - layout = new ThemeLayoutHorizontal(_curLayout.top(), getVar("Globals.Layout.Spacing", 4), reverse, center); + layout = new ThemeLayoutHorizontal(_curLayout.top(), spacing, reverse, center); layout->setPadding( getVar("Globals.Padding.Left", 0), @@ -206,7 +206,7 @@ void ThemeEval::addLayout(ThemeLayout::LayoutType type, bool reverse, bool cente _curLayout.push(layout); } -void ThemeEval::addSpacing(int size) { +void ThemeEval::addSpace(int size) { ThemeLayout *space = new ThemeLayoutSpacing(_curLayout.top(), size); _curLayout.top()->addChild(space); } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 671a737336..77c15729ed 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -254,9 +254,9 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name); } void addDialog(const Common::String &name, const Common::String &overlays); - void addLayout(ThemeLayout::LayoutType type, bool reverse, bool center = false); + void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); void addWidget(const Common::String &name, int w, int h); - void addSpacing(int size); + void addSpace(int size); void addPadding(int16 l, int16 r, int16 t, int16 b) { _curLayout.top()->setPadding(l, r, t, b); @@ -267,11 +267,11 @@ public: bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { Common::StringTokenizer tokenizer(widget, "."); + + if (widget.hasPrefix("Dialog.")) + tokenizer.nextToken(); + Common::String dialogName = "Dialog." + tokenizer.nextToken(); - - if (dialogName == "Dialog.Dialog") - dialogName = "Dialog." + tokenizer.nextToken(); - Common::String widgetName = tokenizer.nextToken(); if (!_layouts.contains(dialogName)) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index fafe2ccad7..edb801552c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -499,14 +499,20 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { } 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->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, spacing, node->values["direction"] == "bottom2top", node->values["center"] == "true"); else if (node->values["type"] == "horizontal") - _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, spacing, node->values["direction"] == "right2left", node->values["center"] == "true"); @@ -518,6 +524,8 @@ bool ThemeParser::parserCallback_layout(ParserNode *node) { _theme->themeEval()->addPadding(paddingL, paddingR, paddingT, paddingB); } + + return true; } @@ -529,7 +537,7 @@ bool ThemeParser::parserCallback_space(ParserNode *node) { if (!parseIntegerKey(node->values["size"].c_str(), 1, &size)) return parserError("Invalid value for Spacing size."); - _theme->themeEval()->addSpacing(size); + _theme->themeEval()->addSpace(size); return true; } diff --git a/gui/options.cpp b/gui/options.cpp index 76c9f8ab82..b8b0ca70cb 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -675,7 +675,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // 2) The audio tab // tab->addTab("Audio"); - addAudioControls(tab, "GlobalOptions."); + addAudioControls(tab, "GlobalOptions_Audio."); addSubtitleControls(tab, "GlobalOptions_Audio."); tab->addTab("Volume"); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 7ba64bbb83..bfe1e1ec8e 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 8d0e91ea0c..431ccb0d68 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -298,6 +298,10 @@ horizontal_align = 'right' /> + +/* Tanoku-TODO: text editing width + CARET! +/* + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 4095f2eea9fc682c723c2736369817bf816b4f08 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 6 Aug 2008 13:58:07 +0000 Subject: Bugfix: Text selection background in list widget overlays scrollbar (finally). Bugfix: Game list missing one entry. svn-id: r33658 --- gui/ListWidget.cpp | 26 ++++++++++++++++---------- gui/ThemeEval.h | 7 ++++++- gui/ThemeRenderer.cpp | 9 ++------- gui/eval.h | 7 ++++++- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 3 +++ 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 80898d06c8..dda110aa07 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -30,6 +30,8 @@ #include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { ListWidget::ListWidget(GuiObject *boss, const String &name) @@ -374,7 +376,8 @@ void ListWidget::drawWidget() { if (_hasFocus) inverted = true; else - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1), _hints, Theme::kWidgetBackgroundBorderSmall); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1), + _hints, Theme::kWidgetBackgroundBorderSmall); } Common::Rect r(getEditRect()); @@ -385,7 +388,8 @@ void ListWidget::drawWidget() { char temp[10]; sprintf(temp, "%2d. ", (pos + _numberingMode)); buffer = temp; - g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), buffer, _state, Theme::kTextAlignLeft, inverted, _leftPadding); + g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), + buffer, _state, Theme::kTextAlignLeft, inverted, _leftPadding); pad = 0; } @@ -395,7 +399,8 @@ void ListWidget::drawWidget() { buffer = _editString; adjustOffset(); width = _w - r.left - _hlRightPadding - _leftPadding; - g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); + g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), + buffer, _state, Theme::kTextAlignLeft, inverted, pad); } else { int maxWidth = _textWidth[i]; buffer = _list[pos]; @@ -407,7 +412,8 @@ void ListWidget::drawWidget() { width = _w - r.left - _hlRightPadding; if (width > maxWidth) maxWidth = width; - g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); + g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), + buffer, _state, Theme::kTextAlignLeft, inverted, pad); } _textWidth[i] = width; @@ -480,12 +486,12 @@ void ListWidget::abortEditMode() { void ListWidget::reflowLayout() { Widget::reflowLayout(); - _leftPadding = g_gui.evaluator()->getVar("ListWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("ListWidget.rightPadding", 0); - _topPadding = g_gui.evaluator()->getVar("ListWidget.topPadding", 0); - _bottomPadding = g_gui.evaluator()->getVar("ListWidget.bottomPadding", 0); - _hlLeftPadding = g_gui.evaluator()->getVar("ListWidget.hlLeftPadding", 0); - _hlRightPadding = g_gui.evaluator()->getVar("ListWidget.hlRightPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Right", 0); + _topPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Top", 0); + _bottomPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Bottom", 0); + _hlLeftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlLeftPadding", 0); + _hlRightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlRightPadding", 0); if (g_gui.getWidgetSize() == kBigWidgetSize) { _scrollBarWidth = kBigScrollBarWidth; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 77c15729ed..e55c4a5519 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -246,7 +246,12 @@ public: } int getVar(const Common::String &s, int def) { - return (_vars.contains(s)) ? _vars[s] : def; + if (_vars.contains(s)) + return _vars[s]; + + warning("Returning default value %d for '%s'", def, s.c_str()); + return def; +// return (_vars.contains(s)) ? _vars[s] : def; } void setVar(const String &name, int val) { _vars[name] = val; } diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 474b927845..1272845702 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -361,13 +361,8 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } else { if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) queueDD(kDrawDataDefaults[type].parent, r); - - // HACK: text selection backgrounds must be drawn before other widgets, because - // they are implemented poorly and they overlap. - if (type == kDDTextSelectionBackground) - _screenQueue.push_front(q); - else - _screenQueue.push_back(q); + + _screenQueue.push_back(q); } } else { drawDD(q, !_widgets[type]->_buffer, _widgets[type]->_buffer); diff --git a/gui/eval.h b/gui/eval.h index 47c8313903..bd58a0e1c3 100644 --- a/gui/eval.h +++ b/gui/eval.h @@ -54,8 +54,13 @@ public: void setStringVar(const String &name, const String &val) { _strings[name] = val; } void setAlias(const Common::String &name, const String &val) { _aliases[name] = val; } - int getVar(const Common::String &s) { return getVar_(s); } + int getVar(const Common::String &s) { + warning("Old evaluator access: '%s'", s.c_str()); + return getVar_(s); + } + int getVar(const Common::String &s, int def) { + warning("Old evaluator access: '%s'", s.c_str()); int val = getVar_(s); return (val == EVAL_UNDEF_VAR) ? def : val; } diff --git a/gui/themes/default.inc b/gui/themes/default.inc index bfe1e1ec8e..e76c504bee 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 431ccb0d68..230468fdda 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -432,6 +432,9 @@ + + + " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 230468fdda..c20997e493 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -449,7 +449,7 @@ size = '-1, 19' /> setWidth(w); - widget->setHeight(h); + int typeW = -1; + int typeH = -1; + + if (!type.empty()) { + typeW = getVar("Globals." + type + ".Width", -1); + typeH = getVar("Globals." + type + ".Height", -1); + } + + widget->setWidth(typeW == -1 ? w : typeW); + widget->setHeight(typeH == -1 ? h : typeH); _curLayout.top()->addChild(widget); } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index e55c4a5519..4813892c5e 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -260,7 +260,7 @@ public: void addDialog(const Common::String &name, const Common::String &overlays); void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); - void addWidget(const Common::String &name, int w, int h); + void addWidget(const Common::String &name, int w, int h, const Common::String &type); void addSpace(int size); void addPadding(int16 l, int16 r, int16 t, int16 b) { diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index edb801552c..4226bd714a 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -475,8 +475,7 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return parserError("Corrupted height value in key for %s", var.c_str()); } - _theme->themeEval()->addWidget(var, width, height); - + _theme->themeEval()->addWidget(var, width, height, node->values["type"]); } return true; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index e26a841fe6..d8993439af 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -446,6 +446,7 @@ protected: XML_PROP(name, true) XML_PROP(width, false) XML_PROP(height, false) + XML_PROP(type, false) KEY_END() XML_KEY(space) diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 2979eacc41..8dbf8fb7c2 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index c20997e493..5ae8db30ea 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -437,7 +437,7 @@ + @@ -485,36 +488,29 @@ /> - - - - - - - @@ -526,13 +522,11 @@ - @@ -543,16 +537,16 @@ @@ -560,15 +554,14 @@ -- cgit v1.2.3 From 7df651c4d63bbab40d55cafffd464369188bbd07 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 6 Aug 2008 14:38:23 +0000 Subject: Bugfix: Problem with spaces/comments in embeded theme script. svn-id: r33662 --- gui/themes/default.inc | 2 +- gui/themes/makedeftheme.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 8dbf8fb7c2..e34dc80646 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/makedeftheme.py b/gui/themes/makedeftheme.py index f347516fff..d9729bc33f 100644 --- a/gui/themes/makedeftheme.py +++ b/gui/themes/makedeftheme.py @@ -10,9 +10,10 @@ def main(): try: output = "\"" for line in theme_file: - output += (line.rstrip("\n\r ").lstrip() + " ") + if (len(line)): + output += (line.rstrip("\n\r\t ").lstrip() + " ") - output = re.sub("\/\*(.*?)\*\/", "", output) + output = re.sub("\/\*(.*?)\*\/", "", output).replace("\t", " ").replace(" ", " ") def_file.write(output + "\"\n") finally: theme_file.close() -- cgit v1.2.3 From 8cb26074bd8d5381d11cae9e9acb2da3df9d5387 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 6 Aug 2008 15:06:22 +0000 Subject: Added support for customized background dimming on dialogs. Bugfix: Popup widgets were dimming the background. svn-id: r33663 --- gui/ThemeParser.cpp | 11 +++++++++++ gui/ThemeParser.h | 1 + gui/newgui.cpp | 2 +- gui/themes/default.inc | 2 +- gui/themes/modern.stx | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 4226bd714a..868b6fa9e7 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -493,6 +493,17 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"]; _theme->themeEval()->addDialog(var, node->values["overlays"]); + + 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->themeEval()->setVar(var + ".Shading", shading); + } return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index d8993439af..256d1d3770 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -436,6 +436,7 @@ protected: XML_KEY(dialog) XML_PROP(name, true) XML_PROP(overlays, true) + XML_PROP(shading, false) XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) diff --git a/gui/newgui.cpp b/gui/newgui.cpp index b8c953619c..e45c081e9b 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -214,7 +214,7 @@ void NewGui::redraw() { _theme->updateScreen(); case kRedrawOpenDialog: - _theme->openDialog(true, GUI::Theme::kShadingDim); + _theme->openDialog(true, (Theme::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0)); _dialogStack.top()->drawDialog(); _theme->finishBuffering(); break; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index e34dc80646..499ca752e7 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 5ae8db30ea..e1639cd6a6 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -519,7 +519,7 @@ - + getVar("TabWidget.tabWidth"); - _tabHeight = g_gui.evaluator()->getVar("TabWidget.tabHeight"); - _titleVPad = g_gui.evaluator()->getVar("TabWidget.titleVPad"); + _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width"); + _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height"); + _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); - _butRP = g_gui.evaluator()->getVar("TabWidget.navButtonRightPad", 0); - _butTP = g_gui.evaluator()->getVar("TabWidget.navButtonTopPad", 0); - _butW = g_gui.evaluator()->getVar("TabWidget.navButtonW", 10); - _butH = g_gui.evaluator()->getVar("TabWidget.navButtonH", 10); + _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.navButtonPadding.Right", 0); + _butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0); + _butW = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Width", 10); + _butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10); int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; @@ -96,7 +98,7 @@ int TabWidget::addTab(const String &title) { int numTabs = _tabs.size(); - if (g_gui.evaluator()->getVar("TabWidget.tabWidth") == 0) { + if (g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width") == 0) { if (_tabWidth == 0) _tabWidth = 40; // Determine the new tab width @@ -216,9 +218,9 @@ void TabWidget::reflowLayout() { } } - _tabHeight = g_gui.evaluator()->getVar("TabWidget.tabHeight"); - _tabWidth = g_gui.evaluator()->getVar("TabWidget.tabWidth"); - _titleVPad = g_gui.evaluator()->getVar("TabWidget.titleVPad"); + _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height"); + _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width"); + _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); if (_tabWidth == 0) { _tabWidth = 40; @@ -234,10 +236,10 @@ void TabWidget::reflowLayout() { } } - _butRP = g_gui.evaluator()->getVar("TabWidget.navButtonRightPad", 0); - _butTP = g_gui.evaluator()->getVar("TabWidget.navButtonTopPad", 0); - _butW = g_gui.evaluator()->getVar("TabWidget.navButtonW", 10); - _butH = g_gui.evaluator()->getVar("TabWidget.navButtonH", 10); + _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.PaddingRight", 0); + _butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0); + _butW = g_gui.xmlEval()->getVar("GlobalsTabWidget.NavButton.Width", 10); + _butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10); int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 332dcfd841..cadaf0ba6a 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -59,9 +59,13 @@ void ThemeLayoutMain::reflowLayout() { assert(_children.size() <= 1); if (_children.size()) { + _children[0]->resetLayout(); _children[0]->setWidth(_w); _children[0]->setHeight(_h); _children[0]->reflowLayout(); + +// _children[0]->setX(_x); +// _children[0]->setY(_y); } } @@ -75,6 +79,7 @@ void ThemeLayoutVertical::reflowLayout() { for (uint i = 0; i < _children.size(); ++i) { assert(_children[i]->getLayoutType() != kLayoutVertical); + _children[i]->resetLayout(); _children[i]->reflowLayout(); if (i != _children.size() - 1) @@ -88,7 +93,7 @@ void ThemeLayoutVertical::reflowLayout() { _children[i]->setY(curY); - if (_centered) + if (_centered && _children[i]->getWidth() < _w) _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); else _children[i]->setX(curX); @@ -115,22 +120,24 @@ void ThemeLayoutHorizontal::reflowLayout() { for (uint i = 0; i < _children.size(); ++i) { assert(_children[i]->getLayoutType() != kLayoutHorizontal); + _children[i]->resetLayout(); _children[i]->reflowLayout(); if (i != _children.size() - 1) assert(_children[i]->getWidth() != -1); - - if (i == 0) - assert(_children[i]->getHeight() != -1); if (_children[i]->getHeight() == -1) - _children[i]->setHeight(_h - _paddingTop - _paddingBottom); + _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); if (_children[i]->getWidth() == -1) _children[i]->setWidth(getParentW() - _w - _spacing); _children[i]->setX(curX); - _children[i]->setY(curY); + + if (_centered && _children[i]->getHeight() < _h) + _children[i]->setY((_h >> 1) - (_children[i]->getHeight() >> 1)); + else + _children[i]->setY(curY); if (_reverse) { for (int j = i - 1; j >= 0; --j) @@ -145,27 +152,24 @@ void ThemeLayoutHorizontal::reflowLayout() { } -void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type) { - ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name); - +void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled) { int typeW = -1; int typeH = -1; if (!type.empty()) { typeW = getVar("Globals." + type + ".Width", -1); typeH = getVar("Globals." + type + ".Height", -1); - } + } - widget->setWidth(typeW == -1 ? w : typeW); - widget->setHeight(typeH == -1 ? h : typeH); + ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name, + typeW == -1 ? w : typeW, + typeH == -1 ? h : typeH); _curLayout.top()->addChild(widget); + setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0); } -void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays) { - ThemeLayout *layout = new ThemeLayoutMain(); - _layouts[name] = layout; - +void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled) { int16 x, y; uint16 w, h; @@ -177,10 +181,8 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over error("Error when loading dialog position for '%s'", overlays.c_str()); } - layout->setX(x); - layout->setY(y); - layout->setWidth(w); - layout->setHeight(h); + ThemeLayout *layout = new ThemeLayoutMain(x, y, w, h); + _layouts[name] = layout; layout->setPadding( getVar("Globals.Padding.Left", 0), @@ -190,6 +192,8 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over ); _curLayout.push(layout); + _curDialog = name; + setVar(name + ".Enabled", enabled ? 1 : 0); } void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center) { @@ -219,4 +223,12 @@ void ThemeEval::addSpace(int size) { _curLayout.top()->addChild(space); } +bool ThemeEval::addImportedLayout(const Common::String &name) { + if (!_layouts.contains(name)) + return false; + + _curLayout.top()->importLayout(_layouts[name]); + return true; +} + } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 4813892c5e..c507e8a3df 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -60,6 +60,13 @@ public: virtual void reflowLayout() = 0; + virtual void resetLayout() { + _x = 0; + _y = 0; + _w = _defaultW; + _h = _defaultH; + } + void addChild(ThemeLayout *child) { _children.push_back(child); } void setPadding(int8 left, int8 right, int8 top, int8 bottom) { @@ -154,8 +161,27 @@ public: return true; } + virtual ThemeLayout *buildCopy() = 0; + + void importLayout(ThemeLayout *layout) { + assert(layout->getLayoutType() == kLayoutMain); + + if (layout->_children.size() == 0) + return; + + layout = layout->_children[0]; + + if (getLayoutType() == layout->getLayoutType()) { + for (uint i = 0; i < layout->_children.size(); ++i) + _children.push_back(layout->_children[i]->buildCopy()); + } else { + _children.push_back(layout->buildCopy()); + } + } + protected: int16 _x, _y, _w, _h; + int16 _defaultW, _defaultH; int8 _paddingTop, _paddingBottom, _paddingLeft, _paddingRight; int8 _spacing; Common::Array _children; @@ -167,10 +193,28 @@ protected: class ThemeLayoutMain : public ThemeLayout { public: - ThemeLayoutMain() : ThemeLayout(0, "") {} + ThemeLayoutMain(int16 x, int16 y, int16 w, int16 h) : ThemeLayout(0, "") { + _w = _defaultW = w; + _h = _defaultH = h; + _x = _defaultX = x; + _y = _defaultY = y; + } void reflowLayout(); + + void resetLayout() { + ThemeLayout::resetLayout(); + _x = _defaultX; + _y = _defaultY; + } + const char *getName() { return "Global Layout"; } LayoutType getLayoutType() { return kLayoutMain; } + + ThemeLayout *buildCopy() { assert(!"Do not copy Main Layouts!"); return 0; } + +protected: + int16 _defaultX; + int16 _defaultY; }; class ThemeLayoutVertical : public ThemeLayout { @@ -185,6 +229,16 @@ public: void reflowLayout(); const char *getName() { return "Vertical Layout"; } LayoutType getLayoutType() { return kLayoutVertical; } + + + ThemeLayout *buildCopy() { + ThemeLayoutVertical *n = new ThemeLayoutVertical(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } }; class ThemeLayoutHorizontal : public ThemeLayout { @@ -199,25 +253,40 @@ public: void reflowLayout(); const char *getName() { return "Horizontal Layout"; } LayoutType getLayoutType() { return kLayoutHorizontal; } + + ThemeLayout *buildCopy() { + ThemeLayoutHorizontal *n = new ThemeLayoutHorizontal(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } }; class ThemeLayoutWidget : public ThemeLayout { public: - ThemeLayoutWidget(ThemeLayout *p, const Common::String &name) : ThemeLayout(p, name) {} + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h) : ThemeLayout(p, name) { + _w = _defaultW = w; + _h = _defaultH = h; + } + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); void reflowLayout() {} LayoutType getLayoutType() { return kLayoutWidget; } + + ThemeLayout *buildCopy() { return new ThemeLayoutWidget(*this); } }; class ThemeLayoutSpacing : public ThemeLayout { public: ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p, "") { if (p->getLayoutType() == kLayoutHorizontal) { - _w = size; - _h = 1; + _w = _defaultW = size; + _h = _defaultH = 1; } else if (p->getLayoutType() == kLayoutVertical) { - _w = 1; - _h = size; + _w = _defaultW = 1; + _h = _defaultH = size; } } @@ -225,6 +294,8 @@ public: void reflowLayout() {} LayoutType getLayoutType() { return kLayoutWidget; } const char *getName() { return "SPACE"; } + + ThemeLayout *buildCopy() { return new ThemeLayoutSpacing(*this); } }; class ThemeEval { @@ -238,7 +309,7 @@ public: int getVar(const Common::String &s) { if (!_vars.contains(s)) { - warning("Missing variable: '%s'", s.c_str()); + error("CRITICAL: Missing variable: '%s'", s.c_str()); return -13375; //EVAL_UNDEF_VAR } @@ -246,21 +317,17 @@ public: } int getVar(const Common::String &s, int def) { - if (_vars.contains(s)) - return _vars[s]; - - warning("Returning default value %d for '%s'", def, s.c_str()); - return def; -// return (_vars.contains(s)) ? _vars[s] : def; + return (_vars.contains(s)) ? _vars[s] : def; } void setVar(const String &name, int val) { _vars[name] = val; } bool hasVar(const Common::String &name) { return _vars.contains(name); } - void addDialog(const Common::String &name, const Common::String &overlays); + void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true); void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); - void addWidget(const Common::String &name, int w, int h, const Common::String &type); + void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true); + bool addImportedLayout(const Common::String &name); void addSpace(int size); void addPadding(int16 l, int16 r, int16 t, int16 b) { @@ -268,7 +335,7 @@ public: } void closeLayout() { _curLayout.pop(); } - void closeDialog() { _curLayout.pop()->reflowLayout(); } + void closeDialog() { _curLayout.pop()->reflowLayout(); _curDialog.clear(); } bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { Common::StringTokenizer tokenizer(widget, "."); @@ -298,14 +365,15 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.GlobalOptions"]->debugDraw(screen, font); - _layouts["Dialog.GlobalOptions_Graphics"]->debugDraw(screen, font); + _layouts["Dialog.GameOptions"]->debugDraw(screen, font); + _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } private: VariablesMap _vars; LayoutsMap _layouts; Common::Stack _curLayout; + Common::String _curDialog; }; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 868b6fa9e7..eec0826a8f 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -458,6 +458,14 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { 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->themeEval()->hasVar(node->values["width"]) == true) @@ -475,7 +483,7 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return parserError("Corrupted height value in key for %s", var.c_str()); } - _theme->themeEval()->addWidget(var, width, height, node->values["type"]); + _theme->themeEval()->addWidget(var, width, height, node->values["type"], enabled); } return true; @@ -492,7 +500,16 @@ bool ThemeParser::parserCallback_child(ParserNode *node) { bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"]; - _theme->themeEval()->addDialog(var, node->values["overlays"]); + 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 Dialog enabling (expecting true/false)"); + } + + _theme->themeEval()->addDialog(var, node->values["overlays"], enabled); if (node->values.contains("shading")) { int shading = 0; @@ -508,6 +525,13 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { return true; } +bool ThemeParser::parserCallback_import(ParserNode *node) { + + if (!_theme->themeEval()->addImportedLayout(node->values["layout"])) + return parserError("Error when importing external layout"); + return true; +} + bool ThemeParser::parserCallback_layout(ParserNode *node) { int spacing = -1; @@ -535,8 +559,6 @@ bool ThemeParser::parserCallback_layout(ParserNode *node) { _theme->themeEval()->addPadding(paddingL, paddingR, paddingT, paddingB); } - - return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 256d1d3770..999828e5db 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -437,17 +437,24 @@ protected: XML_PROP(name, true) XML_PROP(overlays, true) XML_PROP(shading, false) + XML_PROP(enabled, false) XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) XML_PROP(direction, false) XML_PROP(padding, false) XML_PROP(spacing, false) + + XML_KEY(import) + XML_PROP(layout, true) + KEY_END() + XML_KEY(widget) XML_PROP(name, true) XML_PROP(width, false) XML_PROP(height, false) XML_PROP(type, false) + XML_PROP(enabled, false) KEY_END() XML_KEY(space) @@ -481,6 +488,7 @@ protected: bool parserCallback_child(ParserNode *node); bool parserCallback_layout(ParserNode *node); bool parserCallback_space(ParserNode *node); + bool parserCallback_import(ParserNode *node); bool closedKeyCallback(ParserNode *node); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1272845702..084e1496ec 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -691,8 +691,8 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); // _vectorRenderer->fillSurface(); - // themeEval()->debugDraw(_screen, _font); - // _vectorRenderer->copyWholeFrame(_system); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/dialog.cpp b/gui/dialog.cpp index ac9d0dbb4d..1e58c654eb 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -150,7 +150,8 @@ void Dialog::drawDialog() { // Draw all children Widget *w = _firstWidget; while (w) { - if (w->_debugVisible) w->draw(); + //if (w->_debugVisible) + w->draw(); w = w->_next; } } diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 451c089d3a..27d74a905a 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -143,7 +143,7 @@ protected: }; EditGameDialog::EditGameDialog(const String &domain, const String &desc) - : OptionsDialog(domain, "gameoptions") { + : OptionsDialog(domain, "GameOptions") { int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); @@ -159,7 +159,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // GUI: Add tab widget - TabWidget *tab = new TabWidget(this, "gameoptions_tabwidget"); + TabWidget *tab = new TabWidget(this, "GameOptions.TabWidget"); tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); // @@ -168,15 +168,15 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) tab->addTab("Game"); // GUI: Label & edit widget for the game ID - new StaticTextWidget(tab, "gameoptions_id", "ID:"); - _domainWidget = new DomainEditTextWidget(tab, "gameoptions_domain", _domain); + new StaticTextWidget(tab, "GameOptions_Game.Id", "ID:"); + _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain); // GUI: Label & edit widget for the description - new StaticTextWidget(tab, "gameoptions_name", "Name:"); - _descriptionWidget = new EditTextWidget(tab, "gameoptions_desc", description); + new StaticTextWidget(tab, "GameOptions_Game.Name", "Name:"); + _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description); // Language popup - _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language:", labelWidth); + _langPopUp = new PopUpWidget(tab, "GameOptions_Game.Lang", "Language:", labelWidth); _langPopUp->appendEntry(""); _langPopUp->appendEntry(""); const Common::LanguageDescription *l = Common::g_languages; @@ -185,7 +185,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // Platform popup - _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform:", labelWidth); + _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.Platform", "Platform:", labelWidth); _platformPopUp->appendEntry(""); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; @@ -198,37 +198,37 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // tab->addTab("Graphics"); - _globalGraphicsOverride = new CheckboxWidget(tab, "gameoptions_graphicsCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); + _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); - addGraphicControls(tab, "gameoptions_"); + addGraphicControls(tab, "GameOptions_Graphics."); // // 4) The audio tab // tab->addTab("Audio"); - _globalAudioOverride = new CheckboxWidget(tab, "gameoptions_audioCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0); + _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0); - addAudioControls(tab, "gameoptions_"); - addSubtitleControls(tab, "gameoptions_"); + addAudioControls(tab, "GameOptions_Audio."); + addSubtitleControls(tab, "GameOptions_Audio."); // // 5) The volume tab // tab->addTab("Volume"); - _globalVolumeOverride = new CheckboxWidget(tab, "gameoptions_volumeCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0); + _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0); - addVolumeControls(tab, "gameoptions_"); + addVolumeControls(tab, "GameOptions_Volume."); // // 6) The MIDI tab // tab->addTab("MIDI"); - _globalMIDIOverride = new CheckboxWidget(tab, "gameoptions_midiCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); + _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); - addMIDIControls(tab, "gameoptions_"); + addMIDIControls(tab, "GameOptions_MIDI."); // // 2) The 'Path' tab @@ -239,29 +239,29 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // in the small version of the GUI. // GUI: Button + Label for the game path - new ButtonWidget(tab, "gameoptions_gamepath", "Game Path:", kCmdGameBrowser, 0); - _gamePathWidget = new StaticTextWidget(tab, "gameoptions_gamepathText", gamePath); + new ButtonWidget(tab, "GameOptions_Paths.Gamepath", "Game Path:", kCmdGameBrowser, 0); + _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath); // GUI: Button + Label for the additional path - new ButtonWidget(tab, "gameoptions_extrapath", "Extra Path:", kCmdExtraBrowser, 0); - _extraPathWidget = new StaticTextWidget(tab, "gameoptions_extrapathText", extraPath); + new ButtonWidget(tab, "GameOptions_Paths.Extrapath", "Extra Path:", kCmdExtraBrowser, 0); + _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath); if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) { _extraPathWidget->setLabel("None"); } // GUI: Button + Label for the save path - new ButtonWidget(tab, "gameoptions_savepath", "Save Path:", kCmdSaveBrowser, 0); - _savePathWidget = new StaticTextWidget(tab, "gameoptions_savepathText", savePath); + new ButtonWidget(tab, "GameOptions_Paths.Savepath", "Save Path:", kCmdSaveBrowser, 0); + _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath); if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { _savePathWidget->setLabel("Default"); } - + // Activate the first tab tab->setActiveTab(0); // Add OK & Cancel buttons - new ButtonWidget(this, "gameoptions_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "gameoptions_ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GameOptions.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "GameOptions.Ok", "OK", kOKCmd, 0); } void EditGameDialog::reflowLayout() { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 499ca752e7..eb6747923b 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index e1639cd6a6..f182f6a2d5 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -706,4 +706,111 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/widget.cpp b/gui/widget.cpp index e9afc30301..1b3fc8c055 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -29,6 +29,8 @@ #include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { Widget::Widget(GuiObject *boss, int x, int y, int w, int h) @@ -153,14 +155,14 @@ Widget *Widget::findWidgetInChain(Widget *w, const char *name) { } bool Widget::isEnabled() const { - if (g_gui.evaluator()->getVar(_name + ".enabled") == 0) { + if (g_gui.xmlEval()->getVar("Dialog." + _name + ".Enabled", 1) == 0) { return false; } return ((_flags & WIDGET_ENABLED) != 0); } bool Widget::isVisible() const { - if (g_gui.evaluator()->getVar(_name + ".visible") == 0) + if (g_gui.xmlEval()->getVar("Dialog." + _name + ".Visible", 1) == 0) return false; return !(_flags & WIDGET_INVISIBLE); -- cgit v1.2.3 From 7c132d340a222b7cc14e53e700338c422f5ddb10 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 7 Aug 2008 18:42:47 +0000 Subject: Misc text drawing improvements. Added carets/text edit widgets. svn-id: r33684 --- gui/EditTextWidget.cpp | 8 +++++--- gui/PopUpWidget.cpp | 8 +++++--- gui/ThemeParser.cpp | 2 +- gui/ThemeParser.h | 2 +- gui/ThemeRenderer.cpp | 46 +++++++++++++++++++++++++++++++++++++--------- gui/ThemeRenderer.h | 33 +++++++++++++++++++++++++++------ gui/themes/default.inc | 2 +- gui/themes/modern.stx | 37 ++++++++++++++++++++++++++++--------- 8 files changed, 105 insertions(+), 33 deletions(-) diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp index 3b5afab669..244d296c80 100644 --- a/gui/EditTextWidget.cpp +++ b/gui/EditTextWidget.cpp @@ -27,6 +27,8 @@ #include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text) @@ -52,10 +54,10 @@ void EditTextWidget::setEditString(const String &str) { } void EditTextWidget::reflowLayout() { - _leftPadding = g_gui.evaluator()->getVar("EditTextWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("EditTextWidget.rightPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Right", 0); - _font = (Theme::FontStyle)g_gui.evaluator()->getVar("EditTextWidget.font", Theme::kFontStyleNormal); + _font = (Theme::FontStyle)g_gui.xmlEval()->getVar("EditTextWidget.Font", Theme::kFontStyleNormal); EditableWidget::reflowLayout(); } diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 91b7c40687..921647e038 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -30,6 +30,8 @@ #include "gui/PopUpWidget.h" #include "engines/engine.h" +#include "gui/ThemeEval.h" + namespace GUI { // @@ -380,9 +382,9 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { } void PopUpWidget::reflowLayout() { - _leftPadding = g_gui.evaluator()->getVar("PopUpWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("PopUpWidget.rightPadding", 0); - _labelSpacing = g_gui.evaluator()->getVar("PopUpWidget.labelSpacing", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Right", 0); + _labelSpacing = g_gui.xmlEval()->getVar("Globals.PopUpWidget.labelSpacing", 10); Widget::reflowLayout(); } diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index eec0826a8f..4d74750b39 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -135,7 +135,7 @@ bool ThemeParser::parserCallback_font(ParserNode *node) { else if (!parseIntegerKey(node->values["color"].c_str(), 3, &red, &green, &blue)) return parserError("Error when parsing color value for font definition."); - if (!_theme->addFont(node->values["id"], red, green, blue)) + if (!_theme->addFont(node->values["id"], node->values["file"], red, green, blue)) return parserError("Error when loading Font in theme engine."); return true; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 999828e5db..ad7f2b36be 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -343,7 +343,7 @@ protected: XML_KEY(fonts) XML_KEY(font) XML_PROP(id, true) - XML_PROP(type, true) + XML_PROP(file, true) XML_PROP(color, true) KEY_END() KEY_END() diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 084e1496ec..454015d338 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -89,7 +89,8 @@ const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { {kTextDataDisabled, "text_disabled"}, {kTextDataInverted, "text_inverted"}, {kTextDataButton, "text_button"}, - {kTextDataButtonHover, "text_button_hover"} + {kTextDataButtonHover, "text_button_hover"}, + {kTextDataNormalFont, "text_normal"} }; @@ -232,7 +233,7 @@ bool ThemeRenderer::addTextData(const Common::String &drawDataId, const Common:: return true; } -bool ThemeRenderer::addFont(const Common::String &fontId, int r, int g, int b) { +bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String &file, int r, int g, int b) { TextData textId = getTextDataId(fontId); if (textId == -1) @@ -243,8 +244,22 @@ bool ThemeRenderer::addFont(const Common::String &fontId, int r, int g, int b) { _texts[textId] = new TextDrawData; - // TODO: Allow the user to specify the font he wants, instead of choosing based on resolution - _texts[textId]->_fontPtr = _font; +// _texts[textId]->_fontPtr = _font; + + if (file == "default") { + _texts[textId]->_fontPtr = _font; + } else { + _texts[textId]->_fontPtr = FontMan.getFontByName(file); + + if (!_texts[textId]->_fontPtr) { + _texts[textId]->_fontPtr = loadFont(file.c_str()); + + if (!_texts[textId]->_fontPtr) + error("Couldn't load %s font '%s'", fontId.c_str(), file.c_str()); + + FontMan.assignFontToName(file, _texts[textId]->_fontPtr); + } + } _texts[textId]->_color.r = r; _texts[textId]->_color.g = g; @@ -552,8 +567,12 @@ void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, Wi void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { if (!ready()) return; - - debugWidgetPosition("Caret", r); + + if (erase) { + restoreBackground(r); + addDirtyRect(r); + } else + queueDD(kDDCaret, r); } void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { @@ -636,19 +655,28 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W queueDDText(kTextDataInverted, r, str, false, useEllipsis, align); return; } + + switch (font) { + case kFontStyleNormal: + queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align); + return; + + default: + break; + } switch (state) { case kStateDisabled: queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align); - break; + return; case kStateHighlight: queueDDText(kTextDataHover, r, str, true, useEllipsis, align); - break; + return; case kStateEnabled: queueDDText(kTextDataDefault, r, str, true, useEllipsis, align); - break; + return; } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 35d2f31d40..39fa6910d1 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -174,6 +174,7 @@ protected: kTextDataInverted, kTextDataButton, kTextDataButtonHover, + kTextDataNormalFont, kTextDataMAX }; @@ -264,10 +265,30 @@ public: /** * FONT MANAGEMENT METHODS */ - const Graphics::Font *getFont(FontStyle font) const { return _font; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } + + TextData fontStyleToData(FontStyle font) const { + switch (font) { + case kFontStyleNormal: + return kTextDataNormalFont; + + default: + return kTextDataDefault; + } + } + + const Graphics::Font *getFont(FontStyle font) const { return _texts[fontStyleToData(font)]->_fontPtr; } + + int getFontHeight(FontStyle font = kFontStyleBold) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getFontHeight() : 0; + } + + int getStringWidth(const Common::String &str, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0; + } + + int getCharWidth(byte c, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0; + } /** @@ -372,7 +393,7 @@ public: * @param cached Whether this DD set will be cached beforehand. */ bool addDrawData(const Common::String &data, bool cached); - bool addFont(const Common::String &fontName, int r, int g, int b); + bool addFont(const Common::String &fontName, const Common::String &file, int r, int g, int b); /** * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the @@ -391,7 +412,7 @@ public: * this checks if the renderer is initialized AND if the theme * is loaded. */ - bool ready() { + bool ready() const { return _initOk && _themeOk; } diff --git a/gui/themes/default.inc b/gui/themes/default.inc index eb6747923b..fa7f3b5236 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1 +1 @@ -" " +" " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index f182f6a2d5..be55749806 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -59,29 +59,33 @@ + @@ -298,10 +302,24 @@ horizontal_align = 'right' /> + + + + -/* Tanoku-TODO: text editing width + CARET! -/* - + + + " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " diff --git a/gui/themes/makedeftheme.py b/gui/themes/makedeftheme.py index d9729bc33f..c2ece4c26b 100644 --- a/gui/themes/makedeftheme.py +++ b/gui/themes/makedeftheme.py @@ -6,15 +6,18 @@ import re def main(): theme_file = open(sys.argv[1], "r") def_file = open("default.inc", "w") + comm = re.compile("\/\*(.*?)\*\/", re.DOTALL) try: - output = "\"" + output = "" for line in theme_file: - if (len(line)): - output += (line.rstrip("\n\r\t ").lstrip() + " ") + output += line.rstrip("\r\n\t ").lstrip() + " \n" - output = re.sub("\/\*(.*?)\*\/", "", output).replace("\t", " ").replace(" ", " ") - def_file.write(output + "\"\n") + output = re.sub(comm, "", output).replace("\t", " ").replace(" ", " ").splitlines() + + for line in output: + if line and not line.isspace(): + def_file.write("\"" + line + "\"\n") finally: theme_file.close() def_file.close() -- cgit v1.2.3 From 39c28e434beb94addd9788e7ab7c4dd9d66ca12e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 7 Aug 2008 23:23:21 +0000 Subject: SCUMM general and options dialog. Misc fixes. svn-id: r33692 --- engines/scumm/dialogs.cpp | 28 +++++----- gui/ThemeEval.cpp | 21 ++++++-- gui/ThemeEval.h | 4 +- gui/ThemeParser.cpp | 8 ++- gui/ThemeRenderer.cpp | 6 +-- gui/newgui.cpp | 11 ---- gui/object.h | 3 -- gui/themes/default.inc | 127 +++++++++++++++++++++++++++++++++++++++----- gui/themes/modern.stx | 130 +++++++++++++++++++++++++++++++++++++++++----- 9 files changed, 274 insertions(+), 64 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index e4e2b2b620..51c012d46d 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -443,20 +443,20 @@ Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode) { } MainMenuDialog::MainMenuDialog(ScummEngine *scumm) - : ScummDialog("scummmain"), _vm(scumm) { + : ScummDialog("ScummMain"), _vm(scumm) { - new GUI::ButtonWidget(this, "scummmain_resume", "Resume", kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "ScummMain.Resume", "Resume", kPlayCmd, 'P'); - new GUI::ButtonWidget(this, "scummmain_load", "Load", kLoadCmd, 'L'); - new GUI::ButtonWidget(this, "scummmain_save", "Save", kSaveCmd, 'S'); + new GUI::ButtonWidget(this, "ScummMain.Load", "Load", kLoadCmd, 'L'); + new GUI::ButtonWidget(this, "ScummMain.Save", "Save", kSaveCmd, 'S'); - new GUI::ButtonWidget(this, "scummmain_options", "Options", kOptionsCmd, 'O'); + new GUI::ButtonWidget(this, "ScummMain.Options", "Options", kOptionsCmd, 'O'); #ifndef DISABLE_HELP - new GUI::ButtonWidget(this, "scummmain_help", "Help", kHelpCmd, 'H'); + new GUI::ButtonWidget(this, "ScummMain.Help", "Help", kHelpCmd, 'H'); #endif - new GUI::ButtonWidget(this, "scummmain_about", "About", kAboutCmd, 'A'); + new GUI::ButtonWidget(this, "ScummMain.About", "About", kAboutCmd, 'A'); - new GUI::ButtonWidget(this, "scummmain_quit", "Quit", kQuitCmd, 'Q'); + new GUI::ButtonWidget(this, "ScummMain.Quit", "Quit", kQuitCmd, 'Q'); // // Create the sub dialog(s) @@ -576,29 +576,29 @@ enum { // "" as value for the domain, and in fact provide a somewhat better user // experience at the same time. ConfigDialog::ConfigDialog() - : GUI::OptionsDialog("", "scummconfig") { + : GUI::OptionsDialog("", "ScummConfig") { // // Sound controllers // - addVolumeControls(this, "scummconfig_"); + addVolumeControls(this, "ScummConfig."); // // Some misc options // // SCUMM has a talkspeed range of 0-9 - addSubtitleControls(this, "scummconfig_", 9); + addSubtitleControls(this, "ScummConfig.", 9); // // Add the buttons // - new GUI::ButtonWidget(this, "scummconfig_ok", "OK", GUI::OptionsDialog::kOKCmd, 'O'); - new GUI::ButtonWidget(this, "scummconfig_cancel", "Cancel", kCloseCmd, 'C'); + new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::OptionsDialog::kOKCmd, 'O'); + new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", kCloseCmd, 'C'); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "scummconfig_keys", "Keys", kKeysCmd, 'K'); + new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K'); #endif #ifdef SMALL_SCREEN_DEVICE diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index cadaf0ba6a..426ca4fc40 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -64,8 +64,17 @@ void ThemeLayoutMain::reflowLayout() { _children[0]->setHeight(_h); _children[0]->reflowLayout(); -// _children[0]->setX(_x); -// _children[0]->setY(_y); + if (_w == -1) + _w = _children[0]->getWidth(); + + if (_h == -1) + _h = _children[0]->getHeight(); + + if (_y == -1) + _y = (g_system->getOverlayHeight() >> 1) - (_h >> 1); + + if (_x == -1) + _x = (g_system->getOverlayWidth() >> 1) - (_w >> 1); } } @@ -171,13 +180,15 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled) { int16 x, y; - uint16 w, h; + int16 w, h; - if (overlays == "screen" || overlays.empty()) { + if (overlays == "screen") { x = y = 0; w = g_system->getOverlayWidth(); h = g_system->getOverlayHeight(); - } else if (!getWidgetData(overlays, x, y, w, h)) { + } else if (overlays == "screen_center") { + x = y = w = h = -1; + } else if (!getWidgetData(overlays, x, y, (uint16&)w, (uint16&)h)) { error("Error when loading dialog position for '%s'", overlays.c_str()); } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index c507e8a3df..ba6e3381ac 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -365,8 +365,8 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.GameOptions"]->debugDraw(screen, font); - _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); + _layouts["Dialog.ScummConfig"]->debugDraw(screen, font); +// _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } private: diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 4d74750b39..010fcaeaf3 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -565,9 +565,13 @@ bool ThemeParser::parserCallback_layout(ParserNode *node) { bool ThemeParser::parserCallback_space(ParserNode *node) { int size = -1; - if (node->values.contains("size")) - if (!parseIntegerKey(node->values["size"].c_str(), 1, &size)) + if (node->values.contains("size")) { + if (_theme->themeEval()->hasVar(node->values["size"])) + size = _theme->themeEval()->getVar(node->values["size"]); + + else if (!parseIntegerKey(node->values["size"].c_str(), 1, &size)) return parserError("Invalid value for Spacing size."); + } _theme->themeEval()->addSpace(size); return true; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 454015d338..49e0d3bb35 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -718,9 +718,9 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); -// _vectorRenderer->fillSurface(); -// themeEval()->debugDraw(_screen, _font); -// _vectorRenderer->copyWholeFrame(_system); +// _vectorRenderer->fillSurface(); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index e45c081e9b..9a0d8cef88 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -60,18 +60,7 @@ void GuiObject::reflowLayout() { if (!_name.empty()) { if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { warning("Could not load widget position for '%s'", _name.c_str()); - -// if ((_x = g_gui.evaluator()->getVar(_name + ".x")) == EVAL_UNDEF_VAR) -// error("Undefined variable %s.x", _name.c_str()); -// if ((_y = g_gui.evaluator()->getVar(_name + ".y")) == EVAL_UNDEF_VAR) -// error("Undefined variable %s.y", _name.c_str()); -// _w = g_gui.evaluator()->getVar(_name + ".w"); -// _h = g_gui.evaluator()->getVar(_name + ".h"); - _w = _x = _y = _h = 32; - _debugVisible = false; } - - _debugVisible = true; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); diff --git a/gui/object.h b/gui/object.h index 9e5ea5fa60..01046bd668 100644 --- a/gui/object.h +++ b/gui/object.h @@ -78,10 +78,7 @@ public: virtual uint16 getWidth() const { return _w; } virtual uint16 getHeight() const { return _h; } -// Tanoku-TODO: fix this back virtual bool isVisible() const = 0; - bool _debugVisible; - virtual void draw() = 0; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 9295e31a7d..1206ffc914 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -72,6 +72,16 @@ "gradient_end = '232, 192, 16' " "/> " " " +" " +" " +" " " " " " +" " " " " " " " " " " " " " @@ -545,8 +557,7 @@ "type = 'Slider' " "/> " " " " " " " @@ -557,8 +568,7 @@ "type = 'Slider' " "/> " " " " " " " @@ -569,8 +579,7 @@ "type = 'Slider' " "/> " " " " " " " @@ -606,8 +615,7 @@ "type = 'Slider' " "/> " " " " " " " @@ -755,4 +763,99 @@ " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index be55749806..26c0fcdfff 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -104,6 +104,17 @@ gradient_end = '232, 192, 16' /> + + + + + @@ -612,8 +625,7 @@ type = 'Slider' /> @@ -624,8 +636,7 @@ type = 'Slider' /> @@ -636,8 +647,7 @@ type = 'Slider' /> @@ -674,8 +684,7 @@ type = 'Slider' /> @@ -832,4 +841,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 1ea3301a8a358e9da9be644b8de54a9fec952dce Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 8 Aug 2008 10:37:58 +0000 Subject: SCUMM save/load dialog. Expanded documentation. Added support for sub-blitting in the vector renderer. svn-id: r33697 --- engines/scumm/dialogs.cpp | 40 ++++++++++++--------- graphics/VectorRenderer.h | 90 ++++++++++++++++++++++++++++++++++++++++++++--- gui/ThemeEval.cpp | 17 +++++++++ gui/ThemeEval.h | 40 +++++++++++++-------- gui/ThemeRenderer.cpp | 11 +++--- gui/themes/default.inc | 23 ++++++++++++ gui/themes/modern.stx | 24 +++++++++++++ 7 files changed, 204 insertions(+), 41 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 51c012d46d..bdb7118f56 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -39,6 +39,7 @@ #include "gui/eval.h" #include "gui/newgui.h" #include "gui/ListWidget.h" +#include "gui/ThemeEval.h" #include "scumm/dialogs.h" #include "scumm/sound.h" @@ -233,14 +234,14 @@ enum { }; SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine) - : Dialog("scummsaveload"), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) { + : Dialog("ScummSaveLoad"), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) { _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; - new StaticTextWidget(this, "scummsaveload_title", title); + new StaticTextWidget(this, "ScummSaveload.Title", title); // Add choice list - _list = new GUI::ListWidget(this, "scummsaveload_list"); + _list = new GUI::ListWidget(this, "ScummSaveLoad.List"); _list->setEditable(saveMode); _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero); @@ -254,8 +255,8 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, _playtime = new StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", kTextAlignCenter); // Buttons - new GUI::ButtonWidget(this, "scummsaveload_cancel", "Cancel", kCloseCmd, 0); - _chooseButton = new GUI::ButtonWidget(this, "scummsaveload_choose", buttonLabel, kChooseCmd, 0); + new GUI::ButtonWidget(this, "ScummSaveLoad.Cancel", "Cancel", kCloseCmd, 0); + _chooseButton = new GUI::ButtonWidget(this, "ScummSaveLoad.Choose", buttonLabel, kChooseCmd, 0); _chooseButton->setEnabled(false); } @@ -318,16 +319,21 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da void SaveLoadChooser::reflowLayout() { if (g_gui.evaluator()->getVar("scummsaveload_extinfo.visible") == 1) { - int thumbX = g_gui.evaluator()->getVar("scummsaveload_thumbnail.x"); - int thumbY = g_gui.evaluator()->getVar("scummsaveload_thumbnail.y"); - int hPad = g_gui.evaluator()->getVar("scummsaveload_thumbnail.hPad"); - int vPad = g_gui.evaluator()->getVar("scummsaveload_thumbnail.vPad"); + int16 x, y; + uint16 w, h; + + if (!g_gui.xmlEval()->getWidgetData("ScummSaveLoad.Thumbnail", x, y, w, h)) + error("Error when loading position data for Save/Load Thumbnails."); + + _container->resize(x, y, w, h); + + int thumbW = kThumbnailWidth; int thumbH = ((g_system->getHeight() % 200 && g_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1); - - _container->resize(thumbX - hPad, thumbY - vPad, kThumbnailWidth + hPad * 2, thumbH + vPad * 2 + kLineHeight * 4); - - // Add the thumbnail display - _gfxWidget->resize(thumbX, thumbY, kThumbnailWidth, thumbH); + int thumbX = x + (w >> 1) - (thumbW >> 1); + int thumbY = y + kLineHeight; + + _container->resize(x, y, w, h); + _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH); int height = thumbY + thumbH + kLineHeight; @@ -347,9 +353,9 @@ void SaveLoadChooser::reflowLayout() { _time->clearFlags(GUI::WIDGET_INVISIBLE); _playtime->clearFlags(GUI::WIDGET_INVISIBLE); - _fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR"); - _fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG"); - _fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB"); + _fillR = 0; //g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR"); + _fillG = 0; //g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG"); + _fillB = 0; //g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB"); updateInfos(false); } else { _container->setFlags(GUI::WIDGET_INVISIBLE); diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 2c5530c07c..a2352762a7 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -349,8 +349,16 @@ public: _gradientFactor = factor; } + /** + * Translates the position data inside a DrawStep into actual + * screen drawing positions. + */ void stepGetPositions(const DrawStep &step, const Common::Rect &area, uint16 &in_x, uint16 &in_y, uint16 &in_w, uint16 &in_h); + /** + * Translates the radius data inside a drawstep into the real radius + * for the shape. Used for automatic radius calculations. + */ int stepGetRadius(const DrawStep &step, const Common::Rect &area); /** @@ -417,34 +425,90 @@ public: virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0); /** - * Copies the current surface to the system overlay + * Copies the part of the current frame to the system overlay. * * @param sys Pointer to the global System class + * @param r Zone of the surface to copy into the overlay. */ virtual void copyFrame(OSystem *sys, const Common::Rect &r) = 0; + + /** + * Copies the current surface to the system overlay + * + * @param sys Pointer to the global System class + */ virtual void copyWholeFrame(OSystem *sys) = 0; /** * Blits a given graphics surface on top of the current drawing surface. * + * Note that the source surface and the active + * surface are expected to be of the same size, hence the area delimited + * by "r" in the source surface will be blitted into the area delimited by + * "r" on the current surface. + * + * If you wish to blit a smaller surface into the active drawing area, use + * VectorRenderer::blitSubSurface(). + * * @param source Surface to blit into the drawing surface. * @param r Position in the active drawing surface to do the blitting. */ - virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; + virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r) = 0; + + /** + * Blits a given graphics surface into a small area of the current drawing surface. + * + * Note that the given surface is expected to be smaller than the + * active drawing surface, hence the WHOLE source surface will be + * blitted into the active surface, at the position specified by "r". + */ + virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) = 0; + /** + * Draws a string into the screen. Wrapper for the Graphics::Font string drawing + * method. + */ virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax) = 0; + /** + * Allows to temporarily enable/disable all shadows drawing. + * i.e. for performance issues, blitting, etc + */ virtual void disableShadows() { _disableShadows = true; } virtual void enableShadows() { _disableShadows = false; } + /** + * Applies a convolution matrix on the given surface area. + * Call applyConvolutionMatrix() instead if you want to use + * the embeded matrixes (blur/sharpen masks, bevels, etc). + * + * @param area Area in which the convolution matrix will be applied. + * @param filter Convolution matrix (3X3) + * @param filterDiv Divisor for the convolution matrix. + * Make sure this equals the total sum of the elements + * of the matrix or brightness data will be distorted. + * @param offset Offset on the convolution area. + */ virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset) = 0; + /** + * Applies one of the predefined convolution effects on the given area. + * + * WARNING: Because of performance issues, this is currently disabled on all renderers. + * + * @param id Id of the convolution data set (see VectorRenderer::ConvolutionData) + * @param area Area in which the convolution effect will be applied. + */ virtual void applyConvolutionMatrix(const ConvolutionData id, const Common::Rect &area) { #ifdef ENABLE_CONVOLUTIONS areaConvolution(area, _convolutionData[id].matrix, _convolutionData[id].divisor, _convolutionData[id].offset); #endif } + /** + * Applies a whole-screen shading effect, used before opening a new dialog. + * Currently supports screen dimmings and luminance (b&w). + */ virtual void applyScreenShading(GUI::Theme::ShadingStyle) = 0; protected: @@ -453,7 +517,7 @@ protected: FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ int _shadowOffset; /** offset for drawn shadows */ - int _bevel; + int _bevel; /** amount of fake bevel */ bool _disableShadows; /** Disables temporarily shadow drawing for overlayed images. */ int _strokeWidth; /** Width of the stroke of all drawn shapes */ uint32 _dynamicData; /** Dynamic data from the GUI Theme that modifies the drawing of the current shape */ @@ -463,7 +527,7 @@ protected: static const ConvolutionDataSet _convolutionData[kConvolutionMAX]; - static const int _dimPercentValue = 256 * 50 / 100; + static const int _dimPercentValue = 256 * 50 / 100; /** default value for screen dimming (50%) */ }; /** @@ -607,7 +671,7 @@ public: /** * @see VectorRenderer::blitSurface() */ - virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) { + virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r) { PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); PixelType *src_ptr = (PixelType *)source->getBasePtr(r.left, r.top); @@ -623,6 +687,22 @@ public: } } + virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) { + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); + PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int h = r.height(), w = r.width(); + + while (h--) { + colorCopy(src_ptr, dst_ptr, w); + dst_ptr += dst_pitch; + src_ptr += src_pitch; + } + } + virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { int pixels = _activeSurface->w * _activeSurface->h; PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 426ca4fc40..b452e1c2f5 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -29,6 +29,7 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "common/xmlparser.h" +#include "graphics/scaler.h" #include "gui/ThemeRenderer.h" #include "gui/ThemeParser.h" @@ -160,6 +161,22 @@ void ThemeLayoutHorizontal::reflowLayout() { } } +void ThemeEval::buildBuiltinVars() { + _builtin["kThumbnailWidth"] = kThumbnailWidth; + _builtin["kThumbnailHeight"] = kThumbnailHeight1; + _builtin["kThumbnailHeight2"] = kThumbnailHeight2; + + _builtin["kButtonWidth"] = GUI::kButtonWidth; + _builtin["kButtonHeight"] = GUI::kButtonHeight; + _builtin["kSliderWidth"] = GUI::kSliderWidth; + _builtin["kSliderHeight"] = GUI::kSliderHeight; + _builtin["kBigButtonWidth"] = GUI::kBigButtonWidth; + _builtin["kBigButtonHeight"] = GUI::kBigButtonHeight; + _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; + _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; + _builtin["kBigSliderHeight"] = GUI::kBigSliderHeight; +} + void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled) { int typeW = -1; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index ba6e3381ac..7df4d60aa4 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -91,8 +91,7 @@ public: width += p->_paddingRight + p->_paddingLeft; if (p->getLayoutType() == kLayoutHorizontal) { for (uint i = 0; i < p->_children.size(); ++i) - if (p->_children[i]->getLayoutType() == kLayoutWidget) - width += p->_children[i]->getHeight() + p->_spacing; + width += p->_children[i]->getHeight() + p->_spacing; } p = p->_parent; } @@ -108,8 +107,7 @@ public: height += p->_paddingBottom + p->_paddingTop; if (p->getLayoutType() == kLayoutVertical) { for (uint i = 0; i < p->_children.size(); ++i) - if (p->_children[i]->getLayoutType() == kLayoutWidget) - height += p->_children[i]->getHeight() + p->_spacing; + height += p->_children[i]->getHeight() + p->_spacing; } p = p->_parent; } @@ -304,25 +302,37 @@ class ThemeEval { typedef Common::HashMap LayoutsMap; public: - ThemeEval() {} + ThemeEval() { + buildBuiltinVars(); + } ~ThemeEval() {} + void buildBuiltinVars(); + int getVar(const Common::String &s) { - if (!_vars.contains(s)) { - error("CRITICAL: Missing variable: '%s'", s.c_str()); - return -13375; //EVAL_UNDEF_VAR - } - - return _vars[s]; + if (_vars.contains(s)) + return _vars[s]; + + if (_builtin.contains(s)) + return _builtin[s]; + + error("CRITICAL: Missing variable: '%s'", s.c_str()); + return -13375; //EVAL_UNDEF_VAR } int getVar(const Common::String &s, int def) { - return (_vars.contains(s)) ? _vars[s] : def; + if (_vars.contains(s)) + return _vars[s]; + + if (_builtin.contains(s)) + return _builtin[s]; + + return def; } void setVar(const String &name, int val) { _vars[name] = val; } - bool hasVar(const Common::String &name) { return _vars.contains(name); } + bool hasVar(const Common::String &name) { return _vars.contains(name) || _builtin.contains(name); } void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true); void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); @@ -365,12 +375,14 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.ScummConfig"]->debugDraw(screen, font); + _layouts["Dialog.ScummSaveLoad"]->debugDraw(screen, font); // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } private: VariablesMap _vars; + VariablesMap _builtin; + LayoutsMap _layouts; Common::Stack _curLayout; Common::String _curDialog; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 49e0d3bb35..6244895719 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -592,8 +592,9 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { if (!ready()) return; - - debugWidgetPosition("Surface", r); + + _vectorRenderer->blitSubSurface(&surface, r); + addDirtyRect(r); } void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { @@ -718,9 +719,9 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); -// _vectorRenderer->fillSurface(); -// themeEval()->debugDraw(_screen, _font); -// _vectorRenderer->copyWholeFrame(_system); + // _vectorRenderer->fillSurface(); + // themeEval()->debugDraw(_screen, _font); + // _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 1206ffc914..4c1e57a52c 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -858,4 +858,27 @@ " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 26c0fcdfff..a0a4bfad0a 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -938,4 +938,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 3ca6f76f7be2ef8c982c83ed0c1a1da633033c35 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 8 Aug 2008 15:06:28 +0000 Subject: Browser dialog. Improved layout expansion in the layout parser. Fixed serious coordinates initialization bug. svn-id: r33702 --- gui/ListWidget.cpp | 12 +++++++++- gui/ThemeEval.cpp | 64 ++++++++++++++++++++++++++++++++++---------------- gui/ThemeEval.h | 4 ++-- gui/ThemeRenderer.cpp | 19 ++++++++------- gui/browser.cpp | 14 +++++------ gui/themes/default.inc | 27 +++++++++++++++++++-- gui/themes/modern.stx | 29 +++++++++++++++++++++-- 7 files changed, 127 insertions(+), 42 deletions(-) diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index dda110aa07..4f829fd323 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -499,7 +499,17 @@ void ListWidget::reflowLayout() { _scrollBarWidth = kNormalScrollBarWidth; } - _entriesPerPage = (_h - _topPadding - _bottomPadding) / kLineHeight; + // HACK: Once we take padding into account, there are times where + // integer rounding leaves a big chunk of white space in the bottom + // of the list. + // We do a rough rounding on the decimal places of Entries Per Page, + // to add another entry even if it goes a tad over the padding. + _entriesPerPage = ((_h - _topPadding - _bottomPadding) << 16) / kLineHeight; + + if ((uint)(_entriesPerPage & 0xFFFF) >= 0xF000) + _entriesPerPage += (1 << 16); + + _entriesPerPage >>= 16; delete[] _textWidth; _textWidth = new int[_entriesPerPage]; diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index b452e1c2f5..96ac8098ad 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -65,6 +65,9 @@ void ThemeLayoutMain::reflowLayout() { _children[0]->setHeight(_h); _children[0]->reflowLayout(); +// _children[0]->setX(_x); +// _children[0]->setY(_y); + if (_w == -1) _w = _children[0]->getWidth(); @@ -81,25 +84,27 @@ void ThemeLayoutMain::reflowLayout() { void ThemeLayoutVertical::reflowLayout() { int curX, curY; + int autoWidget = -1; curX = _paddingLeft; curY = _paddingTop; _h = _paddingTop + _paddingBottom; for (uint i = 0; i < _children.size(); ++i) { - assert(_children[i]->getLayoutType() != kLayoutVertical); _children[i]->resetLayout(); _children[i]->reflowLayout(); - - if (i != _children.size() - 1) - assert(_children[i]->getHeight() != -1); if (_children[i]->getWidth() == -1) _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); - if (_children[i]->getHeight() == -1) + if (_children[i]->getHeight() == -1) { + if (autoWidget != -1) + error("Cannot expand automatically two different widgets."); + + autoWidget = i; _children[i]->setHeight(getParentH() - _h - _spacing); + } _children[i]->setY(curY); @@ -116,31 +121,40 @@ void ThemeLayoutVertical::reflowLayout() { } _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); - _h += _children[i]->getHeight() + _spacing; + + if (autoWidget != -1 && autoWidget != (int)i) { + _children[autoWidget]->setHeight(_children[autoWidget]->getHeight() - (_children[i]->getHeight() + _spacing)); + for (int j = autoWidget - 1; j >= 0; --j) + _children[j]->setY(-(_children[i]->getHeight() + _spacing)); + } else { + _h += _children[i]->getHeight() + _spacing; + } } } void ThemeLayoutHorizontal::reflowLayout() { int curX, curY; + int autoWidget = -1; curX = _paddingLeft; curY = _paddingTop; _w = _paddingLeft + _paddingRight; for (uint i = 0; i < _children.size(); ++i) { - assert(_children[i]->getLayoutType() != kLayoutHorizontal); _children[i]->resetLayout(); _children[i]->reflowLayout(); - if (i != _children.size() - 1) - assert(_children[i]->getWidth() != -1); - if (_children[i]->getHeight() == -1) _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); - if (_children[i]->getWidth() == -1) + if (_children[i]->getWidth() == -1) { + if (autoWidget != -1) + error("Cannot expand automatically two different widgets."); + + autoWidget = i; _children[i]->setWidth(getParentW() - _w - _spacing); + } _children[i]->setX(curX); @@ -156,7 +170,15 @@ void ThemeLayoutHorizontal::reflowLayout() { curX += (_children[i]->getWidth() + _spacing); } - _w += _children[i]->getWidth() + _spacing; + if (autoWidget != -1 && autoWidget != (int)i) { + _children[autoWidget]->setWidth(_children[autoWidget]->getWidth() - (_children[i]->getWidth() + _spacing)); + for (int j = autoWidget - 1; j >= 0; --j) + _children[j]->setX(-(_children[i]->getWidth() + _spacing)); + } else { + _w += _children[i]->getWidth() + _spacing; + } + + _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); } } @@ -197,19 +219,21 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled) { int16 x, y; - int16 w, h; + uint16 w, h; + + ThemeLayout *layout = 0; if (overlays == "screen") { - x = y = 0; - w = g_system->getOverlayWidth(); - h = g_system->getOverlayHeight(); + layout = new ThemeLayoutMain(0, 0, g_system->getOverlayWidth(), g_system->getOverlayHeight()); } else if (overlays == "screen_center") { - x = y = w = h = -1; - } else if (!getWidgetData(overlays, x, y, (uint16&)w, (uint16&)h)) { - error("Error when loading dialog position for '%s'", overlays.c_str()); + layout = new ThemeLayoutMain(-1, -1, -1, -1); + } else if (getWidgetData(overlays, x, y, w, h)) { + layout = new ThemeLayoutMain(x, y, w, h); } - ThemeLayout *layout = new ThemeLayoutMain(x, y, w, h); + if (!layout) + error("Error when loading dialog position for '%s'", overlays.c_str()); + _layouts[name] = layout; layout->setPadding( diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 7df4d60aa4..4d5a3db5f6 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -52,7 +52,7 @@ public: ThemeLayout(ThemeLayout *p, const Common::String &name) : _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), _reverse(false), _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), - _centered(false) { } + _centered(false), _defaultW(-1), _defaultH(-1) { } virtual ~ThemeLayout() { _children.clear(); @@ -375,7 +375,7 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.ScummSaveLoad"]->debugDraw(screen, font); + _layouts["Dialog.Browser"]->debugDraw(screen, font); // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 6244895719..f2dfb4fd1f 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -651,15 +651,18 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W if (!ready()) return; + Common::Rect dr = r; + dr.left += deltax; + if (inverted) { queueDD(kDDTextSelectionBackground, r); - queueDDText(kTextDataInverted, r, str, false, useEllipsis, align); + queueDDText(kTextDataInverted, dr, str, false, useEllipsis, align); return; } switch (font) { case kFontStyleNormal: - queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align); + queueDDText(kTextDataNormalFont, dr, str, true, useEllipsis, align); return; default: @@ -668,15 +671,15 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W switch (state) { case kStateDisabled: - queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align); + queueDDText(kTextDataDisabled, dr, str, true, useEllipsis, align); return; case kStateHighlight: - queueDDText(kTextDataHover, r, str, true, useEllipsis, align); + queueDDText(kTextDataHover, dr, str, true, useEllipsis, align); return; case kStateEnabled: - queueDDText(kTextDataDefault, r, str, true, useEllipsis, align); + queueDDText(kTextDataDefault, dr, str, true, useEllipsis, align); return; } } @@ -719,9 +722,9 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); - // _vectorRenderer->fillSurface(); - // themeEval()->debugDraw(_screen, _font); - // _vectorRenderer->copyWholeFrame(_system); +// _vectorRenderer->fillSurface(); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/browser.cpp b/gui/browser.cpp index 41d3d15bb6..21d492f942 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -133,29 +133,29 @@ int BrowserDialog::runModal() { */ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser) - : Dialog("browser") { + : Dialog("Browser") { _isDirBrowser = dirBrowser; _fileList = NULL; _currentPath = NULL; // Headline - TODO: should be customizable during creation time - new StaticTextWidget(this, "browser_headline", title); + new StaticTextWidget(this, "Browser.Headline", title); // Current path - TODO: handle long paths ? - _currentPath = new StaticTextWidget(this, "browser_path", "DUMMY"); + _currentPath = new StaticTextWidget(this, "Browser.Path", "DUMMY"); // Add file list - _fileList = new ListWidget(this, "browser_list"); + _fileList = new ListWidget(this, "Browser.List"); _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); _fileList->setHints(THEME_HINT_PLAIN_COLOR); // Buttons - new ButtonWidget(this, "browser_up", "Go up", kGoUpCmd, 0); - new ButtonWidget(this, "browser_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "browser_choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Up", "Go up", kGoUpCmd, 0); + new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); } void BrowserDialog::open() { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 4c1e57a52c..41de1be85f 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -401,7 +401,7 @@ " " " " " " -" " +" " " " " " " " " " " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index a0a4bfad0a..3551b637df 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -462,7 +462,7 @@ - + @@ -485,7 +485,7 @@ size = '-1, Globals.Line.Height' /> + + + + + + + + + + + + + + + -- cgit v1.2.3 From dab1fa0942cffa82c1944170774b659b8bcfb6b2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 8 Aug 2008 18:30:16 +0000 Subject: Resolution-dependence in XML files. G1X scaler GUI now loads. Added layout for the launcher menu. MILESTONE: All core GUI dialogs/widgets working on G2x/G3x MILESTONE: Completely removed old Evaluator/Parser. Improved layout expanding again. Improved XML parser. Several bugfixes. svn-id: r33704 --- common/xmlparser.cpp | 5 +++-- common/xmlparser.h | 24 +++++++++----------- gui/ThemeEval.cpp | 5 ++++- gui/ThemeEval.h | 2 +- gui/ThemeParser.cpp | 54 +++++++++++++++++++++++++++++++++++---------- gui/ThemeParser.h | 8 ++++++- gui/ThemeRenderer.cpp | 23 ++++++++++++-------- gui/ThemeRenderer.h | 3 ++- gui/console.cpp | 16 ++++++-------- gui/launcher.cpp | 19 ++++++++-------- gui/newgui.cpp | 4 +++- gui/options.cpp | 9 ++++---- gui/themes/default.inc | 47 +++++++++++++++++++++++++++++++++++++++- gui/themes/modern.stx | 59 +++++++++++++++++++++++++++++++++++++++++++++++--- gui/widget.cpp | 5 +---- 15 files changed, 212 insertions(+), 71 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 526e6e6fb1..b845f7f66f 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -110,9 +110,10 @@ bool XMLParser::parseActiveKey(bool closed) { return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str()); } - if (key->layout->anyProps == false && localMap.empty() == false) + if (localMap.empty() == false) return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str()); - } else if (layout->anyKeys == false) { + + } else { return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str()); } diff --git a/common/xmlparser.h b/common/xmlparser.h index 2f73b5905d..e26ea1eb53 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -182,12 +182,12 @@ namespace Common { #define XML_KEY(keyName) {\ lay = new XMLKeyLayout; \ - lay->anyProps = false; \ - lay->anyKeys = false; \ lay->custom = new kLocalParserName::CustomParserCallback; \ ((kLocalParserName::CustomParserCallback*)(lay->custom))->callback = (&kLocalParserName::parserCallback_##keyName); \ layout.top()->children[#keyName] = lay; \ - layout.push(lay); + layout.push(lay); \ + for (Common::List::const_iterator p = globalProps.begin(); p != globalProps.end(); ++p){\ + layout.top()->properties.push_back(*p);} #define XML_KEY_RECURSIVE(keyName) {\ layout.top()->children[#keyName] = layout.top();\ @@ -199,13 +199,13 @@ namespace Common { #define XML_PROP(propName, req) {\ prop.name = #propName; \ prop.required = req; \ - layout.top()->properties.push_back(prop); }\ + layout.top()->properties.push_back(prop); } + +#define XML_GLOBAL_PROP(propName, req) {\ + prop.name = #propName; \ + prop.required = req;\ + globalProps.push_back(prop); } -#define XML_PROP_ANY() {\ - layout.top()->anyProps = true; } - -#define XML_KEY_ANY() {\ - layout.top()->anyKeys = true; } #define CUSTOM_XML_PARSER(parserName) \ protected: \ @@ -217,9 +217,8 @@ namespace Common { Common::Stack layout; \ XMLKeyLayout *lay = 0; \ XMLKeyLayout::XMLKeyProperty prop; \ + Common::List globalProps; \ _XMLkeys = new XMLKeyLayout; \ - _XMLkeys->anyProps = false; \ - _XMLkeys->anyKeys = false; \ layout.push(_XMLkeys); #define PARSER_END() layout.clear(); } @@ -310,14 +309,11 @@ public: }; Common::List properties; - bool anyProps; - bool anyKeys; ChildMap children; ~XMLKeyLayout() { properties.clear(); children.clear(); -// delete custom; } } *_XMLkeys; diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 96ac8098ad..fe520eb80b 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -196,7 +196,10 @@ void ThemeEval::buildBuiltinVars() { _builtin["kBigButtonHeight"] = GUI::kBigButtonHeight; _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; - _builtin["kBigSliderHeight"] = GUI::kBigSliderHeight; + _builtin["kBigSliderHeight"] = GUI::kBigSliderHeight; + + _builtin["kNormalWidgetSize"] = GUI::kNormalWidgetSize; + _builtin["kBigWidgetSize"] = GUI::kBigWidgetSize; } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 4d5a3db5f6..c12fa12fa9 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -375,7 +375,7 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.Browser"]->debugDraw(screen, font); + _layouts["Dialog.Launcher"]->debugDraw(screen, font); // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 010fcaeaf3..d9275b1df0 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -129,6 +129,11 @@ bool ThemeParser::parserCallback_defaults(ParserNode *node) { bool ThemeParser::parserCallback_font(ParserNode *node) { int red, green, blue; + + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } if (_palette.contains(node->values["color"])) getPaletteColor(node->values["color"], red, green, blue); @@ -226,6 +231,11 @@ bool ThemeParser::parserCallback_drawstep(ParserNode *node) { bool ThemeParser::parserCallback_drawdata(ParserNode *node) { bool cached = false; + + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } if (node->values.contains("cache")) { if (node->values["cache"] == "true") @@ -235,16 +245,6 @@ bool ThemeParser::parserCallback_drawdata(ParserNode *node) { else return parserError("'Parsed' value must be either true or false."); } - // Both Max and Johannes suggest using a non-platform specfic approach based on available - // resources and active resolution. getHostPlatformString() has been removed, so fix this. - -/* if (drawdataNode->values.contains("platform")) { - if (drawdataNode->values["platform"].compareToIgnoreCase(Common::getHostPlatformString()) != 0) { - drawdataNode->ignore = true; - return true; - } - }*/ - if (_theme->addDrawData(node->values["id"], cached) == false) return parserError("Error when adding Draw Data set: Invalid DrawData name."); @@ -437,10 +437,18 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } bool ThemeParser::parserCallback_def(ParserNode *node) { + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } + Common::String var = "Globals." + node->values["var"]; int value; - if (!parseIntegerKey(node->values["value"].c_str(), 1, &value)) + if (_theme->themeEval()->hasVar(node->values["value"]) == true) + value = _theme->themeEval()->getVar(node->values["value"]); + + else if (!parseIntegerKey(node->values["value"].c_str(), 1, &value)) return parserError("Invalid definition for '%s'.", var.c_str()); _theme->themeEval()->setVar(var, value); @@ -451,9 +459,16 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { Common::String var; if (getParentNode(node)->name == "globals") { + + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } + var = "Globals." + node->values["name"] + "."; if (!parseCommonLayoutProps(node, var)) return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + } else { var = node->values["name"]; int width = -1; @@ -502,6 +517,11 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"]; bool enabled = true; + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } + if (node->values.contains("enabled")) { if (node->values["enabled"] == "false") enabled = false; @@ -703,4 +723,16 @@ bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String return true; } +bool ThemeParser::resolutionCheck(const Common::String &resolution) { + if (resolution.empty()) + return false; + + Common::StringTokenizer tokenizer(resolution, "x"); + Common::String w = tokenizer.nextToken(); + Common::String h = tokenizer.nextToken(); + + return ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) && + (h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight())) == false; +} + } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index ad7f2b36be..bae015cf25 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -331,7 +331,6 @@ protected: ThemeRenderer *_theme; CUSTOM_XML_PARSER(ThemeParser) { - XML_KEY(render_info) XML_KEY(palette) XML_KEY(color) @@ -345,6 +344,7 @@ protected: XML_PROP(id, true) XML_PROP(file, true) XML_PROP(color, true) + XML_PROP(resolution, false) KEY_END() KEY_END() @@ -365,6 +365,7 @@ protected: XML_KEY(drawdata) XML_PROP(id, true) XML_PROP(cache, false) + XML_PROP(resolution, false) XML_KEY(defaults) XML_PROP(stroke, false) @@ -417,6 +418,7 @@ protected: XML_KEY(def) XML_PROP(var, true) XML_PROP(value, true) + XML_PROP(resolution, false) KEY_END() XML_KEY(widget) @@ -424,6 +426,7 @@ protected: XML_PROP(size, false) XML_PROP(pos, false) XML_PROP(padding, false) + XML_PROP(resolution, false) XML_KEY(child) XML_PROP(name, true) @@ -438,6 +441,7 @@ protected: XML_PROP(overlays, true) XML_PROP(shading, false) XML_PROP(enabled, false) + XML_PROP(resolution, false) XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) @@ -492,6 +496,8 @@ protected: bool closedKeyCallback(ParserNode *node); + bool resolutionCheck(const Common::String &resolution); + void cleanup(); Graphics::DrawStep *newDrawStep(); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index f2dfb4fd1f..fc6f34fa9c 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -113,8 +113,6 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _graphicsMode = mode; setGraphicsMode(_graphicsMode); - loadConfigFile("modern"); - if (_screen->w >= 400 && _screen->h >= 300) { _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); } else { @@ -138,9 +136,6 @@ bool ThemeRenderer::init() { if (isThemeLoadingRequired() || !_themeOk) { loadTheme(_themeName); - - Theme::loadTheme(_defaultConfig); - Theme::loadTheme(_configFile, false, true); } return true; @@ -240,12 +235,10 @@ bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String & return false; if (_texts[textId] != 0) - return false; + delete _texts[textId]; _texts[textId] = new TextDrawData; -// _texts[textId]->_fontPtr = _font; - if (file == "default") { _texts[textId]->_fontPtr = _font; } else { @@ -271,8 +264,11 @@ bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String & bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { DrawData data_id = getDrawDataId(data); - if (data_id == -1 || _widgets[data_id] != 0) + if (data_id == -1) return false; + + if (_widgets[data_id] != 0) + delete _widgets[data_id]; _widgets[data_id] = new WidgetDrawData; _widgets[data_id]->_cached = cached; @@ -684,6 +680,15 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W } } +void ThemeRenderer::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { + if (!ready()) + return; + + restoreBackground(r); + font->drawChar(_screen, ch, r.left, r.top, 0); + addDirtyRect(r); +} + void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); _screen->hLine(r.left, r.top, r.right, 0xFFFF); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 39fa6910d1..b131b6b5e7 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -330,7 +330,7 @@ public: WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); void drawChar(const Common::Rect &r, byte ch, - const Graphics::Font *font, WidgetStateInfo state) {} + const Graphics::Font *font, WidgetStateInfo state); /** * Actual implementation of a Dirty Rect drawing routine. @@ -435,6 +435,7 @@ public: } void *evaluator() { return _themeEval; } + bool supportsImages() const { return true; } protected: diff --git a/gui/console.cpp b/gui/console.cpp index 728724d76f..de4db14a4f 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -25,6 +25,7 @@ #include "gui/console.h" #include "gui/ScrollBarWidget.h" #include "gui/eval.h" +#include "gui/ThemeEval.h" #include "engines/engine.h" #include "base/version.h" @@ -97,17 +98,14 @@ ConsoleDialog::ConsoleDialog(float widthPercent, float heightPercent) void ConsoleDialog::init() { const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - int f = g_gui.evaluator()->getVar("Console.font"); - if (f == EVAL_UNDEF_VAR) - _font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont); - else - _font = g_gui.theme()->getFont((Theme::FontStyle)f); + _font = FontMan.getFontByUsage((Graphics::FontManager::FontUsage) + g_gui.xmlEval()->getVar("Console.Font", Graphics::FontManager::kConsoleFont)); - _leftPadding = g_gui.evaluator()->getVar("Console.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("Console.rightPadding", 0); - _topPadding = g_gui.evaluator()->getVar("Console.topPadding", 0); - _bottomPadding = g_gui.evaluator()->getVar("Console.bottomPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Right", 0); + _topPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Top", 0); + _bottomPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Bottom", 0); // Calculate the real width/height (rounded to char/line multiples) _w = (uint16)(_widthPercent * screenW); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 27d74a905a..62f1daf244 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -48,6 +48,7 @@ #include "sound/mididrv.h" +#include "gui/ThemeEval.h" using Common::ConfigManager; @@ -145,7 +146,7 @@ protected: EditGameDialog::EditGameDialog(const String &domain, const String &desc) : OptionsDialog(domain, "GameOptions") { - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w) String gamePath(ConfMan.get("path", _domain)); @@ -267,7 +268,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) void EditGameDialog::reflowLayout() { OptionsDialog::reflowLayout(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); if (_langPopUp) _langPopUp->changeLabelWidth(labelWidth); @@ -480,7 +481,7 @@ LauncherDialog::LauncherDialog() #ifndef DISABLE_FANCY_THEMES _logo = 0; - if (g_gui.evaluator()->getVar("launcher_logo.visible") == 1 && g_gui.theme()->supportsImages()) { + if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) { _logo = new GraphicsWidget(this, "Launcher.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(Theme::kImageLogo)); @@ -878,21 +879,21 @@ void LauncherDialog::updateButtons() { void LauncherDialog::reflowLayout() { #ifndef DISABLE_FANCY_THEMES - if (g_gui.evaluator()->getVar("launcher_logo.visible") == 1 && g_gui.theme()->supportsImages()) { - StaticTextWidget *ver = (StaticTextWidget*)findWidget("launcher_version"); + if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) { + StaticTextWidget *ver = (StaticTextWidget*)findWidget("lLauncher.Version"); if (ver) { - ver->setAlign((Graphics::TextAlignment)g_gui.evaluator()->getVar("launcher_version.align")); + ver->setAlign((Graphics::TextAlignment)g_gui.xmlEval()->getVar("Launcher.Version.Align", Graphics::kTextAlignCenter)); ver->setLabel(gScummVMVersionDate); } if (!_logo) - _logo = new GraphicsWidget(this, "launcher_logo"); + _logo = new GraphicsWidget(this, "Launcher.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(Theme::kImageLogo)); } else { - StaticTextWidget *ver = (StaticTextWidget*)findWidget("launcher_version"); + StaticTextWidget *ver = (StaticTextWidget*)findWidget("Launcher.Version"); if (ver) { - ver->setAlign((Graphics::TextAlignment)g_gui.evaluator()->getVar("launcher_version.align")); + ver->setAlign((Graphics::TextAlignment)g_gui.xmlEval()->getVar("Launcher.Version.Align", Graphics::kTextAlignCenter)); ver->setLabel(gScummVMFullVersion); } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 9a0d8cef88..c89937595b 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -61,6 +61,8 @@ void GuiObject::reflowLayout() { if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { warning("Could not load widget position for '%s'", _name.c_str()); } + + return; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); @@ -442,7 +444,7 @@ void NewGui::animateCursor() { } WidgetSize NewGui::getWidgetSize() { - return (WidgetSize)(_theme->_evaluator->getVar("widgetSize")); + return (WidgetSize)(g_gui.xmlEval()->getVar("Globals.WidgetSize")); } void NewGui::clearDragWidget() { diff --git a/gui/options.cpp b/gui/options.cpp index b8b0ca70cb..12153469ef 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -28,6 +28,7 @@ #include "gui/eval.h" #include "gui/message.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" #include "gui/options.h" #include "gui/PopUpWidget.h" #include "gui/TabWidget.h" @@ -500,7 +501,7 @@ void OptionsDialog::setSubtitleSettingsState(bool enabled) { void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // The GFX mode popup _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:", labelWidth); @@ -537,7 +538,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { } void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // The MIDI mode popup & a label _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:", labelWidth); @@ -643,7 +644,7 @@ int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { void OptionsDialog::reflowLayout() { Dialog::reflowLayout(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); if (_midiPopUp) _midiPopUp->changeLabelWidth(labelWidth); @@ -723,7 +724,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0); _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 41de1be85f..97b7d6a260 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -397,6 +397,9 @@ " " " " " " +" " +" " +" " " " " " " " @@ -404,6 +407,8 @@ " " " " " " +" " +" " " " @@ -411,7 +416,11 @@ "size = '24, Globals.Line.Height' " "/> " " " +" " " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index 3551b637df..cf022960bb 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -456,6 +456,11 @@ + + + + + @@ -465,6 +470,9 @@ + + + + + + + @@ -552,6 +567,43 @@ + + + + + + + + + + + + + + + + + + @@ -574,8 +626,7 @@ height = 'Globals.Line.Height' /> - - + @@ -592,6 +643,8 @@ + + getVar(name + ".align"); - - if (_align == (int)EVAL_UNDEF_VAR) - _align = kTextAlignLeft; + _align = (Graphics::TextAlignment)g_gui.xmlEval()->getVar(name + ".Align", kTextAlignLeft); } void StaticTextWidget::setValue(int value) { -- cgit v1.2.3 From f546aa9dc8d3bc811a4a356271022c29d121711d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 8 Aug 2008 18:48:12 +0000 Subject: BUGFIX: XMLParser issuing key-close callbacks on ignored keys. svn-id: r33706 --- common/xmlparser.cpp | 22 +++++++++++++++++++--- common/xmlparser.h | 9 +++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index b845f7f66f..6c6bc4b7f8 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -135,7 +135,7 @@ bool XMLParser::parseActiveKey(bool closed) { } if (closed) - delete _activeKey.pop(); + return closeKey(); return true; } @@ -166,6 +166,23 @@ bool XMLParser::parseKeyValue(Common::String keyName) { return true; } +bool XMLParser::closeKey() { + bool ignore = false; + bool result = true; + + for (int i = _activeKey.size() - 1; i >= 0; --i) { + if (_activeKey[i]->ignore) + ignore = true; + } + + if (ignore == false) + result = closedKeyCallback(_activeKey.top()); + + delete _activeKey.pop(); + + return result; +} + bool XMLParser::parse() { if (_text.ready() == false) @@ -235,13 +252,12 @@ bool XMLParser::parse() { case kParserNeedPropertyName: if (activeClosure) { - if (!closedKeyCallback(_activeKey.top())) { + if (!closeKey()) { parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str()); break; } activeClosure = false; - delete _activeKey.pop(); if (_text[_pos++] != '>') parserError("Invalid syntax in key closure."); diff --git a/common/xmlparser.h b/common/xmlparser.h index e26ea1eb53..d1abd321e7 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -423,12 +423,21 @@ protected: * The closedKeyCallback is issued once a key has been finished parsing, to let * the parser verify that all the required subkeys, etc, were included. * + * Unlike the keyCallbacks(), there's just a closedKeyCallback() for all keys. + * Use "node->name" to distinguish between each key type. + * * Returns true if the key was properly closed, false otherwise. * By default, all keys are properly closed. */ virtual bool closedKeyCallback(ParserNode *node) { return true; } + + /** + * Called when a node is closed. Manages its cleanup and calls the + * closing callback function if needed. + */ + bool closeKey(); /** * Parses the value of a given key. There's no reason to overload this. -- cgit v1.2.3 From 01b8373d95c216ce8cbe29abcc98837d35046e37 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 8 Aug 2008 21:52:16 +0000 Subject: Fixed: About dialog in all resolutions. svn-id: r33707 --- gui/about.cpp | 15 ++++++++------- gui/themes/default.inc | 2 ++ gui/themes/modern.stx | 3 +++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/gui/about.cpp b/gui/about.cpp index 71bf877d21..eeb2533e0d 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -29,10 +29,11 @@ #include "common/system.h" #include "common/util.h" #include "gui/about.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/widget.h" +#include "gui/ThemeEval.h" + namespace GUI { enum { @@ -85,9 +86,9 @@ AboutDialog::AboutDialog() const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - _xOff = g_gui.evaluator()->getVar("aboutXOff"); - _yOff = g_gui.evaluator()->getVar("aboutYOff"); - int outerBorder = g_gui.evaluator()->getVar("aboutOuterBorder"); + _xOff = g_gui.xmlEval()->getVar("Globals.About.XOffset", 5); + _yOff = g_gui.xmlEval()->getVar("Globals.About.YOffset", 5); + int outerBorder = g_gui.xmlEval()->getVar("Globals.About.OuterBorder"); _w = screenW - 2 * outerBorder; _h = screenH - 2 * outerBorder; @@ -316,9 +317,9 @@ void AboutDialog::reflowLayout() { const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - _xOff = g_gui.evaluator()->getVar("aboutXOff"); - _yOff = g_gui.evaluator()->getVar("aboutYOff"); - int outerBorder = g_gui.evaluator()->getVar("aboutOuterBorder"); + _xOff = g_gui.xmlEval()->getVar("Globals.About.XOffset", 5); + _yOff = g_gui.xmlEval()->getVar("Globals.About.YOffset", 5); + int outerBorder = g_gui.xmlEval()->getVar("Globals.About.OuterBorder"); _w = screenW - 2 * outerBorder; _h = screenH - 2 * outerBorder; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 97b7d6a260..961917b05e 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -404,6 +404,8 @@ " " " " " " +" " +" " " " " " " " diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx index cf022960bb..33f557b366 100644 --- a/gui/themes/modern.stx +++ b/gui/themes/modern.stx @@ -467,6 +467,9 @@ + + + -- cgit v1.2.3 From ea69217a136210347689e9536d67e1dda883f45a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 9 Aug 2008 14:15:34 +0000 Subject: Fixed 1.000.000 Valgrind warnings. svn-id: r33711 --- common/xmlparser.cpp | 3 +++ common/xmlparser.h | 42 +++++++++++++++++++++++++++--------------- gui/ThemeEval.cpp | 8 +++++++- gui/ThemeEval.h | 16 ++++++++++++++-- gui/ThemeParser.cpp | 9 ++++----- gui/ThemeParser.h | 9 ++++++++- gui/ThemeRenderer.cpp | 14 +++++++++++--- gui/ThemeRenderer.h | 11 ++++------- 8 files changed, 78 insertions(+), 34 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 6c6bc4b7f8..900f2f81ab 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -191,6 +191,9 @@ bool XMLParser::parse() { if (_XMLkeys == 0) buildLayout(); + while (!_activeKey.empty()) + delete _activeKey.pop(); + cleanup(); bool activeClosure = false; diff --git a/common/xmlparser.h b/common/xmlparser.h index d1abd321e7..b7a7093bc5 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -179,13 +179,13 @@ namespace Common { for a working sample of a Custom XML Parser. */ - + #define XML_KEY(keyName) {\ - lay = new XMLKeyLayout; \ - lay->custom = new kLocalParserName::CustomParserCallback; \ - ((kLocalParserName::CustomParserCallback*)(lay->custom))->callback = (&kLocalParserName::parserCallback_##keyName); \ - layout.top()->children[#keyName] = lay; \ + lay = new CustomXMLKeyLayout;\ + lay->callback = (&kLocalParserName::parserCallback_##keyName);\ + layout.top()->children[#keyName] = lay;\ layout.push(lay); \ + _layoutList.push_back(lay);\ for (Common::List::const_iterator p = globalProps.begin(); p != globalProps.end(); ++p){\ layout.top()->properties.push_back(*p);} @@ -209,16 +209,18 @@ namespace Common { #define CUSTOM_XML_PARSER(parserName) \ protected: \ - typedef bool (parserName::*ParserCallback)(ParserNode *node); \ typedef parserName kLocalParserName; \ - struct CustomParserCallback { ParserCallback callback; }; \ - bool keyCallback(ParserNode *node) {return (this->*(((parserName::CustomParserCallback*)(node->layout->custom))->callback))(node);}\ + bool keyCallback(ParserNode *node) {return node->layout->doCallback(this, node); }\ + struct CustomXMLKeyLayout : public XMLKeyLayout {\ + typedef bool (parserName::*ParserCallback)(ParserNode *node);\ + ParserCallback callback;\ + bool doCallback(XMLParser *parent, ParserNode *node) {return ((kLocalParserName*)parent->*callback)(node);} };\ virtual void buildLayout() { \ Common::Stack layout; \ - XMLKeyLayout *lay = 0; \ + CustomXMLKeyLayout *lay = 0; \ XMLKeyLayout::XMLKeyProperty prop; \ Common::List globalProps; \ - _XMLkeys = new XMLKeyLayout; \ + _XMLkeys = new CustomXMLKeyLayout; \ layout.push(_XMLkeys); #define PARSER_END() layout.clear(); } @@ -280,8 +282,14 @@ public: virtual ~XMLParser() { while (!_activeKey.empty()) delete _activeKey.pop(); - + delete _XMLkeys; + + for (Common::List::iterator i = _layoutList.begin(); + i != _layoutList.end(); ++i) + delete *i; + + _layoutList.clear(); } /** Active state for the parser */ @@ -297,12 +305,12 @@ public: }; struct XMLKeyLayout; + struct ParserNode; typedef Common::HashMap ChildMap; /** nested struct representing the layout of the XML file */ struct XMLKeyLayout { - void *custom; struct XMLKeyProperty { Common::String name; bool required; @@ -311,9 +319,10 @@ public: Common::List properties; ChildMap children; - ~XMLKeyLayout() { + virtual bool doCallback(XMLParser *parent, ParserNode *node) = 0; + + virtual ~XMLKeyLayout() { properties.clear(); - children.clear(); } } *_XMLkeys; @@ -336,8 +345,10 @@ public: bool loadFile(Common::String filename) { Common::File *f = new Common::File; - if (!f->open(filename)) + if (!f->open(filename)) { + delete f; return false; + } _fileName = filename; _text.loadStream(f); @@ -564,6 +575,7 @@ protected: */ virtual void cleanup() {} + Common::List _layoutList; private: int _pos; /** Current position on the XML buffer. */ diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index fe520eb80b..ec866cc626 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -178,11 +178,14 @@ void ThemeLayoutHorizontal::reflowLayout() { _w += _children[i]->getWidth() + _spacing; } - _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); } } +ThemeEval::~ThemeEval() { + reset(); +} + void ThemeEval::buildBuiltinVars() { _builtin["kThumbnailWidth"] = kThumbnailWidth; _builtin["kThumbnailHeight"] = kThumbnailHeight1; @@ -236,6 +239,9 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over if (!layout) error("Error when loading dialog position for '%s'", overlays.c_str()); + + if (_layouts.contains(name)) + delete _layouts[name]; _layouts[name] = layout; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index c12fa12fa9..aaab4cb2bf 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -55,7 +55,8 @@ public: _centered(false), _defaultW(-1), _defaultH(-1) { } virtual ~ThemeLayout() { - _children.clear(); + for (uint i = 0; i < _children.size(); ++i) + delete _children[i]; } virtual void reflowLayout() = 0; @@ -305,7 +306,8 @@ public: ThemeEval() { buildBuiltinVars(); } - ~ThemeEval() {} + + ~ThemeEval(); void buildBuiltinVars(); @@ -379,6 +381,16 @@ public: // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } + void reset() { + _vars.clear(); + _builtin.clear(); + _curDialog.clear(); + _curLayout.clear(); + + for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i) + delete i->_value; + } + private: VariablesMap _vars; VariablesMap _builtin; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index d9275b1df0..21554f4c7a 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -97,12 +97,12 @@ Graphics::DrawStep *ThemeParser::defaultDrawStep() { Graphics::DrawStep *ThemeParser::newDrawStep() { assert(_defaultStepGlobal); - Graphics::DrawStep *step = new DrawStep; + Graphics::DrawStep *step = 0 ; //new DrawStep; if (_defaultStepLocal) { - memcpy(step, _defaultStepLocal, sizeof(DrawStep)); + step = new DrawStep(*_defaultStepLocal); } else { - memcpy(step, _defaultStepGlobal, sizeof(DrawStep)); + step = new DrawStep(*_defaultStepGlobal); } return step; @@ -116,9 +116,8 @@ bool ThemeParser::parserCallback_defaults(ParserNode *node) { step = _defaultStepGlobal; } else if (parentNode->name == "drawdata") { if (_defaultStepLocal == 0) - _defaultStepLocal = new DrawStep; + _defaultStepLocal = new DrawStep(*_defaultStepLocal); - memcpy(_defaultStepLocal, _defaultStepGlobal, sizeof(DrawStep)); step = _defaultStepLocal; } else { return parserError(" key out of scope. Must be inside or keys."); diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index bae015cf25..78423652bc 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -312,10 +312,17 @@ class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); - + public: ThemeParser(GUI::ThemeRenderer *parent); + virtual ~ThemeParser() { + delete _defaultStepGlobal; + delete _defaultStepLocal; + _palette.clear(); + _drawFunctions.clear(); + } + bool getPaletteColor(const Common::String &name, int &r, int &g, int &b) { if (!_palette.contains(name)) return false; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index fc6f34fa9c..679db6c3e7 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -123,6 +123,15 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : _themeName = themeName; } +ThemeRenderer::~ThemeRenderer() { + freeRenderer(); + freeScreen(); + freeBackbuffer(); + unloadTheme(); + delete _parser; + delete _themeEval; +} + bool ThemeRenderer::init() { // reset everything and reload the graphics deinit(); @@ -174,17 +183,16 @@ void ThemeRenderer::disable() { template void ThemeRenderer::screenInit(bool backBuffer) { - freeScreen(); - freeBackbuffer(); - uint32 width = _system->getOverlayWidth(); uint32 height = _system->getOverlayHeight(); if (backBuffer) { + freeBackbuffer(); _backBuffer = new Surface; _backBuffer->create(width, height, sizeof(PixelType)); } + freeScreen(); _screen = new Surface; _screen->create(width, height, sizeof(PixelType)); _system->clearOverlay(); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index b131b6b5e7..55c75bd76e 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -35,13 +35,15 @@ #include "gui/dialog.h" #include "gui/ThemeParser.h" -#include "gui/ThemeEval.h" #include "graphics/VectorRenderer.h" +#include "gui/ThemeEval.h" + namespace GUI { struct WidgetDrawData; struct DrawDataInfo; +class ThemeEval; struct TextDrawData { const Graphics::Font *_fontPtr; @@ -210,12 +212,7 @@ public: ThemeRenderer(Common::String themeName, GraphicsMode mode); /** Default destructor */ - ~ThemeRenderer() { - freeRenderer(); - freeScreen(); - unloadTheme(); - delete _parser; - } + ~ThemeRenderer(); GUI::ThemeEval *themeEval() { return _themeEval; } -- cgit v1.2.3 From 103a4f66813df8f806467ad6f27cd0831ae0abf4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 9 Aug 2008 18:34:16 +0000 Subject: Added support for image loading/blitting. Added support for loading theme files. (Make sure to grab the sample theme "scummodern.zip" from the gui/themes/ directory to try it out) Misc fixes. svn-id: r33718 --- common/xmlparser.h | 6 +++ graphics/VectorRenderer.h | 55 +++++++++++++++++++++++++++ gui/ThemeParser.cpp | 21 +++++++++++ gui/ThemeParser.h | 12 +++++- gui/ThemeRenderer.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++-- gui/ThemeRenderer.h | 49 +++++++++++++++++++++++- gui/launcher.cpp | 2 +- gui/newgui.cpp | 57 ++++------------------------ gui/theme.h | 2 +- gui/themes/default.inc | 4 ++ gui/themes/modern.stx | 5 +++ gui/themes/scummodern.zip | Bin 0 -> 29651 bytes 12 files changed, 250 insertions(+), 57 deletions(-) create mode 100644 gui/themes/scummodern.zip diff --git a/common/xmlparser.h b/common/xmlparser.h index b7a7093bc5..e3d39bfb82 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -371,6 +371,12 @@ public: _fileName = "Memory Stream"; return true; } + + bool loadStream(MemoryReadStream *stream) { + _text.loadStream(stream); + _fileName = "Compressed File Stream"; + return true; + } /** * The actual parsing function. diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index a2352762a7..7eff0a9c50 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -71,6 +71,7 @@ struct DrawStep { uint32 scale; /** scale of all the coordinates in FIXED POINT with 16 bits mantissa */ void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ + Graphics::Surface *blitSrc; }; VectorRenderer *createRenderer(int mode); @@ -412,6 +413,12 @@ public: stepGetPositions(step, area, x, y, w, h); drawTab(x, y, stepGetRadius(step, area), w, h); } + + void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step) { + uint16 x, y, w, h; + stepGetPositions(step, area, x, y, w, h); + blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, w, h)); + } void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {} @@ -464,6 +471,8 @@ public: */ virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) = 0; + virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) = 0; + /** * Draws a string into the screen. Wrapper for the Graphics::Font string drawing * method. @@ -554,6 +563,11 @@ class VectorRendererSpec : public VectorRenderer { typedef VectorRenderer Base; public: + VectorRendererSpec() { + _bitmapAlphaColor = RGBToColor(255, 0, 255); + } + + /** * @see VectorRenderer::drawLine() */ @@ -672,6 +686,8 @@ public: * @see VectorRenderer::blitSurface() */ virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r) { + assert(source->w == _activeSurface->w && source->h == _activeSurface->h); + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); PixelType *src_ptr = (PixelType *)source->getBasePtr(r.left, r.top); @@ -703,6 +719,43 @@ public: } } + virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { + assert(r.width() >= source->w && r.height() >= source->h); + + int16 x = r.left; + int16 y = r.top; + + if (r.width() > source->w) + x = x + (r.width() >> 1) - (source->w >> 1); + + if (r.height() > source->h) + y = y + (r.height() >> 1) - (source->h >> 1); + + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int w, h = source->h; + + while (h--) { + w = source->w; + + while (w--) { + if (*src_ptr != _bitmapAlphaColor) + *dst_ptr = *src_ptr; + + dst_ptr++; + src_ptr++; + } + + dst_ptr = dst_ptr - source->w + dst_pitch; + src_ptr = src_ptr - source->w + src_pitch; + } + + } + virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { int pixels = _activeSurface->w * _activeSurface->h; PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); @@ -935,6 +988,8 @@ protected: PixelType _gradientEnd; /** End color for the fill gradient */ PixelType _bevelColor; + + PixelType _bitmapAlphaColor; }; /** diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 21554f4c7a..df36ad6c7c 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -51,6 +51,7 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; _drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB; _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; + _drawFunctions["bitmap"] = &Graphics::VectorRenderer::drawCallback_BITMAP; _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; @@ -149,6 +150,18 @@ bool ThemeParser::parserCallback_fonts(ParserNode *node) { return true; } +bool ThemeParser::parserCallback_bitmap(ParserNode *node) { + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } + + if (!_theme->addBitmap(node->values["filename"])) + return parserError("Error when loading Bitmap file '%s'", node->values["filename"].c_str()); + + return true; +} + bool ThemeParser::parserCallback_text(ParserNode *node) { GUI::Theme::TextAlign alignH; GUI::Theme::TextAlignVertical alignV; @@ -319,6 +332,14 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst if (functionSpecific) { assert(stepNode->values.contains("func")); Common::String functionName = stepNode->values["func"]; + + if (functionName == "bitmap") { + if (!stepNode->values.contains("filename")) + return parserError("Need to specify a filename for Bitmap blitting."); + + if (!_theme->getBitmap(stepNode->values["filename"])) + 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") { diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 78423652bc..b9fa69179d 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -308,7 +308,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -class ThemeRenderer; +class ThemeRenderer; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); @@ -354,6 +354,13 @@ protected: XML_PROP(resolution, false) KEY_END() KEY_END() + + XML_KEY(bitmaps) + XML_KEY(bitmap) + XML_PROP(filename, true) + XML_PROP(resolution, false) + KEY_END() + KEY_END() XML_KEY(defaults) XML_PROP(stroke, false) @@ -408,6 +415,7 @@ protected: XML_PROP(xpos, false) XML_PROP(ypos, false) XML_PROP(orientation, false) + XML_PROP(bitmap, false) KEY_END() XML_KEY(text) @@ -489,6 +497,8 @@ protected: bool parserCallback_color(ParserNode *node); bool parserCallback_drawstep(ParserNode *node); bool parserCallback_drawdata(ParserNode *node); + bool parserCallback_bitmaps(ParserNode *node) { return true; } + bool parserCallback_bitmap(ParserNode *node); /** Layout info callbacks */ bool parserCallback_layout_info(ParserNode *node); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 679db6c3e7..6cfdb777ad 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -29,6 +29,7 @@ #include "common/system.h" #include "common/events.h" #include "common/config-manager.h" +#include "graphics/imageman.h" #include "gui/launcher.h" @@ -118,6 +119,8 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : } else { _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); } + + ImageMan.addArchive(themeName + ".zip"); _initOk = true; _themeName = themeName; @@ -130,6 +133,13 @@ ThemeRenderer::~ThemeRenderer() { unloadTheme(); delete _parser; delete _themeEval; + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) { +// delete i->_value; + ImageMan.unregisterSurface(i->_key); + } + + ImageMan.remArchive(_stylefile + ".zip"); } bool ThemeRenderer::init() { @@ -269,6 +279,18 @@ bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String & } +bool ThemeRenderer::addBitmap(const Common::String &filename) { + if (_bitmaps.contains(filename)) { + delete _bitmaps[filename]; + ImageMan.unregisterSurface(filename); + } + + ImageMan.registerSurface(filename, 0); + _bitmaps[filename] = ImageMan.getSurface(filename); + + return _bitmaps[filename] != 0; +} + bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { DrawData data_id = getDrawDataId(data); @@ -346,9 +368,41 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - - if (!parser()->loadFile(themeName + ".xml")) + + if (!parser()->loadFile(themeName + ".stx")){ +#ifdef USE_ZLIB + unzFile zipFile = unzOpen((themeName + ".zip").c_str()); + + if (zipFile && unzLocateFile(zipFile, (themeName + ".stx").c_str(), 2) == UNZ_OK) { + + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + + Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); + + if (!parser()->loadStream(stream)) { + unzClose(zipFile); + delete stream; + return false; + } + +// delete[] buffer; + buffer = 0; + } else { + unzClose(zipFile); + return false; + } + unzClose(zipFile); +#else return false; +#endif + } return parser()->parse(); } @@ -411,6 +465,19 @@ void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Comm } } +void ThemeRenderer::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &area, bool alpha) { + BitmapQueue q; + q.bitmap = bitmap; + q.area = area; + q.alpha = alpha; + + if (_buffering) { + _bitmapQueue.push_back(q); + } else { + drawBitmap(q); + } +} + void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { Common::Rect extendedRect = q.area; extendedRect.grow(kDirtyRectangleThreshold); @@ -442,6 +509,16 @@ void ThemeRenderer::drawDDText(const DrawQueueText &q) { addDirtyRect(q.area); } +void ThemeRenderer::drawBitmap(const BitmapQueue &q) { + + if (q.alpha) + _vectorRenderer->blitAlphaBitmap(q.bitmap, q.area); + else + _vectorRenderer->blitSubSurface(q.bitmap, q.area); + + addDirtyRect(q.area); +} + void ThemeRenderer::calcBackgroundOffset(DrawData type) { uint maxShadow = 0; for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); @@ -597,8 +674,10 @@ void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface & if (!ready()) return; - _vectorRenderer->blitSubSurface(&surface, r); - addDirtyRect(r); + queueBitmap(&surface, r, themeTrans); + +// _vectorRenderer->blitSubSurface(&surface, r); +// addDirtyRect(r); } void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { @@ -726,6 +805,13 @@ void ThemeRenderer::updateScreen() { _screenQueue.clear(); } + if (!_bitmapQueue.empty()) { + for (Common::List::const_iterator q = _bitmapQueue.begin(); q != _bitmapQueue.end(); ++q) + drawBitmap(*q); + + _bitmapQueue.clear(); + } + if (!_textQueue.empty()) { for (Common::List::const_iterator q = _textQueue.begin(); q != _textQueue.end(); ++q) drawDDText(*q); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 55c75bd76e..cb68b9ca5c 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -88,6 +88,7 @@ class ThemeRenderer : public Theme { protected: typedef Common::String String; typedef GUI::Dialog Dialog; + typedef Common::HashMap ImagesMap; friend class GUI::Dialog; friend class GUI::GuiObject; @@ -197,6 +198,12 @@ protected: int deltax; }; + struct BitmapQueue { + const Graphics::Surface *bitmap; + Common::Rect area; + bool alpha; + }; + public: /** Graphics mode enumeration. * Each item represents a set of BPP and Renderer modes for a given @@ -390,8 +397,27 @@ public: * @param cached Whether this DD set will be cached beforehand. */ bool addDrawData(const Common::String &data, bool cached); + + + /** + * Interface for the ThemeParser class: Loads a font to use on the GUI from the given + * filename. + * + * @param fontName Identifier name for the font. + * @param file Name of the font file. + * @param r, g, b Color of the font. + */ bool addFont(const Common::String &fontName, const Common::String &file, int r, int g, int b); + + /** + * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI. + * The filename is also used as its identifier. + * + * @param filename Name of the bitmap file. + */ + bool addBitmap(const Common::String &filename); + /** * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the * new Font API is in place. @@ -433,6 +459,19 @@ public: void *evaluator() { return _themeEval; } bool supportsImages() const { return true; } + + Graphics::Surface *getBitmap(const Common::String &name) { + return _bitmaps.contains(name) ? _bitmaps[name] : 0; + } + + const Graphics::Surface *getImageSurface(const kThemeImages n) const { + if (n == kImageLogo) + return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; + + return 0; + } + + const Common::String &getThemeName() { return _themeName; } protected: @@ -487,7 +526,9 @@ protected: * Not implemented yet. * TODO: reload themes, reload the renderer, recheck everything */ - void screenChange() {} + void screenChange() { + error("Screen Changes are not supported yet. Fix this!"); + } /** * Actual Dirty Screen handling function. @@ -570,6 +611,7 @@ protected: */ inline void drawDD(const DrawQueue &q, bool draw = true, bool restore = false); inline void drawDDText(const DrawQueueText &q); + inline void drawBitmap(const BitmapQueue &q); /** * Generates a DrawQueue item and enqueues it so it's drawn to the screen @@ -585,6 +627,7 @@ protected: inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); + inline void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); /** * DEBUG: Draws a white square around the given position and writes the given next to it. @@ -646,6 +689,8 @@ protected: /** Array of all the text fonts that can be drawn. */ TextDrawData *_texts[kTextDataMAX]; + ImagesMap _bitmaps; + /** List of all the dirty screens that must be blitted to the overlay. */ Common::List _dirtyScreen; @@ -657,6 +702,8 @@ protected: /** Queue with all the text drawing that must be done to the screen */ Common::List _textQueue; + + Common::List _bitmapQueue; bool _initOk; /** Class and renderer properly initialized */ bool _themeOk; /** Theme data successfully loaded. */ diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 62f1daf244..3d35420326 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -880,7 +880,7 @@ void LauncherDialog::updateButtons() { void LauncherDialog::reflowLayout() { #ifndef DISABLE_FANCY_THEMES if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) { - StaticTextWidget *ver = (StaticTextWidget*)findWidget("lLauncher.Version"); + StaticTextWidget *ver = (StaticTextWidget*)findWidget("Launcher.Version"); if (ver) { ver->setAlign((Graphics::TextAlignment)g_gui.xmlEval()->getVar("Launcher.Version.Align", Graphics::kTextAlignCenter)); ver->setLabel(gScummVMVersionDate); diff --git a/gui/newgui.cpp b/gui/newgui.cpp index c89937595b..e83c86a451 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -91,31 +91,16 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), // Clear the cursor memset(_cursor, 0xFF, sizeof(_cursor)); - bool loadClassicTheme = true; -#ifndef DISABLE_FANCY_THEMES + ConfMan.registerDefault("gui_theme", "default"); Common::String style(ConfMan.get("gui_theme")); - // The default theme for now is the 'modern' theme. if (style.compareToIgnoreCase("default") == 0) - style = "modern"; - - Common::String styleType; - Common::ConfigFile cfg; - if (loadNewTheme(style)) { - loadClassicTheme = false; - } else { - loadClassicTheme = true; - warning("falling back to classic style"); - } -#endif + style = "builtin"; + + //DEBUG: + style = "scummodern"; - if (loadClassicTheme) { - _theme = new ThemeClassic(_system); - assert(_theme); - if (!_theme->init()) { - error("Couldn't initialize classic theme"); - } - } + loadNewTheme(style); _theme->resetDrawArea(); _themeChange = false; @@ -129,7 +114,7 @@ bool NewGui::loadNewTheme(const Common::String &style) { Common::String styleType; Common::ConfigFile cfg; - Common::String oldTheme = (_theme != 0) ? _theme->getStylefileName() : ""; + Common::String oldTheme = (_theme != 0) ? _theme->getThemeName() : ""; if (_theme) _theme->disable(); @@ -142,38 +127,12 @@ bool NewGui::loadNewTheme(const Common::String &style) { delete _theme; _theme = 0; -/* if (style.compareToIgnoreCase("classic (builtin)") == 0 || - style.compareToIgnoreCase("classic") == 0) { - _theme = new ThemeClassic(_system, style); - } else { - if (Theme::themeConfigUseable(style, "", &styleType, &cfg)) { - if (0 == styleType.compareToIgnoreCase("classic")) - _theme = new ThemeClassic(_system, style, &cfg); -#ifndef DISABLE_FANCY_THEMES - else if (0 == styleType.compareToIgnoreCase("modern")) - _theme = new ThemeModern(_system, style, &cfg); -#endif - else - warning("Unsupported theme type '%s'", styleType.c_str()); - } else { - warning("Config '%s' is NOT usable for themes or not found", style.c_str()); - } - } - cfg.clear(); */ - _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxAntialias16bit); -// _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxStandard16bit); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); - if (!_theme->init()) { - warning("Could not initialize your preferred theme"); - delete _theme; - _theme = 0; - loadNewTheme(oldTheme); - return false; - } + _theme->init(); _theme->resetDrawArea(); if (!oldTheme.empty()) diff --git a/gui/theme.h b/gui/theme.h index 0d0fadb8ad..74158f473c 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -371,7 +371,7 @@ public: static bool themeConfigUseable(const Common::String &file, const Common::String &style="", Common::String *cStyle=0, Common::ConfigFile *cfg=0); const Common::String &getStylefileName() const { return _stylefile; } - const Common::String &getThemeName() const { return _stylename; } + virtual const Common::String &getThemeName() const { return _stylename; } virtual bool isDynamic() { return false; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 961917b05e..262260a7fc 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -28,6 +28,10 @@ "rgb = '63, 60, 17' " "/> " " " +" " +" " +" " +" " " " " + + + + + >= 16; + + assert(_entriesPerPage > 0); delete[] _textWidth; _textWidth = new int[_entriesPerPage]; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index aaab4cb2bf..eecd2db3ee 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -377,7 +377,7 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.Launcher"]->debugDraw(screen, font); + _layouts["Dialog.Browser"]->debugDraw(screen, font); // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 6cfdb777ad..378e32649f 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -95,7 +95,7 @@ const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { }; -ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : +ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false), _buffering(false) { @@ -119,11 +119,9 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : } else { _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); } - - ImageMan.addArchive(themeName + ".zip"); + _themeFileName = fileName; _initOk = true; - _themeName = themeName; } ThemeRenderer::~ThemeRenderer() { @@ -134,12 +132,8 @@ ThemeRenderer::~ThemeRenderer() { delete _parser; delete _themeEval; - for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) { -// delete i->_value; + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) ImageMan.unregisterSurface(i->_key); - } - - ImageMan.remArchive(_stylefile + ".zip"); } bool ThemeRenderer::init() { @@ -154,7 +148,7 @@ bool ThemeRenderer::init() { } if (isThemeLoadingRequired() || !_themeOk) { - loadTheme(_themeName); + loadTheme(_themeFileName); } return true; @@ -170,6 +164,30 @@ void ThemeRenderer::deinit() { } } +void ThemeRenderer::unloadTheme() { + if (!_themeOk) + return; + + for (int i = 0; i < kDrawDataMAX; ++i) { + delete _widgets[i]; + _widgets[i] = 0; + } + + for (int i = 0; i < kTextDataMAX; ++i) { + delete _texts[i]; + _texts[i] = 0; + } + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) + ImageMan.unregisterSurface(i->_key); + + ImageMan.remArchive(_themeFileName + ".zip"); + + _themeName.clear(); + _themeFileName.clear(); + _themeOk = false; +} + void ThemeRenderer::clearAll() { if (!_initOk) return; @@ -281,7 +299,6 @@ bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String & bool ThemeRenderer::addBitmap(const Common::String &filename) { if (_bitmaps.contains(filename)) { - delete _bitmaps[filename]; ImageMan.unregisterSurface(filename); } @@ -309,14 +326,28 @@ bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { return true; } -bool ThemeRenderer::loadTheme(Common::String themeName) { +bool ThemeRenderer::loadTheme(Common::String fileName) { unloadTheme(); - if (themeName == "builtin" && !loadDefaultXML()) - error("Could not load default embeded theme."); + if (fileName != "builtin") { + if (ConfMan.hasKey("themepath")) + Common::File::addDefaultDirectory(ConfMan.get("themepath")); - if (!loadThemeXML(themeName)) { - warning("Could not parse custom theme '%s'.\nFalling back to default theme", themeName.c_str()); +#ifdef DATA_PATH + Common::File::addDefaultDirectoryRecursive(DATA_PATH); +#endif + if (ConfMan.hasKey("extrapath")) + Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + + ImageMan.addArchive(fileName + ".zip"); + } + + if (fileName == "builtin") { + if (!loadDefaultXML()) + error("Could not load default embeded theme"); + } + else if (!loadThemeXML(fileName)) { + warning("Could not parse custom theme '%s'.\nFalling back to default theme", fileName.c_str()); if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure error("Could not load default embeded theme"); @@ -333,9 +364,7 @@ bool ThemeRenderer::loadTheme(Common::String themeName) { } } - // Debug print all the parsed variables. remove - _themeEval->debugPrint(); - + _themeName = "DEBUG - A Theme name"; _themeOk = true; return true; } @@ -346,6 +375,8 @@ bool ThemeRenderer::loadDefaultXML() { // file inside the themes directory. // Use the Python script "makedeftheme.py" to convert a normal XML theme // into the "default.inc" file, which is ready to be included in the code. + +#ifdef GUI_ENABLE_BUILTIN_THEME const char *defaultXML = #include "themes/default.inc" ; @@ -354,20 +385,14 @@ bool ThemeRenderer::loadDefaultXML() { return false; return parser()->parse(); +#else + warning("The built-in theme is not enabled in the current build. Please load an external theme"); + return false; +#endif } bool ThemeRenderer::loadThemeXML(Common::String themeName) { assert(_parser); - - if (ConfMan.hasKey("themepath")) - Common::File::addDefaultDirectory(ConfMan.get("themepath")); - -#ifdef DATA_PATH - Common::File::addDefaultDirectoryRecursive(DATA_PATH); -#endif - - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); if (!parser()->loadFile(themeName + ".stx")){ #ifdef USE_ZLIB @@ -821,9 +846,9 @@ void ThemeRenderer::updateScreen() { renderDirtyScreen(); -// _vectorRenderer->fillSurface(); -// themeEval()->debugDraw(_screen, _font); -// _vectorRenderer->copyWholeFrame(_system); + // _vectorRenderer->fillSurface(); + // themeEval()->debugDraw(_screen, _font); + // _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index cb68b9ca5c..3c7d07b419 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -216,7 +216,7 @@ public: }; /** Default constructor */ - ThemeRenderer(Common::String themeName, GraphicsMode mode); + ThemeRenderer(Common::String fileName, GraphicsMode mode); /** Default destructor */ ~ThemeRenderer(); @@ -470,10 +470,11 @@ public: return 0; } - - const Common::String &getThemeName() { return _themeName; } protected: + + const Common::String &getThemeName() const { return _themeName; } + const Common::String &getThemeFileName() const { return _themeFileName; } /** * Initializes the drawing screen surfaces, _screen and _backBuffer. @@ -505,22 +506,7 @@ protected: * Unloads the currently loaded theme so another one can * be loaded. */ - void unloadTheme() { - if (!_themeOk) - return; - - for (int i = 0; i < kDrawDataMAX; ++i) { - delete _widgets[i]; - _widgets[i] = 0; - } - - for (int i = 0; i < kTextDataMAX; ++i) { - delete _texts[i]; - _texts[i] = 0; - } - - _themeOk = false; - } + void unloadTheme(); /** * Not implemented yet. @@ -710,6 +696,7 @@ protected: bool _enabled; /** Whether the Theme is currently shown on the overlay */ Common::String _themeName; /** Name of the currently loaded theme */ + Common::String _themeFileName; }; } // end of namespace GUI. diff --git a/gui/newgui.cpp b/gui/newgui.cpp index e83c86a451..f2e013bc0a 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -98,7 +98,7 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), style = "builtin"; //DEBUG: - style = "scummodern"; +// style = "scummodern"; loadNewTheme(style); @@ -110,11 +110,8 @@ NewGui::~NewGui() { delete _theme; } -bool NewGui::loadNewTheme(const Common::String &style) { - Common::String styleType; - Common::ConfigFile cfg; - - Common::String oldTheme = (_theme != 0) ? _theme->getThemeName() : ""; +bool NewGui::loadNewTheme(const Common::String &filename) { + Common::String oldTheme = (_theme != 0) ? _theme->getThemeFileName() : ""; if (_theme) _theme->disable(); @@ -127,7 +124,7 @@ bool NewGui::loadNewTheme(const Common::String &style) { delete _theme; _theme = 0; - _theme = new ThemeRenderer(style, GUI::ThemeRenderer::kGfxAntialias16bit); + _theme = new ThemeRenderer(filename, GUI::ThemeRenderer::kGfxAntialias16bit); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); diff --git a/gui/options.cpp b/gui/options.cpp index 12153469ef..96a8619cf7 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -907,7 +907,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 if (browser.runModal() > 0) { // User made his choice... const Common::String &theme = browser.selected(); - if (0 != theme.compareToIgnoreCase(g_gui.theme()->getStylefileName())) + if (0 != theme.compareToIgnoreCase(g_gui.theme()->getThemeFileName())) if (g_gui.loadNewTheme(theme)) { _curTheme->setLabel(g_gui.theme()->getThemeName()); ConfMan.set("gui_theme", theme); diff --git a/gui/theme.h b/gui/theme.h index 74158f473c..2a0b908330 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -370,12 +370,8 @@ public: static bool themeConfigUseable(const Common::String &file, const Common::String &style="", Common::String *cStyle=0, Common::ConfigFile *cfg=0); - const Common::String &getStylefileName() const { return _stylefile; } - virtual const Common::String &getThemeName() const { return _stylename; } - - virtual bool isDynamic() { - return false; - } + virtual const Common::String &getThemeFileName() const = 0; + virtual const Common::String &getThemeName() const = 0; /** * Checks if the theme renderer supports drawing of images. diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 98e6df8565..97184fda91 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -43,21 +43,21 @@ enum { // but for now this simple browser works, // also it will get its own theme config values // and not use 'browser_' anymore -ThemeBrowser::ThemeBrowser() : Dialog("browser") { +ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _fileList = 0; - new StaticTextWidget(this, "browser_headline", "Select a Theme"); + new StaticTextWidget(this, "Browser.Headline", "Select a Theme"); // Add file list - _fileList = new ListWidget(this, "browser_list"); + _fileList = new ListWidget(this, "Browser.List"); _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); _fileList->setHints(THEME_HINT_PLAIN_COLOR); // Buttons - new ButtonWidget(this, "browser_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "browser_choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); } void ThemeBrowser::open() { @@ -91,9 +91,8 @@ void ThemeBrowser::updateListing() { // classic is always build in Entry th; - th.name = "Classic (Builtin)"; - th.type = "Classic"; - th.file = "Classic (Builtin)"; + th.name = "Modern Development Theme (Builtin) - WIP"; + th.file = "builtin"; _themes.push_back(th); // we are using only the paths 'themepath', 'extrapath', DATA_PATH and '.' @@ -172,10 +171,11 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { } bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { - Common::ConfigFile cfg; - Common::String type; - out.file = node.getName(); + + if (!out.file.hasSuffix(".zip") && !out.file.hasSuffix(".stx")) + return false; + for (int i = out.file.size()-1; out.file[i] != '.' && i > 0; --i) { out.file.deleteLastChar(); } @@ -184,14 +184,13 @@ bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { if (out.file.empty()) return false; - if (!Theme::themeConfigUseable(out.file, "", &type, &cfg)) - return false; - - out.type = type; +// TODO: Check if theme is usable. +// if (!Theme::themeConfigUseable(out.file, "", &type, &cfg)) +// return false; - if (cfg.hasKey("name", "theme")) - cfg.getKey("name", "theme", out.name); - else +// if (cfg.hasKey("name", "theme")) +// cfg.getKey("name", "theme", out.name); +// else out.name = out.file; return true; diff --git a/gui/themebrowser.h b/gui/themebrowser.h index 9351648d24..7a3bc2ca7d 100644 --- a/gui/themebrowser.h +++ b/gui/themebrowser.h @@ -46,7 +46,6 @@ public: private: struct Entry { Common::String name; - Common::String type; Common::String file; }; -- cgit v1.2.3 From ba00896f5d51936947921d0e73b8d277f589f25a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 09:53:42 +0000 Subject: Fixed error when loading BDF fonts. Hot scaler swapping works without crashes! svn-id: r33751 --- gui/ThemeRenderer.cpp | 13 +++++++++++-- gui/ThemeRenderer.h | 2 +- gui/theme.cpp | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 378e32649f..2be95350e1 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -183,8 +183,8 @@ void ThemeRenderer::unloadTheme() { ImageMan.remArchive(_themeFileName + ".zip"); - _themeName.clear(); - _themeFileName.clear(); +// _themeName.clear(); +// _themeFileName.clear(); _themeOk = false; } @@ -196,6 +196,15 @@ void ThemeRenderer::clearAll() { _system->grabOverlay((OverlayColor*)_screen->pixels, _screen->w); } +void ThemeRenderer::refresh() { + init(); + if (_enabled) { + _system->showOverlay(); +// CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); +// CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + } +} + void ThemeRenderer::enable() { init(); resetDrawArea(); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 3c7d07b419..1fd5ea321c 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -234,7 +234,7 @@ public: void deinit(); void clearAll(); - void refresh() {} + void refresh(); void enable(); void disable(); diff --git a/gui/theme.cpp b/gui/theme.cpp index c8501c4f91..5355894c85 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -68,7 +68,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { return font; #ifdef USE_ZLIB - unzFile zipFile = unzOpen((_stylefile + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName() + ".zip").c_str()); if (zipFile && unzLocateFile(zipFile, cacheFilename.c_str(), 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); @@ -98,7 +98,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { #ifdef USE_ZLIB if (!font) { - unzFile zipFile = unzOpen((_stylefile + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName() + ".zip").c_str()); if (zipFile && unzLocateFile(zipFile, filename, 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); -- cgit v1.2.3 From b48d9e9f2053a79cf3d7c06184a2331370997d62 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 11:09:28 +0000 Subject: Graphic cursors. svn-id: r33753 --- gui/ThemeRenderer.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++--- gui/ThemeRenderer.h | 15 +++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 2be95350e1..30fb371cd5 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -30,7 +30,7 @@ #include "common/events.h" #include "common/config-manager.h" #include "graphics/imageman.h" - +#include "graphics/cursorman.h" #include "gui/launcher.h" #include "gui/ThemeRenderer.h" @@ -98,10 +98,12 @@ const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), - _themeOk(false), _enabled(false), _buffering(false) { + _themeOk(false), _enabled(false), _buffering(false), _cursor(0) { _system = g_system; _parser = new ThemeParser(this); _themeEval = new GUI::ThemeEval(); + + _useCursor = false; for (int i = 0; i < kDrawDataMAX; ++i) { _widgets[i] = 0; @@ -131,6 +133,7 @@ ThemeRenderer::~ThemeRenderer() { unloadTheme(); delete _parser; delete _themeEval; + delete[] _cursor; for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) ImageMan.unregisterSurface(i->_key); @@ -200,14 +203,18 @@ void ThemeRenderer::refresh() { init(); if (_enabled) { _system->showOverlay(); -// CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); -// CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); } } void ThemeRenderer::enable() { init(); resetDrawArea(); + + if (_useCursor) + setUpCursor(); + _system->showOverlay(); clearAll(); _enabled = true; @@ -215,6 +222,12 @@ void ThemeRenderer::enable() { void ThemeRenderer::disable() { _system->hideOverlay(); + + if (_useCursor) { + CursorMan.popCursorPalette(); + CursorMan.popCursor(); + } + _enabled = false; } @@ -373,6 +386,10 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { } } + if (_system->hasFeature(OSystem::kFeatureCursorHasPalette)) { + createCursor(); + } + _themeName = "DEBUG - A Theme name"; _themeOk = true; return true; @@ -890,4 +907,70 @@ void ThemeRenderer::openDialog(bool doBuffer, ShadingStyle style) { _vectorRenderer->setSurface(_screen); } +void ThemeRenderer::setUpCursor() { + CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + CursorMan.showMouse(true); +} + +void ThemeRenderer::createCursor() { + const Surface *cursor = _bitmaps["cursor.bmp"]; + + if (!cursor) + return; + + _cursorHotspotX = _themeEval->getVar("Cursor.Hotspot.X", 0); + _cursorHotspotY = _themeEval->getVar("Cursor.Hotspot.Y", 0); + + _cursorTargetScale = _themeEval->getVar("Cursor.TargetScale", 3); + + _cursorWidth = cursor->w; + _cursorHeight = cursor->h; + + uint colorsFound = 0; + const OverlayColor *src = (const OverlayColor*)cursor->pixels; + + byte *table = new byte[65536]; + assert(table); + memset(table, 0, sizeof(byte)*65536); + + byte r, g, b; + + uint16 transparency = RGBToColor >(255, 0, 255); + + delete[] _cursor; + + _cursor = new byte[_cursorWidth * _cursorHeight]; + assert(_cursor); + memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); + + for (uint y = 0; y < _cursorHeight; ++y) { + for (uint x = 0; x < _cursorWidth; ++x) { + _system->colorToRGB(src[x], r, g, b); + uint16 col = RGBToColor >(r, g, b); + if (!table[col] && col != transparency) { + table[col] = colorsFound++; + + uint index = table[col]; + _cursorPal[index * 4 + 0] = r; + _cursorPal[index * 4 + 1] = g; + _cursorPal[index * 4 + 2] = b; + _cursorPal[index * 4 + 3] = 0xFF; + + if (colorsFound > MAX_CURS_COLORS) + error("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); + } + + if (col != transparency) { + uint index = table[col]; + _cursor[y * _cursorWidth + x] = index; + } + } + src += _cursorWidth; + } + + _useCursor = true; + delete[] table; +} + } // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 1fd5ea321c..0ddfe0d7c4 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -458,7 +458,9 @@ public: } void *evaluator() { return _themeEval; } + bool supportsImages() const { return true; } + bool ownCursor() const { return _useCursor; } Graphics::Surface *getBitmap(const Common::String &name) { return _bitmaps.contains(name) ? _bitmaps[name] : 0; @@ -697,6 +699,19 @@ protected: Common::String _themeName; /** Name of the currently loaded theme */ Common::String _themeFileName; + + /** Custom Cursor Management */ + void setUpCursor(); + void createCursor(); + + bool _useCursor; + int _cursorHotspotX, _cursorHotspotY; + int _cursorTargetScale; +#define MAX_CURS_COLORS 255 + byte *_cursor; + bool _needPaletteUpdates; + uint _cursorWidth, _cursorHeight; + byte _cursorPal[4*MAX_CURS_COLORS]; }; } // end of namespace GUI. -- cgit v1.2.3 From 8a31616f46d64a1972692f8d7cd8559231a53424 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 17:22:12 +0000 Subject: Bitmap cursor loading from XML files. svn-id: r33760 --- gui/ThemeParser.cpp | 20 + gui/ThemeParser.h | 9 + gui/ThemeRenderer.cpp | 28 +- gui/ThemeRenderer.h | 12 +- gui/themes/modern.stx | 1051 -------------------------------------------- gui/themes/scummodern.stx | 1053 +++++++++++++++++++++++++++++++++++++++++++++ gui/themes/scummodern.zip | Bin 29651 -> 30075 bytes 7 files changed, 1108 insertions(+), 1065 deletions(-) delete mode 100644 gui/themes/modern.stx create mode 100644 gui/themes/scummodern.stx diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index df36ad6c7c..8fda7c2894 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -150,6 +150,26 @@ bool ThemeParser::parserCallback_fonts(ParserNode *node) { return true; } +bool ThemeParser::parserCallback_cursor(ParserNode *node) { + if (resolutionCheck(node->values["resolution"])) { + node->ignore = true; + return true; + } + + int spotx, spoty, scale; + + if (!parseIntegerKey(node->values["hotspot"].c_str(), 2, &spotx, &spoty)) + return parserError("Error when parsing cursor Hot Spot coordinates."); + + if (!parseIntegerKey(node->values["scale"].c_str(), 1, &scale)) + return parserError("Error when parsing cursor scale."); + + if (!_theme->createCursor(node->values["file"], spotx, spoty, scale)) + return parserError("Error when creating Bitmap Cursor."); + + return true; +} + bool ThemeParser::parserCallback_bitmap(ParserNode *node) { if (resolutionCheck(node->values["resolution"])) { node->ignore = true; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index b9fa69179d..905795f8ed 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -361,6 +361,13 @@ protected: XML_PROP(resolution, false) KEY_END() KEY_END() + + XML_KEY(cursor) + XML_PROP(file, true) + XML_PROP(hotspot, true) + XML_PROP(scale, true) + XML_PROP(resolution, false) + KEY_END() XML_KEY(defaults) XML_PROP(stroke, false) @@ -499,6 +506,8 @@ protected: bool parserCallback_drawdata(ParserNode *node); bool parserCallback_bitmaps(ParserNode *node) { return true; } bool parserCallback_bitmap(ParserNode *node); + bool parserCallback_cursor(ParserNode *node); + /** Layout info callbacks */ bool parserCallback_layout_info(ParserNode *node); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 30fb371cd5..73043063a5 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -386,10 +386,6 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { } } - if (_system->hasFeature(OSystem::kFeatureCursorHasPalette)) { - createCursor(); - } - _themeName = "DEBUG - A Theme name"; _themeOk = true; return true; @@ -913,16 +909,18 @@ void ThemeRenderer::setUpCursor() { CursorMan.showMouse(true); } -void ThemeRenderer::createCursor() { - const Surface *cursor = _bitmaps["cursor.bmp"]; +bool ThemeRenderer::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { + if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette)) + return false; + + const Surface *cursor = _bitmaps[filename]; if (!cursor) - return; + return false; - _cursorHotspotX = _themeEval->getVar("Cursor.Hotspot.X", 0); - _cursorHotspotY = _themeEval->getVar("Cursor.Hotspot.Y", 0); - - _cursorTargetScale = _themeEval->getVar("Cursor.TargetScale", 3); + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; + _cursorTargetScale = scale; _cursorWidth = cursor->w; _cursorHeight = cursor->h; @@ -957,8 +955,10 @@ void ThemeRenderer::createCursor() { _cursorPal[index * 4 + 2] = b; _cursorPal[index * 4 + 3] = 0xFF; - if (colorsFound > MAX_CURS_COLORS) - error("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); + if (colorsFound > MAX_CURS_COLORS) { + warning("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); + return false; + } } if (col != transparency) { @@ -971,6 +971,8 @@ void ThemeRenderer::createCursor() { _useCursor = true; delete[] table; + + return true; } } // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 0ddfe0d7c4..5ed5818f73 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -472,6 +472,17 @@ public: return 0; } + + /** + * Interface for the Theme Parser: Creates a new cursor by loading the given + * bitmap and sets it as the active cursor. + * + * @param filename File name of the bitmap to load. + * @param hotspotX X Coordinate of the bitmap which does the cursor click. + * @param hotspotY Y Coordinate of the bitmap which does the cursor click. + * @param scale Scale at which the bitmap is supposed to be used. + */ + bool createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale); protected: @@ -702,7 +713,6 @@ protected: /** Custom Cursor Management */ void setUpCursor(); - void createCursor(); bool _useCursor; int _cursorHotspotX, _cursorHotspotY; diff --git a/gui/themes/modern.stx b/gui/themes/modern.stx deleted file mode 100644 index 671e9d0856..0000000000 --- a/gui/themes/modern.stx +++ /dev/null @@ -1,1051 +0,0 @@ -/* 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$ - * - */ - -/* ScummVM Theme XML file */ -/* Modern Theme */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx new file mode 100644 index 0000000000..965008a6e8 --- /dev/null +++ b/gui/themes/scummodern.stx @@ -0,0 +1,1053 @@ +/* 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$ + * + */ + +/* ScummVM Theme XML file */ +/* Modern Theme */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 67b89951ed..2a6f268eb9 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 559c19e9f4aa22ab37cbc4af29ea1dae28dd42a4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 18:26:14 +0000 Subject: Bugfix: Inverse layout reflowing. Bugfix: Glitches with several layouts when using Aspect Ratio Correction. svn-id: r33764 --- engines/scumm/dialogs.cpp | 33 ++++++++++++++++----------------- gui/ThemeEval.cpp | 10 ++++++++-- gui/ThemeEval.h | 2 +- gui/ThemeRenderer.cpp | 8 ++++---- gui/themes/scummodern.stx | 27 ++++++++++++++++++++++++++- gui/themes/scummodern.zip | Bin 30075 -> 109834 bytes 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index bdb7118f56..559ad6e69e 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -318,7 +318,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da } void SaveLoadChooser::reflowLayout() { - if (g_gui.evaluator()->getVar("scummsaveload_extinfo.visible") == 1) { + if (g_gui.xmlEval()->getVar("ScummSaveLoad.ExtInfo.Visible", 1) == 1) { int16 x, y; uint16 w, h; @@ -644,16 +644,16 @@ enum { }; HelpDialog::HelpDialog(const GameSettings &game) - : ScummDialog("scummhelp"), _game(game) { - _title = new StaticTextWidget(this, "scummhelp_title", ""); + : ScummDialog("ScummHelp"), _game(game) { + _title = new StaticTextWidget(this, "ScummHelp.Title", ""); _page = 1; _numPages = ScummHelp::numPages(_game.id); - _prevButton = new GUI::ButtonWidget(this, "scummhelp_prev", "Previous", kPrevCmd, 'P'); - _nextButton = new GUI::ButtonWidget(this, "scummhelp_next", "Next", kNextCmd, 'N'); - new GUI::ButtonWidget(this, "scummhelp_close", "Close", kCloseCmd, 'C'); + _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", "Previous", kPrevCmd, 'P'); + _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", "Next", kNextCmd, 'N'); + new GUI::ButtonWidget(this, "ScummHelp.Close", "Close", kCloseCmd, 'C'); _prevButton->clearFlags(WIDGET_ENABLED); // Dummy entries @@ -670,19 +670,18 @@ void HelpDialog::reflowLayout() { _drawingHints &= ~GUI::THEME_HINT_SPECIAL_COLOR; int lineHeight = g_gui.getFontHeight(); - - int keyX = g_gui.evaluator()->getVar("scummhelp_key.x"); - int keyYoff = g_gui.evaluator()->getVar("scummhelp_key.yoffset"); - int keyW = g_gui.evaluator()->getVar("scummhelp_key.w"); - int keyH = g_gui.evaluator()->getVar("scummhelp_key.h"); - int dscX = g_gui.evaluator()->getVar("scummhelp_dsc.x"); - int dscYoff = g_gui.evaluator()->getVar("scummhelp_dsc.yoffset"); - int dscW = g_gui.evaluator()->getVar("scummhelp_dsc.w"); - int dscH = g_gui.evaluator()->getVar("scummhelp_dsc.h"); + int16 x, y; + uint16 w, h; + + g_gui.xmlEval()->getWidgetData("ScummHelp.HelpText", x, y, w, h); + + int keyW = w * 20 / 100; + int dscX = x + keyW; + int dscW = w * 80 / 100; for (int i = 0; i < HELP_NUM_LINES; i++) { - _key[i]->resize(keyX, keyYoff + lineHeight * (i + 2), keyW, keyH); - _dsc[i]->resize(dscX, dscYoff + lineHeight * (i + 2), dscW, dscH); + _key[i]->resize(x, y + lineHeight * i, keyW, lineHeight + 2); + _dsc[i]->resize(dscX, y + lineHeight * i, dscW, lineHeight + 2); } displayKeyBindings(); diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index ec866cc626..ab9e726b75 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -124,8 +124,11 @@ void ThemeLayoutVertical::reflowLayout() { if (autoWidget != -1 && autoWidget != (int)i) { _children[autoWidget]->setHeight(_children[autoWidget]->getHeight() - (_children[i]->getHeight() + _spacing)); - for (int j = autoWidget - 1; j >= 0; --j) + + if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) _children[j]->setY(-(_children[i]->getHeight() + _spacing)); + else + _children[i]->setY(-2 * (_children[i]->getHeight() + _spacing)); } else { _h += _children[i]->getHeight() + _spacing; } @@ -172,8 +175,11 @@ void ThemeLayoutHorizontal::reflowLayout() { if (autoWidget != -1 && autoWidget != (int)i) { _children[autoWidget]->setWidth(_children[autoWidget]->getWidth() - (_children[i]->getWidth() + _spacing)); - for (int j = autoWidget - 1; j >= 0; --j) + + if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) _children[j]->setX(-(_children[i]->getWidth() + _spacing)); + else + _children[i]->setX(-2 * (_children[i]->getWidth() + _spacing)); } else { _w += _children[i]->getWidth() + _spacing; } diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index eecd2db3ee..aaab4cb2bf 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -377,7 +377,7 @@ public: } void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.Browser"]->debugDraw(screen, font); + _layouts["Dialog.Launcher"]->debugDraw(screen, font); // _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); } diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 73043063a5..1c3a1af8cf 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -866,11 +866,11 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } - renderDirtyScreen(); +// renderDirtyScreen(); - // _vectorRenderer->fillSurface(); - // themeEval()->debugDraw(_screen, _font); - // _vectorRenderer->copyWholeFrame(_system); + _vectorRenderer->fillSurface(); + themeEval()->debugDraw(_screen, _font); + _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx index 965008a6e8..d3df1865ca 100644 --- a/gui/themes/scummodern.stx +++ b/gui/themes/scummodern.stx @@ -483,6 +483,8 @@ + + - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 2a6f268eb9..e9280529f1 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From b2bac41d0ed98f4f69a9a9232d7a373d76ef1e39 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 18:35:27 +0000 Subject: Reverted debug layout drawing. Bugfix: Scrollbar overlapping in text widgets/text overlapping? svn-id: r33765 --- gui/ListWidget.cpp | 4 ++-- gui/ThemeRenderer.cpp | 8 ++++---- gui/themes/scummodern.stx | 2 +- gui/themes/scummodern.zip | Bin 109834 -> 112527 bytes 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index d6649fc7f2..fa79ef4670 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -398,7 +398,7 @@ void ListWidget::drawWidget() { if (_selectedItem == pos && _editMode) { buffer = _editString; adjustOffset(); - width = _w - r.left - _hlRightPadding - _leftPadding; + width = _w - r.left - _hlRightPadding - _leftPadding - _scrollBarWidth; g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); } else { @@ -409,7 +409,7 @@ void ListWidget::drawWidget() { if (width > _w - r.left) width = _w - r.left; } else - width = _w - r.left - _hlRightPadding; + width = _w - r.left - _hlRightPadding - _scrollBarWidth; if (width > maxWidth) maxWidth = width; g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1c3a1af8cf..b8d7204669 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -866,11 +866,11 @@ void ThemeRenderer::updateScreen() { _textQueue.clear(); } -// renderDirtyScreen(); + renderDirtyScreen(); - _vectorRenderer->fillSurface(); - themeEval()->debugDraw(_screen, _font); - _vectorRenderer->copyWholeFrame(_system); +// _vectorRenderer->fillSurface(); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); } void ThemeRenderer::renderDirtyScreen() { diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx index d3df1865ca..fb388b7e5f 100644 --- a/gui/themes/scummodern.stx +++ b/gui/themes/scummodern.stx @@ -478,7 +478,7 @@ - + diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index e9280529f1..dd53887cda 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 52f3551587aad266a794e69416a9662023e55e0f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 18:56:10 +0000 Subject: Bugfix: Several text-drawing issues. Bugfix: Overlapping text in text edit dialogs. svn-id: r33768 --- graphics/VectorRenderer.cpp | 27 ++++++++++++++------------- graphics/VectorRenderer.h | 4 ++-- gui/ListWidget.cpp | 2 +- gui/ThemeRenderer.cpp | 15 ++++++--------- gui/ThemeRenderer.h | 2 +- gui/themes/scummodern.zip | Bin 112527 -> 107874 bytes 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index e3e7174d90..17a221a725 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -323,23 +323,24 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, - GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax) { + GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax, bool ellipsis) { - int offset = 0; + int offset = area.top; - switch (alignV) { - case GUI::Theme::kTextAlignVCenter: - offset = area.top + (area.height() - font->getFontHeight()) / 2; - break; - case GUI::Theme::kTextAlignVBottom: - offset = area.bottom - font->getFontHeight(); - break; - case GUI::Theme::kTextAlignVTop: - offset = area.top; - break; + if (font->getFontHeight() < area.height()) { + switch (alignV) { + case GUI::Theme::kTextAlignVCenter: + offset = area.top + ((area.height() - font->getFontHeight()) >> 1); + break; + case GUI::Theme::kTextAlignVBottom: + offset = area.bottom - font->getFontHeight(); + break; + default: + break; + } } - font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, deltax, false); + font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, deltax, ellipsis); } /** LINES **/ diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 7eff0a9c50..13ba9ff480 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -477,7 +477,7 @@ public: * Draws a string into the screen. Wrapper for the Graphics::Font string drawing * method. */ - virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax, bool useEllipsis) = 0; /** * Allows to temporarily enable/disable all shadows drawing. @@ -604,7 +604,7 @@ public: void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, - GUI::Theme::TextAlignVertical alignV, int deltax); + GUI::Theme::TextAlignVertical alignV, int deltax, bool elipsis); /** * @see VectorRenderer::setFgColor() diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index fa79ef4670..5881d9fcef 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -407,7 +407,7 @@ void ListWidget::drawWidget() { if (_selectedItem != pos) { width = g_gui.getStringWidth(buffer) + pad; if (width > _w - r.left) - width = _w - r.left; + width = _w - r.left - _hlRightPadding - _scrollBarWidth; } else width = _w - r.left - _hlRightPadding - _scrollBarWidth; if (width > maxWidth) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index b8d7204669..b179ac75c3 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -552,7 +552,7 @@ void ThemeRenderer::drawDDText(const DrawQueueText &q) { restoreBackground(q.area); _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); - _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax); + _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax, q.elipsis); addDirtyRect(q.area); } @@ -781,18 +781,15 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W if (!ready()) return; - Common::Rect dr = r; - dr.left += deltax; - if (inverted) { queueDD(kDDTextSelectionBackground, r); - queueDDText(kTextDataInverted, dr, str, false, useEllipsis, align); + queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax); return; } switch (font) { case kFontStyleNormal: - queueDDText(kTextDataNormalFont, dr, str, true, useEllipsis, align); + queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); return; default: @@ -801,15 +798,15 @@ void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, W switch (state) { case kStateDisabled: - queueDDText(kTextDataDisabled, dr, str, true, useEllipsis, align); + queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); return; case kStateHighlight: - queueDDText(kTextDataHover, dr, str, true, useEllipsis, align); + queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); return; case kStateEnabled: - queueDDText(kTextDataDefault, dr, str, true, useEllipsis, align); + queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); return; } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 5ed5818f73..1c328430e7 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -94,7 +94,7 @@ protected: friend class GUI::GuiObject; /** Constant value to expand dirty rectangles, to make sure they are fully copied */ - static const int kDirtyRectangleThreshold = 2; + static const int kDirtyRectangleThreshold = 0; /** Sets whether backcaching is enabled */ static const bool kEnableBackCaching = true; diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index dd53887cda..aca5fa32a8 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From a4b3434af91bcb7ea272c7e214e249c0f6823126 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Aug 2008 22:03:00 +0000 Subject: Bugfix: Selection background too short when scrollbar not present. Bugfix: Vector renderer drawstep for bitmap blitting. Added bitmap GFX for checkboxes. svn-id: r33771 --- graphics/VectorRenderer.h | 4 +--- gui/ListWidget.cpp | 7 ++++--- gui/ThemeParser.cpp | 6 ++++-- gui/ThemeParser.h | 2 +- gui/themes/scummodern.stx | 8 ++++++-- gui/themes/scummodern.zip | Bin 107874 -> 111123 bytes 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 13ba9ff480..34c9c2c8a5 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -417,7 +417,7 @@ public: void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step) { uint16 x, y, w, h; stepGetPositions(step, area, x, y, w, h); - blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, w, h)); + blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, x + w, y + h)); } void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {} @@ -720,8 +720,6 @@ public: } virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { - assert(r.width() >= source->w && r.height() >= source->h); - int16 x = r.left; int16 y = r.top; diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 5881d9fcef..13633941c8 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -364,6 +364,7 @@ void ListWidget::drawWidget() { // Draw a thin frame around the list. g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _hints, Theme::kWidgetBackgroundBorder); + const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0; // Draw the list items for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) { @@ -398,7 +399,7 @@ void ListWidget::drawWidget() { if (_selectedItem == pos && _editMode) { buffer = _editString; adjustOffset(); - width = _w - r.left - _hlRightPadding - _leftPadding - _scrollBarWidth; + width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW; g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); } else { @@ -407,9 +408,9 @@ void ListWidget::drawWidget() { if (_selectedItem != pos) { width = g_gui.getStringWidth(buffer) + pad; if (width > _w - r.left) - width = _w - r.left - _hlRightPadding - _scrollBarWidth; + width = _w - r.left - _hlRightPadding - scrollbarW; } else - width = _w - r.left - _hlRightPadding - _scrollBarWidth; + width = _w - r.left - _hlRightPadding - scrollbarW; if (width > maxWidth) maxWidth = width; g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 8fda7c2894..572acc0b76 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -354,10 +354,12 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst Common::String functionName = stepNode->values["func"]; if (functionName == "bitmap") { - if (!stepNode->values.contains("filename")) + if (!stepNode->values.contains("file")) return parserError("Need to specify a filename for Bitmap blitting."); - if (!_theme->getBitmap(stepNode->values["filename"])) + drawstep->blitSrc = _theme->getBitmap(stepNode->values["file"]); + + if (!drawstep->blitSrc) return parserError("The given filename hasn't been loaded into the GUI."); } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 905795f8ed..782ab9a44f 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -422,7 +422,7 @@ protected: XML_PROP(xpos, false) XML_PROP(ypos, false) XML_PROP(orientation, false) - XML_PROP(bitmap, false) + XML_PROP(file, false) KEY_END() XML_KEY(text) diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx index fb388b7e5f..a2a58e3e67 100644 --- a/gui/themes/scummodern.stx +++ b/gui/themes/scummodern.stx @@ -60,6 +60,7 @@ + @@ -419,7 +420,7 @@ vertical_align = 'top' horizontal_align = 'left' /> - */ + @@ -518,7 +522,7 @@ padding = '7, 5, 0, 0' /> 137193 bytes 9 files changed, 688 insertions(+), 425 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 559ad6e69e..1dbbc28f92 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -238,7 +238,7 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; - new StaticTextWidget(this, "ScummSaveload.Title", title); + new StaticTextWidget(this, "ScummSaveLoad.Title", title); // Add choice list _list = new GUI::ListWidget(this, "ScummSaveLoad.List"); @@ -318,7 +318,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da } void SaveLoadChooser::reflowLayout() { - if (g_gui.xmlEval()->getVar("ScummSaveLoad.ExtInfo.Visible", 1) == 1) { + if (g_gui.xmlEval()->getVar("Globals.ScummSaveLoad.ExtInfo.Visible") == 1) { int16 x, y; uint16 w, h; diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index ab9e726b75..f93706cb47 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -85,6 +85,7 @@ void ThemeLayoutMain::reflowLayout() { void ThemeLayoutVertical::reflowLayout() { int curX, curY; int autoWidget = -1; + int extraHeight = 0; curX = _paddingLeft; curY = _paddingTop; @@ -127,8 +128,13 @@ void ThemeLayoutVertical::reflowLayout() { if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) _children[j]->setY(-(_children[i]->getHeight() + _spacing)); - else - _children[i]->setY(-2 * (_children[i]->getHeight() + _spacing)); + else { + extraHeight -= (_children[i]->getHeight() + _spacing); + _children[i]->setY(extraHeight); + + for (int j = i - 1; j > autoWidget; --j) + _children[j]->setY(-(_children[i]->getHeight() + _spacing)); + } } else { _h += _children[i]->getHeight() + _spacing; } @@ -138,6 +144,7 @@ void ThemeLayoutVertical::reflowLayout() { void ThemeLayoutHorizontal::reflowLayout() { int curX, curY; int autoWidget = -1; + int autoWidth = 0; curX = _paddingLeft; curY = _paddingTop; @@ -178,8 +185,13 @@ void ThemeLayoutHorizontal::reflowLayout() { if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) _children[j]->setX(-(_children[i]->getWidth() + _spacing)); - else - _children[i]->setX(-2 * (_children[i]->getWidth() + _spacing)); + else { + autoWidth -= (_children[i]->getWidth() + _spacing); + _children[i]->setX(autoWidth); + + for (int j = i - 1; j > autoWidget; --j) + _children[j]->setX(-(_children[i]->getWidth() + _spacing)); + } } else { _w += _children[i]->getWidth() + _spacing; } @@ -229,18 +241,18 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0); } -void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled) { +void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled, int inset) { int16 x, y; uint16 w, h; ThemeLayout *layout = 0; if (overlays == "screen") { - layout = new ThemeLayoutMain(0, 0, g_system->getOverlayWidth(), g_system->getOverlayHeight()); + layout = new ThemeLayoutMain(inset, inset, g_system->getOverlayWidth() - 2 * inset, g_system->getOverlayHeight() - 2 * inset); } else if (overlays == "screen_center") { layout = new ThemeLayoutMain(-1, -1, -1, -1); } else if (getWidgetData(overlays, x, y, w, h)) { - layout = new ThemeLayoutMain(x, y, w, h); + layout = new ThemeLayoutMain(x + inset, y + inset, w - 2 * inset, h - 2 * inset); } if (!layout) diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index aaab4cb2bf..e0c1c5af59 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -336,7 +336,7 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name) || _builtin.contains(name); } - void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true); + void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true, int inset = 0); void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true); bool addImportedLayout(const Common::String &name); @@ -383,12 +383,13 @@ public: void reset() { _vars.clear(); - _builtin.clear(); _curDialog.clear(); _curLayout.clear(); for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i) delete i->_value; + + _layouts.clear(); } private: diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 572acc0b76..3167f94009 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -130,7 +130,7 @@ bool ThemeParser::parserCallback_defaults(ParserNode *node) { bool ThemeParser::parserCallback_font(ParserNode *node) { int red, green, blue; - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -151,7 +151,7 @@ bool ThemeParser::parserCallback_fonts(ParserNode *node) { } bool ThemeParser::parserCallback_cursor(ParserNode *node) { - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -171,7 +171,7 @@ bool ThemeParser::parserCallback_cursor(ParserNode *node) { } bool ThemeParser::parserCallback_bitmap(ParserNode *node) { - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -209,12 +209,16 @@ bool ThemeParser::parserCallback_text(ParserNode *node) { } bool ThemeParser::parserCallback_render_info(ParserNode *node) { - // TODO: Skip key if it's not for this platform. + if (resolutionCheck(node->values["resolution"]) == false) + node->ignore = true; + return true; } bool ThemeParser::parserCallback_layout_info(ParserNode *node) { - // TODO: skip key + if (resolutionCheck(node->values["resolution"]) == false) + node->ignore = true; + return true; } @@ -264,7 +268,7 @@ bool ThemeParser::parserCallback_drawstep(ParserNode *node) { bool ThemeParser::parserCallback_drawdata(ParserNode *node) { bool cached = false; - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -479,7 +483,7 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } bool ThemeParser::parserCallback_def(ParserNode *node) { - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -502,7 +506,7 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { if (getParentNode(node)->name == "globals") { - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -546,20 +550,12 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { return true; } -bool ThemeParser::parserCallback_child(ParserNode *node) { - Common::String var = "Globals." + getParentNode(node)->values["name"] + "." + node->values["name"] + "."; - - if (!parseCommonLayoutProps(node, var)) - return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); - - return true; -} - bool ThemeParser::parserCallback_dialog(ParserNode *node) { Common::String var = "Dialog." + node->values["name"]; bool enabled = true; + int inset = 0; - if (resolutionCheck(node->values["resolution"])) { + if (resolutionCheck(node->values["resolution"]) == false) { node->ignore = true; return true; } @@ -571,7 +567,12 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { return parserError("Invalid value for Dialog enabling (expecting true/false)"); } - _theme->themeEval()->addDialog(var, node->values["overlays"], enabled); + if (node->values.contains("inset")) { + if (!parseIntegerKey(node->values["inset"].c_str(), 1, &inset)) + return false; + } + + _theme->themeEval()->addDialog(var, node->values["overlays"], enabled, inset); if (node->values.contains("shading")) { int shading = 0; @@ -767,14 +768,33 @@ bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String bool ThemeParser::resolutionCheck(const Common::String &resolution) { if (resolution.empty()) - return false; + return true; - Common::StringTokenizer tokenizer(resolution, "x"); - Common::String w = tokenizer.nextToken(); - Common::String h = tokenizer.nextToken(); + Common::StringTokenizer globTokenizer(resolution, ", "); + Common::String cur, w, h; + bool definedRes = false; - return ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) && - (h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight())) == false; + while (!globTokenizer.empty()) { + bool ignore = false; + cur = globTokenizer.nextToken(); + + if (cur[0] == '-') { + ignore = true; + cur.deleteChar(0); + } else { + definedRes = true; + } + + Common::StringTokenizer resTokenizer(cur, "x"); + w = resTokenizer.nextToken(); + h = resTokenizer.nextToken(); + + if ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) && + (h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight())) + return !ignore; + } + + return !definedRes; } } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 782ab9a44f..e4821ef00f 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -38,272 +38,6 @@ #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; @@ -339,6 +73,7 @@ protected: CUSTOM_XML_PARSER(ThemeParser) { XML_KEY(render_info) + XML_PROP(resolution, false) XML_KEY(palette) XML_KEY(color) XML_PROP(name, true) @@ -435,6 +170,7 @@ protected: KEY_END() // render_info end XML_KEY(layout_info) + XML_PROP(resolution, false) XML_KEY(globals) XML_PROP(resolution, false) XML_KEY(def) @@ -449,12 +185,6 @@ protected: XML_PROP(pos, false) XML_PROP(padding, false) XML_PROP(resolution, false) - - XML_KEY(child) - XML_PROP(name, true) - XML_PROP(size, false) - XML_PROP(padding, false) - KEY_END() KEY_END() KEY_END() @@ -464,6 +194,7 @@ protected: XML_PROP(shading, false) XML_PROP(enabled, false) XML_PROP(resolution, false) + XML_PROP(inset, false) XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) @@ -515,7 +246,6 @@ protected: bool parserCallback_def(ParserNode *node); bool parserCallback_widget(ParserNode *node); bool parserCallback_dialog(ParserNode *node); - bool parserCallback_child(ParserNode *node); bool parserCallback_layout(ParserNode *node); bool parserCallback_space(ParserNode *node); bool parserCallback_import(ParserNode *node); diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index b179ac75c3..9f517abd2d 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -96,7 +96,7 @@ const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : - _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), + _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _font(0), _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), _themeOk(false), _enabled(false), _buffering(false), _cursor(0) { _system = g_system; @@ -114,16 +114,8 @@ ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : } _graphicsMode = mode; - setGraphicsMode(_graphicsMode); - - if (_screen->w >= 400 && _screen->h >= 300) { - _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } - _themeFileName = fileName; - _initOk = true; + _initOk = false; } ThemeRenderer::~ThemeRenderer() { @@ -149,6 +141,12 @@ bool ThemeRenderer::init() { clearAll(); resetDrawArea(); } + + if (_screen->w >= 400 && _screen->h >= 300) { + _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + } else { + _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + } if (isThemeLoadingRequired() || !_themeOk) { loadTheme(_themeFileName); @@ -185,9 +183,8 @@ void ThemeRenderer::unloadTheme() { ImageMan.unregisterSurface(i->_key); ImageMan.remArchive(_themeFileName + ".zip"); - -// _themeName.clear(); -// _themeFileName.clear(); + + _themeEval->reset(); _themeOk = false; } diff --git a/gui/options.cpp b/gui/options.cpp index 96a8619cf7..1e6e551a57 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -669,7 +669,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // // 1) The graphics tab // - tab->addTab("Graphics"); + tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); addGraphicControls(tab, "GlobalOptions_Graphics."); // diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx index a2a58e3e67..5399ed62f0 100644 --- a/gui/themes/scummodern.stx +++ b/gui/themes/scummodern.stx @@ -420,16 +420,6 @@ vertical_align = 'top' horizontal_align = 'left' /> -/* */ @@ -462,55 +452,35 @@ - + - - - - - - + + + - - - - - - + + + - - + + - - - + - - + - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index c58c4c1c2e..a607166b47 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 0dcfb38d49e60881c5727ff8ec4d806f339ab696 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 13 Aug 2008 12:08:14 +0000 Subject: Improved theme loading. Added support for multiple STX files. svn-id: r33824 --- gui/ThemeRenderer.cpp | 67 ++++++++++++++++++++++++++-------------------- gui/themes/scummodern.zip | Bin 137193 -> 116190 bytes 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 9f517abd2d..3cb7f13dbd 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -412,43 +412,52 @@ bool ThemeRenderer::loadDefaultXML() { bool ThemeRenderer::loadThemeXML(Common::String themeName) { assert(_parser); - - if (!parser()->loadFile(themeName + ".stx")){ + #ifdef USE_ZLIB - unzFile zipFile = unzOpen((themeName + ".zip").c_str()); - - if (zipFile && unzLocateFile(zipFile, (themeName + ".stx").c_str(), 2) == UNZ_OK) { - + unzFile zipFile = unzOpen((themeName + ".zip").c_str()); + char fileNameBuffer[32]; + int parseCount = 0; + + if (zipFile && unzGoToFirstFile(zipFile) == UNZ_OK) { + while (true) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - - Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); + unzGetCurrentFileInfo(zipFile, &fileInfo, fileNameBuffer, 32, NULL, 0, NULL, 0); + + if (matchString(fileNameBuffer, "*.stx")) { + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - if (!parser()->loadStream(stream)) { - unzClose(zipFile); - delete stream; - return false; + Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); + + if (parser()->loadStream(stream) == false || parser()->parse() == false) { + warning("Failed to load stream for %s", fileNameBuffer); + unzClose(zipFile); + delete stream; + return false; + } + + parseCount++; } - -// delete[] buffer; - buffer = 0; - } else { - unzClose(zipFile); - return false; + + unzCloseCurrentFile(zipFile); + + if (unzGoToNextFile(zipFile) == UNZ_END_OF_LIST_OF_FILE) + break; } - unzClose(zipFile); -#else - return false; -#endif + } else if (parser()->loadFile(themeName + ".stx") && parser()->parse()) { + parseCount++; + } else { + warning("No theme files for '%s' found.", themeName.c_str()); } - return parser()->parse(); + unzClose(zipFile); + return (parseCount > 0); +#else + return (parser()->loadFile(themeName + ".stx") && parser()->parse()); +#endif } bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index a607166b47..3f23dde775 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 1d9f98d121e51943b4967cf6188062aae9195af4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 13 Aug 2008 16:50:50 +0000 Subject: Massive API cleanup (removed legacy code). Improved theme loading support. svn-id: r33832 --- gui/ThemeRenderer.cpp | 4 +- gui/ThemeRenderer.h | 7 ++- gui/module.mk | 5 +- gui/newgui.cpp | 14 ++---- gui/newgui.h | 3 +- gui/theme-config.cpp | 12 ----- gui/theme.cpp | 124 ++++------------------------------------------ gui/theme.h | 58 ++-------------------- gui/themes/scummodern.zip | Bin 116190 -> 116164 bytes 9 files changed, 25 insertions(+), 202 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 3cb7f13dbd..1632488b91 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -433,7 +433,7 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); if (parser()->loadStream(stream) == false || parser()->parse() == false) { - warning("Failed to load stream for %s", fileNameBuffer); + warning("Failed to load stream for zipped file '%s'", fileNameBuffer); unzClose(zipFile); delete stream; return false; @@ -444,7 +444,7 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { unzCloseCurrentFile(zipFile); - if (unzGoToNextFile(zipFile) == UNZ_END_OF_LIST_OF_FILE) + if (unzGoToNextFile(zipFile) != UNZ_OK) break; } } else if (parser()->loadFile(themeName + ".stx") && parser()->parse()) { diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 1c328430e7..d26dc21f48 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -453,11 +453,10 @@ public: * Finishes buffering: widgets from there one will be drawn straight on the screen * without drawing queues. */ - void finishBuffering() { - _buffering = false; - } + void finishBuffering() { _buffering = false; } + void startBuffering() { _buffering = true; } - void *evaluator() { return _themeEval; } + ThemeEval *evaluator() { return _themeEval; } bool supportsImages() const { return true; } bool ownCursor() const { return _useCursor; } diff --git a/gui/module.mk b/gui/module.mk index 0711f236a4..1cb9ecb30f 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -25,10 +25,7 @@ MODULE_OBJS := \ widget.o \ theme.o \ ThemeEval.o \ - ThemeClassic.o \ - ThemeModern.o \ - ThemeParser.o \ - theme-config.o + ThemeParser.o # Include common rules include $(srcdir)/rules.mk diff --git a/gui/newgui.cpp b/gui/newgui.cpp index f2e013bc0a..665d190e6f 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -93,16 +93,11 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), ConfMan.registerDefault("gui_theme", "default"); - Common::String style(ConfMan.get("gui_theme")); - if (style.compareToIgnoreCase("default") == 0) - style = "builtin"; - - //DEBUG: -// style = "scummodern"; - - loadNewTheme(style); + Common::String themefile(ConfMan.get("gui_theme")); + if (themefile.compareToIgnoreCase("default") == 0) + themefile = "builtin"; - _theme->resetDrawArea(); + loadNewTheme(themefile); _themeChange = false; } @@ -130,7 +125,6 @@ bool NewGui::loadNewTheme(const Common::String &filename) { return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); _theme->init(); - _theme->resetDrawArea(); if (!oldTheme.empty()) screenChange(); diff --git a/gui/newgui.h b/gui/newgui.h index 5fabe4ea1f..b7ef589f07 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -79,8 +79,7 @@ public: bool loadNewTheme(const Common::String &file); Theme *theme() { return _theme; } - Eval *evaluator() { return _theme->_evaluator; } - ThemeEval *xmlEval() { return (ThemeEval*)_theme->evaluator(); } + ThemeEval *xmlEval() { return _theme->evaluator(); } const Graphics::Font &getFont(Theme::FontStyle style = Theme::kFontStyleBold) const { return *(_theme->getFont(style)); } int getFontHeight(Theme::FontStyle style = Theme::kFontStyleBold) const { return _theme->getFontHeight(style); } diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp index 1f52567e3e..f70696e8d5 100644 --- a/gui/theme-config.cpp +++ b/gui/theme-config.cpp @@ -666,18 +666,6 @@ void Theme::setSpecialAlias(const String &alias, const String &name) { } } -bool Theme::isThemeLoadingRequired() { - int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - - if (_loadedThemeX == x && _loadedThemeY == y) - return false; - - _loadedThemeX = x; - _loadedThemeY = y; - - return true; -} - bool Theme::sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h) { if (!config.hasKey("skipFor", name)) return false; diff --git a/gui/theme.cpp b/gui/theme.cpp index 5355894c85..6e05ce086c 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -29,32 +29,9 @@ namespace GUI { -Theme::Theme() : _drawArea(), _stylefile(""), _configFile(), _loadedThemeX(0), _loadedThemeY(0) { - Common::MemoryReadStream s((const byte *)_defaultConfigINI, strlen(_defaultConfigINI)); - _defaultConfig.loadFromStream(s); +Theme::Theme() : _loadedThemeX(0), _loadedThemeY(0) {} - _evaluator = new Eval(); -} - -Theme::~Theme() { - delete _evaluator; -} - -void Theme::getColorFromConfig(const Common::String &value, OverlayColor &color) { - const char *postfixes[] = {".r", ".g", ".b"}; - int rgb[3]; - - for (int cnt = 0; cnt < 3; cnt++) - rgb[cnt] = _evaluator->getVar(value + postfixes[cnt], 0); - - color = g_system->RGBToColor(rgb[0], rgb[1], rgb[2]); -} - -void Theme::getColorFromConfig(const Common::String &value, uint8 &r, uint8 &g, uint8 &b) { - r = _evaluator->getVar(value + ".r", 0); - g = _evaluator->getVar(value + ".g", 0); - b = _evaluator->getVar(value + ".b", 0); -} +Theme::~Theme() {} const Graphics::Font *Theme::loadFont(const char *filename) { const Graphics::NewFont *font = 0; @@ -146,51 +123,19 @@ Common::String Theme::genCacheFilename(const char *filename) { return ""; } -bool Theme::loadConfigFile(const Common::String &stylefile) { - if (ConfMan.hasKey("themepath")) - Common::File::addDefaultDirectory(ConfMan.get("themepath")); - -#ifdef DATA_PATH - Common::File::addDefaultDirectoryRecursive(DATA_PATH); -#endif - - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); +bool Theme::isThemeLoadingRequired() { + int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - if (!_configFile.loadFromFile(stylefile + ".ini")) { -#ifdef USE_ZLIB - // Maybe find a nicer solution to this - unzFile zipFile = unzOpen((stylefile + ".zip").c_str()); - if (zipFile && unzLocateFile(zipFile, (stylefile + ".ini").c_str(), 2) == UNZ_OK) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); - if (!_configFile.loadFromStream(stream)) { - unzClose(zipFile); - return false; - } - delete[] buffer; - buffer = 0; - } else { - unzClose(zipFile); - return false; - } - unzClose(zipFile); -#else + if (_loadedThemeX == x && _loadedThemeY == y) return false; -#endif - } + + _loadedThemeX = x; + _loadedThemeY = y; return true; } -bool Theme::themeConfigUseable(const Common::String &stylefile, const Common::String &style, Common::String *cStyle, Common::ConfigFile *cfg) { +bool Theme::themeConfigUseable(const Common::String &filename) { if (ConfMan.hasKey("themepath")) Common::File::addDefaultDirectory(ConfMan.get("themepath")); @@ -201,58 +146,7 @@ bool Theme::themeConfigUseable(const Common::String &stylefile, const Common::St if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - Common::File file; - Common::ConfigFile configFile; - if (!cfg && (cStyle || !style.empty())) - cfg = &configFile; - if (!file.open(stylefile + ".ini")) { -#ifdef USE_ZLIB - // Maybe find a nicer solution to this - unzFile zipFile = unzOpen((stylefile + ".zip").c_str()); - if (zipFile && unzLocateFile(zipFile, (stylefile + ".ini").c_str(), 2) == UNZ_OK) { - if (!style.empty() || cStyle || cfg) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); - if (!cfg->loadFromStream(stream)) { - unzClose(zipFile); - return false; - } - delete[] buffer; - buffer = 0; - } - } else { - unzClose(zipFile); - return false; - } - unzClose(zipFile); -#else - return false; -#endif - } - - if (!style.empty() || cStyle || cfg) { - if (file.isOpen()) { - if (!cfg->loadFromStream(file)) - return false; - file.close(); - } - - Common::String temp; - if (!cfg->getKey("type", "theme", temp)) - return false; - if (cStyle) - *cStyle = temp; - if (0 != temp.compareToIgnoreCase(style) && !style.empty()) - return false; - } return true; } diff --git a/gui/theme.h b/gui/theme.h index 2a0b908330..067603d562 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -38,7 +38,7 @@ namespace GUI { -class Eval; +class ThemeEval; //! Hint to the theme engine that the widget is used in a non-standard way. enum ThemeHint { @@ -250,9 +250,8 @@ public: * the dialog, we return false, which means we need to redraw * the dialog stack from scratch. */ - virtual bool closeDialog() { return false; } - virtual void startBuffering() {} - virtual void finishBuffering() {} + virtual void startBuffering() = 0; + virtual void finishBuffering() = 0; /** * Clear the complete GUI screen. @@ -267,36 +266,6 @@ public: */ virtual void updateScreen() = 0; - /** - * Set the active screen area, in which the renderer is able to - * draw. - * - * This does not affect the coordinates for the draw* functions, - * it just marks the screen rect given in param r as writeable. - * - * This is for example used in the credits dialog, which, if not - * just a part of the screen would be marked as writeable, would - * draw parts of the scrolling text outside the dialog box and - * thus would look strange. - * - * The active area defaults to the whole screen, so there is just - * need to use this function if you want to limit it. - * - * @param r rect of the screen, which should be writeable - * - * @see resetDrawArea - */ - virtual void setDrawArea(const Common::Rect &r) { _drawArea = r; } - - /** - * Resets the draw area to the whole screen. - * - * @see setDrawArea - */ - virtual void resetDrawArea() = 0; - - virtual const Common::ConfigFile &getConfigFile() const { return _configFile; } - virtual const Graphics::Font *getFont(FontStyle font = kFontStyleBold) const = 0; virtual int getFontHeight(FontStyle font = kFontStyleBold) const = 0; virtual int getStringWidth(const Common::String &str, FontStyle font = kFontStyleBold) const = 0; @@ -356,19 +325,11 @@ public: return kTextAlignCenter; } - void processResSection(Common::ConfigFile &config, const Common::String &name, bool skipDefs = false, const Common::String &prefix = ""); - void processSingleLine(const Common::String §ion, const Common::String &prefix, const Common::String &name, const Common::String &str); - void setSpecialAlias(const Common::String &alias, const Common::String &name); bool isThemeLoadingRequired(); - bool sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h); - void loadTheme(Common::ConfigFile &config, bool reset = true); - void loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing); - Eval *_evaluator; - - virtual void *evaluator() { return (void*)_evaluator; } + virtual ThemeEval *evaluator() = 0; - static bool themeConfigUseable(const Common::String &file, const Common::String &style="", Common::String *cStyle=0, Common::ConfigFile *cfg=0); + static bool themeConfigUseable(const Common::String &file); virtual const Common::String &getThemeFileName() const = 0; virtual const Common::String &getThemeName() const = 0; @@ -395,19 +356,10 @@ public: */ virtual const Graphics::Surface *getImageSurface(const kThemeImages n) const { return 0; } protected: - bool loadConfigFile(const Common::String &file); - void getColorFromConfig(const Common::String &name, OverlayColor &col); - void getColorFromConfig(const Common::String &value, uint8 &r, uint8 &g, uint8 &b); const Graphics::Font *loadFont(const char *filename); Common::String genCacheFilename(const char *filename); - Common::String _stylefile, _stylename; - - Common::Rect _drawArea; - Common::ConfigFile _configFile; - Common::ConfigFile _defaultConfig; - public: bool needThemeReload() { return ((_loadedThemeX != g_system->getOverlayWidth()) || (_loadedThemeY != g_system->getOverlayHeight())); } diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 3f23dde775..c240b0080c 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 2b52383534ecb5c3770dfb267d7238516f0ca144 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 13 Aug 2008 17:46:00 +0000 Subject: Finished legacy API cleanup. Removed all legacy code. Possible regressions. svn-id: r33833 --- engines/parallaction/saveload.cpp | 12 +- engines/scumm/dialogs.cpp | 20 +- gui/EditTextWidget.cpp | 4 +- gui/ListWidget.cpp | 7 +- gui/PopUpWidget.cpp | 6 +- gui/TabWidget.cpp | 5 +- gui/ThemeClassic.cpp | 710 ----------------- gui/ThemeClassic.h | 127 --- gui/ThemeModern.cpp | 1586 ------------------------------------- gui/ThemeModern.h | 340 -------- gui/ThemeRenderer.cpp | 26 +- gui/ThemeRenderer.h | 2 +- gui/console.cpp | 8 +- gui/dialog.cpp | 20 +- gui/dialog.h | 11 +- gui/eval.cpp | 333 -------- gui/eval.h | 130 --- gui/launcher.cpp | 4 +- gui/module.mk | 1 - gui/newgui.cpp | 3 - gui/options.cpp | 2 - gui/theme-config.cpp | 772 ------------------ gui/theme.cpp | 2 - gui/theme.h | 43 +- gui/themebrowser.cpp | 2 +- gui/themes/classic080.ini | 466 ----------- gui/themes/modern.ini | 622 --------------- gui/themes/modern.zip | Bin 42693 -> 0 bytes gui/themes/scummodern.zip | Bin 116164 -> 121066 bytes gui/widget.cpp | 26 +- gui/widget.h | 5 - 31 files changed, 65 insertions(+), 5230 deletions(-) delete mode 100644 gui/ThemeClassic.cpp delete mode 100644 gui/ThemeClassic.h delete mode 100644 gui/ThemeModern.cpp delete mode 100644 gui/ThemeModern.h delete mode 100644 gui/eval.cpp delete mode 100644 gui/eval.h delete mode 100644 gui/theme-config.cpp delete mode 100644 gui/themes/classic080.ini delete mode 100644 gui/themes/modern.ini delete mode 100644 gui/themes/modern.zip diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp index 002295315d..87a556182e 100644 --- a/engines/parallaction/saveload.cpp +++ b/engines/parallaction/saveload.cpp @@ -248,19 +248,19 @@ enum { SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine) - : Dialog("scummsaveload"), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) { + : Dialog("ScummSaveLoad"), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) { // _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; + _backgroundType = GUI::Theme::kDialogBackgroundSpecial; - new GUI::StaticTextWidget(this, "scummsaveload_title", title); + new GUI::StaticTextWidget(this, "ScummSaveLoad.Title", title); // Add choice list - _list = new GUI::ListWidget(this, "scummsaveload_list"); + _list = new GUI::ListWidget(this, "ScummSaveLoad.List"); _list->setEditable(true); _list->setNumberingMode(GUI::kListNumberingOne); _container = new GUI::ContainerWidget(this, 0, 0, 10, 10); - _container->setHints(GUI::THEME_HINT_USE_SHADOW); _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10); @@ -269,8 +269,8 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, _playtime = new GUI::StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", GUI::kTextAlignCenter); // Buttons - new GUI::ButtonWidget(this, "scummsaveload_cancel", "Cancel", GUI::kCloseCmd, 0); - _chooseButton = new GUI::ButtonWidget(this, "scummsaveload_choose", buttonLabel, kChooseCmd, 0); + new GUI::ButtonWidget(this, "ScummSaveLoad.Cancel", "Cancel", GUI::kCloseCmd, 0); + _chooseButton = new GUI::ButtonWidget(this, "ScummSaveLoad.Choose", buttonLabel, kChooseCmd, 0); _chooseButton->setEnabled(false); } diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 1dbbc28f92..6a4ab4bd3c 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -36,7 +36,7 @@ #endif #include "gui/about.h" -#include "gui/eval.h" +#include "gui/theme.h" #include "gui/newgui.h" #include "gui/ListWidget.h" #include "gui/ThemeEval.h" @@ -213,9 +213,8 @@ static const ResString string_map_table_v345[] = { #pragma mark - -ScummDialog::ScummDialog(String name) - : GUI::Dialog(name) { -_drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; +ScummDialog::ScummDialog(String name) : GUI::Dialog(name) { + _backgroundType = GUI::Theme::kDialogBackgroundSpecial; } #pragma mark - @@ -235,8 +234,8 @@ enum { SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine) : Dialog("ScummSaveLoad"), _saveMode(saveMode), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) { - - _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; + + _backgroundType = GUI::Theme::kDialogBackgroundSpecial; new StaticTextWidget(this, "ScummSaveLoad.Title", title); @@ -246,8 +245,6 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero); _container = new GUI::ContainerWidget(this, 0, 0, 10, 10); - _container->setHints(GUI::THEME_HINT_USE_SHADOW); - _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10); _date = new StaticTextWidget(this, 0, 0, 10, 10, "No date saved", kTextAlignCenter); @@ -667,8 +664,6 @@ HelpDialog::HelpDialog(const GameSettings &game) void HelpDialog::reflowLayout() { ScummDialog::reflowLayout(); - _drawingHints &= ~GUI::THEME_HINT_SPECIAL_COLOR; - int lineHeight = g_gui.getFontHeight(); int16 x, y; uint16 w, h; @@ -853,7 +848,7 @@ void ConfirmDialog::handleKeyDown(Common::KeyState state) { ValueDisplayDialog::ValueDisplayDialog(const Common::String& label, int minVal, int maxVal, int val, uint16 incKey, uint16 decKey) - : GUI::Dialog("scummDummyDialog", false), + : GUI::Dialog("scummDummyDialog"), _label(label), _min(minVal), _max(maxVal), _value(val), _incKey(incKey), _decKey(decKey) { assert(_min <= _value && _value <= _max); @@ -861,8 +856,7 @@ ValueDisplayDialog::ValueDisplayDialog(const Common::String& label, int minVal, void ValueDisplayDialog::drawDialog() { const int labelWidth = _w - 8 - _percentBarWidth; - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), - GUI::THEME_HINT_SAVE_BACKGROUND | GUI::THEME_HINT_FIRST_DRAW); + g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), GUI::Theme::kDialogBackgroundDefault); g_gui.theme()->drawText(Common::Rect(_x+4, _y+4, _x+labelWidth+4, _y+g_gui.theme()->getFontHeight()+4), _label); g_gui.theme()->drawSlider(Common::Rect(_x+4+labelWidth, _y+4, _x+_w-4, _y+_h-4), diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp index 244d296c80..889310d958 100644 --- a/gui/EditTextWidget.cpp +++ b/gui/EditTextWidget.cpp @@ -24,7 +24,6 @@ #include "gui/EditTextWidget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/ThemeEval.h" @@ -43,7 +42,6 @@ EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String : EditableWidget(boss, name) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; - _hints |= THEME_HINT_USE_SHADOW; setEditString(text); } @@ -84,7 +82,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) { void EditTextWidget::drawWidget() { - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _hints, Theme::kWidgetBackgroundEditText); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, Theme::kWidgetBackgroundEditText); // Draw the text adjustOffset(); diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 13633941c8..c17963ea95 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -27,7 +27,6 @@ #include "gui/ListWidget.h" #include "gui/ScrollBarWidget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/ThemeEval.h" @@ -47,7 +46,6 @@ ListWidget::ListWidget(GuiObject *boss, const String &name) _scrollBar->setTarget(this); setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); - setHints(THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); _type = kListWidget; _editMode = false; _numberingMode = kListNumberingOne; @@ -77,7 +75,6 @@ ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h) _scrollBar->setTarget(this); setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); - setHints(THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); _type = kListWidget; _editMode = false; _numberingMode = kListNumberingOne; @@ -363,7 +360,7 @@ void ListWidget::drawWidget() { Common::String buffer; // Draw a thin frame around the list. - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _hints, Theme::kWidgetBackgroundBorder); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, Theme::kWidgetBackgroundBorder); const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0; // Draw the list items @@ -378,7 +375,7 @@ void ListWidget::drawWidget() { inverted = true; else g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1), - _hints, Theme::kWidgetBackgroundBorderSmall); + 0, Theme::kWidgetBackgroundBorderSmall); } Common::Rect r(getEditRect()); diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 921647e038..6c89e7113c 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -25,7 +25,6 @@ #include "common/system.h" #include "common/events.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/PopUpWidget.h" #include "engines/engine.h" @@ -73,7 +72,7 @@ protected: }; PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) - : Dialog(0, 0, 16, 16, false), + : Dialog(0, 0, 16, 16), _popUpBoss(boss) { // Copy the selection index @@ -153,7 +152,7 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) void PopUpDialog::drawDialog() { // Draw the menu border - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0); /*if (_twoColumns) g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/ @@ -360,7 +359,6 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) { PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const String &label, uint labelWidth) : Widget(boss, name), CommandSender(boss), _label(label), _labelWidth(labelWidth) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS); - setHints(THEME_HINT_SAVE_BACKGROUND); _type = kPopUpWidget; _selectedItem = -1; diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp index 3933823943..402e9075c1 100644 --- a/gui/TabWidget.cpp +++ b/gui/TabWidget.cpp @@ -26,7 +26,6 @@ #include "gui/TabWidget.h" #include "gui/dialog.h" #include "gui/newgui.h" -#include "gui/eval.h" #include "gui/ThemeEval.h" @@ -69,9 +68,7 @@ void TabWidget::init() { int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", kCmdLeft, 0); - _navLeft->setHints(THEME_HINT_NO_BACKGROUND_RESTORE); _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", kCmdRight, 0); - _navRight->setHints(THEME_HINT_NO_BACKGROUND_RESTORE); } TabWidget::~TabWidget() { @@ -256,7 +253,7 @@ void TabWidget::drawWidget() { for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) { tabs.push_back(_tabs[i].title); } - g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, _hints, _titleVPad); + g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad); } void TabWidget::draw() { diff --git a/gui/ThemeClassic.cpp b/gui/ThemeClassic.cpp deleted file mode 100644 index eaf86d1cbb..0000000000 --- a/gui/ThemeClassic.cpp +++ /dev/null @@ -1,710 +0,0 @@ -/* 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$ - */ - -#include "gui/ThemeClassic.h" -#include "gui/eval.h" - -namespace GUI { -ThemeClassic::ThemeClassic(OSystem *system, const Common::String &config, const Common::ConfigFile *cfg) : Theme() { - _enableBlending = true; - _stylefile = config; - _system = system; - _initOk = false; - _enabled = false; - _font = 0; - _fontName.clear(); - memset(&_screen, 0, sizeof(_screen)); -#ifndef CT_NO_TRANSPARENCY - memset(&_dialog, 0, sizeof(_dialog)); -#endif - _font = 0; - - // 'classic' is always the built in one, we force it and - // ignore all 'classic' named config files - if (config.compareToIgnoreCase("classic (builtin)") != 0) { - if (cfg) - _configFile = *cfg; - else - loadConfigFile(_stylefile); - } - - if (_configFile.hasKey("name", "theme")) - _configFile.getKey("name", "theme", _stylename); - else - _stylename = _stylefile; -} - -ThemeClassic::~ThemeClassic() { - deinit(); -} - -bool ThemeClassic::init() { - deinit(); - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - resetDrawArea(); - } - - if (isThemeLoadingRequired()) { - loadTheme(_defaultConfig); - loadTheme(_configFile, false, true); - - setupConfig(); - } - - _bgcolor = _system->RGBToColor(_colors[kBGColor][0], _colors[kBGColor][1], _colors[kBGColor][2]); - _color = _system->RGBToColor(_colors[kColor][0], _colors[kColor][1], _colors[kColor][2]); - _shadowcolor = _system->RGBToColor(_colors[kShadowColor][0], _colors[kShadowColor][1], _colors[kShadowColor][2]); - _textcolor = _system->RGBToColor(_colors[kTextColor][0], _colors[kTextColor][1], _colors[kTextColor][2]); - _textcolorhi = _system->RGBToColor(_colors[kTextColorHi][0], _colors[kTextColorHi][1], _colors[kTextColorHi][2]); - if (_fontName.empty()) { - if (_screen.w >= 400 && _screen.h >= 300) { - _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } - } - - return true; -} - -void ThemeClassic::deinit() { - if (_initOk) { - _system->hideOverlay(); - _screen.free(); - _initOk = false; - } -} - -void ThemeClassic::refresh() { - init(); - if (_enabled) - _system->showOverlay(); -} - -void ThemeClassic::enable() { - init(); - resetDrawArea(); - _system->showOverlay(); - clearAll(); - _enabled = true; -} - -void ThemeClassic::disable() { - _system->hideOverlay(); - _enabled = false; -} - -void ThemeClassic::openDialog(bool topDialog, ShadingStyle shading) { -#ifndef CT_NO_TRANSPARENCY - if (!_dialog) { - _dialog = new DialogState; - assert(_dialog); - // first dialog - _dialog->screen.create(_screen.w, _screen.h, sizeof(OverlayColor)); - } - memcpy(_dialog->screen.pixels, _screen.pixels, _screen.pitch*_screen.h); - if (!_enableBlending) - _dialog->screen.fillRect(Common::Rect(0, 0, _screen.w, _screen.h), _bgcolor); - else - blendScreenToDialog(); -#endif -} - -void ThemeClassic::closeAllDialogs() { -#ifndef CT_NO_TRANSPARENCY - if (_dialog) { - _dialog->screen.free(); - delete _dialog; - _dialog = 0; - } - _forceRedraw = true; -#endif -} - -void ThemeClassic::clearAll() { - if (!_initOk) - return; - _system->clearOverlay(); - // FIXME: problem with the 'pitch' - _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); -} - -void ThemeClassic::updateScreen() { - _forceRedraw = false; -} - -void ThemeClassic::resetDrawArea() { - if (_initOk) { - _drawArea = Common::Rect(0, 0, _screen.w, _screen.h); - } -} - -int ThemeClassic::getTabSpacing() const { - return 2; -} -int ThemeClassic::getTabPadding() const { - return 3; -} - -void ThemeClassic::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - -#ifndef CT_NO_TRANSPARENCY - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - addDirtyRect(r); - return; - } -#endif - - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - addDirtyRect(r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeClassic::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!_initOk) - return; - - if (!inverted) { - restoreBackground(r); - _font->drawString(&_screen, str, r.left, r.top, r.width(), getColor(state), convertAligment(align), deltax, useEllipsis); - } else { - _screen.fillRect(r, getColor(state)); - _font->drawString(&_screen, str, r.left, r.top, r.width(), _bgcolor, convertAligment(align), deltax, useEllipsis); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - font->drawChar(&_screen, ch, r.left, r.top, getColor(state)); - addDirtyRect(r); -} - -void ThemeClassic::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { - if (!_initOk || background == kWidgetBackgroundNo) - return; - - restoreBackground(r); - -#ifndef CT_NO_TRANSPARENCY - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - addDirtyRect(r); - return; - } -#endif - - switch (background) { - case kWidgetBackgroundBorder: - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - break; - - //case kWidgetBackgroundPlain: - //case kWidgetBackgroundBorderSmall: - default: - box(r.left, r.top, r.width(), r.height()); - break; - }; - - addDirtyRect(r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeClassic::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!_initOk) - return; - restoreBackground(r); - - drawWidgetBackground(r, 0, kWidgetBackgroundBorder, state); - - const int off = (r.height() - _font->getFontHeight()) / 2; - _font->drawString(&_screen, str, r.left, r.top+off, r.width(), getColor(state), Graphics::kTextAlignCenter, 0, false); - - addDirtyRect(r); -} - -void ThemeClassic::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { - if (!_initOk) - return; - - Common::Rect rect(r.left, r.top, r.left + surface.w, r.top + surface.h); - rect.clip(_screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - assert(surface.bytesPerPixel == sizeof(OverlayColor)); - - OverlayColor *src = (OverlayColor *)surface.pixels; - OverlayColor *dst = (OverlayColor *)_screen.getBasePtr(rect.left, rect.top); - - int w = rect.width(); - int h = rect.height(); - - while (h--) { - memcpy(dst, src, surface.pitch); - src += w; - // FIXME: this should be pitch - dst += _screen.w; - } - addDirtyRect(r); -} - -void ThemeClassic::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { - if (!_initOk) - return; - Common::Rect r2 = r; - - restoreBackground(r); - - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - r2.left = r.left + 2; - r2.top = r.top + 2; - r2.bottom = r.bottom - 2; - r2.right = r2.left + width; - if (r2.right > r.right - 2) { - r2.right = r.right - 2; - } - - _screen.fillRect(r2, getColor(state)); - - addDirtyRect(r); -} - -void ThemeClassic::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { - if (!_initOk) - return; - - restoreBackground(r); - - box(r.left, r.top, r.width(), r.height()); - - Common::Point p0, p1; - - p0 = Common::Point(r.right + 1 - r.height() / 2, r.top + 4); - p1 = Common::Point(r.right + 1 - r.height() / 2, r.bottom - 4); - - OverlayColor color = getColor(state); - - // Evil HACK to draw filled triangles - // FIXME: The "big" version is pretty ugly. - for (; p1.y - p0.y > 1; p0.y++, p0.x--, p1.y--, p1.x++) { - _screen.drawLine(p0.x, p0.y, p1.x, p0.y, color); - _screen.drawLine(p0.x, p1.y, p1.x, p1.y, color); - } - - if (!sel.empty()) { - Common::Rect text(r.left + 2, r.top + 3, r.right - 4, r.top + 3 + _font->getFontHeight()); - _font->drawString(&_screen, sel, text.left, text.top, text.width(), color, convertAligment(align), deltax, false); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2 = r; - int checkBoxSize = getFontHeight(); - if (checkBoxSize > r.height()) { - checkBoxSize = r.height(); - } - r2.bottom = r2.top + checkBoxSize; - - restoreBackground(r2); - - box(r.left, r.top, checkBoxSize, checkBoxSize, _color, _shadowcolor); - - if (checked) { - r2.top += 3; - r2.bottom = r.top + checkBoxSize - 4; - r2.left += 3; - r2.right = r.left + checkBoxSize - 4; - - OverlayColor c = getColor(state); - - // Draw a cross - _screen.drawLine(r2.left, r2.top, r2.right, r2.bottom, c); - _screen.drawLine(r2.left, r2.bottom, r2.right, r2.top, c); - - if (r2.height() > 5) { - // Thicken the lines - _screen.drawLine(r2.left, r2.top + 1, r2.right - 1, r2.bottom, c); - _screen.drawLine(r2.left + 1, r2.top, r2.right, r2.bottom - 1, c); - _screen.drawLine(r2.left, r2.bottom - 1, r2.right - 1, r2.top, c); - _screen.drawLine(r2.left + 1, r2.bottom, r2.right, r2.top + 1, c); - } - - r2 = r; - } - - r2.left += checkBoxSize + 10; - _font->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, true); - - addDirtyRect(r); -} - -void ThemeClassic::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - - for (int i = 0; i < (int)tabs.size(); ++i) { - if (i == active) - continue; - box(r.left + i * tabWidth, r.top+2, tabWidth, tabHeight-2, _color, _shadowcolor); - _font->drawString(&_screen, tabs[i], r.left + i * tabWidth, r.top+4, tabWidth, getColor(state), Graphics::kTextAlignCenter, 0, true); - } - - if (active >= 0) { - box(r.left + active * tabWidth, r.top, tabWidth, tabHeight, _color, _shadowcolor, true); - _font->drawString(&_screen, tabs[active], r.left + active * tabWidth, r.top+titleVPad, tabWidth, getColor(kStateHighlight), Graphics::kTextAlignCenter, 0, true); - - _screen.hLine(r.left, r.top + tabHeight, r.left + active * tabWidth + 1, _color); - _screen.hLine(r.left + active * tabWidth + tabWidth - 2, r.top + tabHeight, r.right, _color); - _screen.hLine(r.left, r.bottom - 1, r.right - 1, _shadowcolor); - _screen.vLine(r.left, r.top + tabHeight, r.bottom - 1, _color); - _screen.vLine(r.right - 1, r.top + tabHeight, r.bottom - 1, _shadowcolor); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scroll, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - Common::Rect r2 = r; - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - - const int UP_DOWN_BOX_HEIGHT = r.width() + 1; - const int B = 3; - const int arrowSize = (r.width() / 2 - B + 1); - - OverlayColor color = 0; - if (scroll == kScrollbarStateSinglePage) { - color = _color; - } else if (scroll == kScrollbarStateUp && state == kStateHighlight) { - color = _textcolorhi; - } else { - color = _textcolor; - } - - // draws the 'up' button - box(r.left, r.top, r.width(), UP_DOWN_BOX_HEIGHT, _color, _shadowcolor); - Common::Point p0 = Common::Point(r.left + r.width() / 2, r.top + (UP_DOWN_BOX_HEIGHT - arrowSize - 1) / 2); - Common::Point p1 = Common::Point(p0.x - arrowSize, p0.y + arrowSize); - Common::Point p2 = Common::Point(p0.x + arrowSize, p0.y + arrowSize); - for (; p1.x <= p2.x; ++p1.x) - _screen.drawLine(p0.x, p0.y, p1.x, p1.y, color); - - if (scroll != kScrollbarStateSinglePage) { - r2.top += sliderY; - r2.left += 2; - r2.right -= 2; - r2.bottom = r2.top + sliderHeight; - _screen.fillRect(r2, (state == kStateHighlight && scroll == kScrollbarStateSlider) ? _textcolorhi : _textcolor); - box(r2.left, r2.top, r2.width(), r2.height()); - int y = r2.top + sliderHeight / 2; - color = (state == kStateHighlight && scroll == kScrollbarStateSlider) ? _color : _bgcolor; - _screen.hLine(r2.left + 1, y - 2, r2.right - 2, color); - _screen.hLine(r2.left + 1, y, r2.right - 2, color); - _screen.hLine(r2.left + 1, y + 2, r2.right - 2, color); - r2 = r; - } - - r2.top = r2.bottom - UP_DOWN_BOX_HEIGHT; - if (scroll == kScrollbarStateSinglePage) { - color = _color; - } else if (scroll == kScrollbarStateDown && state == kStateHighlight) { - color = _textcolorhi; - } else { - color = _textcolor; - } - - // draws the 'down' button - box(r2.left, r2.top, r2.width(), UP_DOWN_BOX_HEIGHT, _color, _shadowcolor); - p0 = Common::Point(r2.left + r2.width() / 2, r2.top + (UP_DOWN_BOX_HEIGHT + arrowSize + 1) / 2); - p1 = Common::Point(p0.x - arrowSize, p0.y - arrowSize); - p2 = Common::Point(p0.x + arrowSize, p0.y - arrowSize); - for (; p1.x <= p2.x; ++p1.x) - _screen.drawLine(p0.x, p0.y, p1.x, p1.y, color); - - addDirtyRect(r); -} - -void ThemeClassic::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { - if (!_initOk) - return; - - OverlayColor color = 0; - if (erase) { - color = _bgcolor; - } else { - color = getColor(state); - } - - _screen.vLine(r.left, r.top, r.bottom - 2, color); - addDirtyRect(r); -} - -void ThemeClassic::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!_initOk) - return; - _screen.hLine(r.left - 1, r.top + r.height() / 2, r.right, _shadowcolor); - _screen.hLine(r.left, r.top + 1 + r.height() / 2, r.right, _color); - addDirtyRect(r); -} - -// intern drawing - -void ThemeClassic::restoreBackground(Common::Rect r, bool special) { - r.clip(_screen.w, _screen.h); - r.clip(_drawArea); -#ifdef CT_NO_TRANSPARENCY - _screen.fillRect(r, _bgcolor); -#else - if (_dialog) { - if (!_dialog->screen.pixels) { - _screen.fillRect(r, _bgcolor); - return; - } - const OverlayColor *src = (const OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - - int h = r.height(); - int w = r.width(); - while (h--) { - memcpy(dst, src, w*sizeof(OverlayColor)); - src += _dialog->screen.w; - dst += _screen.w; - } - } else { - _screen.fillRect(r, _bgcolor); - } -#endif -} - -bool ThemeClassic::addDirtyRect(Common::Rect r, bool save, bool special) { - // TODO: implement proper dirty rect handling - // FIXME: problem with the 'pitch' - r.clip(_screen.w, _screen.h); - r.clip(_drawArea); - _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(r.left, r.top), _screen.w, r.left, r.top, r.width(), r.height()); -#ifndef CT_NO_TRANSPARENCY - if (_dialog && save) { - if (_dialog->screen.pixels) { - OverlayColor *dst = (OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left, r.top); - int h = r.height(); - while (h--) { - memcpy(dst, src, r.width()*sizeof(OverlayColor)); - dst += _dialog->screen.w; - src += _screen.w; - } - } - } -#endif - return true; -} - -void ThemeClassic::box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB, bool skipLastRow) { - if (y >= 0) { - _screen.hLine(x + 1, y, x + width - 2, colorA); - _screen.hLine(x, y + 1, x + width - 1, colorA); - } - int drawY = y; - if (drawY < 0) { - height += drawY; - drawY = 0; - } - _screen.vLine(x, drawY + 1, drawY + height - 2, colorA); - _screen.vLine(x + 1, drawY, drawY + height - 1, colorA); - _screen.vLine(x + width - 1, drawY + 1, drawY + height - 2, colorB); - _screen.vLine(x + width - 2, drawY + 1, drawY + height - 1, colorB); - - if (y + height >= 0 && !skipLastRow) { - _screen.hLine(x + 1, drawY + height - 2, x + width - 1, colorB); - _screen.hLine(x + 1, drawY + height - 1, x + width - 2, colorB); - } -} - -void ThemeClassic::box(int x, int y, int w, int h) { - _screen.hLine(x, y, x + w - 1, _color); - _screen.hLine(x, y + h - 1, x +w - 1, _shadowcolor); - _screen.vLine(x, y, y + h - 1, _color); - _screen.vLine(x + w - 1, y, y + h - 1, _shadowcolor); -} - -OverlayColor ThemeClassic::getColor(State state) { - OverlayColor usedColor = _color; - switch (state) { - case kStateEnabled: - usedColor = _textcolor; - break; - - case kStateHighlight: - usedColor = _textcolorhi; - break; - - default: - break; - } - return usedColor; -} - -#ifndef CT_NO_TRANSPARENCY -void ThemeClassic::blendScreenToDialog() { - Common::Rect rect(0, 0, _screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - if (_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) { - int a, r, g, b; - uint8 aa, ar, ag, ab; - _system->colorToARGB(_bgcolor, aa, ar, ag, ab); - a = aa*3/(3+1); - if (a < 1) - return; - r = ar * a; - g = ag * a; - b = ab * a; - - OverlayColor *ptr = (OverlayColor*)_dialog->screen.getBasePtr(rect.left, rect.top); - - int h = rect.height(); - int w = rect.width(); - while (h--) { - for (int i = 0; i < w; i++) { - _system->colorToARGB(ptr[i], aa, ar, ag, ab); - int a2 = aa + a - (a*aa)/255; - ptr[i] = _system->ARGBToColor(a2, - ((255-a)*aa*ar/255+r)/a2, - ((255-a)*aa*ag/255+g)/a2, - ((255-a)*aa*ab/255+b)/a2); - } - ptr += _screen.w; - } - } else { - int r, g, b; - uint8 ar, ag, ab; - _system->colorToRGB(_bgcolor, ar, ag, ab); - r = ar * 3; - g = ag * 3; - b = ab * 3; - - OverlayColor *ptr = (OverlayColor*)_dialog->screen.getBasePtr(rect.left, rect.top); - - int h = rect.height(); - int w = rect.width(); - - while (h--) { - for (int i = 0; i < w; i++) { - _system->colorToRGB(ptr[i], ar, ag, ab); - ptr[i] = _system->RGBToColor((ar + r) / (3+1), - (ag + g) / (3+1), - (ab + b) / (3+1)); - } - ptr += _screen.w; - } - } -} -#endif - -void ThemeClassic::setupConfig() { - if (_configFile.hasSection("theme")) { - if (loadConfig()) - return; - } - - static const uint8 colors[][3] = { - { 104, 104, 104 }, - { 64, 64, 64 }, - { 0, 0, 0, }, - { 32, 160, 32 }, - { 0, 255, 0 } - }; - - memcpy(_colors, colors, sizeof(colors)); -} - -bool ThemeClassic::loadConfig() { - Common::String temp; - _configFile.getKey("version", "theme", temp); - if (atoi(temp.c_str()) != THEME_VERSION) { - // TODO: improve this detection and handle it nicer - warning("Theme config uses a different version (you have: '%s', needed is: '%d')", temp.c_str(), THEME_VERSION); - _configFile.clear(); - - // force a theme reload here - loadTheme(_defaultConfig); - return false; - } - - temp.clear(); - _configFile.getKey("type", "theme", temp); - if (0 != temp.compareToIgnoreCase("classic")) { - warning("Theme config is not for the classic style theme"); - _configFile.clear(); - - // force a theme reload here - loadTheme(_defaultConfig); - return false; - } - - getColorFromConfig("color", _colors[kColor][0], _colors[kColor][1], _colors[kColor][2]); - getColorFromConfig("shadowcolor", _colors[kShadowColor][0], _colors[kShadowColor][1], _colors[kShadowColor][2]); - getColorFromConfig("bgcolor", _colors[kBGColor][0], _colors[kBGColor][1], _colors[kBGColor][2]); - getColorFromConfig("textcolor", _colors[kTextColor][0], _colors[kTextColor][1], _colors[kTextColor][2]); - getColorFromConfig("textcolorhi", _colors[kTextColorHi][0], _colors[kTextColorHi][1], _colors[kTextColorHi][2]); - - temp.clear(); - temp = _evaluator->getStringVar("font"); - if (temp.empty() || 0 == temp.compareToIgnoreCase("builtin")) { - if (!_fontName.empty()) - delete _font; - _fontName.clear(); - } else if (temp != _fontName) { - if (!_fontName.empty()) - delete _font; - _font = loadFont(temp.c_str()); - _fontName = temp; - } - - _enableBlending = (_evaluator->getVar("blending") != 0); - - return true; -} - -} // end of namespace GUI - diff --git a/gui/ThemeClassic.h b/gui/ThemeClassic.h deleted file mode 100644 index 28c522b906..0000000000 --- a/gui/ThemeClassic.h +++ /dev/null @@ -1,127 +0,0 @@ -/* 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 GUI_THEMECLASSIC_H -#define GUI_THEMECLASSIC_H - -#include "gui/theme.h" - -namespace GUI { - -// enable this to disable transparency support for the classic theme -//#define CT_NO_TRANSPARENCY - -class ThemeClassic : public Theme { -public: - ThemeClassic(OSystem *system, const Common::String &config = "classic", const Common::ConfigFile *cfg = 0); - virtual ~ThemeClassic(); - - bool init(); - void deinit(); - - void refresh(); - - void enable(); - void disable(); - - void openDialog(bool topDialog, ShadingStyle = kShadingNone); - void closeAllDialogs(); - - void clearAll(); - void updateScreen(); - - void resetDrawArea(); - - const Graphics::Font *getFont(FontStyle font) const { return _font; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } - - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state); - - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state); - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans); - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state); - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align); - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state); - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state); - void restoreBackground(Common::Rect r, bool special = false); - bool addDirtyRect(Common::Rect r, bool save = false, bool special = false); - - int getTabSpacing() const; - int getTabPadding() const; - -private: - void box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB, bool skipLastRow = false); - void box(int x, int y, int width, int height); - - OverlayColor getColor(State state); - - OSystem *_system; - Graphics::Surface _screen; - -#ifndef CT_NO_TRANSPARENCY - struct DialogState { - Graphics::Surface screen; - } *_dialog; - - void blendScreenToDialog(); -#endif - bool _enableBlending; - - bool _forceRedraw; - bool _initOk; - bool _enabled; - - Common::String _fontName; - const Graphics::Font *_font; - OverlayColor _color, _shadowcolor; - OverlayColor _bgcolor; - OverlayColor _textcolor; - OverlayColor _textcolorhi; - - enum { - kColor = 0, - kShadowColor = 1, - kBGColor = 2, - kTextColor = 3, - kTextColorHi = 4, - kMaxColors = 5 - }; - uint8 _colors[kMaxColors][3]; - - void setupConfig(); - bool loadConfig(); -}; - -} // end of namespace GUI - -#endif - diff --git a/gui/ThemeModern.cpp b/gui/ThemeModern.cpp deleted file mode 100644 index 45a454e00e..0000000000 --- a/gui/ThemeModern.cpp +++ /dev/null @@ -1,1586 +0,0 @@ -/* 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 DISABLE_FANCY_THEMES - -#include "gui/ThemeModern.h" -#include "gui/eval.h" - -#include "graphics/imageman.h" -#include "graphics/imagedec.h" -#include "graphics/colormasks.h" -#include "graphics/cursorman.h" - -#include "common/config-manager.h" -#include "common/file.h" - -#define kShadowTr0 8 -#define kShadowTr1 16 -#define kShadowTr2 32 -#define kShadowTr3 64 -#define kShadowTr35 96 -#define kShadowTr4 128 -#define kShadowTr5 192 - -using Graphics::Surface; - -/** Specifies the currently active 16bit pixel format, 555 or 565. */ -extern int gBitFormat; - -namespace GUI { - -// TODO: This should be moved to ThemeModern -OverlayColor getColorAlpha(OverlayColor col1, OverlayColor col2, int alpha); -OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos, int max, uint factor); -void getStateColor(OverlayColor &s, OverlayColor &e, OverlayColor enabledS, OverlayColor enabledE, OverlayColor highlightS, OverlayColor highlightE, Theme::WidgetStateInfo state); - -#pragma mark - - -ThemeModern::ThemeModern(OSystem *system, const Common::String &stylefile, const Common::ConfigFile *cfg) : Theme(), _system(system), _screen(), _initOk(false), -_forceRedraw(false), _lastUsedBitMask(0), _fonts(), _cursor(0), _imageHandles(), _images(0), _colors(), _gradientFactors() { - _stylefile = stylefile; - _initOk = false; - _enabled = false; - _useCursor = false; - memset(&_screen, 0, sizeof(_screen)); - memset(&_dialog, 0, sizeof(_dialog)); - memset(&_colors, 0, sizeof(_colors)); - memset(&_gradientFactors, 0, sizeof(_gradientFactors)); - - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - } - - if (cfg) { - _configFile = *cfg; - } else { - if (!loadConfigFile(stylefile)) { - warning("Can not find theme config file '%s'", (stylefile + ".ini").c_str()); - return; - } - } - - ImageMan.addArchive(stylefile + ".zip"); - - Common::String temp; - _configFile.getKey("version", "theme", temp); - if (atoi(temp.c_str()) != THEME_VERSION) { - // TODO: improve this detection and handle it nicer - warning("Theme config uses a different version (you have: '%s', needed is: '%d')", temp.c_str(), THEME_VERSION); - return; - } - - temp.clear(); - _configFile.getKey("type", "theme", temp); - if (0 != temp.compareToIgnoreCase("modern")) { - warning("Theme config is not for the modern style theme"); - return; - } - - if (_configFile.hasKey("name", "theme")) - _configFile.getKey("name", "theme", _stylename); - else - _stylename = _stylefile; - - _images = new const Graphics::Surface*[kImageHandlesMax]; - assert(_images); - - _lastUsedBitMask = gBitFormat; -} - -ThemeModern::~ThemeModern() { - deleteFonts(); - deinit(); - delete[] _images; - delete[] _cursor; - _images = 0; - for (int i = 0; i < kImageHandlesMax; ++i) { - ImageMan.unregisterSurface(_imageHandles[i]); - } - ImageMan.remArchive(_stylefile + ".zip"); -} - -bool ThemeModern::init() { - if (!_images) - return false; - - deinit(); - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - resetDrawArea(); - } - - if (isThemeLoadingRequired()) { - loadTheme(_defaultConfig); - loadTheme(_configFile, false, true); // Don't reset - - processExtraValues(); - } - - for (int i = 0; i < kImageHandlesMax; ++i) { - if (!_images[i]) { - return false; - } - } - - return true; -} - -void ThemeModern::deinit() { - if (_initOk) { - _system->hideOverlay(); - _screen.free(); - _initOk = false; - } -} - -void ThemeModern::refresh() { - init(); - resetupGuiRenderer(); - if (_enabled) { - _system->showOverlay(); - CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - } -} - -void ThemeModern::enable() { - init(); - resetupGuiRenderer(); - resetDrawArea(); - if (_useCursor) - setUpCursor(); - _system->showOverlay(); - clearAll(); - _enabled = true; -} - -void ThemeModern::disable() { - _system->hideOverlay(); - if (_useCursor) { - CursorMan.popCursorPalette(); - CursorMan.popCursor(); - } - _enabled = false; -} - -void ThemeModern::openDialog(bool topDialog, ShadingStyle shading) { - if (!_dialog) { - _dialog = new DialogState; - assert(_dialog); - // first dialog - _dialog->screen.create(_screen.w, _screen.h, sizeof(OverlayColor)); - } - - if (_dialogShadingCallback && topDialog) { - OverlayColor *col = (OverlayColor*)_screen.pixels; - for (int y = 0; y < _screen.h; ++y) { - for (int x = 0; x < _screen.w; ++x) { - col[x] = (this->*(_dialogShadingCallback))(col[x]); - } - col += _screen.w; - } - } - - memcpy(_dialog->screen.pixels, _screen.pixels, _screen.pitch*_screen.h); - - if ((_dialogShadingCallback) && topDialog) - addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h), false, false); -} - -void ThemeModern::closeAllDialogs() { - if (_dialog) { - _dialog->screen.free(); - delete _dialog; - _dialog = 0; - } - _forceRedraw = true; -} - -void ThemeModern::clearAll() { - if (!_initOk) - return; - _system->clearOverlay(); - // FIXME: problem with the 'pitch' - _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); -} - -void ThemeModern::updateScreen() { - // TODO: see ThemeModern::addDirtyRect - _forceRedraw = false; -} - -void ThemeModern::setDrawArea(const Common::Rect &r) { - if (_initOk) { - _drawArea = r; - _shadowDrawArea = Common::Rect(r.left-_shadowLeftWidth, r.top-_shadowTopHeight, r.right+_shadowRightWidth, r.bottom+_shadowBottomHeight); - _drawArea.clip(_screen.w, _screen.h); - _shadowDrawArea.clip(_screen.w, _screen.h); - } -} - -void ThemeModern::resetDrawArea() { - if (_initOk) { - _drawArea = Common::Rect(0, 0, _screen.w, _screen.h); - _shadowDrawArea = _drawArea; - } -} - -#define surface(x) (_images[x]) - -void ThemeModern::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowFull); - - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - restoreBackground(r2, true); - addDirtyRect(r2); - return; - } - - if (hints & THEME_HINT_MAIN_DIALOG) { - colorFade(r, _colors[kMainDialogStart], _colors[kMainDialogEnd], _gradientFactors[kMainDialogFactor]); - } else if (hints & THEME_HINT_SPECIAL_COLOR) { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kMainDialogStart], _colors[kMainDialogEnd], _gradientFactors[kDialogSpecialFactor]); - } else if (hints & THEME_HINT_PLAIN_COLOR) { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kDialogEnd], _colors[kDialogEnd], _gradientFactors[kDialogFactor]); - } else { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kDialogStart], _colors[kDialogEnd], _gradientFactors[kDialogFactor]); - } - - addDirtyRect(r2, (hints & THEME_HINT_SAVE_BACKGROUND) != 0, true); -} - -void ThemeModern::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!_initOk) - return; - - uint32 color; - - restoreBackground(r); - - if (inverted) { - _screen.fillRect(r, _colors[kTextInvertedBackground]); - color = _colors[kTextInvertedColor]; - } else { - color = getColor(state); - } - - getFont(font)->drawString(&_screen, str, r.left, r.top, r.width(), color, convertAligment(align), deltax, useEllipsis); - addDirtyRect(r); -} - -void ThemeModern::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - font->drawChar(&_screen, ch, r.left, r.top, getColor(state)); - addDirtyRect(r); -} - -void ThemeModern::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2; - - ImageHandles corner, top, left, bkgd; - ShadowStyles shadow; - ColorHandles start, end; - GradientFactors factor; - - switch (background) { - case kWidgetBackgroundBorderSmall: - corner = kWidgetSmallBkgdCorner; - top = kWidgetSmallBkgdTop; - left = kWidgetSmallBkgdLeft; - bkgd = kWidgetSmallBkgd; - shadow = kShadowSmall; - start = kWidgetBackgroundSmallStart; - end = kWidgetBackgroundSmallEnd; - factor = kWidgetSmallFactor; - break; - case kWidgetBackgroundEditText: - corner = kEditTextBkgdCorner; - top = kEditTextBkgdTop; - left = kEditTextBkgdLeft; - bkgd = kEditTextBkgd; - shadow = kShadowEmboss; - start = kEditTextBackgroundStart; - end = kEditTextBackgroundEnd; - factor = kEditTextFactor; - break; - case kWidgetBackgroundSlider: - corner = kSliderBkgdCorner; - top = kSliderBkgdTop; - left = kSliderBkgdLeft; - bkgd = kSliderBkgd; - shadow = kShadowEmboss; - start = kSliderBackgroundStart; - end = kSliderBackgroundEnd; - factor = kSliderBackground; - break; - default: - corner = kWidgetBkgdCorner; - top = kWidgetBkgdTop; - left = kWidgetBkgdLeft; - bkgd = kWidgetBkgd; - shadow = kShadowFull; - if (hints & THEME_HINT_PLAIN_COLOR) - start = kWidgetBackgroundEnd; - else - start = kWidgetBackgroundStart; - end = kWidgetBackgroundEnd; - factor = kWidgetFactor; - break; - } - - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - restoreBackground((hints & THEME_HINT_USE_SHADOW) ? r2 : r); - addDirtyRect((hints & THEME_HINT_USE_SHADOW) ? r2 : r); - return; - } - - if ((hints & THEME_HINT_USE_SHADOW)) { - r2 = shadowRect(r, shadow); - restoreBackground(r2); - // shadow - drawShadow(r, surface(corner), surface(top), surface(left), surface(bkgd), shadow); - } - - drawRectMasked(r, surface(corner), surface(top), surface(left), surface(bkgd), - (state == kStateDisabled) ? -30 : 256, _colors[start], _colors[end], - _gradientFactors[factor]); - - addDirtyRect((hints & THEME_HINT_USE_SHADOW) ? r2 : r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeModern::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowButton); - - if (!(hints & THEME_HINT_NO_BACKGROUND_RESTORE) || state == kStateDisabled) - restoreBackground(r2); - - // shadow - drawShadow(r, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), kShadowButton); - - OverlayColor start, end; - int alpha = 256; - - getStateColor(start, end, _colors[kButtonBackgroundStart], _colors[kButtonBackgroundEnd], - _colors[kButtonBackgroundHighlightStart], _colors[kButtonBackgroundHighlightEnd], state); - - if (state != kStateHighlight) - alpha = (state == kStateDisabled) ? -30 : 256; - - drawRectMasked(r, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), - alpha, start, end, _gradientFactors[kButtonFactor]); - - const int off = (r.height() - getFontHeight()) / 2; - - OverlayColor col = 0; - switch (state) { - case kStateEnabled: - col = _colors[kButtonTextEnabled]; - break; - - case kStateHighlight: - col = _colors[kButtonTextHighlight]; - break; - - default: - col = _colors[kButtonTextDisabled]; - break; - }; - - getFont()->drawString(&_screen, str, r.left, r.top + off, r.width(), col, Graphics::kTextAlignCenter, 0, true); - - addDirtyRect(r2); -} - -void ThemeModern::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { - if (!_initOk) - return; - - Common::Rect rect(r.left, r.top, r.left + surface.w, r.top + surface.h); - rect.clip(_screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - assert(surface.bytesPerPixel == sizeof(OverlayColor)); - - if (alpha != 256) - restoreBackground(rect); - - if (themeTrans) - drawSurface(rect, &surface, false, false, alpha); - else { - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(rect.left, rect.top); - const OverlayColor *src = (OverlayColor*)surface.pixels; - - int h = rect.height(); - if (alpha == 256) { - while (h--) { - memcpy(dst, src, surface.pitch); - dst += _screen.w; - src += surface.w; - } - } else { - int w = rect.width(); - while (h--) { - for (int i = 0; i < w; ++i) { - *dst = getColorAlpha(*src, *dst, alpha); - } - dst += _screen.w; - src += surface.w; - } - } - } - - addDirtyRect(rect); -} - -void ThemeModern::drawSlider(const Common::Rect &rr, int width, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r = rr; - - r.left++; - r.right++; - - drawWidgetBackground(r, THEME_HINT_USE_SHADOW, kWidgetBackgroundSlider, kStateEnabled); - - Common::Rect r2 = r; - r2.left = r.left; - r2.top = r.top; - r2.bottom = r.bottom-1; - r2.right = r2.left + width-1; - if (r2.right > r.right) { - r2.right = r.right; - } - - drawShadow(r2, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), kShadowButton); - - OverlayColor start, end; - int alpha = 256; - - getStateColor(start, end, _colors[kSliderStart], _colors[kSliderEnd], _colors[kSliderHighStart], _colors[kSliderHighEnd], state); - - if (state != kStateHighlight) - alpha = (state == kStateDisabled) ? -30 : 256; - - drawRectMasked(r2, surface(kSliderCorner), surface(kSliderTop), surface(kSliderLeft), surface(kSliderBkgd), - alpha, start, end, _gradientFactors[kSliderFactor]); - - addDirtyRect(r); -} - -void ThemeModern::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowSmall); - restoreBackground(r2); - - OverlayColor start = _colors[kPopUpWidgetStart], end = _colors[kPopUpWidgetEnd]; - if (state == kStateHighlight) { - start = _colors[kPopUpWidgetHighlightStart]; - end = _colors[kPopUpWidgetHighlightEnd]; - } - - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowPopUp); - - drawRectMasked(r, surface(kPopUpWidgetBkgdCorner), surface(kPopUpWidgetBkgdTop), surface(kPopUpWidgetBkgdLeft), surface(kPopUpWidgetBkgd), - (state == kStateDisabled) ? -30 : 256, start, end, _gradientFactors[kPopUpWidgetFactor]); - - const Graphics::Surface *arrow = surface(kWidgetArrow); - - int yOff = r.height() / 2 - arrow->h; - if (yOff < 0) - yOff = 0; - - Common::Rect arrowRect(r.right - 4 - arrow->w, r.top + yOff, r.right - 4, r.top + yOff + arrow->h); - arrowRect.clip(r); - - drawSurface(arrowRect, arrow, false, false, (state == kStateDisabled) ? -30 : 256); - - arrowRect.top += arrow->h; - arrowRect.bottom += arrow->h; - arrowRect.clip(r); - drawSurface(arrowRect, arrow, true, false, (state == kStateDisabled) ? -30 : 256); - - if (!sel.empty()) { - Common::Rect text(r.left + 2, r.top + 3, r.right - 4, r.top + 3 + getFont()->getFontHeight()); - getFont()->drawString(&_screen, sel, text.left, text.top, text.width(), getColor(state), convertAligment(align), deltax, false); - } - - addDirtyRect(r2); -} - -void ThemeModern::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!_initOk) - return; - Common::Rect r2 = r; - - const Graphics::Surface *checkBox = surface(checked ? kCheckboxChecked : kCheckboxEmpty); - int checkBoxSize = checkBox->w; - - restoreBackground(Common::Rect(r.left, r.top, r.left+checkBox->w, r.top+checkBox->h)); - - drawSurface(Common::Rect(r.left, r.top, r.left+checkBox->w, r.top+checkBox->h), checkBox, false, false, (state == kStateDisabled) ? 128 : 256); - - r2.left += checkBoxSize + 5; - getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); - - addDirtyRect(r); -} - -void ThemeModern::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - - // whole tab background - drawRectMasked(r, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - /*(state == kStateDisabled) ? -30 : */256, _colors[kTabBackgroundStart], _colors[kTabBackgroundEnd], - _gradientFactors[kTabFactor]); - - OverlayColor tabEnd = calcGradient(_colors[kTabActiveStart], _colors[kTabActiveEnd], tabHeight, r.height()-1, _gradientFactors[kTabFactor]); - - const int tabOffset = 1; - - // tab shadows - for (int i = 0; i < (int)tabs.size(); ++i) { - Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - drawShadow(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - kShadowSmall, true); - } - - // inactive tabs - for (int i = 0; i < (int)tabs.size(); ++i) { - if (i == active) - continue; - - Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight + 5); - drawRectMasked(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - 256, _colors[kTabInactiveStart], _colors[kTabInactiveEnd], _gradientFactors[kTabFactor], true); - - getFont()->drawString(&_screen, tabs[i], tabRect.left, tabRect.top+titleVPad, tabRect.width(), getColor(kStateEnabled), Graphics::kTextAlignCenter, 0, true); - } - - // area shadow - Common::Rect widgetBackground = Common::Rect(r.left, r.top + tabHeight - 1, r.right, r.top - + tabHeight + 20); - drawShadow(widgetBackground, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - kShadowSmall); - - // area itself - widgetBackground = Common::Rect(r.left, r.top + tabHeight, r.right, r.bottom); - drawRectMasked(widgetBackground, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - /*(state == kStateDisabled) ? -30 : */256, tabEnd, _colors[kTabActiveEnd], - _gradientFactors[kTabFactor]); - addDirtyRect(widgetBackground, true); - - // active tab - if (active >= 0) { - Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight + 5); - - Common::Rect shadowRect2(tabRect.left, r.top, tabRect.right, tabRect.bottom - 6); - drawShadow(shadowRect2, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), kShadowSmall, false, true); - - drawRectMasked(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - 256, _colors[kTabActiveStart], tabEnd, _gradientFactors[kTabFactor], true); - - - getFont()->drawString(&_screen, tabs[active], tabRect.left, tabRect.top+titleVPad, tabRect.width(), getColor(kStateEnabled), Graphics::kTextAlignCenter, 0, true); - } - - addDirtyRect(Common::Rect(r.left, r.top-2, r.right, r.bottom)); -} - -void ThemeModern::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { - if (!_initOk) - return; - const int UP_DOWN_BOX_HEIGHT = r.width() + 1; - Common::Rect r2 = r; - - // draws the scrollbar background - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - _colors[kScrollbarBackgroundStart], _colors[kScrollbarBackgroundEnd], _gradientFactors[kScrollbarBkgdFactor]); - - // draws the 'up' button - OverlayColor buttonStart = _colors[kScrollbarButtonStart]; - OverlayColor buttonEnd = _colors[kScrollbarButtonEnd]; - - if (scrollState == kScrollbarStateUp) - getStateColor(buttonStart, buttonEnd, buttonStart, buttonEnd, _colors[kScrollbarButtonHighlightStart], _colors[kScrollbarButtonHighlightEnd], state); - - r2.bottom = r2.top + UP_DOWN_BOX_HEIGHT; - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - buttonStart, buttonEnd, _gradientFactors[kScrollbarBkgdFactor]); - - const Graphics::Surface *arrow = surface(kWidgetArrow); - r2.left += 1 + (r2.width() - arrow->w) / 2; - r2.right = r2.left + arrow->w; - r2.top += (r2.height() - arrow->h) / 2; - r2.bottom = r2.top + arrow->h; - drawSurface(r2, arrow, false, false, 256); - - // draws the slider - OverlayColor sliderStart = _colors[kScrollbarSliderStart]; - OverlayColor sliderEnd = _colors[kScrollbarSliderEnd]; - - if (scrollState == kScrollbarStateSlider) - getStateColor(sliderStart, sliderEnd, sliderStart, sliderEnd, _colors[kScrollbarSliderHighlightStart], _colors[kScrollbarSliderHighlightEnd], state); - - r2 = r; - r2.left += 1; - r2.right -= 1; - r2.top += sliderY; - r2.bottom = r2.top + sliderHeight - 1; - - drawShadow(r2, surface(kSliderCorner), surface(kSliderTop), surface(kSliderLeft), surface(kSliderBkgd), kShadowSmall); - - r2.left += 1; - r2.right -= 1; - - r2.bottom = r2.top + sliderHeight / 2 + surface(kScrollbarCorner)->h + 4; - drawRectMasked(r2, surface(kScrollbarCorner), surface(kScrollbarTop), surface(kScrollbarLeft), surface(kScrollbarBkgd), 256, - sliderStart, sliderEnd, _gradientFactors[kScrollbarFactor]); - r2.top += sliderHeight / 2; - r2.bottom += sliderHeight / 2 - surface(kScrollbarCorner)->h - 4; - drawRectMasked(r2, surface(kScrollbarCorner), surface(kScrollbarTop), surface(kScrollbarLeft), surface(kScrollbarBkgd), 256, - sliderEnd, sliderStart, _gradientFactors[kScrollbarFactor]); - - // draws the 'down' button - buttonStart = _colors[kScrollbarButtonStart]; - buttonEnd = _colors[kScrollbarButtonEnd]; - - if (scrollState == kScrollbarStateDown) - getStateColor(buttonStart, buttonEnd, buttonStart, buttonEnd, _colors[kScrollbarButtonHighlightStart], _colors[kScrollbarButtonHighlightEnd], state); - - r2 = r; - r2.top = r2.bottom - UP_DOWN_BOX_HEIGHT; - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - buttonStart, buttonEnd, _gradientFactors[kScrollbarBkgdFactor]); - - r2.left += 1 + (r2.width() - arrow->w) / 2; - r2.right = r2.left + arrow->w; - r2.top += (r2.height() - arrow->h) / 2; - r2.bottom = r2.top + arrow->h; - drawSurface(r2, arrow, true, false, 256); - - addDirtyRect(r); -} - -void ThemeModern::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - if (!erase) { - _screen.vLine(r.left, r.top, r.bottom-1, _colors[kCaretColor]); - } else if (r.top >= 0) { - // FIXME: hack to restore the caret background correctly - const OverlayColor search = _colors[kTextInvertedBackground]; - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left-1, r.top-1); - int height = r.height() + 2; - if (r.top + height > _screen.h) { - height = _screen.h - r.top; - } - bool drawInvBackground = false; - while (height--) { - if (src[0] == search || src[1] == search || src[2] == search) { - drawInvBackground = true; - } - src += _screen.w; - } - if (drawInvBackground) { - _screen.vLine(r.left, r.top, r.bottom-1, search); - } - } - addDirtyRect(r); -} - -void ThemeModern::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!_initOk) - return; - _screen.hLine(r.left - 1, r.top + r.height() / 2, r.right, _system->RGBToColor(0, 0, 0)); - addDirtyRect(r); -} - -int ThemeModern::getTabSpacing() const { - return 0; -} -int ThemeModern::getTabPadding() const { - return 3; -} - -#pragma mark - intern drawing - -void ThemeModern::restoreBackground(Common::Rect r, bool special) { - r.clip(_screen.w, _screen.h); - if (special) { - r.clip(_shadowDrawArea); - } else { - r.clip(_drawArea); - } - if (_dialog) { - if (!_dialog->screen.pixels) { - return; - } - const OverlayColor *src = (const OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - - int h = r.height(); - int w = r.width(); - while (h--) { - memcpy(dst, src, w*sizeof(OverlayColor)); - src += _dialog->screen.w; - dst += _screen.w; - } - } -} - -bool ThemeModern::addDirtyRect(Common::Rect r, bool backup, bool special) { - // TODO: implement proper dirty rect handling - // FIXME: problem with the 'pitch' - r.clip(_screen.w, _screen.h); - if (special) { - r.clip(_shadowDrawArea); - } else { - r.clip(_drawArea); - } - _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(r.left, r.top), _screen.w, r.left, r.top, r.width(), r.height()); - if (_dialog && backup) { - if (_dialog->screen.pixels) { - OverlayColor *dst = (OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left, r.top); - int h = r.height(); - while (h--) { - memcpy(dst, src, r.width()*sizeof(OverlayColor)); - dst += _dialog->screen.w; - src += _screen.w; - } - } - } - return true; -} - -void ThemeModern::colorFade(const Common::Rect &r, OverlayColor start, OverlayColor end, uint factor) { - OverlayColor *ptr = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - const int h = r.height(); - const int w = r.width(); - const int lastRow = r.height() - 1; - const int ptrAdd = _screen.w - r.width(); - for (int l = 0; l < h; ++l) { - OverlayColor col = calcGradient(start, end, l, lastRow, factor); - for (int i = 0; i < w; ++i) { - *ptr++ = col; - } - ptr += ptrAdd; - } -} - -void ThemeModern::drawRect(const Common::Rect &r, const Surface *corner, const Surface *top, const Surface *left, const Surface *fill, int alpha, bool skipLastRow) { - drawRectMasked(r, corner, top, left, fill, alpha, _system->RGBToColor(255, 255, 255), _system->RGBToColor(255, 255, 255), 1, skipLastRow); -} - -void ThemeModern::drawRectMasked(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, - OverlayColor start, OverlayColor end, uint factor, bool skipLastRow, bool skipTopRow) { - int drawWidth = MIN(corner->w, MIN(top->w, MIN(left->w, fill->w))); - int drawHeight = MIN(corner->h, MIN(top->h, MIN(left->h, fill->h))); - int partsH = r.height() / drawHeight; - int partsW = r.width() / drawWidth; - int yPos = r.top; - - int specialHeight = 0; - int specialWidth = 0; - - if (drawHeight*2 > r.height()) { - drawHeight = r.height() / 2; - partsH = 2; - } else { - specialHeight = r.height() % drawHeight; - if (specialHeight != 0) - ++partsH; - } - - if (drawWidth*2 > r.width()) { - drawWidth = r.width() / 2; - partsW = 2; - } else { - specialWidth = r.width() % drawWidth; - if (specialWidth != 0) - ++partsW; - } - - for (int y = 0; y < partsH; ++y) { - int xPos = r.left; - bool upDown = (y == partsH - 1); - - // calculate the correct drawing height - int usedHeight = drawHeight; - if (specialHeight && y == 1) { - usedHeight = specialHeight; - } - - OverlayColor startCol = calcGradient(start, end, yPos-r.top, r.height()-1, factor); - OverlayColor endCol = calcGradient(start, end, yPos-r.top+usedHeight, r.height()-1, factor); - - for (int i = 0; i < partsW; ++i) { - // calculate the correct drawing width - int usedWidth = drawWidth; - if (specialWidth && i == 1) { - usedWidth = specialWidth; - } - - // draw the right surface - if (!i || i == partsW - 1) { - if ((!y && !skipTopRow) || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), corner, upDown, (i == partsW - 1), alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), left, upDown, (i == partsW - 1), alpha, startCol, endCol); - } - } else if (!y || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), top, upDown, false, alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), fill, false, false, alpha, startCol, endCol); - } - xPos += usedWidth; - } - - yPos += usedHeight; - } -} - -Common::Rect ThemeModern::shadowRect(const Common::Rect &r, uint32 shadowStyle) { - switch (shadowStyle) { - case kShadowButton: - return Common::Rect(r.left - 1, r.top - 1, r.right + 1, r.bottom + 1); - - case kShadowEmboss: - return Common::Rect(r.left - 1, r.top - 1, r.right + 1, r.bottom + 1); - - case kShadowPopUp: - return Common::Rect(r.left - 1, r.top - 1, r.right + 3, r.bottom + 3); - - case kShadowFull: - return Common::Rect(r.left - 2, r.top - 2, r.right + 4, r.bottom + 4); - - default: - return Common::Rect(r.left - _shadowLeftWidth/2, r.top - _shadowTopHeight/2, r.right + _shadowRightWidth/2 + 1, r.bottom + _shadowBottomHeight/2 + 1); - } - - return Common::Rect(); -} - -void ThemeModern::drawShadow(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, uint32 shadowStyle, bool skipLastRow, bool skipTopRow) { - switch (shadowStyle) { - case kShadowFull: { - Common::Rect r2(r.left-1, r.top-1, r.right + 4, r.bottom + 4); - Common::Rect r3(r.left, r.top+1, r.right + 3, r.bottom + 3); - Common::Rect r4(r.left, r.top+1, r.right + 2, r.bottom + 2); - Common::Rect r5(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr0, skipLastRow, skipTopRow); - drawShadowRect(r3, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - drawShadowRect(r5, r, corner, top, left, fill, kShadowTr3, skipLastRow, skipTopRow); - //drawShadowRect(r5, r, corner, top, left, fill, kShadowTr35, skipLastRow); - } break; - - case kShadowSmall: { - Common::Rect r3(r.left - _shadowLeftWidth/2, r.top - _shadowTopHeight/2, r.right + _shadowRightWidth/2, r.bottom + _shadowBottomHeight/2); - Common::Rect r4(r.left - _shadowLeftWidth/2 + 1, r.top - _shadowTopHeight/2 + 1, r.right + _shadowRightWidth/2-1, r.bottom + _shadowBottomHeight/2-1); - - drawShadowRect(r3, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - } break; - - case kShadowButton: { - Common::Rect r2(r.left-1, r.top - 1, r.right, r.bottom); - Common::Rect r4(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, -kShadowTr35-256, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr4, skipLastRow, skipTopRow); - } break; - - case kShadowEmboss: { - Common::Rect r2(r.left - 1, r.top - 1, r.right, r.bottom); - Common::Rect r4(r.left + 1, r.top + 1, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr5, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - } break; - - case kShadowPopUp: { - Common::Rect r2(r.left, r.top, r.right + 3, r.bottom + 3); - Common::Rect r25(r.left-1, r.top-1, r.right + 2, r.bottom + 2); - Common::Rect r3(r.left - 1, r.top-1, r.right, r.bottom); - Common::Rect r4(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r25, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr3, skipLastRow, skipTopRow); - drawShadowRect(r3, r, corner, top, left, fill, -kShadowTr35-256, skipLastRow, skipTopRow); - } break; - - default: - break; - } -} - -void ThemeModern::drawShadowRect(const Common::Rect &r, const Common::Rect &area, const Graphics::Surface *corner, - const Graphics::Surface *top, const Graphics::Surface *left, const Graphics::Surface *fill, - int alpha, bool skipLastRow, bool skipTopRow) { - int drawWidth = MIN(corner->w, MIN(top->w, MIN(left->w, fill->w))); - int drawHeight = MIN(corner->h, MIN(top->h, MIN(left->h, fill->h))); - int partsH = r.height() / drawHeight; - int partsW = r.width() / drawWidth; - int yPos = r.top; - - int yDrawTilesTop = 1 + (ABS(area.top - r.top) % drawHeight); - int xDrawTilesLeft = 1 + (ABS(area.left - r.left) % drawWidth); - int yDrawTilesBottom = 1 + (ABS(area.bottom - r.bottom) % drawHeight); - int xDrawTilesRight = 1 + (ABS(area.right - r.right) % drawWidth); - - int specialHeight = 0; - int specialWidth = 0; - - if (drawHeight*2 > r.height()) { - drawHeight = r.height() / 2; - partsH = 2; - } else { - specialHeight = r.height() % drawHeight; - if (specialHeight != 0) - ++partsH; - } - - if (drawWidth*2 > r.width()) { - drawWidth = r.width() / 2; - partsW = 2; - } else { - specialWidth = r.width() % drawWidth; - if (specialWidth != 0) - ++partsW; - } - - OverlayColor startCol = g_system->RGBToColor(0, 0, 0); - OverlayColor endCol = g_system->RGBToColor(0, 0, 0); - - for (int y = 0; y < partsH; ++y) { - // calculate the correct drawing height - int usedHeight = drawHeight; - if (specialHeight && y == 1) { - usedHeight = specialHeight; - } - - int xPos = r.left; - bool upDown = (y == partsH - 1); - - for (int i = 0; i < partsW; ++i) { - // calculate the correct drawing width - int usedWidth = drawWidth; - if (specialWidth && i == 1) { - usedWidth = specialWidth; - } - - if (i >= xDrawTilesLeft && i <= partsW - xDrawTilesRight && y >= yDrawTilesTop && y <= partsH - yDrawTilesBottom) { - xPos += usedWidth; - continue; - } - - // draw the right surface - if (!i || i == partsW - 1) { - if ((!y && !skipTopRow) || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), corner, upDown, (i == partsW - 1), alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), left, upDown, (i == partsW - 1), alpha, startCol, endCol); - } - } else if (!y || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), top, upDown, false, alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), fill, upDown, false, alpha, startCol, endCol); - } - xPos += usedWidth; - } - yPos += usedHeight; - } -} - -void ThemeModern::drawSurface(const Common::Rect &r, const Surface *surf, bool upDown, bool leftRight, int alpha) { - drawSurfaceMasked(r, surf, upDown, leftRight, alpha, _system->RGBToColor(255, 255, 255), _system->RGBToColor(255, 255, 255)); -} - -void ThemeModern::drawSurfaceMasked(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, - int alpha, OverlayColor start, OverlayColor end, uint factor) { - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - const OverlayColor *src = 0; - - const OverlayColor transparency = _colors[kColorTransparency]; - int drawWidth = (r.width() < surf->w) ? r.width() : surf->w; - if (r.left + drawWidth > _screen.w) - drawWidth = _screen.w - r.left; - - int srcAdd = 0; - if (upDown) { - src = (const OverlayColor*)surf->pixels + (surf->h - 1) * surf->w; - srcAdd = -surf->w; - } else { - src = (const OverlayColor*)surf->pixels; - srcAdd = surf->w; - } - - int h = r.height(); - if (r.top + h > _screen.h) - h = _screen.h - r.top; - - while (dst < _screen.pixels) { - dst += _screen.w; - src += srcAdd; - --h; - } - - if (h <= 0) - return; - -#define NO_EFFECT(x) ((x) & rowColor) -#define ALPHA_EFFECT(x) (getColorAlpha((x) & rowColor, *dst, alpha)) -#define DARKEN_EFFECT(x) (calcDimColor((x) & rowColor)) - -#define LEFT_RIGHT_OFFSET(x) (drawWidth-x-1) -#define NORMAL_OFFSET(x) (x) - -#define blitSurface(a, b) \ - const int dstAdd = _screen.w - drawWidth; \ - const int lastRow = r.height() - 1; \ - for (int i = 0; i < h; ++i) { \ - OverlayColor rowColor = calcGradient(start, end, i, lastRow, factor); \ - for (int x = 0; x < drawWidth; ++x, ++dst) { \ - OverlayColor col = src[a(x)]; \ - if (col != transparency) { \ - col = b(col); \ - *dst = col; \ - } \ - } \ - dst += dstAdd; \ - src += srcAdd; \ - } - if (alpha >= 256) { - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, NO_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, NO_EFFECT); - } - } else if (alpha < 0 && alpha >= -256) { - int backUp = _dimPercentValue; - _dimPercentValue = 256 * (100 - (-alpha)) / 100; - - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, DARKEN_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, DARKEN_EFFECT); - } - - _dimPercentValue = backUp; - } else { - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, ALPHA_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, ALPHA_EFFECT); - } - } -#undef blitSurface - -#undef NORMAL_OFFSET -#undef LEFT_RIGHT_OFFSET - -#undef DARKEN_EFFECT -#undef ALPHA_EFFECT -#undef NO_EFFECT -} - -OverlayColor ThemeModern::getColor(State state) { - switch (state) { - case kStateDisabled: - return _colors[kColorStateDisabled]; - - case kStateHighlight: - return _colors[kColorStateHighlight]; - - default: - break; - }; - return _colors[kColorStateEnabled]; -} - -void ThemeModern::resetupGuiRenderer() { - if (_lastUsedBitMask == gBitFormat || !_initOk) { - // ok same format no need to reload - return; - } - - _lastUsedBitMask = gBitFormat; - - int i; - for (i = 0; i < kImageHandlesMax; ++i) { - ImageMan.unregisterSurface(_imageHandles[i]); - } - - for (i = 0; i < kImageHandlesMax; ++i) { - ImageMan.registerSurface(_imageHandles[i], 0); - _images[i] = ImageMan.getSurface(_imageHandles[i]); - } - - setupColors(); -} - -void ThemeModern::setupColors() { - // load the colors from the config file - getColorFromConfig("main_dialog_start", _colors[kMainDialogStart]); - getColorFromConfig("main_dialog_end", _colors[kMainDialogEnd]); - - getColorFromConfig("dialog_start", _colors[kDialogStart]); - getColorFromConfig("dialog_end", _colors[kDialogEnd]); - - getColorFromConfig("color_state_disabled", _colors[kColorStateDisabled]); - getColorFromConfig("color_state_highlight", _colors[kColorStateHighlight]); - getColorFromConfig("color_state_enabled", _colors[kColorStateEnabled]); - getColorFromConfig("color_transparency", _colors[kColorTransparency]); - - getColorFromConfig("text_inverted_background", _colors[kTextInvertedBackground]); - getColorFromConfig("text_inverted_color", _colors[kTextInvertedColor]); - - getColorFromConfig("widget_bkgd_start", _colors[kWidgetBackgroundStart]); - getColorFromConfig("widget_bkgd_end", _colors[kWidgetBackgroundEnd]); - getColorFromConfig("widget_bkgd_small_start", _colors[kWidgetBackgroundSmallStart]); - getColorFromConfig("widget_bkgd_small_end", _colors[kWidgetBackgroundSmallEnd]); - - getColorFromConfig("button_bkgd_start", _colors[kButtonBackgroundStart]); - getColorFromConfig("button_bkgd_end", _colors[kButtonBackgroundEnd]); - getColorFromConfig("button_bkgd_highlight_start", _colors[kButtonBackgroundHighlightStart]); - getColorFromConfig("button_bkgd_highlight_end", _colors[kButtonBackgroundHighlightEnd]); - getColorFromConfig("button_text_enabled", _colors[kButtonTextEnabled]); - getColorFromConfig("button_text_disabled", _colors[kButtonTextDisabled]); - getColorFromConfig("button_text_highlight", _colors[kButtonTextHighlight]); - - getColorFromConfig("slider_background_start", _colors[kSliderBackgroundStart]); - getColorFromConfig("slider_background_end", _colors[kSliderBackgroundEnd]); - getColorFromConfig("slider_start", _colors[kSliderStart]); - getColorFromConfig("slider_end", _colors[kSliderEnd]); - getColorFromConfig("slider_highlight_start", _colors[kSliderHighStart]); - getColorFromConfig("slider_highlight_end", _colors[kSliderHighEnd]); - - getColorFromConfig("tab_background_start", _colors[kTabBackgroundStart]); - getColorFromConfig("tab_background_end", _colors[kTabBackgroundEnd]); - - getColorFromConfig("tab_active_start", _colors[kTabActiveStart]); - getColorFromConfig("tab_active_end", _colors[kTabActiveEnd]); - getColorFromConfig("tab_inactive_start", _colors[kTabInactiveStart]); - getColorFromConfig("tab_inactive_end", _colors[kTabInactiveEnd]); - - getColorFromConfig("scrollbar_background_start", _colors[kScrollbarBackgroundStart]); - getColorFromConfig("scrollbar_background_end", _colors[kScrollbarBackgroundEnd]); - getColorFromConfig("scrollbar_button_start", _colors[kScrollbarButtonStart]); - getColorFromConfig("scrollbar_button_end", _colors[kScrollbarButtonEnd]); - getColorFromConfig("scrollbar_slider_start", _colors[kScrollbarSliderStart]); - getColorFromConfig("scrollbar_slider_end", _colors[kScrollbarSliderEnd]); - getColorFromConfig("scrollbar_button_highlight_start", _colors[kScrollbarButtonHighlightStart]); - getColorFromConfig("scrollbar_button_highlight_end", _colors[kScrollbarButtonHighlightEnd]); - getColorFromConfig("scrollbar_slider_highlight_start", _colors[kScrollbarSliderHighlightStart]); - getColorFromConfig("scrollbar_slider_highlight_end", _colors[kScrollbarSliderHighlightEnd]); - - getColorFromConfig("caret_color", _colors[kCaretColor]); - - getColorFromConfig("popupwidget_start", _colors[kPopUpWidgetStart]); - getColorFromConfig("popupwidget_end", _colors[kPopUpWidgetEnd]); - getColorFromConfig("popupwidget_highlight_start", _colors[kPopUpWidgetHighlightStart]); - getColorFromConfig("popupwidget_highlight_end", _colors[kPopUpWidgetHighlightEnd]); - - getColorFromConfig("edittext_background_start", _colors[kEditTextBackgroundStart]); - getColorFromConfig("edittext_background_end", _colors[kEditTextBackgroundEnd]); -} - -#define FONT_NAME_NORMAL "newgui_normal" -#define FONT_NAME_BOLD "newgui_bold" -#define FONT_NAME_ITALIC "newgui_italic" -#define FONT_NAME_FIXED_NORMAL "newgui_fixed_normal" -#define FONT_NAME_FIXED_BOLD "newgui_fixed_bold" -#define FONT_NAME_FIXED_ITALIC "newgui_fixed_italic" - -void ThemeModern::setupFonts() { - if (_screen.w >= 400 && _screen.h >= 270) { - setupFont("fontfile_bold", FONT_NAME_BOLD, kFontStyleBold); - setupFont("fontfile_normal", FONT_NAME_NORMAL, kFontStyleNormal); - setupFont("fontfile_italic", FONT_NAME_ITALIC, kFontStyleItalic); - - setupFont("fontfile_fixed_bold", FONT_NAME_FIXED_BOLD, kFontStyleFixedBold); - setupFont("fontfile_fixed_normal", FONT_NAME_FIXED_NORMAL, kFontStyleFixedNormal); - setupFont("fontfile_fixed_italic", FONT_NAME_FIXED_ITALIC, kFontStyleFixedItalic); - } else { - _fonts[kFontStyleBold] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - _fonts[kFontStyleNormal] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - _fonts[kFontStyleItalic] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } -} - -void ThemeModern::deleteFonts() { - const Graphics::Font *normal = FontMan.getFontByName(FONT_NAME_NORMAL); - const Graphics::Font *bold = FontMan.getFontByName(FONT_NAME_BOLD); - const Graphics::Font *italic = FontMan.getFontByName(FONT_NAME_ITALIC); - - delete normal; - delete bold; - delete italic; - - FontMan.removeFontName(FONT_NAME_NORMAL); - FontMan.removeFontName(FONT_NAME_BOLD); - FontMan.removeFontName(FONT_NAME_ITALIC); -} - -void ThemeModern::setupFont(const Common::String &key, const Common::String &name, FontStyle style) { - if (_evaluator->getVar(key) == EVAL_STRING_VAR) { - _fonts[style] = FontMan.getFontByName(name); - - if (!_fonts[style]) { - Common::String temp(_evaluator->getStringVar(key)); - - _fonts[style] = loadFont(temp.c_str()); - if (!_fonts[style]) - error("Couldn't load %s font '%s'", key.c_str(), temp.c_str()); - - FontMan.assignFontToName(name, _fonts[style]); - } - } else { - _fonts[style] = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } -} - -#pragma mark - - -void ThemeModern::processExtraValues() { - // TODO: think of unloading all old graphic files first, instead of just - // loading new ones if needed when this is processed? - - // load the pixmap filenames from the config file -#define loadRectData(type, str) \ - _imageHandles[k##type##Corner] = _evaluator->getStringVar("pix_"str"_corner"); \ - _imageHandles[k##type##Top] = _evaluator->getStringVar("pix_"str"_top"); \ - _imageHandles[k##type##Left] = _evaluator->getStringVar("pix_"str"_left"); \ - _imageHandles[k##type] = _evaluator->getStringVar("pix_"str"_bkgd") - - loadRectData(DialogBkgd, "dialog"); - loadRectData(WidgetBkgd, "widget"); - loadRectData(WidgetSmallBkgd, "widget_small"); - loadRectData(TabBkgd, "tab"); - loadRectData(SliderBkgd, "slider_bkgd"); - loadRectData(Slider, "slider"); - loadRectData(ScrollbarBkgd, "scrollbar_bkgd"); - loadRectData(Scrollbar, "scrollbar"); - loadRectData(ButtonBkgd, "button"); - loadRectData(PopUpWidgetBkgd, "popupwidget"); - loadRectData(EditTextBkgd, "edittext_bkgd"); - -#undef loadRectData - - _imageHandles[kCheckboxEmpty] = _evaluator->getStringVar("pix_checkbox_empty"); - _imageHandles[kCheckboxChecked] = _evaluator->getStringVar("pix_checkbox_checked"); - - _imageHandles[kWidgetArrow] = _evaluator->getStringVar("pix_widget_arrow"); - - _imageHandles[kThemeLogo] = _evaluator->getStringVar("pix_theme_logo"); - - _imageHandles[kGUICursor] = _evaluator->getStringVar("pix_cursor_image"); - - for (int i = 0; i < kImageHandlesMax; ++i) { - ImageMan.registerSurface(_imageHandles[i], 0); - _images[i] = ImageMan.getSurface(_imageHandles[i]); - } - - // load the gradient factors from the config file - _gradientFactors[kMainDialogFactor] = _evaluator->getVar("gradient_dialog_main", 1); - _gradientFactors[kDialogFactor] = _evaluator->getVar("gradient_dialog", 1); - _gradientFactors[kDialogSpecialFactor] = _evaluator->getVar("gradient_dialog_special", 1); - - _gradientFactors[kWidgetSmallFactor] = _evaluator->getVar("gradient_widget_small", 1); - _gradientFactors[kWidgetFactor] = _evaluator->getVar("gradient_widget", 1); - - _gradientFactors[kButtonFactor] = _evaluator->getVar("gradient_button", 1); - - _gradientFactors[kSliderFactor] = _evaluator->getVar("gradient_slider", 1); - _gradientFactors[kSliderBackground] = _evaluator->getVar("gradient_silder_bkgd", 1); - - _gradientFactors[kTabFactor] = _evaluator->getVar("gradient_tab", 1); - - _gradientFactors[kScrollbarFactor] = _evaluator->getVar("gradient_scrollbar", 1); - _gradientFactors[kScrollbarBkgdFactor] = _evaluator->getVar("gradient_scrollbar_background", 1); - - _gradientFactors[kPopUpWidgetFactor] = _evaluator->getVar("gradient_popupwidget", 1); - - _gradientFactors[kEditTextFactor] = _evaluator->getVar("gradient_edittext", 1); - - // load values with default values from the config file - _shadowLeftWidth = _evaluator->getVar("shadow_left_width", 2); - _shadowRightWidth = _evaluator->getVar("shadow_right_width", 4); - _shadowTopHeight = _evaluator->getVar("shadow_top_height", 2); - _shadowBottomHeight = _evaluator->getVar("shadow_bottom_height", 4); - - _cursorHotspotX = _evaluator->getVar("cursor_hotspot_x", 0); - _cursorHotspotY = _evaluator->getVar("cursor_hotspot_y", 0); - - _cursorTargetScale = _evaluator->getVar("cursor_targetScale", 1); - - // inactive dialog shading stuff - - ShadingStyle shading = (ShadingStyle)_evaluator->getVar("inactive_dialog_shading", kShadingNone); - - switch (shading) { - case kShadingNone: - _dialogShadingCallback = 0; - break; - - case kShadingLuminance: - _dialogShadingCallback = &ThemeModern::calcLuminance; - break; - - case kShadingDim: - _dimPercentValue = _evaluator->getVar("shading_dim_percent", -1); - - if (_dimPercentValue < 0) { - _dimPercentValue = 0; - } else if (_dimPercentValue > 100) { - _dimPercentValue = 100; - } - - if (_dimPercentValue != 0) { - _dimPercentValue = 256 * (100 - _dimPercentValue) / 100; - _dialogShadingCallback = &ThemeModern::calcDimColor; - } - break; - - default: - warning("no valid 'inactive_dialog_shading' specified"); - } - - setupFonts(); - - // load the colors from the config file - setupColors(); - - // creates cursor image - if (_system->hasFeature(OSystem::kFeatureCursorHasPalette)) { - createCursor(); - } -} - -#pragma mark - - -OverlayColor ThemeModern::calcLuminance(OverlayColor col) { - uint8 r, g, b; - _system->colorToRGB(col, r, g, b); - - // A better (but slower) formula to calculate the luminance would be: - //uint lum = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5); - // Note that the approximation below will only produce values between - // (and including) 0 and 221. - uint lum = (r >> 2) + (g >> 1) + (b >> 3); - - return _system->RGBToColor(lum, lum, lum); -} - -OverlayColor ThemeModern::calcDimColor(OverlayColor col) { - uint8 r, g, b; - _system->colorToRGB(col, r, g, b); - - r = r * _dimPercentValue >> 8; - g = g * _dimPercentValue >> 8; - b = b * _dimPercentValue >> 8; - - return _system->RGBToColor(r, g, b); -} - -#pragma mark - - -void ThemeModern::setUpCursor() { - CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - CursorMan.showMouse(true); -} - -void ThemeModern::createCursor() { - const Surface *cursor = _images[kGUICursor]; - - _cursorWidth = cursor->w; - _cursorHeight = cursor->h; - - uint colorsFound = 0; - const OverlayColor *src = (const OverlayColor*)cursor->pixels; - - byte *table = new byte[65536]; - assert(table); - memset(table, 0, sizeof(byte)*65536); - - byte r, g, b; - - _system->colorToRGB(_colors[kColorTransparency], r, g, b); - uint16 transparency = RGBToColor >(r, g, b); - - delete[] _cursor; - - _cursor = new byte[_cursorWidth * _cursorHeight]; - assert(_cursor); - memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); - - for (uint y = 0; y < _cursorHeight; ++y) { - for (uint x = 0; x < _cursorWidth; ++x) { - _system->colorToRGB(src[x], r, g, b); - uint16 col = RGBToColor >(r, g, b); - if (!table[col] && col != transparency) { - table[col] = colorsFound++; - - uint index = table[col]; - _cursorPal[index * 4 + 0] = r; - _cursorPal[index * 4 + 1] = g; - _cursorPal[index * 4 + 2] = b; - _cursorPal[index * 4 + 3] = 0xFF; - - if (colorsFound > MAX_CURS_COLORS) - error("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); - } - - if (col != transparency) { - uint index = table[col]; - _cursor[y * _cursorWidth + x] = index; - } - } - src += _cursorWidth; - } - - _useCursor = true; - delete[] table; -} - -#pragma mark - - -template -inline OverlayColor getColorAlphaImpl(OverlayColor col1, OverlayColor col2, int alpha) { - OverlayColor output = 0; - output |= ((alpha * ((col1 & T::kRedMask) - (col2 & T::kRedMask)) >> 8) + (col2 & T::kRedMask)) & T::kRedMask; - output |= ((alpha * ((col1 & T::kGreenMask) - (col2 & T::kGreenMask)) >> 8) + (col2 & T::kGreenMask)) & T::kGreenMask; - output |= ((alpha * ((col1 & T::kBlueMask) - (col2 & T::kBlueMask)) >> 8) + (col2 & T::kBlueMask)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -// broken implementation! -template -inline OverlayColor getColorAlphaImp2(OverlayColor col1, OverlayColor col2, int alpha) { - OverlayColor output = 0; - output |= ((alpha * ((~col1 & T::kRedMask) - (col2 & T::kRedMask)) >> 8) + (col2 & T::kRedMask)) & T::kRedMask; - output |= ((alpha * ((~col1 & T::kGreenMask) - (col2 & T::kGreenMask)) >> 8) + (col2 & T::kGreenMask)) & T::kGreenMask; - output |= ((alpha * ((~col1 & T::kBlueMask) - (col2 & T::kBlueMask)) >> 8) + (col2 & T::kBlueMask)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -OverlayColor getColorAlpha(OverlayColor col1, OverlayColor col2, int alpha) { - if (alpha >= 0) { - if (gBitFormat == 565) { - return getColorAlphaImpl >(col1, col2, alpha); - } else { - return getColorAlphaImpl >(col1, col2, alpha); - } - } else { - if (gBitFormat == 565) { - return getColorAlphaImp2 >(col1, col2, -alpha - 256); - } else { - return getColorAlphaImp2 >(col1, col2, -alpha - 256); - } - } -} - -template -inline OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos) { - OverlayColor output = 0; - output |= (start + ((((end & T::kRedMask) - (start & T::kRedMask))) * pos >> 12)) & T::kRedMask; - output |= (start + ((((end & T::kGreenMask) - (start & T::kGreenMask))) * pos >> 12)) & T::kGreenMask; - output |= (start + ((((end & T::kBlueMask) - (start & T::kBlueMask))) * pos >> 12)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos, int max, uint factor = 1) { - pos *= factor; - if (pos >= max) - return end; - - pos = (0x1000 * pos) / max; - - if (gBitFormat == 565) { - return calcGradient >(start, end, pos); - } else { - return calcGradient >(start, end, pos); - } -} - -void getStateColor(OverlayColor &s, OverlayColor &e, - OverlayColor enabledS, OverlayColor enabledE, - OverlayColor highlightS, OverlayColor highlightE, - Theme::WidgetStateInfo state) { - if (state == Theme::kStateHighlight) { - s = highlightS; - e = highlightE; - } else { - s = enabledS; - e = enabledE; - } -} - -} // end of namespace GUI - -#endif diff --git a/gui/ThemeModern.h b/gui/ThemeModern.h deleted file mode 100644 index 29843a73e0..0000000000 --- a/gui/ThemeModern.h +++ /dev/null @@ -1,340 +0,0 @@ -/* 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 GUI_THEMEMODERN_H -#define GUI_THEMEMODERN_H - -#ifndef DISABLE_FANCY_THEMES - -#include "gui/theme.h" - -namespace GUI { - -class ThemeModern : public Theme { -public: - ThemeModern(OSystem *system, const Common::String &stylefile, const Common::ConfigFile *cfg = 0); - virtual ~ThemeModern(); - - bool init(); - void deinit(); - - void refresh(); - - bool ownCursor() const { return _useCursor; } - - void enable(); - void disable(); - - void openDialog(bool topDialog, ShadingStyle = kShadingNone); - void closeAllDialogs(); - - void clearAll(); - void updateScreen(); - - void setDrawArea(const Common::Rect &r); - void resetDrawArea(); - - const Graphics::Font *getFont(FontStyle font = kFontStyleBold) const { return _fonts[font]; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getCharWidth(c); return 0; } - - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state); - - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state); - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans); - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state); - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align); - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state); - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state); - - void restoreBackground(Common::Rect r, bool special = false); - bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false); - - int getTabSpacing() const; - int getTabPadding() const; - - bool supportsImages() const { return true; } - const Graphics::Surface *getImageSurface(const kThemeImages n) const { return n == kImageLogo ? _images[kThemeLogo] : 0; } -private: - void colorFade(const Common::Rect &r, OverlayColor start, OverlayColor end, uint factor = 1); - void drawRect(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, bool skipLastRow = false); - void drawRectMasked(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, - OverlayColor start, OverlayColor end, uint factor = 1, bool skipLastRow = false, bool skipTopRow = false); - void drawSurface(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, int alpha); - void drawSurfaceMasked(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, int alpha, - OverlayColor start, OverlayColor end, uint factor = 1); - - enum ShadowStyles { - kShadowFull = 0, - kShadowSmall = 1, - kShadowButton = 2, - kShadowEmboss = 3, - kShadowPopUp = 4 - }; - - Common::Rect shadowRect(const Common::Rect &r, uint32 shadowStyle); - void drawShadow(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, uint32 shadowStyle, bool skipLastRow = false, - bool skipTopRow = false); - void drawShadowRect(const Common::Rect &r, const Common::Rect &area, const Graphics::Surface *corner, - const Graphics::Surface *top, const Graphics::Surface *left, const Graphics::Surface *fill, - int alpha, bool skipLastRow = false, bool skipTopRow = false); - - int _shadowLeftWidth, _shadowRightWidth; - int _shadowTopHeight, _shadowBottomHeight; - - OSystem *_system; - Graphics::Surface _screen; - Common::Rect _shadowDrawArea; - - bool _initOk; - bool _forceRedraw; - bool _enabled; - - int _lastUsedBitMask; - void resetupGuiRenderer(); - void setupColors(); - - OverlayColor getColor(State state); - - struct DialogState { - Graphics::Surface screen; - } *_dialog; - - void setupFonts(); - void deleteFonts(); - - void setupFont(const Common::String &key, const Common::String &name, FontStyle style); - - const Graphics::Font *_fonts[kFontStyleMax]; - -private: - void processExtraValues(); - - enum ImageHandles { - kDialogBkgdCorner = 0, - kDialogBkgdTop = 1, - kDialogBkgdLeft = 2, - kDialogBkgd = 3, - - kWidgetBkgdCorner = 4, - kWidgetBkgdTop = 5, - kWidgetBkgdLeft = 6, - kWidgetBkgd = 7, - - kCheckboxEmpty = 8, - kCheckboxChecked = 9, - - kWidgetArrow = 10, - - kTabBkgdCorner = 11, - kTabBkgdTop = 12, - kTabBkgdLeft = 13, - kTabBkgd = 14, - - kSliderBkgdCorner = 15, - kSliderBkgdTop = 16, - kSliderBkgdLeft = 17, - kSliderBkgd = 18, - - kSliderCorner = 19, - kSliderTop = 20, - kSliderLeft = 21, - kSlider = 22, - - kScrollbarBkgdCorner = 23, - kScrollbarBkgdTop = 24, - kScrollbarBkgdLeft = 25, - kScrollbarBkgd = 26, - - kScrollbarCorner = 27, - kScrollbarTop = 28, - kScrollbarLeft = 29, - kScrollbar = 30, - - kButtonBkgdCorner = 31, - kButtonBkgdTop = 32, - kButtonBkgdLeft = 33, - kButtonBkgd = 34, - - kWidgetSmallBkgdCorner = 35, - kWidgetSmallBkgdTop = 36, - kWidgetSmallBkgdLeft = 37, - kWidgetSmallBkgd = 38, - - kThemeLogo = 39, - - kPopUpWidgetBkgdCorner = 40, - kPopUpWidgetBkgdTop = 41, - kPopUpWidgetBkgdLeft = 42, - kPopUpWidgetBkgd = 43, - - kEditTextBkgdCorner = 44, - kEditTextBkgdTop = 45, - kEditTextBkgdLeft = 46, - kEditTextBkgd = 47, - - kGUICursor = 48, - - kImageHandlesMax - }; - -private: - int _dimPercentValue; - typedef OverlayColor (ThemeModern::*InactiveDialogCallback)(OverlayColor col); - InactiveDialogCallback _dialogShadingCallback; - - OverlayColor calcLuminance(OverlayColor col); - OverlayColor calcDimColor(OverlayColor col); - - bool _useCursor; - void setUpCursor(); - void createCursor(); - int _cursorHotspotX, _cursorHotspotY; - int _cursorTargetScale; -#define MAX_CURS_COLORS 255 - byte *_cursor; - bool _needPaletteUpdates; - uint _cursorWidth, _cursorHeight; - byte _cursorPal[4*MAX_CURS_COLORS]; - -private: - Common::String _imageHandles[kImageHandlesMax]; - const Graphics::Surface **_images; - - enum ColorHandles { - kMainDialogStart = 0, - kMainDialogEnd = 1, - - kDialogStart = 2, - kDialogEnd = 3, - - kColorStateDisabled = 4, - kColorStateHighlight = 5, - kColorStateEnabled = 6, - kColorTransparency = 7, - - kTextInvertedBackground = 8, - kTextInvertedColor = 9, - - kWidgetBackgroundStart = 10, - kWidgetBackgroundEnd = 11, - kWidgetBackgroundSmallStart = 12, - kWidgetBackgroundSmallEnd = 13, - - kButtonBackgroundStart = 14, - kButtonBackgroundEnd = 15, - kButtonTextEnabled = 16, - kButtonTextDisabled = 17, - kButtonTextHighlight = 18, - - kSliderBackgroundStart = 19, - kSliderBackgroundEnd = 20, - kSliderStart = 21, - kSliderEnd = 22, - - kTabBackgroundStart = 23, - kTabBackgroundEnd = 24, - - kScrollbarBackgroundStart = 25, - kScrollbarBackgroundEnd = 26, - kScrollbarButtonStart = 27, - kScrollbarButtonEnd = 28, - kScrollbarSliderStart = 29, - kScrollbarSliderEnd = 30, - - kCaretColor = 31, - - kSliderHighStart = 32, - kSliderHighEnd = 33, - - kButtonBackgroundHighlightStart = 34, - kButtonBackgroundHighlightEnd = 35, - - kScrollbarButtonHighlightStart = 36, - kScrollbarButtonHighlightEnd = 37, - kScrollbarSliderHighlightStart = 38, - kScrollbarSliderHighlightEnd = 39, - - kPopUpWidgetStart = 40, - kPopUpWidgetEnd = 41, - kPopUpWidgetHighlightStart = 42, - kPopUpWidgetHighlightEnd = 43, - - kEditTextBackgroundStart = 44, - kEditTextBackgroundEnd = 45, - - kTabActiveStart = 46, - kTabActiveEnd = 47, - kTabInactiveStart = 48, - kTabInactiveEnd = 49, - - kColorHandlesMax - }; - - OverlayColor _colors[kColorHandlesMax]; - - enum GradientFactors { - kMainDialogFactor = 0, - kDialogFactor = 1, - kDialogSpecialFactor = 2, - - kWidgetSmallFactor = 3, - kWidgetFactor = 4, - - kButtonFactor = 5, - - kSliderFactor = 6, - kSliderBackground = 7, - - kTabFactor = 7, - - kScrollbarFactor = 8, - kScrollbarBkgdFactor = 9, - - kPopUpWidgetFactor = 10, - - kEditTextFactor = 11, - - kMaxGradientFactors - }; - - uint _gradientFactors[kMaxGradientFactors]; -}; - -} // end of namespace GUI - -#endif - -#endif - diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 1632488b91..00a07909b0 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -683,18 +683,26 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); } -void ThemeRenderer::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { +void ThemeRenderer::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) { if (!ready()) return; - if (hints & THEME_HINT_MAIN_DIALOG) { - queueDD(kDDMainDialogBackground, r); - } else if (hints & THEME_HINT_SPECIAL_COLOR) { - queueDD(kDDSpecialColorBackground, r); - } else if (hints & THEME_HINT_PLAIN_COLOR) { - queueDD(kDDPlainColorBackground, r); - } else { - queueDD(kDDDefaultBackground, r); + switch (bgtype) { + case kDialogBackgroundMain: + queueDD(kDDMainDialogBackground, r); + break; + + case kDialogBackgroundSpecial: + queueDD(kDDSpecialColorBackground, r); + break; + + case kDialogBackgroundPlain: + queueDD(kDDPlainColorBackground, r); + break; + + case kDialogBackgroundDefault: + queueDD(kDDDefaultBackground, r); + break; } } diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index d26dc21f48..4fe968752c 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -328,7 +328,7 @@ public: void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); + void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state); void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); diff --git a/gui/console.cpp b/gui/console.cpp index de4db14a4f..58c7404a19 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -24,7 +24,6 @@ #include "gui/console.h" #include "gui/ScrollBarWidget.h" -#include "gui/eval.h" #include "gui/ThemeEval.h" #include "engines/engine.h" @@ -120,8 +119,6 @@ void ConsoleDialog::init() { scrollBarWidth = kNormalScrollBarWidth; _scrollBar->resize(_w - scrollBarWidth - 1, 0, scrollBarWidth, _h); - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; - _pageWidth = (_w - scrollBarWidth - 2 - _leftPadding - _topPadding - scrollBarWidth) / kConsoleCharWidth; _linesPerPage = (_h - 2 - _topPadding - _bottomPadding) / kConsoleLineHeight; _linesInBuffer = kBufferSize / kCharsPerLine; @@ -152,8 +149,6 @@ void ConsoleDialog::open() { if (_w != w || _h != h) init(); - _drawingHints |= THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; - _y = -_h; _slideTime = g_system->getMillis(); _slideMode = kDownSlideMode; @@ -170,7 +165,7 @@ void ConsoleDialog::close() { } void ConsoleDialog::drawDialog() { - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _drawingHints); + g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); // FIXME: for the old theme the frame around the console vanishes // when any action is processed if we enable this // _drawingHints &= ~THEME_HINT_FIRST_DRAW; @@ -229,7 +224,6 @@ void ConsoleDialog::handleTickle() { // Perform the "slide animation". if (_slideMode != kNoSlideMode) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; const float tmp = (float)(g_system->getMillis() - _slideTime) / kConsoleSlideDownDuration; if (_slideMode == kUpSlideMode) { _y = (int)(_h * (0.0 - tmp)); diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 1e58c654eb..3b302ff36a 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -42,18 +42,15 @@ namespace GUI { * ... */ -Dialog::Dialog(int x, int y, int w, int h, bool dimsInactive_) +Dialog::Dialog(int x, int y, int w, int h) : GuiObject(x, y, w, h), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), _drawingHints(0), - _dimsInactive(dimsInactive_) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; -} + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _backgroundType(GUI::Theme::kDialogBackgroundDefault) {} -Dialog::Dialog(const Common::String &name, bool dimsInactive_) +Dialog::Dialog(const Common::String &name) : GuiObject(name), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), _drawingHints(0), - _dimsInactive(dimsInactive_) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _backgroundType(GUI::Theme::kDialogBackgroundDefault) { // It may happen that we have 3x scaler in launcher (960xY) and then 640x480 // game will be forced to 1x. At this stage GUI will not be aware of @@ -113,11 +110,9 @@ void Dialog::reflowLayout() { // changed, so any cached image may be invalid. The subsequent redraw // should be treated as the very first draw. - _drawingHints |= THEME_HINT_FIRST_DRAW; Widget *w = _firstWidget; while (w) { w->reflowLayout(); - w->setHints(THEME_HINT_FIRST_DRAW); w = w->_next; } @@ -144,8 +139,7 @@ void Dialog::drawDialog() { if (!isVisible()) return; - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _drawingHints); - _drawingHints &= ~THEME_HINT_FIRST_DRAW; + g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); // Draw all children Widget *w = _firstWidget; diff --git a/gui/dialog.h b/gui/dialog.h index 553a63d1a9..bc5ce6b6e0 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -49,15 +49,15 @@ protected: Widget *_focusedWidget; Widget *_dragWidget; bool _visible; - uint16 _drawingHints; + + Theme::DialogBackground _backgroundType; private: int _result; - bool _dimsInactive; public: - Dialog(int x, int y, int w, int h, bool dimsInactive = true); - Dialog(const Common::String &name, bool dimsInactive = true); + Dialog(int x, int y, int w, int h); + Dialog(const Common::String &name); virtual int runModal(); @@ -91,9 +91,6 @@ protected: void setResult(int result) { _result = result; } int getResult() const { return _result; } - - // Whether dialog dims all underneath dialogs or not when active - bool dimsInactive() { return _dimsInactive; } }; } // End of namespace GUI diff --git a/gui/eval.cpp b/gui/eval.cpp deleted file mode 100644 index 716006c108..0000000000 --- a/gui/eval.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* 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$ - * - */ - -#include "common/system.h" -#include "gui/eval.h" -#include "gui/widget.h" -#include "gui/newgui.h" - -#include "graphics/scaler.h" - -namespace GUI { - -static bool isdelim(char c) { - return strchr(" ;,+-<>/*%^=()", c) != 0 || c == 9 || c == '\n' || !c; -} - -Eval::Eval() { - loadConstants(); -} - -Eval::~Eval() { - _vars.clear(); - _aliases.clear(); -} - -int Eval::eval(const String &input, const String §ion, const String &name, int startpos) { - int result; - - debug(5, "%s=%s", name.c_str(), input.c_str()); - - strncpy(_input, input.c_str(), 256); - _section = section; - _name = name; - _startpos = startpos; - - _pos = 0; - - getToken(); - - if (_tokenType == tString) - return EVAL_STRING_VAR; - - if (!*_token) - exprError(eBadExpr); - - level2(&result); - - debug(5, "Result: %d", result); - - return result; -} - -void Eval::level2(int *result) { - char op; - int hold; - - level3(result); - - while ((op = *_token) == '+' || op == '-') { - getToken(); - level3(&hold); - arith(op, result, &hold); - } -} - -void Eval::level3(int *result) { - char op; - int hold; - - level4(result); - - while ((op = *_token) == '*' || op == '/' || op == '%') { - getToken(); - level4(&hold); - arith(op, result, &hold); - } -} - -void Eval::level4(int *result) { - char op; - - op = 0; - if ((_tokenType == tDelimiter) && (*_token == '+' || *_token == '-')) { - op = *_token; - getToken(); - } - - level5(result); - - if (op) - unary(op, result); -} - -void Eval::level5(int *result) { - if ((*_token == '(') && (_tokenType == tDelimiter)) { - getToken(); - - level2(result); - - if (*_token != ')') - exprError(eUnclosedBracket); - getToken(); - } else { - primitive(result); - } -} - -void Eval::primitive(int *result) { - if (*_token == ')') - exprError(eExtraBracket); - - switch (_tokenType) { - case tVariable: - *result = getVar_(_token); - if (*result == EVAL_UNDEF_VAR) - exprError(eUndefVar); - getToken(); - return; - case tNumber: - *result = atoi(_token); - getToken(); - return; - default: - exprError(eSyntaxError); - } -} - -void Eval::arith(char op, int *r, int *h) { - switch (op) { - case '-': - *r = *r - *h; - break; - case '+': - *r = *r + *h; - break; - case '*': - *r = *r * *h; - break; - case '/': - *r = (*r) / (*h); - break; - case '%': - *r = (*r) % (*h); - break; - } -} - -void Eval::unary(char op, int *r) { - if (op == '-') - *r = -(*r); -} - -void Eval::getToken() { - char *temp; - - _tokenType = tNone; - temp = _token; - - if (_input[_pos] == 0) { - *_token = 0; - _tokenType = tDelimiter; - return; - } - while (isspace(_input[_pos])) - _pos++; - - if (_input[_pos] == '"') { - _pos++; - while (_input[_pos] != '"' && _input[_pos] != '\n') - *temp++ = _input[_pos++]; - - if (_input[_pos] == '\n') - exprError(eMissingQuote); - - _pos++; - *temp = 0; - - _tokenType = tString; - return; - } - - if (isdigit(_input[_pos])) { - while (!isdelim(_input[_pos])) - *temp++ = _input[_pos++]; - *temp = 0; - - _tokenType = tNumber; - return; - } - - if (isalpha(_input[_pos])) { - while (!isdelim(_input[_pos])) - *temp++ = _input[_pos++]; - *temp = 0; - _tokenType = tVariable; - return; - } - - if (!_tokenType && isdelim(_input[_pos])) { - *temp++ = _input[_pos++]; - *temp = 0; - _tokenType = tDelimiter; - } -} - -void Eval::exprError(EvalErrors err) { - static const char *errors[] = { - "Syntax error", - "Extra ')'", - "Missing ')'", - "Bad expression", - "Undefined variable", - "Missing '\"'" - }; - - error("%s in section [%s] expression: \"%s\" start is at: %d near token '%s'", - errors[err], _section.c_str(), _name.c_str(), _pos + _startpos, _token); -} - -struct BuiltinConsts { - const char *name; - int value; -}; - -static const BuiltinConsts builtinConsts[] = { - {"kButtonWidth", GUI::kButtonWidth}, - {"kButtonHeight", GUI::kButtonHeight}, - {"kSliderWidth", GUI::kSliderWidth}, - {"kSliderHeight", GUI::kSliderHeight}, - - {"kBigButtonWidth", GUI::kBigButtonWidth}, - {"kBigButtonHeight", GUI::kBigButtonHeight}, - {"kBigSliderWidth", GUI::kBigSliderWidth}, - {"kBigSliderHeight", GUI::kBigSliderHeight}, - - {"kNormalWidgetSize", GUI::kNormalWidgetSize}, - {"kBigWidgetSize", GUI::kBigWidgetSize}, - - {"kThumbnailWidth", kThumbnailWidth}, - - {"kTextAlignLeft", kTextAlignLeft}, - {"kTextAlignRight", kTextAlignRight}, - {"kTextAlignCenter", kTextAlignCenter}, - - {"kFontStyleBold", Theme::kFontStyleBold}, - {"kFontStyleNormal", Theme::kFontStyleNormal}, - {"kFontStyleItalic", Theme::kFontStyleItalic}, - - {"kFontStyleFixedBold", Theme::kFontStyleFixedBold}, - {"kFontStyleFixedNormal", Theme::kFontStyleFixedNormal}, - {"kFontStyleFixedItalic", Theme::kFontStyleFixedItalic}, - - {"kShadingNone", Theme::kShadingNone}, - {"kShadingDim", Theme::kShadingDim}, - {"kShadingLuminance", Theme::kShadingLuminance}, - - {"false", 0}, - {"true", 1}, - {NULL, 0} -}; - -void Eval::loadConstants() { - int i; - - for (i = 0; builtinConsts[i].name; i++) - _vars[builtinConsts[i].name] = builtinConsts[i].value; -} - -int Eval::getBuiltinVar(const char *s) { - if (!strcmp(s, "w")) - return g_system->getOverlayWidth(); - - if (!strcmp(s, "h")) - return g_system->getOverlayHeight(); - - return EVAL_UNDEF_VAR; -} - -int Eval::getVar_(const Common::String &s, bool includeAliases) { - int val; - - val = getBuiltinVar(s.c_str()); - - if (val != EVAL_UNDEF_VAR) - return val; - - const Common::String *var = &s; - if (includeAliases) { - AliasesMap::const_iterator itera = _aliases.find(s); - if (itera != _aliases.end()) - var = &(itera->_value); - } - - VariablesMap::const_iterator iterv = _vars.find(*var); - if (iterv != _vars.end()) - return iterv->_value; - - return EVAL_UNDEF_VAR; -} - -void Eval::setVar(const String §ion, const String &name, const String &value) { - _vars[name.c_str() + 4] = eval(value, section, name, 0); -} - -void Eval::reset() { - _vars.clear(); - _aliases.clear(); - loadConstants(); -} - -} // end of namespace GUI diff --git a/gui/eval.h b/gui/eval.h deleted file mode 100644 index bd58a0e1c3..0000000000 --- a/gui/eval.h +++ /dev/null @@ -1,130 +0,0 @@ -/* 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 GUI_EVAL_H -#define GUI_EVAL_H - -#include "common/str.h" -#include "common/hashmap.h" -#include "common/hash-str.h" - -namespace GUI { - -using Common::String; -using Common::HashMap; - -enum { - EVAL_UNDEF_VAR = -13375, - EVAL_STRING_VAR = -13376 -}; - -class Eval { -public: - Eval(); - ~Eval(); - - int eval(const String &input, const String §ion, const String &name, int startpos); - void setVar(const String §ion, const String &name, const String &value); - - void setParent(const String &name); - - void setVar(const String &name, int val) { _vars[name] = val; } - void setStringVar(const String &name, const String &val) { _strings[name] = val; } - void setAlias(const Common::String &name, const String &val) { _aliases[name] = val; } - - int getVar(const Common::String &s) { - warning("Old evaluator access: '%s'", s.c_str()); - return getVar_(s); - } - - int getVar(const Common::String &s, int def) { - warning("Old evaluator access: '%s'", s.c_str()); - int val = getVar_(s); - return (val == EVAL_UNDEF_VAR) ? def : val; - } - - const String &getStringVar(const Common::String &name) { return _strings[name]; } - - uint getNumVars() { return _vars.size(); } - - void reset(); - - char *lastToken() { return _token; } - - typedef HashMap VariablesMap; - typedef HashMap AliasesMap; - typedef HashMap StringsMap; - -private: - enum TokenTypes { - tNone, - tDelimiter, - tVariable, - tNumber, - tString - }; - - enum EvalErrors { - eSyntaxError, - eExtraBracket, - eUnclosedBracket, - eBadExpr, - eUndefVar, - eMissingQuote - }; - - - void getToken(); - void level2(int *); - void level3(int *); - void level4(int *); - void level5(int *); - void primitive(int *); - void arith(char op, int *r, int *h); - void unary(char op, int *r); - void exprError(EvalErrors error); - int getVar_(const Common::String &s, bool includeAliases = true); - int getBuiltinVar(const char *s); - void loadConstants(); - - char _input[256]; - String _section; - String _name; - - int _startpos; - - TokenTypes _tokenType; - int _pos; - - char _token[256]; - - AliasesMap _aliases; - VariablesMap _vars; - StringsMap _strings; -}; - -} // end of namespace GUI - -#endif diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 3d35420326..d1187a4ad5 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -34,7 +34,6 @@ #include "gui/about.h" #include "gui/browser.h" #include "gui/chooser.h" -#include "gui/eval.h" #include "gui/launcher.h" #include "gui/massadd.h" #include "gui/message.h" @@ -161,7 +160,6 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // GUI: Add tab widget TabWidget *tab = new TabWidget(this, "GameOptions.TabWidget"); - tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); // // 1) The game tab @@ -471,7 +469,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat LauncherDialog::LauncherDialog() : Dialog(0, 0, 320, 200) { - _drawingHints |= THEME_HINT_MAIN_DIALOG; + _backgroundType = GUI::Theme::kDialogBackgroundMain; const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); diff --git a/gui/module.mk b/gui/module.mk index 1cb9ecb30f..f1ba840459 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -9,7 +9,6 @@ MODULE_OBJS := \ dialog.o \ editable.o \ EditTextWidget.o \ - eval.o \ ThemeRenderer.o \ launcher.o \ ListWidget.o \ diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 665d190e6f..f4d20920dd 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -28,9 +28,6 @@ #include "graphics/cursorman.h" #include "gui/newgui.h" #include "gui/dialog.h" -#include "gui/eval.h" -#include "gui/ThemeModern.h" -#include "gui/ThemeClassic.h" #include "gui/ThemeRenderer.h" #include "common/config-manager.h" diff --git a/gui/options.cpp b/gui/options.cpp index 1e6e551a57..590b0bd900 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -25,7 +25,6 @@ #include "gui/browser.h" #include "gui/themebrowser.h" #include "gui/chooser.h" -#include "gui/eval.h" #include "gui/message.h" #include "gui/newgui.h" #include "gui/ThemeEval.h" @@ -664,7 +663,6 @@ GlobalOptionsDialog::GlobalOptionsDialog() // The tab widget TabWidget *tab = new TabWidget(this, "GlobalOptions.TabWidget"); - tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); // // 1) The graphics tab diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp deleted file mode 100644 index f70696e8d5..0000000000 --- a/gui/theme-config.cpp +++ /dev/null @@ -1,772 +0,0 @@ -/* 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$ - */ - -#include "gui/theme.h" -#include "gui/eval.h" - -namespace GUI { - -const char *Theme::_defaultConfigINI = -"# Define our classic greenish theme here\n" -"[320xY]\n" -"def_widgetSize=kNormalWidgetSize\n" -"def_buttonWidth=kButtonWidth\n" -"def_buttonHeight=kButtonHeight\n" -"def_sliderWidth=kSliderWidth\n" -"def_sliderHeight=kSliderHeight\n" -"def_kLineHeight=12\n" -"def_kFontHeight=10\n" -"def_insetX=10\n" -"def_insetY=10\n" -"def_insetW=(w - 2 * 10)\n" -"def_insetH=(h - 30)\n" -"def_gameOptionsLabelWidth=60\n" -"def_tabPopupsLabelW=100\n" -"def_aboutXOff=3\n" -"def_aboutYOff=2\n" -"def_aboutOuterBorder=10\n" -"def_scummmainHOffset=8\n" -"def_scummmainVSpace=5\n" -"def_scummmainVAddOff=2\n" -"def_scummmainButtonWidth=90\n" -"def_scummmainButtonHeight=16\n" -"def_scummhelpX=5\n" -"def_scummhelpW=(w - 2 * 5)\n" -"def_midiControlsSpacing=1\n" -"def_vcAudioTabIndent=0\n" -"def_vcAudioTabSpacing=2\n" -"use=XxY\n" -"\n" -"# Override audio tab\n" -"set_parent=gameoptions\n" -"vBorder=5\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=audioControls globaloptions_\n" -"useWithPrefix=subtitleControls globaloptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=volumeControls globaloptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"useWithPrefix=audioControls gameoptions_\n" -"useWithPrefix=subtitleControls gameoptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"useWithPrefix=volumeControls gameoptions_\n" -"\n" -"TabWidget.tabWidth=0\n" -"TabWidget.tabHeight=16\n" -"TabWidget.titleVPad=2\n" -"# Scumm Saveload dialog\n" -"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n" -"set_parent=scummsaveload\n" -"scummsaveload_title=10 2 (parent.w - 2 * 10) kLineHeight\n" -"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n" -"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18\n" -"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"scummsaveload_extinfo.visible=false\n" -"\n" -"# MM NES resolution\n" -"[256x240]\n" -"useAsIs=320xY\n" -"\n" -"[XxY]\n" -"def_widgetSize=kBigWidgetSize\n" -"def_buttonWidth=kBigButtonWidth\n" -"def_buttonHeight=kBigButtonHeight\n" -"def_sliderWidth=kBigSliderWidth\n" -"def_sliderHeight=kBigSliderHeight\n" -"def_kLineHeight=16\n" -"def_kFontHeight=14\n" -"def_insetX=10\n" -"def_insetY=20\n" -"def_insetW=(w - 2 * 10)\n" -"def_insetH=(h - 2 * 40)\n" -"def_gameOptionsLabelWidth=90\n" -"def_tabPopupsLabelW=150\n" -"def_aboutXOff=8\n" -"def_aboutYOff=5\n" -"def_aboutOuterBorder=80\n" -"def_scummmainHOffset=12\n" -"def_scummmainVSpace=7\n" -"def_scummmainVAddOff=3\n" -"def_scummmainButtonWidth=160\n" -"def_scummmainButtonHeight=28\n" -"def_scummhelpW=370\n" -"def_scummhelpX=((w - scummhelpW) / 2)\n" -"def_midiControlsSpacing=2\n" -"def_vcAudioTabIndent=10\n" -"def_vcAudioTabSpacing=4\n" -"##### Widgets config\n" -"ListWidget.leftPadding=4\n" -"ListWidget.rightPadding=0\n" -"ListWidget.topPadding=2\n" -"ListWidget.bottomPadding=2\n" -"ListWidget.hlLeftPadding=2\n" -"ListWidget.hlRightPadding=1\n" -"PopUpWidget.leftPadding=4\n" -"PopUpWidget.rightPadding=0\n" -"TabWidget.tabWidth=70\n" -"TabWidget.tabHeight=22\n" -"TabWidget.titleVPad=2\n" -"\n" -"###### chooser\n" -"opHeight=(h * 7 / 10)\n" -"useWithPrefix=chooser defaultChooser_\n" -"\n" -"##### browser\n" -"brW=((w * 7) / 8)\n" -"brH=((h * 9) / 10)\n" -"browser=((w - brW) / 2) ((h - brH) / 2) brW brH\n" -"set_parent=browser\n" -"browser_headline=10 kLineHeight (parent.w - 2 * 10) kLineHeight\n" -"browser_headline.align=kTextAlignCenter\n" -"browser_path=10 prev.y2 prev.w prev.h\n" -"browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14)\n" -"browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"browser_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"##### launcher\n" -"hBorder=10\n" -"launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight\n" -"launcher_version.align=kTextAlignCenter\n" -"top=(h - 8 - buttonHeight)\n" -"numButtons=4\n" -"space=8\n" -"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n" -"launcher_quit_button=hBorder top butWidth buttonHeight\n" -"launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"top=(top - buttonHeight * 2)\n" -"numButtons=3\n" -"space=10\n" -"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n" -"launcher_addGame_button=hBorder top butWidth buttonHeight\n" -"launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20)\n" -"\n" -"### global options\n" -"globaloptions=insetX insetY insetW insetH\n" -"set_parent=globaloptions\n" -"vBorder=5\n" -"globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" -"\n" -"# graphics tab\n" -"opYoffset=vBorder\n" -"opXoffset=0\n" -"useWithPrefix=graphicsControls globaloptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=audioControls globaloptions_\n" -"useWithPrefix=subtitleControls globaloptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=volumeControls globaloptions_\n" -"\n" -"# MIDI tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=midiControls globaloptions_\n" -"\n" -"# paths tab\n" -"yoffset=vBorder\n" -"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"globaloptions_savebutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_extrabutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_themebutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_pluginsbutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_pluginspath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"\n" -"# Misc options\n" -"yoffset=vBorder\n" -"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight\n" -"globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) (kLineHeight + 2)\n" -"\n" -"globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"### game options\n" -"gameoptions=insetX insetY insetW insetH\n" -"set_parent=gameoptions\n" -"vBorder=5\n" -"gox=5\n" -"gow=(parent.w - 15)\n" -"\n" -"gameoptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" -"\n" -"# game tab\n" -"opYoffset=vBorder\n" -"gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n" -"gameoptions_id.align=kTextAlignRight\n" -"gameoptions_domain=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n" -"gameoptions_name.align=kTextAlignRight\n" -"gameoptions_desc=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n" -"opYoffset=(opYoffset + prev.h + 7)\n" -"gameoptions_lang=gox (opYoffset - 1) gow (kLineHeight + 2)\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"gameoptions_platform=prev.x opYoffset prev.w prev.h\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"\n" -"# paths tab\n" -"opYoffset=vBorder\n" -"goOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"gameoptions_savepath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"gameoptions_extrapath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"gameoptions_gamepath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"\n" -"# graphics tab\n" -"opYoffset=vBorder\n" -"opXoffset=gox\n" -"gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=graphicsControls gameoptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=audioControls gameoptions_\n" -"useWithPrefix=subtitleControls gameoptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=volumeControls gameoptions_\n" -"\n" -"# midi tab\n" -"opYoffset=vBorder\n" -"gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=midiControls gameoptions_\n" -"\n" -"gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"### keys dialog\n" -"keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 4)\n" -"set_parent=keysdialog\n" -"keysdialog_map=(parent.w - buttonWidth - 10) (10 + 2 * kLineHeight) buttonWidth buttonHeight\n" -"keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h\n" -"keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h\n" -"keysdialog_action=10 10 (parent.w - 20) kLineHeight\n" -"keysdialog_action.align=kTextAlignCenter\n" -"keysdialog_list=prev.x (prev.y + 2 * kLineHeight) (parent.w - buttonWidth - 30) (parent.h - kLineHeight * 6)\n" -"keysdialog_mapping=prev.x (prev.y + prev.h + kLineHeight) (parent.w - buttonWidth - 20) kLineHeight\n" -"\n" -"### mass add dialog\n" -"massadddialog=10 20 300 174\n" -"set_parent=massadddialog\n" -"massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_caption.align=kTextAlignCenter\n" -"massadddialog_dirprogress=10 (10 + 3 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_dirprogress.align=kTextAlignCenter\n" -"massadddialog_gameprogress=10 (10 + 4 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_gameprogress.align=kTextAlignCenter\n" -"massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"\n" -"##### SCUMM dialogs\n" -"scummDummyDialog=0 80 0 16\n" -"\n" -"use=scummmain\n" -"## Engine config\n" -"# note that scummconfig size depends on overall height\n" -"# hence it is on the end of the list\n" -"opYoffset=8\n" -"useWithPrefix=volumeControls scummconfig_\n" -"useWithPrefix=subtitleControls scummconfig_\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"soWidth=(39 + 3 * buttonWidth)\n" -"scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight\n" -"scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h\n" -"scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8)\n" -"\n" -"## Help\n" -"scummHelpNumLines=15\n" -"shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7)\n" -"scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH\n" -"scummhelp_title=10 5 scummhelpW kFontHeight\n" -"scummhelp_key.x=10\n" -"scummhelp_key.yoffset=5\n" -"scummhelp_key.w=80\n" -"scummhelp_key.h=kFontHeight\n" -"scummhelp_dsc.x=90\n" -"scummhelp_dsc.yoffset=5\n" -"scummhelp_dsc.w=(scummhelpW - 10 - 90)\n" -"scummhelp_dsc.h=kFontHeight\n" -"scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) buttonWidth buttonHeight\n" -"scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h\n" -"scummhelp_close=(scummhelpW - 8 - buttonWidth) prev.y prev.w prev.h\n" -"\n" -"# Saveload dialog\n" -"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n" -"set_parent=scummsaveload\n" -"scummsaveload_title=10 2 (parent.w - 2 * 10 - 180) kLineHeight\n" -"scummsaveload_title.align=kTextAlignCenter\n" -"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n" -"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 18)) 22\n" -"scummsaveload_thumbnail.hPad=4\n" -"scummsaveload_thumbnail.vPad=4\n" -"scummsaveload_thumbnail.fillR=0\n" -"scummsaveload_thumbnail.fillG=0\n" -"scummsaveload_thumbnail.fillB=0\n" -"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"scummsaveload_extinfo.visible=true\n" -"\n" -"############################################\n" -"[chooser]\n" -"chooserW=(w - 2 * 8)\n" -"chooser=((w - chooserW) / 2) ((h - opHeight) / 2) chooserW opHeight\n" -"chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight)\n" -"chooser_headline.align=kTextAlignCenter\n" -"chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12)\n" -"chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight\n" -"chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"[graphicsControls]\n" -"gcx=10\n" -"gcw=(parent.w - 2 * 10)\n" -"grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + kLineHeight + 4)\n" -"grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h\n" -"opYoffset=(opYoffset + kLineHeight + 4)\n" -"grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"grAspectCheckbox=prev.x opYoffset prev.w prev.h\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"\n" -"[audioControls]\n" -"aux=10\n" -"auw=(parent.w - 2 * 10)\n" -"auMidiPopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"auSampleRatePopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"\n" -"[volumeControls]\n" -"vctextw=(95 + vcAudioTabIndent)\n" -"vcxoff=(opXoffset + vctextw + 15)\n" -"vcx=(opXoffset + 10)\n" -"vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcMusicText.align=kTextAlignRight\n" -"vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcSfxText.align=kTextAlignRight\n" -"vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcSpeechText.align=kTextAlignRight\n" -"vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"\n" -"[midiControls]\n" -"mcx=10\n" -"mcFontButton=mcx opYoffset buttonWidth buttonHeight\n" -"mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - 15 - kLineHeight - 10) kLineHeight\n" -"mcFontClearButton=(prev.x2 + 10) (opYoffset + 2) kLineHeight kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)\n" -"mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcMt32Checkbox=mcx opYoffset prev.w buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcGSCheckbox=mcx opYoffset prev.w buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight\n" -"mcMidiGainText.align=kTextAlignRight\n" -"mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight\n" -"mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + midiControlsSpacing)\n" -"\n" -"[subtitleControls]\n" -"sbx=(opXoffset + 10)\n" -"sbYoff=(buttonHeight / 8)\n" -"sbOff=((sliderHeight - kLineHeight) / 2 + 2)\n" -"sbtextw=(100 + vcAudioTabIndent)\n" -"opYoffset=(opYoffset + sbYoff)\n" -"subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight\n" -"subToggleDesc.align=kTextAlignRight\n" -"subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight\n" -"subSubtitleSpeedDesc.align=kTextAlignRight\n" -"subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight\n" -"subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + 8)\n" -"\n" -"[scummmain]\n" -"## Main dialog\n" -"# note that scummmain size depends on overall height\n" -"smY=(scummmainVSpace + scummmainVAddOff)\n" -"scummmain_resume=scummmainHOffset smY scummmainButtonWidth scummmainButtonHeight\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_load=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_save=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_options=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_about=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_help=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_quit=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smW=(scummmainButtonWidth + 2 * scummmainHOffset)\n" -"smH=(smY + scummmainVSpace)\n" -"scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH\n" -"\n" -"# PSP GUI\n" -"[480x272]\n" -"def_buttonWidth=100\n" -"def_buttonHeight=23\n" -"def_insetX=20\n" -"def_insetY=10\n" -"def_insetW=(w - 2 * insetX)\n" -"def_insetH=(h - 13 - insetY)\n" -"def_launcherVersionX=50\n" -"def_launcherVersionY=5\n" -"def_midiControlsSpacing=2\n" -"def_gameOptionsOverrideVPad=10\n" -"def_aboutXOff=3\n" -"def_aboutYOff=2\n" -"def_aboutOuterBorder=10\n" -"\n" -"use=XxY\n" -""; - -using Common::String; - -void Theme::processSingleLine(const String §ion, const String &prefix, const String &name, const String &str) { - int level = 0; - int start = 0; - uint i; - int value; - const char *selfpostfixes[] = {"self.x", "self.y", "self.w", "self.h"}; - const char *postfixesXYWH[] = {".x", ".y", ".w", ".h"}; - const char *postfixesRGB[] = {".r", ".g", ".b"}; - int npostfix = 0; - const String prefixedname(prefix + name); - - // Make self.BLAH work, but not self.ANYTHING.BLAH - if (!strchr(prefixedname.c_str(), '.')) { - for (i = 0; i < ARRAYSIZE(postfixesXYWH); i++) { - String to(prefixedname); - - to += postfixesXYWH[i]; - - _evaluator->setAlias(selfpostfixes[i], to); - _evaluator->setVar(to, EVAL_UNDEF_VAR); - } - } - - // Count the number of parameters, so that we know if they're meant to - // be XY[WH] or RGB. - - int ntmppostfix = 0; - - for (i = 0; i < str.size(); i++) { - if (isspace(str[i]) && level == 0) { - ntmppostfix++; - } - - if (str[i] == '(') - level++; - else if (str[i] == ')') { - if (level == 0) { - error("Extra ')' in section: [%s] expression: \"%s\" start is at: %d", - section.c_str(), name.c_str(), start); - } - level--; - } - } - - if (level > 0) - error("Missing ')' in section: [%s] expression: \"%s\" start is at: %d", - section.c_str(), name.c_str(), start); - - const char **postfixes = (ntmppostfix == 2) ? postfixesRGB : postfixesXYWH; - - // Now do it for real, only this time we already know the parentheses - // are balanced. - - for (i = 0; i < str.size(); i++) { - if (isspace(str[i]) && level == 0) { - value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start); - _evaluator->setVar(prefixedname + postfixes[npostfix++], value); - start = i + 1; - } - if (str[i] == '(') - level++; - else if (str[i] == ')') - level--; - } - - value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start); - - if (value == EVAL_STRING_VAR) - _evaluator->setStringVar(prefixedname, _evaluator->lastToken()); - - // process VAR=VALUE construct - if (npostfix == 0) { - _evaluator->setVar(name, value); - - // Fix bug #1742561: "GUI: Missaligned text" - // "blah.align=foo" should be prefixed too - _evaluator->setVar(prefixedname, value); - } else { - _evaluator->setVar(prefixedname + postfixes[npostfix], value); - } - - // If we have all 4 parameters, set .x2 and .y2 - if (npostfix == 3) { - _evaluator->setVar(prefixedname + ".x2", - _evaluator->getVar(prefixedname + ".x") + _evaluator->getVar(prefixedname + ".w")); - _evaluator->setVar(prefixedname + ".y2", - _evaluator->getVar(prefixedname + ".y") + _evaluator->getVar(prefixedname + ".h")); - } - - if (npostfix != 0) - setSpecialAlias("prev", prefixedname); -} - - -void Theme::processResSection(Common::ConfigFile &config, const String &name, bool skipDefs, const String &prefix) { - debug(3, "Reading section: [%s]", name.c_str()); - - const Common::ConfigFile::SectionKeyList &keys = config.getKeys(name); - - Common::ConfigFile::SectionKeyList::const_iterator iterk; - for (iterk = keys.begin(); iterk != keys.end(); ++iterk) { - if (iterk->key == "set_parent") { - setSpecialAlias("parent", prefix + iterk->value); - continue; - } - if (iterk->key.hasPrefix("set_")) { - _evaluator->setAlias(iterk->key.c_str() + 4, prefix + iterk->value); - continue; - } - if (iterk->key.hasPrefix("def_")) { - if (!skipDefs) - _evaluator->setVar(name, prefix + iterk->key, iterk->value); - continue; - } - if (iterk->key == "use") { - if (iterk->value == name) - error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(iterk->value)) - error("Undefined use of section [%s]", iterk->value.c_str()); - processResSection(config, iterk->value, true); - continue; - } - if (iterk->key == "useAsIs") { - if (iterk->value == name) - error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(iterk->value)) - error("Undefined use of section [%s]", iterk->value.c_str()); - processResSection(config, iterk->value); - continue; - } - if (iterk->key == "useWithPrefix") { - const char *temp = iterk->value.c_str(); - const char *pos = strrchr(temp, ' '); - - if (pos == NULL) - error("2 arguments required for useWithPrefix keyword"); - - String n(temp, strchr(temp, ' ') - temp); - String pref(pos + 1); - - if (n == name) - error("Theme section [%s]: cannot use itself", n.c_str()); - if (!config.hasSection(n)) - error("Undefined use of section [%s]", n.c_str()); - processResSection(config, n, true, pref); - continue; - } - processSingleLine(name, prefix, iterk->key, iterk->value); - } -} - -void Theme::setSpecialAlias(const String &alias, const String &name) { - const char *postfixes[] = {".x", ".y", ".w", ".h", ".x2", ".y2"}; - int i; - - for (i = 0; i < ARRAYSIZE(postfixes); i++) { - String from(alias + postfixes[i]); - String to(name + postfixes[i]); - - _evaluator->setAlias(from.c_str(), to); - } -} - -bool Theme::sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h) { - if (!config.hasKey("skipFor", name)) - return false; - - String res; - - config.getKey("skipFor", name, res); - - int x, y; - int phase = 0; - const char *ptr = res.c_str(); - - x = y = 0; - - while (phase != 3) { - switch (phase) { - case 0: - if (*ptr >= '0' && *ptr <= '9') { - x = x * 10 + *ptr - '0'; - } else if (*ptr == 'X') { - phase = 1; - } else if (*ptr == 'x') { - phase = 1; - } else { - error("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - case 1: - if (*ptr >= '0' && *ptr <= '9') { - y = y * 10 + *ptr - '0'; - } else if (*ptr == 'Y' || !*ptr || *ptr == ',') { - phase = 2; - - if ((x == w || x == 0) && (y == h || y == 0)) - return true; - if (!*ptr) - return false; - if (*ptr == ',') { - phase = x = y = 0; - } - } else { - error("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - case 2: - if (*ptr == ',') { - phase = x = y = 0; - } else if (!*ptr) { - if ((x == w || x == 0) && (y == h || y == 0)) - return true; - return false; - } else { - error ("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - default: - break; - } - - ptr++; - } - - return false; -} - -void Theme::loadTheme(Common::ConfigFile &config, bool reset) { - char name[80]; - int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - - if (reset) - _evaluator->reset(); - - strcpy(name, "XxY"); - if (config.hasSection(name) && !sectionIsSkipped(config, "XxY", x, y)) - processResSection(config, name); - - sprintf(name, "%dxY", x); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - sprintf(name, "Xx%d", y); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - sprintf(name, "%dx%d", x, y); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - debug(3, "Number of variables: %d", _evaluator->getNumVars()); -} - -void Theme::loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing) { - loadTheme(config, reset); - - if (doBackendSpecificPostProcessing && !g_system->getExtraThemeConfig().empty()) { - Common::ConfigFile myConfig; - Common::String myConfigINI = g_system->getExtraThemeConfig(); - Common::MemoryReadStream s((const byte *)myConfigINI.c_str(), myConfigINI.size()); - myConfig.loadFromStream(s); - loadTheme(myConfig, false); - } -} - -} // End of namespace GUI diff --git a/gui/theme.cpp b/gui/theme.cpp index 6e05ce086c..e61fc1993d 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -23,8 +23,6 @@ */ #include "gui/theme.h" -#include "gui/eval.h" - #include "common/unzip.h" namespace GUI { diff --git a/gui/theme.h b/gui/theme.h index 067603d562..72495b3a22 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -40,39 +40,6 @@ namespace GUI { class ThemeEval; -//! Hint to the theme engine that the widget is used in a non-standard way. -enum ThemeHint { - //! Indicates that this is the first time the widget is drawn. - THEME_HINT_FIRST_DRAW = 1 << 0, - - /** - * Indicates that the widget will be redrawn often, e.g. list widgets. - * It may therefore be a good idea to save the background so that it - * can be redrawn quickly. - */ - THEME_HINT_SAVE_BACKGROUND = 1 << 1, - - //! Indicates that this is the launcher dialog (maybe delete this in the future) - THEME_HINT_MAIN_DIALOG = 1 << 2, - - //! Indicates special colorfade - THEME_HINT_SPECIAL_COLOR = 1 << 3, - - //! Indicates no colorfade - THEME_HINT_PLAIN_COLOR = 1 << 4, - - //! Indictaes that a shadows should be drawn around the background - THEME_HINT_USE_SHADOW = 1 << 5, - - /** - * Indicates that no background should be restored when drawing the widget - * (note that this can be silently ignored if for example the theme does - * alpha blending and would blend over an already drawn widget) - * TODO: currently only ThemeModern::drawButton supports this - */ - THEME_HINT_NO_BACKGROUND_RESTORE = 1 << 6 -}; - /** * Our theme renderer class. * @@ -109,6 +76,14 @@ public: kWidgetBackgroundEditText, //! Background used for edit text fields kWidgetBackgroundSlider //! Background used for sliders }; + + //! Dialog background type + enum DialogBackground { + kDialogBackgroundMain, + kDialogBackgroundSpecial, + kDialogBackgroundPlain, + kDialogBackgroundDefault + }; //! State of the widget to be drawn enum State { @@ -271,7 +246,7 @@ public: virtual int getStringWidth(const Common::String &str, FontStyle font = kFontStyleBold) const = 0; virtual int getCharWidth(byte c, FontStyle font = kFontStyleBold) const = 0; - virtual void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state = kStateEnabled) = 0; + virtual void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled) = 0; virtual void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignCenter, bool inverted = false, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold) = 0; // this should ONLY be used by the debugger until we get a nicer solution virtual void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled) = 0; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 97184fda91..f4039c6cff 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -53,7 +53,7 @@ ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); - _fileList->setHints(THEME_HINT_PLAIN_COLOR); + _backgroundType = GUI::Theme::kDialogBackgroundPlain; // Buttons new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); diff --git a/gui/themes/classic080.ini b/gui/themes/classic080.ini deleted file mode 100644 index b5c911bada..0000000000 --- a/gui/themes/classic080.ini +++ /dev/null @@ -1,466 +0,0 @@ -# $URL$ -# $Id$ -[theme] -version=23 -type=classic -name=Classic (ScummVM 0.8.0) - -[colors] -color=104 104 104 -shadowcolor=64 64 64 -bgcolor=0 0 0 -textcolor=32 160 32 -textcolorhi=0 255 0 - -[extra] -font="builtin" -blending=true - -[XxY] -def_widgetSize=kBigWidgetSize -def_buttonWidth=kBigButtonWidth -def_buttonHeight=kBigButtonHeight -def_sliderWidth=kBigSliderWidth -def_sliderHeight=kBigSliderHeight -def_kLineHeight=16 -def_kFontHeight=14 -def_insetX=10 -def_insetY=20 -def_insetW=(w - 2 * 10) -def_insetH=(h - 2 * 40) -def_gameOptionsLabelWidth=90 -def_tabPopupsLabelW=150 -def_aboutXOff=8 -def_aboutYOff=5 -def_aboutOuterBorder=80 -def_scummmainHOffset=12 -def_scummmainVSpace=7 -def_scummmainVAddOff=3 -def_scummmainButtonWidth=160 -def_scummmainButtonHeight=28 -def_scummhelpW=370 -def_scummhelpX=((w - scummhelpW) / 2) -def_midiControlsSpacing=2 -def_vcAudioTabIndent=10 -def_vcAudioTabSpacing=4 - -use=colors -use=extra - -##### Widgets config -ListWidget.leftPadding=4 -ListWidget.rightPadding=0 -ListWidget.topPadding=2 -ListWidget.bottomPadding=2 -ListWidget.hlLeftPadding=2 -ListWidget.hlRightPadding=1 -PopUpWidget.leftPadding=4 -PopUpWidget.rightPadding=0 -TabWidget.tabWidth=70 -TabWidget.tabHeight=21 -TabWidget.titleVPad=2 - -###### chooser -opHeight=(h * 7 / 10) -useWithPrefix=chooser defaultChooser_ - -##### browser -brW=((w * 7) / 8) -brH=((h * 9) / 10) -browser=((w - brW) / 2) ((h - brH) / 2) brW brH -set_parent=browser -browser_headline=10 kLineHeight (parent.w - 2 * 10) kLineHeight -browser_headline.align=kTextAlignCenter -browser_path=10 prev.y2 prev.w prev.h -browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) -browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_choose=(prev.x2 + 10) prev.y prev.w prev.h - -##### launcher -hBorder=10 -launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight -launcher_version.align=kTextAlignCenter -top=(h - 8 - buttonHeight) -numButtons=4 -space=8 -butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons) -launcher_quit_button=hBorder top butWidth buttonHeight -launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h -top=(top - buttonHeight * 2) -numButtons=3 -space=10 -butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons) -launcher_addGame_button=hBorder top butWidth buttonHeight -launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20) - -### global options -globaloptions=insetX insetY insetW insetH -set_parent=globaloptions -vBorder=5 -globaloptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder) - -# graphics tab -opYoffset=vBorder -opXoffset=0 -useWithPrefix=graphicsControls globaloptions_ - -# audio tab -opYoffset=vBorder -useWithPrefix=audioControls globaloptions_ -useWithPrefix=subtitleControls globaloptions_ - -# volume tab -opYoffset=vBorder -useWithPrefix=volumeControls globaloptions_ - -# MIDI tab -opYoffset=vBorder -useWithPrefix=midiControls globaloptions_ - -# paths tab -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_savebutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_extrabutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_themebutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_pluginsbutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_pluginspath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight - -# Misc options -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight -globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 12) -globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) (kLineHeight + 2) - -globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h - -### game options -gameoptions=insetX insetY insetW insetH -set_parent=gameoptions -vBorder=5 -gox=5 -gow=(parent.w - 15) - -gameoptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder) - -# game tab -opYoffset=vBorder -gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight -gameoptions_id.align=kTextAlignRight -gameoptions_domain=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2) -opYoffset=(opYoffset + prev.h + 5) -gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight -gameoptions_name.align=kTextAlignRight -gameoptions_desc=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2) -opYoffset=(opYoffset + prev.h + 7) -gameoptions_lang=gox (opYoffset - 1) gow (kLineHeight + 2) -opYoffset=(opYoffset + prev.h + 5) -gameoptions_platform=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + prev.h + 5) - -# paths tab -opYoffset=vBorder -goOff=((buttonHeight - kLineHeight) / 2 + 2) -gameoptions_savepath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) -gameoptions_extrapath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) -gameoptions_gamepath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) - -# graphics tab -opYoffset=vBorder -opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=graphicsControls gameoptions_ - -# audio tab -opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=audioControls gameoptions_ -useWithPrefix=subtitleControls gameoptions_ - -# volume tab -opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=volumeControls gameoptions_ - -# midi tab -opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=midiControls gameoptions_ - -gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h - -### keys dialog -keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5) -set_parent=keysdialog -keysdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight -keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y) -keysdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight -keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h - -### mass add dialog -massadddialog=10 20 300 174 -set_parent=massadddialog -massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight -massadddialog_caption.align=kTextAlignCenter -massadddialog_dirprogress=10 (10 + 3 * kLineHeight) prev.w prev.h -massadddialog_dirprogress.align=kTextAlignCenter -massadddialog_gameprogress=10 (10 + 4 * kLineHeight) prev.w prev.h -massadddialog_gameprogress.align=kTextAlignCenter -massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h - - -##### SCUMM dialogs -scummDummyDialog=0 80 0 16 - -use=scummmain -## Engine config -# note that scummconfig size depends on overall height -# hence it is on the end of the list -opYoffset=8 -useWithPrefix=volumeControls scummconfig_ -useWithPrefix=subtitleControls scummconfig_ -opYoffset=(opYoffset + buttonHeight) -opYoffset=(opYoffset + buttonHeight + 4) -soWidth=(39 + 3 * buttonWidth) -scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight -scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h -scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h -opYoffset=(opYoffset + buttonHeight) -scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8) - -## Help -scummHelpNumLines=15 -shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7) -scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH -scummhelp_title=10 5 scummhelpW kFontHeight -scummhelp_key.x=10 -scummhelp_key.yoffset=5 -scummhelp_key.w=80 -scummhelp_key.h=kFontHeight -scummhelp_dsc.x=90 -scummhelp_dsc.yoffset=5 -scummhelp_dsc.w=(scummhelpW - 10 - 90) -scummhelp_dsc.h=kFontHeight -scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) buttonWidth buttonHeight -scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h -scummhelp_close=(scummhelpW - 8 - buttonWidth) prev.y prev.w prev.h - -# Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10 - 180) kLineHeight -scummsaveload_title.align=kTextAlignCenter -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 18)) 22 -scummsaveload_thumbnail.hPad=4 -scummsaveload_thumbnail.vPad=4 -scummsaveload_thumbnail.fillR=0 -scummsaveload_thumbnail.fillG=0 -scummsaveload_thumbnail.fillB=0 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=true - -############################################ -[chooser] -chooserW=(w - 2 * 8) -chooser=((w - chooserW) / 2) ((h - opHeight) / 2) chooserW opHeight -chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight) -chooser_headline.align=kTextAlignCenter -chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12) -chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight -chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h - -[graphicsControls] -gcx=10 -gcw=(parent.w - 2 * 10) -grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + kLineHeight + 4) -grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h -opYoffset=(opYoffset + kLineHeight + 4) -grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -grAspectCheckbox=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + buttonHeight) - -[audioControls] -aux=10 -auw=(parent.w - 2 * 10) -auMidiPopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + buttonHeight + 4) -auSampleRatePopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + buttonHeight + 4) - -[volumeControls] -vctextw=(95 + vcAudioTabIndent) -vcxoff=(opXoffset + vctextw + 15) -vcx=(opXoffset + 10) -vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight -vcMusicText.align=kTextAlignRight -vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight -vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) -vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight -vcSfxText.align=kTextAlignRight -vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) -vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight -vcSpeechText.align=kTextAlignRight -vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) - -[midiControls] -mcx=10 -mcFontButton=mcx opYoffset buttonWidth buttonHeight -mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight -mcFontClearButton=(prev.x2 + 10) (opYoffset + 3) kLineHeight kLineHeight -opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing) -mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMt32Checkbox=mcx opYoffset prev.w buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcGSCheckbox=mcx opYoffset prev.w buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight -mcMidiGainText.align=kTextAlignRight -mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight -mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight -opYoffset=(opYoffset + sliderHeight + midiControlsSpacing) - -[subtitleControls] -sbx=(opXoffset + 10) -sbYoff=(buttonHeight / 8) -sbOff=((sliderHeight - kLineHeight) / 2 + 2) -sbtextw=(100 + vcAudioTabIndent) -opYoffset=(opYoffset + sbYoff) -subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight -subToggleDesc.align=kTextAlignRight -subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) -subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight -subSubtitleSpeedDesc.align=kTextAlignRight -subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight -subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 8) - -[scummmain] -## Main dialog -# note that scummmain size depends on overall height -smY=(scummmainVSpace + scummmainVAddOff) -scummmain_resume=scummmainHOffset smY scummmainButtonWidth scummmainButtonHeight -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_load=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_save=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_options=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_about=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_help=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_quit=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smW=(scummmainButtonWidth + 2 * scummmainHOffset) -smH=(smY + scummmainVSpace) -scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH - -# Define our classic greenish theme here -[320xY] -def_widgetSize=kNormalWidgetSize -def_buttonWidth=kButtonWidth -def_buttonHeight=kButtonHeight -def_sliderWidth=kSliderWidth -def_sliderHeight=kSliderHeight -def_kLineHeight=12 -def_kFontHeight=10 -def_insetX=10 -def_insetY=10 -def_insetW=(w - 2 * 10) -def_insetH=(h - 30) -def_gameOptionsLabelWidth=60 -def_tabPopupsLabelW=100 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 -def_scummmainHOffset=8 -def_scummmainVSpace=5 -def_scummmainVAddOff=2 -def_scummmainButtonWidth=90 -def_scummmainButtonHeight=16 -def_scummhelpX=5 -def_scummhelpW=(w - 2 * 5) -def_midiControlsSpacing=1 -def_vcAudioTabIndent=0 -def_vcAudioTabSpacing=2 -use=XxY - -TabWidget.tabWidth=0 -TabWidget.tabHeight=16 -TabWidget.titleVPad=2 -# Scumm Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10) kLineHeight -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=false - -# MM NES resolution -[256x240] -useAsIs=320xY - -# PSP GUI -[480x272] -def_buttonWidth=100 -def_buttonHeight=23 -def_insetX=20 -def_insetY=10 -def_insetW=(w - 2 * insetX) -def_insetH=(h - 13 - insetY) -def_launcherVersionX=50 -def_launcherVersionY=5 -def_midiControlsSpacing=2 -def_gameOptionsOverrideVPad=10 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 - -use=XxY diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini deleted file mode 100644 index 87ef0bcbb9..0000000000 --- a/gui/themes/modern.ini +++ /dev/null @@ -1,622 +0,0 @@ -# $URL$ -# $Id$ -[theme] -version=23 -type=modern -name=Modern Style - -[pixmaps] -pix_dialog_corner="dialog_bkgd_corner.bmp" -pix_dialog_top="dialog_bkgd_top.bmp" -pix_dialog_left="dialog_bkgd_left.bmp" -pix_dialog_bkgd="dialog_bkgd.bmp" - -pix_widget_corner="widget_bkgd_corner.bmp" -pix_widget_top="widget_bkgd_top.bmp" -pix_widget_left="widget_bkgd_left.bmp" -pix_widget_bkgd="widget_bkgd.bmp" - -pix_widget_small_corner="widget_small_bkgd_corner.bmp" -pix_widget_small_top="widget_small_bkgd_top.bmp" -pix_widget_small_left="widget_small_bkgd_left.bmp" -pix_widget_small_bkgd="widget_small_bkgd.bmp" - -pix_checkbox_empty="checkbox_empty.bmp" -pix_checkbox_checked="checkbox_checked.bmp" - -pix_widget_arrow="widget_arrow.bmp" - -pix_tab_corner="button_bkgd_corner.bmp" -pix_tab_top="widget_bkgd_top.bmp" -pix_tab_left="widget_bkgd_left.bmp" -pix_tab_bkgd="widget_bkgd.bmp" - -pix_slider_bkgd_corner="button_bkgd_corner.bmp" -pix_slider_bkgd_top="button_bkgd_top.bmp" -pix_slider_bkgd_left="button_bkgd_left.bmp" -pix_slider_bkgd_bkgd="button_bkgd.bmp" - -pix_slider_corner="button_bkgd_corner.bmp" -pix_slider_top="button_bkgd_top.bmp" -pix_slider_left="button_bkgd_left.bmp" -pix_slider_bkgd="button_bkgd.bmp" - -pix_scrollbar_bkgd_corner="widget_small_bkgd_corner.bmp" -pix_scrollbar_bkgd_top="widget_small_bkgd_top.bmp" -pix_scrollbar_bkgd_left="widget_small_bkgd_left.bmp" -pix_scrollbar_bkgd_bkgd="widget_small_bkgd.bmp" - -pix_scrollbar_corner="widget_bkgd_corner.bmp" -pix_scrollbar_top="widget_bkgd_top.bmp" -pix_scrollbar_left="widget_bkgd_left.bmp" -pix_scrollbar_bkgd="widget_bkgd.bmp" - -pix_button_corner="button_bkgd_corner.bmp" -pix_button_top="button_bkgd_top.bmp" -pix_button_left="button_bkgd_left.bmp" -pix_button_bkgd="button_bkgd.bmp" - -pix_popupwidget_corner="button_bkgd_corner.bmp" -pix_popupwidget_top="button_bkgd_top.bmp" -pix_popupwidget_left="button_bkgd_left.bmp" -pix_popupwidget_bkgd="button_bkgd.bmp" - -pix_edittext_bkgd_corner="button_bkgd_corner.bmp" -pix_edittext_bkgd_top="button_bkgd_top.bmp" -pix_edittext_bkgd_left="button_bkgd_left.bmp" -pix_edittext_bkgd_bkgd="button_bkgd.bmp" - -pix_theme_logo="logo.bmp" - -pix_cursor_image="cursor.bmp" - -[colors] -main_dialog_start=210 114 10 -main_dialog_end=239 196 24 - -dialog_start=246 224 139 -dialog_end=251 241 206 - -color_state_disabled=192 192 192 -color_state_highlight=100 162 8 -color_state_enabled=0 0 0 - -color_transparency=255 0 255 - -text_inverted_background=100 162 8 -text_inverted_color=0 0 0 - -widget_bkgd_start=246 224 139 -widget_bkgd_end=251 241 206 -widget_bkgd_small_start=246 224 139 -widget_bkgd_small_end=251 241 206 - -button_bkgd_start=203 126 107 -button_bkgd_end=169 42 12 -button_bkgd_highlight_start=255 210 200 -button_bkgd_highlight_end=200 70 50 -button_text_enabled=255 255 255 -button_text_disabled=192 192 192 -button_text_highlight=255 214 84 - -slider_background_start=247 228 166 -slider_background_end=247 228 166 -slider_start=203 126 107 -slider_end=169 42 12 -slider_highlight_start=255 210 200 -slider_highlight_end=200 70 50 - -tab_background_start=232 180 80 -tab_background_end=232 180 80 - -tab_active_start=246 224 139 -tab_active_end=251 241 206 -tab_inactive_start=239 202 109 -tab_inactive_end=239 202 109 - -scrollbar_background_start=247 228 166 -scrollbar_background_end=247 228 166 -scrollbar_button_start=247 228 166 -scrollbar_button_end=247 228 166 -scrollbar_slider_start=203 126 107 -scrollbar_slider_end=169 42 12 -scrollbar_button_highlight_start=255 210 200 -scrollbar_button_highlight_end=200 70 50 -scrollbar_slider_highlight_start=255 210 200 -scrollbar_slider_highlight_end=200 70 50 - -popupwidget_start=251 241 206 -popupwidget_end=251 241 206 -popupwidget_highlight_start=246 224 139 -popupwidget_highlight_end=251 241 206 - -edittext_background_start=247 228 166 -edittext_background_end=247 228 166 - -caret_color=0 0 0 - -[gradients] -gradient_dialog_main=1 -gradient_dialog=4 -gradient_dialog_special=4 - -gradient_widget_small=9 -gradient_widget=9 - -gradient_button=1 - -gradient_slider=1 -gradient_slider_bkgd=1 - -gradient_tab=4 - -gradient_scrollbar=1 -gradient_scrollbar_background=1 - -gradient_popupwidget=1 - -gradient_edittext=1 - -[extra] -shadow_left_width=2 -shadow_right_width=4 -shadow_top_height=2 -shadow_bottom_height=4 -inactive_dialog_shading=kShadingDim -shading_dim_percent=50 -fontfile_normal="helvr12-l1.bdf" -fontfile_fixed_normal="courr12-l1.bdf" -cursor_hotspot_x=0 -cursor_hotspot_y=0 -cursor_targetScale=3 - -[XxY] -skipFor=320xY,256x240 -def_widgetSize=kBigWidgetSize -def_buttonWidth=120 -def_buttonHeight=25 -def_sliderWidth=kBigSliderWidth -def_sliderHeight=kBigSliderHeight -def_kLineHeight=16 -def_kFontHeight=14 -def_kPopUpHeight=(kLineHeight + 3) -def_insetX=23 -def_insetY=94 -def_insetW=(w - buttonWidth - 17 * 2 - insetX) -def_insetH=(h - 23 - insetY) -def_optionsVPad=20 -def_optionsLabelWidth=110 -def_gameOptionsOverrideVPad=20 -def_tabPopupsLabelW=optionsLabelWidth -def_aboutXOff=8 -def_aboutYOff=5 -def_aboutOuterBorder=80 -def_scummmainHOffset=12 -def_scummmainVSpace=15 -def_scummmainVAddOff=5 -def_scummhelpW=370 -def_scummhelpX=((w - scummhelpW) / 2) -def_launcherVersionX=(w / 2 - 283 / 2 - 90) -def_launcherVersionY=21 - -def_xSeparation=10 -def_ySeparation=10 -def_xBorder=15 - -use=pixmaps -use=colors -use=gradients -use=extra - -##### Widgets config -ListWidget.leftPadding=7 -ListWidget.rightPadding=5 -ListWidget.topPadding=5 -ListWidget.bottomPadding=5 -ListWidget.hlLeftPadding=0 -ListWidget.hlRightPadding=0 -PopUpWidget.leftPadding=7 -PopUpWidget.rightPadding=5 -PopUpWidget.labelSpacing=xSeparation -EditTextWidget.font=kFontStyleNormal -EditTextWidget.leftPadding=7 -EditTextWidget.rightPadding=5 -Console.font=kFontStyleFixedNormal -Console.leftPadding=7 -Console.rightPadding=5 -Console.topPadding=5 -Console.bottomPadding=5 -TabWidget.tabWidth=75 -TabWidget.tabHeight=27 -TabWidget.titleVPad=8 -TabWidget.navButtonRightPad=3 -TabWidget.navButtonTopPad=4 -TabWidget.navButtonW=15 -TabWidget.navButtonH=18 - -###### chooser -opHeight=insetH -useWithPrefix=chooser defaultChooser_ - -##### browser -use=browser - -##### launcher -launcher_version=launcherVersionX launcherVersionY 247 kLineHeight -launcher_version.align=kTextAlignRight -launcher_logo=(w / 2 - 283 / 2) 5 283 80 -launcher_logo.visible=true -space1=20 -space2=5 -launcher_list=insetX insetY insetW insetH -launcher_start_button=(prev.x2 + 17) prev.y buttonWidth buttonHeight -launcher_addGame_button=prev.x (prev.y2 + space1) prev.w prev.h -launcher_editGame_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_removeGame_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_options_button=prev.x (prev.y2 + space1) prev.w prev.h -launcher_about_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_quit_button=prev.x (prev.y2 + space1) prev.w prev.h - -use=scummmain - -### global options -globaloptions=insetX insetY insetW insetH -set_parent=globaloptions -vBorder=optionsVPad -globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) - -# graphics tab -opYoffset=vBorder -opXoffset=0 -useWithPrefix=graphicsControls globaloptions_ - -# audio tab -opYoffset=vBorder -useWithPrefix=audioControls globaloptions_ -useWithPrefix=subtitleControls globaloptions_ - -# volume tab -opYoffset=vBorder -useWithPrefix=volumeControls globaloptions_ - -# MIDI tab -opYoffset=vBorder -useWithPrefix=midiControls globaloptions_ - -# paths tab -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_savebutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_savepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_extrabutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_extrapath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_themebutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_themepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_pluginsbutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_pluginspath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_keysbutton=xBorder yoffset buttonWidth buttonHeight - -# Misc options -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_themebutton2=xBorder yoffset buttonWidth buttonHeight -globaloptions_curtheme=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_autosaveperiod=xBorder yoffset (parent.w - self.x - xBorder) kPopUpHeight - -globaloptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -globaloptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -### game options -gameoptions=insetX insetY insetW insetH -set_parent=gameoptions -vBorder=gameOptionsOverrideVPad -gox=xBorder -gow=(parent.w - gox - xBorder) - -gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) - -# game tab -opYoffset=optionsVPad -glOff=((kPopUpHeight - kLineHeight) / 2 + 2) -gameoptions_id=gox (opYoffset + glOff) optionsLabelWidth kLineHeight -gameoptions_id.align=kTextAlignRight -gameoptions_domain=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_name=gox (opYoffset + glOff) optionsLabelWidth kLineHeight -gameoptions_name.align=kTextAlignRight -gameoptions_desc=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_lang=gox opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_platform=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + prev.h + ySeparation) - -# paths tab -opYoffset=optionsVPad -goOff=((buttonHeight - kLineHeight) / 2 + 2) -gameoptions_savepath=gox opYoffset buttonWidth buttonHeight -gameoptions_savepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -gameoptions_extrapath=gox opYoffset buttonWidth buttonHeight -gameoptions_extrapathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -gameoptions_gamepath=gox opYoffset buttonWidth buttonHeight -gameoptions_gamepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) - -# graphics tab -opYoffset=vBorder -opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=graphicsControls gameoptions_ - -# audio tab -opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=audioControls gameoptions_ -useWithPrefix=subtitleControls gameoptions_ - -# volume tab -opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=volumeControls gameoptions_ - -# midi tab -opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=midiControls gameoptions_ - -gameoptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -gameoptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -### keys dialog -keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5) -set_parent=keysdialog -keysdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight -keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y) -keysdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight -keysdialog_action.align=kTextAlignCenter -keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h -keysdialog_mapping.align=kTextAlignCenter - -### mass add dialog -massadddialog=10 20 300 174 -set_parent=massadddialog -massadddialog_caption=xBorder (10 + 1 * kLineHeight) (parent.w - 2 * xBorder) kLineHeight -massadddialog_caption.align=kTextAlignCenter -massadddialog_dirprogress=xBorder (10 + 3 * kLineHeight) prev.w prev.h -massadddialog_dirprogress.align=kTextAlignCenter -massadddialog_gameprogress=xBorder (10 + 4 * kLineHeight) prev.w prev.h -massadddialog_gameprogress.align=kTextAlignCenter -massadddialog_ok=((parent.w - (buttonWidth * 2) - xSeparation) / 2) (parent.h - buttonHeight - ySeparation) buttonWidth buttonHeight -massadddialog_cancel=(prev.x2 + xSeparation) prev.y prev.w prev.h - - -##### SCUMM dialogs -scummDummyDialog=0 80 0 16 - -use=scummmain -## Engine config -# note that scummconfig size depends on overall height -# hence it is on the end of the list -opYoffset=8 -useWithPrefix=volumeControls scummconfig_ -opYoffset=(opYoffset + 2) -useWithPrefix=subtitleControls scummconfig_ -opYoffset=(opYoffset + buttonHeight) -opYoffset=(opYoffset + buttonHeight + 4) -soWidth=(8 + 3 * buttonWidth + 4) -scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight -scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h -scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h -opYoffset=(opYoffset + buttonHeight) -scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8) - -## Help -scummHelpNumLines=15 -shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7) -shButtonWidth=(buttonWidth - 20) -scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH -scummhelp_title=10 5 scummhelpW kFontHeight -scummhelp_title.align=kTextAlignCenter -scummhelp_key.x=10 -scummhelp_key.yoffset=5 -scummhelp_key.w=80 -scummhelp_key.h=kFontHeight -scummhelp_dsc.x=90 -scummhelp_dsc.yoffset=5 -scummhelp_dsc.w=(scummhelpW - 10 - 90) -scummhelp_dsc.h=kFontHeight -scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) shButtonWidth buttonHeight -scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h -scummhelp_close=(scummhelpW - 8 - shButtonWidth) prev.y prev.w prev.h - -# Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10 - 180-20) kLineHeight -scummsaveload_title.align=kTextAlignCenter -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18 -scummsaveload_thumbnail.hPad=10 -scummsaveload_thumbnail.vPad=10 -scummsaveload_thumbnail.fillR=0 -scummsaveload_thumbnail.fillG=0 -scummsaveload_thumbnail.fillB=0 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=true - -############################################ -[chooser] -chooserW=insetW -chooser=insetX insetY chooserW opHeight -chooser_headline=xBorder 6 (chooserW - 2 * xBorder) kLineHeight -chooser_list=prev.x (prev.y2 + 2) prev.w (opHeight - self.y - buttonHeight - 12) -#JVPRAT: next Y doesn't seem right -chooser_cancel=(chooserW - 2 * buttonWidth - xSeparation - xBorder) (opHeight - buttonHeight - 8) buttonWidth buttonHeight -chooser_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -[browser] -browser=insetX insetY insetW insetH -set_parent=browser -browser_headline=xBorder 5 (parent.w - 2 * xBorder) kLineHeight -browser_headline.align=kTextAlignCenter -browser_path=prev.x (prev.y2 + 5) prev.w prev.h -browser_list=prev.x prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) -browser_up=prev.x (parent.h - buttonHeight - 8) buttonWidth buttonHeight -#JVPRAT: doesn't it lack insetx?: -browser_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_choose=(prev.x2 + xSeparation) prev.y prev.w prev.h - -[graphicsControls] -gcx=(opXoffset + xBorder) -grModePopup=gcx opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(prev.y2 + ySeparation) -grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h -opYoffset=(prev.y2 + ySeparation) -grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - xBorder) kLineHeight -opYoffset=(prev.y2 + ySeparation) -grAspectCheckbox=prev.x opYoffset prev.w prev.h -opYoffset=(prev.y2 + ySeparation) - -[audioControls] -aux=(opXoffset + xBorder) -auMidiPopup=aux opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -auSampleRatePopup=aux (opYoffset - 1) prev.w kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) - -[volumeControls] -vcx=(opXoffset + xBorder) -vcOff=((sliderHeight - kLineHeight) / 2 + 2) -vcMusicText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcMusicText.align=kTextAlignRight -vcMusicSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcMusicLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) -vcSfxText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcSfxText.align=kTextAlignRight -vcSfxSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcSfxLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) -vcSpeechText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcSpeechText.align=kTextAlignRight -vcSpeechSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcSpeechLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[midiControls] -mcx=(opXoffset + xBorder) -mcOff=((buttonHeight - kLineHeight) / 2 + 2) -mcFontButton=mcx opYoffset buttonWidth buttonHeight -mcFontPath=(prev.x2 + xSeparation) (opYoffset + mcOff) (parent.w - self.x - xSeparation - kLineHeight - xBorder) kLineHeight -mcFontClearButton=(prev.x2 + xSeparation) prev.y kLineHeight kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -mcMixedCheckbox=mcx opYoffset (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcMt32Checkbox=mcx opYoffset prev.w kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcGSCheckbox=mcx opYoffset prev.w kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcOff=((sliderHeight - kLineHeight) / 2 + 2) -mcMidiGainText=mcx (opYoffset + mcOff) optionsLabelWidth kLineHeight -mcMidiGainText.align=kTextAlignRight -mcMidiGainSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -mcMidiGainLabel=(prev.x2 + xSeparation) (opYoffset + mcOff) 40 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[subtitleControls] -sbx=(opXoffset + xBorder) -sbOff=((sliderHeight - kLineHeight) / 2 + 2) -subToggleDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight -subToggleDesc.align=kTextAlignRight -subToggleButton=(prev.x2 + xSeparation) opYoffset (buttonWidth + 34) sliderHeight -opYoffset=(prev.y2 + ySeparation) -subSubtitleSpeedDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight -subSubtitleSpeedDesc.align=kTextAlignRight -subSubtitleSpeedSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -subSubtitleSpeedLabel=(prev.x2 + xSeparation) (opYoffset + sbOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[scummmain] -## Main dialog -# note that scummmain size depends on overall height -smY=scummmainHOffset -scummmain_resume=scummmainHOffset smY buttonWidth buttonHeight -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_load=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_save=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_options=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_about=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_help=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_quit=prev.x smY prev.w prev.h -smH=(smY + buttonHeight + scummmainHOffset) -smW=(buttonWidth + 2 * scummmainHOffset) -scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH - -[320xY] -use=pixmaps -use=colors -use=gradients -use=extra -shadow_right_width=1 -pix_checkbox_empty="checkbox_empty320.bmp" -pix_checkbox_checked="checkbox_checked320.bmp" -pix_cursor_image="cursor320.bmp" - -# NES resoltuion -[256x240] -use=320xY - -# PSP GUI -[480x272] -def_buttonWidth=100 -def_buttonHeight=23 -def_insetX=20 -def_insetY=10 -def_insetW=(w - buttonWidth - 17 * 2 - insetX) -def_insetH=(h - 13 - insetY) -def_launcherVersionX=50 -def_launcherVersionY=5 -def_gameOptionsOverrideVPad=10 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 - -use=XxY - -TabWidget.tabWidth=75 - -# Override launcher -launcher_list=insetX 103 (w - buttonWidth - 17 * 2 - self.x) (h - 15 - self.y) -launcher_version=50 80 247 kLineHeight -launcher_version.align=kTextAlignCenter -launcher_logo=40 2 283 80 -launcher_logo.visible=true - -# Override extras -inactive_dialog_shading=kShadingNone - -# Override browser -def_buttonWidth=90 -use=browser diff --git a/gui/themes/modern.zip b/gui/themes/modern.zip deleted file mode 100644 index 739c6d23ac..0000000000 Binary files a/gui/themes/modern.zip and /dev/null differ diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index c240b0080c..4f83ad5cd8 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/widget.cpp b/gui/widget.cpp index 0320aa1f04..685b6dfc65 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -26,7 +26,6 @@ #include "graphics/fontman.h" #include "gui/widget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/ThemeEval.h" @@ -35,15 +34,13 @@ namespace GUI { Widget::Widget(GuiObject *boss, int x, int y, int w, int h) : GuiObject(x, y, w, h), _type(0), _boss(boss), - _id(0), _flags(0), _hints(THEME_HINT_FIRST_DRAW), - _hasFocus(false), _state(Theme::kStateEnabled) { + _id(0), _flags(0), _hasFocus(false), _state(Theme::kStateEnabled) { init(); } Widget::Widget(GuiObject *boss, const Common::String &name) : GuiObject(name), _type(0), _boss(boss), - _id(0), _flags(0), _hints(THEME_HINT_FIRST_DRAW), - _hasFocus(false), _state(Theme::kStateDisabled) { + _id(0), _flags(0), _hasFocus(false), _state(Theme::kStateDisabled) { init(); } @@ -51,8 +48,6 @@ void Widget::init() { // Insert into the widget list of the boss _next = _boss->_firstWidget; _boss->_firstWidget = this; - // HACK: we enable background saving for all widgets by default for now - _hints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; } Widget::~Widget() { @@ -101,7 +96,7 @@ void Widget::draw() { // Draw border if (_flags & WIDGET_BORDER) { - gui->theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _hints, Theme::kWidgetBackgroundBorder); + gui->theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, Theme::kWidgetBackgroundBorder); _x += 4; _y += 4; _w -= 8; @@ -128,8 +123,6 @@ void Widget::draw() { w->draw(); w = w->_next; } - - clearHints(THEME_HINT_FIRST_DRAW); } Widget *Widget::findWidgetInChain(Widget *w, int x, int y) { @@ -225,7 +218,6 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co : StaticTextWidget(boss, name, label), CommandSender(boss), _cmd(cmd), _hotkey(hotkey) { setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG); - _hints = THEME_HINT_USE_SHADOW; _type = kButtonWidget; } @@ -235,7 +227,7 @@ void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) { } void ButtonWidget::drawWidget() { - g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, _hints); + g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, 0); } #pragma mark - @@ -335,20 +327,12 @@ GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h) : Widget(boss, x, y, w, h), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; - // HACK: Don't save the background. We want to be sure that redrawing - // the widget updates the screen, even when there isn't any image - // to draw. - _hints &= ~THEME_HINT_SAVE_BACKGROUND; } GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name) : Widget(boss, name), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; - // HACK: Don't save the background. We want to be sure that redrawing - // the widget updates the screen, even when there isn't any image - // to draw. - _hints &= ~THEME_HINT_SAVE_BACKGROUND; } GraphicsWidget::~GraphicsWidget() { @@ -403,7 +387,7 @@ ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) : } void ContainerWidget::drawWidget() { - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _hints, Theme::kWidgetBackgroundBorder); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, Theme::kWidgetBackgroundBorder); } } // End of namespace GUI diff --git a/gui/widget.h b/gui/widget.h index 00bf800857..3e111f28d4 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -93,7 +93,6 @@ protected: GuiObject *_boss; Widget *_next; uint16 _id; - uint16 _hints; bool _hasFocus; Theme::WidgetStateInfo _state; @@ -142,10 +141,6 @@ public: void clearFlags(int flags); int getFlags() const { return _flags; } - void setHints(int hints) { _hints |= hints; } - void clearHints(int hints) { _hints &= ~hints; } - int getHints() const { return _hints; } - void setEnabled(bool e) { if (e) setFlags(WIDGET_ENABLED); else clearFlags(WIDGET_ENABLED); } bool isEnabled() const; bool isVisible() const; -- cgit v1.2.3 From 80e059f2bb61f58e02d44d9dd125d23627d38b83 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 13 Aug 2008 18:48:14 +0000 Subject: Fixed compilation bugs in non-OSX platforms. svn-id: r33836 --- dists/msvc9/scummvm.vcproj | 20 -------------------- gui/browser.cpp | 2 +- gui/themes/scummodern.zip | Bin 121066 -> 114585 bytes 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 1a6d3519c8..7fd256cd42 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1100,14 +1100,6 @@ RelativePath="..\..\gui\EditTextWidget.h" > - - - - @@ -1196,10 +1188,6 @@ RelativePath="..\..\gui\TabWidget.h" > - - @@ -1216,14 +1204,6 @@ RelativePath="..\..\gui\themebrowser.h" > - - - - diff --git a/gui/browser.cpp b/gui/browser.cpp index 21d492f942..a5c71e6987 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -150,7 +150,7 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser) _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); - _fileList->setHints(THEME_HINT_PLAIN_COLOR); + _backgroundType = GUI::Theme::kDialogBackgroundPlain; // Buttons new ButtonWidget(this, "Browser.Up", "Go up", kGoUpCmd, 0); diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 4f83ad5cd8..940377a713 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From c4f2a691ce3feed23b28ba8b657e94baa9d2301b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 13 Aug 2008 23:07:26 +0000 Subject: Finished theme loading support. Added "themerc" file to default theme. svn-id: r33851 --- gui/ThemeRenderer.cpp | 39 +++++++++++++++++++-------------- gui/newgui.cpp | 3 +++ gui/theme.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++--- gui/theme.h | 4 +++- gui/themebrowser.cpp | 22 ++++--------------- gui/themes/scummodern.zip | Bin 114585 -> 87340 bytes 6 files changed, 84 insertions(+), 38 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 00a07909b0..f323807903 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -383,7 +383,6 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { } } - _themeName = "DEBUG - A Theme name"; _themeOk = true; return true; } @@ -412,9 +411,10 @@ bool ThemeRenderer::loadDefaultXML() { bool ThemeRenderer::loadThemeXML(Common::String themeName) { assert(_parser); + _themeName.clear(); #ifdef USE_ZLIB - unzFile zipFile = unzOpen((themeName + ".zip").c_str()); + unzFile zipFile = unzOpen(themeName.c_str()); char fileNameBuffer[32]; int parseCount = 0; @@ -424,7 +424,7 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { unzOpenCurrentFile(zipFile); unzGetCurrentFileInfo(zipFile, &fileInfo, fileNameBuffer, 32, NULL, 0, NULL, 0); - if (matchString(fileNameBuffer, "*.stx")) { + if (matchString(fileNameBuffer, "*.stx") || !strcmp(fileNameBuffer, "THEMERC")) { uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; assert(buffer); memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); @@ -432,31 +432,38 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); - if (parser()->loadStream(stream) == false || parser()->parse() == false) { - warning("Failed to load stream for zipped file '%s'", fileNameBuffer); - unzClose(zipFile); + if (!strcmp(fileNameBuffer, "THEMERC")) { + char stxHeader[128]; + stream->readLine(stxHeader, 128); + + if (!themeConfigParseHeader(stxHeader, _themeName)) + error("Corrupted 'THEMERC' file"); + delete stream; - return false; + + } else { + parseCount++; + + if (parser()->loadStream(stream) == false || parser()->parse() == false) { + warning("Failed to load stream for zipped file '%s'", fileNameBuffer); + unzClose(zipFile); + delete stream; + return false; + } } - - parseCount++; - } + } unzCloseCurrentFile(zipFile); if (unzGoToNextFile(zipFile) != UNZ_OK) break; } - } else if (parser()->loadFile(themeName + ".stx") && parser()->parse()) { - parseCount++; - } else { - warning("No theme files for '%s' found.", themeName.c_str()); } unzClose(zipFile); - return (parseCount > 0); + return (parseCount > 0 && _themeName.empty() == false); #else - return (parser()->loadFile(themeName + ".stx") && parser()->parse()); + return false; #endif } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index f4d20920dd..945c944b93 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -93,6 +93,9 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), Common::String themefile(ConfMan.get("gui_theme")); if (themefile.compareToIgnoreCase("default") == 0) themefile = "builtin"; + + if (!themefile.hasSuffix(".zip")) + themefile += ".zip"; loadNewTheme(themefile); _themeChange = false; diff --git a/gui/theme.cpp b/gui/theme.cpp index e61fc1993d..3e77919ba9 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -133,7 +133,27 @@ bool Theme::isThemeLoadingRequired() { return true; } -bool Theme::themeConfigUseable(const Common::String &filename) { +bool Theme::themeConfigParseHeader(Common::String header, Common::String &themeName) { + header.trim(); + + if (header[0] != '[' || header.lastChar() != ']') + return false; + + header.deleteChar(0); + header.deleteLastChar(); + + Common::StringTokenizer tok(header, ":"); + + if (tok.nextToken() != SCUMMVM_THEME_VERSION_STR) + return false; + + themeName = tok.nextToken(); + Common::String author = tok.nextToken(); + + return tok.empty(); +} + +bool Theme::themeConfigUseable(const Common::String &filename, Common::String &themeName) { if (ConfMan.hasKey("themepath")) Common::File::addDefaultDirectory(ConfMan.get("themepath")); @@ -143,11 +163,39 @@ bool Theme::themeConfigUseable(const Common::String &filename) { if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + +#ifdef USE_ZLIB + unzFile zipFile = unzOpen(filename.c_str()); + char stxHeader[128]; + bool foundHeader = false; + + if (zipFile && unzLocateFile(zipFile, "THEMERC", 2) == UNZ_OK) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); + stream.readLine(stxHeader, 128); + + if (themeConfigParseHeader(stxHeader, themeName)) + foundHeader = true; + + delete[] buffer; + buffer = 0; + } + unzClose(zipFile); +#else + return false; +#endif + return foundHeader; +} - return true; -} } // End of namespace GUI diff --git a/gui/theme.h b/gui/theme.h index 72495b3a22..4c1ab2e195 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -35,6 +35,7 @@ #include "graphics/fontman.h" #define THEME_VERSION 23 +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_THEME_V23" namespace GUI { @@ -304,7 +305,8 @@ public: bool isThemeLoadingRequired(); virtual ThemeEval *evaluator() = 0; - static bool themeConfigUseable(const Common::String &file); + static bool themeConfigUseable(const Common::String &file, Common::String &themeName); + static bool themeConfigParseHeader(Common::String header, Common::String &themeName); virtual const Common::String &getThemeFileName() const = 0; virtual const Common::String &getThemeName() const = 0; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index f4039c6cff..2f1ab48f2d 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -91,7 +91,7 @@ void ThemeBrowser::updateListing() { // classic is always build in Entry th; - th.name = "Modern Development Theme (Builtin) - WIP"; + th.name = "ScummVM Modern Theme (Builtin Version)"; th.file = "builtin"; _themes.push_back(th); @@ -173,26 +173,12 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { out.file = node.getName(); - if (!out.file.hasSuffix(".zip") && !out.file.hasSuffix(".stx")) + if (!out.file.hasSuffix(".zip")) return false; - - for (int i = out.file.size()-1; out.file[i] != '.' && i > 0; --i) { - out.file.deleteLastChar(); - } - out.file.deleteLastChar(); - - if (out.file.empty()) + + if (!Theme::themeConfigUseable(out.file, out.name)) return false; -// TODO: Check if theme is usable. -// if (!Theme::themeConfigUseable(out.file, "", &type, &cfg)) -// return false; - -// if (cfg.hasKey("name", "theme")) -// cfg.getKey("name", "theme", out.name); -// else - out.name = out.file; - return true; } diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 940377a713..bbd750a1fa 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 89f46dc907f4b6ca1596f6c22249891eb5dadeb8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 14 Aug 2008 10:58:28 +0000 Subject: Bugfix: Compressed font/bitmap loading. svn-id: r33862 --- gui/ThemeRenderer.cpp | 4 ++-- gui/theme.cpp | 4 ++-- gui/themes/scummodern.zip | Bin 87340 -> 34925 bytes 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index f323807903..5ead02ae9a 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -182,7 +182,7 @@ void ThemeRenderer::unloadTheme() { for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) ImageMan.unregisterSurface(i->_key); - ImageMan.remArchive(_themeFileName + ".zip"); + ImageMan.remArchive(_themeFileName); _themeEval->reset(); _themeOk = false; @@ -358,7 +358,7 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - ImageMan.addArchive(fileName + ".zip"); + ImageMan.addArchive(fileName); } if (fileName == "builtin") { diff --git a/gui/theme.cpp b/gui/theme.cpp index 3e77919ba9..45fc047c45 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -43,7 +43,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { return font; #ifdef USE_ZLIB - unzFile zipFile = unzOpen((getThemeFileName() + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName()).c_str()); if (zipFile && unzLocateFile(zipFile, cacheFilename.c_str(), 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); @@ -73,7 +73,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { #ifdef USE_ZLIB if (!font) { - unzFile zipFile = unzOpen((getThemeFileName() + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName()).c_str()); if (zipFile && unzLocateFile(zipFile, filename, 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index bbd750a1fa..e12c89830b 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 4368e8132f2caefe886bce595731c67ea16855ad Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 14 Aug 2008 11:26:24 +0000 Subject: Several GFX tweaks/fixes. svn-id: r33863 --- gui/ThemeRenderer.cpp | 12 +++++------- gui/ThemeRenderer.h | 4 ++-- gui/themes/scummodern.zip | Bin 34925 -> 69091 bytes 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 5ead02ae9a..80e605ac85 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -53,7 +53,7 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, - {kDDButtonIdle, "button_idle", true, kDDNone}, + {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider}, {kDDButtonHover, "button_hover", false, kDDButtonIdle}, {kDDButtonDisabled, "button_disabled", true, kDDNone}, @@ -503,7 +503,7 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic } void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { + bool ellipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { if (_texts[type] == 0) return; @@ -517,6 +517,7 @@ void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Comm q.alignV = alignV; q.restoreBg = restoreBg; q.deltax = deltax; + q.ellipsis = ellipsis; if (_buffering) { _textQueue.push_back(q); @@ -565,7 +566,7 @@ void ThemeRenderer::drawDDText(const DrawQueueText &q) { restoreBackground(q.area); _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); - _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax, q.elipsis); + _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax, q.ellipsis); addDirtyRect(q.area); } @@ -743,9 +744,6 @@ void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface & return; queueBitmap(&surface, r, themeTrans); - -// _vectorRenderer->blitSubSurface(&surface, r); -// addDirtyRect(r); } void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { @@ -800,7 +798,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { if (!ready()) - return; + return; if (inverted) { queueDD(kDDTextSelectionBackground, r); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 4fe968752c..2b77121da0 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -94,7 +94,7 @@ protected: friend class GUI::GuiObject; /** Constant value to expand dirty rectangles, to make sure they are fully copied */ - static const int kDirtyRectangleThreshold = 0; + static const int kDirtyRectangleThreshold = 1; /** Sets whether backcaching is enabled */ static const bool kEnableBackCaching = true; @@ -193,7 +193,7 @@ protected: GUI::Theme::TextAlign alignH; GUI::Theme::TextAlignVertical alignV; - bool elipsis; + bool ellipsis; bool restoreBg; int deltax; }; diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index e12c89830b..66e0a736e8 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From 8eaa982c41a083337aa512f1d303b178d25f6a2a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 14 Aug 2008 18:43:27 +0000 Subject: Added Classic Theme - WIP (yes, it's working). Added Builtin theme back. Added Python script to automatically build themes. svn-id: r33868 --- graphics/VectorRenderer.cpp | 74 +- graphics/VectorRenderer.h | 7 +- gui/ThemeEval.cpp | 4 + gui/ThemeParser.cpp | 4 - gui/ThemeParser.h | 1 - gui/ThemeRenderer.cpp | 18 +- gui/themebrowser.cpp | 2 +- gui/themes/default.inc | 544 ++++---- gui/themes/makedeftheme.py | 26 - gui/themes/scummclassic.zip | Bin 0 -> 28291 bytes gui/themes/scummclassic/THEMERC | 1 + gui/themes/scummclassic/classic_gfx.stx | 360 +++++ gui/themes/scummclassic/classic_layout.stx | 730 +++++++++++ gui/themes/scummodern.stx | 1585 ----------------------- gui/themes/scummodern.zip | Bin 69091 -> 122557 bytes gui/themes/scummodern/THEMERC | 1 + gui/themes/scummodern/checkbox.bmp | Bin 0 -> 774 bytes gui/themes/scummodern/cursor.bmp | Bin 0 -> 3126 bytes gui/themes/scummodern/cursor_small.bmp | Bin 0 -> 1062 bytes gui/themes/scummodern/helvr12-l1.fcc | Bin 0 -> 5615 bytes gui/themes/scummodern/logo.bmp | Bin 0 -> 68214 bytes gui/themes/scummodern/scummodern_gfx.stx | 464 +++++++ gui/themes/scummodern/scummodern_layout.stx | 602 +++++++++ gui/themes/scummodern/scummodern_layout_320.stx | 579 +++++++++ gui/themes/scummtheme.py | 87 ++ 25 files changed, 3193 insertions(+), 1896 deletions(-) delete mode 100644 gui/themes/makedeftheme.py create mode 100644 gui/themes/scummclassic.zip create mode 100644 gui/themes/scummclassic/THEMERC create mode 100644 gui/themes/scummclassic/classic_gfx.stx create mode 100644 gui/themes/scummclassic/classic_layout.stx delete mode 100644 gui/themes/scummodern.stx create mode 100644 gui/themes/scummodern/THEMERC create mode 100644 gui/themes/scummodern/checkbox.bmp create mode 100644 gui/themes/scummodern/cursor.bmp create mode 100644 gui/themes/scummodern/cursor_small.bmp create mode 100644 gui/themes/scummodern/helvr12-l1.fcc create mode 100644 gui/themes/scummodern/logo.bmp create mode 100644 gui/themes/scummodern/scummodern_gfx.stx create mode 100644 gui/themes/scummodern/scummodern_layout.stx create mode 100644 gui/themes/scummodern/scummodern_layout_320.stx create mode 100644 gui/themes/scummtheme.py diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 17a221a725..16797fa930 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -477,7 +477,7 @@ template void VectorRendererSpec:: drawRoundedSquare(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0) + w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0) return; if ((r << 1) > w || (r << 1) > h) @@ -527,6 +527,13 @@ drawTab(int x, int y, int r, int w, int h) { if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h) return; + + if (r == 0 && Base::_bevel > 0) { + drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); + return; + } + + if (r == 0) return; switch (Base::_fillMode) { case kFillDisabled: @@ -696,6 +703,51 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } } + +/** BEVELED TABS FOR CLASSIC THEME **/ +template +void VectorRendererSpec:: +drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) { + int pitch = Base::surfacePitch(); + int i, j; + + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + + i = bevel; + while (i--) { + colorFill(ptr_left, ptr_left + w, top_color); + ptr_left += pitch; + } + + if (baseLeft > 0) { + i = h - bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + while (i--) { + colorFill(ptr_left, ptr_left + bevel, top_color); + ptr_left += pitch; + } + } + + i = h - bevel; + j = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); + while (i--) { + colorFill(ptr_left + j, ptr_left + bevel, bottom_color); + if (j > 0) j--; + ptr_left += pitch; + } + + i = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel); + while (i--) { + colorFill(ptr_left, ptr_left + baseRight + bevel, bottom_color); + + if (baseLeft) + colorFill(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color); + ptr_left += pitch; + } +} + /** SQUARE ALGORITHM **/ template void VectorRendererSpec:: @@ -732,10 +784,26 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillM /** SQUARE ALGORITHM **/ template void VectorRendererSpec:: -drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color) { - PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); +drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) { int pitch = Base::surfacePitch(); + + int height = h; + PixelType *ptr_fill = (PixelType *)_activeSurface->getBasePtr(x, y); + + if (fill) { + while (height--) { + blendFill(ptr_fill, ptr_fill + w, _bgColor, 200); + ptr_fill += pitch; + } + } + int i, j; + x = MAX(x - bevel, 0); + y = MAX(y - bevel, 0); + h += bevel << 1; + w += bevel << 1; + + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); i = bevel; while (i--) { diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 34c9c2c8a5..0407028556 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -405,7 +405,7 @@ public: 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.extraData); + drawBeveledSquare(x, y, w, h, _bevel); } void drawCallback_TAB(const Common::Rect &area, const DrawStep &step) { @@ -599,7 +599,7 @@ public: void drawTab(int x, int y, int r, int w, int h); void drawBeveledSquare(int x, int y, int w, int h, int bevel) { - drawBevelSquareAlg(x, y, w, h, bevel, _fgColor, _bgColor); + drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled); } void drawString(const Graphics::Font *font, const Common::String &text, @@ -860,8 +860,9 @@ protected: virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); virtual void drawTriangleFast(int x, int y, int size, bool inverted, PixelType color, FillMode fill_m); - virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color); + virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill); virtual void drawTabAlg(int x, int y, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft = 0, int baseRight = 0); + virtual void drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType topColor, PixelType bottomColor, int baseLeft = 0, int baseRight = 0); /** * SHADOW DRAWING ALGORITHMS diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index f93706cb47..2d8290ffa8 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -139,6 +139,8 @@ void ThemeLayoutVertical::reflowLayout() { _h += _children[i]->getHeight() + _spacing; } } + + _h -= _spacing; } void ThemeLayoutHorizontal::reflowLayout() { @@ -198,6 +200,8 @@ void ThemeLayoutHorizontal::reflowLayout() { _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); } + + _w -= _spacing; } ThemeEval::~ThemeEval() { diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 3167f94009..6972d89b6f 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -375,10 +375,6 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst } } - if (functionName == "bevelsq") { - __PARSER_ASSIGN_INT(extraData, "bevel", true); - } - if (functionName == "triangle") { drawstep->extraData = VectorRenderer::kTriangleUp; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index e4821ef00f..5c6ecd6649 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -150,7 +150,6 @@ protected: XML_PROP(gradient_factor, false) XML_PROP(bevel_color, false) XML_PROP(fill, false) - XML_PROP(bevel, false) XML_PROP(radius, false) XML_PROP(width, false) XML_PROP(height, false) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 80e605ac85..f018910944 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -37,6 +37,8 @@ #include "gui/ThemeEval.h" #include "graphics/VectorRenderer.h" +#define GUI_ENABLE_BUILTIN_THEME + namespace GUI { using namespace Graphics; @@ -401,6 +403,9 @@ bool ThemeRenderer::loadDefaultXML() { if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) return false; + + _themeName = "ScummVM Classic Theme (Builtin Version)"; + _themeFileName = "builtin"; return parser()->parse(); #else @@ -541,9 +546,9 @@ void ThemeRenderer::queueBitmap(const Graphics::Surface *bitmap, const Common::R void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { Common::Rect extendedRect = q.area; - extendedRect.grow(kDirtyRectangleThreshold); - extendedRect.right += _widgets[q.type]->_backgroundOffset; - extendedRect.bottom += _widgets[q.type]->_backgroundOffset; + extendedRect.grow(kDirtyRectangleThreshold + _widgets[q.type]->_backgroundOffset); +// extendedRect.right += _widgets[q.type]->_backgroundOffset; +// extendedRect.bottom += _widgets[q.type]->_backgroundOffset; if (restore) restoreBackground(extendedRect); @@ -584,8 +589,11 @@ void ThemeRenderer::calcBackgroundOffset(DrawData type) { uint maxShadow = 0; for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); step != _widgets[type]->_steps.end(); ++step) { - if (((*step).autoWidth || (*step).autoHeight) && (*step).shadow > maxShadow) - maxShadow = (*step).shadow; + if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow) + maxShadow = step->shadow; + + if (step->drawingCall == &Graphics::VectorRenderer::drawCallback_BEVELSQ && step->bevel > maxShadow) + maxShadow = step->bevel; } _widgets[type]->_backgroundOffset = maxShadow; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 2f1ab48f2d..490248619b 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -91,7 +91,7 @@ void ThemeBrowser::updateListing() { // classic is always build in Entry th; - th.name = "ScummVM Modern Theme (Builtin Version)"; + th.name = "ScummVM Classic Theme (Builtin Version)"; th.file = "builtin"; _themes.push_back(th); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 262260a7fc..d87a1f5632 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1,137 +1,101 @@ " " " " -" " -" " -" " -" " -" " -" " " " -" " -" " +" " +" " " " -" " -" " -" " -" " " " " " " " " " " " " " " " " " " " -" " +" " " " " " " " " " " " " " " " -" " " " " " " " " " " " -" " " " " " -" " " " " " -" " " " " " -" " " " " " " " -" " " " " " " " -" " " " " " " " @@ -178,62 +136,50 @@ "horizontal_align = 'center' " "/> " " " " " " " -" " " " " " -" " +" " +" " +" " " " " " -" " " " " " -" " +" " +" " +" " " " " " -" " " " " " " " -" " " " " " " " -" " +" " +" " +" " " " " " " " " " " " -" " " " " " @@ -299,15 +238,9 @@ "vertical_align = 'center' " "horizontal_align = 'center' " "/> " -" " " " " " @@ -315,17 +248,9 @@ "vertical_align = 'center' " "horizontal_align = 'center' " "/> " -" " " " " " @@ -333,12 +258,9 @@ "vertical_align = 'center' " "horizontal_align = 'center' " "/> " -" " " " " " @@ -346,13 +268,9 @@ "vertical_align = 'top' " "horizontal_align = 'left' " "/> " -" " " " " " @@ -360,15 +278,9 @@ "vertical_align = 'top' " "horizontal_align = 'left' " "/> " -" " " " " " @@ -376,66 +288,70 @@ "vertical_align = 'top' " "horizontal_align = 'left' " "/> " -" " " " " " -" " " " " " " " " " -" " " " " " " " +" " +" " +" " " " -" " -" " -" " -" " -" " " " -" " -" " -" " " " -" " -" " +" " +" " +" " +" " +" " +" " +" " " " " " +" " +" " " " -" " +" " -" " " " +" " " " +" " " " " " " " -" " -" " -" " -" " +" " +" " " " " " -" " +" " " " -" " -" " -" " -" " -" " +" " +" " " " " " " " -" " -" " +" " +" " +" " " " -" " -" " +" " -" " -" " -" " " " " " " " -" " -" " +" " +" " " " -" " -" " +" " +" " " " " " " " " " -" " +" " +" " " " " " " " " " " " " " @@ -575,6 +501,43 @@ " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " " " " " @@ -689,7 +652,8 @@ "type = 'Slider' " "/> " " " " " " " @@ -720,6 +684,14 @@ "height = 'Globals.Line.Height' " "/> " " " +" " +" " +" " +" " " " " " " " @@ -751,6 +723,20 @@ " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " " " " " " " " " " " " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " diff --git a/gui/themes/makedeftheme.py b/gui/themes/makedeftheme.py deleted file mode 100644 index c2ece4c26b..0000000000 --- a/gui/themes/makedeftheme.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -import sys -import re - -def main(): - theme_file = open(sys.argv[1], "r") - def_file = open("default.inc", "w") - comm = re.compile("\/\*(.*?)\*\/", re.DOTALL) - - try: - output = "" - for line in theme_file: - output += line.rstrip("\r\n\t ").lstrip() + " \n" - - output = re.sub(comm, "", output).replace("\t", " ").replace(" ", " ").splitlines() - - for line in output: - if line and not line.isspace(): - def_file.write("\"" + line + "\"\n") - finally: - theme_file.close() - def_file.close() - -if __name__ == "__main__": - sys.exit(main()) diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip new file mode 100644 index 0000000000..653f789baf Binary files /dev/null and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC new file mode 100644 index 0000000000..df6c0508b2 --- /dev/null +++ b/gui/themes/scummclassic/THEMERC @@ -0,0 +1 @@ +[SCUMMVM_THEME_V23:ScummVM Classic Theme:No Author] \ No newline at end of file diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx new file mode 100644 index 0000000000..66c442066d --- /dev/null +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -0,0 +1,360 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* TODO */ + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx new file mode 100644 index 0000000000..bfb09a511b --- /dev/null +++ b/gui/themes/scummclassic/classic_layout.stx @@ -0,0 +1,730 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummodern.stx b/gui/themes/scummodern.stx deleted file mode 100644 index 5399ed62f0..0000000000 --- a/gui/themes/scummodern.stx +++ /dev/null @@ -1,1585 +0,0 @@ -/* 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$ - * - */ - -/* ScummVM Theme XML file */ -/* Modern Theme */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 66e0a736e8..1cd8471709 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/THEMERC b/gui/themes/scummodern/THEMERC new file mode 100644 index 0000000000..d11c959867 --- /dev/null +++ b/gui/themes/scummodern/THEMERC @@ -0,0 +1 @@ +[SCUMMVM_THEME_V23:ScummVM Modern Theme:No Author] \ No newline at end of file diff --git a/gui/themes/scummodern/checkbox.bmp b/gui/themes/scummodern/checkbox.bmp new file mode 100644 index 0000000000..a0b91b569f Binary files /dev/null and b/gui/themes/scummodern/checkbox.bmp differ diff --git a/gui/themes/scummodern/cursor.bmp b/gui/themes/scummodern/cursor.bmp new file mode 100644 index 0000000000..e7bdb60cad Binary files /dev/null and b/gui/themes/scummodern/cursor.bmp differ diff --git a/gui/themes/scummodern/cursor_small.bmp b/gui/themes/scummodern/cursor_small.bmp new file mode 100644 index 0000000000..5f25f32f1a Binary files /dev/null and b/gui/themes/scummodern/cursor_small.bmp differ diff --git a/gui/themes/scummodern/helvr12-l1.fcc b/gui/themes/scummodern/helvr12-l1.fcc new file mode 100644 index 0000000000..651a25934a Binary files /dev/null and b/gui/themes/scummodern/helvr12-l1.fcc differ diff --git a/gui/themes/scummodern/logo.bmp b/gui/themes/scummodern/logo.bmp new file mode 100644 index 0000000000..659ec47d03 Binary files /dev/null and b/gui/themes/scummodern/logo.bmp differ diff --git a/gui/themes/scummodern/scummodern_gfx.stx b/gui/themes/scummodern/scummodern_gfx.stx new file mode 100644 index 0000000000..672d3915e2 --- /dev/null +++ b/gui/themes/scummodern/scummodern_gfx.stx @@ -0,0 +1,464 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx new file mode 100644 index 0000000000..808004ab66 --- /dev/null +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -0,0 +1,602 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx new file mode 100644 index 0000000000..07ea81371f --- /dev/null +++ b/gui/themes/scummodern/scummodern_layout_320.stx @@ -0,0 +1,579 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py new file mode 100644 index 0000000000..202372cfea --- /dev/null +++ b/gui/themes/scummtheme.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# encoding: utf-8 +import sys +import re +import os +import zipfile + +def buildTheme(themeName): + if not os.path.isdir(themeName): + print "Invalid theme name: " + themeName + return + + zf = zipfile.ZipFile(themeName + ".zip", 'w') + + print "Building '" + themeName + "' theme:" + os.chdir(themeName) + + for filename in os.listdir('.'): + if os.path.isfile(filename) and not filename[0] == '.': + zf.write(filename, './' + filename) + print " Adding file: " + filename + + os.chdir('../') + + zf.close() + +def buildAllThemes(): + for f in os.listdir('.'): + if os.path.isdir(os.path.join('.', f)) and not f[0] == '.': + buildTheme(f) + +def parseSTX(theme_file, def_file): + comm = re.compile("\/\*(.*?)\*\/", re.DOTALL) + + output = "" + for line in theme_file: + output += line.rstrip("\r\n\t ").lstrip() + " \n" + + output = re.sub(comm, "", output).replace("\t", " ").replace(" ", " ").replace("\"", "'").splitlines() + + for line in output: + if line and not line.isspace(): + def_file.write("\"" + line + "\"\n") + +def buildDefTheme(themeName): + def_file = open("default.inc", "w") + + if not os.path.isdir(themeName): + print "Cannot open default theme dir." + + for filename in os.listdir(themeName): + filename = os.path.join(themeName, filename) + if os.path.isfile(filename) and filename.endswith(".stx"): + theme_file = open(filename, "r") + parseSTX(theme_file, def_file) + theme_file.close() + + def_file.close() + +def printUsage(): + print "===============================" + print "ScummVM Theme Generation Script" + print "===============================" + print "Usage:" + print "scummtheme.py makeall" + print " Builds all the available themes.\n" + print "scummtheme.py make [themename]" + print " Builds the theme called 'themename'.\n" + print "scummtheme.py default [themename]" + print " Creates a 'default.inc' file to embed the given theme in the source code.\n" + +def main(): + + if len(sys.argv) == 2 and sys.argv[1] == "makeall": + buildAllThemes() + + elif len(sys.argv) == 3 and sys.argv[1] == "make": + buildTheme(sys.argv[2]) + + elif len(sys.argv) == 3 and sys.argv[1] == "default": + buildDefTheme(sys.argv[2]) + + else: + printUsage() + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.2.3 From 8e60e6c558be96286ad8df3502c69060f9db117c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 14 Aug 2008 23:17:41 +0000 Subject: Misc GFX tweaks. svn-id: r33883 --- gui/TabWidget.h | 5 +++++ gui/launcher.cpp | 3 ++- gui/newgui.cpp | 2 +- gui/options.cpp | 10 +++++++--- gui/options.h | 4 ++++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/gui/TabWidget.h b/gui/TabWidget.h index bf316a7ac3..3dffcd2afe 100644 --- a/gui/TabWidget.h +++ b/gui/TabWidget.h @@ -85,6 +85,11 @@ public: * Widgets are always added to the active tab. */ void setActiveTab(int tabID); + + void setTabTitle(int tabID, const String &title) { + assert(0 <= tabID && tabID < (int)_tabs.size()); + _tabs[tabID].title = title; + } virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual bool handleKeyDown(Common::KeyState state); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index d1187a4ad5..e056b60f02 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -195,7 +195,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 3) The graphics tab // - tab->addTab("Graphics"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); @@ -257,6 +257,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // Activate the first tab tab->setActiveTab(0); + _tabWidget = tab; // Add OK & Cancel buttons new ButtonWidget(this, "GameOptions.Cancel", "Cancel", kCloseCmd, 0); diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 945c944b93..2fa0dc8620 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -94,7 +94,7 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), if (themefile.compareToIgnoreCase("default") == 0) themefile = "builtin"; - if (!themefile.hasSuffix(".zip")) + if (themefile != "builtin" && !themefile.hasSuffix(".zip")) themefile += ".zip"; loadNewTheme(themefile); diff --git a/gui/options.cpp b/gui/options.cpp index 590b0bd900..6377bd6377 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -73,12 +73,12 @@ static const int outputRateValues[] = { 0, 22050, 8000, 11025, 44100, 48000, -1 OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h) - : Dialog(x, y, w, h), _domain(domain) { + : Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _tabWidget(0) { init(); } OptionsDialog::OptionsDialog(const String &domain, const String &name) - : Dialog(name), _domain(domain) { + : Dialog(name), _domain(domain), _graphicsTabId(-1), _tabWidget(0) { init(); } @@ -644,6 +644,9 @@ void OptionsDialog::reflowLayout() { Dialog::reflowLayout(); int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); + + if (_graphicsTabId != -1 && _tabWidget) + _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); if (_midiPopUp) _midiPopUp->changeLabelWidth(labelWidth); @@ -667,7 +670,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // // 1) The graphics tab // - tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); addGraphicControls(tab, "GlobalOptions_Graphics."); // @@ -735,6 +738,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // Activate the first tab tab->setActiveTab(0); + _tabWidget = tab; // Add OK & Cancel buttons new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0); diff --git a/gui/options.h b/gui/options.h index 8f4496c753..af13663b29 100644 --- a/gui/options.h +++ b/gui/options.h @@ -26,6 +26,7 @@ #define OPTIONS_DIALOG_H #include "gui/dialog.h" +#include "gui/TabWidget.h" #include "common/str.h" #ifdef SMALL_SCREEN_DEVICE @@ -80,6 +81,9 @@ protected: void setMIDISettingsState(bool enabled); void setVolumeSettingsState(bool enabled); void setSubtitleSettingsState(bool enabled); + + TabWidget *_tabWidget; + int _graphicsTabId; private: // -- cgit v1.2.3 From 1b0c29cb015e00d26db44391f994867f15d26f53 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 11:05:25 +0000 Subject: Added popup widget in Options menu to change GUI renderer on the fly. svn-id: r33898 --- gui/ThemeRenderer.cpp | 8 +++++++- gui/ThemeRenderer.h | 6 +++++- gui/newgui.cpp | 17 ++++++++++++----- gui/newgui.h | 4 +++- gui/options.cpp | 16 +++++++++++++++- gui/options.h | 2 +- gui/theme.h | 1 + gui/themes/default.inc | 3 +++ gui/themes/scummclassic.zip | Bin 28291 -> 28494 bytes gui/themes/scummclassic/classic_layout.stx | 3 +++ gui/themes/scummodern.zip | Bin 122557 -> 123017 bytes gui/themes/scummodern/scummodern_layout.stx | 3 +++ gui/themes/scummodern/scummodern_layout_320.stx | 3 +++ gui/themes/scummtheme.py | 2 +- 14 files changed, 57 insertions(+), 11 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index f018910944..f33e152630 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -43,6 +43,12 @@ namespace GUI { using namespace Graphics; +const char *ThemeRenderer::rendererModeLabels[] = { + "Disabled GFX", + "Stardard Renderer (16bpp)", + "Antialiased Renderer (16bpp)" +}; + const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, {kDDSpecialColorBackground, "special_bg", true, kDDNone}, @@ -256,7 +262,7 @@ void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { break; default: - return; + error("Invalid graphics mode"); } freeRenderer(); diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h index 2b77121da0..e8f6d76ee2 100644 --- a/gui/ThemeRenderer.h +++ b/gui/ThemeRenderer.h @@ -212,9 +212,12 @@ public: enum GraphicsMode { kGfxDisabled = 0, /** No GFX */ kGfxStandard16bit, /** 2BPP with the standard (aliased) renderer. */ - kGfxAntialias16bit /** 2BPP with the optimized AA renderer. */ + kGfxAntialias16bit, /** 2BPP with the optimized AA renderer. */ + kGfxMAX }; + static const char *rendererModeLabels[]; + /** Default constructor */ ThemeRenderer(Common::String fileName, GraphicsMode mode); @@ -487,6 +490,7 @@ protected: const Common::String &getThemeName() const { return _themeName; } const Common::String &getThemeFileName() const { return _themeFileName; } + int getThemeRenderer() const { return _graphicsMode; } /** * Initializes the drawing screen surfaces, _screen and _backBuffer. diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 2fa0dc8620..d90431503d 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -58,8 +58,6 @@ void GuiObject::reflowLayout() { if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { warning("Could not load widget position for '%s'", _name.c_str()); } - - return; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); @@ -96,8 +94,11 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), if (themefile != "builtin" && !themefile.hasSuffix(".zip")) themefile += ".zip"; + + ConfMan.registerDefault("gui_renderer", 2); + ThemeRenderer::GraphicsMode gfxMode = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); - loadNewTheme(themefile); + loadNewTheme(themefile, gfxMode); _themeChange = false; } @@ -105,8 +106,14 @@ NewGui::~NewGui() { delete _theme; } -bool NewGui::loadNewTheme(const Common::String &filename) { +bool NewGui::loadNewTheme(const Common::String &filename, ThemeRenderer::GraphicsMode gfx) { + if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getThemeRenderer()) + return true; + Common::String oldTheme = (_theme != 0) ? _theme->getThemeFileName() : ""; + + if (gfx == ThemeRenderer::kGfxDisabled) + gfx = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); if (_theme) _theme->disable(); @@ -119,7 +126,7 @@ bool NewGui::loadNewTheme(const Common::String &filename) { delete _theme; _theme = 0; - _theme = new ThemeRenderer(filename, GUI::ThemeRenderer::kGfxAntialias16bit); + _theme = new ThemeRenderer(filename, gfx); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); diff --git a/gui/newgui.h b/gui/newgui.h index b7ef589f07..cc9e6b9f3c 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -33,6 +33,8 @@ #include "gui/theme.h" #include "gui/widget.h" +#include "gui/ThemeRenderer.h" + class OSystem; namespace GUI { @@ -76,7 +78,7 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(const Common::String &file); + bool loadNewTheme(const Common::String &file, ThemeRenderer::GraphicsMode gfx = ThemeRenderer::kGfxDisabled); Theme *theme() { return _theme; } ThemeEval *xmlEval() { return _theme->evaluator(); } diff --git a/gui/options.cpp b/gui/options.cpp index 6377bd6377..05b0f790a2 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -724,9 +724,16 @@ GlobalOptionsDialog::GlobalOptionsDialog() new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0); _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); - + + _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.Renderer", "GUI Renderer:", labelWidth); + + for (int i = 1; i < GUI::ThemeRenderer::kGfxMAX; ++i) { + _rendererPopUp->appendEntry(GUI::ThemeRenderer::rendererModeLabels[i], i); + } + _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth); for (int i = 0; savePeriodLabels[i]; i++) { @@ -799,6 +806,8 @@ void GlobalOptionsDialog::open() { if (value == savePeriodValues[i]) _autosavePeriodPopUp->setSelected(i); } + + _rendererPopUp->setSelected(ConfMan.getInt("gui_renderer") - 1); } void GlobalOptionsDialog::close() { @@ -828,6 +837,11 @@ void GlobalOptionsDialog::close() { #endif ConfMan.setInt("autosave_period", _autosavePeriodPopUp->getSelectedTag(), _domain); + + if ((int)_rendererPopUp->getSelectedTag() != ConfMan.getInt("gui_renderer")) { + g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), (GUI::ThemeRenderer::GraphicsMode)_rendererPopUp->getSelectedTag()); + ConfMan.setInt("gui_renderer", _rendererPopUp->getSelectedTag(), _domain); + } } OptionsDialog::close(); } diff --git a/gui/options.h b/gui/options.h index af13663b29..39f2918ce2 100644 --- a/gui/options.h +++ b/gui/options.h @@ -170,7 +170,7 @@ protected: // Misc controls // StaticTextWidget *_curTheme; - + PopUpWidget *_rendererPopUp; PopUpWidget *_autosavePeriodPopUp; }; diff --git a/gui/theme.h b/gui/theme.h index 4c1ab2e195..f4709067ef 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -310,6 +310,7 @@ public: virtual const Common::String &getThemeFileName() const = 0; virtual const Common::String &getThemeName() const = 0; + virtual int getThemeRenderer() const = 0; /** * Checks if the theme renderer supports drawing of images. diff --git a/gui/themes/default.inc b/gui/themes/default.inc index d87a1f5632..55d1211e24 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -704,6 +704,9 @@ "height = 'Globals.Line.Height' " "/> " " " +" " " " diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index 653f789baf..334d2a2274 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index bfb09a511b..e404aa37da 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -456,6 +456,9 @@ height = 'Globals.Line.Height' /> + diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 1cd8471709..3c68cc7df3 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx index 808004ab66..4d7d07c51b 100644 --- a/gui/themes/scummodern/scummodern_layout.stx +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -343,6 +343,9 @@ height = 'Globals.Line.Height' /> + diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx index 07ea81371f..a84fa97cd7 100644 --- a/gui/themes/scummodern/scummodern_layout_320.stx +++ b/gui/themes/scummodern/scummodern_layout_320.stx @@ -325,6 +325,9 @@ height = 'Globals.Line.Height' /> + diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py index 202372cfea..da0b88cf61 100644 --- a/gui/themes/scummtheme.py +++ b/gui/themes/scummtheme.py @@ -6,7 +6,7 @@ import os import zipfile def buildTheme(themeName): - if not os.path.isdir(themeName): + if not os.path.isdir(themeName) or not os.path.isfile(os.path.join(themeName, "THEMERC")): print "Invalid theme name: " + themeName return -- cgit v1.2.3 From 57e2c128df4cfa4674bead48a0ac8640b9c99781 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 13:50:08 +0000 Subject: Bugfix: Cross cursor animation disabled when switching themes/resolutions on the fly. svn-id: r33899 --- gui/ThemeRenderer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index f33e152630..27409d8192 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -208,8 +208,11 @@ void ThemeRenderer::refresh() { init(); if (_enabled) { _system->showOverlay(); - CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + + if (_useCursor) { + CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + } } } @@ -374,7 +377,7 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { error("Could not load default embeded theme"); } else if (!loadThemeXML(fileName)) { - warning("Could not parse custom theme '%s'.\nFalling back to default theme", fileName.c_str()); + warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str()); if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure error("Could not load default embeded theme"); -- cgit v1.2.3 From 784c1114cc07363359d1e8ae7d12152157b7983b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 16:44:44 +0000 Subject: Deprecated support for "direction" layout keys. svn-id: r33904 --- engines/scumm/dialogs.cpp | 13 +- gui/ThemeEval.cpp | 52 +- gui/ThemeEval.h | 11 +- gui/ThemeParser.cpp | 8 +- gui/ThemeParser.h | 1 - gui/themes/default.inc | 790 ++++++++++++++++++------ gui/themes/scummclassic.zip | Bin 28494 -> 40155 bytes gui/themes/scummclassic/classic_layout.stx | 284 +++------ gui/themes/scummodern.zip | Bin 123017 -> 122543 bytes gui/themes/scummodern/scummodern_layout.stx | 157 +++-- gui/themes/scummodern/scummodern_layout_320.stx | 145 ++--- 11 files changed, 860 insertions(+), 601 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 6a4ab4bd3c..e1fe3cfeed 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -645,6 +645,7 @@ HelpDialog::HelpDialog(const GameSettings &game) _title = new StaticTextWidget(this, "ScummHelp.Title", ""); _page = 1; + _backgroundType = GUI::Theme::kDialogBackgroundDefault; _numPages = ScummHelp::numPages(_game.id); @@ -655,8 +656,8 @@ HelpDialog::HelpDialog(const GameSettings &game) // Dummy entries for (int i = 0; i < HELP_NUM_LINES; i++) { - _key[i] = new StaticTextWidget(this, 0, 0, 10, 10, "", kTextAlignLeft); - _dsc[i] = new StaticTextWidget(this, 0, 0, 10, 10, "", kTextAlignLeft); + _key[i] = new StaticTextWidget(this, 0, 0, 10, 10, "", Graphics::kTextAlignRight); + _dsc[i] = new StaticTextWidget(this, 0, 0, 10, 10, "", Graphics::kTextAlignLeft); } } @@ -671,12 +672,14 @@ void HelpDialog::reflowLayout() { g_gui.xmlEval()->getWidgetData("ScummHelp.HelpText", x, y, w, h); int keyW = w * 20 / 100; - int dscX = x + keyW; + int dscX = x + keyW + 32; int dscW = w * 80 / 100; + + int xoff = (_w >> 1) - (w >> 1); for (int i = 0; i < HELP_NUM_LINES; i++) { - _key[i]->resize(x, y + lineHeight * i, keyW, lineHeight + 2); - _dsc[i]->resize(dscX, y + lineHeight * i, dscW, lineHeight + 2); + _key[i]->resize(xoff + x, y + lineHeight * i, keyW, lineHeight + 2); + _dsc[i]->resize(xoff + dscX, y + lineHeight * i, dscW, lineHeight + 2); } displayKeyBindings(); diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 2d8290ffa8..ecf48e71b4 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -65,9 +65,6 @@ void ThemeLayoutMain::reflowLayout() { _children[0]->setHeight(_h); _children[0]->reflowLayout(); -// _children[0]->setX(_x); -// _children[0]->setY(_y); - if (_w == -1) _w = _children[0]->getWidth(); @@ -109,32 +106,22 @@ void ThemeLayoutVertical::reflowLayout() { _children[i]->setY(curY); - if (_centered && _children[i]->getWidth() < _w) + if (_centered && _children[i]->getWidth() < _w && _w != -1) _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); else _children[i]->setX(curX); - if (_reverse) { - for (int j = i - 1; j >= 0; --j) - _children[j]->setY(_children[i]->getHeight() + _spacing); - } else { - curY += _children[i]->getHeight() + _spacing; - } - + curY += _children[i]->getHeight() + _spacing; _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); if (autoWidget != -1 && autoWidget != (int)i) { _children[autoWidget]->setHeight(_children[autoWidget]->getHeight() - (_children[i]->getHeight() + _spacing)); - if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) + extraHeight -= (_children[i]->getHeight() + _spacing); + _children[i]->setY(extraHeight); + + for (int j = i - 1; j > autoWidget; --j) _children[j]->setY(-(_children[i]->getHeight() + _spacing)); - else { - extraHeight -= (_children[i]->getHeight() + _spacing); - _children[i]->setY(extraHeight); - - for (int j = i - 1; j > autoWidget; --j) - _children[j]->setY(-(_children[i]->getHeight() + _spacing)); - } } else { _h += _children[i]->getHeight() + _spacing; } @@ -170,30 +157,21 @@ void ThemeLayoutHorizontal::reflowLayout() { _children[i]->setX(curX); - if (_centered && _children[i]->getHeight() < _h) + if (_centered && _children[i]->getHeight() < _h && _h != -1) _children[i]->setY((_h >> 1) - (_children[i]->getHeight() >> 1)); else _children[i]->setY(curY); - if (_reverse) { - for (int j = i - 1; j >= 0; --j) - _children[j]->setX(_children[i]->getWidth() + _spacing); - } else { - curX += (_children[i]->getWidth() + _spacing); - } + curX += (_children[i]->getWidth() + _spacing); if (autoWidget != -1 && autoWidget != (int)i) { _children[autoWidget]->setWidth(_children[autoWidget]->getWidth() - (_children[i]->getWidth() + _spacing)); - if (_reverse) for (int j = autoWidget - 1; j >= 0; --j) + autoWidth -= (_children[i]->getWidth() + _spacing); + _children[i]->setX(autoWidth); + + for (int j = i - 1; j > autoWidget; --j) _children[j]->setX(-(_children[i]->getWidth() + _spacing)); - else { - autoWidth -= (_children[i]->getWidth() + _spacing); - _children[i]->setX(autoWidth); - - for (int j = i - 1; j > autoWidget; --j) - _children[j]->setX(-(_children[i]->getWidth() + _spacing)); - } } else { _w += _children[i]->getWidth() + _spacing; } @@ -279,16 +257,16 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over setVar(name + ".Enabled", enabled ? 1 : 0); } -void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center) { +void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool center) { ThemeLayout *layout = 0; if (spacing == -1) spacing = getVar("Globals.Layout.Spacing", 4); if (type == ThemeLayout::kLayoutVertical) - layout = new ThemeLayoutVertical(_curLayout.top(), spacing, reverse, center); + layout = new ThemeLayoutVertical(_curLayout.top(), spacing, center); else if (type == ThemeLayout::kLayoutHorizontal) - layout = new ThemeLayoutHorizontal(_curLayout.top(), spacing, reverse, center); + layout = new ThemeLayoutHorizontal(_curLayout.top(), spacing, center); layout->setPadding( getVar("Globals.Padding.Left", 0), diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index e0c1c5af59..8d55ff6066 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -50,7 +50,7 @@ public: }; ThemeLayout(ThemeLayout *p, const Common::String &name) : - _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), _reverse(false), + _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), _centered(false), _defaultW(-1), _defaultH(-1) { } @@ -185,7 +185,6 @@ protected: int8 _spacing; Common::Array _children; ThemeLayout *_parent; - bool _reverse; bool _centered; Common::String _name; }; @@ -218,10 +217,9 @@ protected: class ThemeLayoutVertical : public ThemeLayout { public: - ThemeLayoutVertical(ThemeLayout *p, int spacing, bool reverse, bool center) : + ThemeLayoutVertical(ThemeLayout *p, int spacing, bool center) : ThemeLayout(p, "") { _spacing = spacing; - _reverse = reverse; _centered = center; } @@ -242,10 +240,9 @@ public: class ThemeLayoutHorizontal : public ThemeLayout { public: - ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool reverse, bool center) : + ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool center) : ThemeLayout(p, "") { _spacing = spacing; - _reverse = reverse; _centered = center; } @@ -337,7 +334,7 @@ public: bool hasVar(const Common::String &name) { return _vars.contains(name) || _builtin.contains(name); } void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true, int inset = 0); - void addLayout(ThemeLayout::LayoutType type, int spacing, bool reverse, bool center = false); + void addLayout(ThemeLayout::LayoutType type, int spacing, bool center = false); void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true); bool addImportedLayout(const Common::String &name); void addSpace(int size); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 6972d89b6f..63fc868ba6 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -600,14 +600,10 @@ bool ThemeParser::parserCallback_layout(ParserNode *node) { } if (node->values["type"] == "vertical") - _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, spacing, - node->values["direction"] == "bottom2top", - node->values["center"] == "true"); + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, spacing, node->values["center"] == "true"); else if (node->values["type"] == "horizontal") - _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, spacing, - node->values["direction"] == "right2left", - node->values["center"] == "true"); + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, spacing, node->values["center"] == "true"); if (node->values.contains("padding")) { int paddingL, paddingR, paddingT, paddingB; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 5c6ecd6649..098bdb0540 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -197,7 +197,6 @@ protected: XML_KEY(layout) XML_PROP(type, true) XML_PROP(center, false) - XML_PROP(direction, false) XML_PROP(padding, false) XML_PROP(spacing, false) diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 55d1211e24..3462b928c8 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -299,24 +299,17 @@ "/> " " " " " -" " +" " " " " " " " " " -" " -" " -" " " " " " " " -" " -" " -" " " " " " " " -" " " " @@ -326,33 +319,18 @@ " " -" " " " " " -" " -" " " " -" " " " -" " " " @@ -373,14 +351,6 @@ "size = '15, 18' " "padding = '0, 3, 4, 0' " "/> " -" " -" " " " " " " " @@ -423,119 +393,41 @@ " " " " " " -" " -" " -" " +" " +" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " +" " +" " +" " " " -" " -" " " " -" " -" " -" " " " " " " " -" " -" " -" " -" " -" " -" " +" " " " -" " -" " -" " -" " -" " -" " -" " +" " " " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " " " -" " -" " " " -" " " " " " " " @@ -567,7 +459,7 @@ "type = 'OptionsLabel' " "/> " " " " " @@ -713,31 +605,17 @@ " " " " " " -" " -" " -" " +" " +" " +" " +" " " " -" " -" " -" " -" " -" " -" " -" " -" " " " -" " -" " " " -" " " " " " " " @@ -776,7 +654,7 @@ " " " " " " " " " " " " " " " " " " -" " -" " -" " -" " -" " -" " -" " +" " " " -" " -" " -" " " " " " -" " -" " +" " " " " " @@ -898,54 +768,69 @@ "/> " " " " " -" " -" " -" " " " " " -" " -" " -" " " " -" " -" " -" " -" " -" " -" " +" " +" " +" " -" " -" " " " -" " -" " +" " +" " +" " +" " +" " +" " +" " " " -" " " " -" " +" " +" " +" " +" " " " " " " " " " -" " +" " +" " +" " " " " " " " -" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " -" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index 334d2a2274..a8d9bf90e6 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index e404aa37da..48c8c181ee 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -23,29 +23,20 @@ * */ - + - - - - - - - - - - - - - - - - - - @@ -110,15 +82,6 @@ size = '15, 18' padding = '0, 3, 4, 0' /> - - - @@ -163,128 +126,45 @@ - - - + + - - - - - - - - - - - - - - - - - - - - + + + + - - + /> - - - - - - - - - + - - - - - - - - + - - - - - - - - - - - - - - - - @@ -466,32 +346,17 @@ - - - + + + + - - - - - - - - - - - - @@ -535,7 +400,7 @@ - - - - - - - + - - - - - + @@ -660,56 +517,71 @@ /> - - - - - - - + + + + + + + - - - - + + + + + + + + - - - - - - - - + - + + + - - \ No newline at end of file diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 3c68cc7df3..09fd31b8ab 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx index 4d7d07c51b..61545d0ffa 100644 --- a/gui/themes/scummodern/scummodern_layout.stx +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -23,7 +23,7 @@ * */ - + @@ -132,46 +132,44 @@ - - - + + + + + + - - + /> - - - - - - + + + + - - - - - - - - + + + + - - - @@ -489,35 +487,27 @@ - - - - - - - + - - - - - + @@ -532,56 +522,71 @@ /> - - - - - - - + + + + + + + - - - - + + + + + + + + - - - - - - - - + - + + + - - \ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx index a84fa97cd7..75dd08a753 100644 --- a/gui/themes/scummodern/scummodern_layout_320.stx +++ b/gui/themes/scummodern/scummodern_layout_320.stx @@ -116,41 +116,43 @@ - - - + + + + + + - - - - - - + /> + - - - + + + + - - - @@ -335,17 +337,17 @@ - - - + + + + - - - @@ -474,35 +476,27 @@ - - - - - - - + - - - - - + @@ -517,48 +511,63 @@ /> - - - - - - - + + + + + + + - - - - + + + + + + - - - - + + - + + + - - -- cgit v1.2.3 From 9fc0a9b31e14092689a1c2a22eb5fc551416e87a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 16:47:03 +0000 Subject: Added missing layout file. svn-id: r33905 --- gui/themes/scummclassic/classic_layout_320.stx | 592 +++++++++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100644 gui/themes/scummclassic/classic_layout_320.stx diff --git a/gui/themes/scummclassic/classic_layout_320.stx b/gui/themes/scummclassic/classic_layout_320.stx new file mode 100644 index 0000000000..9608fad7b8 --- /dev/null +++ b/gui/themes/scummclassic/classic_layout_320.stx @@ -0,0 +1,592 @@ +/* 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$ + * + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 9aaf83df03276cc3428cd392dc6100a2bbe3579d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 17:40:58 +0000 Subject: Added support for automatically resizing more than one widget in a flowing layout. Classic theme launcher now looks ok in g3x. svn-id: r33906 --- gui/ThemeEval.cpp | 74 +++++++++++------------- gui/newgui.cpp | 2 + gui/themes/default.inc | 18 +----- gui/themes/scummclassic.zip | Bin 40155 -> 40072 bytes gui/themes/scummclassic/classic_layout.stx | 7 --- gui/themes/scummclassic/classic_layout_320.stx | 11 +--- gui/themes/scummodern.zip | Bin 122543 -> 122565 bytes gui/themes/scummodern/scummodern_layout_320.stx | 17 +++--- 8 files changed, 47 insertions(+), 82 deletions(-) diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index ecf48e71b4..614f2089d1 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -81,8 +81,8 @@ void ThemeLayoutMain::reflowLayout() { void ThemeLayoutVertical::reflowLayout() { int curX, curY; - int autoWidget = -1; - int extraHeight = 0; + int resize[8]; + int rescount = 0; curX = _paddingLeft; curY = _paddingTop; @@ -97,43 +97,41 @@ void ThemeLayoutVertical::reflowLayout() { _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); if (_children[i]->getHeight() == -1) { - if (autoWidget != -1) - error("Cannot expand automatically two different widgets."); - - autoWidget = i; - _children[i]->setHeight(getParentH() - _h - _spacing); + resize[rescount++] = i; + _children[i]->setHeight(0); } _children[i]->setY(curY); - if (_centered && _children[i]->getWidth() < _w && _w != -1) + if (_centered && _children[i]->getWidth() < _w && _w != -1) { _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); + } else _children[i]->setX(curX); curY += _children[i]->getHeight() + _spacing; _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); - - if (autoWidget != -1 && autoWidget != (int)i) { - _children[autoWidget]->setHeight(_children[autoWidget]->getHeight() - (_children[i]->getHeight() + _spacing)); - - extraHeight -= (_children[i]->getHeight() + _spacing); - _children[i]->setY(extraHeight); - - for (int j = i - 1; j > autoWidget; --j) - _children[j]->setY(-(_children[i]->getHeight() + _spacing)); - } else { - _h += _children[i]->getHeight() + _spacing; - } + _h += _children[i]->getHeight() + _spacing; } _h -= _spacing; + + if (rescount) { + int newh = (getParentH() - _h - _paddingBottom) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setHeight(newh); + _h += newh; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setY(newh); + } + } } void ThemeLayoutHorizontal::reflowLayout() { int curX, curY; - int autoWidget = -1; - int autoWidth = 0; + int resize[8]; + int rescount = 0; curX = _paddingLeft; curY = _paddingTop; @@ -148,11 +146,8 @@ void ThemeLayoutHorizontal::reflowLayout() { _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); if (_children[i]->getWidth() == -1) { - if (autoWidget != -1) - error("Cannot expand automatically two different widgets."); - - autoWidget = i; - _children[i]->setWidth(getParentW() - _w - _spacing); + resize[rescount++] = i; + _children[i]->setWidth(0); } _children[i]->setX(curX); @@ -163,23 +158,22 @@ void ThemeLayoutHorizontal::reflowLayout() { _children[i]->setY(curY); curX += (_children[i]->getWidth() + _spacing); - - if (autoWidget != -1 && autoWidget != (int)i) { - _children[autoWidget]->setWidth(_children[autoWidget]->getWidth() - (_children[i]->getWidth() + _spacing)); - - autoWidth -= (_children[i]->getWidth() + _spacing); - _children[i]->setX(autoWidth); - - for (int j = i - 1; j > autoWidget; --j) - _children[j]->setX(-(_children[i]->getWidth() + _spacing)); - } else { - _w += _children[i]->getWidth() + _spacing; - } - + _w += _children[i]->getWidth() + _spacing; _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); } _w -= _spacing; + + if (rescount) { + int neww = (getParentW() - _w - _paddingRight) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setWidth(neww); + _w += neww; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setX(neww); + } + } } ThemeEval::~ThemeEval() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index d90431503d..c49b3cdb8f 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -58,6 +58,8 @@ void GuiObject::reflowLayout() { if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { warning("Could not load widget position for '%s'", _name.c_str()); } + + return; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 3462b928c8..fd948ab3fa 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -360,34 +360,27 @@ " " " " " " " " " " " " " " " " " " " " " " " " " " @@ -904,34 +897,27 @@ " " " " " " " " " " " " " " " " " " " " " " " " " " @@ -963,7 +949,7 @@ " " " " " " -" " +" " " " " " " " " " -" " +" " " " " diff --git a/gui/themes/scummclassic/classic_layout_320.stx b/gui/themes/scummclassic/classic_layout_320.stx index 9608fad7b8..0a9c84c71b 100644 --- a/gui/themes/scummclassic/classic_layout_320.stx +++ b/gui/themes/scummclassic/classic_layout_320.stx @@ -88,34 +88,27 @@ @@ -150,7 +143,7 @@ - + - + - + @@ -143,7 +140,7 @@ - + - + getWidgetData(_name, _x, _y, _w, _h)) { warning("Could not load widget position for '%s'", _name.c_str()); } - - return; if (_x < 0) error("Widget <%s> has x < 0: %d", _name.c_str(), _x); @@ -425,6 +423,7 @@ void NewGui::screenChange() { // redrawn before redraw() has been called. _redrawStatus = kRedrawFull; redraw(); + _system->updateScreen(); } } // End of namespace GUI -- cgit v1.2.3 From 7c213ab11022ffce603099fe409d44d383ce94e7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 15 Aug 2008 19:10:37 +0000 Subject: Tons of misc. GFX fixes. svn-id: r33911 --- engines/scumm/dialogs.cpp | 5 ++- graphics/VectorRenderer.cpp | 10 ++++-- graphics/VectorRenderer.h | 15 +++++++++ gui/ThemeParser.cpp | 1 + gui/ThemeRenderer.cpp | 9 ++++- gui/newgui.cpp | 1 + gui/options.cpp | 8 ++++- gui/options.h | 1 + gui/themes/default.inc | 5 +++ gui/themes/scummclassic.zip | Bin 40072 -> 40158 bytes gui/themes/scummclassic/classic_gfx.stx | 6 +++- gui/themes/scummclassic/classic_layout.stx | 6 ++-- gui/themes/scummclassic/classic_layout_320.stx | 6 ++-- gui/themes/scummodern.zip | Bin 122565 -> 122840 bytes gui/themes/scummodern/scummodern_gfx.stx | 43 +++++++++++++++--------- gui/themes/scummodern/scummodern_layout_320.stx | 6 ++-- 16 files changed, 91 insertions(+), 31 deletions(-) diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index e1fe3cfeed..8d977719da 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -951,7 +951,10 @@ void SubtitleSettingsDialog::cycleValue() { if (_value > 2) _value = 0; - setInfoText(subtitleDesc[_value]); + if (_value == 1 && g_system->getOverlayWidth() <= 320) + setInfoText("Speech & Subs"); + else + setInfoText(subtitleDesc[_value]); _timer = getMillis() + 1500; } diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 16797fa930..655602ef20 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -370,15 +370,21 @@ drawLine(int x1, int y1, int x2, int y2) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); int pitch = Base::surfacePitch(); + int st = Base::_strokeWidth >> 1; if (dy == 0) { // horizontal lines // these can be filled really fast with a single memset. colorFill(ptr, ptr + dx + 1, (PixelType)_fgColor); + + for (int i = 0, p = pitch; i < st; ++i, p += pitch) { + colorFill(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor); + colorFill(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor); + } } else if (dx == 0) { // vertical lines // these ones use a static pitch increase. while (y1++ <= y2) { - *ptr = (PixelType)_fgColor; + colorFill(ptr - st, ptr + st, (PixelType)_fgColor); ptr += pitch; } @@ -387,7 +393,7 @@ drawLine(int x1, int y1, int x2, int y2) { pitch += (x2 > x1) ? 1 : -1; while (dy--) { - *ptr = (PixelType)_fgColor; + colorFill(ptr - st, ptr + st, (PixelType)_fgColor); ptr += pitch; } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0407028556..bd1bd1db42 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -211,6 +211,15 @@ public: * @param r Radius of the corners of the tab (0 for squared tabs). */ virtual void drawTab(int x, int y, int r, int w, int h) = 0; + + + /** + * Simple helper function to draw a cross. + */ + virtual void drawCross(int x, int y, int w, int h) { + drawLine(x, y, x + w, y + w); + drawLine(x + w, y, x, y + h); + } /** * Gets the pixel pitch for the current drawing surface. @@ -419,6 +428,12 @@ public: stepGetPositions(step, area, x, y, w, h); blitAlphaBitmap(step.blitSrc, Common::Rect(x, y, x + w, y + h)); } + + void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step) { + uint16 x, y, w, h; + stepGetPositions(step, area, x, y, w, h); + drawCross(x, y, w, h); + } void drawCallback_VOID(const Common::Rect &area, const DrawStep &step) {} diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 63fc868ba6..2656f2a898 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -52,6 +52,7 @@ ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { _drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB; _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; _drawFunctions["bitmap"] = &Graphics::VectorRenderer::drawCallback_BITMAP; + _drawFunctions["cross"] = &Graphics::VectorRenderer::drawCallback_CROSS; _defaultStepGlobal = defaultDrawStep(); _defaultStepLocal = 0; diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 27409d8192..c24f8a6d50 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -29,6 +29,7 @@ #include "common/system.h" #include "common/events.h" #include "common/config-manager.h" +#include "common/fs.h" #include "graphics/imageman.h" #include "graphics/cursorman.h" #include "gui/launcher.h" @@ -461,7 +462,7 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { if (parser()->loadStream(stream) == false || parser()->parse() == false) { warning("Failed to load stream for zipped file '%s'", fileNameBuffer); unzClose(zipFile); - delete stream; +// delete stream; return false; } } @@ -474,6 +475,9 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { } } +// FilesystemNode dir(themeName); +// FSList files = dir.listDir(FilesystemNode::kListFilesOnly); + unzClose(zipFile); return (parseCount > 0 && _themeName.empty() == false); #else @@ -705,6 +709,9 @@ void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int slider r2.right -= 1; r2.top += sliderY; r2.bottom = r2.top + sliderHeight - 1; + + r2.top += r.width() / 5; + r2.bottom -= r.width() / 5; queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 82d6b2db91..fc781f731d 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -423,6 +423,7 @@ void NewGui::screenChange() { // redrawn before redraw() has been called. _redrawStatus = kRedrawFull; redraw(); + _system->showOverlay(); _system->updateScreen(); } diff --git a/gui/options.cpp b/gui/options.cpp index 05b0f790a2..c24b338af6 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -88,6 +88,12 @@ const char *OptionsDialog::_subModeDesc[] = { "Subtitles Only" }; +const char *OptionsDialog::_lowresSubModeDesc[] = { + "Speech Only", + "Speech & Subs", + "Subtitles Only" +}; + void OptionsDialog::init() { _enableGraphicSettings = false; _gfxPopUp = 0; @@ -417,7 +423,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data else _subMode = 0; - _subToggleButton->setLabel(_subModeDesc[_subMode]); + _subToggleButton->setLabel(g_system->getOverlayWidth() > 320 ? _subModeDesc[_subMode] : _lowresSubModeDesc[_subMode]); _subToggleButton->draw(); _subSpeedDesc->draw(); _subSpeedSlider->draw(); diff --git a/gui/options.h b/gui/options.h index 39f2918ce2..187e163b79 100644 --- a/gui/options.h +++ b/gui/options.h @@ -122,6 +122,7 @@ private: ButtonWidget *_subToggleButton; int _subMode; static const char *_subModeDesc[]; + static const char *_lowresSubModeDesc[]; StaticTextWidget *_subSpeedDesc; SliderWidget *_subSpeedSlider; StaticTextWidget *_subSpeedLabel; diff --git a/gui/themes/default.inc b/gui/themes/default.inc index fd948ab3fa..ce7fc16cfc 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -282,6 +282,11 @@ "bevel = '2' " "fill = 'none' " "/> " +" " " " " " " -/* TODO */ + diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index 8be91e9de6..005ebb89f3 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -250,12 +250,12 @@ + - + - - + + + + diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx index e545f5f98d..9d689e5c8d 100644 --- a/gui/themes/scummodern/scummodern_layout_320.stx +++ b/gui/themes/scummodern/scummodern_layout_320.stx @@ -245,12 +245,12 @@ + - loadStream(stream) == false || parser()->parse() == false) { warning("Failed to load stream for zipped file '%s'", fileNameBuffer); unzClose(zipFile); -// delete stream; return false; } } @@ -473,16 +473,34 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { if (unzGoToNextFile(zipFile) != UNZ_OK) break; } + } else { +#endif + FilesystemNode node(themeName); + if (node.exists() && node.isReadable() && node.isDirectory()) { + + FSList fslist; + if (!node.getChildren(fslist, FilesystemNode::kListFilesOnly)) + return false; + + for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { + if (i->getName().hasSuffix(".stx")) { + + } else if (i->getName() == "THEMERC") { + + } + + } + + } +#ifdef USE_ZLIB } -// FilesystemNode dir(themeName); -// FSList files = dir.listDir(FilesystemNode::kListFilesOnly); - unzClose(zipFile); - return (parseCount > 0 && _themeName.empty() == false); -#else - return false; + #endif + + + return (parseCount > 0 && _themeName.empty() == false); } bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { -- cgit v1.2.3 From 5201a46054a1390739b21532c45e0e9926b857bc Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 16 Aug 2008 14:06:26 +0000 Subject: Added support for loading uncompressed/unpackaged themes. svn-id: r33941 --- common/xmlparser.h | 16 +++++++++++- gui/ThemeRenderer.cpp | 36 +++++++++++++++++++------- gui/newgui.cpp | 4 +-- gui/theme.cpp | 61 +++++++++++++++++++++++++++----------------- gui/theme.h | 2 +- gui/themebrowser.cpp | 43 +++++++++++++++++++++++-------- gui/themes/scummclassic.zip | Bin 40158 -> 40158 bytes gui/themes/scummodern.zip | Bin 122840 -> 122841 bytes 8 files changed, 115 insertions(+), 47 deletions(-) diff --git a/common/xmlparser.h b/common/xmlparser.h index e3d39bfb82..4d1c8fc85d 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -32,6 +32,7 @@ #include "common/xmlparser.h" #include "common/stream.h" #include "common/file.h" +#include "common/fs.h" #include "common/hashmap.h" #include "common/hash-str.h" @@ -342,7 +343,7 @@ public: * * @param filename Name of the file to load. */ - bool loadFile(Common::String filename) { + bool loadFile(const Common::String &filename) { Common::File *f = new Common::File; if (!f->open(filename)) { @@ -354,6 +355,19 @@ public: _text.loadStream(f); return true; } + + bool loadFile(const FilesystemNode &node) { + Common::File *f = new Common::File; + + if (!f->open(node)) { + delete f; + return false; + } + + _fileName = node.getName(); + _text.loadStream(f); + return true; + } /** * Loads a memory buffer into the parser. diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index 5f12cf3fd4..c272de96f9 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -191,7 +191,10 @@ void ThemeRenderer::unloadTheme() { for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) ImageMan.unregisterSurface(i->_key); - ImageMan.remArchive(_themeFileName); + if (_themeFileName.hasSuffix(".zip")) + ImageMan.remArchive(_themeFileName); + + Common::File::resetDefaultDirectories(); _themeEval->reset(); _themeOk = false; @@ -370,7 +373,10 @@ bool ThemeRenderer::loadTheme(Common::String fileName) { if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - ImageMan.addArchive(fileName); + if (fileName.hasSuffix(".zip")) + ImageMan.addArchive(fileName); + else + Common::File::addDefaultDirectory(fileName); } if (fileName == "builtin") { @@ -429,10 +435,11 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { _themeName.clear(); char fileNameBuffer[32]; + char stxHeader[128]; int parseCount = 0; #ifdef USE_ZLIB - unzFile zipFile = unzOpen(themeName.c_str()); + unzFile zipFile = unzOpen((themeName).c_str()); if (zipFile && unzGoToFirstFile(zipFile) == UNZ_OK) { while (true) { @@ -449,11 +456,12 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); if (!strcmp(fileNameBuffer, "THEMERC")) { - char stxHeader[128]; stream->readLine(stxHeader, 128); - if (!themeConfigParseHeader(stxHeader, _themeName)) - error("Corrupted 'THEMERC' file"); + if (!themeConfigParseHeader(stxHeader, _themeName)) { + warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); + return false; + } delete stream; @@ -484,13 +492,23 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { if (i->getName().hasSuffix(".stx")) { + parseCount++; + if (parser()->loadFile(*i) == false || parser()->parse() == false) { + warning("Failed to parse STX file '%s'", i->getName().c_str()); + return false; + } } else if (i->getName() == "THEMERC") { - + Common::File f; + f.open(*i); + f.readLine(stxHeader, 128); + + if (!themeConfigParseHeader(stxHeader, _themeName)) { + warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); + return false; + } } - } - } #ifdef USE_ZLIB } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index fc781f731d..2291d9e3c1 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -92,8 +92,8 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), if (themefile.compareToIgnoreCase("default") == 0) themefile = "builtin"; - if (themefile != "builtin" && !themefile.hasSuffix(".zip")) - themefile += ".zip"; +// if (themefile != "builtin" && !themefile.hasSuffix(".zip")) +// themefile += ".zip"; ConfMan.registerDefault("gui_renderer", 2); ThemeRenderer::GraphicsMode gfxMode = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); diff --git a/gui/theme.cpp b/gui/theme.cpp index 45fc047c45..3a6280ab95 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -23,6 +23,7 @@ */ #include "gui/theme.h" +#include "common/fs.h" #include "common/unzip.h" namespace GUI { @@ -153,7 +154,10 @@ bool Theme::themeConfigParseHeader(Common::String header, Common::String &themeN return tok.empty(); } -bool Theme::themeConfigUseable(const Common::String &filename, Common::String &themeName) { +bool Theme::themeConfigUseable(const FilesystemNode &node, Common::String &themeName) { + char stxHeader[128]; + bool foundHeader = false; + if (ConfMan.hasKey("themepath")) Common::File::addDefaultDirectory(ConfMan.get("themepath")); @@ -164,38 +168,47 @@ bool Theme::themeConfigUseable(const Common::String &filename, Common::String &t if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + if (node.getName().hasSuffix(".zip")) { #ifdef USE_ZLIB - unzFile zipFile = unzOpen(filename.c_str()); - char stxHeader[128]; - bool foundHeader = false; + unzFile zipFile = unzOpen(node.getPath().c_str()); - if (zipFile && unzLocateFile(zipFile, "THEMERC", 2) == UNZ_OK) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); - stream.readLine(stxHeader, 128); + if (zipFile && unzLocateFile(zipFile, "THEMERC", 2) == UNZ_OK) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); + stream.readLine(stxHeader, 128); - if (themeConfigParseHeader(stxHeader, themeName)) - foundHeader = true; + if (themeConfigParseHeader(stxHeader, themeName)) + foundHeader = true; - delete[] buffer; - buffer = 0; - } - unzClose(zipFile); + delete[] buffer; + buffer = 0; + } + unzClose(zipFile); #else - return false; + return false; #endif + } else if (node.isDirectory()) { + FilesystemNode headerfile = node.getChild("THEMERC"); + if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory()) + return false; + + Common::File f; + f.open(headerfile); + f.readLine(stxHeader, 128); + + if (themeConfigParseHeader(stxHeader, themeName)) + foundHeader = true; + } return foundHeader; } - - } // End of namespace GUI diff --git a/gui/theme.h b/gui/theme.h index f4709067ef..50b2951ae5 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -305,7 +305,7 @@ public: bool isThemeLoadingRequired(); virtual ThemeEval *evaluator() = 0; - static bool themeConfigUseable(const Common::String &file, Common::String &themeName); + static bool themeConfigUseable(const FilesystemNode &node, Common::String &themeName); static bool themeConfigParseHeader(Common::String header, Common::String &themeName); virtual const Common::String &getThemeFileName() const = 0; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 490248619b..dd15742258 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -146,16 +146,34 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { return; FSList fslist; - if (!node.getChildren(fslist, FilesystemNode::kListAll)) - return; - - for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { - if (i->isDirectory()) { - addDir(list, i->getPath(), level-1); - } else { + +#ifdef USE_ZLIB + if (node.lookupFile(fslist, "*.zip", false, true, 0)) { + for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { Entry th; if (isTheme(*i, th)) { bool add = true; + + for (ThList::const_iterator p = list.begin(); p != list.end(); ++p) { + if (p->name == th.name || p->file == th.file) { + add = false; + break; + } + } + + if (add) + list.push_back(th); + } + } + } +#endif + + if (node.lookupFile(fslist, "THEMERC", false, true, 1)) { + for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { + Entry th; + if (isTheme(i->getParent(), th)) { + bool add = true; + for (ThList::const_iterator p = list.begin(); p != list.end(); ++p) { if (p->name == th.name || p->file == th.file) { add = false; @@ -171,12 +189,17 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { } bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { - out.file = node.getName(); + out.file = node.getName(); - if (!out.file.hasSuffix(".zip")) +#ifdef USE_ZLIB + if (!out.file.hasSuffix(".zip") && !node.isDirectory()) return false; +#else + if (!node.isDirectory()) + return false; +#endif - if (!Theme::themeConfigUseable(out.file, out.name)) + if (!Theme::themeConfigUseable(node, out.name)) return false; return true; diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index 3211ca2cd9..4015f24b93 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index ff08f25dd3..a6c3c31625 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ -- cgit v1.2.3 From f6ee4117840ea084a0bedda9731108f79ef0e3c2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 18 Aug 2008 19:06:58 +0000 Subject: Misc GFX fixes. Bugfix: Theme folder loading. svn-id: r34002 --- gui/ThemeRenderer.cpp | 6 +++--- gui/themebrowser.cpp | 2 +- gui/themes/scummclassic.zip | Bin 40158 -> 40156 bytes gui/themes/scummclassic/classic_gfx.stx | 4 ++-- gui/themes/scummodern.zip | Bin 122841 -> 123105 bytes gui/themes/scummodern/scummodern_gfx.stx | 16 ++++++++++++++-- gui/themes/scummodern/scummodern_layout.stx | 6 +++--- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index c272de96f9..ab186101b1 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -483,9 +483,9 @@ bool ThemeRenderer::loadThemeXML(Common::String themeName) { } } else { #endif - FilesystemNode node(themeName); + + FilesystemNode node(themeName); if (node.exists() && node.isReadable() && node.isDirectory()) { - FSList fslist; if (!node.getChildren(fslist, FilesystemNode::kListFilesOnly)) return false; @@ -795,7 +795,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String if (!sel.empty()) { Common::Rect text(r.left, r.top, r.right - 16, r.bottom); - queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); } } diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index dd15742258..f764b05f6a 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -189,7 +189,7 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { } bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { - out.file = node.getName(); + out.file = node.getPath(); #ifdef USE_ZLIB if (!out.file.hasSuffix(".zip") && !node.isDirectory()) diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index 4015f24b93..768d02b7f6 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx index 6c96dcebdb..d9189743d3 100644 --- a/gui/themes/scummclassic/classic_gfx.stx +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -234,7 +234,7 @@ /> @@ -255,7 +255,7 @@ /> diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index a6c3c31625..db728c5169 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/scummodern_gfx.stx b/gui/themes/scummodern/scummodern_gfx.stx index 37d6590e3c..c67dcee4d5 100644 --- a/gui/themes/scummodern/scummodern_gfx.stx +++ b/gui/themes/scummodern/scummodern_gfx.stx @@ -300,7 +300,7 @@ /> @@ -325,7 +325,7 @@ /> @@ -472,4 +472,16 @@ shadow = 3 /> + + + + \ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx index 61545d0ffa..9d3c009eff 100644 --- a/gui/themes/scummodern/scummodern_layout.stx +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -261,13 +261,13 @@ + - 40156 bytes gui/themes/scummodern.zip | Bin 123105 -> 123105 bytes 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp index ab186101b1..43659eeb16 100644 --- a/gui/ThemeRenderer.cpp +++ b/gui/ThemeRenderer.cpp @@ -363,16 +363,7 @@ bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { bool ThemeRenderer::loadTheme(Common::String fileName) { unloadTheme(); - if (fileName != "builtin") { - if (ConfMan.hasKey("themepath")) - Common::File::addDefaultDirectory(ConfMan.get("themepath")); - -#ifdef DATA_PATH - Common::File::addDefaultDirectoryRecursive(DATA_PATH); -#endif - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - + if (fileName != "builtin") { if (fileName.hasSuffix(".zip")) ImageMan.addArchive(fileName); else diff --git a/gui/themes/default.inc b/gui/themes/default.inc index ce7fc16cfc..71e655f5bc 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -189,7 +189,7 @@ "/> " " " " " " " @@ -208,7 +208,7 @@ "/> " " " " " " " @@ -517,12 +517,12 @@ " " -" " -" " " " " " -" " -" " " " " 123105 bytes gui/themes/scummodern/scummodern_gfx.stx | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index d5030f8ecf..2a896ca374 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/scummodern_gfx.stx b/gui/themes/scummodern/scummodern_gfx.stx index c67dcee4d5..c9f4c35985 100644 --- a/gui/themes/scummodern/scummodern_gfx.stx +++ b/gui/themes/scummodern/scummodern_gfx.stx @@ -32,10 +32,10 @@ rgb = '203, 126, 107' /> >; - - case GUI::ThemeRenderer::kGfxAntialias16bit: - return new VectorRendererAA >; - - default: - return 0; - } -} - const VectorRenderer::ConvolutionDataSet VectorRenderer::_convolutionData[VectorRenderer::kConvolutionMAX] = { { {{1, 1, 1}, {1, 8, 1}, {1, 1, 1}}, 16, 0 }, // soft blur matrix { {{2, 2, 2}, {2, 2, 2}, {2, 2, 2}}, 18, 0 }, // hard blur matrix @@ -169,1303 +156,4 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect & } } -/******************************************************************** - * MISCELANEOUS functions - ********************************************************************/ -template -void VectorRendererSpec:: -areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset) { - PixelType *ptr = 0; - int newR, newG, newB; - uint8 r, g, b; - int yVal; - - for (int y = area.top; y < area.bottom; ++y) { - for (int x = area.left; x < area.right; ++x) { - newR = newG = newB = 0; - - for (int j = 0; j < 3; ++j) { - yVal = MIN(MAX(y - 1 + j, 0), area.bottom - 1); - - for (int i = 0; i < 3; ++i) { - ptr = (PixelType *)Base::_activeSurface->getBasePtr(MIN(MAX(x - 1 + j, 0), area.right - 1), yVal); - colorToRGB((uint32)*ptr, r, g, b); - - newR += r * filter[j][i]; - newG += g * filter[j][i]; - newB += b * filter[j][i]; - } - } - - newR = (newR / filterDiv) + offset; - newG = (newG / filterDiv) + offset; - newB = (newB / filterDiv) + offset; - - ptr = (PixelType *)Base::_activeSurface->getBasePtr(x, y); - *ptr = RGBToColor(CLIP(newR, 0, 255), CLIP(newG, 0, 255), CLIP(newB, 0, 255)); - } - } -} - -/** Fixed point SQUARE ROOT **/ -inline uint32 fp_sqroot(uint32 x) { - register uint32 root, remHI, remLO, testDIV, count; - - root = 0; - remHI = 0; - remLO = x; - count = 23; - - do { - remHI = (remHI << 2) | (remLO >> 30); - remLO <<= 2; - root <<= 1; - testDIV = (root << 1) + 1; - - if (remHI >= testDIV) { - remHI -= testDIV; - root++; - } - } while (count--); - - return root; -} - -/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ -#define __BE_ALGORITHM() { \ - if (f >= 0) { \ - y--; \ - ddF_y += 2; \ - f += ddF_y; \ - py -= pitch; \ - } \ - px += pitch; \ - ddF_x += 2; \ - f += ddF_x + 1; \ -} - -#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ - *(ptr1 + (y) - (px)) = color; \ - *(ptr1 + (x) - (py)) = color; \ - *(ptr2 - (x) - (py)) = color; \ - *(ptr2 - (y) - (px)) = color; \ - *(ptr3 - (y) + (px)) = color; \ - *(ptr3 - (x) + (py)) = color; \ - *(ptr4 + (x) + (py)) = color; \ - *(ptr4 + (y) + (px)) = color; \ -} - -#define __BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ - *(ptr1 + (y) - (px)) = color1; \ - *(ptr1 + (x) - (py)) = color2; \ - *(ptr2 - (x) - (py)) = color2; \ - *(ptr2 - (y) - (px)) = color1; \ - *(ptr3 - (y) + (px)) = color3; \ - *(ptr3 - (x) + (py)) = color4; \ - *(ptr4 + (x) + (py)) = color4; \ - *(ptr4 + (y) + (px)) = color3; \ -} - -#define __BE_RESET() { \ - f = 1 - r; \ - ddF_x = 0; ddF_y = -2 * r; \ - x = 0; y = r; px = 0; py = pitch * r; \ -} - -/** HELPER MACROS for WU's circle drawing algorithm **/ -#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ - blendPixelPtr(ptr1 + (y) - (px), color, a); \ - blendPixelPtr(ptr1 + (x) - (py), color, a); \ - blendPixelPtr(ptr2 - (x) - (py), color, a); \ - blendPixelPtr(ptr2 - (y) - (px), color, a); \ - blendPixelPtr(ptr3 - (y) + (px), color, a); \ - blendPixelPtr(ptr3 - (x) + (py), color, a); \ - blendPixelPtr(ptr4 + (x) + (py), color, a); \ - blendPixelPtr(ptr4 + (y) + (px), color, a); \ -} - -#define __WU_ALGORITHM() { \ - oldT = T; \ - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ - py += p; \ - if (T < oldT) { \ - x--; px -= p; \ - } \ - a2 = (T >> 8); \ - a1 = ~a2; \ -} - -#define __TRIANGLE_MAINX() \ - if (error_term >= 0) { \ - ptr_right += pitch; \ - ptr_left += pitch; \ - error_term += dysub; \ - } else { \ - error_term += ddy; \ - } \ - ptr_right++; \ - ptr_left--; - -#define __TRIANGLE_MAINY() \ - if (error_term >= 0) { \ - ptr_right++; \ - ptr_left--; \ - error_term += dxsub; \ - } else { \ - error_term += ddx; \ - } \ - ptr_right += pitch; \ - ptr_left += pitch; - -/******************************************************************** - * Primitive shapes drawing - Public API calls - VectorRendererSpec - ********************************************************************/ -template -void VectorRendererSpec:: -drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, - GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax, bool ellipsis) { - - int offset = area.top; - - if (font->getFontHeight() < area.height()) { - switch (alignV) { - case GUI::Theme::kTextAlignVCenter: - offset = area.top + ((area.height() - font->getFontHeight()) >> 1); - break; - case GUI::Theme::kTextAlignVBottom: - offset = area.bottom - font->getFontHeight(); - break; - default: - break; - } - } - - font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, deltax, ellipsis); -} - -/** LINES **/ -template -void VectorRendererSpec:: -drawLine(int x1, int y1, int x2, int y2) { - x1 = CLIP(x1, 0, (int)Base::_activeSurface->w); - x2 = CLIP(x2, 0, (int)Base::_activeSurface->w); - y1 = CLIP(y1, 0, (int)Base::_activeSurface->h); - y2 = CLIP(y2, 0, (int)Base::_activeSurface->h); - - // we draw from top to bottom - if (y2 < y1) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - int dx = ABS(x2 - x1); - int dy = ABS(y2 - y1); - - // this is a point, not a line. stoopid. - if (dy == 0 && dx == 0) - return; - - if (Base::_strokeWidth == 0) - return; - - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = Base::surfacePitch(); - int st = Base::_strokeWidth >> 1; - - if (dy == 0) { // horizontal lines - // these can be filled really fast with a single memset. - colorFill(ptr, ptr + dx + 1, (PixelType)_fgColor); - - for (int i = 0, p = pitch; i < st; ++i, p += pitch) { - colorFill(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor); - colorFill(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor); - } - - } else if (dx == 0) { // vertical lines - // these ones use a static pitch increase. - while (y1++ <= y2) { - colorFill(ptr - st, ptr + st, (PixelType)_fgColor); - ptr += pitch; - } - - } else if (ABS(dx) == ABS(dy)) { // diagonal lines - // these ones also use a fixed pitch increase - pitch += (x2 > x1) ? 1 : -1; - - while (dy--) { - colorFill(ptr - st, ptr + st, (PixelType)_fgColor); - ptr += pitch; - } - - } else { // generic lines, use the standard algorithm... - drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor); - } -} - -/** CIRCLES **/ -template -void VectorRendererSpec:: -drawCircle(int x, int y, int r) { - if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h || - x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0) - return; - - if (Base::_fillMode != kFillDisabled && Base::_shadowOffset - && x + r + Base::_shadowOffset < Base::_activeSurface->w - && y + r + Base::_shadowOffset < Base::_activeSurface->h) { - drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground); - } - - switch (Base::_fillMode) { - case kFillDisabled: - if (Base::_strokeWidth) - drawCircleAlg(x, y, r, _fgColor, kFillDisabled); - break; - - case kFillForeground: - drawCircleAlg(x, y, r, _fgColor, kFillForeground); - break; - - case kFillBackground: - if (Base::_strokeWidth > 1) { - drawCircleAlg(x, y, r, _fgColor, kFillForeground); - drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground); - } else { - drawCircleAlg(x, y, r, _bgColor, kFillBackground); - drawCircleAlg(x, y, r, _fgColor, kFillDisabled); - } - break; - - case kFillGradient: - break; - } -} - -/** SQUARES **/ -template -void VectorRendererSpec:: -drawSquare(int x, int y, int w, int h) { - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0) - return; - - if (Base::_fillMode != kFillDisabled && Base::_shadowOffset - && x + w + Base::_shadowOffset < Base::_activeSurface->w - && y + h + Base::_shadowOffset < Base::_activeSurface->h) { - drawSquareShadow(x, y, w, h, Base::_shadowOffset); - } - - switch (Base::_fillMode) { - case kFillDisabled: - if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); - break; - - case kFillForeground: - drawSquareAlg(x, y, w, h, _fgColor, kFillForeground); - break; - - case kFillBackground: - drawSquareAlg(x, y, w, h, _bgColor, kFillBackground); - drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); - break; - - case kFillGradient: - VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient); - if (Base::_strokeWidth) - drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); - break; - } -} - -/** ROUNDED SQUARES **/ -template -void VectorRendererSpec:: -drawRoundedSquare(int x, int y, int r, int w, int h) { - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0) - return; - - if ((r << 1) > w || (r << 1) > h) - r = MIN(w >> 1, h >> 1); - - if (Base::_fillMode != kFillDisabled && Base::_shadowOffset - && x + w + Base::_shadowOffset < Base::_activeSurface->w - && y + h + Base::_shadowOffset < Base::_activeSurface->h) { - drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); - } - - switch (Base::_fillMode) { - case kFillDisabled: - if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - break; - - case kFillForeground: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); - break; - - case kFillBackground: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillBackground); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - break; - - case kFillGradient: - if (Base::_strokeWidth > 1) { - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); - VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, - r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillGradient); - } else { - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillGradient); - if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - } - break; - } - - if (Base::_bevel) - drawRoundedSquareFakeBevel(x, y, r, w, h, Base::_bevel); -} - -template -void VectorRendererSpec:: -drawTab(int x, int y, int r, int w, int h) { - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || - w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h) - return; - - if (r == 0 && Base::_bevel > 0) { - drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); - return; - } - - if (r == 0) return; - - switch (Base::_fillMode) { - case kFillDisabled: - return; - - case kFillGradient: - case kFillBackground: - drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); - if (Base::_strokeWidth) - drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); - break; - - case kFillForeground: - drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); - break; - } -} - -template -void VectorRendererSpec:: -drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { - // Awesome hack: the AA messes up the last pixel triangles if their width is even - // ...fix the width instead of fixing the AA :p - // if (w % 2 == 0) { - // w++; h++; - // } - - if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) - return; - - PixelType color = 0; - - if (Base::_strokeWidth <= 1) { - if (Base::_fillMode == kFillForeground) - color = _fgColor; - else if (Base::_fillMode == kFillBackground) - color = _bgColor; - } else { - if (Base::_fillMode == kFillDisabled) - return; - color = _fgColor; - } - - if (Base::_dynamicData != 0) - orient = (TriangleOrientation)Base::_dynamicData; - - int newW = w / 2; - if (newW % 2) newW++; - - switch(orient) { - case kTriangleUp: - case kTriangleDown: - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), color, Base::_fillMode); - break; - - case kTriangleLeft: - case kTriangleRight: - case kTriangleAuto: - break; - } - - if (Base::_strokeWidth > 0) - if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), _fgColor, kFillDisabled); - } -} - -/******************************************************************** - * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec - ********************************************************************/ -/** TAB ALGORITHM - NON AA */ -template -void VectorRendererSpec:: -drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) { - int f, ddF_x, ddF_y; - int x, y, px, py; - int pitch = Base::surfacePitch(); - int sw = 0, sp = 0, hp = 0; - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int real_radius = r; - int short_h = h - r + 2; - int long_h = h; - - if (fill_m == kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); - sp += pitch; - - __BE_RESET(); - r--; - - while (x++ < y) { - __BE_ALGORITHM(); - *(ptr_tr + (y) - (px)) = color; - *(ptr_tr + (x) - (py)) = color; - *(ptr_tl - (x) - (py)) = color; - *(ptr_tl - (y) - (px)) = color; - - if (Base::_strokeWidth > 1) { - *(ptr_tr + (y) - (px - pitch)) = color; - *(ptr_tr + (x) - (py)) = color; - *(ptr_tl - (x) - (py)) = color; - *(ptr_tl - (y) - (px - pitch)) = color; - } - } - } - - ptr_fill += pitch * real_radius; - while (short_h--) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth - 1, color); - colorFill(ptr_fill + w - Base::_strokeWidth + 2, ptr_fill + w, color); - ptr_fill += pitch; - } - - if (baseLeft) { - sw = 0; - ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h); - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill - baseLeft, ptr_fill, color); - ptr_fill += pitch; - } - } - - if (baseRight) { - sw = 0; - ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h); - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill, ptr_fill + baseRight, color); - ptr_fill += pitch; - } - } - } else { - __BE_RESET(); - - PixelType color1, color2; - color1 = color2 = color; - - while (x++ < y) { - __BE_ALGORITHM(); - - if (fill_m == kFillGradient) { - color1 = calcGradient(real_radius - x, long_h); - color2 = calcGradient(real_radius - y, long_h); - } - - colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); - - *(ptr_tr + (y) - (px)) = color1; - *(ptr_tr + (x) - (py)) = color2; - *(ptr_tl - (x) - (py)) = color2; - *(ptr_tl - (y) - (px)) = color1; - } - - ptr_fill += pitch * r; - while (short_h--) { - if (fill_m == kFillGradient) - color = calcGradient(real_radius++, long_h); - colorFill(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; - } - } -} - - -/** BEVELED TABS FOR CLASSIC THEME **/ -template -void VectorRendererSpec:: -drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) { - int pitch = Base::surfacePitch(); - int i, j; - - PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); - - i = bevel; - while (i--) { - colorFill(ptr_left, ptr_left + w, top_color); - ptr_left += pitch; - } - - if (baseLeft > 0) { - i = h - bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); - while (i--) { - colorFill(ptr_left, ptr_left + bevel, top_color); - ptr_left += pitch; - } - } - - i = h - bevel; - j = bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); - while (i--) { - colorFill(ptr_left + j, ptr_left + bevel, bottom_color); - if (j > 0) j--; - ptr_left += pitch; - } - - i = bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel); - while (i--) { - colorFill(ptr_left, ptr_left + baseRight + bevel, bottom_color); - - if (baseLeft) - colorFill(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color); - ptr_left += pitch; - } -} - -/** SQUARE ALGORITHM **/ -template -void VectorRendererSpec:: -drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - int pitch = Base::surfacePitch(); - int max_h = h; - - if (fill_m != kFillDisabled) { - while (h--) { - if (fill_m == kFillGradient) - color = calcGradient(max_h - h, max_h); - - colorFill(ptr, ptr + w, color); - ptr += pitch; - } - } else { - int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1); - - while (sw--) { - colorFill(ptr + sp, ptr + w + sp, color); - colorFill(ptr + hp - sp, ptr + w + hp - sp, color); - sp += pitch; - } - - while (h--) { - colorFill(ptr, ptr + Base::_strokeWidth, color); - colorFill(ptr + w - Base::_strokeWidth, ptr + w, color); - ptr += pitch; - } - } -} - -/** SQUARE ALGORITHM **/ -template -void VectorRendererSpec:: -drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) { - int pitch = Base::surfacePitch(); - - int height = h; - PixelType *ptr_fill = (PixelType *)_activeSurface->getBasePtr(x, y); - - if (fill) { - while (height--) { - blendFill(ptr_fill, ptr_fill + w, _bgColor, 200); - ptr_fill += pitch; - } - } - - int i, j; - x = MAX(x - bevel, 0); - y = MAX(y - bevel, 0); - h += bevel << 1; - w += bevel << 1; - - PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); - - i = bevel; - while (i--) { - colorFill(ptr_left, ptr_left + w, top_color); - ptr_left += pitch; - } - - i = h - bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel); - while (i--) { - colorFill(ptr_left, ptr_left + bevel, top_color); - ptr_left += pitch; - } - - i = bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel); - while (i--) { - colorFill(ptr_left + i, ptr_left + w, bottom_color); - ptr_left += pitch; - } - - i = h - bevel; - j = bevel; - ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); - while (i--) { - colorFill(ptr_left + j, ptr_left + bevel, bottom_color); - if (j > 0) j--; - ptr_left += pitch; - } -} - -/** GENERIC LINE ALGORITHM **/ -template -void VectorRendererSpec:: -drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = Base::surfacePitch(); - int xdir = (x2 > x1) ? 1 : -1; - - *ptr = (PixelType)color; - - if (dx > dy) { - int ddy = dy * 2; - int dysub = ddy - (dx * 2); - int error_term = ddy - dx; - - while (dx--) { - if (error_term >= 0) { - ptr += pitch; - error_term += dysub; - } else { - error_term += ddy; - } - - ptr += xdir; - *ptr = (PixelType)color; - } - } else { - int ddx = dx * 2; - int dxsub = ddx - (dy * 2); - int error_term = ddx - dy; - - while (dy--) { - if (error_term >= 0) { - ptr += xdir; - error_term += dxsub; - } else { - error_term += ddx; - } - - ptr += pitch; - *ptr = (PixelType)color; - } - } - - ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); - *ptr = (PixelType)color; -} - -/** VERTICAL TRIANGLE DRAWING ALGORITHM **/ -template -void VectorRendererSpec:: -drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { - int dx = w >> 1, dy = h, gradient_h = 0; - int pitch = Base::surfacePitch(); - PixelType *ptr_right = 0, *ptr_left = 0; - - if (inverted) { - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); - } else { - ptr_right = ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + dx, y1); - } - - if (dx > dy) { - int ddy = dy * 2; - int dysub = ddy - (dx * 2); - int error_term = ddy - dx; - - switch(fill_m) { - case kFillDisabled: - while (dx--) { - __TRIANGLE_MAINX(); - *ptr_right = color; - *ptr_left = color; - } - colorFill(ptr_left, ptr_right, color); - break; - - case kFillForeground: - case kFillBackground: - while (dx--) { - __TRIANGLE_MAINX(); - if (inverted) colorFill(ptr_right, ptr_left, color); - else colorFill(ptr_left, ptr_right, color); - } - break; - - case kFillGradient: - while (dx--) { - __TRIANGLE_MAINX(); - if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); - } - break; - } - } else { - int ddx = dx * 2; - int dxsub = ddx - (dy * 2); - int error_term = ddx - dy; - - switch(fill_m) { - case kFillDisabled: - while (dy--) { - __TRIANGLE_MAINY(); - *ptr_right = color; - *ptr_left = color; - } - colorFill(ptr_left, ptr_right, color); - break; - - case kFillForeground: - case kFillBackground: - while (dy--) { - __TRIANGLE_MAINY(); - if (inverted) colorFill(ptr_right, ptr_left, color); - else colorFill(ptr_left, ptr_right, color); - } - break; - case kFillGradient: - while (dy--) { - __TRIANGLE_MAINY(); - if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); - } - break; - } - } -} - - -/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */ -template -void VectorRendererSpec:: -drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { - int pitch = Base::surfacePitch(); - int hstep = 0, dy = size; - bool grad = (fill_m == kFillGradient); - - PixelType *ptr_right = 0, *ptr_left = 0; - - if (inverted) { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); - } else { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1 + size); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1 + size); - pitch = -pitch; - } - - if (fill_m == kFillDisabled) { - while (ptr_left < ptr_right) { - *ptr_left = color; - *ptr_right = color; - ptr_left += pitch; - ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } - } - } else { - while (ptr_left < ptr_right) { - colorFill(ptr_left, ptr_right, grad ? calcGradient(dy--, size) : color); - ptr_left += pitch; - ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } - } - } -} - -/** ROUNDED SQUARE ALGORITHM **/ -template -void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { - int f, ddF_x, ddF_y; - int x, y, px, py; - int pitch = Base::surfacePitch(); - int sw = 0, sp = 0, hp = h * pitch; - -// if (r < 8) r = 3; - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int real_radius = r; - int short_h = h - (2 * r) + 2; - int long_h = h; - - if (fill_m == kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); - sp += pitch; - - __BE_RESET(); - r--; - - while (x++ < y) { - __BE_ALGORITHM(); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - - if (Base::_strokeWidth > 1) { - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); - } - } - } - - ptr_fill += pitch * real_radius; - while (short_h--) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); - colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); - ptr_fill += pitch; - } - } else { - __BE_RESET(); - PixelType color1, color2, color3, color4; - - if (fill_m == kFillGradient) { - while (x++ < y) { - __BE_ALGORITHM(); - - color1 = calcGradient(real_radius - x, long_h); - color2 = calcGradient(real_radius - y, long_h); - color3 = calcGradient(long_h - r + x, long_h); - color4 = calcGradient(long_h - r + y, long_h); - - colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); - - colorFill(ptr_bl - x + py, ptr_br + x + py, color4); - colorFill(ptr_bl - y + px, ptr_br + y + px, color3); - - __BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - } - } else { - while (x++ < y) { - __BE_ALGORITHM(); - - colorFill(ptr_tl - x - py, ptr_tr + x - py, color); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color); - - colorFill(ptr_bl - x + py, ptr_br + x + py, color); - colorFill(ptr_bl - y + px, ptr_br + y + px, color); - - // do not remove - messes up the drawing at lower resolutions - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - } - } - - ptr_fill += pitch * r; - while (short_h--) { - if (fill_m == kFillGradient) - color = calcGradient(real_radius++, long_h); - colorFill(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; - } - } -} - -/** CIRCLE ALGORITHM **/ -template -void VectorRendererSpec:: -drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { - int f, ddF_x, ddF_y; - int x, y, px, py, sw = 0; - int pitch = Base::surfacePitch(); - PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - if (fill_m == kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - __BE_RESET(); - r--; - - *(ptr + y) = color; - *(ptr - y) = color; - *(ptr + py) = color; - *(ptr - py) = color; - - while (x++ < y) { - __BE_ALGORITHM(); - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py); - - if (Base::_strokeWidth > 1) { - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py); - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py); - } - } - } - } else { - colorFill(ptr - r, ptr + r, color); - __BE_RESET(); - - while (x++ < y) { - __BE_ALGORITHM(); - colorFill(ptr - x + py, ptr + x + py, color); - colorFill(ptr - x - py, ptr + x - py, color); - colorFill(ptr - y + px, ptr + y + px, color); - colorFill(ptr - y - px, ptr + y - px, color); - } - } -} - - -/******************************************************************** - * SHADOW drawing algorithms - VectorRendererSpec - ********************************************************************/ -template -void VectorRendererSpec:: -drawSquareShadow(int x, int y, int w, int h, int blur) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); - int pitch = Base::surfacePitch(); - int i, j; - - i = h - blur; - - while (i--) { - j = blur; - while (j--) - blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); - ptr += pitch; - } - - ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); - - while (i++ < blur) { - j = w - blur; - while (j--) - blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); - ptr += pitch; - } - - ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); - - i = 0; - while (i++ < blur) { - j = blur - 1; - while (j--) - blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); - ptr += pitch; - } -} - -template -void VectorRendererSpec:: -drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { - int f, ddF_x, ddF_y; - int x, y, px, py; - int pitch = Base::surfacePitch(); - int alpha = 102; - - x1 += blur; - y1 += blur; - - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r); - - int short_h = h - (2 * r) + 1; - - __BE_RESET(); - - // HACK: As we are drawing circles exploting 8-axis symmetry, - // there are 4 pixels on each circle which are drawn twice. - // this is ok on filled circles, but when blending on surfaces, - // we cannot let it blend twice. awful. - uint32 hb = 0; - - while (x++ < y) { - __BE_ALGORITHM(); - - if (((1 << x) & hb) == 0) { - blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); - blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha); - hb |= (1 << x); - } - - if (((1 << y) & hb) == 0) { - blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha); - blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha); - hb |= (1 << y); - } - } - - while (short_h--) { - blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha); - ptr_fill += pitch; - } -} - -template -void VectorRendererSpec:: -drawRoundedSquareFakeBevel(int x1, int y1, int r, int w, int h, int amount) { - int x, y; - int p = Base::surfacePitch(), px, py; - int sw = 0, sp = 0; - - uint32 rsq = (r * r) << 16; - uint32 T = 0, oldT; - uint8 a1, a2; - - PixelType color = _bevelColor; //RGBToColor(63, 60, 17); - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int short_h = h - 2 * r; - - while (sw++ < amount) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - sp += p; - - x = r - (sw - 1); y = 0; T = 0; - px = p * x; py = 0; - - while (x > y++) { - __WU_ALGORITHM(); - - blendPixelPtr(ptr_tr + (y) - (px - p), color, a2); - blendPixelPtr(ptr_tr + (x - 1) - (py), color, a2); - blendPixelPtr(ptr_tl - (x - 1) - (py), color, a2); - blendPixelPtr(ptr_tl - (y) - (px - p), color, a2); - blendPixelPtr(ptr_bl - (y) + (px - p), color, a2); - blendPixelPtr(ptr_bl - (x - 1) + (py), color, a2); - - blendPixelPtr(ptr_tr + (y) - (px), color, a1); - blendPixelPtr(ptr_tr + (x) - (py), color, a1); - blendPixelPtr(ptr_tl - (x) - (py), color, a1); - blendPixelPtr(ptr_tl - (y) - (px), color, a1); - blendPixelPtr(ptr_bl - (y) + (px), color, a1); - blendPixelPtr(ptr_bl - (x) + (py), color, a1); - } - } - - ptr_fill += p * r; - while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + amount, color); - ptr_fill += p; - } -} - - -/******************************************************************** - * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA - ********************************************************************/ -/** LINES **/ -template -void VectorRendererAA:: -drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { - - PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - int pitch = Base::surfacePitch(); - int xdir = (x2 > x1) ? 1 : -1; - uint16 error_tmp, error_acc, gradient; - uint8 alpha; - - *ptr = (PixelType)color; - - if (dx > dy) { - gradient = (uint32)(dy << 16) / (uint32)dx; - error_acc = 0; - - while (--dx) { - error_tmp = error_acc; - error_acc += gradient; - - if (error_acc <= error_tmp) - ptr += pitch; - - ptr += xdir; - alpha = (error_acc >> 8); - - blendPixelPtr(ptr, color, ~alpha); - blendPixelPtr(ptr + pitch, color, alpha); - } - } else { - gradient = (uint32)(dx << 16) / (uint32)dy; - error_acc = 0; - - while (--dy) { - error_tmp = error_acc; - error_acc += gradient; - - if (error_acc <= error_tmp) - ptr += xdir; - - ptr += pitch; - alpha = (error_acc >> 8); - - blendPixelPtr(ptr, color, ~alpha); - blendPixelPtr(ptr + xdir, color, alpha); - } - } - - Base::putPixel(x2, y2, color); -} - -/** ROUNDED SQUARES **/ -template -void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { - int x, y; - int p = Base::surfacePitch(), px, py; - int sw = 0, sp = 0, hp = h * p; - - uint32 rsq = (r * r) << 16; - uint32 T = 0, oldT; - uint8 a1, a2; - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int short_h = h - 2 * r; - - if (fill_m == VectorRenderer::kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); - sp += p; - - x = r - (sw - 1); y = 0; T = 0; - px = p * x; py = 0; - - while (x > y++) { - __WU_ALGORITHM(); - - if (sw != 1 && sw != Base::_strokeWidth) - a2 = a1 = 255; - - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - p), py, a2); - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); - } - } - - ptr_fill += p * r; - while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); - colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); - ptr_fill += p; - } - } else { - x = r; y = 0; T = 0; - px = p * x; py = 0; - - while (x > y++) { - __WU_ALGORITHM(); - - colorFill(ptr_tl - x - py, ptr_tr + x - py, color); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color); - - colorFill(ptr_bl - x + py, ptr_br + x + py, color); - colorFill(ptr_bl - y + px, ptr_br + y + px, color); - - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); - } - - ptr_fill += p * r; - while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += p; - } - } -} - -/** CIRCLES **/ -template -void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { - int x, y, sw = 0; - int p = Base::surfacePitch(), px, py; - - uint32 rsq = (r * r) << 16; - uint32 T = 0, oldT; - uint8 a1, a2; - - PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - if (fill_m == VectorRenderer::kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - x = r - (sw - 1); y = 0; T = 0; - px = p * x; py = 0; - - *(ptr + x) = (PixelType)color; - *(ptr - x) = (PixelType)color; - *(ptr + px) = (PixelType)color; - *(ptr - px) = (PixelType)color; - - while (x > y++) { - __WU_ALGORITHM(); - - if (sw != 1 && sw != Base::_strokeWidth) - a2 = a1 = 255; - - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - p), py, a2); - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); - } - } - } else { - colorFill(ptr - r, ptr + r + 1, color); - x = r; y = 0; T = 0; - px = p * x; py = 0; - - while (x > y++) { - __WU_ALGORITHM(); - - colorFill(ptr - x + py, ptr + x + py, color); - colorFill(ptr - x - py, ptr + x - py, color); - colorFill(ptr - y + px, ptr + y + px, color); - colorFill(ptr - y - px, ptr + y - px, color); - - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); - } - } -} - } // end of namespace Graphics diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index bd1bd1db42..8ba9126b3e 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -34,10 +34,8 @@ #include "gui/ThemeRenderer.h" - namespace Graphics { class VectorRenderer; -struct DrawStep; struct DrawStep { struct { @@ -492,7 +490,9 @@ public: * Draws a string into the screen. Wrapper for the Graphics::Font string drawing * method. */ - virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax, bool useEllipsis) = 0; + virtual void drawString(const Graphics::Font *font, const Common::String &text, + const Common::Rect &area, GUI::Theme::TextAlign alignH, + GUI::Theme::TextAlignVertical alignV, int deltax, bool useEllipsis) = 0; /** * Allows to temporarily enable/disable all shadows drawing. @@ -524,9 +524,7 @@ public: * @param area Area in which the convolution effect will be applied. */ virtual void applyConvolutionMatrix(const ConvolutionData id, const Common::Rect &area) { -#ifdef ENABLE_CONVOLUTIONS areaConvolution(area, _convolutionData[id].matrix, _convolutionData[id].divisor, _convolutionData[id].offset); -#endif } /** @@ -554,511 +552,6 @@ protected: static const int _dimPercentValue = 256 * 50 / 100; /** default value for screen dimming (50%) */ }; -/** - * VectorRendererSpec: Specialized Vector Renderer Class - * - * This templated class implements the basic subset of vector operations for - * all platforms by allowing the user to provide the actual Pixel Type and - * pixel information structs. - * - * This class takes two template parameters: - * - * @param PixelType Defines a type which may hold the color value of a single - * pixel, such as "byte" or "uint16" for 8 and 16 BPP respectively. - * - * @param PixelFormat Defines the type of the PixelFormat struct which contains all - * the actual information of the pixels being used, as declared in "graphics/colormasks.h" - * - * TODO: Expand documentation. - * - * @see VectorRenderer - */ -template -class VectorRendererSpec : public VectorRenderer { - typedef VectorRenderer Base; - -public: - VectorRendererSpec() { - _bitmapAlphaColor = RGBToColor(255, 0, 255); - } - - - /** - * @see VectorRenderer::drawLine() - */ - void drawLine(int x1, int y1, int x2, int y2); - - /** - * @see VectorRenderer::drawCircle() - */ - void drawCircle(int x, int y, int r); - - /** - * @see VectorRenderer::drawSquare() - */ - void drawSquare(int x, int y, int w, int h); - - /** - * @see VectorRenderer::drawRoundedSquare() - */ - void drawRoundedSquare(int x, int y, int r, int w, int h); - - /** - * @see VectorRenderer::drawTriangle() - */ - void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); - - /** - * @see VectorRenderer::drawTab() - */ - void drawTab(int x, int y, int r, int w, int h); - - void drawBeveledSquare(int x, int y, int w, int h, int bevel) { - drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled); - } - - void drawString(const Graphics::Font *font, const Common::String &text, - const Common::Rect &area, GUI::Theme::TextAlign alignH, - GUI::Theme::TextAlignVertical alignV, int deltax, bool elipsis); - - /** - * @see VectorRenderer::setFgColor() - */ - void setFgColor(uint8 r, uint8 g, uint8 b) { - this->_fgColor = RGBToColor(r, g, b); - } - - /** - * @see VectorRenderer::setBgColor() - */ - void setBgColor(uint8 r, uint8 g, uint8 b) { - this->_bgColor = RGBToColor(r, g, b); - } - - void setBevelColor(uint8 r, uint8 g, uint8 b) { - this->_bevelColor = RGBToColor(r, g, b); - } - - /** - * @see VectorRenderer::setGradientColors() - */ - void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { - _gradientEnd = RGBToColor(r2, g2, b2); - _gradientStart = RGBToColor(r1, g1, b1); - - Base::_gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); - Base::_gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); - Base::_gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); - } - - /** - * @see VectorRenderer::fillSurface() - */ - void fillSurface() { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); - - int w = _activeSurface->w; - int h = _activeSurface->h ; - int pitch = surfacePitch(); - - if (Base::_fillMode == kFillBackground) - colorFill(ptr, ptr + w * h, _bgColor); - else if (Base::_fillMode == kFillForeground) - colorFill(ptr, ptr + w * h, _fgColor); - else if (Base::_fillMode == kFillGradient) { - int i = h; - while (i--) { - colorFill(ptr, ptr + w, calcGradient(h - i, h)); - ptr += pitch; - } - } - } - - /** - * @see VectorRenderer::copyFrame() - */ - virtual void copyFrame(OSystem *sys, const Common::Rect &r) { -#ifdef OVERLAY_MULTIPLE_DEPTHS - sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(r.left, r.top), - _activeSurface->w, r.left, r.top, r.width(), r.height()); -#else - sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(r.left, r.top), - _activeSurface->w, r.left, r.top, r.width(), r.height()); -#endif - } - - virtual void copyWholeFrame(OSystem *sys) { -#ifdef OVERLAY_MULTIPLE_DEPTHS - sys->copyRectToOverlay((const PixelType*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); -#else - sys->copyRectToOverlay((const OverlayColor*)_activeSurface->getBasePtr(0, 0), - _activeSurface->w, 0, 0, _activeSurface->w, _activeSurface->h); -#endif - } - - /** - * @see VectorRenderer::blitSurface() - */ - virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r) { - assert(source->w == _activeSurface->w && source->h == _activeSurface->h); - - PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); - PixelType *src_ptr = (PixelType *)source->getBasePtr(r.left, r.top); - - int dst_pitch = surfacePitch(); - int src_pitch = source->pitch / source->bytesPerPixel; - - int h = r.height(), w = r.width(); - - while (h--) { - colorCopy(src_ptr, dst_ptr, w); - dst_ptr += dst_pitch; - src_ptr += src_pitch; - } - } - - virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) { - PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); - PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); - - int dst_pitch = surfacePitch(); - int src_pitch = source->pitch / source->bytesPerPixel; - - int h = r.height(), w = r.width(); - - while (h--) { - colorCopy(src_ptr, dst_ptr, w); - dst_ptr += dst_pitch; - src_ptr += src_pitch; - } - } - - virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { - int16 x = r.left; - int16 y = r.top; - - if (r.width() > source->w) - x = x + (r.width() >> 1) - (source->w >> 1); - - if (r.height() > source->h) - y = y + (r.height() >> 1) - (source->h >> 1); - - PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); - - int dst_pitch = surfacePitch(); - int src_pitch = source->pitch / source->bytesPerPixel; - - int w, h = source->h; - - while (h--) { - w = source->w; - - while (w--) { - if (*src_ptr != _bitmapAlphaColor) - *dst_ptr = *src_ptr; - - dst_ptr++; - src_ptr++; - } - - dst_ptr = dst_ptr - source->w + dst_pitch; - src_ptr = src_ptr - source->w + src_pitch; - } - - } - - virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { - int pixels = _activeSurface->w * _activeSurface->h; - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); - uint8 r, g, b; - uint lum; - - if (shadingStyle == GUI::Theme::kShadingDim) { - while (pixels--) { - colorToRGB(*ptr, r, g, b); - r = r * _dimPercentValue >> 8; - g = g * _dimPercentValue >> 8; - b = b * _dimPercentValue >> 8; - *ptr++ = RGBToColor(r, g, b); - } - } else if (shadingStyle == GUI::Theme::kShadingLuminance) { - while (pixels--) { - colorToRGB(*ptr, r, g, b); - lum = (r >> 2) + (g >> 1) + (b >> 3); - *ptr++ = RGBToColor(lum, lum, lum); - } - } - } - -protected: - - /** - * Draws a single pixel on the surface with the given coordinates and - * the given color. - * - * @param x Horizontal coordinate of the pixel. - * @param y Vertical coordinate of the pixel. - * @param color Color of the pixel - */ - virtual inline void putPixel(int x, int y, PixelType color) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - *ptr = color; - } - - /** - * Blends a single pixel on the surface with the given coordinates, color - * and Alpha intensity. - * - * @param x Horizontal coordinate of the pixel. - * @param y Vertical coordinate of the pixel. - * @param color Color of the pixel - * @param alpha Alpha intensity of the pixel (0-255) - */ - virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { - if (alpha == 255) - putPixel(x, y, color); - else if (alpha > 0) - blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); - } - - /** - * Blends a single pixel on the surface in the given pixel pointer, using supplied color - * and Alpha intensity. - * - * This is implemented to prevent blendPixel() to calculate the surface pointer on each call. - * Optimized drawing algorithms should call this function when possible. - * - * @see blendPixel - * @param ptr Pointer to the pixel to blend on top of - * @param color Color of the pixel - * @param alpha Alpha intensity of the pixel (0-255) - */ - virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - if (!ptr) return; - - if (alpha == 255) { - *ptr = color; - return; - } - - register int idst = *ptr; - register int isrc = color; - - *ptr = (PixelType)( - (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + - ((int)(((int)(isrc & PixelFormat::kRedMask) - - (int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) | - (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + - ((int)(((int)(isrc & PixelFormat::kGreenMask) - - (int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) | - (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + - ((int)(((int)(isrc & PixelFormat::kBlueMask) - - (int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) ); - } - - /** - * PRIMITIVE DRAWING ALGORITHMS - * - * Generic algorithms for drawing all kinds of aliased primitive shapes. - * These may be overloaded in inheriting classes to implement platform-specific - * optimizations or improve looks. - * - * @see VectorRendererAA - * @see VectorRendererAA::drawLineAlg - * @see VectorRendererAA::drawCircleAlg - */ - virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); - virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); - virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); - virtual void drawTriangleVertAlg(int x, int y, int w, int h, bool inverted, PixelType color, FillMode fill_m); - virtual void drawTriangleFast(int x, int y, int size, bool inverted, PixelType color, FillMode fill_m); - virtual void drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill); - virtual void drawTabAlg(int x, int y, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft = 0, int baseRight = 0); - virtual void drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType topColor, PixelType bottomColor, int baseLeft = 0, int baseRight = 0); - - /** - * SHADOW DRAWING ALGORITHMS - * - * Optimized versions of the primitive drawing algorithms with alpha blending - * for shadow drawing. - * There functions may be overloaded in inheriting classes to improve performance - * in the slowest platforms where pixel alpha blending just doesn't cut it. - * - * @param blur Intensity/size of the shadow. - */ - virtual void drawSquareShadow(int x, int y, int w, int h, int blur); - virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); - virtual void drawRoundedSquareFakeBevel(int x, int y, int r, int w, int h, int amount); - - /** - * Calculates the color gradient on a given point. - * This function assumes that the gradient start/end colors have been set - * beforehand from the API function call. - * - * @param pos Progress of the gradient. - * @param max Maximum amount of the progress. - * @return Composite color of the gradient at the given "progress" amount. - */ - virtual inline PixelType calcGradient(uint32 pos, uint32 max) { - PixelType output = 0; - pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; - - output |= (_gradientStart + ((Base::_gradientBytes[0] * pos) >> 12)) & PixelFormat::kRedMask; - output |= (_gradientStart + ((Base::_gradientBytes[1] * pos) >> 12)) & PixelFormat::kGreenMask; - output |= (_gradientStart + ((Base::_gradientBytes[2] * pos) >> 12)) & PixelFormat::kBlueMask; - output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask); - - return output; - } - - /** - * Fills several pixels in a row with a given color and the specifed alpha blending. - * - * @see blendPixelPtr - * @see blendPixel - * @param first Pointer to the first pixel to fill. - * @param last Pointer to the last pixel to fill. - * @param color Color of the pixel - * @param alpha Alpha intensity of the pixel (0-255) - */ - virtual inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { - while (first != last) - blendPixelPtr(first++, color, alpha); - } - - /** - * Fills several pixels in a row with a given color. - * - * This is a replacement function for Common::set_to, using an unrolled - * loop to maximize performance on most architectures. - * This function may (and should) be overloaded in any child renderers - * for portable platforms with platform-specific assembly code. - * - * This fill operation is extensively used throughout the renderer, so this - * counts as one of the main bottlenecks. Please replace it with assembly - * when possible! - * - * @param first Pointer to the first pixel to fill. - * @param last Pointer to the last pixel to fill. - * @param color Color of the pixel - */ - virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color) { - if (first == last) { - *first = color; - return; - } - - register PixelType *ptr = first; - register int count = (last - first); - register int n = (count + 7) >> 3; - switch (count % 8) { - case 0: do { - *ptr++ = color; - case 7: *ptr++ = color; - case 6: *ptr++ = color; - case 5: *ptr++ = color; - case 4: *ptr++ = color; - case 3: *ptr++ = color; - case 2: *ptr++ = color; - case 1: *ptr++ = color; - } while (--n > 0); - } - } - - /** - * Copies several pixes in a row from a surface to another one. - * Used for surface blitting. - * See colorFill() for optimization guidelines. - * - * @param src Source surface. - * @param dst Destination surface. - * @param count Amount of pixels to copy over. - */ - virtual inline void colorCopy(PixelType *src, PixelType *dst, int count) { - register int n = (count + 7) >> 3; - switch (count % 8) { - case 0: do { - *dst++ = *src++; - case 7: *dst++ = *src++; - case 6: *dst++ = *src++; - case 5: *dst++ = *src++; - case 4: *dst++ = *src++; - case 3: *dst++ = *src++; - case 2: *dst++ = *src++; - case 1: *dst++ = *src++; - } while (--n > 0); - } - } - - virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); - - PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ - PixelType _bgColor; /** Background color currently being used to draw on the renderer */ - - PixelType _gradientStart; /** Start color for the fill gradient */ - PixelType _gradientEnd; /** End color for the fill gradient */ - - PixelType _bevelColor; - - PixelType _bitmapAlphaColor; -}; - -/** - * VectorRendererAA: Anti-Aliased Vector Renderer Class - * - * This templated class inherits all the functionality of the VectorRendererSpec - * class but uses better looking yet slightly slower AA algorithms for drawing - * most primivitves. May be used in faster platforms. - * - * TODO: Expand documentation. - * - * @see VectorRenderer - * @see VectorRendererSpec - */ -template -class VectorRendererAA : public VectorRendererSpec { - typedef VectorRendererSpec Base; -protected: - /** - * "Wu's Line Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 - * Based on the implementation found in Michael Abrash's Graphics Programming Black Book. - * - * Generic line drawing algorithm for the Antialiased renderer. Optimized with no - * floating point operations, assumes no special cases. - * - * @see VectorRenderer::drawLineAlg() - */ - virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); - - /** - * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 - * Based on the theoretical concept of the algorithm. - * - * Implementation of Wu's algorithm for circles using fixed point arithmetics. - * Could be quite fast. - * - * @see VectorRenderer::drawCircleAlg() - */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); - - /** - * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991, - * modified with corner displacement to allow drawing of squares with rounded - * corners. - * - * @see VectorRenderer::drawRoundedAlg() - */ - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); - - virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) { - Base::drawRoundedSquareShadow(x, y, r, w, h, blur); - VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur, Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2)); - } -}; - } // end of namespace Graphics #endif diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp new file mode 100644 index 0000000000..908b9eb1a3 --- /dev/null +++ b/graphics/VectorRendererSpec.cpp @@ -0,0 +1,1605 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" + +#include "graphics/surface.h" +#include "graphics/colormasks.h" + +#include "gui/ThemeRenderer.h" +#include "graphics/VectorRenderer.h" +#include "graphics/VectorRendererSpec.h" + +#define VECTOR_RENDERER_FAST_TRIANGLES + +/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ +#define __BE_ALGORITHM() { \ + if (f >= 0) { \ + y--; \ + ddF_y += 2; \ + f += ddF_y; \ + py -= pitch; \ + } \ + px += pitch; \ + ddF_x += 2; \ + f += ddF_x + 1; \ +} + +#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ + *(ptr1 + (y) - (px)) = color; \ + *(ptr1 + (x) - (py)) = color; \ + *(ptr2 - (x) - (py)) = color; \ + *(ptr2 - (y) - (px)) = color; \ + *(ptr3 - (y) + (px)) = color; \ + *(ptr3 - (x) + (py)) = color; \ + *(ptr4 + (x) + (py)) = color; \ + *(ptr4 + (y) + (px)) = color; \ +} + +#define __BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ + *(ptr1 + (y) - (px)) = color1; \ + *(ptr1 + (x) - (py)) = color2; \ + *(ptr2 - (x) - (py)) = color2; \ + *(ptr2 - (y) - (px)) = color1; \ + *(ptr3 - (y) + (px)) = color3; \ + *(ptr3 - (x) + (py)) = color4; \ + *(ptr4 + (x) + (py)) = color4; \ + *(ptr4 + (y) + (px)) = color3; \ +} + +#define __BE_RESET() { \ + f = 1 - r; \ + ddF_x = 0; ddF_y = -2 * r; \ + x = 0; y = r; px = 0; py = pitch * r; \ +} + +#define __TRIANGLE_MAINX() \ + if (error_term >= 0) { \ + ptr_right += pitch; \ + ptr_left += pitch; \ + error_term += dysub; \ + } else { \ + error_term += ddy; \ + } \ + ptr_right++; \ + ptr_left--; + +#define __TRIANGLE_MAINY() \ + if (error_term >= 0) { \ + ptr_right++; \ + ptr_left--; \ + error_term += dxsub; \ + } else { \ + error_term += ddx; \ + } \ + ptr_right += pitch; \ + ptr_left += pitch; + +/** HELPER MACROS for WU's circle drawing algorithm **/ +#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ + blendPixelPtr(ptr1 + (y) - (px), color, a); \ + blendPixelPtr(ptr1 + (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (y) - (px), color, a); \ + blendPixelPtr(ptr3 - (y) + (px), color, a); \ + blendPixelPtr(ptr3 - (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (y) + (px), color, a); \ +} + +#define __WU_ALGORITHM() { \ + oldT = T; \ + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ + py += p; \ + if (T < oldT) { \ + x--; px -= p; \ + } \ + a2 = (T >> 8); \ + a1 = ~a2; \ +} + + + +namespace Graphics { + +VectorRenderer *createRenderer(int mode) { + switch (mode) { + case GUI::ThemeRenderer::kGfxStandard16bit: + return new VectorRendererSpec >; + + case GUI::ThemeRenderer::kGfxAntialias16bit: + return new VectorRendererAA >; + + default: + return 0; + } +} + +/** Fixed point SQUARE ROOT **/ +inline uint32 fp_sqroot(uint32 x) { + register uint32 root, remHI, remLO, testDIV, count; + + root = 0; + remHI = 0; + remLO = x; + count = 23; + + do { + remHI = (remHI << 2) | (remLO >> 30); + remLO <<= 2; + root <<= 1; + testDIV = (root << 1) + 1; + + if (remHI >= testDIV) { + remHI -= testDIV; + root++; + } + } while (count--); + + return root; +} + +template +void VectorRendererSpec:: +areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset) { + PixelType *ptr = 0; + int newR, newG, newB; + uint8 r, g, b; + int yVal; + + for (int y = area.top; y < area.bottom; ++y) { + for (int x = area.left; x < area.right; ++x) { + newR = newG = newB = 0; + + for (int j = 0; j < 3; ++j) { + yVal = MIN(MAX(y - 1 + j, 0), area.bottom - 1); + + for (int i = 0; i < 3; ++i) { + ptr = (PixelType *)Base::_activeSurface->getBasePtr(MIN(MAX(x - 1 + j, 0), area.right - 1), yVal); + colorToRGB((uint32)*ptr, r, g, b); + + newR += r * filter[j][i]; + newG += g * filter[j][i]; + newB += b * filter[j][i]; + } + } + + newR = (newR / filterDiv) + offset; + newG = (newG / filterDiv) + offset; + newB = (newB / filterDiv) + offset; + + ptr = (PixelType *)Base::_activeSurface->getBasePtr(x, y); + *ptr = RGBToColor(CLIP(newR, 0, 255), CLIP(newG, 0, 255), CLIP(newB, 0, 255)); + } + } +} + +template +void VectorRendererSpec:: +setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { + _gradientEnd = RGBToColor(r2, g2, b2); + _gradientStart = RGBToColor(r1, g1, b1); + + Base::_gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); + Base::_gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); + Base::_gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); +} + +template +void VectorRendererSpec:: +fillSurface() { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); + + int w = _activeSurface->w; + int h = _activeSurface->h ; + int pitch = surfacePitch(); + + if (Base::_fillMode == kFillBackground) + colorFill(ptr, ptr + w * h, _bgColor); + else if (Base::_fillMode == kFillForeground) + colorFill(ptr, ptr + w * h, _fgColor); + else if (Base::_fillMode == kFillGradient) { + int i = h; + while (i--) { + colorFill(ptr, ptr + w, calcGradient(h - i, h)); + ptr += pitch; + } + } +} + +template +void VectorRendererSpec:: +copyFrame(OSystem *sys, const Common::Rect &r) { + + sys->copyRectToOverlay( + +#ifdef OVERLAY_MULTIPLE_DEPTHS + (const PixelType*) +#else + (const OverlayColor*) +#endif + + _activeSurface->getBasePtr(r.left, r.top), _activeSurface->w, + r.left, r.top, r.width(), r.height() + ); +} + +template +void VectorRendererSpec:: +blitSurface(const Graphics::Surface *source, const Common::Rect &r) { + assert(source->w == _activeSurface->w && source->h == _activeSurface->h); + + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); + PixelType *src_ptr = (PixelType *)source->getBasePtr(r.left, r.top); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int h = r.height(), w = r.width(); + + while (h--) { + colorCopy(src_ptr, dst_ptr, w); + dst_ptr += dst_pitch; + src_ptr += src_pitch; + } +} + +template +void VectorRendererSpec:: +blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) { + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(r.left, r.top); + PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int h = r.height(), w = r.width(); + + while (h--) { + colorCopy(src_ptr, dst_ptr, w); + dst_ptr += dst_pitch; + src_ptr += src_pitch; + } +} + +template +void VectorRendererSpec:: +blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { + int16 x = r.left; + int16 y = r.top; + + if (r.width() > source->w) + x = x + (r.width() >> 1) - (source->w >> 1); + + if (r.height() > source->h) + y = y + (r.height() >> 1) - (source->h >> 1); + + PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + PixelType *src_ptr = (PixelType *)source->getBasePtr(0, 0); + + int dst_pitch = surfacePitch(); + int src_pitch = source->pitch / source->bytesPerPixel; + + int w, h = source->h; + + while (h--) { + w = source->w; + + while (w--) { + if (*src_ptr != _bitmapAlphaColor) + *dst_ptr = *src_ptr; + + dst_ptr++; + src_ptr++; + } + + dst_ptr = dst_ptr - source->w + dst_pitch; + src_ptr = src_ptr - source->w + src_pitch; + } +} + +template +void VectorRendererSpec:: +applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { + int pixels = _activeSurface->w * _activeSurface->h; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); + uint8 r, g, b; + uint lum; + + if (shadingStyle == GUI::Theme::kShadingDim) { + while (pixels--) { + colorToRGB(*ptr, r, g, b); + r = r * _dimPercentValue >> 8; + g = g * _dimPercentValue >> 8; + b = b * _dimPercentValue >> 8; + *ptr++ = RGBToColor(r, g, b); + } + } else if (shadingStyle == GUI::Theme::kShadingLuminance) { + while (pixels--) { + colorToRGB(*ptr, r, g, b); + lum = (r >> 2) + (g >> 1) + (b >> 3); + *ptr++ = RGBToColor(lum, lum, lum); + } + } +} + +template +inline void VectorRendererSpec:: +blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + if (!ptr) return; + + if (alpha == 255) { + *ptr = color; + return; + } + + register int idst = *ptr; + register int isrc = color; + + *ptr = (PixelType)( + (PixelFormat::kRedMask & ((idst & PixelFormat::kRedMask) + + ((int)(((int)(isrc & PixelFormat::kRedMask) - + (int)(idst & PixelFormat::kRedMask)) * alpha) >> 8))) | + (PixelFormat::kGreenMask & ((idst & PixelFormat::kGreenMask) + + ((int)(((int)(isrc & PixelFormat::kGreenMask) - + (int)(idst & PixelFormat::kGreenMask)) * alpha) >> 8))) | + (PixelFormat::kBlueMask & ((idst & PixelFormat::kBlueMask) + + ((int)(((int)(isrc & PixelFormat::kBlueMask) - + (int)(idst & PixelFormat::kBlueMask)) * alpha) >> 8))) ); +} + +template +inline PixelType VectorRendererSpec:: +calcGradient(uint32 pos, uint32 max) { + PixelType output = 0; + pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; + + output |= (_gradientStart + ((Base::_gradientBytes[0] * pos) >> 12)) & PixelFormat::kRedMask; + output |= (_gradientStart + ((Base::_gradientBytes[1] * pos) >> 12)) & PixelFormat::kGreenMask; + output |= (_gradientStart + ((Base::_gradientBytes[2] * pos) >> 12)) & PixelFormat::kBlueMask; + output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask); + + return output; +} + +template +void VectorRendererSpec:: +colorFill(PixelType *first, PixelType *last, PixelType color) { + if (first == last) { + *first = color; + return; + } + + register PixelType *ptr = first; + register int count = (last - first); + register int n = (count + 7) >> 3; + switch (count % 8) { + case 0: do { + *ptr++ = color; + case 7: *ptr++ = color; + case 6: *ptr++ = color; + case 5: *ptr++ = color; + case 4: *ptr++ = color; + case 3: *ptr++ = color; + case 2: *ptr++ = color; + case 1: *ptr++ = color; + } while (--n > 0); + } +} + +template +inline void VectorRendererSpec:: +colorCopy(PixelType *src, PixelType *dst, int count) { + register int n = (count + 7) >> 3; + switch (count % 8) { + case 0: do { + *dst++ = *src++; + case 7: *dst++ = *src++; + case 6: *dst++ = *src++; + case 5: *dst++ = *src++; + case 4: *dst++ = *src++; + case 3: *dst++ = *src++; + case 2: *dst++ = *src++; + case 1: *dst++ = *src++; + } while (--n > 0); + } +} + +/******************************************************************** + ******************************************************************** + * Primitive shapes drawing - Public API calls - VectorRendererSpec * + ******************************************************************** + ********************************************************************/ +template +void VectorRendererSpec:: +drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, + GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, int deltax, bool ellipsis) { + + int offset = area.top; + + if (font->getFontHeight() < area.height()) { + switch (alignV) { + case GUI::Theme::kTextAlignVCenter: + offset = area.top + ((area.height() - font->getFontHeight()) >> 1); + break; + case GUI::Theme::kTextAlignVBottom: + offset = area.bottom - font->getFontHeight(); + break; + default: + break; + } + } + + font->drawString(_activeSurface, text, area.left, offset, area.width(), _fgColor, (Graphics::TextAlignment)alignH, deltax, ellipsis); +} + +/** LINES **/ +template +void VectorRendererSpec:: +drawLine(int x1, int y1, int x2, int y2) { + x1 = CLIP(x1, 0, (int)Base::_activeSurface->w); + x2 = CLIP(x2, 0, (int)Base::_activeSurface->w); + y1 = CLIP(y1, 0, (int)Base::_activeSurface->h); + y2 = CLIP(y2, 0, (int)Base::_activeSurface->h); + + // we draw from top to bottom + if (y2 < y1) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + int dx = ABS(x2 - x1); + int dy = ABS(y2 - y1); + + // this is a point, not a line. stoopid. + if (dy == 0 && dx == 0) + return; + + if (Base::_strokeWidth == 0) + return; + + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = Base::surfacePitch(); + int st = Base::_strokeWidth >> 1; + + if (dy == 0) { // horizontal lines + // these can be filled really fast with a single memset. + colorFill(ptr, ptr + dx + 1, (PixelType)_fgColor); + + for (int i = 0, p = pitch; i < st; ++i, p += pitch) { + colorFill(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor); + colorFill(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor); + } + + } else if (dx == 0) { // vertical lines + // these ones use a static pitch increase. + while (y1++ <= y2) { + colorFill(ptr - st, ptr + st, (PixelType)_fgColor); + ptr += pitch; + } + + } else if (ABS(dx) == ABS(dy)) { // diagonal lines + // these ones also use a fixed pitch increase + pitch += (x2 > x1) ? 1 : -1; + + while (dy--) { + colorFill(ptr - st, ptr + st, (PixelType)_fgColor); + ptr += pitch; + } + + } else { // generic lines, use the standard algorithm... + drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor); + } +} + +/** CIRCLES **/ +template +void VectorRendererSpec:: +drawCircle(int x, int y, int r) { + if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h || + x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0) + return; + + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset + && x + r + Base::_shadowOffset < Base::_activeSurface->w + && y + r + Base::_shadowOffset < Base::_activeSurface->h) { + drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground); + } + + switch (Base::_fillMode) { + case kFillDisabled: + if (Base::_strokeWidth) + drawCircleAlg(x, y, r, _fgColor, kFillDisabled); + break; + + case kFillForeground: + drawCircleAlg(x, y, r, _fgColor, kFillForeground); + break; + + case kFillBackground: + if (Base::_strokeWidth > 1) { + drawCircleAlg(x, y, r, _fgColor, kFillForeground); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground); + } else { + drawCircleAlg(x, y, r, _bgColor, kFillBackground); + drawCircleAlg(x, y, r, _fgColor, kFillDisabled); + } + break; + + case kFillGradient: + break; + } +} + +/** SQUARES **/ +template +void VectorRendererSpec:: +drawSquare(int x, int y, int w, int h) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0) + return; + + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset + && x + w + Base::_shadowOffset < Base::_activeSurface->w + && y + h + Base::_shadowOffset < Base::_activeSurface->h) { + drawSquareShadow(x, y, w, h, Base::_shadowOffset); + } + + switch (Base::_fillMode) { + case kFillDisabled: + if (Base::_strokeWidth) + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); + break; + + case kFillForeground: + drawSquareAlg(x, y, w, h, _fgColor, kFillForeground); + break; + + case kFillBackground: + drawSquareAlg(x, y, w, h, _bgColor, kFillBackground); + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); + break; + + case kFillGradient: + VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient); + if (Base::_strokeWidth) + drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled); + break; + } +} + +/** ROUNDED SQUARES **/ +template +void VectorRendererSpec:: +drawRoundedSquare(int x, int y, int r, int w, int h) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0) + return; + + if ((r << 1) > w || (r << 1) > h) + r = MIN(w >> 1, h >> 1); + + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset + && x + w + Base::_shadowOffset < Base::_activeSurface->w + && y + h + Base::_shadowOffset < Base::_activeSurface->h) { + drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); + } + + switch (Base::_fillMode) { + case kFillDisabled: + if (Base::_strokeWidth) + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); + break; + + case kFillForeground: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); + break; + + case kFillBackground: + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillBackground); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); + break; + + case kFillGradient: + if (Base::_strokeWidth > 1) { + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); + VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, + r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillGradient); + } else { + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillGradient); + if (Base::_strokeWidth) + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); + } + break; + } + + if (Base::_bevel) + drawRoundedSquareFakeBevel(x, y, r, w, h, Base::_bevel); +} + +template +void VectorRendererSpec:: +drawTab(int x, int y, int r, int w, int h) { + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h || + w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h) + return; + + if (r == 0 && Base::_bevel > 0) { + drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); + return; + } + + if (r == 0) return; + + switch (Base::_fillMode) { + case kFillDisabled: + return; + + case kFillGradient: + case kFillBackground: + drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + if (Base::_strokeWidth) + drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); + break; + + case kFillForeground: + drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + break; + } +} + +template +void VectorRendererSpec:: +drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { + + if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h) + return; + + PixelType color = 0; + + if (Base::_strokeWidth <= 1) { + if (Base::_fillMode == kFillForeground) + color = _fgColor; + else if (Base::_fillMode == kFillBackground) + color = _bgColor; + } else { + if (Base::_fillMode == kFillDisabled) + return; + color = _fgColor; + } + + if (Base::_dynamicData != 0) + orient = (TriangleOrientation)Base::_dynamicData; + + int newW = w / 2; + if (newW % 2) newW++; + + switch(orient) { + case kTriangleUp: + case kTriangleDown: + drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), color, Base::_fillMode); + break; + + case kTriangleLeft: + case kTriangleRight: + case kTriangleAuto: + break; + } + + if (Base::_strokeWidth > 0) + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { + drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), _fgColor, kFillDisabled); + } +} + + + + + +/******************************************************************** + ******************************************************************** + * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec + ******************************************************************** + ********************************************************************/ +/** TAB ALGORITHM - NON AA */ +template +void VectorRendererSpec:: +drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + int sw = 0, sp = 0, hp = 0; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int real_radius = r; + int short_h = h - r + 2; + int long_h = h; + + if (fill_m == kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += pitch; + + __BE_RESET(); + r--; + + while (x++ < y) { + __BE_ALGORITHM(); + *(ptr_tr + (y) - (px)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px)) = color; + + if (Base::_strokeWidth > 1) { + *(ptr_tr + (y) - (px - pitch)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px - pitch)) = color; + } + } + } + + ptr_fill += pitch * real_radius; + while (short_h--) { + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth - 1, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 2, ptr_fill + w, color); + ptr_fill += pitch; + } + + if (baseLeft) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h); + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill - baseLeft, ptr_fill, color); + ptr_fill += pitch; + } + } + + if (baseRight) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h); + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill, ptr_fill + baseRight, color); + ptr_fill += pitch; + } + } + } else { + __BE_RESET(); + + PixelType color1, color2; + color1 = color2 = color; + + while (x++ < y) { + __BE_ALGORITHM(); + + if (fill_m == kFillGradient) { + color1 = calcGradient(real_radius - x, long_h); + color2 = calcGradient(real_radius - y, long_h); + } + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); + + *(ptr_tr + (y) - (px)) = color1; + *(ptr_tr + (x) - (py)) = color2; + *(ptr_tl - (x) - (py)) = color2; + *(ptr_tl - (y) - (px)) = color1; + } + + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kFillGradient) + color = calcGradient(real_radius++, long_h); + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } +} + + +/** BEVELED TABS FOR CLASSIC THEME **/ +template +void VectorRendererSpec:: +drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) { + int pitch = Base::surfacePitch(); + int i, j; + + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + + i = bevel; + while (i--) { + colorFill(ptr_left, ptr_left + w, top_color); + ptr_left += pitch; + } + + if (baseLeft > 0) { + i = h - bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + while (i--) { + colorFill(ptr_left, ptr_left + bevel, top_color); + ptr_left += pitch; + } + } + + i = h - bevel; + j = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); + while (i--) { + colorFill(ptr_left + j, ptr_left + bevel, bottom_color); + if (j > 0) j--; + ptr_left += pitch; + } + + i = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel); + while (i--) { + colorFill(ptr_left, ptr_left + baseRight + bevel, bottom_color); + + if (baseLeft) + colorFill(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color); + ptr_left += pitch; + } +} + +/** SQUARE ALGORITHM **/ +template +void VectorRendererSpec:: +drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + int pitch = Base::surfacePitch(); + int max_h = h; + + if (fill_m != kFillDisabled) { + while (h--) { + if (fill_m == kFillGradient) + color = calcGradient(max_h - h, max_h); + + colorFill(ptr, ptr + w, color); + ptr += pitch; + } + } else { + int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1); + + while (sw--) { + colorFill(ptr + sp, ptr + w + sp, color); + colorFill(ptr + hp - sp, ptr + w + hp - sp, color); + sp += pitch; + } + + while (h--) { + colorFill(ptr, ptr + Base::_strokeWidth, color); + colorFill(ptr + w - Base::_strokeWidth, ptr + w, color); + ptr += pitch; + } + } +} + +/** SQUARE ALGORITHM **/ +template +void VectorRendererSpec:: +drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) { + int pitch = Base::surfacePitch(); + + int height = h; + PixelType *ptr_fill = (PixelType *)_activeSurface->getBasePtr(x, y); + + if (fill) { + while (height--) { + blendFill(ptr_fill, ptr_fill + w, _bgColor, 200); + ptr_fill += pitch; + } + } + + int i, j; + x = MAX(x - bevel, 0); + y = MAX(y - bevel, 0); + h += bevel << 1; + w += bevel << 1; + + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); + + i = bevel; + while (i--) { + colorFill(ptr_left, ptr_left + w, top_color); + ptr_left += pitch; + } + + i = h - bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel); + while (i--) { + colorFill(ptr_left, ptr_left + bevel, top_color); + ptr_left += pitch; + } + + i = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel); + while (i--) { + colorFill(ptr_left + i, ptr_left + w, bottom_color); + ptr_left += pitch; + } + + i = h - bevel; + j = bevel; + ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); + while (i--) { + colorFill(ptr_left + j, ptr_left + bevel, bottom_color); + if (j > 0) j--; + ptr_left += pitch; + } +} + +/** GENERIC LINE ALGORITHM **/ +template +void VectorRendererSpec:: +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); + int pitch = Base::surfacePitch(); + int xdir = (x2 > x1) ? 1 : -1; + + *ptr = (PixelType)color; + + if (dx > dy) { + int ddy = dy * 2; + int dysub = ddy - (dx * 2); + int error_term = ddy - dx; + + while (dx--) { + if (error_term >= 0) { + ptr += pitch; + error_term += dysub; + } else { + error_term += ddy; + } + + ptr += xdir; + *ptr = (PixelType)color; + } + } else { + int ddx = dx * 2; + int dxsub = ddx - (dy * 2); + int error_term = ddx - dy; + + while (dy--) { + if (error_term >= 0) { + ptr += xdir; + error_term += dxsub; + } else { + error_term += ddx; + } + + ptr += pitch; + *ptr = (PixelType)color; + } + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2); + *ptr = (PixelType)color; +} + +/** VERTICAL TRIANGLE DRAWING ALGORITHM **/ +template +void VectorRendererSpec:: +drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { + int dx = w >> 1, dy = h, gradient_h = 0; + int pitch = Base::surfacePitch(); + PixelType *ptr_right = 0, *ptr_left = 0; + + if (inverted) { + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); + } else { + ptr_right = ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + dx, y1); + } + + if (dx > dy) { + int ddy = dy * 2; + int dysub = ddy - (dx * 2); + int error_term = ddy - dx; + + switch(fill_m) { + case kFillDisabled: + while (dx--) { + __TRIANGLE_MAINX(); + *ptr_right = color; + *ptr_left = color; + } + colorFill(ptr_left, ptr_right, color); + break; + + case kFillForeground: + case kFillBackground: + while (dx--) { + __TRIANGLE_MAINX(); + if (inverted) colorFill(ptr_right, ptr_left, color); + else colorFill(ptr_left, ptr_right, color); + } + break; + + case kFillGradient: + while (dx--) { + __TRIANGLE_MAINX(); + if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + } + break; + } + } else { + int ddx = dx * 2; + int dxsub = ddx - (dy * 2); + int error_term = ddx - dy; + + switch(fill_m) { + case kFillDisabled: + while (dy--) { + __TRIANGLE_MAINY(); + *ptr_right = color; + *ptr_left = color; + } + colorFill(ptr_left, ptr_right, color); + break; + + case kFillForeground: + case kFillBackground: + while (dy--) { + __TRIANGLE_MAINY(); + if (inverted) colorFill(ptr_right, ptr_left, color); + else colorFill(ptr_left, ptr_right, color); + } + break; + case kFillGradient: + while (dy--) { + __TRIANGLE_MAINY(); + if (inverted) colorFill(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + else colorFill(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + } + break; + } + } +} + + +/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */ +template +void VectorRendererSpec:: +drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { + int pitch = Base::surfacePitch(); + int hstep = 0, dy = size; + bool grad = (fill_m == kFillGradient); + + PixelType *ptr_right = 0, *ptr_left = 0; + + if (inverted) { + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1); + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); + } else { + ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1 + size); + ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1 + size); + pitch = -pitch; + } + + if (fill_m == kFillDisabled) { + while (ptr_left < ptr_right) { + *ptr_left = color; + *ptr_right = color; + ptr_left += pitch; + ptr_right += pitch; + if (hstep++ % 2) { + ptr_left++; + ptr_right--; + } + } + } else { + while (ptr_left < ptr_right) { + colorFill(ptr_left, ptr_right, grad ? calcGradient(dy--, size) : color); + ptr_left += pitch; + ptr_right += pitch; + if (hstep++ % 2) { + ptr_left++; + ptr_right--; + } + } + } +} + +/** ROUNDED SQUARE ALGORITHM **/ +template +void VectorRendererSpec:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + int sw = 0, sp = 0, hp = h * pitch; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; + + if (fill_m == kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += pitch; + + __BE_RESET(); + r--; + + while (x++ < y) { + __BE_ALGORITHM(); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + + if (Base::_strokeWidth > 1) { + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); + } + } + } + + ptr_fill += pitch * real_radius; + while (short_h--) { + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } else { + __BE_RESET(); + PixelType color1, color2, color3, color4; + + if (fill_m == kFillGradient) { + while (x++ < y) { + __BE_ALGORITHM(); + + color1 = calcGradient(real_radius - x, long_h); + color2 = calcGradient(real_radius - y, long_h); + color3 = calcGradient(long_h - r + x, long_h); + color4 = calcGradient(long_h - r + y, long_h); + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color2); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); + + colorFill(ptr_bl - x + py, ptr_br + x + py, color4); + colorFill(ptr_bl - y + px, ptr_br + y + px, color3); + + __BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } + } else { + while (x++ < y) { + __BE_ALGORITHM(); + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color); + + colorFill(ptr_bl - x + py, ptr_br + x + py, color); + colorFill(ptr_bl - y + px, ptr_br + y + px, color); + + // do not remove - messes up the drawing at lower resolutions + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } + } + + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kFillGradient) + color = calcGradient(real_radius++, long_h); + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } +} + +/** CIRCLE ALGORITHM **/ +template +void VectorRendererSpec:: +drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { + int f, ddF_x, ddF_y; + int x, y, px, py, sw = 0; + int pitch = Base::surfacePitch(); + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + if (fill_m == kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + __BE_RESET(); + r--; + + *(ptr + y) = color; + *(ptr - y) = color; + *(ptr + py) = color; + *(ptr - py) = color; + + while (x++ < y) { + __BE_ALGORITHM(); + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py); + + if (Base::_strokeWidth > 1) { + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py); + __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py); + } + } + } + } else { + colorFill(ptr - r, ptr + r, color); + __BE_RESET(); + + while (x++ < y) { + __BE_ALGORITHM(); + colorFill(ptr - x + py, ptr + x + py, color); + colorFill(ptr - x - py, ptr + x - py, color); + colorFill(ptr - y + px, ptr + y + px, color); + colorFill(ptr - y - px, ptr + y - px, color); + } + } +} + + + + + +/******************************************************************** + ******************************************************************** + * SHADOW drawing algorithms - VectorRendererSpec ******************* + ******************************************************************** + ********************************************************************/ +template +void VectorRendererSpec:: +drawSquareShadow(int x, int y, int w, int h, int blur) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); + int pitch = Base::surfacePitch(); + int i, j; + + i = h - blur; + + while (i--) { + j = blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); + + while (i++ < blur) { + j = w - blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); + + i = 0; + while (i++ < blur) { + j = blur - 1; + while (j--) + blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); + ptr += pitch; + } +} + +template +void VectorRendererSpec:: +drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = Base::surfacePitch(); + int alpha = 102; + + x1 += blur; + y1 += blur; + + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r); + + int short_h = h - (2 * r) + 1; + + __BE_RESET(); + + // HACK: As we are drawing circles exploting 8-axis symmetry, + // there are 4 pixels on each circle which are drawn twice. + // this is ok on filled circles, but when blending on surfaces, + // we cannot let it blend twice. awful. + uint32 hb = 0; + + while (x++ < y) { + __BE_ALGORITHM(); + + if (((1 << x) & hb) == 0) { + blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); + blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha); + hb |= (1 << x); + } + + if (((1 << y) & hb) == 0) { + blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha); + blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha); + hb |= (1 << y); + } + } + + while (short_h--) { + blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha); + ptr_fill += pitch; + } +} + +template +void VectorRendererSpec:: +drawRoundedSquareFakeBevel(int x1, int y1, int r, int w, int h, int amount) { + int x, y; + int p = Base::surfacePitch(), px, py; + int sw = 0, sp = 0; + + uint32 rsq = (r * r) << 16; + uint32 T = 0, oldT; + uint8 a1, a2; + + PixelType color = _bevelColor; //RGBToColor(63, 60, 17); + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int short_h = h - 2 * r; + + while (sw++ < amount) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + sp += p; + + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); + + blendPixelPtr(ptr_tr + (y) - (px - p), color, a2); + blendPixelPtr(ptr_tr + (x - 1) - (py), color, a2); + blendPixelPtr(ptr_tl - (x - 1) - (py), color, a2); + blendPixelPtr(ptr_tl - (y) - (px - p), color, a2); + blendPixelPtr(ptr_bl - (y) + (px - p), color, a2); + blendPixelPtr(ptr_bl - (x - 1) + (py), color, a2); + + blendPixelPtr(ptr_tr + (y) - (px), color, a1); + blendPixelPtr(ptr_tr + (x) - (py), color, a1); + blendPixelPtr(ptr_tl - (x) - (py), color, a1); + blendPixelPtr(ptr_tl - (y) - (px), color, a1); + blendPixelPtr(ptr_bl - (y) + (px), color, a1); + blendPixelPtr(ptr_bl - (x) + (py), color, a1); + } + } + + ptr_fill += p * r; + while (short_h-- >= 0) { + colorFill(ptr_fill, ptr_fill + amount, color); + ptr_fill += p; + } +} + + + + + + + +/******************************************************************************/ + + + + + + + + + +/******************************************************************** + * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA + ********************************************************************/ +/** LINES **/ +template +void VectorRendererAA:: +drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { + + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + int pitch = Base::surfacePitch(); + int xdir = (x2 > x1) ? 1 : -1; + uint16 error_tmp, error_acc, gradient; + uint8 alpha; + + *ptr = (PixelType)color; + + if (dx > dy) { + gradient = (uint32)(dy << 16) / (uint32)dx; + error_acc = 0; + + while (--dx) { + error_tmp = error_acc; + error_acc += gradient; + + if (error_acc <= error_tmp) + ptr += pitch; + + ptr += xdir; + alpha = (error_acc >> 8); + + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + pitch, color, alpha); + } + } else { + gradient = (uint32)(dx << 16) / (uint32)dy; + error_acc = 0; + + while (--dy) { + error_tmp = error_acc; + error_acc += gradient; + + if (error_acc <= error_tmp) + ptr += xdir; + + ptr += pitch; + alpha = (error_acc >> 8); + + blendPixelPtr(ptr, color, ~alpha); + blendPixelPtr(ptr + xdir, color, alpha); + } + } + + Base::putPixel(x2, y2, color); +} + +/** ROUNDED SQUARES **/ +template +void VectorRendererAA:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + int x, y; + int p = Base::surfacePitch(), px, py; + int sw = 0, sp = 0, hp = h * p; + + uint32 rsq = (r * r) << 16; + uint32 T = 0, oldT; + uint8 a1, a2; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int short_h = h - 2 * r; + + if (fill_m == VectorRenderer::kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += p; + + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); + + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; + + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } + } + + ptr_fill += p * r; + while (short_h-- >= 0) { + colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color); + colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += p; + } + } else { + x = r; y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); + + colorFill(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color); + + colorFill(ptr_bl - x + py, ptr_br + x + py, color); + colorFill(ptr_bl - y + px, ptr_br + y + px, color); + + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } + + ptr_fill += p * r; + while (short_h-- >= 0) { + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += p; + } + } +} + +/** CIRCLES **/ +template +void VectorRendererAA:: +drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { + int x, y, sw = 0; + int p = Base::surfacePitch(), px, py; + + uint32 rsq = (r * r) << 16; + uint32 T = 0, oldT; + uint8 a1, a2; + + PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + if (fill_m == VectorRenderer::kFillDisabled) { + while (sw++ < Base::_strokeWidth) { + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + *(ptr + x) = (PixelType)color; + *(ptr - x) = (PixelType)color; + *(ptr + px) = (PixelType)color; + *(ptr - px) = (PixelType)color; + + while (x > y++) { + __WU_ALGORITHM(); + + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } + } + } else { + colorFill(ptr - r, ptr + r + 1, color); + x = r; y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); + + colorFill(ptr - x + py, ptr + x + py, color); + colorFill(ptr - x - py, ptr + x - py, color); + colorFill(ptr - y + px, ptr + y + px, color); + colorFill(ptr - y - px, ptr + y - px, color); + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } + } +} + + +} diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h new file mode 100644 index 0000000000..4d30e5a75a --- /dev/null +++ b/graphics/VectorRendererSpec.h @@ -0,0 +1,310 @@ +/* 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 VECTOR_RENDERER_SPEC_H +#define VECTOR_RENDERER_SPEC_H + +#include "graphics/VectorRenderer.h" + +namespace Graphics { + +/** + * VectorRendererSpec: Specialized Vector Renderer Class + * + * This templated class implements the basic subset of vector operations for + * all platforms by allowing the user to provide the actual Pixel Type and + * pixel information structs. + * + * This class takes two template parameters: + * + * @param PixelType Defines a type which may hold the color value of a single + * pixel, such as "byte" or "uint16" for 8 and 16 BPP respectively. + * + * @param PixelFormat Defines the type of the PixelFormat struct which contains all + * the actual information of the pixels being used, as declared in "graphics/colormasks.h" + * + * TODO: Expand documentation. + * + * @see VectorRenderer + */ +template +class VectorRendererSpec : public VectorRenderer { + typedef VectorRenderer Base; + +public: + VectorRendererSpec() { + _bitmapAlphaColor = RGBToColor(255, 0, 255); + } + + void drawLine(int x1, int y1, int x2, int y2); + void drawCircle(int x, int y, int r); + void drawSquare(int x, int y, int w, int h); + void drawRoundedSquare(int x, int y, int r, int w, int h); + void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); + void drawTab(int x, int y, int r, int w, int h); + void drawBeveledSquare(int x, int y, int w, int h, int bevel) { + drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled); + } + void drawString(const Graphics::Font *font, const Common::String &text, + const Common::Rect &area, GUI::Theme::TextAlign alignH, + GUI::Theme::TextAlignVertical alignV, int deltax, bool elipsis); + + void setFgColor(uint8 r, uint8 g, uint8 b) { _fgColor = RGBToColor(r, g, b); } + void setBgColor(uint8 r, uint8 g, uint8 b) { _bgColor = RGBToColor(r, g, b); } + void setBevelColor(uint8 r, uint8 g, uint8 b) { _bevelColor = RGBToColor(r, g, b); } + void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2); + + virtual void copyFrame(OSystem *sys, const Common::Rect &r); + virtual void copyWholeFrame(OSystem *sys) { copyFrame(sys, Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); } + + virtual void fillSurface(); + virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r); + virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r); + virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r); + + virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle); + +protected: + + /** + * Draws a single pixel on the surface with the given coordinates and + * the given color. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param color Color of the pixel + */ + virtual inline void putPixel(int x, int y, PixelType color) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); + *ptr = color; + } + + /** + * Blends a single pixel on the surface with the given coordinates, color + * and Alpha intensity. + * + * @param x Horizontal coordinate of the pixel. + * @param y Vertical coordinate of the pixel. + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) + */ + virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { + if (alpha == 255) + putPixel(x, y, color); + else if (alpha > 0) + blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); + } + + /** + * Blends a single pixel on the surface in the given pixel pointer, using supplied color + * and Alpha intensity. + * + * This is implemented to prevent blendPixel() to calculate the surface pointer on each call. + * Optimized drawing algorithms should call this function when possible. + * + * @see blendPixel + * @param ptr Pointer to the pixel to blend on top of + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) + */ + virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); + + /** + * PRIMITIVE DRAWING ALGORITHMS + * + * Generic algorithms for drawing all kinds of aliased primitive shapes. + * These may be overloaded in inheriting classes to implement platform-specific + * optimizations or improve looks. + * + * @see VectorRendererAA + * @see VectorRendererAA::drawLineAlg + * @see VectorRendererAA::drawCircleAlg + */ + virtual void drawLineAlg(int x1, int y1, int x2, int y2, + int dx, int dy, PixelType color); + + virtual void drawCircleAlg(int x, int y, int r, + PixelType color, FillMode fill_m); + + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, + PixelType color, FillMode fill_m); + + virtual void drawSquareAlg(int x, int y, int w, int h, + PixelType color, FillMode fill_m); + + virtual void drawTriangleVertAlg(int x, int y, int w, int h, + bool inverted, PixelType color, FillMode fill_m); + + virtual void drawTriangleFast(int x, int y, int size, + bool inverted, PixelType color, FillMode fill_m); + + virtual void drawBevelSquareAlg(int x, int y, int w, int h, + int bevel, PixelType top_color, PixelType bottom_color, bool fill); + + virtual void drawTabAlg(int x, int y, int w, int h, int r, + PixelType color, VectorRenderer::FillMode fill_m, + int baseLeft = 0, int baseRight = 0); + + virtual void drawBevelTabAlg(int x, int y, int w, int h, + int bevel, PixelType topColor, PixelType bottomColor, + int baseLeft = 0, int baseRight = 0); + + /** + * SHADOW DRAWING ALGORITHMS + * + * Optimized versions of the primitive drawing algorithms with alpha blending + * for shadow drawing. + * There functions may be overloaded in inheriting classes to improve performance + * in the slowest platforms where pixel alpha blending just doesn't cut it. + * + * @param blur Intensity/size of the shadow. + */ + virtual void drawSquareShadow(int x, int y, int w, int h, int blur); + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); + virtual void drawRoundedSquareFakeBevel(int x, int y, int r, int w, int h, int amount); + + /** + * Calculates the color gradient on a given point. + * This function assumes that the gradient start/end colors have been set + * beforehand from the API function call. + * + * @param pos Progress of the gradient. + * @param max Maximum amount of the progress. + * @return Composite color of the gradient at the given "progress" amount. + */ + virtual inline PixelType calcGradient(uint32 pos, uint32 max); + + /** + * Fills several pixels in a row with a given color and the specifed alpha blending. + * + * @see blendPixelPtr + * @see blendPixel + * @param first Pointer to the first pixel to fill. + * @param last Pointer to the last pixel to fill. + * @param color Color of the pixel + * @param alpha Alpha intensity of the pixel (0-255) + */ + virtual inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { + while (first != last) blendPixelPtr(first++, color, alpha); + } + + /** + * Fills several pixels in a row with a given color. + * + * This is a replacement function for Common::set_to, using an unrolled + * loop to maximize performance on most architectures. + * This function may (and should) be overloaded in any child renderers + * for portable platforms with platform-specific assembly code. + * + * This fill operation is extensively used throughout the renderer, so this + * counts as one of the main bottlenecks. Please replace it with assembly + * when possible! + * + * @param first Pointer to the first pixel to fill. + * @param last Pointer to the last pixel to fill. + * @param color Color of the pixel + */ + virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color); + + /** + * Copies several pixes in a row from a surface to another one. + * Used for surface blitting. + * See colorFill() for optimization guidelines. + * + * @param src Source surface. + * @param dst Destination surface. + * @param count Amount of pixels to copy over. + */ + virtual inline void colorCopy(PixelType *src, PixelType *dst, int count); + + virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); + + PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ + PixelType _bgColor; /** Background color currently being used to draw on the renderer */ + + PixelType _gradientStart; /** Start color for the fill gradient */ + PixelType _gradientEnd; /** End color for the fill gradient */ + + PixelType _bevelColor; + PixelType _bitmapAlphaColor; +}; + + +/** + * VectorRendererAA: Anti-Aliased Vector Renderer Class + * + * This templated class inherits all the functionality of the VectorRendererSpec + * class but uses better looking yet slightly slower AA algorithms for drawing + * most primivitves. May be used in faster platforms. + * + * TODO: Expand documentation. + * + * @see VectorRenderer + * @see VectorRendererSpec + */ +template +class VectorRendererAA : public VectorRendererSpec { + typedef VectorRendererSpec Base; +protected: + /** + * "Wu's Line Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 + * Based on the implementation found in Michael Abrash's Graphics Programming Black Book. + * + * Generic line drawing algorithm for the Antialiased renderer. Optimized with no + * floating point operations, assumes no special cases. + * + * @see VectorRenderer::drawLineAlg() + */ + virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); + + /** + * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991 + * Based on the theoretical concept of the algorithm. + * + * Implementation of Wu's algorithm for circles using fixed point arithmetics. + * Could be quite fast. + * + * @see VectorRenderer::drawCircleAlg() + */ + virtual void drawCircleAlg(int x, int y, int r, PixelType color, VectorRenderer::FillMode fill_m); + + /** + * "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991, + * modified with corner displacement to allow drawing of squares with rounded + * corners. + * + * @see VectorRenderer::drawRoundedAlg() + */ + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); + + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) { + Base::drawRoundedSquareShadow(x, y, r, w, h, blur); +// VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur, +// Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2)); + } +}; + +} +#endif \ No newline at end of file diff --git a/graphics/module.mk b/graphics/module.mk index b8dfd94ad2..b3618ddcfc 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -17,7 +17,8 @@ MODULE_OBJS := \ scaler.o \ scaler/thumbnail.o \ surface.o \ - VectorRenderer.o + VectorRenderer.o \ + VectorRendererSpec.o ifndef DISABLE_SCALERS MODULE_OBJS += \ -- cgit v1.2.3 From 83cc4e1c921eb7d17cfbf830b68c3564926bdf17 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 1 Sep 2008 12:41:46 +0000 Subject: Use memcpy instead of hand-rolled colorCopy (on many systems, memcpy is hand-optimized asm or even a compiler built-in and *way* faster than any C code you could roll yourself -- it's way faster on my system, too) svn-id: r34238 --- graphics/VectorRendererSpec.cpp | 22 ++-------------------- graphics/VectorRendererSpec.h | 11 ----------- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 908b9eb1a3..4819ea8336 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -262,7 +262,7 @@ blitSurface(const Graphics::Surface *source, const Common::Rect &r) { int h = r.height(), w = r.width(); while (h--) { - colorCopy(src_ptr, dst_ptr, w); + memcpy(dst_ptr, src_ptr, w * sizeof(PixelType)); dst_ptr += dst_pitch; src_ptr += src_pitch; } @@ -280,7 +280,7 @@ blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) { int h = r.height(), w = r.width(); while (h--) { - colorCopy(src_ptr, dst_ptr, w); + memcpy(dst_ptr, src_ptr, w * sizeof(PixelType)); dst_ptr += dst_pitch; src_ptr += src_pitch; } @@ -411,24 +411,6 @@ colorFill(PixelType *first, PixelType *last, PixelType color) { } } -template -inline void VectorRendererSpec:: -colorCopy(PixelType *src, PixelType *dst, int count) { - register int n = (count + 7) >> 3; - switch (count % 8) { - case 0: do { - *dst++ = *src++; - case 7: *dst++ = *src++; - case 6: *dst++ = *src++; - case 5: *dst++ = *src++; - case 4: *dst++ = *src++; - case 3: *dst++ = *src++; - case 2: *dst++ = *src++; - case 1: *dst++ = *src++; - } while (--n > 0); - } -} - /******************************************************************** ******************************************************************** * Primitive shapes drawing - Public API calls - VectorRendererSpec * diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index 4d30e5a75a..04f28d4020 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -227,17 +227,6 @@ protected: * @param color Color of the pixel */ virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color); - - /** - * Copies several pixes in a row from a surface to another one. - * Used for surface blitting. - * See colorFill() for optimization guidelines. - * - * @param src Source surface. - * @param dst Destination surface. - * @param count Amount of pixels to copy over. - */ - virtual inline void colorCopy(PixelType *src, PixelType *dst, int count); virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); -- cgit v1.2.3 From dcc72fe29e9b77c1f6dfad4612d5b32b64b610dd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2008 17:51:08 +0000 Subject: Massive refactoring/cleanup on the theme engine/parser. svn-id: r34285 --- base/main.cpp | 2 +- dists/msvc9/scummvm.vcproj | 40 +- graphics/VectorRenderer.cpp | 2 +- graphics/VectorRenderer.h | 2 +- graphics/VectorRendererSpec.cpp | 6 +- gui/ThemeEngine.cpp | 1073 +++++++++++++++++++++++++++++++++++++++ gui/ThemeEngine.h | 744 +++++++++++++++++++++++++++ gui/ThemeEval.cpp | 170 ++----- gui/ThemeEval.h | 305 +---------- gui/ThemeLayout.cpp | 227 +++++++++ gui/ThemeLayout.h | 239 +++++++++ gui/ThemeParser.cpp | 4 +- gui/ThemeParser.h | 8 +- gui/ThemeRenderer.cpp | 1045 -------------------------------------- gui/ThemeRenderer.h | 732 -------------------------- gui/module.mk | 3 +- gui/newgui.cpp | 14 +- gui/newgui.h | 4 +- gui/options.cpp | 6 +- gui/theme.h | 2 +- 20 files changed, 2376 insertions(+), 2252 deletions(-) create mode 100644 gui/ThemeEngine.cpp create mode 100644 gui/ThemeEngine.h create mode 100644 gui/ThemeLayout.cpp create mode 100644 gui/ThemeLayout.h delete mode 100644 gui/ThemeRenderer.cpp delete mode 100644 gui/ThemeRenderer.h diff --git a/base/main.cpp b/base/main.cpp index 666d4fdfe3..031e8fd522 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -43,7 +43,7 @@ #include "common/system.h" #include "gui/newgui.h" #include "gui/message.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "gui/ThemeParser.h" #if defined(_WIN32_WCE) diff --git a/dists/msvc9/scummvm.vcproj b/dists/msvc9/scummvm.vcproj index 7fd256cd42..fc6713c49f 100644 --- a/dists/msvc9/scummvm.vcproj +++ b/dists/msvc9/scummvm.vcproj @@ -1205,31 +1205,39 @@ > - - - + + + + + + + + + + + diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index ae72ce0ce1..4f9bd48334 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -30,7 +30,7 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "graphics/VectorRenderer.h" #define VECTOR_RENDERER_FAST_TRIANGLES diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 8ba9126b3e..c2cd6b0010 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -32,7 +32,7 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" namespace Graphics { class VectorRenderer; diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 4819ea8336..a84a3d6f23 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -30,7 +30,7 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "graphics/VectorRenderer.h" #include "graphics/VectorRendererSpec.h" @@ -128,10 +128,10 @@ namespace Graphics { VectorRenderer *createRenderer(int mode) { switch (mode) { - case GUI::ThemeRenderer::kGfxStandard16bit: + case GUI::ThemeEngine::kGfxStandard16bit: return new VectorRendererSpec >; - case GUI::ThemeRenderer::kGfxAntialias16bit: + case GUI::ThemeEngine::kGfxAntialias16bit: return new VectorRendererAA >; default: diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp new file mode 100644 index 0000000000..006a8768a6 --- /dev/null +++ b/gui/ThemeEngine.cpp @@ -0,0 +1,1073 @@ +/* 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$ + * + */ + +#include "common/util.h" +#include "graphics/surface.h" +#include "graphics/colormasks.h" +#include "common/system.h" +#include "common/events.h" +#include "common/config-manager.h" +#include "common/fs.h" +#include "graphics/imageman.h" +#include "graphics/cursorman.h" +#include "gui/launcher.h" + +#include "gui/ThemeEngine.h" +#include "gui/ThemeEval.h" +#include "graphics/VectorRenderer.h" + +#define GUI_ENABLE_BUILTIN_THEME + +namespace GUI { + +using namespace Graphics; + +const char *ThemeEngine::rendererModeLabels[] = { + "Disabled GFX", + "Stardard Renderer (16bpp)", + "Antialiased Renderer (16bpp)" +}; + + +/********************************************************** + * ThemeItem functions for drawing queues. + *********************************************************/ +void ThemeItemDrawData::drawSelf(bool draw, bool restore) { + + Common::Rect extendedRect = _area; + extendedRect.grow(_engine->kDirtyRectangleThreshold + _data->_backgroundOffset); + + if (restore) + _engine->restoreBackground(extendedRect); + + if (draw) { + Common::List::const_iterator step; + for (step = _data->_steps.begin(); step != _data->_steps.end(); ++step) + _engine->renderer()->drawStep(_area, *step, _dynamicData); + } + + _engine->addDirtyRect(extendedRect); +} + +void ThemeItemTextData::drawSelf(bool draw, bool restore) { + if (_restoreBg || restore) + _engine->restoreBackground(_area); + + if (draw) { + _engine->renderer()->setFgColor(_data->_color.r, _data->_color.g, _data->_color.b); + _engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis); + } + + _engine->addDirtyRect(_area); +} + +void ThemeItemBitmap::drawSelf(bool draw, bool restore) { + if (restore) + _engine->restoreBackground(_area); + + if (draw) { + if (_alpha) + _engine->renderer()->blitAlphaBitmap(_bitmap, _area); + else + _engine->renderer()->blitSubSurface(_bitmap, _area); + } + + _engine->addDirtyRect(_area); +} + + + +/********************************************************** + * Data definitions for theme engine elements + *********************************************************/ +const ThemeEngine::DrawDataInfo ThemeEngine::kDrawDataDefaults[] = { + {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, + {kDDSpecialColorBackground, "special_bg", true, kDDNone}, + {kDDPlainColorBackground, "plain_bg", true, kDDNone}, + {kDDDefaultBackground, "default_bg", true, kDDNone}, + {kDDTextSelectionBackground, "text_selection", false, kDDNone}, + + {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, + {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, + {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, + {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, + + {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider}, + {kDDButtonHover, "button_hover", false, kDDButtonIdle}, + {kDDButtonDisabled, "button_disabled", true, kDDNone}, + + {kDDSliderFull, "slider_full", false, kDDNone}, + {kDDSliderHover, "slider_hover", false, kDDNone}, + {kDDSliderDisabled, "slider_disabled", true, kDDNone}, + + {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, + {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, + {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, + + {kDDTabActive, "tab_active", false, kDDTabInactive}, + {kDDTabInactive, "tab_inactive", true, kDDNone}, + {kDDTabBackground, "tab_background", true, kDDNone}, + + {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, + + {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone}, + {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle}, + + {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone}, + {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase}, + + {kDDPopUpIdle, "popup_idle", true, kDDNone}, + {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, + + {kDDCaret, "caret", false, kDDNone}, + {kDDSeparator, "separator", true, kDDNone}, +}; + +const ThemeEngine::TextDataInfo ThemeEngine::kTextDataDefaults[] = { + {kTextDataDefault, "text_default"}, + {kTextDataHover, "text_hover"}, + {kTextDataDisabled, "text_disabled"}, + {kTextDataInverted, "text_inverted"}, + {kTextDataButton, "text_button"}, + {kTextDataButtonHover, "text_button_hover"}, + {kTextDataNormalFont, "text_normal"} +}; + + +/********************************************************** + * ThemeEngine class + *********************************************************/ +ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) : + _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _font(0), + _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), + _themeOk(false), _enabled(false), _buffering(false), _cursor(0) { + _system = g_system; + _parser = new ThemeParser(this); + _themeEval = new GUI::ThemeEval(); + + _useCursor = false; + + for (int i = 0; i < kDrawDataMAX; ++i) { + _widgets[i] = 0; + } + + for (int i = 0; i < kTextDataMAX; ++i) { + _texts[i] = 0; + } + + _graphicsMode = mode; + _themeFileName = fileName; + _initOk = false; +} + +ThemeEngine::~ThemeEngine() { + freeRenderer(); + freeScreen(); + freeBackbuffer(); + unloadTheme(); + delete _parser; + delete _themeEval; + delete[] _cursor; + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) + ImageMan.unregisterSurface(i->_key); +} + + +/********************************************************** + * Theme setup/initialization + *********************************************************/ +bool ThemeEngine::init() { + // reset everything and reload the graphics + deinit(); + setGraphicsMode(_graphicsMode); + + if (_screen->pixels && _backBuffer->pixels) { + _initOk = true; + clearAll(); + resetDrawArea(); + } + + if (_screen->w >= 400 && _screen->h >= 300) { + _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + } else { + _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + } + + if (isThemeLoadingRequired() || !_themeOk) { + loadTheme(_themeFileName); + } + + return true; +} + +void ThemeEngine::deinit() { + if (_initOk) { + _system->hideOverlay(); + freeRenderer(); + freeScreen(); + freeBackbuffer(); + _initOk = false; + } +} + +void ThemeEngine::unloadTheme() { + if (!_themeOk) + return; + + for (int i = 0; i < kDrawDataMAX; ++i) { + delete _widgets[i]; + _widgets[i] = 0; + } + + for (int i = 0; i < kTextDataMAX; ++i) { + delete _texts[i]; + _texts[i] = 0; + } + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) + ImageMan.unregisterSurface(i->_key); + + if (_themeFileName.hasSuffix(".zip")) + ImageMan.remArchive(_themeFileName); + + Common::File::resetDefaultDirectories(); + + _themeEval->reset(); + _themeOk = false; +} + +void ThemeEngine::clearAll() { + if (!_initOk) + return; + + _system->clearOverlay(); + _system->grabOverlay((OverlayColor*)_screen->pixels, _screen->w); +} + +void ThemeEngine::refresh() { + init(); + if (_enabled) { + _system->showOverlay(); + + if (_useCursor) { + CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + } + } +} + +void ThemeEngine::enable() { + init(); + resetDrawArea(); + + if (_useCursor) + setUpCursor(); + + _system->showOverlay(); + clearAll(); + _enabled = true; +} + +void ThemeEngine::disable() { + _system->hideOverlay(); + + if (_useCursor) { + CursorMan.popCursorPalette(); + CursorMan.popCursor(); + } + + _enabled = false; +} + +template +void ThemeEngine::screenInit(bool backBuffer) { + uint32 width = _system->getOverlayWidth(); + uint32 height = _system->getOverlayHeight(); + + if (backBuffer) { + freeBackbuffer(); + _backBuffer = new Surface; + _backBuffer->create(width, height, sizeof(PixelType)); + } + + freeScreen(); + _screen = new Surface; + _screen->create(width, height, sizeof(PixelType)); + _system->clearOverlay(); +} + +void ThemeEngine::setGraphicsMode(GraphicsMode mode) { + switch (mode) { + case kGfxStandard16bit: + case kGfxAntialias16bit: + _bytesPerPixel = sizeof(uint16); + screenInit(kEnableBackCaching); + break; + + default: + error("Invalid graphics mode"); + } + + freeRenderer(); + _vectorRenderer = createRenderer(mode); + _vectorRenderer->setSurface(_screen); +} + +bool ThemeEngine::isWidgetCached(DrawData type, const Common::Rect &r) { + return _widgets[type] && _widgets[type]->_cached && + _widgets[type]->_surfaceCache->w == r.width() && + _widgets[type]->_surfaceCache->h == r.height(); +} + +void ThemeEngine::drawCached(DrawData type, const Common::Rect &r) { + assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); + _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); +} + +void ThemeEngine::calcBackgroundOffset(DrawData type) { + uint maxShadow = 0; + for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); + step != _widgets[type]->_steps.end(); ++step) { + if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow) + maxShadow = step->shadow; + + if (step->drawingCall == &Graphics::VectorRenderer::drawCallback_BEVELSQ && step->bevel > maxShadow) + maxShadow = step->bevel; + } + + _widgets[type]->_backgroundOffset = maxShadow; +} + +void ThemeEngine::restoreBackground(Common::Rect r, bool special) { + r.clip(_screen->w, _screen->h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( + _vectorRenderer->blitSurface(_backBuffer, r); +} + + + + +/********************************************************** + * Theme elements management + *********************************************************/ +void ThemeEngine::addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step) { + DrawData id = getDrawDataId(drawDataId); + + assert(_widgets[id] != 0); + _widgets[id]->_steps.push_back(step); +} + +bool ThemeEngine::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) { + DrawData id = getDrawDataId(drawDataId); + TextData textId = getTextDataId(textDataId); + + if (id == -1 || textId == -1 || !_widgets[id]) + return false; + + _widgets[id]->_textDataId = textId; + _widgets[id]->_textAlignH = alignH; + _widgets[id]->_textAlignV = alignV; + + return true; +} + +bool ThemeEngine::addFont(const Common::String &fontId, const Common::String &file, int r, int g, int b) { + TextData textId = getTextDataId(fontId); + + if (textId == -1) + return false; + + if (_texts[textId] != 0) + delete _texts[textId]; + + _texts[textId] = new TextDrawData; + + if (file == "default") { + _texts[textId]->_fontPtr = _font; + } else { + _texts[textId]->_fontPtr = FontMan.getFontByName(file); + + if (!_texts[textId]->_fontPtr) { + _texts[textId]->_fontPtr = loadFont(file.c_str()); + + if (!_texts[textId]->_fontPtr) + error("Couldn't load %s font '%s'", fontId.c_str(), file.c_str()); + + FontMan.assignFontToName(file, _texts[textId]->_fontPtr); + } + } + + _texts[textId]->_color.r = r; + _texts[textId]->_color.g = g; + _texts[textId]->_color.b = b; + return true; + +} + +bool ThemeEngine::addBitmap(const Common::String &filename) { + if (_bitmaps.contains(filename)) { + ImageMan.unregisterSurface(filename); + } + + ImageMan.registerSurface(filename, 0); + _bitmaps[filename] = ImageMan.getSurface(filename); + + return _bitmaps[filename] != 0; +} + +bool ThemeEngine::addDrawData(const Common::String &data, bool cached) { + DrawData data_id = getDrawDataId(data); + + if (data_id == -1) + return false; + + if (_widgets[data_id] != 0) + delete _widgets[data_id]; + + _widgets[data_id] = new WidgetDrawData; + _widgets[data_id]->_cached = cached; + _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; + _widgets[data_id]->_surfaceCache = 0; + _widgets[data_id]->_textDataId = -1; + + return true; +} + + +/********************************************************** + * Theme XML loading + *********************************************************/ +bool ThemeEngine::loadTheme(Common::String fileName) { + unloadTheme(); + + if (fileName != "builtin") { + if (fileName.hasSuffix(".zip")) + ImageMan.addArchive(fileName); + else + Common::File::addDefaultDirectory(fileName); + } + + if (fileName == "builtin") { + if (!loadDefaultXML()) + error("Could not load default embeded theme"); + } + else if (!loadThemeXML(fileName)) { + warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str()); + + if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure + error("Could not load default embeded theme"); + } + + for (int i = 0; i < kDrawDataMAX; ++i) { + if (_widgets[i] == 0) { + warning("Missing data asset: '%s'", kDrawDataDefaults[i].name); + } else { + calcBackgroundOffset((DrawData)i); + + // TODO: draw the cached widget to the cache surface + if (_widgets[i]->_cached) {} + } + } + + _themeOk = true; + return true; +} + +bool ThemeEngine::loadDefaultXML() { + + // The default XML theme is included on runtime from a pregenerated + // file inside the themes directory. + // Use the Python script "makedeftheme.py" to convert a normal XML theme + // into the "default.inc" file, which is ready to be included in the code. + +#ifdef GUI_ENABLE_BUILTIN_THEME + const char *defaultXML = +#include "themes/default.inc" + ; + + if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) + return false; + + _themeName = "ScummVM Classic Theme (Builtin Version)"; + _themeFileName = "builtin"; + + return parser()->parse(); +#else + warning("The built-in theme is not enabled in the current build. Please load an external theme"); + return false; +#endif +} + +bool ThemeEngine::loadThemeXML(Common::String themeName) { + assert(_parser); + _themeName.clear(); + + char fileNameBuffer[32]; + char stxHeader[128]; + int parseCount = 0; + +#ifdef USE_ZLIB + unzFile zipFile = unzOpen((themeName).c_str()); + + if (zipFile && unzGoToFirstFile(zipFile) == UNZ_OK) { + while (true) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, fileNameBuffer, 32, NULL, 0, NULL, 0); + + if (matchString(fileNameBuffer, "*.stx") || !strcmp(fileNameBuffer, "THEMERC")) { + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + + Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); + + if (!strcmp(fileNameBuffer, "THEMERC")) { + stream->readLine(stxHeader, 128); + + if (!themeConfigParseHeader(stxHeader, _themeName)) { + warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); + return false; + } + + delete stream; + + } else { + parseCount++; + + if (parser()->loadStream(stream) == false || parser()->parse() == false) { + warning("Failed to load stream for zipped file '%s'", fileNameBuffer); + unzClose(zipFile); + return false; + } + } + } + + unzCloseCurrentFile(zipFile); + + if (unzGoToNextFile(zipFile) != UNZ_OK) + break; + } + } else { +#endif + + FilesystemNode node(themeName); + if (node.exists() && node.isReadable() && node.isDirectory()) { + FSList fslist; + if (!node.getChildren(fslist, FilesystemNode::kListFilesOnly)) + return false; + + for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { + if (i->getName().hasSuffix(".stx")) { + parseCount++; + + if (parser()->loadFile(*i) == false || parser()->parse() == false) { + warning("Failed to parse STX file '%s'", i->getName().c_str()); + return false; + } + } else if (i->getName() == "THEMERC") { + Common::File f; + f.open(*i); + f.readLine(stxHeader, 128); + + if (!themeConfigParseHeader(stxHeader, _themeName)) { + warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); + return false; + } + } + } + } +#ifdef USE_ZLIB + } + + unzClose(zipFile); + +#endif + + + return (parseCount > 0 && _themeName.empty() == false); +} + + + +/********************************************************** + * Drawing Queue management + *********************************************************/ +void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) { + if (_widgets[type] == 0) + return; + + Common::Rect area = r; + area.clip(_screen->w, _screen->h); + + ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, dynamic); + + if (_buffering) { + if (_widgets[type]->_buffer) { + _bufferQueue.push_back(q); + } else { + if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) + queueDD(kDrawDataDefaults[type].parent, r); + + _screenQueue.push_back(q); + } + } else { + q->drawSelf(!_widgets[type]->_buffer, _widgets[type]->_buffer); + delete q; + } +} + +void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, + bool ellipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { + + if (_texts[type] == 0) + return; + + Common::Rect area = r; + area.clip(_screen->w, _screen->h); + + ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], area, text, alignH, alignV, ellipsis, restoreBg, deltax); + + if (_buffering) { + _screenQueue.push_back(q); + } else { + q->drawSelf(true, false); + delete q; + } +} + +void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) { + + Common::Rect area = r; + area.clip(_screen->w, _screen->h); + + ThemeItemBitmap *q = new ThemeItemBitmap(this, area, bitmap, alpha); + + if (_buffering) { + _bufferQueue.push_back(q); + } else { + q->drawSelf(true, false); + delete q; + } +} + + + +/********************************************************** + * Widget drawing functions + *********************************************************/ +void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { + if (!ready()) + return; + + DrawData dd = kDDButtonIdle; + + if (state == kStateEnabled) + dd = kDDButtonIdle; + else if (state == kStateHighlight) + dd = kDDButtonHover; + else if (state == kStateDisabled) + dd = kDDButtonDisabled; + + queueDD(dd, r); + queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); +} + +void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { + if (!ready()) + return; + + queueDD(kDDSeparator, r); +} + +void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { + if (!ready()) + return; + + Common::Rect r2 = r; + DrawData dd = kDDCheckboxDefault; + + if (checked) + dd = kDDCheckboxSelected; + + if (state == kStateDisabled) + dd = kDDCheckboxDisabled; + + TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd); + const int checkBoxSize = MIN((int)r.height(), getFontHeight()); + + r2.bottom = r2.top + checkBoxSize; + r2.right = r2.left + checkBoxSize; + + queueDD(dd, r2); + + r2.left = r2.right + checkBoxSize; + r2.right = r.right; + + queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); +} + +void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { + if (!ready()) + return; + + DrawData dd = kDDSliderFull; + + if (state == kStateHighlight) + dd = kDDSliderHover; + else if (state == kStateDisabled) + dd = kDDSliderDisabled; + + Common::Rect r2 = r; + r2.setWidth(MIN((int16)width, r.width())); +// r2.top++; r2.bottom--; r2.left++; r2.right--; + + drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); + + if (width > r.width() * 5 / 100) + queueDD(dd, r2); +} + +void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { + if (!ready()) + return; + + queueDD(kDDScrollbarBase, r); + + Common::Rect r2 = r; + const int buttonExtra = (r.width() * 120) / 100; + + r2.bottom = r2.top + buttonExtra; + queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); + + r2.translate(0, r.height() - r2.height()); + queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); + + r2 = r; + r2.left += 1; + r2.right -= 1; + r2.top += sliderY; + r2.bottom = r2.top + sliderHeight - 1; + + r2.top += r.width() / 5; + r2.bottom -= r.width() / 5; + queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); +} + +void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) { + if (!ready()) + return; + + switch (bgtype) { + case kDialogBackgroundMain: + queueDD(kDDMainDialogBackground, r); + break; + + case kDialogBackgroundSpecial: + queueDD(kDDSpecialColorBackground, r); + break; + + case kDialogBackgroundPlain: + queueDD(kDDPlainColorBackground, r); + break; + + case kDialogBackgroundDefault: + queueDD(kDDDefaultBackground, r); + break; + } +} + +void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { + if (!ready()) + return; + + if (erase) { + restoreBackground(r); + addDirtyRect(r); + } else + queueDD(kDDCaret, r); +} + +void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { + if (!ready()) + return; + + DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle; + + queueDD(dd, r); + + if (!sel.empty()) { + Common::Rect text(r.left, r.top, r.right - 16, r.bottom); + queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); + } +} + +void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { + if (!ready()) + return; + + queueBitmap(&surface, r, themeTrans); +} + +void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { + if (!ready()) + return; + + switch (background) { + case kWidgetBackgroundBorderSmall: + queueDD(kDDWidgetBackgroundSmall, r); + break; + + case kWidgetBackgroundEditText: + queueDD(kDDWidgetBackgroundEditText, r); + break; + + case kWidgetBackgroundSlider: + queueDD(kDDWidgetBackgroundSlider, r); + break; + + default: + queueDD(kDDWidgetBackgroundDefault, r); + break; + } +} + +void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { + if (!ready()) + return; + + const int tabOffset = 2; + tabWidth -= tabOffset; + + queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); + + for (int i = 0; i < (int)tabs.size(); ++i) { + if (i == active) + continue; + + Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + queueDD(kDDTabInactive, tabRect); + queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); + } + + if (active >= 0) { + Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + const uint16 tabLeft = active * (tabWidth + tabOffset); + const uint16 tabRight = MAX(r.right - tabRect.right, 0); + queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); + queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); + } +} + +void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { + if (!ready()) + return; + + if (inverted) { + queueDD(kDDTextSelectionBackground, r); + queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax); + return; + } + + switch (font) { + case kFontStyleNormal: + queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + default: + break; + } + + switch (state) { + case kStateDisabled: + queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + case kStateHighlight: + queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + case kStateEnabled: + queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + } +} + +void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { + if (!ready()) + return; + + restoreBackground(r); + font->drawChar(_screen, ch, r.left, r.top, 0); + addDirtyRect(r); +} + +void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { + _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); + _screen->hLine(r.left, r.top, r.right, 0xFFFF); + _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); + _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); + _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); +} + + + +/********************************************************** + * Screen/overlay management + *********************************************************/ +void ThemeEngine::updateScreen() { + ThemeItem *item = 0; + + if (!_bufferQueue.empty()) { + _vectorRenderer->setSurface(_backBuffer); + + for (Common::List::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) { + (*q)->drawSelf(true, false); + delete *q; + } + + _vectorRenderer->setSurface(_screen); + _vectorRenderer->blitSurface(_backBuffer, Common::Rect(0, 0, _screen->w, _screen->h)); + _bufferQueue.clear(); + } + + if (!_screenQueue.empty()) { + _vectorRenderer->disableShadows(); + for (Common::List::iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) { + (*q)->drawSelf(true, false); + delete *q; + } + + _vectorRenderer->enableShadows(); + _screenQueue.clear(); + } + + renderDirtyScreen(); +} + +void ThemeEngine::renderDirtyScreen() { + if (_dirtyScreen.empty()) + return; + + Common::List::const_iterator i, j; + for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) { + for (j = i; j != _dirtyScreen.end(); ++j) + if (j != i && i->contains(*j)) + j = _dirtyScreen.reverse_erase(j); + + _vectorRenderer->copyFrame(_system, *i); + } + + _dirtyScreen.clear(); +} + +void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) { + if (doBuffer) + _buffering = true; + + if (style != kShadingNone) { + _vectorRenderer->applyScreenShading(style); + addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h)); + } + + _vectorRenderer->setSurface(_backBuffer); + _vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h)); + _vectorRenderer->setSurface(_screen); +} + +void ThemeEngine::setUpCursor() { + CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + CursorMan.showMouse(true); +} + +bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { + if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette)) + return false; + + const Surface *cursor = _bitmaps[filename]; + + if (!cursor) + return false; + + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; + _cursorTargetScale = scale; + + _cursorWidth = cursor->w; + _cursorHeight = cursor->h; + + uint colorsFound = 0; + const OverlayColor *src = (const OverlayColor*)cursor->pixels; + + byte *table = new byte[65536]; + assert(table); + memset(table, 0, sizeof(byte)*65536); + + byte r, g, b; + + uint16 transparency = RGBToColor >(255, 0, 255); + + delete[] _cursor; + + _cursor = new byte[_cursorWidth * _cursorHeight]; + assert(_cursor); + memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); + + for (uint y = 0; y < _cursorHeight; ++y) { + for (uint x = 0; x < _cursorWidth; ++x) { + _system->colorToRGB(src[x], r, g, b); + uint16 col = RGBToColor >(r, g, b); + if (!table[col] && col != transparency) { + table[col] = colorsFound++; + + uint index = table[col]; + _cursorPal[index * 4 + 0] = r; + _cursorPal[index * 4 + 1] = g; + _cursorPal[index * 4 + 2] = b; + _cursorPal[index * 4 + 3] = 0xFF; + + if (colorsFound > MAX_CURS_COLORS) { + warning("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); + return false; + } + } + + if (col != transparency) { + uint index = table[col]; + _cursor[y * _cursorWidth + x] = index; + } + } + src += _cursorWidth; + } + + _useCursor = true; + delete[] table; + + return true; +} + +} // end of namespace GUI. diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h new file mode 100644 index 0000000000..9f7fe35d82 --- /dev/null +++ b/gui/ThemeEngine.h @@ -0,0 +1,744 @@ +/* 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_ENGINE_H +#define THEME_ENGINE_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" + +#include "graphics/surface.h" +#include "graphics/fontman.h" + +#include "gui/dialog.h" +#include "gui/ThemeParser.h" +#include "graphics/VectorRenderer.h" +#include "gui/ThemeEval.h" + + +namespace GUI { + +struct WidgetDrawData; +struct DrawDataInfo; +class ThemeEval; + +struct TextDrawData { + const Graphics::Font *_fontPtr; + + struct { + uint8 r, g, b; + } _color; +}; + +struct WidgetDrawData { + /** List of all the steps needed to draw this widget */ + Common::List _steps; + + int _textDataId; + GUI::Theme::TextAlign _textAlignH; + GUI::Theme::TextAlignVertical _textAlignV; + + /** Extra space that the widget occupies when it's drawn. + E.g. when taking into account rounded corners, drop shadows, etc + Used when restoring the widget background */ + uint16 _backgroundOffset; + + /** Sets whether the widget is cached beforehand. */ + bool _cached; + bool _buffer; + + /** Texture where the cached widget is stored. */ + Graphics::Surface *_surfaceCache; + + ~WidgetDrawData() { + _steps.clear(); + + if (_surfaceCache) { + _surfaceCache->free(); + delete _surfaceCache; + } + } +}; + +class ThemeItem { + +public: + ThemeItem(ThemeEngine *engine, const Common::Rect &area) : + _engine(engine), _area(area) {} + + virtual void drawSelf(bool doDraw, bool doRestore) = 0; + +protected: + Common::Rect _area; + ThemeEngine *_engine; +}; + +class ThemeItemDrawData : public ThemeItem { +public: + ThemeItemDrawData(ThemeEngine *engine, const WidgetDrawData *data, const Common::Rect &area, uint32 dynData) : + ThemeItem(engine, area), _dynamicData(dynData), _data(data) {} + + void drawSelf(bool draw, bool restore); + +protected: + uint32 _dynamicData; + const WidgetDrawData *_data; +}; + +class ThemeItemTextData : public ThemeItem { +public: + ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const Common::Rect &area, const Common::String &text, + GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV, + bool ellipsis, bool restoreBg, int deltaX) : + ThemeItem(engine, area), _data(data), _text(text), _alignH(alignH), _alignV(alignV), + _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {} + + void drawSelf(bool draw, bool restore); + +protected: + const TextDrawData *_data; + Common::String _text; + GUI::Theme::TextAlign _alignH; + GUI::Theme::TextAlignVertical _alignV; + bool _ellipsis; + bool _restoreBg; + int _deltax; +}; + +class ThemeItemBitmap : public ThemeItem { +public: + ThemeItemBitmap(ThemeEngine *engine, const Common::Rect &area, const Graphics::Surface *bitmap, bool alpha) : + ThemeItem(engine, area), _bitmap(bitmap), _alpha(alpha) {} + + void drawSelf(bool draw, bool restore); + +protected: + const Graphics::Surface *_bitmap; + bool _alpha; +}; + + +class ThemeEngine : public Theme { +protected: + typedef Common::String String; + typedef GUI::Dialog Dialog; + typedef Common::HashMap ImagesMap; + + friend class GUI::Dialog; + friend class GUI::GuiObject; + + /** Sets whether backcaching is enabled */ + static const bool kEnableBackCaching = true; + + /** + * DrawData sets enumeration. + * Each DD set corresponds to the actual looks + * of a widget in a given state. + */ + enum DrawData { + kDDMainDialogBackground, + kDDSpecialColorBackground, + kDDPlainColorBackground, + kDDDefaultBackground, + kDDTextSelectionBackground, + + kDDWidgetBackgroundDefault, + kDDWidgetBackgroundSmall, + kDDWidgetBackgroundEditText, + kDDWidgetBackgroundSlider, + + kDDButtonIdle, + kDDButtonHover, + kDDButtonDisabled, + + kDDSliderFull, + kDDSliderHover, + kDDSliderDisabled, + + kDDCheckboxDefault, + kDDCheckboxDisabled, + kDDCheckboxSelected, + + kDDTabActive, + kDDTabInactive, + kDDTabBackground, + + kDDScrollbarBase, + kDDScrollbarButtonIdle, + kDDScrollbarButtonHover, + kDDScrollbarHandleIdle, + kDDScrollbarHandleHover, + + kDDPopUpIdle, + kDDPopUpHover, + + kDDCaret, + kDDSeparator, + kDrawDataMAX, + kDDNone = -1 + }; + + /** + * Default values for each DrawData item. + * @see kDrawDataDefaults[] for implementation. + */ + static const struct DrawDataInfo { + DrawData id; /** The actual ID of the DrawData item. */ + const char *name; /** The name of the DrawData item as it appears in the Theme Description files */ + bool buffer; /** Sets whether this item is buffered on the backbuffer or drawn directly to the screen. */ + DrawData parent; /** Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover */ + } kDrawDataDefaults[]; + + + enum TextData { + kTextDataNone = -1, + kTextDataDefault = 0, + kTextDataHover, + kTextDataDisabled, + kTextDataInverted, + kTextDataButton, + kTextDataButtonHover, + kTextDataNormalFont, + kTextDataMAX + }; + + static const struct TextDataInfo { + TextData id; + const char *name; + } kTextDataDefaults[]; + + +public: + /** Graphics mode enumeration. + * Each item represents a set of BPP and Renderer modes for a given + * surface. + */ + enum GraphicsMode { + kGfxDisabled = 0, /** No GFX */ + kGfxStandard16bit, /** 2BPP with the standard (aliased) renderer. */ + kGfxAntialias16bit, /** 2BPP with the optimized AA renderer. */ + kGfxMAX + }; + + /** Constant value to expand dirty rectangles, to make sure they are fully copied */ + static const int kDirtyRectangleThreshold = 1; + + static const char *rendererModeLabels[]; + + /** Default constructor */ + ThemeEngine(Common::String fileName, GraphicsMode mode); + + /** Default destructor */ + ~ThemeEngine(); + + GUI::ThemeEval *themeEval() { return _themeEval; } + + /** + * VIRTUAL METHODS + * This is the implementation of the GUI::Theme API to allow + * the ThemeEngine class to be plugged in as any other GUI + * theme. In fact, the renderer works like any other GUI theme, + * but supports extensive customization of the drawn widgets. + */ + bool init(); + void deinit(); + void clearAll(); + + void refresh(); + void enable(); + void disable(); + + /** + * Implementation of the GUI::Theme API. Called when a + * new dialog is opened. Note that the boolean parameter + * meaning has been changed. + * + * @param enableBuffering If set to true, buffering is enabled for + * drawing this dialog, and will continue enabled + * until disabled. + */ + void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); + + /** + * The updateScreen() method is called every frame. + * It processes all the drawing queues and then copies dirty rects + * in the current Screen surface to the overlay. + */ + void updateScreen(); + + /** Since the rendering pipeline changes, closing all dialogs causes no effect + TODO: remove this from the original GUI::Theme API */ + void closeAllDialogs() {} + + /** Drawing area has been removed: it was too hackish. A workaround is on the works. + TODO: finish the workaround for the credits dialog + TODO: remove this from the original GUI::Theme API */ + void resetDrawArea() {} + + + /** + * FONT MANAGEMENT METHODS + */ + + TextData fontStyleToData(FontStyle font) const { + switch (font) { + case kFontStyleNormal: + return kTextDataNormalFont; + + default: + return kTextDataDefault; + } + } + + const Graphics::Font *getFont(FontStyle font) const { return _texts[fontStyleToData(font)]->_fontPtr; } + + int getFontHeight(FontStyle font = kFontStyleBold) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getFontHeight() : 0; + } + + int getStringWidth(const Common::String &str, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0; + } + + int getCharWidth(byte c, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0; + } + + + /** + * WIDGET DRAWING METHODS + */ + void drawWidgetBackground(const Common::Rect &r, uint16 hints, + WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); + + void drawButton(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state = kStateEnabled, uint16 hints = 0); + + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, + WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); + + void drawSlider(const Common::Rect &r, int width, + WidgetStateInfo state = kStateEnabled); + + void drawCheckbox(const Common::Rect &r, const Common::String &str, + bool checked, WidgetStateInfo state = kStateEnabled); + + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, + const Common::Array &tabs, int active, uint16 hints, + int titleVPad, WidgetStateInfo state = kStateEnabled); + + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, + ScrollbarState, WidgetStateInfo state = kStateEnabled); + + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, + int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); + + void drawCaret(const Common::Rect &r, bool erase, + WidgetStateInfo state = kStateEnabled); + + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); + + void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state); + + void drawText(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); + + void drawChar(const Common::Rect &r, byte ch, + const Graphics::Font *font, WidgetStateInfo state); + + /** + * Actual implementation of a Dirty Rect drawing routine. + * Dirty rectangles are queued on a list and are later merged/calculated + * before the actual drawing. + * + * @param r Area of the dirty rect. + * @param backup Deprecated. + * @param special Deprecated. + */ + bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { + _dirtyScreen.push_back(r); + return true; + } + + + /** + * Returns the DrawData enumeration value that represents the given string + * in the DrawDataDefaults enumeration. + * It's slow, but called sparsely. + * + * @returns The drawdata enum value, or -1 if not found. + * @param name The representing name, as found on Theme Description XML files. + * @see kDrawDataDefaults[] + */ + DrawData getDrawDataId(const Common::String &name) { + for (int i = 0; i < kDrawDataMAX; ++i) + if (name.compareToIgnoreCase(kDrawDataDefaults[i].name) == 0) + return kDrawDataDefaults[i].id; + + return kDDNone; + } + + TextData getTextDataId(const Common::String &name) { + for (int i = 0; i < kTextDataMAX; ++i) + if (name.compareToIgnoreCase(kTextDataDefaults[i].name) == 0) + return kTextDataDefaults[i].id; + + return kTextDataNone; + } + + /** + * Interface for ThemeParser class: Parsed DrawSteps are added via this function. + * There is no return type because DrawSteps can always be added, unless something + * goes horribly wrong. + * The specified step will be added to the Steps list of the given DrawData id. + * + * @param drawDataId The representing DrawData name, as found on Theme Description XML files. + * @param step The actual DrawStep struct to be added. + */ + void addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step); + + /** + * Interfacefor the ThemeParser class: Parsed DrawData sets are added via this function. + * The goal of the function is to initialize each DrawData set before their DrawSteps can + * be added, hence this must be called for each DD set before addDrawStep() can be called + * for that given set. + * + * @param data The representing DrawData name, as found on Theme Description XML files. + * @param cached Whether this DD set will be cached beforehand. + */ + bool addDrawData(const Common::String &data, bool cached); + + + /** + * Interface for the ThemeParser class: Loads a font to use on the GUI from the given + * filename. + * + * @param fontName Identifier name for the font. + * @param file Name of the font file. + * @param r, g, b Color of the font. + */ + bool addFont(const Common::String &fontName, const Common::String &file, int r, int g, int b); + + + /** + * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI. + * The filename is also used as its identifier. + * + * @param filename Name of the bitmap file. + */ + bool addBitmap(const Common::String &filename); + + /** + * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the + * new Font API is in place. + */ + bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV); + + /** Interface to the new Theme XML parser */ + ThemeParser *parser() { + return _parser; + } + + /** + * Returns if the Theme is ready to draw stuff on screen. + * Must be called instead of just checking _initOk, because + * this checks if the renderer is initialized AND if the theme + * is loaded. + */ + bool ready() const { + return _initOk && _themeOk; + } + + /** Custom implementation of the GUI::Theme API, changed to use the XML parser. */ + bool loadTheme(Common::String themeName); + + /** + * Changes the active graphics mode of the GUI; may be used to either + * initialize the GUI or to change the mode while the GUI is already running. + */ + void setGraphicsMode(GraphicsMode mode); + + + /** + * Finishes buffering: widgets from then on will be drawn straight on the screen + * without drawing queues. + */ + void finishBuffering() { _buffering = false; } + void startBuffering() { _buffering = true; } + + ThemeEval *evaluator() { return _themeEval; } + VectorRenderer *renderer() { return _vectorRenderer; } + + bool supportsImages() const { return true; } + bool ownCursor() const { return _useCursor; } + + Graphics::Surface *getBitmap(const Common::String &name) { + return _bitmaps.contains(name) ? _bitmaps[name] : 0; + } + + const Graphics::Surface *getImageSurface(const kThemeImages n) const { + if (n == kImageLogo) + return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; + + return 0; + } + + /** + * Interface for the Theme Parser: Creates a new cursor by loading the given + * bitmap and sets it as the active cursor. + * + * @param filename File name of the bitmap to load. + * @param hotspotX X Coordinate of the bitmap which does the cursor click. + * @param hotspotY Y Coordinate of the bitmap which does the cursor click. + * @param scale Scale at which the bitmap is supposed to be used. + */ + bool createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale); + + /** + * Wrapper for restoring data from the Back Buffer to the screen. + * The actual processing is done in the VectorRenderer. + * + * @param r Area to restore. + * @param special Deprecated. + */ + void restoreBackground(Common::Rect r, bool special = false); + + /** + * Checks if a given DrawData set for a widget has been cached beforehand + * and is ready to be blit into the screen. + * + * @param type DrawData type of the widget. + * @param r Size of the widget which is expected to be cached. + */ + bool isWidgetCached(DrawData type, const Common::Rect &r); + +protected: + + const Common::String &getThemeName() const { return _themeName; } + const Common::String &getThemeFileName() const { return _themeFileName; } + int getGraphicsMode() const { return _graphicsMode; } + + /** + * Initializes the drawing screen surfaces, _screen and _backBuffer. + * If the surfaces already exist, they are cleared and re-initialized. + * + * @param backBuffer Sets whether the _backBuffer surface should be initialized. + * @template PixelType C type which specifies the size of each pixel. + * Defaults to uint16 (2 BPP for the surfaces) + */ + template void screenInit(bool backBuffer = true); + + /** + * Loads the given theme into the ThemeEngine. + * Note that ThemeName is an identifier, not a filename. + * + * @param ThemeName Theme identifier. + * @returns True if the theme was succesfully loaded. + */ + bool loadThemeXML(Common::String themeName); + + /** + * Loads the default theme file (the embeded XML file found + * in ThemeDefaultXML.cpp). + * Called only when no other themes are available. + */ + bool loadDefaultXML(); + + /** + * Unloads the currently loaded theme so another one can + * be loaded. + */ + void unloadTheme(); + + /** + * Not implemented yet. + * TODO: reload themes, reload the renderer, recheck everything + */ + void screenChange() { + error("Screen Changes are not supported yet. Fix this!"); + } + + /** + * Actual Dirty Screen handling function. + * Handles all the dirty squares in the list, merges and optimizes + * them when possible and draws them to the screen. + * Called from updateScreen() + */ + void renderDirtyScreen(); + + /** + * Frees the vector renderer. + */ + void freeRenderer() { + delete _vectorRenderer; + _vectorRenderer = 0; + } + + /** + * Frees the Back buffer surface, only if it's available. + */ + void freeBackbuffer() { + if (_backBuffer != 0) { + _backBuffer->free(); + delete _backBuffer; + _backBuffer = 0; + } + } + + /** + * Frees the main screen drawing surface, only if it's available. + */ + void freeScreen() { + if (_screen != 0) { + _screen->free(); + delete _screen; + _screen = 0; + } + } + + TextData getTextData(DrawData ddId) { + return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone; + } + + /** + * Draws a cached widget directly on the screen. Currently deprecated. + * + * @param type DrawData type of the widget. + * @param r Position on screen to draw the widget. + */ + void drawCached(DrawData type, const Common::Rect &r); + + /** + * Calculates the background threshold offset of a given DrawData item. + * After fully loading all DrawSteps of a DrawData item, this function must be + * called in order to calculate if such draw steps would be drawn outside of + * the actual widget drawing zone (e.g. shadows). If this is the case, a constant + * value will be added when restoring the background of the widget. + * + * @param type DrawData type of the widget. + */ + void calcBackgroundOffset(DrawData type); + + /** + * Generates a DrawQueue item and enqueues it so it's drawn to the screen + * when the drawing queue is processed. + * + * If Buffering is enabled, the DrawQueue item will be automatically placed + * on its corresponding queue. + * If Buffering is disabled, the DrawQueue item will be processed immediately + * and drawn to the screen. + * + * This function is called from all the Widget Drawing methods. + */ + inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); + inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, + bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); + inline void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); + + /** + * DEBUG: Draws a white square around the given position and writes the given next to it. + */ + inline void debugWidgetPosition(const char *name, const Common::Rect &r); + + + /** + * Default values from GUI::Theme + */ + int getTabSpacing() const { return 0; } + int getTabPadding() const { return 3; } + + OSystem *_system; /** Global system object. */ + + /** Vector Renderer object, does the actual drawing on screen */ + Graphics::VectorRenderer *_vectorRenderer; + + /** XML Parser, does the Theme parsing instead of the default parser */ + GUI::ThemeParser *_parser; + + /** Theme evaluator (changed from GUI::Eval to add functionality) */ + GUI::ThemeEval *_themeEval; + + /** Main screen surface. This is blitted straight into the overlay. */ + Graphics::Surface *_screen; + + /** Backbuffer surface. Stores previous states of the screen to blit back */ + Graphics::Surface *_backBuffer; + + /** Sets whether the current drawing is being buffered (stored for later + processing) or drawn directly to the screen. */ + bool _buffering; + + /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ + int _bytesPerPixel; + + /** Current graphics mode */ + GraphicsMode _graphicsMode; + + /** Font info. */ + Common::String _fontName; + const Graphics::Font *_font; + + /** Array of all the DrawData elements than can be drawn to the screen. + Must be full so the renderer can work. */ + WidgetDrawData *_widgets[kDrawDataMAX]; + + /** Array of all the text fonts that can be drawn. */ + TextDrawData *_texts[kTextDataMAX]; + + ImagesMap _bitmaps; + + /** List of all the dirty screens that must be blitted to the overlay. */ + Common::List _dirtyScreen; + + /** Queue with all the drawing that must be done to the Back Buffer */ + Common::List _bufferQueue; + + /** Queue with all the drawing that must be done to the screen */ + Common::List _screenQueue; + + bool _initOk; /** Class and renderer properly initialized */ + bool _themeOk; /** Theme data successfully loaded. */ + bool _enabled; /** Whether the Theme is currently shown on the overlay */ + + Common::String _themeName; /** Name of the currently loaded theme */ + Common::String _themeFileName; + + /** Custom Cursor Management */ + void setUpCursor(); + + bool _useCursor; + int _cursorHotspotX, _cursorHotspotY; + int _cursorTargetScale; +#define MAX_CURS_COLORS 255 + byte *_cursor; + bool _needPaletteUpdates; + uint _cursorWidth, _cursorHeight; + byte _cursorPal[4*MAX_CURS_COLORS]; +}; + +} // end of namespace GUI. + +#endif diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 614f2089d1..112cda59a1 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -31,150 +31,11 @@ #include "common/xmlparser.h" #include "graphics/scaler.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "gui/ThemeParser.h" #include "gui/ThemeEval.h" namespace GUI { - -bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { - if (name == _name) { - x = _x; y = _y; - w = _w; h = _h; - return true; - } - - return false; -} - -bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { - for (uint i = 0; i < _children.size(); ++i) { - if (_children[i]->getWidgetData(name, x, y, w, h)) - return true; - } - - return false; -} - -void ThemeLayoutMain::reflowLayout() { - assert(_children.size() <= 1); - - if (_children.size()) { - _children[0]->resetLayout(); - _children[0]->setWidth(_w); - _children[0]->setHeight(_h); - _children[0]->reflowLayout(); - - if (_w == -1) - _w = _children[0]->getWidth(); - - if (_h == -1) - _h = _children[0]->getHeight(); - - if (_y == -1) - _y = (g_system->getOverlayHeight() >> 1) - (_h >> 1); - - if (_x == -1) - _x = (g_system->getOverlayWidth() >> 1) - (_w >> 1); - } -} - -void ThemeLayoutVertical::reflowLayout() { - int curX, curY; - int resize[8]; - int rescount = 0; - - curX = _paddingLeft; - curY = _paddingTop; - _h = _paddingTop + _paddingBottom; - - for (uint i = 0; i < _children.size(); ++i) { - - _children[i]->resetLayout(); - _children[i]->reflowLayout(); - - if (_children[i]->getWidth() == -1) - _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); - - if (_children[i]->getHeight() == -1) { - resize[rescount++] = i; - _children[i]->setHeight(0); - } - - _children[i]->setY(curY); - - if (_centered && _children[i]->getWidth() < _w && _w != -1) { - _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); - } - else - _children[i]->setX(curX); - - curY += _children[i]->getHeight() + _spacing; - _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); - _h += _children[i]->getHeight() + _spacing; - } - - _h -= _spacing; - - if (rescount) { - int newh = (getParentH() - _h - _paddingBottom) / rescount; - - for (int i = 0; i < rescount; ++i) { - _children[resize[i]]->setHeight(newh); - _h += newh; - for (uint j = resize[i] + 1; j < _children.size(); ++j) - _children[j]->setY(newh); - } - } -} - -void ThemeLayoutHorizontal::reflowLayout() { - int curX, curY; - int resize[8]; - int rescount = 0; - - curX = _paddingLeft; - curY = _paddingTop; - _w = _paddingLeft + _paddingRight; - - for (uint i = 0; i < _children.size(); ++i) { - - _children[i]->resetLayout(); - _children[i]->reflowLayout(); - - if (_children[i]->getHeight() == -1) - _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); - - if (_children[i]->getWidth() == -1) { - resize[rescount++] = i; - _children[i]->setWidth(0); - } - - _children[i]->setX(curX); - - if (_centered && _children[i]->getHeight() < _h && _h != -1) - _children[i]->setY((_h >> 1) - (_children[i]->getHeight() >> 1)); - else - _children[i]->setY(curY); - - curX += (_children[i]->getWidth() + _spacing); - _w += _children[i]->getWidth() + _spacing; - _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); - } - - _w -= _spacing; - - if (rescount) { - int neww = (getParentW() - _w - _paddingRight) / rescount; - - for (int i = 0; i < rescount; ++i) { - _children[resize[i]]->setWidth(neww); - _w += neww; - for (uint j = resize[i] + 1; j < _children.size(); ++j) - _children[j]->setX(neww); - } - } -} ThemeEval::~ThemeEval() { reset(); @@ -199,6 +60,35 @@ void ThemeEval::buildBuiltinVars() { _builtin["kBigWidgetSize"] = GUI::kBigWidgetSize; } +void ThemeEval::reset() { + _vars.clear(); + _curDialog.clear(); + _curLayout.clear(); + + for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i) + delete i->_value; + + _layouts.clear(); +} + +bool ThemeEval::getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { + Common::StringTokenizer tokenizer(widget, "."); + + if (widget.hasPrefix("Dialog.")) + tokenizer.nextToken(); + + Common::String dialogName = "Dialog." + tokenizer.nextToken(); + Common::String widgetName = tokenizer.nextToken(); + + if (!_layouts.contains(dialogName)) + return false; + + if (widgetName.empty()) + return _layouts[dialogName]->getDialogData(x, y, w, h); + + return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); +} + void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled) { int typeW = -1; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index 8d55ff6066..a25ff21a88 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -33,267 +33,13 @@ #include "common/hash-str.h" #include "common/xmlparser.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "gui/ThemeParser.h" #include "gui/ThemeEval.h" +#include "gui/ThemeLayout.h" namespace GUI { -class ThemeLayout { - -public: - enum LayoutType { - kLayoutMain, - kLayoutVertical, - kLayoutHorizontal, - kLayoutWidget - }; - - ThemeLayout(ThemeLayout *p, const Common::String &name) : - _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), - _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), - _centered(false), _defaultW(-1), _defaultH(-1) { } - - virtual ~ThemeLayout() { - for (uint i = 0; i < _children.size(); ++i) - delete _children[i]; - } - - virtual void reflowLayout() = 0; - - virtual void resetLayout() { - _x = 0; - _y = 0; - _w = _defaultW; - _h = _defaultH; - } - - void addChild(ThemeLayout *child) { _children.push_back(child); } - - void setPadding(int8 left, int8 right, int8 top, int8 bottom) { - _paddingLeft = left; - _paddingRight = right; - _paddingTop = top; - _paddingBottom = bottom; - } - - void setSpacing(int8 spacing) { - _spacing = spacing; - } - - int16 getParentX() { return _parent ? _parent->_x : 0; } - int16 getParentY() { return _parent ? _parent->_y : 0; } - - int16 getParentW() { - ThemeLayout *p = _parent; - int width = 0; - - while (p && p->getLayoutType() != kLayoutMain) { - width += p->_paddingRight + p->_paddingLeft; - if (p->getLayoutType() == kLayoutHorizontal) { - for (uint i = 0; i < p->_children.size(); ++i) - width += p->_children[i]->getHeight() + p->_spacing; - } - p = p->_parent; - } - - return p->getWidth() - width; - } - - int16 getParentH() { - ThemeLayout *p = _parent; - int height = 0; - - while (p && p->getLayoutType() != kLayoutMain) { - height += p->_paddingBottom + p->_paddingTop; - if (p->getLayoutType() == kLayoutVertical) { - for (uint i = 0; i < p->_children.size(); ++i) - height += p->_children[i]->getHeight() + p->_spacing; - } - p = p->_parent; - } - - return p->getHeight() - height; - } - - int16 getX() { return _x; } - int16 getY() { return _y; } - int16 getWidth() { return _w; } - int16 getHeight() { return _h; } - - void setX(int newX) { - _x += newX; - for (uint i = 0; i < _children.size(); ++i) - _children[i]->setX(newX); - } - - void setY(int newY) { - _y += newY; - for (uint i = 0; i < _children.size(); ++i) - _children[i]->setY(newY); - } - - void setWidth(int16 width) { _w = width; } - void setHeight(int16 height) { _h = height; } - - void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - uint16 color = 0xFFFF; - font->drawString(screen, getName(), _x, _y, _w, color, Graphics::kTextAlignRight, 0, true); - screen->hLine(_x, _y, _x + _w, color); - screen->hLine(_x, _y + _h, _x + _w , color); - screen->vLine(_x, _y, _y + _h, color); - screen->vLine(_x + _w, _y, _y + _h, color); - - for (uint i = 0; i < _children.size(); ++i) - _children[i]->debugDraw(screen, font); - } - - virtual LayoutType getLayoutType() = 0; - virtual const char *getName() { return _name.c_str(); } - - virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); - - virtual bool getDialogData(int16 &x, int16 &y, uint16 &w, uint16 &h) { - assert(getLayoutType() == kLayoutMain); - x = _x; y = _y; - w = _w; h = _h; - return true; - } - - virtual ThemeLayout *buildCopy() = 0; - - void importLayout(ThemeLayout *layout) { - assert(layout->getLayoutType() == kLayoutMain); - - if (layout->_children.size() == 0) - return; - - layout = layout->_children[0]; - - if (getLayoutType() == layout->getLayoutType()) { - for (uint i = 0; i < layout->_children.size(); ++i) - _children.push_back(layout->_children[i]->buildCopy()); - } else { - _children.push_back(layout->buildCopy()); - } - } - -protected: - int16 _x, _y, _w, _h; - int16 _defaultW, _defaultH; - int8 _paddingTop, _paddingBottom, _paddingLeft, _paddingRight; - int8 _spacing; - Common::Array _children; - ThemeLayout *_parent; - bool _centered; - Common::String _name; -}; - -class ThemeLayoutMain : public ThemeLayout { -public: - ThemeLayoutMain(int16 x, int16 y, int16 w, int16 h) : ThemeLayout(0, "") { - _w = _defaultW = w; - _h = _defaultH = h; - _x = _defaultX = x; - _y = _defaultY = y; - } - void reflowLayout(); - - void resetLayout() { - ThemeLayout::resetLayout(); - _x = _defaultX; - _y = _defaultY; - } - - const char *getName() { return "Global Layout"; } - LayoutType getLayoutType() { return kLayoutMain; } - - ThemeLayout *buildCopy() { assert(!"Do not copy Main Layouts!"); return 0; } - -protected: - int16 _defaultX; - int16 _defaultY; -}; - -class ThemeLayoutVertical : public ThemeLayout { -public: - ThemeLayoutVertical(ThemeLayout *p, int spacing, bool center) : - ThemeLayout(p, "") { - _spacing = spacing; - _centered = center; - } - - void reflowLayout(); - const char *getName() { return "Vertical Layout"; } - LayoutType getLayoutType() { return kLayoutVertical; } - - - ThemeLayout *buildCopy() { - ThemeLayoutVertical *n = new ThemeLayoutVertical(*this); - - for (uint i = 0; i < n->_children.size(); ++ i) - n->_children[i] = n->_children[i]->buildCopy(); - - return n; - } -}; - -class ThemeLayoutHorizontal : public ThemeLayout { -public: - ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool center) : - ThemeLayout(p, "") { - _spacing = spacing; - _centered = center; - } - - void reflowLayout(); - const char *getName() { return "Horizontal Layout"; } - LayoutType getLayoutType() { return kLayoutHorizontal; } - - ThemeLayout *buildCopy() { - ThemeLayoutHorizontal *n = new ThemeLayoutHorizontal(*this); - - for (uint i = 0; i < n->_children.size(); ++ i) - n->_children[i] = n->_children[i]->buildCopy(); - - return n; - } -}; - -class ThemeLayoutWidget : public ThemeLayout { -public: - ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h) : ThemeLayout(p, name) { - _w = _defaultW = w; - _h = _defaultH = h; - } - - bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); - void reflowLayout() {} - LayoutType getLayoutType() { return kLayoutWidget; } - - ThemeLayout *buildCopy() { return new ThemeLayoutWidget(*this); } -}; - -class ThemeLayoutSpacing : public ThemeLayout { -public: - ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p, "") { - if (p->getLayoutType() == kLayoutHorizontal) { - _w = _defaultW = size; - _h = _defaultH = 1; - } else if (p->getLayoutType() == kLayoutVertical) { - _w = _defaultW = 1; - _h = _defaultH = size; - } - } - - bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { return false; } - void reflowLayout() {} - LayoutType getLayoutType() { return kLayoutWidget; } - const char *getName() { return "SPACE"; } - - ThemeLayout *buildCopy() { return new ThemeLayoutSpacing(*this); } -}; - class ThemeEval { typedef Common::HashMap VariablesMap; @@ -339,55 +85,20 @@ public: bool addImportedLayout(const Common::String &name); void addSpace(int size); - void addPadding(int16 l, int16 r, int16 t, int16 b) { - _curLayout.top()->setPadding(l, r, t, b); - } + void addPadding(int16 l, int16 r, int16 t, int16 b) { _curLayout.top()->setPadding(l, r, t, b); } void closeLayout() { _curLayout.pop(); } void closeDialog() { _curLayout.pop()->reflowLayout(); _curDialog.clear(); } - bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { - Common::StringTokenizer tokenizer(widget, "."); - - if (widget.hasPrefix("Dialog.")) - tokenizer.nextToken(); - - Common::String dialogName = "Dialog." + tokenizer.nextToken(); - Common::String widgetName = tokenizer.nextToken(); - - if (!_layouts.contains(dialogName)) - return false; - - if (widgetName.empty()) - return _layouts[dialogName]->getDialogData(x, y, w, h); - - return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); - } - - void debugPrint() { - printf("Debug variable list:\n"); - - VariablesMap::const_iterator i; - for (i = _vars.begin(); i != _vars.end(); ++i) { - printf(" '%s' = %d\n", i->_key.c_str(), i->_value); - } - } + bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h); +#ifdef LAYOUT_DEBUG_DIALOG void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { - _layouts["Dialog.Launcher"]->debugDraw(screen, font); -// _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); + _layouts[LAYOUT_DEBUG_DIALOG]->debugDraw(screen, font); } +#endif - void reset() { - _vars.clear(); - _curDialog.clear(); - _curLayout.clear(); - - for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i) - delete i->_value; - - _layouts.clear(); - } + void reset(); private: VariablesMap _vars; diff --git a/gui/ThemeLayout.cpp b/gui/ThemeLayout.cpp new file mode 100644 index 0000000000..a70fb6cdc6 --- /dev/null +++ b/gui/ThemeLayout.cpp @@ -0,0 +1,227 @@ +/* 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$ + * + */ +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" +#include "graphics/scaler.h" + +#include "gui/ThemeEval.h" +#include "gui/ThemeLayout.h" + +namespace GUI { + +void ThemeLayout::importLayout(ThemeLayout *layout) { + assert(layout->getLayoutType() == kLayoutMain); + + if (layout->_children.size() == 0) + return; + + layout = layout->_children[0]; + + if (getLayoutType() == layout->getLayoutType()) { + for (uint i = 0; i < layout->_children.size(); ++i) + _children.push_back(layout->_children[i]->buildCopy()); + } else { + _children.push_back(layout->buildCopy()); + } +} + +bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { + for (uint i = 0; i < _children.size(); ++i) { + if (_children[i]->getWidgetData(name, x, y, w, h)) + return true; + } + + return false; +} + +int16 ThemeLayout::getParentW() { + ThemeLayout *p = _parent; + int width = 0; + + while (p && p->getLayoutType() != kLayoutMain) { + width += p->_paddingRight + p->_paddingLeft; + if (p->getLayoutType() == kLayoutHorizontal) { + for (uint i = 0; i < p->_children.size(); ++i) + width += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; + } + + return p->getWidth() - width; +} + +int16 ThemeLayout::getParentH() { + ThemeLayout *p = _parent; + int height = 0; + + while (p && p->getLayoutType() != kLayoutMain) { + height += p->_paddingBottom + p->_paddingTop; + if (p->getLayoutType() == kLayoutVertical) { + for (uint i = 0; i < p->_children.size(); ++i) + height += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; + } + + return p->getHeight() - height; +} + + +bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { + if (name == _name) { + x = _x; y = _y; + w = _w; h = _h; + return true; + } + + return false; +} + +void ThemeLayoutMain::reflowLayout() { + assert(_children.size() <= 1); + + if (_children.size()) { + _children[0]->resetLayout(); + _children[0]->setWidth(_w); + _children[0]->setHeight(_h); + _children[0]->reflowLayout(); + + if (_w == -1) + _w = _children[0]->getWidth(); + + if (_h == -1) + _h = _children[0]->getHeight(); + + if (_y == -1) + _y = (g_system->getOverlayHeight() >> 1) - (_h >> 1); + + if (_x == -1) + _x = (g_system->getOverlayWidth() >> 1) - (_w >> 1); + } +} + +void ThemeLayoutVertical::reflowLayout() { + int curX, curY; + int resize[8]; + int rescount = 0; + + curX = _paddingLeft; + curY = _paddingTop; + _h = _paddingTop + _paddingBottom; + + for (uint i = 0; i < _children.size(); ++i) { + + _children[i]->resetLayout(); + _children[i]->reflowLayout(); + + if (_children[i]->getWidth() == -1) + _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); + + if (_children[i]->getHeight() == -1) { + resize[rescount++] = i; + _children[i]->setHeight(0); + } + + _children[i]->setY(curY); + + if (_centered && _children[i]->getWidth() < _w && _w != -1) { + _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); + } + else + _children[i]->setX(curX); + + curY += _children[i]->getHeight() + _spacing; + _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); + _h += _children[i]->getHeight() + _spacing; + } + + _h -= _spacing; + + if (rescount) { + int newh = (getParentH() - _h - _paddingBottom) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setHeight(newh); + _h += newh; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setY(newh); + } + } +} + +void ThemeLayoutHorizontal::reflowLayout() { + int curX, curY; + int resize[8]; + int rescount = 0; + + curX = _paddingLeft; + curY = _paddingTop; + _w = _paddingLeft + _paddingRight; + + for (uint i = 0; i < _children.size(); ++i) { + + _children[i]->resetLayout(); + _children[i]->reflowLayout(); + + if (_children[i]->getHeight() == -1) + _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); + + if (_children[i]->getWidth() == -1) { + resize[rescount++] = i; + _children[i]->setWidth(0); + } + + _children[i]->setX(curX); + + if (_centered && _children[i]->getHeight() < _h && _h != -1) + _children[i]->setY((_h >> 1) - (_children[i]->getHeight() >> 1)); + else + _children[i]->setY(curY); + + curX += (_children[i]->getWidth() + _spacing); + _w += _children[i]->getWidth() + _spacing; + _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); + } + + _w -= _spacing; + + if (rescount) { + int neww = (getParentW() - _w - _paddingRight) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setWidth(neww); + _w += neww; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setX(neww); + } + } +} + + +} \ No newline at end of file diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h new file mode 100644 index 0000000000..293804d822 --- /dev/null +++ b/gui/ThemeLayout.h @@ -0,0 +1,239 @@ +/* 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_LAYOUT_H +#define THEME_LAYOUT_H + +namespace GUI { + +class ThemeLayout { + +public: + enum LayoutType { + kLayoutMain, + kLayoutVertical, + kLayoutHorizontal, + kLayoutWidget + }; + + ThemeLayout(ThemeLayout *p, const Common::String &name) : + _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), + _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), + _centered(false), _defaultW(-1), _defaultH(-1) { } + + virtual ~ThemeLayout() { + for (uint i = 0; i < _children.size(); ++i) + delete _children[i]; + } + + virtual void reflowLayout() = 0; + + virtual void resetLayout() { _x = 0; _y = 0; _w = _defaultW; _h = _defaultH; } + + void addChild(ThemeLayout *child) { _children.push_back(child); } + + void setPadding(int8 left, int8 right, int8 top, int8 bottom) { + _paddingLeft = left; + _paddingRight = right; + _paddingTop = top; + _paddingBottom = bottom; + } + + void setSpacing(int8 spacing) { + _spacing = spacing; + } + + int16 getParentX() { return _parent ? _parent->_x : 0; } + int16 getParentY() { return _parent ? _parent->_y : 0; } + int16 getParentW(); + int16 getParentH(); + int16 getX() { return _x; } + int16 getY() { return _y; } + int16 getWidth() { return _w; } + int16 getHeight() { return _h; } + + void setX(int newX) { + _x += newX; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setX(newX); + } + + void setY(int newY) { + _y += newY; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setY(newY); + } + + void setWidth(int16 width) { _w = width; } + void setHeight(int16 height) { _h = height; } + +#ifdef LAYOUT_DEBUG_DIALOG + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + uint16 color = 0xFFFF; + font->drawString(screen, getName(), _x, _y, _w, color, Graphics::kTextAlignRight, 0, true); + screen->hLine(_x, _y, _x + _w, color); + screen->hLine(_x, _y + _h, _x + _w , color); + screen->vLine(_x, _y, _y + _h, color); + screen->vLine(_x + _w, _y, _y + _h, color); + + for (uint i = 0; i < _children.size(); ++i) + _children[i]->debugDraw(screen, font); + } +#endif + + virtual LayoutType getLayoutType() = 0; + virtual const char *getName() { return _name.c_str(); } + + virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + + virtual bool getDialogData(int16 &x, int16 &y, uint16 &w, uint16 &h) { + assert(getLayoutType() == kLayoutMain); + x = _x; y = _y; + w = _w; h = _h; + return true; + } + + virtual ThemeLayout *buildCopy() = 0; + void importLayout(ThemeLayout *layout); + +protected: + int16 _x, _y, _w, _h; + int16 _defaultW, _defaultH; + int8 _paddingTop, _paddingBottom, _paddingLeft, _paddingRight; + int8 _spacing; + Common::Array _children; + ThemeLayout *_parent; + bool _centered; + Common::String _name; +}; + +class ThemeLayoutMain : public ThemeLayout { +public: + ThemeLayoutMain(int16 x, int16 y, int16 w, int16 h) : ThemeLayout(0, "") { + _w = _defaultW = w; + _h = _defaultH = h; + _x = _defaultX = x; + _y = _defaultY = y; + } + void reflowLayout(); + + void resetLayout() { + ThemeLayout::resetLayout(); + _x = _defaultX; + _y = _defaultY; + } + + const char *getName() { return "Global Layout"; } + LayoutType getLayoutType() { return kLayoutMain; } + + ThemeLayout *buildCopy() { assert(!"Do not copy Main Layouts!"); return 0; } + +protected: + int16 _defaultX; + int16 _defaultY; +}; + +class ThemeLayoutVertical : public ThemeLayout { +public: + ThemeLayoutVertical(ThemeLayout *p, int spacing, bool center) : + ThemeLayout(p, "") { + _spacing = spacing; + _centered = center; + } + + void reflowLayout(); + const char *getName() { return "Vertical Layout"; } + LayoutType getLayoutType() { return kLayoutVertical; } + + + ThemeLayout *buildCopy() { + ThemeLayoutVertical *n = new ThemeLayoutVertical(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } +}; + +class ThemeLayoutHorizontal : public ThemeLayout { +public: + ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool center) : + ThemeLayout(p, "") { + _spacing = spacing; + _centered = center; + } + + void reflowLayout(); + const char *getName() { return "Horizontal Layout"; } + LayoutType getLayoutType() { return kLayoutHorizontal; } + + ThemeLayout *buildCopy() { + ThemeLayoutHorizontal *n = new ThemeLayoutHorizontal(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } +}; + +class ThemeLayoutWidget : public ThemeLayout { +public: + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h) : ThemeLayout(p, name) { + _w = _defaultW = w; + _h = _defaultH = h; + } + + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + void reflowLayout() {} + LayoutType getLayoutType() { return kLayoutWidget; } + + ThemeLayout *buildCopy() { return new ThemeLayoutWidget(*this); } +}; + +class ThemeLayoutSpacing : public ThemeLayout { +public: + ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p, "") { + if (p->getLayoutType() == kLayoutHorizontal) { + _w = _defaultW = size; + _h = _defaultH = 1; + } else if (p->getLayoutType() == kLayoutVertical) { + _w = _defaultW = 1; + _h = _defaultH = size; + } + } + + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { return false; } + void reflowLayout() {} + LayoutType getLayoutType() { return kLayoutWidget; } + const char *getName() { return "SPACE"; } + + ThemeLayout *buildCopy() { return new ThemeLayoutSpacing(*this); } +}; + +} + +#endif \ No newline at end of file diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 2656f2a898..52fb90b2a6 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -30,7 +30,7 @@ #include "common/hash-str.h" #include "common/xmlparser.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "gui/ThemeParser.h" #include "gui/newgui.h" #include "graphics/VectorRenderer.h" @@ -40,7 +40,7 @@ namespace GUI { using namespace Graphics; using namespace Common; -ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { +ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() { _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 098bdb0540..67da93ff6c 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -36,19 +36,19 @@ #include "common/xmlparser.h" #include "graphics/VectorRenderer.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" namespace GUI { using namespace Graphics; using namespace Common; -class ThemeRenderer; +class ThemeEngine; class ThemeParser : public XMLParser { typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); public: - ThemeParser(GUI::ThemeRenderer *parent); + ThemeParser(GUI::ThemeEngine *parent); virtual ~ThemeParser() { delete _defaultStepGlobal; @@ -69,7 +69,7 @@ public: } protected: - ThemeRenderer *_theme; + ThemeEngine *_theme; CUSTOM_XML_PARSER(ThemeParser) { XML_KEY(render_info) diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp deleted file mode 100644 index 43659eeb16..0000000000 --- a/gui/ThemeRenderer.cpp +++ /dev/null @@ -1,1045 +0,0 @@ -/* 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$ - * - */ - -#include "common/util.h" -#include "graphics/surface.h" -#include "graphics/colormasks.h" -#include "common/system.h" -#include "common/events.h" -#include "common/config-manager.h" -#include "common/fs.h" -#include "graphics/imageman.h" -#include "graphics/cursorman.h" -#include "gui/launcher.h" - -#include "gui/ThemeRenderer.h" -#include "gui/ThemeEval.h" -#include "graphics/VectorRenderer.h" - -#define GUI_ENABLE_BUILTIN_THEME - -namespace GUI { - -using namespace Graphics; - -const char *ThemeRenderer::rendererModeLabels[] = { - "Disabled GFX", - "Stardard Renderer (16bpp)", - "Antialiased Renderer (16bpp)" -}; - -const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { - {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, - {kDDSpecialColorBackground, "special_bg", true, kDDNone}, - {kDDPlainColorBackground, "plain_bg", true, kDDNone}, - {kDDDefaultBackground, "default_bg", true, kDDNone}, - {kDDTextSelectionBackground, "text_selection", false, kDDNone}, - - {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, - {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, - {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, - {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, - - {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider}, - {kDDButtonHover, "button_hover", false, kDDButtonIdle}, - {kDDButtonDisabled, "button_disabled", true, kDDNone}, - - {kDDSliderFull, "slider_full", false, kDDNone}, - {kDDSliderHover, "slider_hover", false, kDDNone}, - {kDDSliderDisabled, "slider_disabled", true, kDDNone}, - - {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, - {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, - {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, - - {kDDTabActive, "tab_active", false, kDDTabInactive}, - {kDDTabInactive, "tab_inactive", true, kDDNone}, - {kDDTabBackground, "tab_background", true, kDDNone}, - - {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, - - {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone}, - {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle}, - - {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone}, - {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase}, - - {kDDPopUpIdle, "popup_idle", true, kDDNone}, - {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, - - {kDDCaret, "caret", false, kDDNone}, - {kDDSeparator, "separator", true, kDDNone}, -}; - -const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { - {kTextDataDefault, "text_default"}, - {kTextDataHover, "text_hover"}, - {kTextDataDisabled, "text_disabled"}, - {kTextDataInverted, "text_inverted"}, - {kTextDataButton, "text_button"}, - {kTextDataButtonHover, "text_button_hover"}, - {kTextDataNormalFont, "text_normal"} -}; - - -ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : - _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _font(0), - _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), - _themeOk(false), _enabled(false), _buffering(false), _cursor(0) { - _system = g_system; - _parser = new ThemeParser(this); - _themeEval = new GUI::ThemeEval(); - - _useCursor = false; - - for (int i = 0; i < kDrawDataMAX; ++i) { - _widgets[i] = 0; - } - - for (int i = 0; i < kTextDataMAX; ++i) { - _texts[i] = 0; - } - - _graphicsMode = mode; - _themeFileName = fileName; - _initOk = false; -} - -ThemeRenderer::~ThemeRenderer() { - freeRenderer(); - freeScreen(); - freeBackbuffer(); - unloadTheme(); - delete _parser; - delete _themeEval; - delete[] _cursor; - - for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) - ImageMan.unregisterSurface(i->_key); -} - -bool ThemeRenderer::init() { - // reset everything and reload the graphics - deinit(); - setGraphicsMode(_graphicsMode); - - if (_screen->pixels && _backBuffer->pixels) { - _initOk = true; - clearAll(); - resetDrawArea(); - } - - if (_screen->w >= 400 && _screen->h >= 300) { - _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } - - if (isThemeLoadingRequired() || !_themeOk) { - loadTheme(_themeFileName); - } - - return true; -} - -void ThemeRenderer::deinit() { - if (_initOk) { - _system->hideOverlay(); - freeRenderer(); - freeScreen(); - freeBackbuffer(); - _initOk = false; - } -} - -void ThemeRenderer::unloadTheme() { - if (!_themeOk) - return; - - for (int i = 0; i < kDrawDataMAX; ++i) { - delete _widgets[i]; - _widgets[i] = 0; - } - - for (int i = 0; i < kTextDataMAX; ++i) { - delete _texts[i]; - _texts[i] = 0; - } - - for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) - ImageMan.unregisterSurface(i->_key); - - if (_themeFileName.hasSuffix(".zip")) - ImageMan.remArchive(_themeFileName); - - Common::File::resetDefaultDirectories(); - - _themeEval->reset(); - _themeOk = false; -} - -void ThemeRenderer::clearAll() { - if (!_initOk) - return; - - _system->clearOverlay(); - _system->grabOverlay((OverlayColor*)_screen->pixels, _screen->w); -} - -void ThemeRenderer::refresh() { - init(); - if (_enabled) { - _system->showOverlay(); - - if (_useCursor) { - CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - } - } -} - -void ThemeRenderer::enable() { - init(); - resetDrawArea(); - - if (_useCursor) - setUpCursor(); - - _system->showOverlay(); - clearAll(); - _enabled = true; -} - -void ThemeRenderer::disable() { - _system->hideOverlay(); - - if (_useCursor) { - CursorMan.popCursorPalette(); - CursorMan.popCursor(); - } - - _enabled = false; -} - -template -void ThemeRenderer::screenInit(bool backBuffer) { - uint32 width = _system->getOverlayWidth(); - uint32 height = _system->getOverlayHeight(); - - if (backBuffer) { - freeBackbuffer(); - _backBuffer = new Surface; - _backBuffer->create(width, height, sizeof(PixelType)); - } - - freeScreen(); - _screen = new Surface; - _screen->create(width, height, sizeof(PixelType)); - _system->clearOverlay(); -} - -void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { - switch (mode) { - case kGfxStandard16bit: - case kGfxAntialias16bit: - _bytesPerPixel = sizeof(uint16); - screenInit(kEnableBackCaching); - break; - - default: - error("Invalid graphics mode"); - } - - freeRenderer(); - _vectorRenderer = createRenderer(mode); - _vectorRenderer->setSurface(_screen); -} - -void ThemeRenderer::addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step) { - DrawData id = getDrawDataId(drawDataId); - - assert(_widgets[id] != 0); - _widgets[id]->_steps.push_back(step); -} - -bool ThemeRenderer::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) { - DrawData id = getDrawDataId(drawDataId); - TextData textId = getTextDataId(textDataId); - - if (id == -1 || textId == -1 || !_widgets[id]) - return false; - - _widgets[id]->_textDataId = textId; - _widgets[id]->_textAlignH = alignH; - _widgets[id]->_textAlignV = alignV; - - return true; -} - -bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String &file, int r, int g, int b) { - TextData textId = getTextDataId(fontId); - - if (textId == -1) - return false; - - if (_texts[textId] != 0) - delete _texts[textId]; - - _texts[textId] = new TextDrawData; - - if (file == "default") { - _texts[textId]->_fontPtr = _font; - } else { - _texts[textId]->_fontPtr = FontMan.getFontByName(file); - - if (!_texts[textId]->_fontPtr) { - _texts[textId]->_fontPtr = loadFont(file.c_str()); - - if (!_texts[textId]->_fontPtr) - error("Couldn't load %s font '%s'", fontId.c_str(), file.c_str()); - - FontMan.assignFontToName(file, _texts[textId]->_fontPtr); - } - } - - _texts[textId]->_color.r = r; - _texts[textId]->_color.g = g; - _texts[textId]->_color.b = b; - return true; - -} - -bool ThemeRenderer::addBitmap(const Common::String &filename) { - if (_bitmaps.contains(filename)) { - ImageMan.unregisterSurface(filename); - } - - ImageMan.registerSurface(filename, 0); - _bitmaps[filename] = ImageMan.getSurface(filename); - - return _bitmaps[filename] != 0; -} - -bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { - DrawData data_id = getDrawDataId(data); - - if (data_id == -1) - return false; - - if (_widgets[data_id] != 0) - delete _widgets[data_id]; - - _widgets[data_id] = new WidgetDrawData; - _widgets[data_id]->_cached = cached; - _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; - _widgets[data_id]->_surfaceCache = 0; - _widgets[data_id]->_textDataId = -1; - - return true; -} - -bool ThemeRenderer::loadTheme(Common::String fileName) { - unloadTheme(); - - if (fileName != "builtin") { - if (fileName.hasSuffix(".zip")) - ImageMan.addArchive(fileName); - else - Common::File::addDefaultDirectory(fileName); - } - - if (fileName == "builtin") { - if (!loadDefaultXML()) - error("Could not load default embeded theme"); - } - else if (!loadThemeXML(fileName)) { - warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str()); - - if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure - error("Could not load default embeded theme"); - } - - for (int i = 0; i < kDrawDataMAX; ++i) { - if (_widgets[i] == 0) { - warning("Missing data asset: '%s'", kDrawDataDefaults[i].name); - } else { - calcBackgroundOffset((DrawData)i); - - // TODO: draw the cached widget to the cache surface - if (_widgets[i]->_cached) {} - } - } - - _themeOk = true; - return true; -} - -bool ThemeRenderer::loadDefaultXML() { - - // The default XML theme is included on runtime from a pregenerated - // file inside the themes directory. - // Use the Python script "makedeftheme.py" to convert a normal XML theme - // into the "default.inc" file, which is ready to be included in the code. - -#ifdef GUI_ENABLE_BUILTIN_THEME - const char *defaultXML = -#include "themes/default.inc" - ; - - if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) - return false; - - _themeName = "ScummVM Classic Theme (Builtin Version)"; - _themeFileName = "builtin"; - - return parser()->parse(); -#else - warning("The built-in theme is not enabled in the current build. Please load an external theme"); - return false; -#endif -} - -bool ThemeRenderer::loadThemeXML(Common::String themeName) { - assert(_parser); - _themeName.clear(); - - char fileNameBuffer[32]; - char stxHeader[128]; - int parseCount = 0; - -#ifdef USE_ZLIB - unzFile zipFile = unzOpen((themeName).c_str()); - - if (zipFile && unzGoToFirstFile(zipFile) == UNZ_OK) { - while (true) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, fileNameBuffer, 32, NULL, 0, NULL, 0); - - if (matchString(fileNameBuffer, "*.stx") || !strcmp(fileNameBuffer, "THEMERC")) { - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - - Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); - - if (!strcmp(fileNameBuffer, "THEMERC")) { - stream->readLine(stxHeader, 128); - - if (!themeConfigParseHeader(stxHeader, _themeName)) { - warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); - return false; - } - - delete stream; - - } else { - parseCount++; - - if (parser()->loadStream(stream) == false || parser()->parse() == false) { - warning("Failed to load stream for zipped file '%s'", fileNameBuffer); - unzClose(zipFile); - return false; - } - } - } - - unzCloseCurrentFile(zipFile); - - if (unzGoToNextFile(zipFile) != UNZ_OK) - break; - } - } else { -#endif - - FilesystemNode node(themeName); - if (node.exists() && node.isReadable() && node.isDirectory()) { - FSList fslist; - if (!node.getChildren(fslist, FilesystemNode::kListFilesOnly)) - return false; - - for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { - if (i->getName().hasSuffix(".stx")) { - parseCount++; - - if (parser()->loadFile(*i) == false || parser()->parse() == false) { - warning("Failed to parse STX file '%s'", i->getName().c_str()); - return false; - } - } else if (i->getName() == "THEMERC") { - Common::File f; - f.open(*i); - f.readLine(stxHeader, 128); - - if (!themeConfigParseHeader(stxHeader, _themeName)) { - warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); - return false; - } - } - } - } -#ifdef USE_ZLIB - } - - unzClose(zipFile); - -#endif - - - return (parseCount > 0 && _themeName.empty() == false); -} - -bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { - return _widgets[type] && _widgets[type]->_cached && - _widgets[type]->_surfaceCache->w == r.width() && - _widgets[type]->_surfaceCache->h == r.height(); -} - -void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { - assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); - _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); -} - -void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) { - if (_widgets[type] == 0) - return; - - DrawQueue q; - q.type = type; - q.area = r; - q.area.clip(_screen->w, _screen->h); - q.dynData = dynamic; - - if (_buffering) { - if (_widgets[type]->_buffer) { - _bufferQueue.push_back(q); - } else { - if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) - queueDD(kDrawDataDefaults[type].parent, r); - - _screenQueue.push_back(q); - } - } else { - drawDD(q, !_widgets[type]->_buffer, _widgets[type]->_buffer); - } -} - -void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool ellipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { - - if (_texts[type] == 0) - return; - - DrawQueueText q; - q.type = type; - q.area = r; - q.area.clip(_screen->w, _screen->h); - q.text = text; - q.alignH = alignH; - q.alignV = alignV; - q.restoreBg = restoreBg; - q.deltax = deltax; - q.ellipsis = ellipsis; - - if (_buffering) { - _textQueue.push_back(q); - } else { - drawDDText(q); - } -} - -void ThemeRenderer::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &area, bool alpha) { - BitmapQueue q; - q.bitmap = bitmap; - q.area = area; - q.alpha = alpha; - - if (_buffering) { - _bitmapQueue.push_back(q); - } else { - drawBitmap(q); - } -} - -void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { - Common::Rect extendedRect = q.area; - extendedRect.grow(kDirtyRectangleThreshold + _widgets[q.type]->_backgroundOffset); -// extendedRect.right += _widgets[q.type]->_backgroundOffset; -// extendedRect.bottom += _widgets[q.type]->_backgroundOffset; - - if (restore) - restoreBackground(extendedRect); - - if (draw) { - if (isWidgetCached(q.type, q.area)) { - drawCached(q.type, q.area); - } else { - for (Common::List::const_iterator step = _widgets[q.type]->_steps.begin(); - step != _widgets[q.type]->_steps.end(); ++step) - _vectorRenderer->drawStep(q.area, *step, q.dynData); - } - } - - addDirtyRect(extendedRect); -} - -void ThemeRenderer::drawDDText(const DrawQueueText &q) { - if (q.restoreBg) - restoreBackground(q.area); - - _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); - _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax, q.ellipsis); - addDirtyRect(q.area); -} - -void ThemeRenderer::drawBitmap(const BitmapQueue &q) { - - if (q.alpha) - _vectorRenderer->blitAlphaBitmap(q.bitmap, q.area); - else - _vectorRenderer->blitSubSurface(q.bitmap, q.area); - - addDirtyRect(q.area); -} - -void ThemeRenderer::calcBackgroundOffset(DrawData type) { - uint maxShadow = 0; - for (Common::List::const_iterator step = _widgets[type]->_steps.begin(); - step != _widgets[type]->_steps.end(); ++step) { - if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow) - maxShadow = step->shadow; - - if (step->drawingCall == &Graphics::VectorRenderer::drawCallback_BEVELSQ && step->bevel > maxShadow) - maxShadow = step->bevel; - } - - _widgets[type]->_backgroundOffset = maxShadow; -} - -void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { - r.clip(_screen->w, _screen->h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( - _vectorRenderer->blitSurface(_backBuffer, r); -} - -void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!ready()) - return; - - DrawData dd = kDDButtonIdle; - - if (state == kStateEnabled) - dd = kDDButtonIdle; - else if (state == kStateHighlight) - dd = kDDButtonHover; - else if (state == kStateDisabled) - dd = kDDButtonDisabled; - - queueDD(dd, r); - queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); -} - -void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!ready()) - return; - - queueDD(kDDSeparator, r); -} - -void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!ready()) - return; - - Common::Rect r2 = r; - DrawData dd = kDDCheckboxDefault; - - if (checked) - dd = kDDCheckboxSelected; - - if (state == kStateDisabled) - dd = kDDCheckboxDisabled; - - TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd); - const int checkBoxSize = MIN((int)r.height(), getFontHeight()); - - r2.bottom = r2.top + checkBoxSize; - r2.right = r2.left + checkBoxSize; - - queueDD(dd, r2); - - r2.left = r2.right + checkBoxSize; - r2.right = r.right; - - queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); -} - -void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { - if (!ready()) - return; - - DrawData dd = kDDSliderFull; - - if (state == kStateHighlight) - dd = kDDSliderHover; - else if (state == kStateDisabled) - dd = kDDSliderDisabled; - - Common::Rect r2 = r; - r2.setWidth(MIN((int16)width, r.width())); -// r2.top++; r2.bottom--; r2.left++; r2.right--; - - drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); - - if (width > r.width() * 5 / 100) - queueDD(dd, r2); -} - -void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { - if (!ready()) - return; - - queueDD(kDDScrollbarBase, r); - - Common::Rect r2 = r; - const int buttonExtra = (r.width() * 120) / 100; - - r2.bottom = r2.top + buttonExtra; - queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); - - r2.translate(0, r.height() - r2.height()); - queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); - - r2 = r; - r2.left += 1; - r2.right -= 1; - r2.top += sliderY; - r2.bottom = r2.top + sliderHeight - 1; - - r2.top += r.width() / 5; - r2.bottom -= r.width() / 5; - queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); -} - -void ThemeRenderer::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) { - if (!ready()) - return; - - switch (bgtype) { - case kDialogBackgroundMain: - queueDD(kDDMainDialogBackground, r); - break; - - case kDialogBackgroundSpecial: - queueDD(kDDSpecialColorBackground, r); - break; - - case kDialogBackgroundPlain: - queueDD(kDDPlainColorBackground, r); - break; - - case kDialogBackgroundDefault: - queueDD(kDDDefaultBackground, r); - break; - } -} - -void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { - if (!ready()) - return; - - if (erase) { - restoreBackground(r); - addDirtyRect(r); - } else - queueDD(kDDCaret, r); -} - -void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { - if (!ready()) - return; - - DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle; - - queueDD(dd, r); - - if (!sel.empty()) { - Common::Rect text(r.left, r.top, r.right - 16, r.bottom); - queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax); - } -} - -void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { - if (!ready()) - return; - - queueBitmap(&surface, r, themeTrans); -} - -void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { - if (!ready()) - return; - - switch (background) { - case kWidgetBackgroundBorderSmall: - queueDD(kDDWidgetBackgroundSmall, r); - break; - - case kWidgetBackgroundEditText: - queueDD(kDDWidgetBackgroundEditText, r); - break; - - case kWidgetBackgroundSlider: - queueDD(kDDWidgetBackgroundSlider, r); - break; - - default: - queueDD(kDDWidgetBackgroundDefault, r); - break; - } -} - -void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { - if (!ready()) - return; - - const int tabOffset = 2; - tabWidth -= tabOffset; - - queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); - - for (int i = 0; i < (int)tabs.size(); ++i) { - if (i == active) - continue; - - Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - queueDD(kDDTabInactive, tabRect); - queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); - } - - if (active >= 0) { - Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - const uint16 tabLeft = active * (tabWidth + tabOffset); - const uint16 tabRight = MAX(r.right - tabRect.right, 0); - queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); - queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); - } -} - -void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!ready()) - return; - - if (inverted) { - queueDD(kDDTextSelectionBackground, r); - queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax); - return; - } - - switch (font) { - case kFontStyleNormal: - queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); - return; - - default: - break; - } - - switch (state) { - case kStateDisabled: - queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); - return; - - case kStateHighlight: - queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); - return; - - case kStateEnabled: - queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); - return; - } -} - -void ThemeRenderer::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { - if (!ready()) - return; - - restoreBackground(r); - font->drawChar(_screen, ch, r.left, r.top, 0); - addDirtyRect(r); -} - -void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { - _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); - _screen->hLine(r.left, r.top, r.right, 0xFFFF); - _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); - _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); - _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); -} - -void ThemeRenderer::updateScreen() { - if (!_bufferQueue.empty()) { - _vectorRenderer->setSurface(_backBuffer); - - for (Common::List::const_iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) - drawDD(*q, true, false); - - _vectorRenderer->setSurface(_screen); - _vectorRenderer->blitSurface(_backBuffer, Common::Rect(0, 0, _screen->w, _screen->h)); - _bufferQueue.clear(); - } - - if (!_screenQueue.empty()) { - _vectorRenderer->disableShadows(); - for (Common::List::const_iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) - drawDD(*q, true, false); - - _vectorRenderer->enableShadows(); - _screenQueue.clear(); - } - - if (!_bitmapQueue.empty()) { - for (Common::List::const_iterator q = _bitmapQueue.begin(); q != _bitmapQueue.end(); ++q) - drawBitmap(*q); - - _bitmapQueue.clear(); - } - - if (!_textQueue.empty()) { - for (Common::List::const_iterator q = _textQueue.begin(); q != _textQueue.end(); ++q) - drawDDText(*q); - - _textQueue.clear(); - } - - renderDirtyScreen(); - -// _vectorRenderer->fillSurface(); -// themeEval()->debugDraw(_screen, _font); -// _vectorRenderer->copyWholeFrame(_system); -} - -void ThemeRenderer::renderDirtyScreen() { - if (_dirtyScreen.empty()) - return; - - Common::List::const_iterator i, j; - for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) { - for (j = i; j != _dirtyScreen.end(); ++j) - if (j != i && i->contains(*j)) - j = _dirtyScreen.reverse_erase(j); - - _vectorRenderer->copyFrame(_system, *i); - } - - _dirtyScreen.clear(); -} - -void ThemeRenderer::openDialog(bool doBuffer, ShadingStyle style) { - if (doBuffer) - _buffering = true; - - if (style != kShadingNone) { - _vectorRenderer->applyScreenShading(style); - addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h)); - } - - _vectorRenderer->setSurface(_backBuffer); - _vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h)); - _vectorRenderer->setSurface(_screen); -} - -void ThemeRenderer::setUpCursor() { - CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - CursorMan.showMouse(true); -} - -bool ThemeRenderer::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { - if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette)) - return false; - - const Surface *cursor = _bitmaps[filename]; - - if (!cursor) - return false; - - _cursorHotspotX = hotspotX; - _cursorHotspotY = hotspotY; - _cursorTargetScale = scale; - - _cursorWidth = cursor->w; - _cursorHeight = cursor->h; - - uint colorsFound = 0; - const OverlayColor *src = (const OverlayColor*)cursor->pixels; - - byte *table = new byte[65536]; - assert(table); - memset(table, 0, sizeof(byte)*65536); - - byte r, g, b; - - uint16 transparency = RGBToColor >(255, 0, 255); - - delete[] _cursor; - - _cursor = new byte[_cursorWidth * _cursorHeight]; - assert(_cursor); - memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); - - for (uint y = 0; y < _cursorHeight; ++y) { - for (uint x = 0; x < _cursorWidth; ++x) { - _system->colorToRGB(src[x], r, g, b); - uint16 col = RGBToColor >(r, g, b); - if (!table[col] && col != transparency) { - table[col] = colorsFound++; - - uint index = table[col]; - _cursorPal[index * 4 + 0] = r; - _cursorPal[index * 4 + 1] = g; - _cursorPal[index * 4 + 2] = b; - _cursorPal[index * 4 + 3] = 0xFF; - - if (colorsFound > MAX_CURS_COLORS) { - warning("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); - return false; - } - } - - if (col != transparency) { - uint index = table[col]; - _cursor[y * _cursorWidth + x] = index; - } - } - src += _cursorWidth; - } - - _useCursor = true; - delete[] table; - - return true; -} - -} // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h deleted file mode 100644 index e8f6d76ee2..0000000000 --- a/gui/ThemeRenderer.h +++ /dev/null @@ -1,732 +0,0 @@ -/* 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 INTERFACE_MANAGER_H -#define INTERFACE_MANAGER_H - -#include "common/scummsys.h" -#include "graphics/surface.h" -#include "common/system.h" - -#include "graphics/surface.h" -#include "graphics/fontman.h" - -#include "gui/dialog.h" -#include "gui/ThemeParser.h" -#include "graphics/VectorRenderer.h" -#include "gui/ThemeEval.h" - - -namespace GUI { - -struct WidgetDrawData; -struct DrawDataInfo; -class ThemeEval; - -struct TextDrawData { - const Graphics::Font *_fontPtr; - - struct { - uint8 r, g, b; - } _color; -}; - -struct WidgetDrawData { - /** List of all the steps needed to draw this widget */ - Common::List _steps; - - int _textDataId; - GUI::Theme::TextAlign _textAlignH; - GUI::Theme::TextAlignVertical _textAlignV; - - /** Extra space that the widget occupies when it's drawn. - E.g. when taking into account rounded corners, drop shadows, etc - Used when restoring the widget background */ - uint16 _backgroundOffset; - - /** Sets whether the widget is cached beforehand. */ - bool _cached; - bool _buffer; - - /** Texture where the cached widget is stored. */ - Graphics::Surface *_surfaceCache; - - ~WidgetDrawData() { - _steps.clear(); - - if (_surfaceCache) { - _surfaceCache->free(); - delete _surfaceCache; - } - } -}; - -class ThemeRenderer : public Theme { - -protected: - typedef Common::String String; - typedef GUI::Dialog Dialog; - typedef Common::HashMap ImagesMap; - - friend class GUI::Dialog; - friend class GUI::GuiObject; - - /** Constant value to expand dirty rectangles, to make sure they are fully copied */ - static const int kDirtyRectangleThreshold = 1; - - /** Sets whether backcaching is enabled */ - static const bool kEnableBackCaching = true; - - /** - * DrawData sets enumeration. - * Each DD set corresponds to the actual looks - * of a widget in a given state. - */ - enum DrawData { - kDDMainDialogBackground, - kDDSpecialColorBackground, - kDDPlainColorBackground, - kDDDefaultBackground, - kDDTextSelectionBackground, - - kDDWidgetBackgroundDefault, - kDDWidgetBackgroundSmall, - kDDWidgetBackgroundEditText, - kDDWidgetBackgroundSlider, - - kDDButtonIdle, - kDDButtonHover, - kDDButtonDisabled, - - kDDSliderFull, - kDDSliderHover, - kDDSliderDisabled, - - kDDCheckboxDefault, - kDDCheckboxDisabled, - kDDCheckboxSelected, - - kDDTabActive, - kDDTabInactive, - kDDTabBackground, - - kDDScrollbarBase, - kDDScrollbarButtonIdle, - kDDScrollbarButtonHover, - kDDScrollbarHandleIdle, - kDDScrollbarHandleHover, - - kDDPopUpIdle, - kDDPopUpHover, - - kDDCaret, - kDDSeparator, - kDrawDataMAX, - kDDNone = -1 - }; - - /** - * Default values for each DrawData item. - * @see kDrawDataDefaults[] for implementation. - */ - static const struct DrawDataInfo { - DrawData id; /** The actual ID of the DrawData item. */ - const char *name; /** The name of the DrawData item as it appears in the Theme Description files */ - bool buffer; /** Sets whether this item is buffered on the backbuffer or drawn directly to the screen. */ - DrawData parent; /** Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover */ - } kDrawDataDefaults[]; - - /** - * Queue Node for the drawing queue. - * Specifies the exact drawing to be done when processing - * the drawing queues. - */ - struct DrawQueue { - DrawData type; /** DrawData item to draw. */ - Common::Rect area; /** Place on screen to draw it. */ - uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/ - }; - - enum TextData { - kTextDataNone = -1, - kTextDataDefault = 0, - kTextDataHover, - kTextDataDisabled, - kTextDataInverted, - kTextDataButton, - kTextDataButtonHover, - kTextDataNormalFont, - kTextDataMAX - }; - - static const struct TextDataInfo { - TextData id; - const char *name; - } kTextDataDefaults[]; - - struct DrawQueueText { - TextData type; - Common::Rect area; - Common::String text; - - GUI::Theme::TextAlign alignH; - GUI::Theme::TextAlignVertical alignV; - bool ellipsis; - bool restoreBg; - int deltax; - }; - - struct BitmapQueue { - const Graphics::Surface *bitmap; - Common::Rect area; - bool alpha; - }; - -public: - /** Graphics mode enumeration. - * Each item represents a set of BPP and Renderer modes for a given - * surface. - */ - enum GraphicsMode { - kGfxDisabled = 0, /** No GFX */ - kGfxStandard16bit, /** 2BPP with the standard (aliased) renderer. */ - kGfxAntialias16bit, /** 2BPP with the optimized AA renderer. */ - kGfxMAX - }; - - static const char *rendererModeLabels[]; - - /** Default constructor */ - ThemeRenderer(Common::String fileName, GraphicsMode mode); - - /** Default destructor */ - ~ThemeRenderer(); - - GUI::ThemeEval *themeEval() { return _themeEval; } - - /** - * VIRTUAL METHODS - * This is the implementation of the GUI::Theme API to allow - * the ThemeRenderer class to be plugged in as any other GUI - * theme. In fact, the renderer works like any other GUI theme, - * but supports extensive customization of the drawn widgets. - */ - bool init(); - void deinit(); - void clearAll(); - - void refresh(); - void enable(); - void disable(); - - /** - * Implementation of the GUI::Theme API. Called when a - * new dialog is opened. Note that the boolean parameter - * meaning has been changed. - * - * @param enableBuffering If set to true, buffering is enabled for - * drawing this dialog, and will continue enabled - * until disabled. - */ - void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); - - /** - * The updateScreen() method is called every frame. - * It processes all the drawing queues and then copies dirty rects - * in the current Screen surface to the overlay. - */ - void updateScreen(); - - /** Since the rendering pipeline changes, closing all dialogs causes no effect - TODO: remove this from the original GUI::Theme API */ - void closeAllDialogs() {} - - /** Drawing area has been removed: it was too hackish. A workaround is on the works. - TODO: finish the workaround for the credits dialog - TODO: remove this from the original GUI::Theme API */ - void resetDrawArea() {} - - - /** - * FONT MANAGEMENT METHODS - */ - - TextData fontStyleToData(FontStyle font) const { - switch (font) { - case kFontStyleNormal: - return kTextDataNormalFont; - - default: - return kTextDataDefault; - } - } - - const Graphics::Font *getFont(FontStyle font) const { return _texts[fontStyleToData(font)]->_fontPtr; } - - int getFontHeight(FontStyle font = kFontStyleBold) const { - return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getFontHeight() : 0; - } - - int getStringWidth(const Common::String &str, FontStyle font) const { - return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0; - } - - int getCharWidth(byte c, FontStyle font) const { - return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0; - } - - - /** - * WIDGET DRAWING METHODS - */ - void drawWidgetBackground(const Common::Rect &r, uint16 hints, - WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); - - void drawButton(const Common::Rect &r, const Common::String &str, - WidgetStateInfo state = kStateEnabled, uint16 hints = 0); - - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, - WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); - - void drawSlider(const Common::Rect &r, int width, - WidgetStateInfo state = kStateEnabled); - - void drawCheckbox(const Common::Rect &r, const Common::String &str, - bool checked, WidgetStateInfo state = kStateEnabled); - - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, - const Common::Array &tabs, int active, uint16 hints, - int titleVPad, WidgetStateInfo state = kStateEnabled); - - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, - ScrollbarState, WidgetStateInfo state = kStateEnabled); - - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, - int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); - - void drawCaret(const Common::Rect &r, bool erase, - WidgetStateInfo state = kStateEnabled); - - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); - - void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state); - - void drawText(const Common::Rect &r, const Common::String &str, - WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - - void drawChar(const Common::Rect &r, byte ch, - const Graphics::Font *font, WidgetStateInfo state); - - /** - * Actual implementation of a Dirty Rect drawing routine. - * Dirty rectangles are queued on a list and are later merged/calculated - * before the actual drawing. - * - * @param r Area of the dirty rect. - * @param backup Deprecated. - * @param special Deprecated. - */ - bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { - _dirtyScreen.push_back(r); - return true; - } - - - /** - * Returns the DrawData enumeration value that represents the given string - * in the DrawDataDefaults enumeration. - * It's slow, but called sparsely. - * - * @returns The drawdata enum value, or -1 if not found. - * @param name The representing name, as found on Theme Description XML files. - * @see kDrawDataDefaults[] - */ - DrawData getDrawDataId(const Common::String &name) { - for (int i = 0; i < kDrawDataMAX; ++i) - if (name.compareToIgnoreCase(kDrawDataDefaults[i].name) == 0) - return kDrawDataDefaults[i].id; - - return kDDNone; - } - - TextData getTextDataId(const Common::String &name) { - for (int i = 0; i < kTextDataMAX; ++i) - if (name.compareToIgnoreCase(kTextDataDefaults[i].name) == 0) - return kTextDataDefaults[i].id; - - return kTextDataNone; - } - - /** - * Interface for ThemeParser class: Parsed DrawSteps are added via this function. - * There is no return type because DrawSteps can always be added, unless something - * goes horribly wrong. - * The specified step will be added to the Steps list of the given DrawData id. - * - * @param drawDataId The representing DrawData name, as found on Theme Description XML files. - * @param step The actual DrawStep struct to be added. - */ - void addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step); - - /** - * Interfacefor the ThemeParser class: Parsed DrawData sets are added via this function. - * The goal of the function is to initialize each DrawData set before their DrawSteps can - * be added, hence this must be called for each DD set before addDrawStep() can be called - * for that given set. - * - * @param data The representing DrawData name, as found on Theme Description XML files. - * @param cached Whether this DD set will be cached beforehand. - */ - bool addDrawData(const Common::String &data, bool cached); - - - /** - * Interface for the ThemeParser class: Loads a font to use on the GUI from the given - * filename. - * - * @param fontName Identifier name for the font. - * @param file Name of the font file. - * @param r, g, b Color of the font. - */ - bool addFont(const Common::String &fontName, const Common::String &file, int r, int g, int b); - - - /** - * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI. - * The filename is also used as its identifier. - * - * @param filename Name of the bitmap file. - */ - bool addBitmap(const Common::String &filename); - - /** - * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the - * new Font API is in place. - */ - bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV); - - /** Interface to the new Theme XML parser */ - ThemeParser *parser() { - return _parser; - } - - /** - * Returns if the Theme is ready to draw stuff on screen. - * Must be called instead of just checking _initOk, because - * this checks if the renderer is initialized AND if the theme - * is loaded. - */ - bool ready() const { - return _initOk && _themeOk; - } - - /** Custom implementation of the GUI::Theme API, changed to use the XML parser. */ - bool loadTheme(Common::String themeName); - - /** - * Changes the active graphics mode of the GUI; may be used to either - * initialize the GUI or to change the mode while the GUI is already running. - */ - void setGraphicsMode(GraphicsMode mode); - - - /** - * Finishes buffering: widgets from there one will be drawn straight on the screen - * without drawing queues. - */ - void finishBuffering() { _buffering = false; } - void startBuffering() { _buffering = true; } - - ThemeEval *evaluator() { return _themeEval; } - - bool supportsImages() const { return true; } - bool ownCursor() const { return _useCursor; } - - Graphics::Surface *getBitmap(const Common::String &name) { - return _bitmaps.contains(name) ? _bitmaps[name] : 0; - } - - const Graphics::Surface *getImageSurface(const kThemeImages n) const { - if (n == kImageLogo) - return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; - - return 0; - } - - /** - * Interface for the Theme Parser: Creates a new cursor by loading the given - * bitmap and sets it as the active cursor. - * - * @param filename File name of the bitmap to load. - * @param hotspotX X Coordinate of the bitmap which does the cursor click. - * @param hotspotY Y Coordinate of the bitmap which does the cursor click. - * @param scale Scale at which the bitmap is supposed to be used. - */ - bool createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale); - -protected: - - const Common::String &getThemeName() const { return _themeName; } - const Common::String &getThemeFileName() const { return _themeFileName; } - int getThemeRenderer() const { return _graphicsMode; } - - /** - * Initializes the drawing screen surfaces, _screen and _backBuffer. - * If the surfaces already exist, they are cleared and re-initialized. - * - * @param backBuffer Sets whether the _backBuffer surface should be initialized. - * @template PixelType C type which specifies the size of each pixel. - * Defaults to uint16 (2 BPP for the surfaces) - */ - template void screenInit(bool backBuffer = true); - - /** - * Loads the given theme into the ThemeRenderer. - * Note that ThemeName is an identifier, not a filename. - * - * @param ThemeName Theme identifier. - * @returns True if the theme was succesfully loaded. - */ - bool loadThemeXML(Common::String themeName); - - /** - * Loads the default theme file (the embeded XML file found - * in ThemeDefaultXML.cpp). - * Called only when no other themes are available. - */ - bool loadDefaultXML(); - - /** - * Unloads the currently loaded theme so another one can - * be loaded. - */ - void unloadTheme(); - - /** - * Not implemented yet. - * TODO: reload themes, reload the renderer, recheck everything - */ - void screenChange() { - error("Screen Changes are not supported yet. Fix this!"); - } - - /** - * Actual Dirty Screen handling function. - * Handles all the dirty squares in the list, merges and optimizes - * them when possible and draws them to the screen. - * Called from updateScreen() - */ - void renderDirtyScreen(); - - /** - * Frees the vector renderer. - */ - void freeRenderer() { - delete _vectorRenderer; - _vectorRenderer = 0; - } - - /** - * Frees the Back buffer surface, only if it's available. - */ - void freeBackbuffer() { - if (_backBuffer != 0) { - _backBuffer->free(); - delete _backBuffer; - _backBuffer = 0; - } - } - - /** - * Frees the main screen drawing surface, only if it's available. - */ - void freeScreen() { - if (_screen != 0) { - _screen->free(); - delete _screen; - _screen = 0; - } - } - - TextData getTextData(DrawData ddId) { - return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone; - } - - /** - * Checks if a given DrawData set for a widget has been cached beforehand - * and is ready to be blit into the screen. - * - * @param type DrawData type of the widget. - * @param r Size of the widget which is expected to be cached. - */ - bool isWidgetCached(DrawData type, const Common::Rect &r); - - /** - * Draws a cached widget directly on the screen. Currently deprecated. - * - * @param type DrawData type of the widget. - * @param r Position on screen to draw the widget. - */ - void drawCached(DrawData type, const Common::Rect &r); - - /** - * Calculates the background threshold offset of a given DrawData item. - * After fully loading all DrawSteps of a DrawData item, this function must be - * called in order to calculate if such draw steps would be drawn outside of - * the actual widget drawing zone (e.g. shadows). If this is the case, a constant - * value will be added when restoring the background of the widget. - * - * @param type DrawData type of the widget. - */ - void calcBackgroundOffset(DrawData type); - - /** - * Draws a DrawQueue item (which contains DrawData information and a screen - * position) into the screen. - * - * This is the only way the Theme has to drawn on the screen. - * - * @param draw Sets if the DrawData info will be actually drawn. - * @param restore Sets if the background behind the widget will be restored before drawing. - */ - inline void drawDD(const DrawQueue &q, bool draw = true, bool restore = false); - inline void drawDDText(const DrawQueueText &q); - inline void drawBitmap(const BitmapQueue &q); - - /** - * Generates a DrawQueue item and enqueues it so it's drawn to the screen - * when the drawing queue is processed. - * - * If Buffering is enabled, the DrawQueue item will be automatically placed - * on its corresponding queue. - * If Buffering is disabled, the DrawQueue item will be processed immediately - * and drawn to the screen. - * - * This function is called from all the Widget Drawing methods. - */ - inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); - inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); - inline void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); - - /** - * DEBUG: Draws a white square around the given position and writes the given next to it. - */ - inline void debugWidgetPosition(const char *name, const Common::Rect &r); - - - /** - * Wrapper for restoring data from the Back Buffer to the screen. - * The actual processing is done in the VectorRenderer. - * - * @param r Area to restore. - * @param special Deprecated. - */ - void restoreBackground(Common::Rect r, bool special = false); - - - /** - * Default values from GUI::Theme - */ - int getTabSpacing() const { return 0; } - int getTabPadding() const { return 3; } - - OSystem *_system; /** Global system object. */ - - /** Vector Renderer object, does the actual drawing on screen */ - Graphics::VectorRenderer *_vectorRenderer; - - /** XML Parser, does the Theme parsing instead of the default parser */ - GUI::ThemeParser *_parser; - - /** Theme evaluator (changed from GUI::Eval to add functionality) */ - GUI::ThemeEval *_themeEval; - - /** Main screen surface. This is blitted straight into the overlay. */ - Graphics::Surface *_screen; - - /** Backbuffer surface. Stores previous states of the screen to blit back */ - Graphics::Surface *_backBuffer; - - /** Sets whether the current drawing is being buffered (stored for later - processing) or drawn directly to the screen. */ - bool _buffering; - - /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ - int _bytesPerPixel; - - /** Current graphics mode */ - GraphicsMode _graphicsMode; - - /** Font info. */ - Common::String _fontName; - const Graphics::Font *_font; - - /** Array of all the DrawData elements than can be drawn to the screen. - Must be full so the renderer can work. */ - WidgetDrawData *_widgets[kDrawDataMAX]; - - /** Array of all the text fonts that can be drawn. */ - TextDrawData *_texts[kTextDataMAX]; - - ImagesMap _bitmaps; - - /** List of all the dirty screens that must be blitted to the overlay. */ - Common::List _dirtyScreen; - - /** Queue with all the drawing that must be done to the Back Buffer */ - Common::List _bufferQueue; - - /** Queue with all the drawing that must be done to the screen */ - Common::List _screenQueue; - - /** Queue with all the text drawing that must be done to the screen */ - Common::List _textQueue; - - Common::List _bitmapQueue; - - bool _initOk; /** Class and renderer properly initialized */ - bool _themeOk; /** Theme data successfully loaded. */ - bool _enabled; /** Whether the Theme is currently shown on the overlay */ - - Common::String _themeName; /** Name of the currently loaded theme */ - Common::String _themeFileName; - - /** Custom Cursor Management */ - void setUpCursor(); - - bool _useCursor; - int _cursorHotspotX, _cursorHotspotY; - int _cursorTargetScale; -#define MAX_CURS_COLORS 255 - byte *_cursor; - bool _needPaletteUpdates; - uint _cursorWidth, _cursorHeight; - byte _cursorPal[4*MAX_CURS_COLORS]; -}; - -} // end of namespace GUI. - -#endif diff --git a/gui/module.mk b/gui/module.mk index f1ba840459..f87ef36599 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -9,7 +9,7 @@ MODULE_OBJS := \ dialog.o \ editable.o \ EditTextWidget.o \ - ThemeRenderer.o \ + ThemeEngine.o \ launcher.o \ ListWidget.o \ massadd.o \ @@ -24,6 +24,7 @@ MODULE_OBJS := \ widget.o \ theme.o \ ThemeEval.o \ + ThemeLayout.o \ ThemeParser.o # Include common rules diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 2291d9e3c1..097a38291a 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -28,7 +28,7 @@ #include "graphics/cursorman.h" #include "gui/newgui.h" #include "gui/dialog.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" #include "common/config-manager.h" @@ -96,7 +96,7 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), // themefile += ".zip"; ConfMan.registerDefault("gui_renderer", 2); - ThemeRenderer::GraphicsMode gfxMode = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); + ThemeEngine::GraphicsMode gfxMode = (ThemeEngine::GraphicsMode)ConfMan.getInt("gui_renderer"); loadNewTheme(themefile, gfxMode); _themeChange = false; @@ -106,14 +106,14 @@ NewGui::~NewGui() { delete _theme; } -bool NewGui::loadNewTheme(const Common::String &filename, ThemeRenderer::GraphicsMode gfx) { - if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getThemeRenderer()) +bool NewGui::loadNewTheme(const Common::String &filename, ThemeEngine::GraphicsMode gfx) { + if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getGraphicsMode()) return true; Common::String oldTheme = (_theme != 0) ? _theme->getThemeFileName() : ""; - if (gfx == ThemeRenderer::kGfxDisabled) - gfx = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); + if (gfx == ThemeEngine::kGfxDisabled) + gfx = (ThemeEngine::GraphicsMode)ConfMan.getInt("gui_renderer"); if (_theme) _theme->disable(); @@ -126,7 +126,7 @@ bool NewGui::loadNewTheme(const Common::String &filename, ThemeRenderer::Graphic delete _theme; _theme = 0; - _theme = new ThemeRenderer(filename, gfx); + _theme = new ThemeEngine(filename, gfx); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); diff --git a/gui/newgui.h b/gui/newgui.h index cc9e6b9f3c..9dace522ab 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -33,7 +33,7 @@ #include "gui/theme.h" #include "gui/widget.h" -#include "gui/ThemeRenderer.h" +#include "gui/ThemeEngine.h" class OSystem; @@ -78,7 +78,7 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(const Common::String &file, ThemeRenderer::GraphicsMode gfx = ThemeRenderer::kGfxDisabled); + bool loadNewTheme(const Common::String &file, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); Theme *theme() { return _theme; } ThemeEval *xmlEval() { return _theme->evaluator(); } diff --git a/gui/options.cpp b/gui/options.cpp index c24b338af6..110f7c9b69 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -736,8 +736,8 @@ GlobalOptionsDialog::GlobalOptionsDialog() _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.Renderer", "GUI Renderer:", labelWidth); - for (int i = 1; i < GUI::ThemeRenderer::kGfxMAX; ++i) { - _rendererPopUp->appendEntry(GUI::ThemeRenderer::rendererModeLabels[i], i); + for (int i = 1; i < GUI::ThemeEngine::kGfxMAX; ++i) { + _rendererPopUp->appendEntry(GUI::ThemeEngine::rendererModeLabels[i], i); } _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth); @@ -845,7 +845,7 @@ void GlobalOptionsDialog::close() { ConfMan.setInt("autosave_period", _autosavePeriodPopUp->getSelectedTag(), _domain); if ((int)_rendererPopUp->getSelectedTag() != ConfMan.getInt("gui_renderer")) { - g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), (GUI::ThemeRenderer::GraphicsMode)_rendererPopUp->getSelectedTag()); + g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), (GUI::ThemeEngine::GraphicsMode)_rendererPopUp->getSelectedTag()); ConfMan.setInt("gui_renderer", _rendererPopUp->getSelectedTag(), _domain); } } diff --git a/gui/theme.h b/gui/theme.h index 50b2951ae5..57744db584 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -310,7 +310,7 @@ public: virtual const Common::String &getThemeFileName() const = 0; virtual const Common::String &getThemeName() const = 0; - virtual int getThemeRenderer() const = 0; + virtual int getGraphicsMode() const = 0; /** * Checks if the theme renderer supports drawing of images. -- cgit v1.2.3 From 689341894228292f792b00b36299398ffdd8c841 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 5 Sep 2008 11:32:23 +0000 Subject: Fixing some compiler warnings svn-id: r34341 --- graphics/VectorRendererSpec.h | 2 +- gui/ThemeEngine.cpp | 2 -- gui/ThemeEngine.h | 1 + gui/ThemeLayout.cpp | 2 +- gui/ThemeLayout.h | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index 04f28d4020..f9669bdb41 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -296,4 +296,4 @@ protected: }; } -#endif \ No newline at end of file +#endif diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 006a8768a6..8da4d3d808 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -939,8 +939,6 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { * Screen/overlay management *********************************************************/ void ThemeEngine::updateScreen() { - ThemeItem *item = 0; - if (!_bufferQueue.empty()) { _vectorRenderer->setSurface(_backBuffer); diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 9f7fe35d82..2d99076fc3 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -88,6 +88,7 @@ class ThemeItem { public: ThemeItem(ThemeEngine *engine, const Common::Rect &area) : _engine(engine), _area(area) {} + virtual ~ThemeItem() {} virtual void drawSelf(bool doDraw, bool doRestore) = 0; diff --git a/gui/ThemeLayout.cpp b/gui/ThemeLayout.cpp index a70fb6cdc6..247c1c0d5e 100644 --- a/gui/ThemeLayout.cpp +++ b/gui/ThemeLayout.cpp @@ -224,4 +224,4 @@ void ThemeLayoutHorizontal::reflowLayout() { } -} \ No newline at end of file +} diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h index 293804d822..87078d086e 100644 --- a/gui/ThemeLayout.h +++ b/gui/ThemeLayout.h @@ -236,4 +236,4 @@ public: } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 020be5bc2183ef8cdf27595a476b8b1cc4cff194 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 5 Sep 2008 11:33:19 +0000 Subject: Fixing a typo :) svn-id: r34342 --- graphics/VectorRendererSpec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index a84a3d6f23..e3000346e2 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -36,7 +36,7 @@ #define VECTOR_RENDERER_FAST_TRIANGLES -/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ +/** HELPER MACROS for BRESENHAM's circle drawing algorithm **/ #define __BE_ALGORITHM() { \ if (f >= 0) { \ y--; \ -- cgit v1.2.3 From e0592c7d25acd42cd93b9dab5048209bab858ba8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 5 Sep 2008 14:48:47 +0000 Subject: Fixed severe bottleneck in the XML Parser code. Applied Max's patch for character drawing. Added new FP squareroot function. svn-id: r34354 --- common/xmlparser.cpp | 62 +++++++---- common/xmlparser.h | 238 ++++++++-------------------------------- graphics/VectorRendererSpec.cpp | 104 +++++++++++++----- graphics/font.cpp | 49 +++++---- gui/newgui.cpp | 4 +- gui/newgui.h | 2 +- 6 files changed, 194 insertions(+), 265 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 900f2f81ab..44bf03336e 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -37,7 +37,8 @@ using namespace Graphics; bool XMLParser::parserError(const char *errorString, ...) { _state = kParserError; - int pos = _pos; + int original_pos = _stream->pos(); + int pos = original_pos; int lineCount = 1; int lineStart = 0; @@ -46,18 +47,21 @@ bool XMLParser::parserError(const char *errorString, ...) { lineCount = 0; } else { do { - if (_text[pos] == '\n' || _text[pos] == '\r') { + if (_char == '\n' || _char == '\r') { lineCount++; if (lineStart == 0) lineStart = MAX(pos + 1, _pos - 60); } - } while (pos-- > 0); + + _stream->seek(-1, SEEK_CUR); + + } while (_stream->pos() > 0); } char lineStr[70]; - _text.stream()->seek(lineStart, SEEK_SET); - _text.stream()->readLine(lineStr, 70); + _stream->seek(original_pos - 35, SEEK_SET); + _stream->readLine(lineStr, 70); for (int i = 0; i < 70; ++i) if (lineStr[i] == '\n') @@ -70,7 +74,7 @@ bool XMLParser::parserError(const char *errorString, ...) { printf("%s%s%s\n", startFull ? "" : "...", lineStr, endFull ? "" : "..."); - int cursor = MIN(_pos - lineStart, 70); + int cursor = 35; if (!startFull) cursor += 3; @@ -149,15 +153,20 @@ bool XMLParser::parseKeyValue(Common::String keyName) { _token.clear(); char stringStart; - if (_text[_pos] == '"' || _text[_pos] == '\'') { - stringStart = _text[_pos++]; + if (_char == '"' || _char == '\'') { + stringStart = _char; + _char = _stream->readByte(); - while (_text[_pos] && _text[_pos] != stringStart) - _token += _text[_pos++]; + while (_char && _char != stringStart) { + _token += _char; + _char = _stream->readByte(); + } - if (_text[_pos++] == 0) + if (_char == 0) return false; + _char = _stream->readByte(); + } else if (!parseToken()) { return false; } @@ -185,7 +194,7 @@ bool XMLParser::closeKey() { bool XMLParser::parse() { - if (_text.ready() == false) + if (_stream == 0) return parserError("XML stream not ready for reading."); if (_XMLkeys == 0) @@ -202,8 +211,10 @@ bool XMLParser::parse() { _state = kParserNeedKey; _pos = 0; _activeKey.clear(); + + _char = _stream->readByte(); - while (_text[_pos] && _state != kParserError) { + while (_char && _state != kParserError) { if (skipSpaces()) continue; @@ -212,18 +223,18 @@ bool XMLParser::parse() { switch (_state) { case kParserNeedKey: - if (_text[_pos++] != '<') { + if (_char != '<') { parserError("Parser expecting key start."); break; } - if (_text[_pos] == 0) { + if ((_char = _stream->readByte()) == 0) { parserError("Unexpected end of file."); break; } - if (_text[_pos] == '/' && _text[_pos + 1] != '*') { - _pos++; + if (_char == '/') { // FIXME: What if it's a comment start + _char = _stream->readByte(); activeClosure = true; } @@ -262,19 +273,25 @@ bool XMLParser::parse() { activeClosure = false; - if (_text[_pos++] != '>') + if (_char != '>') parserError("Invalid syntax in key closure."); else _state = kParserNeedKey; + _char = _stream->readByte(); break; } - selfClosure = (_text[_pos] == '/'); + selfClosure = false; + + if (_char == '/') { // FIXME: comment start? + selfClosure = true; + _char = _stream->readByte(); + } - if ((selfClosure && _text[_pos + 1] == '>') || _text[_pos] == '>') { + if (_char == '>') { if (parseActiveKey(selfClosure)) { - _pos += selfClosure ? 2 : 1; + _char = _stream->readByte(); _state = kParserNeedKey; } break; @@ -288,11 +305,12 @@ bool XMLParser::parse() { break; case kParserNeedPropertyOperator: - if (_text[_pos++] != '=') + if (_char != '=') parserError("Syntax error after key name."); else _state = kParserNeedPropertyValue; + _char = _stream->readByte(); break; case kParserNeedPropertyValue: diff --git a/common/xmlparser.h b/common/xmlparser.h index 4d1c8fc85d..7edabf62f3 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -40,145 +40,12 @@ namespace Common { -/*********************************************** - **** XMLParser.cpp/h -- Generic XML Parser **** - *********************************************** +/* + XMLParser.cpp/h -- Generic XML Parser + ===================================== - This is a simple implementation of a generic parser which is able to - interpret a subset of the XML language. - - The XMLParser class is virtual, and must be derived into a child class, - called a Custom Parser Class, which will manage the parsed data for your - specific needs. - - Custom Parser Classes have two basic requirements: - They must inherit directly the XMLParser class, and they must define the - parsing layout of the XML file. - - Declaring the XML layout is done with the help of the CUSTOM_XML_PARSER() - macro: this macro must appear once inside the Custom Parser Class - declaration, and takes a single parameter, the name of the Custom Parser - Class. - - The macro must be followed by the actual layout of the XML files to be - parsed, and closed with the PARSER_END() macro. The layout of XML files - is defined by the use of 3 helper macros: XML_KEY(), KEY_END() and - XML_PROP(). - - Here's a sample of its usage: - - =========== =========== =========== =========== =========== =========== - - 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() - KEY_END() - } PARSER_END() - - =========== =========== =========== =========== =========== =========== - - The XML_KEY() macro takes a single argument, the name of the expected key. - Inside the scope of each key, you may define properties for the given key - with the XML_PROP() macro, which takes as parameters the name of the - property and whether it's optional or required. You might also define the - contained children keys, using the XML_KEY() macro again. - The scope of a XML key is closed with the KEY_END() macro. - - Keys which may contain any kind of Property names may be defined with the - XML_PROP_ANY() macro instead of the XML_PROP() macro. This macro takes no - arguments. - - As an example, the following XML layout: - - XML_KEY(palette) - XML_KEY(color) - XML_PROP(name, true) - XML_PROP(rgb, true) - XML_PROP(optional_param, false) - KEY_END() - KEY_END() - - will expect to parse a syntax like this: - - - - - - - Once a layout has been defined, everytime a XML node (that is, a key and - all its properties) has been parsed, a specific callback funcion is called, - which should take care of managing the parsed data for the node. - - Callback functions must be explicitly declared with the following syntax: - - bool parserCallback_KEYNAME(ParserNode *node); - - A callback function is needed for each key that can be parsed, since they - are called automatically; the function will receive a pointer to the XML - Node that has been parsed. This XML Node has the following properties: - - - It's assured to be expected in the layout of the XML file (i.e. - has the proper position and depth in the XML tree). - - - It's assured to contain all the required Properties that have - been declared in the XML layout. - - - It's assured to contain NO unexpected properties (i.e. properties - which haven't been declared in the XML layout). - - Further validation of the Node's data may be performed inside the callback - function. Once the node has been validated and its data has been parsed/ - managed, the callback function is expected to return true. - - If the data in the XML Node is corrupted or there was a problem when - parsing it, the callback function is expected to return false or, - preferably, to throw a parserError() using the following syntax: - - return parserError("There was a problem in key '%s'.", arg1, ...); - - Also, note that the XML parser doesn't take into account the actual order - of the keys and properties in the XML layout definition, only its layout - and relationships. - - Lastly, when defining your own Custom XML Parser, further customization - may be accomplished _optionally_ by overloading several virtual functions - of the XMLParser class. - - Check the API documentation of the following functions for more info: - - virtual bool closedKeyCallback(ParserNode *node); - virtual bool skipComments(); - virtual bool isValidNameChar(char c); - virtual void cleanup(); - - Check the sample implementation of the GUI::ThemeParser custom parser - for a working sample of a Custom XML Parser. - + External documentation available at: + http://www.smartlikearoboc.com/scummvm_doc/xmlparser_doc.html */ #define XML_KEY(keyName) {\ @@ -226,43 +93,6 @@ namespace Common { #define PARSER_END() layout.clear(); } -class XMLStream { -protected: - SeekableReadStream *_stream; - int _pos; - -public: - XMLStream() : _stream(0), _pos(0) {} - - ~XMLStream() { - delete _stream; - } - - SeekableReadStream *stream() { - return _stream; - } - - char operator [](int idx) { - assert(_stream && idx >= 0); - - if (_pos + 1 != idx) - _stream->seek(idx, SEEK_SET); - - _pos = idx; - - return _stream->readByte(); - } - - void loadStream(SeekableReadStream *s) { - delete _stream; - _stream = s; - } - - bool ready() { - return _stream != 0; - } -}; - /** * The base XMLParser class implements generic functionality for parsing * XML-like files. @@ -278,13 +108,14 @@ public: /** * Parser constructor. */ - XMLParser() : _XMLkeys(0) {} + XMLParser() : _XMLkeys(0), _stream(0) {} virtual ~XMLParser() { while (!_activeKey.empty()) delete _activeKey.pop(); delete _XMLkeys; + delete _stream; for (Common::List::iterator i = _layoutList.begin(); i != _layoutList.end(); ++i) @@ -352,7 +183,7 @@ public: } _fileName = filename; - _text.loadStream(f); + _stream = f; return true; } @@ -365,7 +196,7 @@ public: } _fileName = node.getName(); - _text.loadStream(f); + _stream = f; return true; } @@ -381,13 +212,13 @@ public: * no longer needed by the parser. */ bool loadBuffer(const byte *buffer, uint32 size, bool disposable = false) { - _text.loadStream(new MemoryReadStream(buffer, size, disposable)); + _stream = new MemoryReadStream(buffer, size, disposable); _fileName = "Memory Stream"; return true; } bool loadStream(MemoryReadStream *stream) { - _text.loadStream(stream); + _stream = stream; _fileName = "Compressed File Stream"; return true; } @@ -492,11 +323,11 @@ protected: * Skips spaces/whitelines etc. Returns true if any spaces were skipped. */ bool skipSpaces() { - if (!isspace(_text[_pos])) + if (!isspace(_char)) return false; - while (_text[_pos] && isspace(_text[_pos])) - _pos++; + while (_char && isspace(_char)) + _char = _stream->readByte(); return true; } @@ -508,14 +339,31 @@ protected: * or to change the commenting syntax. */ virtual bool skipComments() { - if (_text[_pos] == '/' && _text[_pos + 1] == '*') { - _pos += 2; - while (_text[_pos++]) { - if (_text[_pos - 2] == '*' && _text[_pos - 1] == '/') + char endComment1 = 0, endComment2 = 0; + + if (_char == '/') { + _char = _stream->readByte(); + + if (_char != '*') { + _stream->seek(-1, SEEK_CUR); + _char = '/'; + return false; + } + + _char = _stream->readByte(); + + while (_char) { + endComment1 = endComment2; + endComment2 = _char; + _char = _stream->readByte(); + + if (endComment1 == '*' && endComment2 == '/') break; - if (_text[_pos] == 0) + + if (_char == 0) parserError("Comment has no closure."); } + _char = _stream->readByte(); return true; } @@ -527,7 +375,7 @@ protected: * Overload this if you want to support keys with strange characters * in their name. */ - virtual bool isValidNameChar(char c) { + virtual inline bool isValidNameChar(char c) { return isalnum(c) || c == '_'; } @@ -537,10 +385,13 @@ protected: */ bool parseToken() { _token.clear(); - while (isValidNameChar(_text[_pos])) - _token += _text[_pos++]; - return isspace(_text[_pos]) != 0 || _text[_pos] == '>' || _text[_pos] == '=' || _text[_pos] == '/'; + while (isValidNameChar(_char)) { + _token += _char; + _char = _stream->readByte(); + } + + return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/'; } /** @@ -599,7 +450,8 @@ protected: private: int _pos; /** Current position on the XML buffer. */ - XMLStream _text; /** Buffer with the text being parsed */ + char _char; + SeekableReadStream *_stream; Common::String _fileName; ParserState _state; /** Internal state of the parser */ diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e3000346e2..428ec7ee5e 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -36,7 +36,71 @@ #define VECTOR_RENDERER_FAST_TRIANGLES -/** HELPER MACROS for BRESENHAM's circle drawing algorithm **/ +const uint16 inv_sqrt_tbl[] = { + 0x0000, 0x0100, 0x016A, 0x01BB, 0x0200, 0x023C, 0x0273, 0x02A5, + 0x02D4, 0x0300, 0x0329, 0x0351, 0x0376, 0x039B, 0x03BD, 0x03DF, + 0x0400, 0x041F, 0x043E, 0x045B, 0x0478, 0x0495, 0x04B0, 0x04CB, + 0x04E6, 0x0500, 0x0519, 0x0532, 0x054A, 0x0562, 0x057A, 0x0591, + 0x05A8, 0x05BE, 0x05D4, 0x05EA, 0x0600, 0x0615, 0x062A, 0x063E, + 0x0653, 0x0667, 0x067B, 0x068E, 0x06A2, 0x06B5, 0x06C8, 0x06DB, + 0x06ED, 0x0700, 0x0712, 0x0724, 0x0736, 0x0747, 0x0759, 0x076A, + 0x077B, 0x078C, 0x079D, 0x07AE, 0x07BE, 0x07CF, 0x07DF, 0x07EF, + 0x0800, 0x080F, 0x081F, 0x082F, 0x083F, 0x084E, 0x085D, 0x086D, + 0x087C, 0x088B, 0x089A, 0x08A9, 0x08B7, 0x08C6, 0x08D4, 0x08E3, + 0x08F1, 0x0900, 0x090E, 0x091C, 0x092A, 0x0938, 0x0946, 0x0953, + 0x0961, 0x096F, 0x097C, 0x098A, 0x0997, 0x09A4, 0x09B2, 0x09BF, + 0x09CC, 0x09D9, 0x09E6, 0x09F3, 0x0A00, 0x0A0C, 0x0A19, 0x0A26, + 0x0A32, 0x0A3F, 0x0A4B, 0x0A58, 0x0A64, 0x0A70, 0x0A7C, 0x0A89, + 0x0A95, 0x0AA1, 0x0AAD, 0x0AB9, 0x0AC5, 0x0AD1, 0x0ADC, 0x0AE8, + 0x0AF4, 0x0B00, 0x0B0B, 0x0B17, 0x0B22, 0x0B2E, 0x0B39, 0x0B44, + 0x0B50, 0x0B5B, 0x0B66, 0x0B72, 0x0B7D, 0x0B88, 0x0B93, 0x0B9E, + 0x0BA9, 0x0BB4, 0x0BBF, 0x0BCA, 0x0BD5, 0x0BDF, 0x0BEA, 0x0BF5, + 0x0C00, 0x0C0A, 0x0C15, 0x0C1F, 0x0C2A, 0x0C34, 0x0C3F, 0x0C49, + 0x0C54, 0x0C5E, 0x0C68, 0x0C73, 0x0C7D, 0x0C87, 0x0C91, 0x0C9C, + 0x0CA6, 0x0CB0, 0x0CBA, 0x0CC4, 0x0CCE, 0x0CD8, 0x0CE2, 0x0CEC, + 0x0CF6, 0x0D00, 0x0D09, 0x0D13, 0x0D1D, 0x0D27, 0x0D30, 0x0D3A, + 0x0D44, 0x0D4D, 0x0D57, 0x0D61, 0x0D6A, 0x0D74, 0x0D7D, 0x0D87, + 0x0D90, 0x0D99, 0x0DA3, 0x0DAC, 0x0DB6, 0x0DBF, 0x0DC8, 0x0DD1, + 0x0DDB, 0x0DE4, 0x0DED, 0x0DF6, 0x0E00, 0x0E09, 0x0E12, 0x0E1B, + 0x0E24, 0x0E2D, 0x0E36, 0x0E3F, 0x0E48, 0x0E51, 0x0E5A, 0x0E63, + 0x0E6C, 0x0E74, 0x0E7D, 0x0E86, 0x0E8F, 0x0E98, 0x0EA0, 0x0EA9, + 0x0EB2, 0x0EBB, 0x0EC3, 0x0ECC, 0x0ED5, 0x0EDD, 0x0EE6, 0x0EEE, + 0x0EF7, 0x0F00, 0x0F08, 0x0F11, 0x0F19, 0x0F21, 0x0F2A, 0x0F32, + 0x0F3B, 0x0F43, 0x0F4C, 0x0F54, 0x0F5C, 0x0F65, 0x0F6D, 0x0F75, + 0x0F7D, 0x0F86, 0x0F8E, 0x0F96, 0x0F9E, 0x0FA7, 0x0FAF, 0x0FB7, + 0x0FBF, 0x0FC7, 0x0FCF, 0x0FD7, 0x0FDF, 0x0FE7, 0x0FEF, 0x0FF7, + 0x1000 +}; + +inline uint32 fp_sqroot(uint32 x) { + int bit; + +#if defined(__arm__) + __asm__ ("clz %0, %1\nrsb %0, %0, #31\n" : "=r"(bit) : "r" (x)); +#elif defined(__i386__) + __asm__("bsrl %1, %0" : "=r" (bit) : "r" (x)); +#else + unsigned int mask = 0x40000000; + bit = 30; + while (bit >= 0) { + if (x & mask) + break; + + mask = (mask >> 1 | mask >> 2); + bit -= 2; + } +#endif + + bit -= 6 + (bit & 1); + return inv_sqrt_tbl[x >> bit] << (bit >> 1); +} + +inline uint32 circleSqrt(int x) { + return (x > 255 ? fp_sqroot(x) : inv_sqrt_tbl[x]) ^ 0xFF; +} + + +/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ #define __BE_ALGORITHM() { \ if (f >= 0) { \ y--; \ @@ -111,7 +175,7 @@ blendPixelPtr(ptr4 + (y) + (px), color, a); \ } -#define __WU_ALGORITHM() { \ +/*#define __WU_ALGORITHM() { \ oldT = T; \ T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ py += p; \ @@ -120,6 +184,16 @@ } \ a2 = (T >> 8); \ a1 = ~a2; \ +} */ + +// optimized Wu's algorithm +#define __WU_ALGORITHM() {\ + py += p; \ + oldT = T; \ + T = circleSqrt(rsq - (y * y)); \ + a2 = T; \ + a1 = ~T; \ + if (T < oldT) { x--; px -= p; } \ } @@ -138,30 +212,6 @@ VectorRenderer *createRenderer(int mode) { return 0; } } - -/** Fixed point SQUARE ROOT **/ -inline uint32 fp_sqroot(uint32 x) { - register uint32 root, remHI, remLO, testDIV, count; - - root = 0; - remHI = 0; - remLO = x; - count = 23; - - do { - remHI = (remHI << 2) | (remLO >> 30); - remLO <<= 2; - root <<= 1; - testDIV = (root << 1) + 1; - - if (remHI >= testDIV) { - remHI -= testDIV; - root++; - } - } while (count--); - - return root; -} template void VectorRendererSpec:: @@ -1512,7 +1562,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto x = r; y = 0; T = 0; px = p * x; py = 0; - while (x > y++) { + while (x > 1 + y++) { __WU_ALGORITHM(); colorFill(ptr_tl - x - py, ptr_tr + x - py, color); diff --git a/graphics/font.cpp b/graphics/font.cpp index 0b0405b4b4..3e817e3e6c 100644 --- a/graphics/font.cpp +++ b/graphics/font.cpp @@ -48,7 +48,29 @@ int NewFont::getCharWidth(byte chr) const { return desc.width[chr - desc.firstchar]; } -void NewFont::drawChar(Surface *dst, byte chr, int tx, int ty, uint32 color) const { + +template +void drawCharIntern(byte *ptr, uint pitch, const bitmap_t *src, int h, int minX, int maxX, const uint32 color) { + while (h-- > 0) { + const bitmap_t buffer = READ_UINT16(src); + src++; + + int x = minX; + uint mask = 0x8000 >> minX; + for (; x < maxX; x++, mask >>= 1) { + if ((buffer & mask) != 0) { + if (bytesPerPixel == 1) + ptr[x] = color; + else if (bytesPerPixel == 2) + ((uint16 *)ptr)[x] = color; + } + } + + ptr += pitch; + } +} + +void NewFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const uint32 color) const { assert(dst != 0); assert(desc.bits != 0 && desc.maxwidth <= 17); @@ -80,25 +102,14 @@ void NewFont::drawChar(Surface *dst, byte chr, int tx, int ty, uint32 color) con const bitmap_t *tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * desc.fbbh)); - for (int y = 0; y < bbh; y++, ptr += dst->pitch) { - const bitmap_t buffer = READ_UINT16(tmp); - tmp++; - bitmap_t mask = 0x8000; - if (ty + desc.ascent - bby - bbh + y < 0 || - ty + desc.ascent - bby - bbh + y >= dst->h) - continue; + int y = MIN(bbh, ty + desc.ascent - bby); + tmp += bbh - y; + y -= MAX(0, ty + desc.ascent - bby - dst->h); - for (int x = 0; x < bbw; x++, mask >>= 1) { - if (tx + bbx + x < 0 || tx + bbx + x >= dst->w) - continue; - if ((buffer & mask) != 0) { - if (dst->bytesPerPixel == 1) - ptr[x] = color; - else if (dst->bytesPerPixel == 2) - ((uint16 *)ptr)[x] = color; - } - } - } + if (dst->bytesPerPixel == 1) + drawCharIntern<1>(ptr, dst->pitch, tmp, y, MAX(0, -(tx + bbx)), MIN(bbw, dst->w - tx - bbx), color); + else if (dst->bytesPerPixel == 2) + drawCharIntern<2>(ptr, dst->pitch, tmp, y, MAX(0, -(tx + bbx)), MIN(bbw, dst->w - tx - bbx), color); } diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 097a38291a..3361a76602 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -106,7 +106,7 @@ NewGui::~NewGui() { delete _theme; } -bool NewGui::loadNewTheme(const Common::String &filename, ThemeEngine::GraphicsMode gfx) { +bool NewGui::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode gfx) { if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getGraphicsMode()) return true; @@ -124,8 +124,6 @@ bool NewGui::loadNewTheme(const Common::String &filename, ThemeEngine::GraphicsM } delete _theme; - _theme = 0; - _theme = new ThemeEngine(filename, gfx); if (!_theme) diff --git a/gui/newgui.h b/gui/newgui.h index 9dace522ab..0b3de01c83 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -78,7 +78,7 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(const Common::String &file, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); + bool loadNewTheme(Common::String file, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); Theme *theme() { return _theme; } ThemeEval *xmlEval() { return _theme->evaluator(); } -- cgit v1.2.3 From dcc2caf6d07592eb63085c32e39cab27d027cf36 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 7 Sep 2008 09:43:10 +0000 Subject: Misc performance fixes. svn-id: r34398 --- graphics/VectorRendererSpec.cpp | 29 +++++++---------------------- graphics/VectorRendererSpec.h | 33 +++++++++++++++------------------ 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 428ec7ee5e..7e1164b2de 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -75,9 +75,9 @@ const uint16 inv_sqrt_tbl[] = { inline uint32 fp_sqroot(uint32 x) { int bit; -#if defined(__arm__) - __asm__ ("clz %0, %1\nrsb %0, %0, #31\n" : "=r"(bit) : "r" (x)); -#elif defined(__i386__) +//#if defined(ARM9) +// __asm__ ("clz %0, %1\nrsb %0, %0, #31\n" : "=r"(bit) : "r" (x)); +#if defined(__i386__) __asm__("bsrl %1, %0" : "=r" (bit) : "r" (x)); #else unsigned int mask = 0x40000000; @@ -100,7 +100,10 @@ inline uint32 circleSqrt(int x) { } -/** HELPER MACROS for BESENHALM's circle drawing algorithm **/ +/* + HELPER MACROS for Bresenham's circle drawing algorithm + Note the proper spelling on this header. +*/ #define __BE_ALGORITHM() { \ if (f >= 0) { \ y--; \ @@ -175,17 +178,6 @@ inline uint32 circleSqrt(int x) { blendPixelPtr(ptr4 + (y) + (px), color, a); \ } -/*#define __WU_ALGORITHM() { \ - oldT = T; \ - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ - py += p; \ - if (T < oldT) { \ - x--; px -= p; \ - } \ - a2 = (T >> 8); \ - a1 = ~a2; \ -} */ - // optimized Wu's algorithm #define __WU_ALGORITHM() {\ py += p; \ @@ -400,13 +392,6 @@ applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { template inline void VectorRendererSpec:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - if (!ptr) return; - - if (alpha == 255) { - *ptr = color; - return; - } - register int idst = *ptr; register int isrc = color; diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index f9669bdb41..77336e329e 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -76,15 +76,15 @@ public: void setBevelColor(uint8 r, uint8 g, uint8 b) { _bevelColor = RGBToColor(r, g, b); } void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2); - virtual void copyFrame(OSystem *sys, const Common::Rect &r); - virtual void copyWholeFrame(OSystem *sys) { copyFrame(sys, Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); } + void copyFrame(OSystem *sys, const Common::Rect &r); + void copyWholeFrame(OSystem *sys) { copyFrame(sys, Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); } - virtual void fillSurface(); - virtual void blitSurface(const Graphics::Surface *source, const Common::Rect &r); - virtual void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r); - virtual void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r); + void fillSurface(); + void blitSurface(const Graphics::Surface *source, const Common::Rect &r); + void blitSubSurface(const Graphics::Surface *source, const Common::Rect &r); + void blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r); - virtual void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle); + void applyScreenShading(GUI::Theme::ShadingStyle shadingStyle); protected: @@ -96,7 +96,7 @@ protected: * @param y Vertical coordinate of the pixel. * @param color Color of the pixel */ - virtual inline void putPixel(int x, int y, PixelType color) { + inline void putPixel(int x, int y, PixelType color) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); *ptr = color; } @@ -110,11 +110,8 @@ protected: * @param color Color of the pixel * @param alpha Alpha intensity of the pixel (0-255) */ - virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { - if (alpha == 255) - putPixel(x, y, color); - else if (alpha > 0) - blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); + inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { + blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } /** @@ -129,7 +126,7 @@ protected: * @param color Color of the pixel * @param alpha Alpha intensity of the pixel (0-255) */ - virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); + inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); /** * PRIMITIVE DRAWING ALGORITHMS @@ -194,7 +191,7 @@ protected: * @param max Maximum amount of the progress. * @return Composite color of the gradient at the given "progress" amount. */ - virtual inline PixelType calcGradient(uint32 pos, uint32 max); + inline PixelType calcGradient(uint32 pos, uint32 max); /** * Fills several pixels in a row with a given color and the specifed alpha blending. @@ -206,7 +203,7 @@ protected: * @param color Color of the pixel * @param alpha Alpha intensity of the pixel (0-255) */ - virtual inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { + inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) { while (first != last) blendPixelPtr(first++, color, alpha); } @@ -226,9 +223,9 @@ protected: * @param last Pointer to the last pixel to fill. * @param color Color of the pixel */ - virtual inline void colorFill(PixelType *first, PixelType *last, PixelType color); + inline void colorFill(PixelType *first, PixelType *last, PixelType color); - virtual void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); + void areaConvolution(const Common::Rect &area, const int filter[3][3], int filterDiv, int offset); PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ -- cgit v1.2.3 From 2de0d7d42e100b56861c1f95ba8a6bab2cf9ff0d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 7 Sep 2008 21:45:18 +0000 Subject: Bugfix: Theme loading on platforms which don't support cursor palettes. svn-id: r34427 --- gui/ThemeEngine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 8da4d3d808..17623845b0 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -462,6 +462,8 @@ bool ThemeEngine::addDrawData(const Common::String &data, bool cached) { bool ThemeEngine::loadTheme(Common::String fileName) { unloadTheme(); + warning("Loading theme: %s.\n", fileName.c_str()); + if (fileName != "builtin") { if (fileName.hasSuffix(".zip")) ImageMan.addArchive(fileName); @@ -1004,7 +1006,7 @@ void ThemeEngine::setUpCursor() { bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette)) - return false; + return true; const Surface *cursor = _bitmaps[filename]; -- cgit v1.2.3 From 81715eae04f522af5a39645f97e5c88f10ccef67 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2008 18:43:24 +0000 Subject: Fixed bottleneck: Screen dimming. svn-id: r34482 --- graphics/VectorRendererSpec.cpp | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 7e1164b2de..b129bbfc79 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -371,15 +371,17 @@ applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); uint8 r, g, b; uint lum; + + uint32 shiftMask = (uint32)( + (1 << PixelFormat::kGreenShift) | + (1 << PixelFormat::kRedShift) | + (1 << PixelFormat::kBlueShift)); + + shiftMask = (~shiftMask) >> 1; if (shadingStyle == GUI::Theme::kShadingDim) { - while (pixels--) { - colorToRGB(*ptr, r, g, b); - r = r * _dimPercentValue >> 8; - g = g * _dimPercentValue >> 8; - b = b * _dimPercentValue >> 8; - *ptr++ = RGBToColor(r, g, b); - } + while (pixels--) + *ptr++ = (*ptr >> 1) & shiftMask; } else if (shadingStyle == GUI::Theme::kShadingLuminance) { while (pixels--) { colorToRGB(*ptr, r, g, b); @@ -424,24 +426,18 @@ calcGradient(uint32 pos, uint32 max) { template void VectorRendererSpec:: colorFill(PixelType *first, PixelType *last, PixelType color) { - if (first == last) { - *first = color; - return; - } - - register PixelType *ptr = first; register int count = (last - first); register int n = (count + 7) >> 3; switch (count % 8) { case 0: do { - *ptr++ = color; - case 7: *ptr++ = color; - case 6: *ptr++ = color; - case 5: *ptr++ = color; - case 4: *ptr++ = color; - case 3: *ptr++ = color; - case 2: *ptr++ = color; - case 1: *ptr++ = color; + *first++ = color; + case 7: *first++ = color; + case 6: *first++ = color; + case 5: *first++ = color; + case 4: *first++ = color; + case 3: *first++ = color; + case 2: *first++ = color; + case 1: *first++ = color; } while (--n > 0); } } -- cgit v1.2.3 From c7e07102b69a5fd66a89605c619e008060744bf4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 19 Sep 2008 17:15:20 +0000 Subject: Unrolled a loop. Misc fixes. svn-id: r34604 --- graphics/VectorRendererSpec.cpp | 23 +++++++++++++++++------ gui/ThemeEngine.cpp | 2 -- gui/newgui.cpp | 3 --- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index b129bbfc79..375dfca20a 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -372,16 +372,27 @@ applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { uint8 r, g, b; uint lum; - uint32 shiftMask = (uint32)( + const uint32 shiftMask = (uint32)~( (1 << PixelFormat::kGreenShift) | (1 << PixelFormat::kRedShift) | - (1 << PixelFormat::kBlueShift)); - - shiftMask = (~shiftMask) >> 1; + (1 << PixelFormat::kBlueShift)) >> 1; if (shadingStyle == GUI::Theme::kShadingDim) { - while (pixels--) - *ptr++ = (*ptr >> 1) & shiftMask; + + int n = (pixels + 7) >> 3; + switch (pixels % 8) { + case 0: do { + *ptr++ = (*ptr >> 1) & shiftMask; + case 7: *ptr++ = (*ptr >> 1) & shiftMask; + case 6: *ptr++ = (*ptr >> 1) & shiftMask; + case 5: *ptr++ = (*ptr >> 1) & shiftMask; + case 4: *ptr++ = (*ptr >> 1) & shiftMask; + case 3: *ptr++ = (*ptr >> 1) & shiftMask; + case 2: *ptr++ = (*ptr >> 1) & shiftMask; + case 1: *ptr++ = (*ptr >> 1) & shiftMask; + } while (--n > 0); + } + } else if (shadingStyle == GUI::Theme::kShadingLuminance) { while (pixels--) { colorToRGB(*ptr, r, g, b); diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 17623845b0..e75c2e295e 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -462,8 +462,6 @@ bool ThemeEngine::addDrawData(const Common::String &data, bool cached) { bool ThemeEngine::loadTheme(Common::String fileName) { unloadTheme(); - warning("Loading theme: %s.\n", fileName.c_str()); - if (fileName != "builtin") { if (fileName.hasSuffix(".zip")) ImageMan.addArchive(fileName); diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 3361a76602..72b7f2612c 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -92,9 +92,6 @@ NewGui::NewGui() : _redrawStatus(kRedrawDisabled), if (themefile.compareToIgnoreCase("default") == 0) themefile = "builtin"; -// if (themefile != "builtin" && !themefile.hasSuffix(".zip")) -// themefile += ".zip"; - ConfMan.registerDefault("gui_renderer", 2); ThemeEngine::GraphicsMode gfxMode = (ThemeEngine::GraphicsMode)ConfMan.getInt("gui_renderer"); -- cgit v1.2.3 From eb65bcd9538f8ec574a24ddb5b5cfb611bbc94f6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 20 Sep 2008 12:28:45 +0000 Subject: Fixed build. svn-id: r34607 --- graphics/module.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/graphics/module.mk b/graphics/module.mk index d21915803e..982711b608 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -17,6 +17,7 @@ MODULE_OBJS := \ scaler.o \ scaler/thumbnail_intern.o \ surface.o \ + thumbnail.o \ VectorRenderer.o \ VectorRendererSpec.o -- cgit v1.2.3 From 2c775d851b3d162b9f00dcb9c9f82d8faeaff74a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 20 Sep 2008 12:36:58 +0000 Subject: Added global ingame menu definitions to theme files. svn-id: r34608 --- engines/dialogs.cpp | 45 +++++++-------- gui/ThemeEngine.h | 2 + gui/themes/default.inc | 70 ++++++++++++++++++++++++ gui/themes/scummclassic.zip | Bin 42002 -> 43805 bytes gui/themes/scummclassic/classic_layout.stx | 36 ++++++++++++ gui/themes/scummclassic/classic_layout_320.stx | 36 ++++++++++++ gui/themes/scummodern.zip | Bin 125107 -> 144239 bytes gui/themes/scummodern/scummodern_gfx.stx | 2 + gui/themes/scummodern/scummodern_layout.stx | 42 +++++++++++++- gui/themes/scummodern/scummodern_layout_320.stx | 36 ++++++++++++ 10 files changed, 244 insertions(+), 25 deletions(-) diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 8d8888246b..b6d4a6d75e 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -73,38 +73,39 @@ enum { }; MainMenuDialog::MainMenuDialog(Engine *engine) - : GlobalDialog("globalmain"), _engine(engine) { + : GlobalDialog("GlobalMenu"), _engine(engine) { + _backgroundType = GUI::Theme::kDialogBackgroundSpecial; #ifndef DISABLE_FANCY_THEMES _logo = 0; - if (g_gui.xmlEval()->getVar("global_logo.visible") == 1 && g_gui.theme()->supportsImages()) { - _logo = new GUI::GraphicsWidget(this, "global_logo"); + if (g_gui.xmlEval()->getVar("Globals.ShowGlobalMenuLogo", 0) == 1 && g_gui.theme()->supportsImages()) { + _logo = new GUI::GraphicsWidget(this, "GlobalMenu.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(GUI::Theme::kImageLogoSmall)); } else { - new StaticTextWidget(this, "global_title", "ScummVM"); + new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); } #else - new StaticTextWidget(this, "global_title", "ScummVM"); + new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); #endif - new StaticTextWidget(this, "global_version", gScummVMVersionDate); + new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); - new GUI::ButtonWidget(this, "globalmain_resume", "Resume", kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", "Resume", kPlayCmd, 'P'); // new GUI::ButtonWidget(this, "globalmain_load", "Load", kLoadCmd, 'L'); // new GUI::ButtonWidget(this, "globalmain_save", "Save", kSaveCmd, 'S'); - new GUI::ButtonWidget(this, "globalmain_options", "Options", kOptionsCmd, 'O'); + new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O'); - new GUI::ButtonWidget(this, "globalmain_about", "About", kAboutCmd, 'A'); + new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A'); - _rtlButton = new GUI::ButtonWidget(this, "globalmain_rtl", "Return to Launcher", kRTLCmd, 'R'); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R'); // '0' corresponds to the kSupportsRTL MetaEngineFeature _rtlButton->setEnabled(_engine->hasFeature(0)); - new GUI::ButtonWidget(this, "globalmain_quit", "Quit", kQuitCmd, 'Q'); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", "Quit", kQuitCmd, 'Q'); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(); @@ -147,22 +148,22 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat void MainMenuDialog::reflowLayout() { #ifndef DISABLE_FANCY_THEMES - if (g_gui.xmlEval()->getVar("global_logo.visible") == 1 && g_gui.theme()->supportsImages()) { + if (g_gui.xmlEval()->getVar("Globals.ShowGlobalMenuLogo", 0) == 1 && g_gui.theme()->supportsImages()) { if (!_logo) - _logo = new GUI::GraphicsWidget(this, "global_logo"); + _logo = new GUI::GraphicsWidget(this, "GlobalMenu.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(GUI::Theme::kImageLogoSmall)); - GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("global_title"); + GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("GlobalMenu.Title"); if (title) { removeWidget(title); title->setNext(0); delete title; } } else { - GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("global_title"); + GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("GlobalMenu.Title"); if (!title) - new StaticTextWidget(this, "global_title", "ScummVM"); + new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); if (_logo) { removeWidget(_logo); @@ -210,30 +211,30 @@ enum { // "" as value for the domain, and in fact provide a somewhat better user // experience at the same time. ConfigDialog::ConfigDialog() - : GUI::OptionsDialog("", "scummconfig") { + : GUI::OptionsDialog("", "ScummConfig") { // // Sound controllers // - addVolumeControls(this, "scummconfig_"); + addVolumeControls(this, "ScummConfig."); // // Some misc options // // SCUMM has a talkspeed range of 0-9 - addSubtitleControls(this, "scummconfig_", 9); + addSubtitleControls(this, "ScummConfig.", 9); // // Add the buttons // - new GUI::ButtonWidget(this, "scummconfig_ok", "OK", GUI::OptionsDialog::kOKCmd, 'O'); - new GUI::ButtonWidget(this, "scummconfig_cancel", "Cancel", kCloseCmd, 'C'); + new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::OptionsDialog::kOKCmd, 'O'); + new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", kCloseCmd, 'C'); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "scummconfig_keys", "Keys", kKeysCmd, 'K'); + new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K'); // // Create the sub dialog(s) diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 2d99076fc3..8f8b06def4 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -503,6 +503,8 @@ public: const Graphics::Surface *getImageSurface(const kThemeImages n) const { if (n == kImageLogo) return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; + else if (n == kImageLogoSmall) + return _bitmaps.contains("logo_small.bmp") ? _bitmaps["logo_small.bmp"] : 0; return 0; } diff --git a/gui/themes/default.inc b/gui/themes/default.inc index c0ea4a9228..f2ef86d241 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -314,6 +314,7 @@ " " " " " " +" " " " " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " " " " " " +" " " " " " " " " " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " " " " " " + @@ -448,6 +449,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip index 93977a3cc7..70141bfce9 100644 Binary files a/gui/themes/scummodern.zip and b/gui/themes/scummodern.zip differ diff --git a/gui/themes/scummodern/scummodern_gfx.stx b/gui/themes/scummodern/scummodern_gfx.stx index c9f4c35985..b8eff77aa1 100644 --- a/gui/themes/scummodern/scummodern_gfx.stx +++ b/gui/themes/scummodern/scummodern_gfx.stx @@ -56,6 +56,7 @@ + @@ -117,6 +118,7 @@ gradient_start = '208, 112, 8' gradient_end = '232, 192, 16' shadow = '3' + gradient_factor = '3' /> diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx index c1029088af..03d920ac05 100644 --- a/gui/themes/scummodern/scummodern_layout.stx +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -43,6 +43,7 @@ + @@ -108,7 +109,7 @@ - + @@ -118,14 +119,14 @@ - + - + @@ -460,6 +461,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 0d4ce96799da99a3f0c7c25ef14aac8951b93239 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 20 Sep 2008 13:04:50 +0000 Subject: Fixed warnings. svn-id: r34609 --- graphics/VectorRendererSpec.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 375dfca20a..f8c2d14521 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -382,14 +382,14 @@ applyScreenShading(GUI::Theme::ShadingStyle shadingStyle) { int n = (pixels + 7) >> 3; switch (pixels % 8) { case 0: do { - *ptr++ = (*ptr >> 1) & shiftMask; - case 7: *ptr++ = (*ptr >> 1) & shiftMask; - case 6: *ptr++ = (*ptr >> 1) & shiftMask; - case 5: *ptr++ = (*ptr >> 1) & shiftMask; - case 4: *ptr++ = (*ptr >> 1) & shiftMask; - case 3: *ptr++ = (*ptr >> 1) & shiftMask; - case 2: *ptr++ = (*ptr >> 1) & shiftMask; - case 1: *ptr++ = (*ptr >> 1) & shiftMask; + *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 7: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 6: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 5: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 4: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 3: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 2: *ptr = (*ptr >> 1) & shiftMask; ++ptr; + case 1: *ptr = (*ptr >> 1) & shiftMask; ++ptr; } while (--n > 0); } -- cgit v1.2.3 From 46168618be0152ebfcb68d2a0a46f98a676e204a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 20 Sep 2008 13:52:12 +0000 Subject: - Reverted circle drawing algorithm. - Fixed Launcher savegame load menu. svn-id: r34610 --- graphics/VectorRendererSpec.cpp | 94 ++++++++++++----------------------------- gui/launcher.cpp | 14 +++--- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index f8c2d14521..5592b97db7 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -36,70 +36,30 @@ #define VECTOR_RENDERER_FAST_TRIANGLES -const uint16 inv_sqrt_tbl[] = { - 0x0000, 0x0100, 0x016A, 0x01BB, 0x0200, 0x023C, 0x0273, 0x02A5, - 0x02D4, 0x0300, 0x0329, 0x0351, 0x0376, 0x039B, 0x03BD, 0x03DF, - 0x0400, 0x041F, 0x043E, 0x045B, 0x0478, 0x0495, 0x04B0, 0x04CB, - 0x04E6, 0x0500, 0x0519, 0x0532, 0x054A, 0x0562, 0x057A, 0x0591, - 0x05A8, 0x05BE, 0x05D4, 0x05EA, 0x0600, 0x0615, 0x062A, 0x063E, - 0x0653, 0x0667, 0x067B, 0x068E, 0x06A2, 0x06B5, 0x06C8, 0x06DB, - 0x06ED, 0x0700, 0x0712, 0x0724, 0x0736, 0x0747, 0x0759, 0x076A, - 0x077B, 0x078C, 0x079D, 0x07AE, 0x07BE, 0x07CF, 0x07DF, 0x07EF, - 0x0800, 0x080F, 0x081F, 0x082F, 0x083F, 0x084E, 0x085D, 0x086D, - 0x087C, 0x088B, 0x089A, 0x08A9, 0x08B7, 0x08C6, 0x08D4, 0x08E3, - 0x08F1, 0x0900, 0x090E, 0x091C, 0x092A, 0x0938, 0x0946, 0x0953, - 0x0961, 0x096F, 0x097C, 0x098A, 0x0997, 0x09A4, 0x09B2, 0x09BF, - 0x09CC, 0x09D9, 0x09E6, 0x09F3, 0x0A00, 0x0A0C, 0x0A19, 0x0A26, - 0x0A32, 0x0A3F, 0x0A4B, 0x0A58, 0x0A64, 0x0A70, 0x0A7C, 0x0A89, - 0x0A95, 0x0AA1, 0x0AAD, 0x0AB9, 0x0AC5, 0x0AD1, 0x0ADC, 0x0AE8, - 0x0AF4, 0x0B00, 0x0B0B, 0x0B17, 0x0B22, 0x0B2E, 0x0B39, 0x0B44, - 0x0B50, 0x0B5B, 0x0B66, 0x0B72, 0x0B7D, 0x0B88, 0x0B93, 0x0B9E, - 0x0BA9, 0x0BB4, 0x0BBF, 0x0BCA, 0x0BD5, 0x0BDF, 0x0BEA, 0x0BF5, - 0x0C00, 0x0C0A, 0x0C15, 0x0C1F, 0x0C2A, 0x0C34, 0x0C3F, 0x0C49, - 0x0C54, 0x0C5E, 0x0C68, 0x0C73, 0x0C7D, 0x0C87, 0x0C91, 0x0C9C, - 0x0CA6, 0x0CB0, 0x0CBA, 0x0CC4, 0x0CCE, 0x0CD8, 0x0CE2, 0x0CEC, - 0x0CF6, 0x0D00, 0x0D09, 0x0D13, 0x0D1D, 0x0D27, 0x0D30, 0x0D3A, - 0x0D44, 0x0D4D, 0x0D57, 0x0D61, 0x0D6A, 0x0D74, 0x0D7D, 0x0D87, - 0x0D90, 0x0D99, 0x0DA3, 0x0DAC, 0x0DB6, 0x0DBF, 0x0DC8, 0x0DD1, - 0x0DDB, 0x0DE4, 0x0DED, 0x0DF6, 0x0E00, 0x0E09, 0x0E12, 0x0E1B, - 0x0E24, 0x0E2D, 0x0E36, 0x0E3F, 0x0E48, 0x0E51, 0x0E5A, 0x0E63, - 0x0E6C, 0x0E74, 0x0E7D, 0x0E86, 0x0E8F, 0x0E98, 0x0EA0, 0x0EA9, - 0x0EB2, 0x0EBB, 0x0EC3, 0x0ECC, 0x0ED5, 0x0EDD, 0x0EE6, 0x0EEE, - 0x0EF7, 0x0F00, 0x0F08, 0x0F11, 0x0F19, 0x0F21, 0x0F2A, 0x0F32, - 0x0F3B, 0x0F43, 0x0F4C, 0x0F54, 0x0F5C, 0x0F65, 0x0F6D, 0x0F75, - 0x0F7D, 0x0F86, 0x0F8E, 0x0F96, 0x0F9E, 0x0FA7, 0x0FAF, 0x0FB7, - 0x0FBF, 0x0FC7, 0x0FCF, 0x0FD7, 0x0FDF, 0x0FE7, 0x0FEF, 0x0FF7, - 0x1000 -}; - +/** Fixed point SQUARE ROOT **/ inline uint32 fp_sqroot(uint32 x) { - int bit; - -//#if defined(ARM9) -// __asm__ ("clz %0, %1\nrsb %0, %0, #31\n" : "=r"(bit) : "r" (x)); -#if defined(__i386__) - __asm__("bsrl %1, %0" : "=r" (bit) : "r" (x)); -#else - unsigned int mask = 0x40000000; - bit = 30; - while (bit >= 0) { - if (x & mask) - break; - - mask = (mask >> 1 | mask >> 2); - bit -= 2; - } -#endif - - bit -= 6 + (bit & 1); - return inv_sqrt_tbl[x >> bit] << (bit >> 1); -} + register uint32 root, remHI, remLO, testDIV, count; + + root = 0; + remHI = 0; + remLO = x; + count = 23; + + do { + remHI = (remHI << 2) | (remLO >> 30); + remLO <<= 2; + root <<= 1; + testDIV = (root << 1) + 1; + + if (remHI >= testDIV) { + remHI -= testDIV; + root++; + } + } while (count--); -inline uint32 circleSqrt(int x) { - return (x > 255 ? fp_sqroot(x) : inv_sqrt_tbl[x]) ^ 0xFF; + return root; } - /* HELPER MACROS for Bresenham's circle drawing algorithm Note the proper spelling on this header. @@ -179,13 +139,15 @@ inline uint32 circleSqrt(int x) { } // optimized Wu's algorithm -#define __WU_ALGORITHM() {\ - py += p; \ +#define __WU_ALGORITHM() { \ oldT = T; \ - T = circleSqrt(rsq - (y * y)); \ - a2 = T; \ - a1 = ~T; \ - if (T < oldT) { x--; px -= p; } \ + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ + py += p; \ + if (T < oldT) { \ + x--; px -= p; \ + } \ + a2 = (T >> 8); \ + a1 = ~a2; \ } diff --git a/gui/launcher.cpp b/gui/launcher.cpp index b79891ef76..978c224afd 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -517,6 +517,7 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel) _delSupport = _metaInfoSupport = _thumbnailSupport = _saveDateSupport = _playTimeSupport = false; // _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR; + _backgroundType = Theme::kDialogBackgroundDefault; new StaticTextWidget(this, "ScummSaveLoad.Title", title); @@ -622,15 +623,12 @@ void SaveLoadChooser::reflowLayout() { int thumbY = y + kLineHeight; int textLines = 0; - if (_saveDateSupport) - textLines += 2; - if (_playTimeSupport) - textLines += 1; - - if (textLines) - ++textLines; + if (!_saveDateSupport) + textLines++; + if (!_playTimeSupport) + textLines++; - _container->resize(x, y, w, h + textLines * kLineHeight); + _container->resize(x, y, w, h - (kLineHeight * textLines)); _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH); int height = thumbY + thumbH + kLineHeight; -- cgit v1.2.3 From 4f511db2c1bb28a069b2dddf349759642366a8b8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 20 Sep 2008 14:06:18 +0000 Subject: Bugfix: Graphical glitch when drawing beveled squares (classic theme). svn-id: r34611 --- graphics/VectorRendererSpec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 5592b97db7..9884fcfd2d 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -933,7 +933,7 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P } i = h - bevel; - j = bevel; + j = bevel - 1; ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y); while (i--) { colorFill(ptr_left + j, ptr_left + bevel, bottom_color); -- cgit v1.2.3 From 1b22a69812672ca6507ef36cd3ed473ddcebc597 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 20 Sep 2008 14:13:09 +0000 Subject: Added missing BMP resource. svn-id: r34612 --- gui/themes/scummodern/logo_small.bmp | Bin 0 -> 17174 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gui/themes/scummodern/logo_small.bmp diff --git a/gui/themes/scummodern/logo_small.bmp b/gui/themes/scummodern/logo_small.bmp new file mode 100644 index 0000000000..eaa998a165 Binary files /dev/null and b/gui/themes/scummodern/logo_small.bmp differ -- cgit v1.2.3 From f267d42080357b4ab697e04f325fe628a1f62c1f Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 20 Sep 2008 16:07:00 +0000 Subject: Fixed text alignment in Global ingame menu. svn-id: r34616 --- engines/dialogs.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index b6d4a6d75e..3ac6abaa5c 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -83,13 +83,16 @@ MainMenuDialog::MainMenuDialog(Engine *engine) _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(GUI::Theme::kImageLogoSmall)); } else { - new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + StaticTextWidget *title = new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + title->setAlign(GUI::kTextAlignCenter); } #else - new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + StaticTextWidget *title = new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + title->setAlign(GUI::kTextAlignCenter); #endif - new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); + StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); + version->setAlign(GUI::kTextAlignCenter); new GUI::ButtonWidget(this, "GlobalMenu.Resume", "Resume", kPlayCmd, 'P'); @@ -162,8 +165,10 @@ void MainMenuDialog::reflowLayout() { } } else { GUI::StaticTextWidget *title = (StaticTextWidget *)findWidget("GlobalMenu.Title"); - if (!title) - new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + if (!title) { + title = new StaticTextWidget(this, "GlobalMenu.Title", "ScummVM"); + title->setAlign(GUI::kTextAlignCenter); + } if (_logo) { removeWidget(_logo); -- cgit v1.2.3 From c8f42a39737dbd50cbdc4cad7c6a6c89ca0efe69 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 29 Sep 2008 10:27:16 +0000 Subject: Reduced memory usage by closing theme files after parsing. Could make things a tad slower. svn-id: r34677 --- common/xmlparser.cpp | 5 ++--- common/xmlparser.h | 10 ++++++++-- gui/ThemeEngine.cpp | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index b93a5205be..6c1aa7d0e4 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -43,7 +43,7 @@ bool XMLParser::parserError(const char *errorString, ...) { int lineStart = 0; if (_fileName == "Memory Stream") { - lineStart = MAX(0, _pos - 35); + lineStart = MAX(0, original_pos - 35); lineCount = 0; } else { do { @@ -51,7 +51,7 @@ bool XMLParser::parserError(const char *errorString, ...) { lineCount++; if (lineStart == 0) - lineStart = MAX(pos + 1, _pos - 60); + lineStart = MAX(pos + 1, original_pos - 60); } _stream->seek(-1, SEEK_CUR); @@ -210,7 +210,6 @@ bool XMLParser::parse() { bool selfClosure = false; _state = kParserNeedKey; - _pos = 0; _activeKey.clear(); _char = _stream->readByte(); diff --git a/common/xmlparser.h b/common/xmlparser.h index 7edabf62f3..967b73535b 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -222,6 +222,13 @@ public: _fileName = "Compressed File Stream"; return true; } + + void close() { + if (_stream) { + delete _stream; + _stream = 0; + } + } /** * The actual parsing function. @@ -361,7 +368,7 @@ protected: break; if (_char == 0) - parserError("Comment has no closure."); + return parserError("Comment has no closure."); } _char = _stream->readByte(); return true; @@ -449,7 +456,6 @@ protected: Common::List _layoutList; private: - int _pos; /** Current position on the XML buffer. */ char _char; SeekableReadStream *_stream; Common::String _fileName; diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index c04ca52834..c33251b546 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -501,6 +501,7 @@ bool ThemeEngine::loadDefaultXML() { // file inside the themes directory. // Use the Python script "makedeftheme.py" to convert a normal XML theme // into the "default.inc" file, which is ready to be included in the code. + bool result; #ifdef GUI_ENABLE_BUILTIN_THEME const char *defaultXML = @@ -513,7 +514,10 @@ bool ThemeEngine::loadDefaultXML() { _themeName = "ScummVM Classic Theme (Builtin Version)"; _themeFileName = "builtin"; - return parser()->parse(); + result = parser()->parse(); + parser()->close(); + + return result; #else warning("The built-in theme is not enabled in the current build. Please load an external theme"); return false; @@ -527,6 +531,7 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) { char fileNameBuffer[32]; Common::String stxHeader; int parseCount = 0; + bool failed = false; #ifdef USE_ZLIB unzFile zipFile = unzOpen((themeName).c_str()); @@ -550,19 +555,25 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) { if (!themeConfigParseHeader(stxHeader.c_str(), _themeName)) { warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); - return false; + failed = true; } delete stream; - } else { + } else if (!failed) { parseCount++; - if (parser()->loadStream(stream) == false || parser()->parse() == false) { + if (parser()->loadStream(stream) == false) { warning("Failed to load stream for zipped file '%s'", fileNameBuffer); - unzClose(zipFile); - return false; + failed = true; + } + + if (parser()->parse() == false) { + warning("Theme parsing failed on zipped file '%s'.", fileNameBuffer); + failed = true; } + + parser()->close(); } } @@ -581,13 +592,20 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) { return false; for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { - if (i->getName().hasSuffix(".stx")) { + if (!failed && i->getName().hasSuffix(".stx")) { parseCount++; - if (parser()->loadFile(*i) == false || parser()->parse() == false) { + if (parser()->loadFile(*i) == false) { + warning("Failed to load STX file '%s'", i->getName().c_str()); + failed = true; + } + + if (parser()->parse() == false) { warning("Failed to parse STX file '%s'", i->getName().c_str()); - return false; + failed = true; } + + parser()->close(); } else if (i->getName() == "THEMERC") { Common::File f; f.open(*i); @@ -595,7 +613,7 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) { if (!themeConfigParseHeader(stxHeader.c_str(), _themeName)) { warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); - return false; + failed = true; } } } @@ -608,7 +626,7 @@ bool ThemeEngine::loadThemeXML(Common::String themeName) { #endif - return (parseCount > 0 && _themeName.empty() == false); + return (parseCount > 0 && _themeName.empty() == false && failed == false); } -- cgit v1.2.3 From b15a6a9a152ce9e056c72f62d8299c982884f15b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 29 Sep 2008 21:44:07 +0000 Subject: Removed unnecessary unzOpenFile() calls in getAllNames() svn-id: r34690 --- common/unzip.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/common/unzip.cpp b/common/unzip.cpp index 27001519a1..bdba2a544a 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -1399,17 +1399,12 @@ int ZipArchive::getAllNames(Common::StringList &list) { if (unzGoToFirstFile(_zipFile) != UNZ_OK) return 0; - char fileNameBuffer[UNZ_MAXFILENAMEINZIP+1]; + char fileNameBuffer[UNZ_MAXFILENAMEINZIP + 1]; list.clear(); do { - unzOpenCurrentFile(_zipFile); - unzGetCurrentFileInfo(_zipFile, 0, fileNameBuffer, UNZ_MAXFILENAMEINZIP+1, 0, 0, 0, 0); - + unzGetCurrentFileInfo(_zipFile, 0, fileNameBuffer, UNZ_MAXFILENAMEINZIP + 1, 0, 0, 0, 0); list.push_back(Common::String(fileNameBuffer)); - - unzCloseCurrentFile(_zipFile); - } while (unzGoToNextFile(_zipFile) == UNZ_OK); return list.size(); -- cgit v1.2.3 From e290a3b6f3cf2fd1b686230126a8a27451cabdff Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 30 Sep 2008 11:55:32 +0000 Subject: Ported ZipArchive::getAllNames() fix from trunk. svn-id: r34699 --- common/unzip.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/common/unzip.cpp b/common/unzip.cpp index bdba2a544a..24744203da 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -1395,19 +1395,20 @@ bool ZipArchive::hasFile(const Common::String &name) { int ZipArchive::getAllNames(Common::StringList &list) { if (!_zipFile) return 0; - + if (unzGoToFirstFile(_zipFile) != UNZ_OK) return 0; char fileNameBuffer[UNZ_MAXFILENAMEINZIP + 1]; - list.clear(); - + int fileCount = 0; + do { unzGetCurrentFileInfo(_zipFile, 0, fileNameBuffer, UNZ_MAXFILENAMEINZIP + 1, 0, 0, 0, 0); list.push_back(Common::String(fileNameBuffer)); + fileCount++; } while (unzGoToNextFile(_zipFile) == UNZ_OK); - - return list.size(); + + return fileCount; } /* -- cgit v1.2.3 From 1380e4f7e70e712ad7984c5b5e8b070ab954987c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 30 Sep 2008 17:21:55 +0000 Subject: - Removed unneeded calls to addDefaultDir() when loading themes. - Removed unneeded depth-browsing on the theme browser. svn-id: r34714 --- gui/theme.cpp | 10 +++++++--- gui/themebrowser.cpp | 12 +++++------- gui/themebrowser.h | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/gui/theme.cpp b/gui/theme.cpp index 8c27d27417..cf77441267 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -134,6 +134,8 @@ bool Theme::themeConfigUseable(const Common::FilesystemNode &node, Common::Strin Common::String stxHeader; bool foundHeader = false; +// Not needed atm, using FSNodes. +/* if (ConfMan.hasKey("themepath")) Common::File::addDefaultDirectory(ConfMan.get("themepath")); @@ -143,10 +145,11 @@ bool Theme::themeConfigUseable(const Common::FilesystemNode &node, Common::Strin if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); +*/ + + if (node.getName().hasSuffix(".zip")) { - if (node.getName().hasSuffix(".zip")) { #ifdef USE_ZLIB - Common::ZipArchive zipArchive(node.getPath().c_str()); if (zipArchive.hasFile("THEMERC")) { Common::FilePtr stream(zipArchive.openFile("THEMERC")); @@ -157,7 +160,8 @@ bool Theme::themeConfigUseable(const Common::FilesystemNode &node, Common::Strin } #else return false; -#endif +#endif + } else if (node.isDirectory()) { Common::FilesystemNode headerfile = node.getChild("THEMERC"); if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory()) diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index c935f04143..5d8c1e3512 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -89,7 +89,7 @@ void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) void ThemeBrowser::updateListing() { _themes.clear(); - // classic is always build in + // classic is always built-in Entry th; th.name = "ScummVM Classic Theme (Builtin Version)"; th.file = "builtin"; @@ -100,7 +100,7 @@ void ThemeBrowser::updateListing() { // files in other places are ignored in this dialog // TODO: let the user browse the complete FS too/only the FS? if (ConfMan.hasKey("themepath")) - addDir(_themes, ConfMan.get("themepath"), 0); + addDir(_themes, ConfMan.get("themepath")); #ifdef DATA_PATH addDir(_themes, DATA_PATH); @@ -112,7 +112,7 @@ void ThemeBrowser::updateListing() { char buf[256]; if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) { Common::String resourcePath = buf; - addDir(_themes, resourcePath, 0); + addDir(_themes, resourcePath); } CFRelease(resourceUrl); } @@ -121,7 +121,7 @@ void ThemeBrowser::updateListing() { if (ConfMan.hasKey("extrapath")) addDir(_themes, ConfMan.get("extrapath")); - addDir(_themes, ".", 0); + addDir(_themes, "."); // Populate the ListWidget Common::StringList list; @@ -136,9 +136,7 @@ void ThemeBrowser::updateListing() { draw(); } -void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { - if (level < 0) - return; +void ThemeBrowser::addDir(ThList &list, const Common::String &dir) { Common::FilesystemNode node(dir); diff --git a/gui/themebrowser.h b/gui/themebrowser.h index c3a46aa3b0..e47c3aac37 100644 --- a/gui/themebrowser.h +++ b/gui/themebrowser.h @@ -56,7 +56,7 @@ private: void updateListing(); - void addDir(ThList &list, const Common::String &dir, int level = 4); + void addDir(ThList &list, const Common::String &dir); bool isTheme(const Common::FilesystemNode &node, Entry &out); }; -- cgit v1.2.3 From e32fc0ccca2570fc560969507351cf99a304ebf4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 5 Oct 2008 10:19:09 +0000 Subject: Added a fixed memory pool for XML Node allocation, as suggested by Max. svn-id: r34747 --- common/xmlparser.cpp | 6 +++--- common/xmlparser.h | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 6c1aa7d0e4..44274f7c8d 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -188,7 +188,7 @@ bool XMLParser::closeKey() { if (ignore == false) result = closedKeyCallback(_activeKey.top()); - delete _activeKey.pop(); + freeNode(_activeKey.pop()); return result; } @@ -202,7 +202,7 @@ bool XMLParser::parse() { buildLayout(); while (!_activeKey.empty()) - delete _activeKey.pop(); + freeNode(_activeKey.pop()); cleanup(); @@ -253,7 +253,7 @@ bool XMLParser::parse() { break; } } else { - ParserNode *node = new ParserNode; + ParserNode *node = allocNode(); //new ParserNode; node->name = _token; node->ignore = false; node->depth = _activeKey.size(); diff --git a/common/xmlparser.h b/common/xmlparser.h index 4b76278d47..ad9ad799f0 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -47,6 +47,8 @@ namespace Common { External documentation available at: http://www.smartlikearoboc.com/scummvm_doc/xmlparser_doc.html */ + +#define MAX_XML_DEPTH 8 #define XML_KEY(keyName) {\ lay = new CustomXMLKeyLayout;\ @@ -112,7 +114,7 @@ public: virtual ~XMLParser() { while (!_activeKey.empty()) - delete _activeKey.pop(); + freeNode(_activeKey.pop()); delete _XMLkeys; delete _stream; @@ -166,6 +168,18 @@ public: int depth; XMLKeyLayout *layout; }; + + FixedSizeMemoryPool _nodePool; + + ParserNode *allocNode() { + void* mem = _nodePool.malloc(); + return new (mem) ParserNode; + } + + void freeNode(ParserNode *node) { + node->~ParserNode(); + _nodePool.free(node); + } /** * Loads a file into the parser. -- cgit v1.2.3