DIRECTOR: Extend Reverse Sprite drawing for shapes and controls.

Translate 32-bit images into palette-based sprites.
This commit is contained in:
stevenhoefel
2020-04-10 22:38:12 +10:00
parent bd992479b3
commit 40501547f4
5 changed files with 113 additions and 52 deletions
+41 -18
View File
@@ -650,7 +650,7 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) {
int width = _vm->getVersion() > 4 ? bc->_initialRect.width() : _sprites[i]->_width;
Common::Rect drawRect(x, y, x + width, y + height);
addDrawRect(i, drawRect);
inkBasedBlit(surface, *(bc->_surface), ink, drawRect);
inkBasedBlit(surface, *(bc->_surface), ink, drawRect, i);
}
}
}
@@ -671,9 +671,7 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
byte backColor = sp->_backColor;
int lineSize = sp->_thickness & 0x3;
// D3 Shared Cast Members don't have these values specified, they're provided when you add
// them to the score in each movie.
if (_vm->getVersion() > 3 && spriteType == kCastMemberSprite) {
if (_vm->getVersion() >= 3 && spriteType == kCastMemberSprite) {
if (!sp->_cast) {
warning("Frame::renderShape(): kCastMemberSprite has no cast defined");
return;
@@ -698,10 +696,12 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
default:
break;
}
foreColor = sc->_fgCol;
backColor = sc->_bgCol;
lineSize = sc->_lineThickness;
ink = sc->_ink;
if (_vm->getVersion() > 3) {
foreColor = sc->_fgCol;
backColor = sc->_bgCol;
lineSize = sc->_lineThickness;
ink = sc->_ink;
}
// shapes should be rendered with transparency by default
if (ink == kInkTypeCopy) {
ink = kInkTypeTransparent;
@@ -778,7 +778,7 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) {
}
addDrawRect(spriteId, shapeRect);
inkBasedBlit(surface, tmpSurface, ink, shapeRect);
inkBasedBlit(surface, tmpSurface, ink, shapeRect, spriteId);
}
@@ -1025,10 +1025,10 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo
if (spriteId == _vm->getCurrentScore()->_currentMouseDownSpriteId)
ink = kInkTypeReverse;
inkBasedBlit(surface, textWithFeatures, ink, Common::Rect(x, y, x + width, y + height));
inkBasedBlit(surface, textWithFeatures, ink, Common::Rect(x, y, x + width, y + height), spriteId);
}
void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect) {
void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId) {
// drawRect could be bigger than the spriteSurface. Clip it
Common::Rect t(spriteSurface.w, spriteSurface.h);
t.moveTo(drawRect.left, drawRect.top);
@@ -1052,7 +1052,7 @@ void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics
drawGhostSprite(targetSurface, spriteSurface, drawRect);
break;
case kInkTypeReverse:
drawReverseSprite(targetSurface, spriteSurface, drawRect);
drawReverseSprite(targetSurface, spriteSurface, drawRect, spriteId);
break;
default:
warning("Frame::inkBasedBlit(): Unhandled ink type %d", ink);
@@ -1103,7 +1103,7 @@ void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Su
}
}
void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) {
void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId) {
Common::Rect srcRect(sprite.w, sprite.h);
if (!target.clip(srcRect, drawRect))
@@ -1113,14 +1113,37 @@ void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::
for (int ii = 0; ii < srcRect.height(); ii++) {
const byte *src = (const byte *)sprite.getBasePtr(srcRect.left, srcRect.top + ii);
byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii);
byte srcColor = *src;
for (int j = 0; j < srcRect.width(); j++) {
if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0)) {
if (*src != skipColor) {
*dst ^= _vm->transformColor(*src);
if (_sprites[spriteId]->_cast->_type == kCastShape)
srcColor = 0x0;
else
srcColor = *src;
uint16 targetSprite = getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii));
if ((targetSprite != 0)) {
// TODO: This entire reverse colour attempt needs a lot more testing on
// a lot more colour depths.
if (srcColor != skipColor) {
if (_sprites[targetSprite]->_cast->_type != kCastBitmap) {
if (*dst == 0 || *dst == 255) {
*dst = _vm->transformColor(*dst);
} else if (srcColor == 255 || srcColor == 0) {
*dst = _vm->transformColor(*dst - 40);
} else {
*dst = _vm->transformColor(*src - 40);
}
} else {
if (*dst == 0 && _vm->getVersion() == 3 &&
((BitmapCast*)_sprites[spriteId]->_cast)->_bitsPerPixel > 1) {
*dst = _vm->transformColor(*src - 40);
} else {
*dst ^= _vm->transformColor(srcColor);
}
}
}
} else if (*src != skipColor) {
*dst = *src;
} else if (srcColor != skipColor) {
*dst = _vm->transformColor(srcColor);
}
src++;
dst++;
+2 -2
View File
@@ -94,8 +94,8 @@ private:
void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect);
void inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect);
void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect, uint16 spriteId);
void inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, InkType ink, Common::Rect drawRect, uint spriteId);
void addDrawRect(uint16 entityId, Common::Rect &rect);
public:
+66 -29
View File
@@ -103,7 +103,7 @@ bool DIBDecoder::loadStream(Common::SeekableReadStream &stream) {
* BITD
****************************/
BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch) {
BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch, const byte *palette) {
_surface = new Graphics::Surface();
if (pitch < w) {
@@ -133,12 +133,10 @@ BITDDecoder::BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch) {
_surface->create(pitch, h, pf);
_surface->w = w;
_palette = new byte[256 * 3];
_palette = palette;
_palette[0] = _palette[1] = _palette[2] = 0;
_palette[255 * 3 + 0] = _palette[255 * 3 + 1] = _palette[255 * 3 + 2] = 0xff;
_paletteColorCount = 2;
// TODO: Bring this in from the main surface?
_paletteColorCount = 255;
_bitsPerPixel = bitsPerPixel;
}
@@ -152,8 +150,6 @@ void BITDDecoder::destroy() {
delete _surface;
_surface = 0;
delete[] _palette;
_palette = 0;
_paletteColorCount = 0;
}
@@ -161,6 +157,42 @@ void BITDDecoder::loadPalette(Common::SeekableReadStream &stream) {
// no op
}
void BITDDecoder::convertPixelIntoSurface(void* surfacePointer, uint fromBpp, uint toBpp, int red, int green, int blue) {
// Initial implementation of 32-bit images to palettised sprites.
switch (fromBpp) {
case 4:
switch (toBpp) {
case 1:
if (red == 255 && blue == 255 && green == 255) {
*((byte*)surfacePointer) = 255;
} else if (red == 0 && blue == 0 && green == 0) {
*((byte*)surfacePointer) = 0;
} else {
for (byte p = 0; p < _paletteColorCount; p++)
{
if (_palette[p * 3 + 0] == red &&
_palette[p * 3 + 1] == green &&
_palette[p * 3 + 2] == blue)
{
*((byte*)surfacePointer) = p;
}
}
}
break;
default:
warning("BITDDecoder::convertPixelIntoSurface(): conversion from %d to %d not implemented",
fromBpp, toBpp);
}
break;
default:
warning("BITDDecoder::convertPixelIntoSurface(): could not convert from %d to %d",
fromBpp, toBpp);
break;
}
}
bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
int x = 0, y = 0;
@@ -180,26 +212,30 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
}
Common::Array<int> pixels;
while (!stream.eos()) {
int data = stream.readByte();
int len = data + 1;
if ((data & 0x80) != 0) {
len = ((data ^ 0xFF) & 0xff) + 2;
data = stream.readByte();
for (int p = 0; p < len; p++) {
pixels.push_back(data);
//*((byte *)_surface->getBasePtr(x, y)) = data;
}
//data = stream.readByte();
// TODO: D3 32-bit bitmap casts seem to just be ARGB pixels in a row and not RLE.
// Determine how to distinguish these different types. Maybe stage version.
if (_bitsPerPixel == 32) {
int data = stream.readByte();
pixels.push_back(data);
} else {
for (int p = 0; p < len; p++) {
int data = stream.readByte();
int len = data + 1;
if ((data & 0x80) != 0) {
len = ((data ^ 0xFF) & 0xff) + 2;
data = stream.readByte();
pixels.push_back(data);
for (int p = 0; p < len; p++) {
pixels.push_back(data);
}
} else {
for (int p = 0; p < len; p++) {
data = stream.readByte();
pixels.push_back(data);
}
}
if (_bitsPerPixel == 32 && pixels.size() % (_surface->w * 3) == 0)
stream.readUint16BE();
}
if (_bitsPerPixel == 32 && pixels.size() % (_surface->w * 3) == 0)
stream.readUint16BE();
}
if (pixels.size() < (uint32)_surface->w * _surface->h) {
@@ -220,12 +256,11 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
for (y = 0; y < _surface->h; y++) {
for (x = 0; x < _surface->w;) {
switch (_bitsPerPixel) {
case 1: {
case 1:
for (int c = 0; c < 8 && x < _surface->w; c++, x++) {
*((byte *)_surface->getBasePtr(x, y)) = (pixels[(((y * _surface->pitch) + x) / 8)] & (1 << (7 - c))) ? 0 : 0xff;
}
break;
}
case 8:
// this calculation is wrong.. need a demo with colours.
@@ -243,10 +278,12 @@ bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) {
break;
case 32:
*((uint32*)_surface->getBasePtr(x, y)) = _surface->format.RGBToColor(
pixels[((y * _surface->w) * 3) + x],
pixels[(((y * _surface->w) * 3) + (_surface->w)) + x],
pixels[(((y * _surface->w) * 3) + (2 * _surface->w)) + x]);
convertPixelIntoSurface(_surface->getBasePtr(x, y),
(_bitsPerPixel / 8),
_surface->format.bytesPerPixel,
pixels[(((y * (_surface->w * 4))) + ((x * 4) + 1))],
pixels[(((y * (_surface->w * 4))) + ((x * 4) + 2))],
pixels[(((y * (_surface->w * 4))) + ((x * 4) + 3))]);
x++;
break;
+3 -2
View File
@@ -61,7 +61,7 @@ private:
class BITDDecoder : public Image::ImageDecoder {
public:
BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch);
BITDDecoder(int w, int h, uint16 bitsPerPixel, uint16 pitch, const byte *palette);
~BITDDecoder() override;
// ImageDecoder API
@@ -71,10 +71,11 @@ public:
const byte *getPalette() const override { return _palette; }
void loadPalette(Common::SeekableReadStream &stream);
uint16 getPaletteColorCount() const override { return _paletteColorCount; }
void convertPixelIntoSurface(void* surfacePointer, uint fromBpp, uint toBpp, int red, int green, int blue);
private:
Graphics::Surface *_surface;
byte *_palette;
const byte *_palette;
uint8 _paletteColorCount;
uint16 _bitsPerPixel;
};
+1 -1
View File
@@ -376,7 +376,7 @@ void Score::loadSpriteImages(bool isSharedCast) {
if (w > 0 && h > 0) {
if (_vm->getVersion() < 6) {
img = new BITDDecoder(w, h, bitmapCast->_bitsPerPixel, bitmapCast->_pitch);
img = new BITDDecoder(w, h, bitmapCast->_bitsPerPixel, bitmapCast->_pitch, _vm->getPalette());
} else {
img = new Image::BitmapDecoder();
}