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
This commit is contained in:
Vicent Marti 2008-08-09 18:34:16 +00:00
parent ea69217a13
commit 103a4f6681
12 changed files with 250 additions and 57 deletions

View File

@ -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.

View File

@ -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<PixelFormat>(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;
};
/**

View File

@ -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") {

View File

@ -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);

View File

@ -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<Graphics::DrawStep>::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<BitmapQueue>::const_iterator q = _bitmapQueue.begin(); q != _bitmapQueue.end(); ++q)
drawBitmap(*q);
_bitmapQueue.clear();
}
if (!_textQueue.empty()) {
for (Common::List<DrawQueueText>::const_iterator q = _textQueue.begin(); q != _textQueue.end(); ++q)
drawDDText(*q);

View File

@ -88,6 +88,7 @@ class ThemeRenderer : public Theme {
protected:
typedef Common::String String;
typedef GUI::Dialog Dialog;
typedef Common::HashMap<Common::String, Graphics::Surface*> 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<Common::Rect> _dirtyScreen;
@ -657,6 +702,8 @@ protected:
/** Queue with all the text drawing that must be done to the screen */
Common::List<DrawQueueText> _textQueue;
Common::List<BitmapQueue> _bitmapQueue;
bool _initOk; /** Class and renderer properly initialized */
bool _themeOk; /** Theme data successfully loaded. */

View File

@ -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);

View File

@ -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";
style = "builtin";
//DEBUG:
style = "scummodern";
Common::String styleType;
Common::ConfigFile cfg;
if (loadNewTheme(style)) {
loadClassicTheme = false;
} else {
loadClassicTheme = true;
warning("falling back to classic style");
}
#endif
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())

View File

@ -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;

View File

@ -28,6 +28,10 @@
"rgb = '63, 60, 17' "
"/> "
"</palette> "
"<bitmaps> "
"<bitmap filename = 'logo.bmp'/> "
"<bitmap filename = 'cursor.bmp'/> "
"</bitmaps> "
"<fonts> "
"<font id = 'text_default' "
"file = 'default' "

View File

@ -56,6 +56,11 @@
rgb = '63, 60, 17'
/>
</palette>
<bitmaps>
<bitmap filename = 'logo.bmp'/>
<bitmap filename = 'cursor.bmp'/>
</bitmaps>
<fonts>
<font id = 'text_default'

BIN
gui/themes/scummodern.zip Normal file

Binary file not shown.