aboutsummaryrefslogtreecommitdiff
path: root/engines/director/frame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/director/frame.cpp')
-rw-r--r--engines/director/frame.cpp556
1 files changed, 380 insertions, 176 deletions
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index de0de6d4d0..eeecc0f29a 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -24,6 +24,7 @@
#include "graphics/font.h"
#include "graphics/macgui/macfontmanager.h"
#include "graphics/macgui/macwindowmanager.h"
+#include "graphics/primitives.h"
#include "image/bmp.h"
#include "director/director.h"
@@ -114,54 +115,61 @@ void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offs
}
void Frame::readChannels(Common::ReadStreamEndian *stream) {
- _actionId = stream->readByte();
- _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
- uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
-
- if (transFlags & 0x80)
- _transArea = 1;
- else
- _transArea = 0;
- _transDuration = transFlags & 0x7f;
-
- _transChunkSize = stream->readByte();
- _tempo = stream->readByte();
- _transType = static_cast<TransitionType>(stream->readByte());
- _sound1 = stream->readUint16();
- if (_vm->getPlatform() == Common::kPlatformMacintosh) {
- _sound2 = stream->readUint16();
- _soundType2 = stream->readByte();
- } else {
- byte unk[3];
- stream->read(unk, 3);
- warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]);
- }
- _skipFrameFlag = stream->readByte();
- _blend = stream->readByte();
+ byte unk[16];
- if (_vm->getPlatform() != Common::kPlatformMacintosh) {
- _sound2 = stream->readUint16();
- _soundType2 = stream->readByte();
- }
+ if (_vm->getVersion() < 4) {
+ _actionId = stream->readByte();
+ _soundType1 = stream->readByte(); // type: 0x17 for sounds (sound is cast id), 0x16 for MIDI (sound is cmd id)
+ uint8 transFlags = stream->readByte(); // 0x80 is whole stage (vs changed area), rest is duration in 1/4ths of a second
- uint16 palette = stream->readUint16();
+ if (transFlags & 0x80)
+ _transArea = 1;
+ else
+ _transArea = 0;
+ _transDuration = transFlags & 0x7f;
+
+ _transChunkSize = stream->readByte();
+ _tempo = stream->readByte();
+ _transType = static_cast<TransitionType>(stream->readByte());
+ _sound1 = stream->readUint16();
+ if (_vm->getPlatform() == Common::kPlatformMacintosh) {
+ _sound2 = stream->readUint16();
+ _soundType2 = stream->readByte();
+ } else {
+ stream->read(unk, 3);
+ warning("unk1: %x unk2: %x unk3: %x", unk[0], unk[1], unk[2]);
+ }
+ _skipFrameFlag = stream->readByte();
+ _blend = stream->readByte();
- if (palette) {
- warning("STUB: Palette info");
- }
+ if (_vm->getPlatform() != Common::kPlatformMacintosh) {
+ _sound2 = stream->readUint16();
+ _soundType2 = stream->readByte();
+ }
- debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+ uint16 palette = stream->readUint16();
- _palette = new PaletteInfo();
- _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
- _palette->lastColor = stream->readByte();
- _palette->flags = stream->readByte();
- _palette->speed = stream->readByte();
- _palette->frameCount = stream->readUint16();
+ if (palette) {
+ warning("STUB: Palette info");
+ }
+
+ debugC(kDebugLoading, 8, "%d %d %d %d %d %d %d %d %d %d %d", _actionId, _soundType1, _transDuration, _transChunkSize, _tempo, _transType, _sound1, _skipFrameFlag, _blend, _sound2, _soundType2);
+
+ _palette = new PaletteInfo();
+ _palette->firstColor = stream->readByte(); // for cycles. note: these start at 0x80 (for pal entry 0)!
+ _palette->lastColor = stream->readByte();
+ _palette->flags = stream->readByte();
+ _palette->speed = stream->readByte();
+ _palette->frameCount = stream->readUint16();
+
+ _palette->cycleCount = stream->readUint16();
+ } else if (_vm->getVersion() < 5) {
+ stream->read(unk, 16);
+ _actionId = stream->readUint16();
+ stream->read(unk, 5);
+ }
- _palette->cycleCount = stream->readUint16();
- byte unk[11];
stream->read(unk, 6);
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
@@ -181,8 +189,9 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
for (int i = 0; i < CHANNEL_COUNT; i++) {
Sprite &sprite = *_sprites[i + 1];
- sprite._x1 = stream->readByte();
- sprite._enabled = (stream->readByte() != 0);
+ sprite._scriptId = stream->readByte();
+ sprite._spriteType = stream->readByte();
+ sprite._enabled = sprite._spriteType != 0;
sprite._x2 = stream->readUint16();
sprite._flags = stream->readUint16();
@@ -193,14 +202,14 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
else
sprite._trails = 0;
+ sprite._lineSize = (sprite._flags >> 8) & 0x03;
+
sprite._castId = stream->readUint16();
sprite._startPoint.y = stream->readUint16();
sprite._startPoint.x = stream->readUint16();
sprite._height = stream->readUint16();
sprite._width = stream->readUint16();
- debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d]", sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height);
-
if (_vm->getPlatform() == Common::kPlatformMacintosh && _vm->getVersion() >= 4) {
sprite._scriptId = stream->readUint16();
sprite._flags2 = stream->readByte(); // 0x40 editable, 0x80 moveable
@@ -209,6 +218,11 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
if (_vm->getVersion() >= 5)
sprite._unk3 = stream->readUint32();
}
+
+ debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d/%d] script:%d",
+ sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags,
+ sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height,
+ sprite._lineSize, sprite._scriptId);
}
}
@@ -360,6 +374,7 @@ void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offse
}
void Frame::prepareFrame(Score *score) {
+ _drawRects.clear();
renderSprites(*score->_surface, false);
renderSprites(*score->_trailSurface, true);
@@ -529,85 +544,175 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail))
continue;
- Cast *cast;
- if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
- if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
- warning("Cast id %d not found", _sprites[i]->_castId);
- continue;
- } else {
- warning("Getting cast id %d from shared cast", _sprites[i]->_castId);
- cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+ CastType castType = kCastTypeNull;
+ Cast *cast = nullptr;
+ if (_vm->getVersion() < 4) {
+ switch (_sprites[i]->_spriteType) {
+ case 0x01:
+ castType = kCastBitmap;
+ break;
+ case 0x02:
+ case 0x0c: //this is actually a mouse-over shape? I don't think it's a real button.
+ castType = kCastShape;
+ break;
+ case 0x07:
+ castType = kCastText;
+ break;
}
} else {
- cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+ if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) {
+ if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) {
+ warning("Cast id %d not found", _sprites[i]->_castId);
+ continue;
+ } else {
+ warning("Getting cast id %d from shared cast", _sprites[i]->_castId);
+ cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId);
+ }
+ } else {
+ cast = _vm->_currentScore->_casts[_sprites[i]->_castId];
+ }
+ castType = cast->type;
}
- if (cast->type == kCastText) {
- renderText(surface, i);
- continue;
- }
+ //this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes.
+ //I don't like this implementation 100% as the 'cast' above might not actually hit a member and be null?
+ if (castType == kCastShape) {
+ renderShape(surface, i);
+ } else if (castType == kCastText) {
+ renderText(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index);
+ } else if (castType == kCastButton) {
+ renderButton(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index);
+ } else {
+ Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId);
- Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId);
+ if (!img) {
+ warning("Image with id %d not found", _sprites[i]->_castId);
+ continue;
+ }
- if (!img) {
- warning("Image with id %d not found", _sprites[i]->_castId);
- continue;
- }
+ if (!img->getSurface()) {
+ warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId);
+ continue;
+ }
- if (!img->getSurface()) {
- warning("Frame::renderSprites: Could not load image %d", _sprites[i]->_castId);
- continue;
- }
+ assert(_sprites[i]->_cast);
- assert(_sprites[i]->_cast);
-
- uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX;
- uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY;
- uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top;
-
- int x = _sprites[i]->_startPoint.x - regX + rectLeft;
- int y = _sprites[i]->_startPoint.y - regY + rectTop;
- int height = _sprites[i]->_height;
- int width = _sprites[i]->_width;
-
- Common::Rect drawRect = Common::Rect(x, y, x + width, y + height);
- _drawRects.push_back(drawRect);
-
- switch (_sprites[i]->_ink) {
- case kInkTypeCopy:
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
- case kInkTypeTransparent:
- // FIXME: is it always white (last entry in pallette)?
- surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1);
- break;
- case kInkTypeBackgndTrans:
- drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeMatte:
- drawMatteSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeGhost:
- drawGhostSprite(surface, *img->getSurface(), drawRect);
- break;
- case kInkTypeReverse:
- drawReverseSprite(surface, *img->getSurface(), drawRect);
- break;
- default:
- warning("Unhandled ink type %d", _sprites[i]->_ink);
- surface.blitFrom(*img->getSurface(), Common::Point(x, y));
- break;
+ BitmapCast *bitmapCast = static_cast<BitmapCast *>(_sprites[i]->_cast);
+ //TODO: might want a quicker way to determine if cast is from Shared Cast.
+ if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(_sprites[i]->_castId + 1024)) {
+ bitmapCast = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(_sprites[i]->_castId));
+ }
+
+ uint32 regX = bitmapCast->regX;
+ uint32 regY = bitmapCast->regY;
+ uint32 rectLeft = bitmapCast->initialRect.left;
+ uint32 rectTop = bitmapCast->initialRect.top;
+
+ int x = _sprites[i]->_startPoint.x - regX + rectLeft;
+ int y = _sprites[i]->_startPoint.y - regY + rectTop;
+ int height = _sprites[i]->_height;
+ int width = _sprites[i]->_width;
+
+ Common::Rect drawRect(x, y, x + width, y + height);
+
+ addDrawRect(i, drawRect);
+
+ switch (_sprites[i]->_ink) {
+ case kInkTypeCopy:
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ case kInkTypeTransparent:
+ // FIXME: is it always white (last entry in pallette)?
+ surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1);
+ break;
+ case kInkTypeBackgndTrans:
+ drawBackgndTransSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeMatte:
+ drawMatteSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeGhost:
+ drawGhostSprite(surface, *img->getSurface(), drawRect);
+ break;
+ case kInkTypeReverse:
+ drawReverseSprite(surface, *img->getSurface(), drawRect);
+ break;
+ default:
+ warning("Unhandled ink type %d", _sprites[i]->_ink);
+ surface.blitFrom(*img->getSurface(), Common::Point(x, y));
+ break;
+ }
}
}
}
}
-void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
- renderText(surface, spriteId);
+void Frame::addDrawRect(uint16 spriteId, Common::Rect &rect) {
+ FrameEntity *fi = new FrameEntity();
+ fi->spriteId = spriteId;
+ fi->rect = rect;
+ _drawRects.push_back(fi);
+}
+
+void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
+ Common::Rect shapeRect = Common::Rect(_sprites[spriteId]->_startPoint.x,
+ _sprites[spriteId]->_startPoint.y,
+ _sprites[spriteId]->_startPoint.x + _sprites[spriteId]->_width,
+ _sprites[spriteId]->_startPoint.y + _sprites[spriteId]->_height);
+
+ Graphics::ManagedSurface tmpSurface;
+ tmpSurface.create(shapeRect.width(), shapeRect.height(), Graphics::PixelFormat::createFormatCLUT8());
+ if (_vm->getVersion() <= 3 && _sprites[spriteId]->_spriteType == 0x0c) {
+ tmpSurface.fillRect(Common::Rect(shapeRect.width(), shapeRect.height()), 255);
+ tmpSurface.frameRect(Common::Rect(shapeRect.width(), shapeRect.height()), 0);
+ //TODO: don't override, work out how to display correctly.
+ _sprites[spriteId]->_ink = kInkTypeTransparent;
+ } else {
+ //No minus one on the pattern here! MacPlotData will do that for us!
+ Graphics::MacPlotData pd(&tmpSurface, &_vm->getPatterns(), _sprites[spriteId]->_castId, 1, _sprites[spriteId]->_backColor);
+ Common::Rect fillRect(shapeRect.width(), shapeRect.height());
+ Graphics::drawFilledRect(fillRect, _sprites[spriteId]->_foreColor, Graphics::macDrawPixel, &pd);
+ }
+
+ if (_sprites[spriteId]->_lineSize > 0) {
+ for (int rr = 0; rr < (_sprites[spriteId]->_lineSize - 1); rr++)
+ tmpSurface.frameRect(Common::Rect(rr, rr, shapeRect.width() - (rr * 2), shapeRect.height() - (rr * 2)), 0);
+ }
+
+ switch (_sprites[spriteId]->_ink) {
+ case kInkTypeCopy:
+ surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteId]->_startPoint.x, _sprites[spriteId]->_startPoint.y));
+ break;
+ case kInkTypeTransparent:
+ // FIXME: is it always white (last entry in pallette)?
+ surface.transBlitFrom(tmpSurface, Common::Point(_sprites[spriteId]->_startPoint.x, _sprites[spriteId]->_startPoint.y), _vm->getPaletteColorCount() - 1);
+ break;
+ case kInkTypeBackgndTrans:
+ drawBackgndTransSprite(surface, tmpSurface, shapeRect);
+ break;
+ case kInkTypeMatte:
+ drawMatteSprite(surface, tmpSurface, shapeRect);
+ break;
+ case kInkTypeGhost:
+ drawGhostSprite(surface, tmpSurface, shapeRect);
+ break;
+ case kInkTypeReverse:
+ drawReverseSprite(surface, tmpSurface, shapeRect);
+ break;
+ default:
+ warning("Unhandled ink type %d", _sprites[spriteId]->_ink);
+ surface.blitFrom(tmpSurface, Common::Point(_sprites[spriteId]->_startPoint.x, _sprites[spriteId]->_startPoint.y));
+ break;
+ }
+
+ addDrawRect(spriteId, shapeRect);
+}
+
+void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) {
+ renderText(surface, spriteId, _vm->getMainArchive()->getResource(MKTAG('S', 'T', 'X', 'T'), textId), true);
- uint16 castID = _sprites[spriteId]->_castId;
- ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]);
+ uint16 castId = _sprites[spriteId]->_castId;
+ ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castId]);
uint32 rectLeft = button->initialRect.left;
uint32 rectTop = button->initialRect.top;
@@ -617,13 +722,21 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
int height = _sprites[spriteId]->_height;
int width = _sprites[spriteId]->_width;
+ Common::Rect _rect;
+
switch (button->buttonType) {
case kTypeCheckBox:
// Magic numbers: checkbox square need to move left about 5px from text and 12px side size (D4)
- surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0);
+ _rect = Common::Rect(x - 17, y, x + 12, y + 12);
+ surface.frameRect(_rect, 0);
+ addDrawRect(spriteId, _rect);
break;
- case kTypeButton:
- surface.frameRect(Common::Rect(x, y, x + width, y + height), 0);
+ case kTypeButton: {
+ _rect = Common::Rect(x, y, x + width - 1, y + height + 5);
+ Graphics::MacPlotData pd(&surface, &_vm->getMacWindowManager()->getPatterns(), Graphics::MacGUIConstants::kPatternSolid, 1);
+ Graphics::drawRoundRect(_rect, 4, 0, false, Graphics::macDrawPixel, &pd);
+ addDrawRect(spriteId, _rect);
+ }
break;
case kTypeRadio:
warning("STUB: renderButton: kTypeRadio");
@@ -633,6 +746,10 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) {
Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
uint16 imgId = spriteId + 1024;
+
+ if (_vm->getVersion() >= 4 && _vm->_currentScore->_casts[spriteId]->children.size() > 0)
+ imgId = _vm->_currentScore->_casts[spriteId]->children[0].index;
+
Image::ImageDecoder *img = NULL;
if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) {
@@ -647,16 +764,31 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
return img;
}
- if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
- Common::SeekableReadStream *pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
+ Common::SeekableReadStream *pic = NULL;
+ BitmapCast *bc = NULL;
- if (_vm->getVersion() <= 4) {
- BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
+ pic = _vm->getSharedBMP()->getVal(imgId);
+ bc = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(spriteId));
+ } else if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) {
+ pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId);
+ bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ }
+
+ if (pic != NULL && bc != NULL) {
+ if (_vm->getVersion() < 4) {
int w = bc->initialRect.width(), h = bc->initialRect.height();
debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
img = new BITDDecoder(w, h);
+ } else if (_vm->getVersion() < 6) {
+ bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]);
+ int w = bc->initialRect.width(), h = bc->initialRect.height();
+
+ debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d",
+ imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2);
+ img = new BITDDecoderV4(w, h, bc->bitsPerPixel);
} else {
img = new Image::BitmapDecoder();
}
@@ -666,34 +798,37 @@ Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) {
byte buf[1024];
int n = s->read(buf, 1024);
Common::hexdump(buf, n);
+ s->seek(0);
}
img->loadStream(*pic);
return img;
}
- if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) {
- img = new Image::BitmapDecoder();
- img->loadStream(*_vm->getSharedBMP()->getVal(imgId));
- return img;
- }
-
warning("Image %d not found", spriteId);
return img;
}
-void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
- uint16 castID = _sprites[spriteID]->_castId;
-
- TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
- Common::SeekableSubReadStreamEndian *textStream;
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 castId) {
+ Common::SeekableSubReadStreamEndian *textStream = NULL;
- if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) {
- textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024);
- } else {
- textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
+ if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S', 'T', 'X', 'T'), castId)) {
+ textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S', 'T', 'X', 'T'), castId);
+ } else if (_vm->getSharedSTXT() != nullptr) {
+ textStream = _vm->getSharedSTXT()->getVal(spriteId + 1024);
}
+
+ renderText(surface, spriteId, textStream, false);
+}
+
+void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Common::SeekableSubReadStreamEndian *textStream, bool isButtonLabel) {
+ if (textStream == NULL)
+ return;
+
+ uint16 castId = _sprites[spriteId]->_castId;
+ TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castId]);
+
uint32 unk1 = textStream->readUint32();
uint32 strLen = textStream->readUint32();
uint32 dataLen = textStream->readUint32();
@@ -711,63 +846,133 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
if (strLen < 200)
debugC(3, kDebugText, "text: '%s'", text.c_str());
- uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
- uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;
+ uint16 a = textStream->readUint16();
+ uint32 b = textStream->readUint32();
+ uint16 c = textStream->readUint16();
+ uint16 d = textStream->readUint16();
+
+ debugC(3, kDebugText, "text: a: %x b: %x c: %x d: %x", a, b, c, d);
+
+ textCast->fontId = textStream->readUint16();
+ textCast->textSlant = textStream->readByte();
+ textStream->readByte();
+ textCast->fontSize = textStream->readUint16();
+
+ textCast->palinfo1 = textStream->readUint16();
+ textCast->palinfo2 = textStream->readUint16();
+ textCast->palinfo3 = textStream->readUint16();
+
+ uint16 boxShadow = (uint16)textCast->boxShadow;
+ uint16 borderSize = (uint16)textCast->borderSize;
+ uint16 padding = (uint16)textCast->gutterSize;
+ uint16 textShadow = (uint16)textCast->textShadow;
+
+ //uint32 rectLeft = textCast->initialRect.left;
+ //uint32 rectTop = textCast->initialRect.top;
+
+ int x = _sprites[spriteId]->_startPoint.x; // +rectLeft;
+ int y = _sprites[spriteId]->_startPoint.y; // +rectTop;
+
+ int height = _sprites[spriteId]->_height;
+ if (_vm->getVersion() >= 4 && !isButtonLabel) height = textCast->initialRect.bottom;
+ height += textShadow;
- int x = _sprites[spriteID]->_startPoint.x + rectLeft;
- int y = _sprites[spriteID]->_startPoint.y + rectTop;
- int height = _sprites[spriteID]->_height;
- int width = _sprites[spriteID]->_width;
+ int width = _sprites[spriteId]->_width;
+ if (_vm->getVersion() >= 4 && !isButtonLabel) width = textCast->initialRect.right;
- Graphics::MacFont macFont(textCast->fontId, textCast->fontSize);
+ Graphics::MacFont macFont(textCast->fontId, textCast->fontSize, textCast->textSlant);
if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
// Override
- macFont.setName(_vm->_currentScore->_fontMap[textCast->fontId]);
+ //macFont.setName(_vm->_currentScore->_fontMap[textCast->fontId]);
+ //TODO: this still needs to take font style and size into account!
}
const Graphics::Font *font = _vm->_wm->_fontMan->getFont(macFont);
- debugC(3, kDebugText, "renderText: x: %d y: %d w: %d h: %d font: '%s'", x, y, width, height, _vm->_wm->_fontMan->getFontName(macFont));
+ height = font->getFontHeight();
- font->drawString(&surface, text, x, y, width, 0);
+ debugC(3, kDebugText, "renderText: x: %d y: %d w: %d h: %d font: '%s'", x, y, width, height, _vm->_wm->_fontMan->getFontName(macFont));
- if (textCast->borderSize != kSizeNone) {
- uint16 size = textCast->borderSize;
+ int alignment = (int)textCast->textAlign;
+ if (alignment == -1)
+ alignment = 3;
+ else
+ alignment++;
+
+ uint16 textX = x, textY = y;
+ if (!isButtonLabel) {
+ if (borderSize > 0) {
+ if (_vm->getVersion() <= 3)
+ height++;
+ else
+ height += borderSize;
+
+ textX += (borderSize + 1);
+ textY += borderSize;
+ } else
+ textX += 1;
+
+ if (padding > 0) {
+ width += padding * 2;
+ height += padding;
+
+ if (textCast->textAlign == kTextAlignLeft)
+ textX += padding;
+ else if (textCast->textAlign == kTextAlignRight)
+ textX -= padding;
+
+ //TODO: alignment issue with odd-size-width center-aligned text
+ //else if (textCast->textAlign == kTextAlignCenter && ((borderSize + padding) % 2 == 1)) textX--;
+
+ textY += padding / 2;
+ }
- // Indent from borders, measured in d4
- x -= 1;
- y -= 4;
+ if (textCast->textAlign == kTextAlignRight)
+ textX -= 1;
- height += 4;
- width += 1;
+ if (textShadow > 0) {
+ if (borderSize == 0 && _vm->getVersion() > 3)
+ textX += 1;
- while (size) {
- surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
- x--;
- y--;
- height += 2;
- width += 2;
- size--;
+ font->drawString(&surface, text, textX + textShadow, textY + textShadow,
+ width, (_sprites[spriteId]->_ink == kInkTypeReverse ? 255 : 0), (Graphics::TextAlign)alignment);
+ if (_vm->getVersion() > 3)
+ height -= (textShadow - 1);
}
+ } else {
+ textY += 2;
}
- if (textCast->gutterSize != kSizeNone) {
- x -= 1;
- y -= 4;
-
- height += 4;
- width += 1;
- uint16 size = textCast->gutterSize;
-
- surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
+ //TODO: the colour is wrong here... need to determine the correct colour for all versions!
+ font->drawString(&surface, text, textX, textY,
+ width, (_sprites[spriteId]->_ink == kInkTypeReverse ? 255 : 0), (Graphics::TextAlign)alignment);
+
+ if (isButtonLabel)
+ return;
+
+ uint16 borderX = x + borderSize - 1, borderY = y + borderSize - 1, borderHeight = height, borderWidth = width;
+ if (borderSize != kSizeNone) {
+ while (borderSize) {
+ borderWidth += 2;
+ borderHeight += 2;
+ surface.frameRect(Common::Rect(borderX, borderY, borderX + borderWidth, borderY + borderHeight), 0);
+ borderSize--;
+ borderX--;
+ borderY--;
+ }
+ }
- while (size) {
- surface.drawLine(x + width, y, x + width, y + height, 0);
- surface.drawLine(x, y + height, x + width, y + height, 0);
- x++;
- y++;
- size--;
+ if (boxShadow > 0) {
+ borderSize = (uint16)textCast->borderSize;
+ uint baseOffsetX = x + boxShadow;
+ uint baseOffsetY = y + height + (borderSize * 2);
+ uint sideOffsetX = x + borderWidth;
+ uint sideOffsetY = y + boxShadow;
+ while (boxShadow) {
+ surface.drawLine(baseOffsetX, baseOffsetY + (boxShadow - 1), baseOffsetX + borderWidth - 1, baseOffsetY + (boxShadow - 1), 0);
+ surface.drawLine(sideOffsetX + (boxShadow - 1), sideOffsetY, sideOffsetX + (boxShadow - 1), sideOffsetY + borderHeight - 1, 0);
+ boxShadow--;
}
}
}
@@ -883,11 +1088,10 @@ void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Su
}
uint16 Frame::getSpriteIDFromPos(Common::Point pos) {
- // Find first from top to bottom
- for (uint16 i = _drawRects.size() - 1; i > 0; i--) {
- if (_drawRects[i].contains(pos))
- return i;
- }
+ // Find first from front to back
+ for (int dr = _drawRects.size() - 1; dr >= 0; dr--)
+ if (_drawRects[dr]->rect.contains(pos))
+ return _drawRects[dr]->spriteId;
return 0;
}