2008-05-25 11:20:28 +00:00
|
|
|
/* 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"
|
2008-06-25 22:30:28 +00:00
|
|
|
#include "common/config-manager.h"
|
2008-11-10 12:45:09 +00:00
|
|
|
#include "common/file.h"
|
2008-08-15 19:10:37 +00:00
|
|
|
#include "common/fs.h"
|
- Merged 75 revisions from trunk.
- Fixed new conflicts.
- Changed Theme loading to use the new ZipArchive class.
- Implemented ZipArchive::getAllNames()
Original log message from SVNMerge.py
================================
Merged revisions 34605,34613-34615,34617,34619-34624,34627-34628,34630-34639,34642-34649,34656-34661,34663-34664,34671-34672,34674-34676,34678-34685 via svnmerge from
https://tanoku@scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
........
r34605 | Tanoku | 2008-09-20 12:32:59 +0200 (Sat, 20 Sep 2008) | 1 line
Fixed "empty control statement" warning in FSDirectory::matchPattern().
........
r34613 | lordhoto | 2008-09-20 16:53:31 +0200 (Sat, 20 Sep 2008) | 2 lines
Updated theme file version, to reflect latest addition of new required entries/files.
........
r34614 | wjpalenstijn | 2008-09-20 17:03:37 +0200 (Sat, 20 Sep 2008) | 1 line
fix drawing order in saveload choosers (draw container before contents)
........
r34615 | fingolfin | 2008-09-20 17:53:17 +0200 (Sat, 20 Sep 2008) | 1 line
Little readability tweak
........
r34617 | fingolfin | 2008-09-20 18:10:29 +0200 (Sat, 20 Sep 2008) | 1 line
Fix for bug #2120602: 5ALL: Starting the launcher with -f triggers assertion
........
r34619 | eriktorbjorn | 2008-09-20 18:21:27 +0200 (Sat, 20 Sep 2008) | 4 lines
I think this is the correct fix for bug #2081347 ("MM: Charset out of
bounds!"). If I understand correctly, version <= 2 games only have one (hard-
coded) font, so when that's initialised we can set _curId to 0.
........
r34620 | marcus_c | 2008-09-20 18:38:50 +0200 (Sat, 20 Sep 2008) | 1 line
game.h is now in engines, not base.
........
r34621 | marcus_c | 2008-09-20 18:47:31 +0200 (Sat, 20 Sep 2008) | 5 lines
In the CD filesystem, nothing can be opened for writing, so just
short-circuit any call to openForWriting(). Also, directories and
non-existing files can't be opened for reading either, so just
return 0 for those.
........
r34622 | sev | 2008-09-21 12:23:22 +0200 (Sun, 21 Sep 2008) | 2 lines
Patch #2054467: CRUISE: 64bits fixes
........
r34623 | sev | 2008-09-21 13:17:22 +0200 (Sun, 21 Sep 2008) | 2 lines
Add recent patch contributors. Reflect current ScummVM team in the credits
........
r34624 | sev | 2008-09-21 13:18:16 +0200 (Sun, 21 Sep 2008) | 2 lines
Reflect current team
........
r34627 | lordhoto | 2008-09-22 19:33:30 +0200 (Mon, 22 Sep 2008) | 1 line
Fixed full screen toggling via alt+enter.
........
r34628 | fingolfin | 2008-09-22 22:55:27 +0200 (Mon, 22 Sep 2008) | 1 line
Fix comments for random() funcs (thanks to salty-horse for pointing this out)
........
r34630 | fingolfin | 2008-09-23 11:39:37 +0200 (Tue, 23 Sep 2008) | 1 line
Moved ZipArchive implementation into unzip.cpp, added new ZipArchive::isOpen method
........
r34631 | fingolfin | 2008-09-23 11:42:38 +0200 (Tue, 23 Sep 2008) | 1 line
ImageManager: renamed remArchive() to removeArchive(); switched to using a SearchSet + ZipArchive to access ZIP files (code is much simpler now yet more flexible, yay)
........
r34632 | fingolfin | 2008-09-23 11:50:03 +0200 (Tue, 23 Sep 2008) | 1 line
Moved ZipArchive to namespace Common; moved unzip internals from unzip.h to unzip.cpp (to be cleaned up)
........
r34633 | fingolfin | 2008-09-23 12:08:45 +0200 (Tue, 23 Sep 2008) | 1 line
cleanup
........
r34634 | fingolfin | 2008-09-23 12:10:29 +0200 (Tue, 23 Sep 2008) | 1 line
Perform error checking when reading from a ZIP file
........
r34635 | fingolfin | 2008-09-23 13:43:57 +0200 (Tue, 23 Sep 2008) | 1 line
Fix for bug #1917981: Game crash when finishing Indy3 demo. At the same time, added a new paranoia check
........
r34636 | Kirben | 2008-09-23 14:34:02 +0200 (Tue, 23 Sep 2008) | 1 line
Add another French Windows version of Putt-Putt Enters the Race.
........
r34637 | lordhoto | 2008-09-23 18:40:41 +0200 (Tue, 23 Sep 2008) | 2 lines
Fix for bug #2120780 "GUI: gui-theme command-line option ignored", '-f' and '-g' command line switch behavior.
........
r34638 | john_doe | 2008-09-24 01:16:47 +0200 (Wed, 24 Sep 2008) | 1 line
Improved updateScreenAndWait; the mouse cursor is less jerky now in some scenes in Manhole:N&E
........
r34639 | thebluegr | 2008-09-24 09:26:45 +0200 (Wed, 24 Sep 2008) | 1 line
Readded missing special case for the storm animation in ITE. Fixes bug #2125675 - "ITE: Game locks up in storm clouds scene"
........
r34642 | fingolfin | 2008-09-24 22:29:29 +0200 (Wed, 24 Sep 2008) | 1 line
Changed Common::String to use a MemoryPool for its refcounts
........
r34643 | fingolfin | 2008-09-24 22:31:14 +0200 (Wed, 24 Sep 2008) | 1 line
cleanup
........
r34644 | fingolfin | 2008-09-24 22:35:31 +0200 (Wed, 24 Sep 2008) | 1 line
Changed builtin Common::String capacity to 24 (on 32 bit systems), to make sizeof(String) 32; reduces overall memory req by 200k on my system; overall # of mallocs after this + the refcount memory pool change is almost unchanged
........
r34645 | sev | 2008-09-25 00:44:01 +0200 (Thu, 25 Sep 2008) | 2 lines
Fix bugs #1981081: "ITE: No blinking disk icon" and #1971729: "IHNM: No Animation of Disk Icon"
........
r34646 | fingolfin | 2008-09-25 10:06:18 +0200 (Thu, 25 Sep 2008) | 1 line
SCUMM: Added a new ActorHE class, as well as a virtual Actor::prepareDrawActorCostume() method
........
r34647 | fingolfin | 2008-09-25 10:19:51 +0200 (Thu, 25 Sep 2008) | 1 line
SCUMM: Moved Actor::drawActorToBackBuf to class ActorHE
........
r34648 | fingolfin | 2008-09-25 12:11:06 +0200 (Thu, 25 Sep 2008) | 1 line
SCUMM: Moved more stuf from class Actor to ActorHE
........
r34649 | fingolfin | 2008-09-25 12:14:50 +0200 (Thu, 25 Sep 2008) | 1 line
cleanup
........
r34656 | eriktorbjorn | 2008-09-27 19:25:40 +0200 (Sat, 27 Sep 2008) | 2 lines
Fixed typos.
........
r34657 | eriktorbjorn | 2008-09-27 19:47:22 +0200 (Sat, 27 Sep 2008) | 2 lines
Allow quitting or returning to the launcher while cutscenes are playing.
........
r34658 | eriktorbjorn | 2008-09-27 19:51:22 +0200 (Sat, 27 Sep 2008) | 2 lines
Slight simplification of last commit.
........
r34659 | fingolfin | 2008-09-27 20:32:01 +0200 (Sat, 27 Sep 2008) | 1 line
Modified Common::SearchSet to take signed integer priorities, for convenience (so that one can add archives with less-than-default priority)
........
r34660 | fingolfin | 2008-09-27 20:34:24 +0200 (Sat, 27 Sep 2008) | 1 line
Fixed a nasty bug in SearchManager::addDirectory; made the 'char' constructor of Common::String explicit, to avoid such bugs in the future
........
r34661 | drmccoy | 2008-09-27 22:04:04 +0200 (Sat, 27 Sep 2008) | 2 lines
Added a spanish floppy version of Lost in Time, as supplied by goodoldgeorg in bug report #2105220
........
r34663 | fingolfin | 2008-09-28 01:00:46 +0200 (Sun, 28 Sep 2008) | 1 line
Changed Common::File to use SearchMan
........
r34664 | fingolfin | 2008-09-28 01:27:01 +0200 (Sun, 28 Sep 2008) | 1 line
SCUMM: Use FilesystemNode::openForReading instead of Common::File::open(FilesystemNode) in the detector
........
r34671 | john_doe | 2008-09-28 22:02:01 +0200 (Sun, 28 Sep 2008) | 1 line
Return 32000 in sfGetCdTime instead of 0; this fixes the Manhole intro/credits (until the function is actually implemented)
........
r34672 | sev | 2008-09-28 23:07:41 +0200 (Sun, 28 Sep 2008) | 2 lines
Add Italian C64 Zak
........
r34674 | sev | 2008-09-28 23:53:14 +0200 (Sun, 28 Sep 2008) | 2 lines
Fix bug #2043489: DRASCULA: Cannot disable speech
........
r34675 | sev | 2008-09-29 00:07:16 +0200 (Mon, 29 Sep 2008) | 3 lines
- Renamed withVoices to _subtitlesDisabled as it reflect the true meaning.
- Allowed to disable subtitles from options dialogs including RTL.
........
r34676 | sev | 2008-09-29 00:19:11 +0200 (Mon, 29 Sep 2008) | 2 lines
Use better "silence" without clicks when speech is disabled.
........
r34678 | fingolfin | 2008-09-29 12:29:01 +0200 (Mon, 29 Sep 2008) | 1 line
Added FIXME to GP2x port
........
r34679 | fingolfin | 2008-09-29 12:30:31 +0200 (Mon, 29 Sep 2008) | 1 line
Add priority parameter to the SearchMan API
........
r34680 | fingolfin | 2008-09-29 12:32:06 +0200 (Mon, 29 Sep 2008) | 1 line
File::open no longer falls back to searching the current dir (if this causes any regressions, please report them; don't work around them, don't revert this change, without discussing it first)
........
r34681 | fingolfin | 2008-09-29 12:49:36 +0200 (Mon, 29 Sep 2008) | 1 line
Don't subclass ArjFile from Common::File (there seems to be no good reason for it). BTW, this code is an abomination and should be replaced by an Archive/SearchSet approach
........
r34682 | fingolfin | 2008-09-29 13:01:25 +0200 (Mon, 29 Sep 2008) | 1 line
Added const qualifiers
........
r34683 | fingolfin | 2008-09-29 13:02:11 +0200 (Mon, 29 Sep 2008) | 1 line
SCUMM HE: Fixed leak in Win32ResExtractor::extractResource_, use _filename instead of File::name
........
r34684 | fingolfin | 2008-09-29 13:03:10 +0200 (Mon, 29 Sep 2008) | 1 line
Added const qualifiers
........
r34685 | fingolfin | 2008-09-29 13:07:39 +0200 (Mon, 29 Sep 2008) | 1 line
Don't use File::name() needlessly (i.e. if you still know which file you just opened :)
........
svn-id: r34687
2008-09-29 19:23:36 +00:00
|
|
|
#include "common/unzip.h"
|
2008-11-09 15:14:01 +00:00
|
|
|
|
|
|
|
#include "graphics/surface.h"
|
|
|
|
#include "graphics/colormasks.h"
|
2008-08-09 18:34:16 +00:00
|
|
|
#include "graphics/imageman.h"
|
2008-08-10 11:09:28 +00:00
|
|
|
#include "graphics/cursorman.h"
|
2008-11-09 15:14:01 +00:00
|
|
|
#include "graphics/VectorRenderer.h"
|
2008-07-01 15:57:30 +00:00
|
|
|
|
2008-11-09 15:14:01 +00:00
|
|
|
#include "gui/launcher.h"
|
2008-09-02 17:51:08 +00:00
|
|
|
#include "gui/ThemeEngine.h"
|
2008-07-31 17:23:38 +00:00
|
|
|
#include "gui/ThemeEval.h"
|
2008-11-09 15:14:01 +00:00
|
|
|
#include "gui/ThemeParser.h"
|
2008-11-10 11:24:55 +00:00
|
|
|
#include "gui/ThemeData.h"
|
2008-05-25 11:20:28 +00:00
|
|
|
|
2008-08-14 18:43:27 +00:00
|
|
|
#define GUI_ENABLE_BUILTIN_THEME
|
|
|
|
|
2008-05-25 11:20:28 +00:00
|
|
|
namespace GUI {
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
/**********************************************************
|
|
|
|
* ThemeEngine class
|
|
|
|
*********************************************************/
|
|
|
|
ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) :
|
|
|
|
_system(0), _vectorRenderer(0), _screen(0), _backBuffer(0),
|
|
|
|
_buffering(false), _bytesPerPixel(0), _graphicsMode(kGfxDisabled),
|
|
|
|
_font(0), _initOk(false), _themeOk(false), _enabled(false), _cursor(0),
|
|
|
|
_loadedThemeX(0), _loadedThemeY(0) {
|
|
|
|
|
|
|
|
_system = g_system;
|
|
|
|
_parser = new ThemeParser(this);
|
|
|
|
_themeEval = new GUI::ThemeEval();
|
2008-11-08 00:54:58 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
_useCursor = false;
|
2008-11-08 00:54:58 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
for (int i = 0; i < kDrawDataMAX; ++i) {
|
|
|
|
_widgets[i] = 0;
|
2008-11-08 00:54:58 +00:00
|
|
|
}
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
for (int i = 0; i < kTextDataMAX; ++i) {
|
|
|
|
_texts[i] = 0;
|
|
|
|
}
|
2008-11-08 00:54:58 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
_graphicsMode = mode;
|
|
|
|
_themeFileName = fileName;
|
|
|
|
_initOk = false;
|
|
|
|
}
|
2008-11-08 00:54:58 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
ThemeEngine::~ThemeEngine() {
|
|
|
|
freeRenderer();
|
|
|
|
freeScreen();
|
|
|
|
freeBackbuffer();
|
|
|
|
unloadTheme();
|
|
|
|
delete _parser;
|
|
|
|
delete _themeEval;
|
|
|
|
delete[] _cursor;
|
2008-11-08 00:54:58 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i)
|
|
|
|
ImageMan.unregisterSurface(i->_key);
|
|
|
|
}
|
2008-11-08 00:54:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
/**********************************************************
|
|
|
|
* Rendering mode management
|
|
|
|
*********************************************************/
|
2008-10-29 20:45:28 +00:00
|
|
|
const ThemeEngine::Renderer ThemeEngine::_rendererModes[] = {
|
|
|
|
{ "Disabled GFX", "none", kGfxDisabled },
|
|
|
|
{ "Standard Renderer (16bpp)", "normal_16bpp", kGfxStandard16bit },
|
2008-10-29 19:48:15 +00:00
|
|
|
#ifndef DISABLE_FANCY_THEMES
|
2008-10-29 20:45:28 +00:00
|
|
|
{ "Antialiased Renderer (16bpp)", "aa_16bpp", kGfxAntialias16bit }
|
2008-10-29 19:48:15 +00:00
|
|
|
#endif
|
2008-08-15 11:05:25 +00:00
|
|
|
};
|
|
|
|
|
2008-10-29 20:45:28 +00:00
|
|
|
const uint ThemeEngine::_rendererModesSize = ARRAYSIZE(ThemeEngine::_rendererModes);
|
|
|
|
|
2008-11-04 05:29:53 +00:00
|
|
|
const ThemeEngine::GraphicsMode ThemeEngine::_defaultRendererMode =
|
2008-10-29 20:45:28 +00:00
|
|
|
#ifndef DISABLE_FANCY_THEMES
|
|
|
|
ThemeEngine::kGfxAntialias16bit;
|
|
|
|
#else
|
|
|
|
ThemeEngine::kGfxStandard16bit;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ThemeEngine::GraphicsMode ThemeEngine::findMode(const Common::String &cfg) {
|
|
|
|
for (uint i = 0; i < _rendererModesSize; ++i) {
|
|
|
|
if (cfg.equalsIgnoreCase(_rendererModes[i].cfg))
|
|
|
|
return _rendererModes[i].mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
return kGfxDisabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *ThemeEngine::findModeConfigName(GraphicsMode mode) {
|
|
|
|
for (uint i = 0; i < _rendererModesSize; ++i) {
|
|
|
|
if (mode == _rendererModes[i].mode)
|
|
|
|
return _rendererModes[i].cfg;
|
|
|
|
}
|
|
|
|
|
|
|
|
return findModeConfigName(kGfxDisabled);
|
|
|
|
}
|
2008-09-02 17:51:08 +00:00
|
|
|
|
2008-06-24 19:48:01 +00:00
|
|
|
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 14:15:34 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Theme setup/initialization
|
|
|
|
*********************************************************/
|
|
|
|
bool ThemeEngine::init() {
|
2008-07-03 10:26:55 +00:00
|
|
|
// reset everything and reload the graphics
|
|
|
|
deinit();
|
|
|
|
setGraphicsMode(_graphicsMode);
|
|
|
|
|
2008-07-21 14:03:37 +00:00
|
|
|
if (_screen->pixels && _backBuffer->pixels) {
|
2008-07-03 10:26:55 +00:00
|
|
|
_initOk = true;
|
|
|
|
clearAll();
|
|
|
|
resetDrawArea();
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 10:42:01 +00:00
|
|
|
if (_screen->w >= 400 && _screen->h >= 300) {
|
|
|
|
_font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
|
|
|
|
} else {
|
|
|
|
_font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
|
|
|
|
}
|
2008-07-03 10:26:55 +00:00
|
|
|
|
2008-07-04 20:05:30 +00:00
|
|
|
if (isThemeLoadingRequired() || !_themeOk) {
|
2008-08-09 22:40:05 +00:00
|
|
|
loadTheme(_themeFileName);
|
2008-07-03 19:42:04 +00:00
|
|
|
}
|
|
|
|
|
2008-07-03 10:26:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::deinit() {
|
2008-07-03 10:26:55 +00:00
|
|
|
if (_initOk) {
|
|
|
|
_system->hideOverlay();
|
|
|
|
freeRenderer();
|
|
|
|
freeScreen();
|
2008-07-21 14:03:37 +00:00
|
|
|
freeBackbuffer();
|
2008-07-03 10:26:55 +00:00
|
|
|
_initOk = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-08 01:30:32 +00:00
|
|
|
void ThemeEngine::freeRenderer() {
|
|
|
|
delete _vectorRenderer;
|
|
|
|
_vectorRenderer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThemeEngine::freeBackbuffer() {
|
|
|
|
if (_backBuffer != 0) {
|
|
|
|
_backBuffer->free();
|
|
|
|
delete _backBuffer;
|
|
|
|
_backBuffer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThemeEngine::freeScreen() {
|
|
|
|
if (_screen != 0) {
|
|
|
|
_screen->free();
|
|
|
|
delete _screen;
|
|
|
|
_screen = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::unloadTheme() {
|
2008-08-09 22:40:05 +00:00
|
|
|
if (!_themeOk)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < kDrawDataMAX; ++i) {
|
|
|
|
delete _widgets[i];
|
|
|
|
_widgets[i] = 0;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 22:40:05 +00:00
|
|
|
for (int i = 0; i < kTextDataMAX; ++i) {
|
|
|
|
delete _texts[i];
|
|
|
|
_texts[i] = 0;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 22:40:05 +00:00
|
|
|
for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i)
|
|
|
|
ImageMan.unregisterSurface(i->_key);
|
|
|
|
|
2008-10-18 01:27:33 +00:00
|
|
|
ImageMan.removeArchive(_themeFileName);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 10:42:01 +00:00
|
|
|
_themeEval->reset();
|
2008-08-09 22:40:05 +00:00
|
|
|
_themeOk = false;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::clearAll() {
|
2008-07-03 10:26:55 +00:00
|
|
|
if (!_initOk)
|
|
|
|
return;
|
|
|
|
|
2008-07-03 19:42:04 +00:00
|
|
|
_system->clearOverlay();
|
2008-11-06 15:02:50 +00:00
|
|
|
_system->grabOverlay((OverlayColor *)_screen->pixels, _screen->w);
|
2008-07-03 19:42:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::refresh() {
|
2008-08-10 09:53:42 +00:00
|
|
|
init();
|
|
|
|
if (_enabled) {
|
|
|
|
_system->showOverlay();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-15 13:50:08 +00:00
|
|
|
if (_useCursor) {
|
|
|
|
CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS);
|
|
|
|
CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale);
|
|
|
|
}
|
2008-08-10 09:53:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::enable() {
|
2008-07-03 19:42:04 +00:00
|
|
|
init();
|
|
|
|
resetDrawArea();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-10 11:09:28 +00:00
|
|
|
if (_useCursor)
|
|
|
|
setUpCursor();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-03 19:42:04 +00:00
|
|
|
_system->showOverlay();
|
|
|
|
clearAll();
|
|
|
|
_enabled = true;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::disable() {
|
2008-07-03 19:42:04 +00:00
|
|
|
_system->hideOverlay();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-10 11:09:28 +00:00
|
|
|
if (_useCursor) {
|
|
|
|
CursorMan.popCursorPalette();
|
|
|
|
CursorMan.popCursor();
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-03 19:42:04 +00:00
|
|
|
_enabled = false;
|
2008-06-09 21:16:26 +00:00
|
|
|
}
|
|
|
|
|
2008-11-04 05:29:53 +00:00
|
|
|
template<typename PixelType>
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::screenInit(bool backBuffer) {
|
2008-07-21 14:03:37 +00:00
|
|
|
uint32 width = _system->getOverlayWidth();
|
|
|
|
uint32 height = _system->getOverlayHeight();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-16 10:48:14 +00:00
|
|
|
if (backBuffer) {
|
2008-08-09 14:15:34 +00:00
|
|
|
freeBackbuffer();
|
2008-11-09 15:14:01 +00:00
|
|
|
_backBuffer = new Graphics::Surface;
|
2008-07-21 14:03:37 +00:00
|
|
|
_backBuffer->create(width, height, sizeof(PixelType));
|
2008-07-16 10:48:14 +00:00
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 14:15:34 +00:00
|
|
|
freeScreen();
|
2008-11-09 15:14:01 +00:00
|
|
|
_screen = new Graphics::Surface;
|
2008-07-21 14:03:37 +00:00
|
|
|
_screen->create(width, height, sizeof(PixelType));
|
2008-05-28 14:27:22 +00:00
|
|
|
_system->clearOverlay();
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::setGraphicsMode(GraphicsMode mode) {
|
2008-05-28 14:27:22 +00:00
|
|
|
switch (mode) {
|
2008-05-28 15:03:30 +00:00
|
|
|
case kGfxStandard16bit:
|
2008-10-29 19:48:15 +00:00
|
|
|
#ifndef DISABLE_FANCY_THEMES
|
2008-05-28 15:03:30 +00:00
|
|
|
case kGfxAntialias16bit:
|
2008-10-29 19:48:15 +00:00
|
|
|
#endif
|
2008-05-28 14:27:22 +00:00
|
|
|
_bytesPerPixel = sizeof(uint16);
|
2008-07-16 10:48:14 +00:00
|
|
|
screenInit<uint16>(kEnableBackCaching);
|
2008-05-28 14:27:22 +00:00
|
|
|
break;
|
2008-05-28 14:30:51 +00:00
|
|
|
|
|
|
|
default:
|
2008-08-15 11:05:25 +00:00
|
|
|
error("Invalid graphics mode");
|
2008-05-28 14:27:22 +00:00
|
|
|
}
|
|
|
|
|
2008-06-10 11:25:00 +00:00
|
|
|
freeRenderer();
|
2008-11-09 15:14:01 +00:00
|
|
|
_vectorRenderer = Graphics::createRenderer(mode);
|
2008-05-28 14:27:22 +00:00
|
|
|
_vectorRenderer->setSurface(_screen);
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::isWidgetCached(DrawData type, const Common::Rect &r) {
|
|
|
|
return _widgets[type] && _widgets[type]->_cached &&
|
2008-11-04 05:29:53 +00:00
|
|
|
_widgets[type]->_surfaceCache->w == r.width() &&
|
2008-09-02 17:51:08 +00:00
|
|
|
_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;
|
2008-11-04 05:29:53 +00:00
|
|
|
for (Common::List<Graphics::DrawStep>::const_iterator step = _widgets[type]->_steps.begin();
|
2008-09-02 17:51:08 +00:00
|
|
|
step != _widgets[type]->_steps.end(); ++step) {
|
2008-11-04 05:29:53 +00:00
|
|
|
if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow)
|
2008-09-02 17:51:08 +00:00
|
|
|
maxShadow = step->shadow;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
bool ThemeEngine::isThemeLoadingRequired() {
|
|
|
|
int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight();
|
|
|
|
|
|
|
|
if (_loadedThemeX == x && _loadedThemeY == y)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_loadedThemeX = x;
|
|
|
|
_loadedThemeY = y;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Theme elements management
|
|
|
|
*********************************************************/
|
2008-11-08 01:30:32 +00:00
|
|
|
void ThemeEngine::addDrawStep(const Common::String &drawDataId, const Graphics::DrawStep &step) {
|
2008-06-24 19:48:01 +00:00
|
|
|
DrawData id = getDrawDataId(drawDataId);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-06-24 19:48:01 +00:00
|
|
|
assert(_widgets[id] != 0);
|
|
|
|
_widgets[id]->_steps.push_back(step);
|
2008-06-18 00:15:21 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) {
|
2008-07-10 15:50:44 +00:00
|
|
|
DrawData id = getDrawDataId(drawDataId);
|
2008-07-23 16:38:39 +00:00
|
|
|
TextData textId = getTextDataId(textDataId);
|
2008-07-20 22:23:35 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
if (id == -1 || textId == -1 || !_widgets[id])
|
|
|
|
return false;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
_widgets[id]->_textDataId = textId;
|
|
|
|
_widgets[id]->_textAlignH = alignH;
|
2008-11-04 05:29:53 +00:00
|
|
|
_widgets[id]->_textAlignV = alignV;
|
2008-07-20 21:47:28 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::addFont(const Common::String &fontId, const Common::String &file, int r, int g, int b) {
|
2008-07-23 16:38:39 +00:00
|
|
|
TextData textId = getTextDataId(fontId);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
if (textId == -1)
|
|
|
|
return false;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
if (_texts[textId] != 0)
|
2008-08-08 18:30:16 +00:00
|
|
|
delete _texts[textId];
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
_texts[textId] = new TextDrawData;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-07 18:42:47 +00:00
|
|
|
if (file == "default") {
|
|
|
|
_texts[textId]->_fontPtr = _font;
|
|
|
|
} else {
|
|
|
|
_texts[textId]->_fontPtr = FontMan.getFontByName(file);
|
|
|
|
|
|
|
|
if (!_texts[textId]->_fontPtr) {
|
2008-10-11 21:39:24 +00:00
|
|
|
_texts[textId]->_fontPtr = loadFont(file);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-07 18:42:47 +00:00
|
|
|
if (!_texts[textId]->_fontPtr)
|
|
|
|
error("Couldn't load %s font '%s'", fontId.c_str(), file.c_str());
|
|
|
|
|
|
|
|
FontMan.assignFontToName(file, _texts[textId]->_fontPtr);
|
|
|
|
}
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
_texts[textId]->_color.r = r;
|
|
|
|
_texts[textId]->_color.g = g;
|
|
|
|
_texts[textId]->_color.b = b;
|
2008-07-10 15:50:44 +00:00
|
|
|
return true;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-10 15:50:44 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::addBitmap(const Common::String &filename) {
|
2008-08-09 18:34:16 +00:00
|
|
|
if (_bitmaps.contains(filename)) {
|
|
|
|
ImageMan.unregisterSurface(filename);
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 18:34:16 +00:00
|
|
|
ImageMan.registerSurface(filename, 0);
|
|
|
|
_bitmaps[filename] = ImageMan.getSurface(filename);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 18:34:16 +00:00
|
|
|
return _bitmaps[filename] != 0;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::addDrawData(const Common::String &data, bool cached) {
|
2008-07-21 19:15:59 +00:00
|
|
|
DrawData data_id = getDrawDataId(data);
|
2008-06-24 19:48:01 +00:00
|
|
|
|
2008-08-08 18:30:16 +00:00
|
|
|
if (data_id == -1)
|
2008-06-24 19:48:01 +00:00
|
|
|
return false;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-08 18:30:16 +00:00
|
|
|
if (_widgets[data_id] != 0)
|
|
|
|
delete _widgets[data_id];
|
2008-06-24 19:48:01 +00:00
|
|
|
|
|
|
|
_widgets[data_id] = new WidgetDrawData;
|
|
|
|
_widgets[data_id]->_cached = cached;
|
2008-07-21 19:15:59 +00:00
|
|
|
_widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer;
|
2008-07-03 10:26:55 +00:00
|
|
|
_widgets[data_id]->_surfaceCache = 0;
|
2008-07-23 16:38:39 +00:00
|
|
|
_widgets[data_id]->_textDataId = -1;
|
2008-06-24 19:48:01 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2008-06-18 00:15:21 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Theme XML loading
|
|
|
|
*********************************************************/
|
2008-11-04 19:49:26 +00:00
|
|
|
bool ThemeEngine::loadTheme(const Common::String &fileName) {
|
2008-06-29 12:08:53 +00:00
|
|
|
unloadTheme();
|
|
|
|
|
2008-11-04 19:49:26 +00:00
|
|
|
bool tryAgain = false;
|
|
|
|
if (fileName != "builtin") {
|
2008-10-18 01:27:33 +00:00
|
|
|
ImageMan.addArchive(fileName);
|
2008-11-04 19:49:26 +00:00
|
|
|
if (!loadThemeXML(fileName)) {
|
|
|
|
warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str());
|
|
|
|
tryAgain = true; // Fall back to default builtin theme
|
|
|
|
}
|
|
|
|
}
|
2008-08-09 22:40:05 +00:00
|
|
|
|
2008-11-04 19:49:26 +00:00
|
|
|
if (fileName == "builtin" || tryAgain) {
|
2008-10-11 22:18:15 +00:00
|
|
|
if (!loadDefaultXML()) // if we can't load the embedded theme, this is a complete failure
|
|
|
|
error("Could not load default embedded theme");
|
2008-06-25 22:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < kDrawDataMAX; ++i) {
|
|
|
|
if (_widgets[i] == 0) {
|
2008-07-23 22:32:00 +00:00
|
|
|
warning("Missing data asset: '%s'", kDrawDataDefaults[i].name);
|
2008-07-17 21:58:43 +00:00
|
|
|
} else {
|
|
|
|
calcBackgroundOffset((DrawData)i);
|
|
|
|
|
|
|
|
// TODO: draw the cached widget to the cache surface
|
|
|
|
if (_widgets[i]->_cached) {}
|
2008-06-25 22:30:28 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-06-25 22:30:28 +00:00
|
|
|
_themeOk = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::loadDefaultXML() {
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 15:15:32 +00:00
|
|
|
// 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.
|
2008-09-29 10:27:16 +00:00
|
|
|
bool result;
|
2008-08-09 22:40:05 +00:00
|
|
|
|
|
|
|
#ifdef GUI_ENABLE_BUILTIN_THEME
|
2008-08-02 15:15:32 +00:00
|
|
|
const char *defaultXML =
|
|
|
|
#include "themes/default.inc"
|
|
|
|
;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
if (!_parser->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false))
|
2008-08-02 15:15:32 +00:00
|
|
|
return false;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-14 18:43:27 +00:00
|
|
|
_themeName = "ScummVM Classic Theme (Builtin Version)";
|
|
|
|
_themeFileName = "builtin";
|
2008-08-02 15:15:32 +00:00
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
result = _parser->parse();
|
|
|
|
_parser->close();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-09-29 10:27:16 +00:00
|
|
|
return result;
|
2008-08-09 22:40:05 +00:00
|
|
|
#else
|
|
|
|
warning("The built-in theme is not enabled in the current build. Please load an external theme");
|
|
|
|
return false;
|
|
|
|
#endif
|
2008-08-02 15:15:32 +00:00
|
|
|
}
|
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
bool ThemeEngine::loadThemeXML(const Common::String &themeName) {
|
2008-06-25 22:30:28 +00:00
|
|
|
assert(_parser);
|
2008-08-13 23:07:26 +00:00
|
|
|
_themeName.clear();
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-11-08 01:34:02 +00:00
|
|
|
Common::FSNode node(themeName);
|
2008-10-09 18:51:26 +00:00
|
|
|
if (!node.exists() || !node.isReadable())
|
|
|
|
return false;
|
2008-10-11 22:14:47 +00:00
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
Common::Archive *archive = 0;
|
2008-10-11 22:14:47 +00:00
|
|
|
|
|
|
|
if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
|
2008-08-15 21:01:32 +00:00
|
|
|
#ifdef USE_ZLIB
|
2008-10-11 22:14:47 +00:00
|
|
|
Common::ZipArchive *zipArchive = new Common::ZipArchive(node);
|
2008-10-22 17:44:12 +00:00
|
|
|
archive = zipArchive;
|
2008-10-11 22:14:47 +00:00
|
|
|
|
|
|
|
if (!zipArchive || !zipArchive->isOpen()) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete zipArchive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Failed to open Zip archive '%s'.", themeName.c_str());
|
2008-10-09 18:51:26 +00:00
|
|
|
return false;
|
2008-08-09 18:34:16 +00:00
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-15 21:01:32 +00:00
|
|
|
#endif
|
2008-10-11 22:14:47 +00:00
|
|
|
} else if (node.isDirectory()) {
|
2008-11-10 11:24:55 +00:00
|
|
|
|
|
|
|
// FIXME: This warning makes no sense whatsoever. Who added this?
|
|
|
|
// warning("Don't know how to open theme '%s'", themeName.c_str());
|
2008-10-22 17:44:12 +00:00
|
|
|
archive = new Common::FSDirectory(node);
|
2008-10-11 22:14:47 +00:00
|
|
|
}
|
|
|
|
|
2008-11-04 19:49:26 +00:00
|
|
|
if (!archive)
|
|
|
|
return false;
|
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
Common::File themercFile;
|
|
|
|
themercFile.open("THEMERC", *archive);
|
|
|
|
if (!themercFile.isOpen()) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Theme '%s' contains no 'THEMERC' file.", themeName.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::String stxHeader = themercFile.readLine();
|
|
|
|
if (!themeConfigParseHeader(stxHeader, _themeName) || _themeName.empty()) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::ArchiveMemberList members;
|
|
|
|
if (0 == archive->listMatchingMembers(members, "*.stx")) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Found no STX files for theme '%s'.", themeName.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loop over all STX files
|
|
|
|
for (Common::ArchiveMemberList::iterator i = members.begin(); i != members.end(); ++i) {
|
|
|
|
assert((*i)->getName().hasSuffix(".stx"));
|
|
|
|
|
|
|
|
if (_parser->loadStream((*i)->open()) == false) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Failed to load STX file '%s'", (*i)->getName().c_str());
|
|
|
|
_parser->close();
|
|
|
|
return false;
|
2008-08-15 21:01:32 +00:00
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
if (_parser->parse() == false) {
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
warning("Failed to parse STX file '%s'", (*i)->getName().c_str());
|
|
|
|
_parser->close();
|
|
|
|
return false;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-10-11 22:14:47 +00:00
|
|
|
_parser->close();
|
|
|
|
}
|
2008-08-15 21:01:32 +00:00
|
|
|
|
2008-10-22 17:44:12 +00:00
|
|
|
delete archive;
|
2008-10-11 22:14:47 +00:00
|
|
|
assert(!_themeName.empty());
|
|
|
|
return true;
|
2008-06-25 22:30:28 +00:00
|
|
|
}
|
|
|
|
|
2008-06-12 11:26:11 +00:00
|
|
|
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
/**********************************************************
|
|
|
|
* Drawing Queue management
|
|
|
|
*********************************************************/
|
|
|
|
void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) {
|
2008-07-10 15:50:44 +00:00
|
|
|
if (_widgets[type] == 0)
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
Common::Rect area = r;
|
|
|
|
area.clip(_screen->w, _screen->h);
|
|
|
|
|
|
|
|
ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, dynamic);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
if (_buffering) {
|
2008-07-21 16:14:06 +00:00
|
|
|
if (_widgets[type]->_buffer) {
|
2008-11-04 05:29:53 +00:00
|
|
|
_bufferQueue.push_back(q);
|
2008-07-21 16:14:06 +00:00
|
|
|
} else {
|
2008-07-21 19:15:59 +00:00
|
|
|
if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type)
|
|
|
|
queueDD(kDrawDataDefaults[type].parent, r);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-06 13:58:07 +00:00
|
|
|
_screenQueue.push_back(q);
|
2008-07-20 21:47:28 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-09-02 17:51:08 +00:00
|
|
|
q->drawSelf(!_widgets[type]->_buffer, _widgets[type]->_buffer);
|
|
|
|
delete q;
|
2008-07-20 21:47:28 +00:00
|
|
|
}
|
|
|
|
}
|
2008-07-18 16:44:42 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg,
|
2008-08-14 11:26:24 +00:00
|
|
|
bool ellipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) {
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
if (_texts[type] == 0)
|
|
|
|
return;
|
2008-09-02 17:51:08 +00:00
|
|
|
|
|
|
|
Common::Rect area = r;
|
|
|
|
area.clip(_screen->w, _screen->h);
|
|
|
|
|
|
|
|
ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], area, text, alignH, alignV, ellipsis, restoreBg, deltax);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
|
|
|
if (_buffering) {
|
2008-09-02 17:51:08 +00:00
|
|
|
_screenQueue.push_back(q);
|
2008-07-10 15:50:44 +00:00
|
|
|
} else {
|
2008-09-02 17:51:08 +00:00
|
|
|
q->drawSelf(true, false);
|
|
|
|
delete q;
|
2008-06-12 11:26:11 +00:00
|
|
|
}
|
2008-07-20 21:47:28 +00:00
|
|
|
}
|
2008-07-18 16:44:42 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
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);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 18:34:16 +00:00
|
|
|
if (_buffering) {
|
2008-09-02 17:51:08 +00:00
|
|
|
_bufferQueue.push_back(q);
|
2008-08-09 18:34:16 +00:00
|
|
|
} else {
|
2008-09-02 17:51:08 +00:00
|
|
|
q->drawSelf(true, false);
|
|
|
|
delete q;
|
2008-07-18 16:44:42 +00:00
|
|
|
}
|
2008-08-09 18:34:16 +00:00
|
|
|
}
|
|
|
|
|
2008-07-17 21:58:43 +00:00
|
|
|
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
/**********************************************************
|
|
|
|
* Widget drawing functions
|
|
|
|
*********************************************************/
|
|
|
|
void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) {
|
2008-06-28 16:49:39 +00:00
|
|
|
if (!ready())
|
2008-06-12 11:26:11 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-10 16:37:45 +00:00
|
|
|
DrawData dd = kDDButtonIdle;
|
2008-06-12 11:26:11 +00:00
|
|
|
|
|
|
|
if (state == kStateEnabled)
|
2008-07-10 15:50:44 +00:00
|
|
|
dd = kDDButtonIdle;
|
2008-06-12 11:26:11 +00:00
|
|
|
else if (state == kStateHighlight)
|
2008-07-10 15:50:44 +00:00
|
|
|
dd = kDDButtonHover;
|
2008-07-03 19:42:04 +00:00
|
|
|
else if (state == kStateDisabled)
|
2008-07-10 15:50:44 +00:00
|
|
|
dd = kDDButtonDisabled;
|
2008-06-12 11:26:11 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(dd, r);
|
2008-07-23 17:57:11 +00:00
|
|
|
queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
|
2008-06-12 11:26:11 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
|
2008-06-28 16:49:39 +00:00
|
|
|
if (!ready())
|
2008-06-12 11:26:11 +00:00
|
|
|
return;
|
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDSeparator, r);
|
2008-06-12 11:26:11 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
|
2008-06-28 16:49:39 +00:00
|
|
|
if (!ready())
|
2008-06-12 19:06:37 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
Common::Rect r2 = r;
|
2008-08-01 20:19:37 +00:00
|
|
|
DrawData dd = kDDCheckboxDefault;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-01 20:19:37 +00:00
|
|
|
if (checked)
|
|
|
|
dd = kDDCheckboxSelected;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-01 20:19:37 +00:00
|
|
|
if (state == kStateDisabled)
|
|
|
|
dd = kDDCheckboxDisabled;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-01 20:19:37 +00:00
|
|
|
TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd);
|
2008-07-11 13:25:23 +00:00
|
|
|
const int checkBoxSize = MIN((int)r.height(), getFontHeight());
|
2008-07-07 18:37:22 +00:00
|
|
|
|
|
|
|
r2.bottom = r2.top + checkBoxSize;
|
|
|
|
r2.right = r2.left + checkBoxSize;
|
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
queueDD(dd, r2);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-11 13:25:23 +00:00
|
|
|
r2.left = r2.right + checkBoxSize;
|
|
|
|
r2.right = r.right;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-01 20:19:37 +00:00
|
|
|
queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
|
2008-06-12 19:06:37 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
|
2008-06-28 16:49:39 +00:00
|
|
|
if (!ready())
|
2008-06-12 19:06:37 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 15:15:32 +00:00
|
|
|
DrawData dd = kDDSliderFull;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 15:15:32 +00:00
|
|
|
if (state == kStateHighlight)
|
|
|
|
dd = kDDSliderHover;
|
|
|
|
else if (state == kStateDisabled)
|
|
|
|
dd = kDDSliderDisabled;
|
2008-06-12 19:06:37 +00:00
|
|
|
|
|
|
|
Common::Rect r2 = r;
|
|
|
|
r2.setWidth(MIN((int16)width, r.width()));
|
2008-08-02 22:11:57 +00:00
|
|
|
// r2.top++; r2.bottom--; r2.left++; r2.right--;
|
2008-06-12 19:06:37 +00:00
|
|
|
|
2008-07-21 16:14:06 +00:00
|
|
|
drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 15:15:32 +00:00
|
|
|
if (width > r.width() * 5 / 100)
|
|
|
|
queueDD(dd, r2);
|
2008-06-12 19:06:37 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
|
2008-06-28 16:49:39 +00:00
|
|
|
if (!ready())
|
2008-06-12 19:06:37 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDScrollbarBase, r);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-24 18:40:36 +00:00
|
|
|
Common::Rect r2 = r;
|
|
|
|
const int buttonExtra = (r.width() * 120) / 100;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-24 18:40:36 +00:00
|
|
|
r2.bottom = r2.top + buttonExtra;
|
2008-07-25 00:59:53 +00:00
|
|
|
queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-24 18:40:36 +00:00
|
|
|
r2.translate(0, r.height() - r2.height());
|
2008-07-25 00:59:53 +00:00
|
|
|
queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-24 18:40:36 +00:00
|
|
|
r2 = r;
|
|
|
|
r2.left += 1;
|
|
|
|
r2.right -= 1;
|
|
|
|
r2.top += sliderY;
|
|
|
|
r2.bottom = r2.top + sliderHeight - 1;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-15 19:10:37 +00:00
|
|
|
r2.top += r.width() / 5;
|
2008-11-04 05:29:53 +00:00
|
|
|
r2.bottom -= r.width() / 5;
|
2008-07-24 18:40:36 +00:00
|
|
|
queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2);
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 17:46:00 +00:00
|
|
|
switch (bgtype) {
|
|
|
|
case kDialogBackgroundMain:
|
|
|
|
queueDD(kDDMainDialogBackground, r);
|
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 17:46:00 +00:00
|
|
|
case kDialogBackgroundSpecial:
|
|
|
|
queueDD(kDDSpecialColorBackground, r);
|
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 17:46:00 +00:00
|
|
|
case kDialogBackgroundPlain:
|
|
|
|
queueDD(kDDPlainColorBackground, r);
|
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-13 17:46:00 +00:00
|
|
|
case kDialogBackgroundDefault:
|
|
|
|
queueDD(kDDDefaultBackground, r);
|
|
|
|
break;
|
2008-07-12 01:59:33 +00:00
|
|
|
}
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-07 18:42:47 +00:00
|
|
|
if (erase) {
|
|
|
|
restoreBackground(r);
|
|
|
|
addDirtyRect(r);
|
|
|
|
} else
|
|
|
|
queueDD(kDDCaret, r);
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-14 18:42:38 +00:00
|
|
|
DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(dd, r);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-14 18:42:38 +00:00
|
|
|
if (!sel.empty()) {
|
|
|
|
Common::Rect text(r.left, r.top, r.right - 16, r.bottom);
|
2008-08-18 19:06:58 +00:00
|
|
|
queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
|
2008-07-15 10:50:31 +00:00
|
|
|
}
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-09 18:34:16 +00:00
|
|
|
queueBitmap(&surface, r, themeTrans);
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-13 11:07:56 +00:00
|
|
|
switch (background) {
|
|
|
|
case kWidgetBackgroundBorderSmall:
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDWidgetBackgroundSmall, r);
|
2008-07-13 11:07:56 +00:00
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-13 11:07:56 +00:00
|
|
|
case kWidgetBackgroundEditText:
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDWidgetBackgroundEditText, r);
|
2008-07-13 11:07:56 +00:00
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-13 11:07:56 +00:00
|
|
|
case kWidgetBackgroundSlider:
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDWidgetBackgroundSlider, r);
|
2008-07-13 11:07:56 +00:00
|
|
|
break;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-13 11:07:56 +00:00
|
|
|
default:
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDWidgetBackgroundDefault, r);
|
2008-07-13 11:07:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
|
2008-07-07 18:37:22 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 16:23:58 +00:00
|
|
|
const int tabOffset = 2;
|
|
|
|
tabWidth -= tabOffset;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-01 20:19:37 +00:00
|
|
|
queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-15 18:53:22 +00:00
|
|
|
for (int i = 0; i < (int)tabs.size(); ++i) {
|
|
|
|
if (i == active)
|
|
|
|
continue;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-15 18:53:22 +00:00
|
|
|
Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight);
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDTabInactive, tabRect);
|
2008-07-23 17:57:11 +00:00
|
|
|
queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
|
2008-07-15 18:53:22 +00:00
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-15 18:53:22 +00:00
|
|
|
if (active >= 0) {
|
|
|
|
Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight);
|
2008-07-17 08:36:16 +00:00
|
|
|
const uint16 tabLeft = active * (tabWidth + tabOffset);
|
2008-07-22 13:32:18 +00:00
|
|
|
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
|
2008-07-20 21:47:28 +00:00
|
|
|
queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
|
2008-07-23 17:57:11 +00:00
|
|
|
queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
|
2008-07-15 18:53:22 +00:00
|
|
|
}
|
2008-07-07 18:37:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {
|
2008-07-23 17:57:11 +00:00
|
|
|
if (!ready())
|
2008-11-04 05:29:53 +00:00
|
|
|
return;
|
|
|
|
|
2008-07-23 17:57:11 +00:00
|
|
|
if (inverted) {
|
2008-07-23 16:38:39 +00:00
|
|
|
queueDD(kDDTextSelectionBackground, r);
|
2008-08-10 18:56:10 +00:00
|
|
|
queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax);
|
2008-07-23 17:57:11 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-07 18:42:47 +00:00
|
|
|
switch (font) {
|
|
|
|
case kFontStyleNormal:
|
2008-08-10 18:56:10 +00:00
|
|
|
queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
2008-08-07 18:42:47 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-07 18:42:47 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2008-07-23 17:57:11 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
switch (state) {
|
|
|
|
case kStateDisabled:
|
2008-08-10 18:56:10 +00:00
|
|
|
queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
2008-08-07 18:42:47 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
case kStateHighlight:
|
2008-08-10 18:56:10 +00:00
|
|
|
queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
2008-08-07 18:42:47 +00:00
|
|
|
return;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-23 16:38:39 +00:00
|
|
|
case kStateEnabled:
|
2008-08-10 18:56:10 +00:00
|
|
|
queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
2008-08-07 18:42:47 +00:00
|
|
|
return;
|
2008-07-23 16:38:39 +00:00
|
|
|
}
|
2008-07-15 10:50:31 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {
|
2008-08-08 18:30:16 +00:00
|
|
|
if (!ready())
|
|
|
|
return;
|
2008-10-18 00:29:23 +00:00
|
|
|
|
|
|
|
Common::Rect charArea = r;
|
|
|
|
charArea.clip(_screen->w, _screen->h);
|
2008-10-18 01:44:12 +00:00
|
|
|
|
2008-11-06 15:02:50 +00:00
|
|
|
Graphics::PixelFormat format = _system->getOverlayFormat();
|
|
|
|
uint32 color = Graphics::RGBToColor(_texts[kTextDataDefault]->_color.r, _texts[kTextDataDefault]->_color.g, _texts[kTextDataDefault]->_color.b, format);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-10-18 00:29:23 +00:00
|
|
|
restoreBackground(charArea);
|
2008-10-18 01:44:12 +00:00
|
|
|
font->drawChar(_screen, ch, charArea.left, charArea.top, color);
|
2008-10-18 00:29:23 +00:00
|
|
|
addDirtyRect(charArea);
|
2008-08-08 18:30:16 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
|
2008-07-15 18:53:22 +00:00
|
|
|
_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);
|
2008-06-12 19:06:37 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Screen/overlay management
|
|
|
|
*********************************************************/
|
|
|
|
void ThemeEngine::updateScreen() {
|
2008-07-20 21:47:28 +00:00
|
|
|
if (!_bufferQueue.empty()) {
|
|
|
|
_vectorRenderer->setSurface(_backBuffer);
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
for (Common::List<ThemeItem*>::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) {
|
|
|
|
(*q)->drawSelf(true, false);
|
|
|
|
delete *q;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
_vectorRenderer->setSurface(_screen);
|
2008-07-21 14:03:37 +00:00
|
|
|
_vectorRenderer->blitSurface(_backBuffer, Common::Rect(0, 0, _screen->w, _screen->h));
|
2008-07-20 21:47:28 +00:00
|
|
|
_bufferQueue.clear();
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
if (!_screenQueue.empty()) {
|
|
|
|
_vectorRenderer->disableShadows();
|
2008-09-02 17:51:08 +00:00
|
|
|
for (Common::List<ThemeItem*>::iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) {
|
|
|
|
(*q)->drawSelf(true, false);
|
|
|
|
delete *q;
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-20 21:47:28 +00:00
|
|
|
_vectorRenderer->enableShadows();
|
|
|
|
_screenQueue.clear();
|
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-10 18:35:27 +00:00
|
|
|
renderDirtyScreen();
|
2008-07-03 19:42:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::renderDirtyScreen() {
|
2008-07-02 18:11:41 +00:00
|
|
|
if (_dirtyScreen.empty())
|
|
|
|
return;
|
2008-07-22 12:07:03 +00:00
|
|
|
|
2008-07-22 17:39:30 +00:00
|
|
|
Common::List<Common::Rect>::const_iterator i, j;
|
|
|
|
for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) {
|
|
|
|
for (j = i; j != _dirtyScreen.end(); ++j)
|
2008-07-22 20:07:53 +00:00
|
|
|
if (j != i && i->contains(*j))
|
2008-07-22 17:39:30 +00:00
|
|
|
j = _dirtyScreen.reverse_erase(j);
|
|
|
|
|
|
|
|
_vectorRenderer->copyFrame(_system, *i);
|
2008-07-22 09:23:37 +00:00
|
|
|
}
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-07-02 18:11:41 +00:00
|
|
|
_dirtyScreen.clear();
|
2008-05-28 14:27:22 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) {
|
2008-07-18 16:44:42 +00:00
|
|
|
if (doBuffer)
|
|
|
|
_buffering = true;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-08-02 16:23:58 +00:00
|
|
|
if (style != kShadingNone) {
|
|
|
|
_vectorRenderer->applyScreenShading(style);
|
|
|
|
addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h));
|
|
|
|
}
|
2008-07-17 21:58:43 +00:00
|
|
|
|
2008-07-21 14:03:37 +00:00
|
|
|
_vectorRenderer->setSurface(_backBuffer);
|
|
|
|
_vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h));
|
|
|
|
_vectorRenderer->setSurface(_screen);
|
2008-07-17 21:58:43 +00:00
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
void ThemeEngine::setUpCursor() {
|
2008-08-10 11:09:28 +00:00
|
|
|
CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS);
|
|
|
|
CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale);
|
|
|
|
CursorMan.showMouse(true);
|
|
|
|
}
|
|
|
|
|
2008-09-02 17:51:08 +00:00
|
|
|
bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) {
|
2008-08-10 17:22:12 +00:00
|
|
|
if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette))
|
2008-09-07 21:45:18 +00:00
|
|
|
return true;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-11-03 16:00:13 +00:00
|
|
|
// Try to locate the specified file among all loaded bitmaps
|
2008-11-09 15:14:01 +00:00
|
|
|
const Graphics::Surface *cursor = _bitmaps[filename];
|
2008-08-10 11:09:28 +00:00
|
|
|
if (!cursor)
|
2008-08-10 17:22:12 +00:00
|
|
|
return false;
|
2008-11-04 05:29:53 +00:00
|
|
|
|
2008-11-03 16:00:13 +00:00
|
|
|
// Set up the cursor parameters
|
2008-08-10 17:22:12 +00:00
|
|
|
_cursorHotspotX = hotspotX;
|
|
|
|
_cursorHotspotY = hotspotY;
|
|
|
|
_cursorTargetScale = scale;
|
2008-08-10 11:09:28 +00:00
|
|
|
|
|
|
|
_cursorWidth = cursor->w;
|
|
|
|
_cursorHeight = cursor->h;
|
|
|
|
|
2008-11-03 16:00:13 +00:00
|
|
|
// Allocate a new buffer for the cursor
|
2008-08-10 11:09:28 +00:00
|
|
|
delete[] _cursor;
|
|
|
|
_cursor = new byte[_cursorWidth * _cursorHeight];
|
|
|
|
assert(_cursor);
|
2008-11-03 15:15:32 +00:00
|
|
|
memset(_cursor, 0xFF, sizeof(byte) * _cursorWidth * _cursorHeight);
|
2008-08-10 11:09:28 +00:00
|
|
|
|
2008-11-03 16:00:13 +00:00
|
|
|
// Now, scan the bitmap. We have to convert it from 16 bit color mode
|
|
|
|
// to 8 bit mode, and have to create a suitable palette on the fly.
|
|
|
|
uint colorsFound = 0;
|
|
|
|
Common::HashMap<int, int> colorToIndex;
|
|
|
|
const OverlayColor *src = (const OverlayColor*)cursor->pixels;
|
2008-11-06 15:02:50 +00:00
|
|
|
Graphics::PixelFormat format = _system->getOverlayFormat();
|
2008-08-10 11:09:28 +00:00
|
|
|
for (uint y = 0; y < _cursorHeight; ++y) {
|
|
|
|
for (uint x = 0; x < _cursorWidth; ++x) {
|
2008-11-03 16:00:13 +00:00
|
|
|
byte r, g, b;
|
2008-11-06 15:02:50 +00:00
|
|
|
Graphics::colorToRGB(src[x], r, g, b, format);
|
2008-11-03 16:00:13 +00:00
|
|
|
const int col = (r << 16) | (g << 8) | b;
|
|
|
|
|
2008-11-03 16:00:52 +00:00
|
|
|
// Skip transparency (the transparent color actually is 0xFF00FF,
|
|
|
|
// but the RGB conversion chops of the lower bits).
|
2008-11-03 16:00:13 +00:00
|
|
|
if ((r > 0xF1) && (g < 0x03) && (b > 0xF1))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If there is no entry yet for this color in the palette: Add one
|
|
|
|
if (!colorToIndex.contains(col)) {
|
2008-11-03 15:15:32 +00:00
|
|
|
const int index = colorsFound++;
|
|
|
|
colorToIndex[col] = index;
|
2008-08-10 11:09:28 +00:00
|
|
|
|
|
|
|
_cursorPal[index * 4 + 0] = r;
|
|
|
|
_cursorPal[index * 4 + 1] = g;
|
|
|
|
_cursorPal[index * 4 + 2] = b;
|
|
|
|
_cursorPal[index * 4 + 3] = 0xFF;
|
|
|
|
|
2008-08-10 17:22:12 +00:00
|
|
|
if (colorsFound > MAX_CURS_COLORS) {
|
2008-11-03 16:00:13 +00:00
|
|
|
warning("Cursor contains too many colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS);
|
2008-08-10 17:22:12 +00:00
|
|
|
return false;
|
|
|
|
}
|
2008-08-10 11:09:28 +00:00
|
|
|
}
|
|
|
|
|
2008-11-03 16:00:13 +00:00
|
|
|
// Copy pixel from the 16 bit source surface to the 8bit target surface
|
|
|
|
const int index = colorToIndex[col];
|
|
|
|
_cursor[y * _cursorWidth + x] = index;
|
2008-08-10 11:09:28 +00:00
|
|
|
}
|
|
|
|
src += _cursorWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
_useCursor = true;
|
2008-11-03 15:15:32 +00:00
|
|
|
|
2008-08-10 17:22:12 +00:00
|
|
|
return true;
|
2008-08-10 11:09:28 +00:00
|
|
|
}
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Legacy GUI::Theme support functions
|
|
|
|
*********************************************************/
|
|
|
|
|
2008-11-08 00:54:58 +00:00
|
|
|
const Graphics::Font *ThemeEngine::getFont(FontStyle font) const {
|
|
|
|
return _texts[fontStyleToData(font)]->_fontPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ThemeEngine::getFontHeight(FontStyle font) const {
|
|
|
|
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getFontHeight() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ThemeEngine::getStringWidth(const Common::String &str, FontStyle font) const {
|
|
|
|
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ThemeEngine::getCharWidth(byte c, FontStyle font) const {
|
|
|
|
return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ThemeEngine::TextData ThemeEngine::getTextData(DrawData ddId) {
|
|
|
|
return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-10 11:24:55 +00:00
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* External data loading
|
|
|
|
*********************************************************/
|
|
|
|
|
|
|
|
const Graphics::Font *ThemeEngine::loadFontFromArchive(const Common::String &filename) {
|
|
|
|
Common::Archive *arch = 0;
|
|
|
|
const Graphics::NewFont *font = 0;
|
|
|
|
|
|
|
|
if (getThemeFileName().hasSuffix(".zip")) {
|
|
|
|
#ifdef USE_ZLIB
|
|
|
|
Common::ZipArchive *zip = new Common::ZipArchive(getThemeFileName());
|
|
|
|
if (!zip || !zip->isOpen())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
arch = zip;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
Common::FSDirectory *dir = new Common::FSDirectory(getThemeFileName());
|
|
|
|
if (!dir || !dir->getFSNode().isDirectory())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
arch = dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::SeekableReadStream *stream(arch->openFile(filename));
|
|
|
|
if (stream) {
|
|
|
|
font = Graphics::NewFont::loadFromCache(*stream);
|
|
|
|
delete stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete arch;
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Graphics::Font *ThemeEngine::loadFont(const Common::String &filename) {
|
|
|
|
const Graphics::Font *font = 0;
|
|
|
|
Common::String cacheFilename = genCacheFilename(filename.c_str());
|
|
|
|
Common::File fontFile;
|
|
|
|
|
|
|
|
if (!cacheFilename.empty()) {
|
|
|
|
if (fontFile.open(cacheFilename))
|
|
|
|
font = Graphics::NewFont::loadFromCache(fontFile);
|
|
|
|
|
|
|
|
if (font)
|
|
|
|
return font;
|
|
|
|
|
|
|
|
if ((font = loadFontFromArchive(cacheFilename)))
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
// normal open
|
|
|
|
if (fontFile.open(filename)) {
|
|
|
|
font = Graphics::NewFont::loadFont(fontFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!font) {
|
|
|
|
font = loadFontFromArchive(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (font) {
|
|
|
|
if (!cacheFilename.empty()) {
|
|
|
|
if (!Graphics::NewFont::cacheFontData(*(const Graphics::NewFont*)font, cacheFilename)) {
|
|
|
|
warning("Couldn't create cache file for font '%s'", filename.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::String ThemeEngine::genCacheFilename(const char *filename) {
|
|
|
|
Common::String cacheName(filename);
|
|
|
|
for (int i = cacheName.size() - 1; i >= 0; --i) {
|
|
|
|
if (cacheName[i] == '.') {
|
|
|
|
while ((uint)i < cacheName.size() - 1) {
|
|
|
|
cacheName.deleteLastChar();
|
|
|
|
}
|
|
|
|
|
|
|
|
cacheName += "fcc";
|
|
|
|
return cacheName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
|
* Static Theme XML functions
|
|
|
|
*********************************************************/
|
|
|
|
|
|
|
|
bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &themeName) {
|
|
|
|
header.trim();
|
|
|
|
|
|
|
|
if (header.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
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 ThemeEngine::themeConfigUseable(const Common::FSNode &node, Common::String &themeName) {
|
|
|
|
Common::File stream;
|
|
|
|
bool foundHeader = false;
|
|
|
|
|
|
|
|
if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
|
|
|
|
#ifdef USE_ZLIB
|
|
|
|
Common::ZipArchive zipArchive(node);
|
|
|
|
if (zipArchive.hasFile("THEMERC")) {
|
|
|
|
stream.open("THEMERC", zipArchive);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} else if (node.isDirectory()) {
|
|
|
|
Common::FSNode headerfile = node.getChild("THEMERC");
|
|
|
|
if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory())
|
|
|
|
return false;
|
|
|
|
stream.open(headerfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream.isOpen()) {
|
|
|
|
Common::String stxHeader = stream.readLine();
|
|
|
|
foundHeader = themeConfigParseHeader(stxHeader, themeName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return foundHeader;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-25 17:06:10 +00:00
|
|
|
} // end of namespace GUI.
|