diff options
Diffstat (limited to 'engines/director/frame.cpp')
-rw-r--r-- | engines/director/frame.cpp | 556 |
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; } |