DIRECTOR: Fix coloring of 1-bit bitmaps

If a channel contains a 1-bit bitmap cast member, use the foreground
color instead of black when rendering in Background Transparent mode.

Fixes various text bitmaps in Total Distortion and iD4 Mission Disk 1.
This commit is contained in:
Scott Percival 2022-10-29 01:00:11 +08:00 committed by Eugene Sandulenko
parent 90e8341f67
commit 1524ee3615
6 changed files with 34 additions and 17 deletions

View File

@ -112,6 +112,12 @@ DirectorPlotData Channel::getPlotData() {
pd.dst = nullptr;
pd.srf = getSurface();
if (_sprite->_spriteType == kBitmapSprite &&
_sprite->_cast && _sprite->_cast->_type == kCastBitmap &&
((BitmapCastMember *)_sprite->_cast)->_bitsPerPixel == 1) {
// Add override flag for 1-bit images
pd.oneBitImage = true;
}
if (!pd.srf && _sprite->_spriteType != kBitmapSprite) {
// Shapes come colourized from macDrawPixel
pd.ms = _sprite->getShape();

View File

@ -285,24 +285,25 @@ public:
// An extension of MacPlotData for interfacing with inks and patterns without
// needing extra surfaces.
struct DirectorPlotData {
DirectorEngine *d;
Graphics::ManagedSurface *dst;
DirectorEngine *d = nullptr;
Graphics::ManagedSurface *dst = nullptr;
Common::Rect destRect;
Common::Point srcPoint;
Graphics::ManagedSurface *srf;
MacShape *ms;
Graphics::ManagedSurface *srf = nullptr;
MacShape *ms = nullptr;
SpriteType sprite;
InkType ink;
SpriteType sprite = kInactiveSprite;
bool oneBitImage = false;
InkType ink = kInkTypeCopy;
uint32 colorWhite;
uint32 colorBlack;
int alpha;
int alpha = 0;
uint32 backColor;
uint32 foreColor;
bool applyColor;
bool applyColor = false;
// graphics.cpp
void setApplyColor();
@ -312,12 +313,8 @@ struct DirectorPlotData {
void inkBlitStretchSurface(Common::Rect &srcRect, const Graphics::Surface *mask);
DirectorPlotData(DirectorEngine *d_, SpriteType s, InkType i, int a, uint32 b, uint32 f) : d(d_), sprite(s), ink(i), alpha(a), backColor(b), foreColor(f) {
srf = nullptr;
ms = nullptr;
dst = nullptr;
colorWhite = d->_wm->_colorWhite;
colorBlack = d->_wm->_colorBlack;
applyColor = false;
}
DirectorPlotData(const DirectorPlotData &old) : d(old.d), sprite(old.sprite),

View File

@ -127,7 +127,7 @@ void Frame::readChannel(Common::SeekableReadStreamEndian &stream, uint16 offset,
}
}
void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
void Frame::readChannels(Common::SeekableReadStreamEndian *stream, uint16 version) {
byte unk[24];
if (version < kFileVer400) {
@ -181,6 +181,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
debugC(8, kDebugLoading, "Frame::readChannels(): STUB: unk1: %02x %02x %02x %02x %02x %02x", unk[0],
unk[1], unk[2], unk[3], unk[4], unk[5]);
} else if (version >= kFileVer400 && version < kFileVer500) {
if (debugChannelSet(8, kDebugLoading)) {
debugC(8, kDebugLoading, "Frame::readChannels(): 40 byte header");
stream->hexdump(40);
}
// Sound/Tempo/Transition
int unk1 = stream->readByte();
if (unk1) {
@ -272,6 +276,10 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
Sprite &sprite = *_sprites[i + 1];
if (version < kFileVer500) {
if (debugChannelSet(8, kDebugLoading)) {
debugC(8, kDebugLoading, "Frame::readChannels(): channel %d, 22 bytes", i);
stream->hexdump(22);
}
sprite._scriptId = CastMemberID(stream->readByte(), 0);
sprite._spriteType = (SpriteType)stream->readByte();
sprite._enabled = sprite._spriteType != kInactiveSprite;
@ -402,7 +410,7 @@ Common::String Frame::formatChannelInfo() {
for (int i = 0; i < _numChannels; i++) {
Sprite &sprite = *_sprites[i + 1];
if (sprite._castId.member) {
result += Common::String::format("CH: %-3d castId: %s [inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x\n",
result += Common::String::format("CH: %-3d castId: %s, [inkData: 0x%02x [ink: %d, trails: %d, line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d], script: %s, flags2: 0x%x, unk2: 0x%x, unk3: 0x%x\n",
i + 1, sprite._castId.asString().c_str(), sprite._inkData,
sprite._ink, sprite._trails, sprite._thickness, sprite._width, sprite._height,
sprite._startPoint.x, sprite._startPoint.y,

View File

@ -91,7 +91,7 @@ public:
Score *getScore() const { return _score; }
void readChannels(Common::ReadStreamEndian *stream, uint16 version);
void readChannels(Common::SeekableReadStreamEndian *stream, uint16 version);
void readChannel(Common::SeekableReadStreamEndian &stream, uint16 offset, uint16 size);
void executeImmediateScripts();

View File

@ -288,7 +288,13 @@ void inkDrawPixel(int x, int y, int src, void *data) {
switch (p->ink) {
case kInkTypeBackgndTrans:
*dst = (src == (int)p->backColor) ? *dst : src;
if (p->oneBitImage) {
// One-bit images have a slightly different rendering algorithm for BackgndTrans.
// Foreground colour is used, and background colour is ignored.
*dst = (src == (int)p->colorBlack) ? p->foreColor : *dst;
} else {
*dst = (src == (int)p->backColor) ? *dst : src;
}
break;
case kInkTypeMatte:
// fall through

View File

@ -1398,7 +1398,7 @@ Common::String Score::formatChannelInfo() {
Channel &channel = *_channels[i + 1];
Sprite &sprite = *channel._sprite;
if (sprite._castId.member) {
result += Common::String::format("CH: %-3d castId: %s, visible:%d,[inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x, constraint: %d, puppet: %d, stretch: %d\n",
result += Common::String::format("CH: %-3d castId: %s, visible: %d, [inkData: 0x%02x [ink: %d, trails: %d, line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d], script: %s, flags2: 0x%x, unk2: 0x%x, unk3: 0x%x, constraint: %d, puppet: %d, stretch: %d\n",
i + 1, sprite._castId.asString().c_str(), channel._visible, sprite._inkData,
sprite._ink, sprite._trails, sprite._thickness, channel._width, channel._height,
channel._currentPoint.x, channel._currentPoint.y,