Skip to content

Commit

Permalink
PEGASUS: Add support for scaled/glowing images/movies
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Hoops committed Oct 23, 2011
1 parent f9ecab1 commit c8526bf
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 6 deletions.
44 changes: 44 additions & 0 deletions engines/pegasus/movie.cpp
Expand Up @@ -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
23 changes: 23 additions & 0 deletions engines/pegasus/movie.h
Expand Up @@ -75,6 +75,29 @@ class Movie : public Animation, public PixelImage {
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
114 changes: 108 additions & 6 deletions engines/pegasus/surface.cpp
Expand Up @@ -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);
Expand All @@ -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);
}

Expand All @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions engines/pegasus/surface.h
Expand Up @@ -70,6 +70,9 @@ class Surface {
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);
Expand All @@ -82,6 +85,9 @@ class Surface {

private:
void getImageFromPICTStream(Common::SeekableReadStream *stream);

uint32 getGlowColor(uint32 color) const;
bool isTransparent(uint32 color) const;
};

class PixelImage : public Surface {
Expand Down

0 comments on commit c8526bf

Please sign in to comment.