aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress/data/subtitle.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2010-10-18 19:17:38 +0000
committerEugene Sandulenko2010-10-18 19:17:38 +0000
commit86d650926f9b991b6398e4ad4b0613ac264dfbaa (patch)
tree5e6791249fa5fce7dd3e1a6406dff4bf720ca085 /engines/lastexpress/data/subtitle.cpp
parentc92d2bc234f2f73a9629b3622cd5e66c57439cda (diff)
downloadscummvm-rg350-86d650926f9b991b6398e4ad4b0613ac264dfbaa.tar.gz
scummvm-rg350-86d650926f9b991b6398e4ad4b0613ac264dfbaa.tar.bz2
scummvm-rg350-86d650926f9b991b6398e4ad4b0613ac264dfbaa.zip
LASTEXPRESS: Merge in the engine.
svn-id: r53579
Diffstat (limited to 'engines/lastexpress/data/subtitle.cpp')
-rw-r--r--engines/lastexpress/data/subtitle.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/engines/lastexpress/data/subtitle.cpp b/engines/lastexpress/data/subtitle.cpp
new file mode 100644
index 0000000000..fb7d4ec6fa
--- /dev/null
+++ b/engines/lastexpress/data/subtitle.cpp
@@ -0,0 +1,243 @@
+/* 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$
+ *
+ */
+
+// Based on the Xentax Wiki documentation:
+// http://wiki.xentax.com/index.php/The_Last_Express_SBE
+
+#include "lastexpress/data/subtitle.h"
+
+#include "lastexpress/data/font.h"
+
+#include "lastexpress/debug.h"
+
+#include "common/debug.h"
+
+namespace LastExpress {
+
+//////////////////////////////////////////////////////////////////////////
+// Subtitle
+//////////////////////////////////////////////////////////////////////////
+class Subtitle {
+public:
+ Subtitle() : _timeStart(0), _timeStop(0), _topLength(0), _topText(NULL),
+ _bottomLength(0), _bottomText(NULL) {}
+ ~Subtitle() { reset(); }
+
+ bool load(Common::SeekableReadStream *in);
+ Common::Rect draw(Graphics::Surface *surface, Font *font);
+
+ uint16 getTimeStart() const { return _timeStart; }
+ uint16 getTimeStop() const { return _timeStop; }
+
+private:
+ uint16 _timeStart; ///< display start time
+ uint16 _timeStop; ///< display stop time
+
+ uint16 _topLength; ///< top line length
+ uint16 *_topText; ///< bottom line length
+
+ uint16 _bottomLength; ///< top line (UTF-16 string)
+ uint16 *_bottomText; ///< bottom line (UTF-16 string)
+
+ void reset();
+};
+
+void Subtitle::reset() {
+ delete[] _topText;
+ delete[] _bottomText;
+ _topText = NULL;
+ _bottomText = NULL;
+}
+
+template<typename T>
+T *newArray(size_t n)
+{
+ if (n <= (size_t)-1 / sizeof(T))
+ return new T[n];
+
+ // n is too large
+ return NULL;
+}
+
+bool Subtitle::load(Common::SeekableReadStream *in) {
+ reset();
+
+ if (!in)
+ return false;
+
+ // Read the display times
+ _timeStart = in->readUint16LE();
+ _timeStop = in->readUint16LE();
+
+ // Read the text lengths
+ _topLength = in->readUint16LE();
+ _bottomLength = in->readUint16LE();
+
+ // Create the buffers
+ if (_topLength) {
+ _topText = newArray<uint16>(_topLength);
+ if (!_topText)
+ return false;
+ }
+ if (_bottomLength) {
+ _bottomText = newArray<uint16>(_bottomLength);
+ if (!_bottomText)
+ return false;
+ }
+
+ // Read the texts
+ for (int i = 0; i < _topLength; i++)
+ _topText[i] = in->readUint16LE();
+ for (int i = 0; i < _bottomLength; i++)
+ _bottomText[i] = in->readUint16LE();
+
+ debugC(9, kLastExpressDebugSubtitle, " %d -> %d:", _timeStart, _timeStop);
+ if (_topLength)
+ debugC(9, kLastExpressDebugSubtitle, "\t%ls", (wchar_t *)_topText);
+ if (_bottomLength)
+ debugC(9, kLastExpressDebugSubtitle, "\t%ls", (wchar_t *)_bottomText);
+
+ return true;
+}
+
+Common::Rect Subtitle::draw(Graphics::Surface *surface, Font *font) {
+ Common::Rect rectTop, rectBottom;
+
+ //FIXME find out proper subtitles coordinates (and hope it's hardcoded and not stored in the sequence or animation)
+ rectTop = font->drawString(surface, 100, 100, _topText, _topLength);
+ rectBottom = font->drawString(surface, 100, 300, _bottomText, _bottomLength);
+
+ rectTop.extend(rectBottom);
+
+ return rectTop;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// SubtitleManager
+//////////////////////////////////////////////////////////////////////////
+SubtitleManager::SubtitleManager(Font *font) : _font(font), _maxTime(0), _currentIndex(-1), _lastIndex(-1) {}
+
+SubtitleManager::~SubtitleManager() {
+ reset();
+
+ _font = NULL;
+}
+
+void SubtitleManager::reset() {
+ for (int i = 0; i < (int)_subtitles.size(); i++)
+ delete _subtitles[i];
+
+ _subtitles.clear();
+ _currentIndex = -1;
+ _lastIndex = -1;
+
+ // Zero passed pointers
+ _font = NULL;
+}
+
+bool SubtitleManager::load(Common::SeekableReadStream *stream) {
+ if (!stream)
+ return false;
+
+ reset();
+
+ // Read header to get the number of subtitles
+ uint32 numSubtitles = stream->readUint16LE();
+ if (stream->eos())
+ error("Cannot read from subtitle file");
+
+ debugC(3, kLastExpressDebugSubtitle, "Number of subtitles in file: %d", numSubtitles);
+
+ // TODO: Check that stream contain enough data
+ //if (stream->size() < (signed)(numSubtitles * sizeof(SubtitleData))) {
+ //debugC(2, kLastExpressDebugSubtitle, "Subtitle file does not contain valid data!");
+ //return false;
+ //}
+
+ // Read the list of subtitles
+ _maxTime = 0;
+ for (uint i = 0; i < numSubtitles; i++) {
+ Subtitle *subtitle = new Subtitle();
+ if (!subtitle->load(stream)) {
+ // Failed to read this line
+ reset();
+
+ delete subtitle;
+
+ return false;
+ }
+
+ // Update the max time
+ if (subtitle->getTimeStop() > _maxTime)
+ _maxTime = subtitle->getTimeStop();
+
+ _subtitles.push_back(subtitle);
+ }
+
+ delete stream;
+
+ return true;
+}
+
+uint16 SubtitleManager::getMaxTime() const {
+ return _maxTime;
+}
+
+void SubtitleManager::setTime(uint16 time) {
+ _currentIndex = -1;
+
+ // Find the appropriate line to show
+ for (int16 i = 0; i < (int16)_subtitles.size(); i++) {
+ if ((time >= _subtitles[i]->getTimeStart()) && (time <= _subtitles[i]->getTimeStop())) {
+ // Keep the index of the line to show
+ _currentIndex = i;
+ return;
+ }
+ }
+}
+
+bool SubtitleManager::hasChanged() const {
+ // TODO: mark the old line rect as dirty
+ if (_currentIndex != _lastIndex)
+ return true;
+ else
+ return false;
+}
+
+Common::Rect SubtitleManager::draw(Graphics::Surface *surface) {
+ // Update the last drawn index
+ _lastIndex = _currentIndex;
+
+ // Return if we don't have to draw any line
+ if (_currentIndex == -1)
+ return Common::Rect();
+
+ // Draw the current line
+ assert(_currentIndex >= 0 && _currentIndex < (int16)_subtitles.size());
+ return _subtitles[_currentIndex]->draw(surface, _font);
+}
+
+} // End of namespace LastExpress