From 352653b8a2d491f9c1bc514a17ec720a31f71e3d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sun, 5 Jul 2020 22:17:03 +0100 Subject: [PATCH] GRAPHICS: Add a function for scaling a standard Graphics::Surface This also makes use of it in the SCI and Wintermute engines --- engines/sci/graphics/video32.cpp | 9 ++------- .../wintermute/base/base_persistence_manager.cpp | 5 +---- engines/wintermute/base/gfx/base_image.cpp | 10 ++++------ .../wintermute/base/gfx/osystem/render_ticket.cpp | 8 +------- graphics/surface.cpp | 15 +++++++++++++++ graphics/surface.h | 13 +++++++++++++ graphics/transparent_surface.cpp | 11 ++--------- graphics/transparent_surface.h | 6 ++---- 8 files changed, 40 insertions(+), 37 deletions(-) diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp index 6b8f9e54b52..5b164bc9a08 100644 --- a/engines/sci/graphics/video32.cpp +++ b/engines/sci/graphics/video32.cpp @@ -30,7 +30,6 @@ #include "common/system.h" // for g_system #include "engines/engine.h" // for Engine, g_engine #include "graphics/palette.h" // for PaletteManager -#include "graphics/transparent_surface.h" // for TransparentSurface #include "sci/console.h" // for Console #include "sci/engine/features.h" // for GameFeatures #include "sci/engine/state.h" // for EngineState @@ -242,20 +241,16 @@ void VideoPlayer::renderFrame(const Graphics::Surface &nextFrame) const { if (_decoder->getWidth() != _drawRect.width() || _decoder->getHeight() != _drawRect.height()) { Graphics::Surface *const unscaledFrame(convertedFrame); - // TODO: The only reason TransparentSurface is used here because it is - // where common scaler code is right now, which should just be part of - // Graphics::Surface (or some free functions). - const Graphics::TransparentSurface tsUnscaledFrame(*unscaledFrame); #ifdef USE_RGB_COLOR if (_hqVideoMode) { - convertedFrame = tsUnscaledFrame.scaleT(_drawRect.width(), _drawRect.height()); + convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), true); } else { #elif 1 { #else } #endif - convertedFrame = tsUnscaledFrame.scaleT(_drawRect.width(), _drawRect.height()); + convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), false); } assert(convertedFrame); if (freeConvertedFrame) { diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp index 5a694e7ce25..ad38f5d529f 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -36,7 +36,6 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/save_thumb_helper.h" #include "engines/wintermute/base/sound/base_sound.h" -#include "graphics/transparent_surface.h" #include "engines/wintermute/wintermute.h" #include "graphics/scaler.h" #include "image/bmp.h" @@ -173,11 +172,9 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des Image::BitmapDecoder bmpDecoder; if (bmpDecoder.loadStream(thumbStream)) { const Graphics::Surface *bmpSurface = bmpDecoder.getSurface(); - Graphics::TransparentSurface *scaleableSurface = new Graphics::TransparentSurface(*bmpSurface, false); - Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2); + Graphics::Surface *scaled = bmpSurface->scale(kThumbnailWidth, kThumbnailHeight2); Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat()); desc.setThumbnail(thumb); - delete scaleableSurface; scaled->free(); delete scaled; } diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp index a1548b83ead..963de43fc8f 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -28,7 +28,6 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/base_file_manager.h" -#include "graphics/transparent_surface.h" #include "graphics/surface.h" #include "image/png.h" #include "image/jpeg.h" @@ -112,14 +111,13 @@ bool BaseImage::saveBMPFile(const Common::String &filename) const { ////////////////////////////////////////////////////////////////////////// bool BaseImage::resize(int newWidth, int newHeight) { // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - Graphics::TransparentSurface temp(*_surface, true); + Graphics::Surface *temp = _surface->scale((uint16)newWidth, (uint16)newHeight); if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; _deletableSurface = nullptr; } - _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); - temp.free(); + _surface = _deletableSurface = temp; return true; } @@ -216,13 +214,13 @@ bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const { bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - Graphics::TransparentSurface temp(*origImage->_surface, false); + Graphics::Surface *temp = origImage->_surface->scale((uint16)newWidth, (uint16)newHeight); if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; _deletableSurface = nullptr; } - _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); + _surface = _deletableSurface = temp; return true; } diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index e092e3cf173..d5297d6529c 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -72,13 +72,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s } else if ((dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) && _transform._numTimesX * _transform._numTimesY == 1) { - Graphics::TransparentSurface src(*_surface, false); - Graphics::Surface *temp; - if (owner->_gameRef->getBilinearFiltering()) { - temp = src.scaleT(dstRect->width(), dstRect->height()); - } else { - temp = src.scaleT(dstRect->width(), dstRect->height()); - } + Graphics::Surface *temp = _surface->scale(dstRect->width(), dstRect->height(), owner->_gameRef->getBilinearFiltering()); _surface->free(); delete _surface; _surface = temp; diff --git a/graphics/surface.cpp b/graphics/surface.cpp index e2e3401cc23..d389f139efa 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -368,6 +368,21 @@ void Surface::flipVertical(const Common::Rect &r) { delete[] temp; } +Graphics::Surface *Surface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const { + + Graphics::Surface *target = new Graphics::Surface(); + + target->create(newWidth, newHeight, format); + + if (filtering) { + scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format); + } else { + scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format); + } + + return target; +} + void Surface::convertToInPlace(const PixelFormat &dstFormat, const byte *palette) { // Do not convert to the same format and ignore empty surfaces. if (format == dstFormat || pixels == 0) { diff --git a/graphics/surface.h b/graphics/surface.h index 87281062736..b7ada5ec28a 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -334,6 +334,19 @@ public: * @param r Rect to flip */ void flipVertical(const Common::Rect &r); + + /** + * Scale the data to the given size. + * + * The calling code must call free on the returned surface and then delete + * it. + * + * @param newWidth the resulting width. + * @param newHeight the resulting height. + * @param filtering Whether or not to use bilinear filtering. + */ + Graphics::Surface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const; + }; /** diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp index 4d9000914fc..21dd893b473 100644 --- a/graphics/transparent_surface.cpp +++ b/graphics/transparent_surface.cpp @@ -909,14 +909,13 @@ TransparentSurface *TransparentSurface::rotoscaleT(const TransformStruct &transf return target; } -template -TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight) const { +TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const { TransparentSurface *target = new TransparentSurface(); target->create(newWidth, newHeight, format); - if (filteringMode == FILTER_BILINEAR) { + if (filtering) { scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format); } else { scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format); @@ -1005,15 +1004,9 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat, template TransparentSurface *TransparentSurface::rotoscaleT(const TransformStruct &transform) const; template TransparentSurface *TransparentSurface::rotoscaleT(const TransformStruct &transform) const; -template TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight) const; -template TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight) const; TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { return rotoscaleT(transform); } -TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { - return scaleT(newWidth, newHeight); -} - } // End of namespace Graphics diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h index 3c2b29b7b36..ae0de7d2e22 100644 --- a/graphics/transparent_surface.h +++ b/graphics/transparent_surface.h @@ -145,12 +145,10 @@ struct TransparentSurface : public Graphics::Surface { * * @param newWidth the resulting width. * @param newHeight the resulting height. + * @param filtering Whether or not to use bilinear filtering. * @see TransformStruct */ - template - TransparentSurface *scaleT(uint16 newWidth, uint16 newHeight) const; - - TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; + TransparentSurface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const; /** * @brief Rotoscale function; this returns a transformed version of this surface after rotation and