Initial commit
This commit is contained in:
173
engines/director/stxt.cpp
Normal file
173
engines/director/stxt.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/macresman.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "director/director.h"
|
||||
#include "director/cast.h"
|
||||
#include "director/stxt.h"
|
||||
|
||||
namespace Director {
|
||||
|
||||
Stxt::Stxt(Cast *cast, Common::SeekableReadStreamEndian &textStream) : _cast(cast) {
|
||||
// TODO: Side effects on textStream make this a little hard to understand in context?
|
||||
|
||||
_textType = kTextTypeFixed;
|
||||
_textAlign = kTextAlignLeft;
|
||||
_textShadow = 0;
|
||||
_unk1f = _unk2f = 0;
|
||||
_unk3f = 0;
|
||||
_size = textStream.size();
|
||||
|
||||
// D4+ variant
|
||||
if (textStream.size() == 0)
|
||||
return;
|
||||
|
||||
uint32 offset = textStream.readUint32();
|
||||
if (offset != 12) {
|
||||
textStream.hexdump(textStream.size());
|
||||
error("Stxt init: unhandled offset, %d", offset);
|
||||
return;
|
||||
}
|
||||
uint32 strLen = textStream.readUint32();
|
||||
uint32 dataLen = textStream.readUint32();
|
||||
Common::String text = textStream.readString(0, strLen);
|
||||
debugC(3, kDebugText, "Stxt init: offset: %d strLen: %d dataLen: %d textlen: %u", offset, strLen, dataLen, text.size());
|
||||
|
||||
// TODO: Before applying formatting and decoding the text to a U32String,
|
||||
// check if the following hold true:
|
||||
// - The engine platform doesn't match the file platform
|
||||
// - The movie has a valid font table (FXmp)
|
||||
// - The font table has a mapping between the two platforms
|
||||
// - The text has sections written in a font without a Map None qualifier
|
||||
// If yes, then just those sections should be preprocessed by churning the
|
||||
// bytes through the appropriate mapping (e.g. if running a Mac file on
|
||||
// Windows, use the "Mac: => Win:" rules).
|
||||
// Confirmed in real Director 4 that these sections are preprocessed in
|
||||
// the cast member on startup and not faked at text render time.
|
||||
|
||||
uint16 formattingCount = textStream.readUint16();
|
||||
uint32 prevPos = 0;
|
||||
|
||||
debugC(3, kDebugText, "Stxt init: formattingCount: %u", formattingCount);
|
||||
|
||||
Common::U32String logText;
|
||||
|
||||
while (formattingCount) {
|
||||
uint16 currentFont = _style.fontId;
|
||||
_style.read(textStream, _cast);
|
||||
|
||||
assert(prevPos <= _style.formatStartOffset); // If this is triggered, we have to implement sorting
|
||||
|
||||
Common::String textPart;
|
||||
while (prevPos != _style.formatStartOffset) {
|
||||
char f = text.firstChar();
|
||||
textPart += f;
|
||||
text.deleteChar(0);
|
||||
|
||||
if (f == '\001') // Insert two \001s as a replacement
|
||||
_ftext += '\001';
|
||||
|
||||
prevPos++;
|
||||
}
|
||||
_rtext += textPart;
|
||||
Common::CodePage encoding = detectFontEncoding(cast->_platform, currentFont);
|
||||
Common::U32String u32TextPart(textPart, encoding);
|
||||
_ptext += u32TextPart;
|
||||
_ftext += u32TextPart;
|
||||
logText += Common::toPrintable(u32TextPart);
|
||||
|
||||
Common::String format = Common::String::format("\001\016%04x%02x%04x%04x%04x%04x", _style.fontId, _style.textSlant, _style.fontSize, _style.r, _style.g, _style.b);
|
||||
_ftext += format;
|
||||
logText += Common::toPrintable(format);
|
||||
|
||||
formattingCount--;
|
||||
}
|
||||
|
||||
_rtext += text;
|
||||
Common::CodePage encoding = detectFontEncoding(cast->_platform, _style.fontId);
|
||||
Common::U32String u32Text(text, encoding);
|
||||
_ptext += u32Text;
|
||||
_ftext += u32Text;
|
||||
logText += Common::toPrintable(u32Text);
|
||||
|
||||
debugC(4, kDebugText, "#### text:\n%s\n####", logText.encode(Common::kUtf8).c_str());
|
||||
}
|
||||
|
||||
FontStyle::FontStyle() {
|
||||
formatStartOffset = 0;
|
||||
height = 0;
|
||||
ascent = 0;
|
||||
|
||||
fontId = 0;
|
||||
textSlant = 0;
|
||||
|
||||
fontSize = 12;
|
||||
|
||||
r = g = b = 0;
|
||||
}
|
||||
|
||||
void FontStyle::read(Common::ReadStreamEndian &stream, Cast *cast) {
|
||||
formatStartOffset = stream.readUint32();
|
||||
uint16 originalHeight = height = stream.readUint16();
|
||||
ascent = stream.readUint16();
|
||||
|
||||
uint16 originalFontId = fontId = stream.readUint16();
|
||||
textSlant = stream.readByte();
|
||||
stream.readByte(); // padding
|
||||
fontSize = stream.readUint16();
|
||||
|
||||
r = stream.readUint16();
|
||||
g = stream.readUint16();
|
||||
b = stream.readUint16();
|
||||
|
||||
if (cast->_fontMap.contains(originalFontId)) {
|
||||
FontMapEntry *info = cast->_fontMap[originalFontId];
|
||||
fontId = info->toFont;
|
||||
if (info->sizeMap.contains(originalHeight)) {
|
||||
height = info->sizeMap[height];
|
||||
}
|
||||
}
|
||||
|
||||
debugC(3, kDebugLoading, "FontStyle::read(): formatStartOffset: %d, height: %d -> %d ascent: %d, fontId: %d -> %d, textSlant: %d, fontSize: %d, r: %x g: %x b: %x",
|
||||
formatStartOffset, originalHeight, height, ascent, originalFontId, fontId, textSlant, fontSize, r, g, b);
|
||||
}
|
||||
|
||||
void FontStyle::write(Common::SeekableWriteStream *writeStream) {
|
||||
debugC(3, kDebugSaving, "FontStyle::write(): formatStartOffset: %d, height: %d ascent: %d, fontId: %d, textSlant: %d, fontSize: %d, r: %x g: %x b: %x",
|
||||
formatStartOffset, height, ascent, fontId, textSlant, fontSize, r, g, b);
|
||||
|
||||
writeStream->writeUint32BE(formatStartOffset);
|
||||
writeStream->writeUint16BE(height);
|
||||
writeStream->writeUint16BE(ascent);
|
||||
writeStream->writeUint16BE(fontId);
|
||||
|
||||
writeStream->writeByte(textSlant);
|
||||
writeStream->writeByte(0); // padding
|
||||
writeStream->writeUint16BE(fontSize);
|
||||
|
||||
writeStream->writeUint16BE(r);
|
||||
writeStream->writeUint16BE(g);
|
||||
writeStream->writeUint16BE(b);
|
||||
}
|
||||
|
||||
} // End of namespace Director
|
||||
Reference in New Issue
Block a user