From c8526bf6c3a193cd41a41789eceb9dc155b85f5b Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 23 Oct 2011 12:51:33 -0400 Subject: PEGASUS: Add support for scaled/glowing images/movies --- engines/pegasus/movie.cpp | 44 +++++++++++++++++ engines/pegasus/movie.h | 23 +++++++++ engines/pegasus/surface.cpp | 114 +++++++++++++++++++++++++++++++++++++++++--- engines/pegasus/surface.h | 6 +++ 4 files changed, 181 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/pegasus/movie.cpp b/engines/pegasus/movie.cpp index fe152614d2..dbdb63fe52 100755 --- a/engines/pegasus/movie.cpp +++ b/engines/pegasus/movie.cpp @@ -202,4 +202,48 @@ void Movie::updateTime() { } } +GlowingMovie::GlowingMovie(const tDisplayElementID id) : Movie(id) { + _glowing = false; +} + +void GlowingMovie::draw(const Common::Rect &r) { + // Make sure the rectangles are clipped properly, OR guarantee that _bounds will + // never fall off the screen. + if (_glowing) { + Common::Rect bounds; + getBounds(bounds); + + copyToCurrentPortTransparentGlow(_movieBox, bounds); + } else { + Movie::draw(r); + } +} + +void GlowingMovie::setBounds(const Common::Rect &r) { + Common::Rect bounds; + getBounds(bounds); + + if (r != bounds) { + // Avoid Movie::setBounds. + // clone2727 asks why, but goes along with it + Animation::setBounds(r); + } +} + +ScalingMovie::ScalingMovie(const tDisplayElementID id) : GlowingMovie(id) { +} + +void ScalingMovie::draw(const Common::Rect &) { + // Make sure the rectangles are clipped properly, OR guarantee that _bounds will + // never fall off the screen. + + Common::Rect bounds; + getBounds(bounds); + + if (_glowing) + scaleTransparentCopyGlow(_movieBox, bounds); + else + scaleTransparentCopy(_movieBox, bounds); +} + } // End of namespace Pegasus diff --git a/engines/pegasus/movie.h b/engines/pegasus/movie.h index 704da0e92e..b248cc19d4 100755 --- a/engines/pegasus/movie.h +++ b/engines/pegasus/movie.h @@ -75,6 +75,29 @@ protected: Common::Rect _movieBox; }; +class GlowingMovie : public Movie { +public: + GlowingMovie(tDisplayElementID); + virtual ~GlowingMovie() {} + + virtual void draw(const Common::Rect &); + + void setBounds(const Common::Rect &); + + void setGlowing(const bool); + +protected: + bool _glowing; +}; + +class ScalingMovie : public GlowingMovie { +public: + ScalingMovie(tDisplayElementID); + virtual ~ScalingMovie() {} + + virtual void draw(const Common::Rect &); +}; + } // End of namespace Pegasus #endif diff --git a/engines/pegasus/surface.cpp b/engines/pegasus/surface.cpp index 69eeb31edf..2bf989588e 100755 --- a/engines/pegasus/surface.cpp +++ b/engines/pegasus/surface.cpp @@ -178,10 +178,6 @@ void Surface::copyToCurrentPort(const Common::Rect &srcRect, const Common::Rect } void Surface::copyToCurrentPortTransparent(const Common::Rect &srcRect, const Common::Rect &dstRect) const { - // HACK: Seems we're truncating some color data somewhere... - uint32 transColor1 = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff); - uint32 transColor2 = g_system->getScreenFormat().RGBToColor(0xf8, 0xf8, 0xf8); - Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface(); byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top); byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top); @@ -192,11 +188,11 @@ void Surface::copyToCurrentPortTransparent(const Common::Rect &srcRect, const Co for (int x = 0; x < srcRect.width(); x++) { if (g_system->getScreenFormat().bytesPerPixel == 2) { uint16 color = READ_UINT16(src); - if (color != transColor1 && color != transColor2) + if (!isTransparent(color)) memcpy(dst, src, 2); } else if (g_system->getScreenFormat().bytesPerPixel == 4) { uint32 color = READ_UINT32(src); - if (color != transColor1 && color != transColor2) + if (!isTransparent(color)) memcpy(dst, src, 4); } @@ -209,6 +205,112 @@ void Surface::copyToCurrentPortTransparent(const Common::Rect &srcRect, const Co } } +void Surface::copyToCurrentPortTransparentGlow(const Common::Rect &srcRect, const Common::Rect &dstRect) const { + // This is the same as copyToCurrentPortTransparent(), but turns the red value of each + // pixel all the way up. + + Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface(); + byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top); + byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top); + + int lineSize = srcRect.width() * _surface->format.bytesPerPixel; + + for (int y = 0; y < srcRect.height(); y++) { + for (int x = 0; x < srcRect.width(); x++) { + if (g_system->getScreenFormat().bytesPerPixel == 2) { + uint16 color = READ_UINT16(src); + if (!isTransparent(color)) + WRITE_UINT16(dst, getGlowColor(color)); + } else if (g_system->getScreenFormat().bytesPerPixel == 4) { + uint32 color = READ_UINT32(src); + if (!isTransparent(color)) + WRITE_UINT32(dst, getGlowColor(color)); + } + + src += g_system->getScreenFormat().bytesPerPixel; + dst += g_system->getScreenFormat().bytesPerPixel; + } + + src += _surface->pitch - lineSize; + dst += screen->pitch - lineSize; + } +} + +void Surface::scaleTransparentCopy(const Common::Rect &srcRect, const Common::Rect &dstRect) const { + // I'm doing simple linear scaling here + // dstRect(x, y) = srcRect(x * srcW / dstW, y * srcH / dstH); + + Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface(); + + int srcW = srcRect.width(); + int srcH = srcRect.height(); + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + for (int y = 0; y < dstH; y++) { + for (int x = 0; x < dstW; x++) { + if (g_system->getScreenFormat().bytesPerPixel == 2) { + uint16 color = READ_UINT16((byte *)_surface->getBasePtr( + x * srcW / dstW + srcRect.left, + y * srcH / dstH + srcRect.top)); + if (!isTransparent(color)) + WRITE_UINT16((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), color); + } else if (g_system->getScreenFormat().bytesPerPixel == 4) { + uint32 color = READ_UINT32((byte *)_surface->getBasePtr( + x * srcW / dstW + srcRect.left, + y * srcH / dstH + srcRect.top)); + if (!isTransparent(color)) + WRITE_UINT32((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), color); + } + } + } +} + +void Surface::scaleTransparentCopyGlow(const Common::Rect &srcRect, const Common::Rect &dstRect) const { + // This is the same as scaleTransparentCopy(), but turns the red value of each + // pixel all the way up. + + Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface(); + + int srcW = srcRect.width(); + int srcH = srcRect.height(); + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + for (int y = 0; y < dstH; y++) { + for (int x = 0; x < dstW; x++) { + if (g_system->getScreenFormat().bytesPerPixel == 2) { + uint16 color = READ_UINT16((byte *)_surface->getBasePtr( + x * srcW / dstW + srcRect.left, + y * srcH / dstH + srcRect.top)); + if (!isTransparent(color)) + WRITE_UINT16((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), getGlowColor(color)); + } else if (g_system->getScreenFormat().bytesPerPixel == 4) { + uint32 color = READ_UINT32((byte *)_surface->getBasePtr( + x * srcW / dstW + srcRect.left, + y * srcH / dstH + srcRect.top)); + if (!isTransparent(color)) + WRITE_UINT32((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), getGlowColor(color)); + } + } + } +} + +uint32 Surface::getGlowColor(uint32 color) const { + // Can't just 'or' it on like the original did :P + byte r, g, b; + g_system->getScreenFormat().colorToRGB(color, r, g, b); + return g_system->getScreenFormat().RGBToColor(0xff, g, b); +} + +bool Surface::isTransparent(uint32 color) const { + // HACK: Seems we're truncating some color data somewhere... + uint32 transColor1 = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff); + uint32 transColor2 = g_system->getScreenFormat().RGBToColor(0xf8, 0xf8, 0xf8); + + return color == transColor1 || color == transColor2; +} + PixelImage::PixelImage() { _transparent = false; } diff --git a/engines/pegasus/surface.h b/engines/pegasus/surface.h index c94ccdf0fc..9270de0665 100755 --- a/engines/pegasus/surface.h +++ b/engines/pegasus/surface.h @@ -70,6 +70,9 @@ public: void copyToCurrentPortTransparent(const Common::Rect &) const; void copyToCurrentPort(const Common::Rect &, const Common::Rect &) const; void copyToCurrentPortTransparent(const Common::Rect &, const Common::Rect &) const; + void copyToCurrentPortTransparentGlow(const Common::Rect &, const Common::Rect &) const; + void scaleTransparentCopy(const Common::Rect &, const Common::Rect &) const; + void scaleTransparentCopyGlow(const Common::Rect &, const Common::Rect &) const; virtual void getImageFromPICTFile(const Common::String &fileName); virtual void getImageFromPICTResource(Common::MacResManager *resFork, uint16 id); @@ -82,6 +85,9 @@ protected: private: void getImageFromPICTStream(Common::SeekableReadStream *stream); + + uint32 getGlowColor(uint32 color) const; + bool isTransparent(uint32 color) const; }; class PixelImage : public Surface { -- cgit v1.2.3