From faeb24f037e3cc3d34c81d4da36996fde4ddf51d Mon Sep 17 00:00:00 2001 From: Miro Kropacek Date: Sun, 12 Mar 2023 00:20:41 +0100 Subject: [PATCH] GRAPHICS: SVGBitmap now inherits from ManagedSurface Since the only use case for SVGBitmap is blitting it to a ManagedSurface, combine both into one to avoid unnecessary allocation and blitting. --- graphics/svg.cpp | 80 ++++++++++++++++---------------------------- graphics/svg.h | 29 ++++------------ gui/ThemeEngine.cpp | 16 ++------- gui/widgets/grid.cpp | 8 +---- 4 files changed, 40 insertions(+), 93 deletions(-) diff --git a/graphics/svg.cpp b/graphics/svg.cpp index 763bd959130..010d3bab5f1 100644 --- a/graphics/svg.cpp +++ b/graphics/svg.cpp @@ -18,76 +18,54 @@ * along with this program. If not, see . */ -#include "common/scummsys.h" -#include "common/stream.h" -#include "common/textconsole.h" - -#include "graphics/managed_surface.h" -#include "graphics/pixelformat.h" - #include "graphics/svg.h" - +#include "common/endian.h" +#include "common/stream.h" +#include "common/textconsole.h" +#include "graphics/pixelformat.h" #define NANOSVG_IMPLEMENTATION #include "graphics/nanosvg/nanosvg.h" #define NANOSVGRAST_IMPLEMENTATION #include "graphics/nanosvg/nanosvgrast.h" +#ifdef SCUMM_BIG_ENDIAN +#define PIXELFORMAT Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0) +#else +#define PIXELFORMAT Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24) +#endif + namespace Graphics { -SVGBitmap::SVGBitmap(Common::SeekableReadStream *in) { - int32 size = in->size(); - char *data = (char *)malloc(size + 1); +SVGBitmap::SVGBitmap(Common::SeekableReadStream *in, int dw, int dh) + : ManagedSurface(dw, dh, PIXELFORMAT) { + if (dw == 0 || dh == 0) + return; + + int64 size = in->size(); + char *data = new char[size + 1]; in->read(data, size); data[size] = '\0'; - _svg = nsvgParse(data, "px", 96); - free(data); - - if (_svg == NULL) + NSVGimage *svg = nsvgParse(data, "px", 96); + if (svg == NULL) error("Cannot parse SVG image"); - _rasterizer = NULL; - _render = NULL; + delete[] data; + data = nullptr; -#ifdef SCUMM_BIG_ENDIAN - _pixelformat = new Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); -#else - _pixelformat = new Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24); -#endif -} + // Maintain aspect ratio + float xRatio = 1.0f * dw / svg->width; + float yRatio = 1.0f * dh / svg->height; + float ratio = xRatio < yRatio ? xRatio : yRatio; -SVGBitmap::~SVGBitmap() { - if (_rasterizer) - nsvgDeleteRasterizer(_rasterizer); + NSVGrasterizer *rasterizer = nsvgCreateRasterizer(); - nsvgDelete(_svg); + nsvgRasterize(rasterizer, svg, 0, 0, ratio, (byte *)getPixels(), dw, dh, pitch); - delete _render; - delete _pixelformat; -} - -void SVGBitmap::render(Graphics::ManagedSurface &target, int dw, int dh) { - if (dw == 0 || dh == 0) - return; - - if (_rasterizer == NULL) - _rasterizer = nsvgCreateRasterizer(); - - if (!_render || _render->w != dw || _render->h != dh) { - // Maintain aspect ratio - float xRatio = 1.0f * dw / _svg->width; - float yRatio = 1.0f * dh / _svg->height; - float ratio = xRatio < yRatio ? xRatio : yRatio; - - delete _render; - _render = new ManagedSurface(dw, dh, *_pixelformat); - - nsvgRasterize(_rasterizer, _svg, 0, 0, ratio, (byte *)_render->getPixels(), dw, dh, _render->pitch); - } - - target.blitFrom(_render->rawSurface()); + nsvgDeleteRasterizer(rasterizer); + nsvgDelete(svg); } } // end of namespace Graphics diff --git a/graphics/svg.h b/graphics/svg.h index b501bc91310..d3a52a39694 100644 --- a/graphics/svg.h +++ b/graphics/svg.h @@ -21,35 +21,20 @@ #ifndef GRAPHICS_SVG_H #define GRAPHICS_SVG_H +#include "graphics/managed_surface.h" + namespace Common { class SeekableReadStream; } -struct NSVGimage; -struct NSVGrasterizer; - namespace Graphics { -class ManagedSurface; -struct Surface; -struct PixelFormat; - -class SVGBitmap { +/** + * A derived graphics surface, which renders bitmap data from a SVG stream. + */ +class SVGBitmap : public ManagedSurface { public: - SVGBitmap(Common::SeekableReadStream *in); - ~SVGBitmap(); - - Graphics::PixelFormat *getPixelFormat() { return _pixelformat; } - - void render(Graphics::ManagedSurface &target, int dw, int dh); - -private: - NSVGimage *_svg; - NSVGrasterizer *_rasterizer; - - Graphics::ManagedSurface *_render; - - Graphics::PixelFormat *_pixelformat; + SVGBitmap(Common::SeekableReadStream *in, int dw, int dh); }; } // end of namespace Graphics diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index f730cd9ea76..bcaab8c9863 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -658,28 +658,18 @@ bool ThemeEngine::addBitmap(const Common::String &filename, const Common::String } if (!scalablefile.empty()) { - Graphics::SVGBitmap *image = nullptr; Common::ArchiveMemberList members; _themeFiles.listMatchingMembers(members, scalablefile); for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) { Common::SeekableReadStream *stream = (*i)->createReadStream(); if (stream) { - image = new Graphics::SVGBitmap(stream); + _bitmaps[filename] = new Graphics::SVGBitmap(stream, width * _scaleFactor, height * _scaleFactor); delete stream; - break; + return true; } } - if (image) { - _bitmaps[filename] = new Graphics::ManagedSurface(width * _scaleFactor, height * _scaleFactor, *image->getPixelFormat()); - image->render(*_bitmaps[filename], width * _scaleFactor, height * _scaleFactor); - - delete image; - } else { - return false; - } - - return true; + return false; } const Graphics::Surface *srcSurface = nullptr; diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp index 829cf80fdc1..3457212e5ed 100644 --- a/gui/widgets/grid.cpp +++ b/gui/widgets/grid.cpp @@ -327,14 +327,8 @@ Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int re g_gui.lockIconsSet(); if (g_gui.getIconsSet().hasFile(name)) { Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(name); - Graphics::SVGBitmap *image = nullptr; - image = new Graphics::SVGBitmap(stream); - + surf = new Graphics::SVGBitmap(stream, renderWidth, renderHeight); delete stream; - - surf = new Graphics::ManagedSurface(renderWidth, renderHeight, *image->getPixelFormat()); - image->render(*surf, renderWidth, renderHeight); - delete image; } else { debug(5, "GridWidget: Cannot read file '%s'", name.c_str()); }