mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
DIRECTOR: Extend Reverse Sprite drawing for shapes and controls.
Translate 32-bit images into palette-based sprites.
This commit is contained in:
+41
-18
@@ -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++;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user