From e5af4dab68996d278d1aece8e5d914fc27acffaa Mon Sep 17 00:00:00 2001 From: mniip Date: Wed, 5 Apr 2023 01:11:16 +0200 Subject: [PATCH] Refactor resize-related code --- src/client/ThumbnailRendererTask.cpp | 42 +-- src/client/ThumbnailRendererTask.h | 13 +- src/client/http/ImageRequest.cpp | 27 +- src/client/http/ImageRequest.h | 9 +- src/graphics/Graphics.cpp | 406 ++++++++------------------- src/graphics/Graphics.h | 62 +--- src/graphics/RasterGraphics.cpp | 5 - src/graphics/RendererBasic.cpp | 3 +- src/gui/preview/PreviewView.cpp | 14 +- 9 files changed, 168 insertions(+), 413 deletions(-) diff --git a/src/client/ThumbnailRendererTask.cpp b/src/client/ThumbnailRendererTask.cpp index d0e629b72..f5a42356f 100644 --- a/src/client/ThumbnailRendererTask.cpp +++ b/src/client/ThumbnailRendererTask.cpp @@ -13,17 +13,20 @@ int ThumbnailRendererTask::QueueSize() return queueSize; } -ThumbnailRendererTask::ThumbnailRendererTask(GameSave *save, int width, int height, bool autoRescale, bool decorations, bool fire) : - Save(new GameSave(*save)), - Width(width), - Height(height), - Decorations(decorations), - Fire(fire), - AutoRescale(autoRescale) +ThumbnailRendererTask::ThumbnailRendererTask(GameSave const &save, Vec2 size, bool autoRescale, bool decorations, bool fire): + save(std::make_unique(save)), + size(size), + decorations(decorations), + fire(fire), + autoRescale(autoRescale) { queueSize += 1; } +ThumbnailRendererTask::ThumbnailRendererTask(GameSave *save, int width, int height, bool autoRescale, bool decorations, bool fire): + ThumbnailRendererTask(*save, Vec2(width, height), autoRescale, decorations, fire) +{} + ThumbnailRendererTask::~ThumbnailRendererTask() { queueSize -= 1; @@ -31,32 +34,17 @@ ThumbnailRendererTask::~ThumbnailRendererTask() bool ThumbnailRendererTask::doWork() { - thumbnail = std::unique_ptr(SaveRenderer::Ref().Render(Save.get(), Decorations, Fire)); + thumbnail = std::unique_ptr(SaveRenderer::Ref().Render(save.get(), decorations, fire)); if (thumbnail) { - if (AutoRescale) + if (autoRescale) { - int scaleX = (int)std::ceil((float)thumbnail->Width / Width); - int scaleY = (int)std::ceil((float)thumbnail->Height / Height); - int scale = scaleX > scaleY ? scaleX : scaleY; - int newWidth = thumbnail->Width / scale, newHeight = thumbnail->Height / scale; - thumbnail->Resize(newWidth, newHeight, true); - newWidth = thumbnail->Width; - newHeight = thumbnail->Height; - if (newWidth > Width || newHeight > Height) - { - auto croppedWidth = newWidth > Width ? Width : newWidth; - auto croppedHeight = newHeight > Height ? Height : newHeight; - thumbnail->Crop(croppedWidth, croppedHeight, (newWidth - croppedWidth) / 2, (newHeight - croppedHeight) / 2); - newWidth = thumbnail->Width; - newHeight = thumbnail->Height; - } - Width = newWidth; - Height = newHeight; + thumbnail->ResizeToFit(size, true); + size = thumbnail->Size(); } else { - thumbnail->Resize(Width, Height, true); + thumbnail->Resize(size); } return true; } diff --git a/src/client/ThumbnailRendererTask.h b/src/client/ThumbnailRendererTask.h index 8a3073b6c..2518def20 100644 --- a/src/client/ThumbnailRendererTask.h +++ b/src/client/ThumbnailRendererTask.h @@ -1,4 +1,5 @@ #pragma once +#include "common/Vec2.h" #include "tasks/AbandonableTask.h" #include @@ -7,16 +8,18 @@ class GameSave; class VideoBuffer; class ThumbnailRendererTask : public AbandonableTask { - std::unique_ptr Save; - int Width, Height; - bool Decorations; - bool Fire; - bool AutoRescale; + std::unique_ptr save; + Vec2 size; + bool decorations; + bool fire; + bool autoRescale; std::unique_ptr thumbnail; static int queueSize; public: + ThumbnailRendererTask(GameSave const &, Vec2 size, bool autoRescale, bool decorations, bool fire); + [[deprecated("Use ThumbnailRendererTask(GameSave const &, Vec2, bool, bool, bool)")]] ThumbnailRendererTask(GameSave *save, int width, int height, bool autoRescale = false, bool decorations = true, bool fire = true); virtual ~ThumbnailRendererTask(); diff --git a/src/client/http/ImageRequest.cpp b/src/client/http/ImageRequest.cpp index 91c139843..b5ed3d68d 100644 --- a/src/client/http/ImageRequest.cpp +++ b/src/client/http/ImageRequest.cpp @@ -4,21 +4,20 @@ namespace http { - ImageRequest::ImageRequest(ByteString url, int width, int height) : - Request(url), - Width(width), - Height(height) - { - } + ImageRequest::ImageRequest(ByteString url, Vec2 size): + Request(std::move(url)), + size(size) + {} + + ImageRequest::ImageRequest(ByteString url, int width, int height): + ImageRequest(url, Vec2(width, height)) + {} ImageRequest::~ImageRequest() - { - } + {} std::unique_ptr ImageRequest::Finish() { - int width = Width; - int height = Height; auto [ status, data ] = Request::Finish(); (void)status; // We don't use this for anything, not ideal >_> std::unique_ptr vb; @@ -28,14 +27,14 @@ namespace http std::vector imageData; if (PngDataToPixels(imageData, imgw, imgh, data.data(), data.size(), true)) { - vb = std::unique_ptr(new VideoBuffer(imageData.data(), imgw, imgh)); + vb = std::make_unique(imageData.data(), Vec2(imgw, imgh)); } else { - vb = std::unique_ptr(new VideoBuffer(32, 32)); - vb->SetCharacter(14, 14, 'x', 255, 255, 255, 255); + vb = std::make_unique(Vec2(32, 32)); + vb->BlendChar(Vec2(14, 14), 'x', 0xFFFFFF_rgb .WithAlpha(0xFF)); } - vb->Resize(width, height, true); + vb->Resize(size, true); } return vb; } diff --git a/src/client/http/ImageRequest.h b/src/client/http/ImageRequest.h index 9cb7ea67c..7e7ac2f50 100644 --- a/src/client/http/ImageRequest.h +++ b/src/client/http/ImageRequest.h @@ -1,6 +1,7 @@ #pragma once -#include "Request.h" #include "common/String.h" +#include "common/Vec2.h" +#include "Request.h" #include @@ -10,9 +11,11 @@ namespace http { class ImageRequest : public Request { - int Width, Height; - + Vec2 size; + public: + ImageRequest(ByteString url, Vec2 size); + [[deprecated("Use ImageRequest(ByteString, Vec)")]] ImageRequest(ByteString url, int width, int height); virtual ~ImageRequest(); diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 3fd6ed6a4..5f213c7a9 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -41,315 +41,133 @@ VideoBuffer::VideoBuffer(pixel const *buffer, int width, int height, int pitch): VideoBuffer(buffer, Vec2(width, height), pitch == 0 ? width : pitch) {} -void VideoBuffer::CopyData(pixel * buffer, int width, int height, int pitch) -{ - for (auto y = 0; y < height; ++y) - { - std::copy(buffer + y * pitch, buffer + y * pitch + width, Buffer.data() + y * width); - } -} - void VideoBuffer::Crop(Rect rect) { - Crop(rect.Size().X, rect.Size().Y, rect.TopLeft.X, rect.TopLeft.Y); + rect &= Size().OriginRect(); + if (rect == Size().OriginRect()) + return; + + PlaneAdapter &> newVideo(rect.Size(), video.Base); + for (auto y = 0; y < newVideo.Size().Y; y++) + std::copy_n( + video.RowIterator(rect.TopLeft + Vec2(0, y)), + newVideo.Size().X, + newVideo.RowIterator(Vec2(0, y)) + ); + newVideo.Base.resize(newVideo.Size().X * newVideo.Size().Y); + newVideo.Base.shrink_to_fit(); + video.SetSize(newVideo.Size()); } -void VideoBuffer::Crop(int width, int height, int x, int y) +void VideoBuffer::Resize(Vec2 size, bool resample) { - CopyData(Buffer.data() + y * Width + x, width, height, Width); - video.SetSize(Vec2(width, height)); + if (size == Size()) + return; + + if (resample) + { + std::array, PIXELCHANNELS> resamplers; + Resampler::Contrib_List *clist_x = NULL, *clist_y = NULL; + for (auto &ptr : resamplers) + { + ptr = std::make_unique( + Size().X, Size().Y, // source size + size.X, size.Y, // destination size + Resampler::BOUNDARY_CLAMP, + 0.0f, 255.0f, // upper and lower bounds for channel values + "lanczos12", + clist_x, clist_y, + 0.75f, 0.75f // X and Y filter scales, values < 1.0 cause aliasing, but create sharper looking mips. + ); + clist_x = ptr->get_clist_x(); + clist_y = ptr->get_clist_y(); + } + + std::array, PIXELCHANNELS> samples; + for (auto &ptr : samples) + ptr = std::make_unique(Size().X); + + PlaneAdapter> newVideo(size); + + pixel const *inIter = video.data(); + std::array outIter; + for (pixel *&it : outIter) + it = newVideo.data(); + + for (int sourceY = 0; sourceY < Size().Y; sourceY++) + { + for (int sourceX = 0; sourceX < Size().X; sourceX++) + { + pixel px = *inIter++; + for (int c = 0; c < PIXELCHANNELS; c++) + samples[c][sourceX] = uint8_t(px >> (8 * c)); + } + + for (int c = 0; c < PIXELCHANNELS; c++) + { + if (!resamplers[c]->put_line(samples[c].get())) + { + fprintf(stderr, "Out of memory when resampling\n"); + Crop(size.OriginRect()); // Better than leaving the image at original size I guess + return; + } + + while (float const *output = resamplers[c]->get_line()) + for (int destX = 0; destX < size.X; destX++) + *outIter[c]++ |= pixel(uint8_t(output[destX])) << (8 * c); + } + } + + video = std::move(newVideo); + } + else + { + PlaneAdapter> newVideo(size); + for (auto pos : size.OriginRect()) + { + auto oldPos = Vec2(pos.X * Size().X / size.X, pos.Y * Size().Y / size.Y); + newVideo[pos] = video[oldPos]; + } + video = std::move(newVideo); + } } void VideoBuffer::Resize(float factor, bool resample) { - int newWidth = int(Width * factor); - int newHeight = int(Height * factor); - Resize(newWidth, newHeight, resample); + Resize(Vec2(Size() * factor), resample); } -void VideoBuffer::Resize(int width, int height, bool resample, bool fixedRatio) +void VideoBuffer::ResizeToFit(Vec2 bound, bool resample) { - int newWidth = width; - int newHeight = height; - pixel * newBuffer; - if(newHeight == -1 && newWidth == -1) - return; - if(newHeight == -1 || newWidth == -1) + Vec2 size = Size(); + if (size.X > bound.X || size.Y > bound.Y) { - if(newHeight == -1) - newHeight = int(float(Height) * newWidth / Width); - if(newWidth == -1) - newWidth = int(float(Width) * newHeight / Height); - } - else if(fixedRatio) - { - //Force proportions - if(newWidth*Height > newHeight*Width) // same as nW/W > nH/H - newWidth = (int)(Width * (newHeight/(float)Height)); + if (bound.X * size.Y < bound.Y * size.X) + size = size * bound.X / size.X; else - newHeight = (int)(Height * (newWidth/(float)Width)); - } - if(resample) - newBuffer = Graphics::resample_img(Buffer.data(), Width, Height, newWidth, newHeight); - else - newBuffer = Graphics::resample_img_nn(Buffer.data(), Width, Height, newWidth, newHeight); - - if(newBuffer) - { - Buffer.assign(newBuffer, newBuffer + newWidth * newHeight); - delete[] newBuffer; - video.SetSize(Vec2(newWidth, newHeight)); + size = size * bound.Y / size.Y; } + Resize(size, resample); } int VideoBuffer::SetCharacter(int x, int y, String::value_type c, int r, int g, int b, int a) { - FontReader reader(c); - for (int j = -2; j < FONT_H - 2; j++) - for (int i = 0; i < reader.GetWidth(); i++) - SetPixel(x + i, y + j, r, g, b, reader.NextPixel() * a / 3); - return x + reader.GetWidth(); + // Technically inaccurate but oh well + BlendChar(Vec2(x, y), c, RGBA(r, g, b, a)); } int VideoBuffer::BlendCharacter(int x, int y, String::value_type c, int r, int g, int b, int a) { - FontReader reader(c); - for (int j = -2; j < FONT_H - 2; j++) - for (int i = 0; i < reader.GetWidth(); i++) - BlendPixel(x + i, y + j, r, g, b, reader.NextPixel() * a / 3); - return x + reader.GetWidth(); + BlendChar(Vec2(x, y), c, RGBA(r, g, b, a)); } int VideoBuffer::AddCharacter(int x, int y, String::value_type c, int r, int g, int b, int a) { - FontReader reader(c); - for (int j = -2; j < FONT_H - 2; j++) - for (int i = 0; i < reader.GetWidth(); i++) - AddPixel(x + i, y + j, r, g, b, reader.NextPixel() * a / 3); - return x + reader.GetWidth(); + AddChar(Vec2(x, y), c, RGBA(r, g, b, a)); } template class RasterDrawMethods; -pixel *Graphics::resample_img_nn(pixel * src, int sw, int sh, int rw, int rh) -{ - int y, x; - pixel *q = NULL; - q = new pixel[rw*rh]; - for (y=0; yget_clist_x(), resamplers[0]->get_clist_y(), filter_scale, filter_scale); - samples[i] = new float[sourceWidth]; - } - - unsigned char * resultImage = new unsigned char[resultHeight * resultPitch]; - std::fill(resultImage, resultImage + (resultHeight*resultPitch), 0); - - //Resample time - int resultY = 0; - for (int sourceY = 0; sourceY < sourceHeight; sourceY++) - { - unsigned char * sourcePixel = &source[sourceY * sourcePitch]; - - //Move pixel components into channel samples - for (int c = 0; c < PIXELCHANNELS; c++) - { - for (int x = 0; x < sourceWidth; x++) - { - samples[c][x] = sourcePixel[(x*PIXELSIZE)+c] * (1.0f/255.0f); - } - } - - //Put channel sample data into resampler - for (int c = 0; c < PIXELCHANNELS; c++) - { - if (!resamplers[c]->put_line(&samples[c][0])) - { - printf("Out of memory!\n"); - return NULL; - } - } - - //Perform resample and Copy components from resampler result samples to image buffer - for ( ; ; ) - { - int comp_index; - for (comp_index = 0; comp_index < PIXELCHANNELS; comp_index++) - { - const float* resultSamples = resamplers[comp_index]->get_line(); - if (!resultSamples) - break; - - unsigned char * resultPixel = &resultImage[(resultY * resultPitch) + comp_index]; - - for (int x = 0; x < resultWidth; x++) - { - int c = (int)(255.0f * resultSamples[x] + .5f); - if (c < 0) c = 0; else if (c > 255) c = 255; - *resultPixel = (unsigned char)c; - resultPixel += PIXELSIZE; - } - } - if (comp_index < PIXELCHANNELS) - break; - - resultY++; - } - } - - //Clean up - for(int i = 0; i < PIXELCHANNELS; i++) - { - delete resamplers[i]; - delete[] samples[i]; - } - - return (pixel*)resultImage; -#else - if constexpr (DEBUG) - { - std::cout << "Resampling " << sw << "x" << sh << " to " << rw << "x" << rh << std::endl; - } - bool stairstep = false; - if(rw < sw || rh < sh) - { - float fx = (float)(((float)sw)/((float)rw)); - float fy = (float)(((float)sh)/((float)rh)); - - int fxint, fyint; - double fxintp_t, fyintp_t; - - float fxf = modf(fx, &fxintp_t), fyf = modf(fy, &fyintp_t); - fxint = fxintp_t; - fyint = fyintp_t; - - if(((fxint & (fxint-1)) == 0 && fxf < 0.1f) || ((fyint & (fyint-1)) == 0 && fyf < 0.1f)) - stairstep = true; - - if constexpr (DEBUG) - { - if(stairstep) - std::cout << "Downsampling by " << fx << "x" << fy << " using stairstepping" << std::endl; - else - std::cout << "Downsampling by " << fx << "x" << fy << " without stairstepping" << std::endl; - } - } - - int y, x, fxceil, fyceil; - //int i,j,x,y,w,h,r,g,b,c; - pixel *q = NULL; - if(rw == sw && rh == sh){ - //Don't resample - q = new pixel[rw*rh]; - std::copy(src, src+(rw*rh), q); - } else if(!stairstep) { - float fx, fy, fyc, fxc; - double intp; - pixel tr, tl, br, bl; - q = new pixel[rw*rh]; - //Bilinear interpolation for upscaling - for (y=0; y=sw) fxceil = sw-1; - if (fyceil>=sh) fyceil = sh-1; - tr = src[sw*(int)floor(fy)+fxceil]; - tl = src[sw*(int)floor(fy)+(int)floor(fx)]; - br = src[sw*fyceil+fxceil]; - bl = src[sw*fyceil+(int)floor(fx)]; - q[rw*y+x] = PIXRGB( - (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)), - (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)), - (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc)) - ); - } - } else { - //Stairstepping - float fx, fy, fyc, fxc; - double intp; - pixel tr, tl, br, bl; - int rrw = rw, rrh = rh; - pixel * oq; - oq = new pixel[sw*sh]; - std::copy(src, src+(sw*sh), oq); - rw = sw; - rh = sh; - while(rrw != rw && rrh != rh){ - if(rw > rrw) - rw *= 0.7; - if(rh > rrh) - rh *= 0.7; - if(rw <= rrw) - rw = rrw; - if(rh <= rrh) - rh = rrh; - q = new pixel[rw*rh]; - //Bilinear interpolation - for (y=0; y=sw) fxceil = sw-1; - if (fyceil>=sh) fyceil = sh-1; - tr = oq[sw*(int)floor(fy)+fxceil]; - tl = oq[sw*(int)floor(fy)+(int)floor(fx)]; - br = oq[sw*fyceil+fxceil]; - bl = oq[sw*fyceil+(int)floor(fx)]; - q[rw*y+x] = PIXRGB( - (int)(((((float)PIXR(tl))*(1.0f-fxc))+(((float)PIXR(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXR(bl))*(1.0f-fxc))+(((float)PIXR(br))*(fxc)))*(fyc)), - (int)(((((float)PIXG(tl))*(1.0f-fxc))+(((float)PIXG(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXG(bl))*(1.0f-fxc))+(((float)PIXG(br))*(fxc)))*(fyc)), - (int)(((((float)PIXB(tl))*(1.0f-fxc))+(((float)PIXB(tr))*(fxc)))*(1.0f-fyc) + ((((float)PIXB(bl))*(1.0f-fxc))+(((float)PIXB(br))*(fxc)))*(fyc)) - ); - } - delete[] oq; - oq = q; - sw = rw; - sh = rh; - } - } - return q; -#endif -} - int Graphics::textwidth(const String &str) { int x = 0; @@ -737,29 +555,25 @@ void Graphics::draw_rgba_image(const pixel *data, int w, int h, int x, int y, fl VideoBuffer Graphics::DumpFrame() { - VideoBuffer newBuffer(WINDOWW, WINDOWH); - std::copy(vid, vid+(WINDOWW*WINDOWH), newBuffer.Buffer.data()); + VideoBuffer newBuffer(WINDOW); + std::copy_n(video.data(), WINDOW.X * WINDOW.Y, newBuffer.Data()); return newBuffer; } +void Graphics::SwapClipRect(Rect &rect) +{ + std::swap(clipRect, rect); + clipRect &= video.Size().OriginRect(); +} + void Graphics::SetClipRect(int &x, int &y, int &w, int &h) { - int newX = x; - int newY = y; - int newW = w; - int newH = h; - if (newX < 0) newX = 0; - if (newY < 0) newY = 0; - if (newW > WINDOWW - newX) newW = WINDOWW - newX; - if (newH > WINDOWH - newY) newH = WINDOWH - newY; - x = clipx1; - y = clipy1; - w = clipx2 - clipx1; - h = clipy2 - clipy1; - clipx1 = newX; - clipy1 = newY; - clipx2 = newX + newW; - clipy2 = newY + newH; + Rect rect = RectSized(Vec2(x, y), Vec2(w, h)); + SwapClipRect(rect); + x = rect.TopLeft.X; + y = rect.TopLeft.Y; + w = rect.Size().X; + h = rect.Size().Y; } bool VideoBuffer::WritePNG(const ByteString &path) const diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index 084e793ca..cfe372b09 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -20,8 +20,6 @@ class VideoBuffer: public RasterDrawMethods friend struct RasterDrawMethods; - void CopyData(pixel * buffer, int width, int height, int pitch); - public: [[deprecated("Use video")]] std::vector &Buffer = video.Base; @@ -40,6 +38,11 @@ public: return video.Size(); } + pixel *Data() + { + return video.data(); + } + pixel const *Data() const { return video.data(); @@ -48,7 +51,9 @@ public: void Crop(Rect); void Resize(float factor, bool resample = false); - void Resize(Vec2 size, bool resamble = false, bool fixedRatio = true); + void Resize(Vec2 size, bool resample = false); + // Automatically choose a size to fit within the given box, keeping aspect ratio + void ResizeToFit(Vec2 bound, bool resample = false); [[deprecated("Use VideoBuffer(VideoBuffer const &)")]] VideoBuffer(VideoBuffer * old); @@ -56,54 +61,25 @@ public: VideoBuffer(pixel const *buffer, int width, int height, int pitch = 0); [[deprecated("Use VideoBuffer(Vec2)")]] VideoBuffer(int width, int height); - [[deprecated("Use Resize(Vec2, bool, bool)")]] - void Resize(int width, int height, bool resample = false, bool fixedRatio = true); - [[deprecated("Use Crop(Rect)")]] - void Crop(int width, int height, int x, int y); using RasterDrawMethods::BlendPixel; [[deprecated("Use BlendPixel(Vec2, RGBA)")]] TPT_INLINE void BlendPixel(int x, int y, int r, int g, int b, int a) { - pixel t; - if (x<0 || y<0 || x>=Width || y>=Height) - return; - if (a!=255) - { - t = Buffer[y*(Width)+x]; - r = (a*r + (255-a)*PIXR(t)) >> 8; - g = (a*g + (255-a)*PIXG(t)) >> 8; - b = (a*b + (255-a)*PIXB(t)) >> 8; - } - Buffer[y*(Width)+x] = PIXRGB(r,g,b); + BlendPixel(Vec2(x, y), RGBA(r, g, b, a)); } [[deprecated("Use DrawPixel")]] TPT_INLINE void SetPixel(int x, int y, int r, int g, int b, int a) { - if (x<0 || y<0 || x>=Width || y>=Height) - return; - Buffer[y*(Width)+x] = PIXRGB((r*a)>>8, (g*a)>>8, (b*a)>>8); + DrawPixel(Vec2(x, y), 0x000000_rgb .Blend(RGBA(r, g, b, a))); } using RasterDrawMethods::AddPixel; [[deprecated("Use AddPixel(Vec2, RGBA)")]] TPT_INLINE void AddPixel(int x, int y, int r, int g, int b, int a) { - pixel t; - if (x<0 || y<0 || x>=Width || y>=Height) - return; - t = Buffer[y*(Width)+x]; - r = (a*r + 255*PIXR(t)) >> 8; - g = (a*g + 255*PIXG(t)) >> 8; - b = (a*b + 255*PIXB(t)) >> 8; - if (r>255) - r = 255; - if (g>255) - g = 255; - if (b>255) - b = 255; - Buffer[y*(Width)+x] = PIXRGB(r,g,b); + AddPixel(Vec2(x, y), RGBA(r, g, b, a)); } [[deprecated("Use BlendChar")]] int SetCharacter(int x, int y, String::value_type c, int r, int g, int b, int a); @@ -127,15 +103,6 @@ class Graphics: public RasterDrawMethods friend struct RasterDrawMethods; - [[deprecated("Use clipRect")]] - int &clipx1 = clipRect.TopLeft.X; - [[deprecated("Use clipRect")]] - int &clipy1 = clipRect.TopLeft.Y; - [[deprecated("Use clipRect")]] - int &clipx2 = clipRect.BottomRight.X; - [[deprecated("Use clipRect")]] - int &clipy2 = clipRect.BottomRight.Y; - public: pixel const *Data() const { @@ -154,10 +121,6 @@ public: }; static std::vector Gradient(std::vector stops, int resolution); - //PTIF methods - static pixel *resample_img_nn(pixel *src, int sw, int sh, int rw, int rh); - static pixel *resample_img(pixel *src, int sw, int sh, int rw, int rh); - //Font/text metrics static int CharWidth(String::value_type c); static int textwidthx(const String &s, int w); @@ -168,7 +131,6 @@ public: void draw_icon(int x, int y, Icon icon, unsigned char alpha = 255, bool invert = false); - void Clear(); void Finalise(); void draw_rgba_image(const pixel *data, int w, int h, int x, int y, float alpha); @@ -176,6 +138,8 @@ public: Graphics() {} + void SwapClipRect(Rect &); + [[deprecated("Use SwapClipRect")]] void SetClipRect(int &x, int &y, int &w, int &h); }; diff --git a/src/graphics/RasterGraphics.cpp b/src/graphics/RasterGraphics.cpp index b5f42f216..eb50fe70b 100644 --- a/src/graphics/RasterGraphics.cpp +++ b/src/graphics/RasterGraphics.cpp @@ -4,11 +4,6 @@ #include "SimulationConfig.h" #include "RasterDrawMethodsImpl.h" -void Graphics::Clear() -{ - memset(vid, 0, PIXELSIZE * (WINDOWW * WINDOWH)); -} - void Graphics::Finalise() { diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp index 2f956822f..b4332b464 100644 --- a/src/graphics/RendererBasic.cpp +++ b/src/graphics/RendererBasic.cpp @@ -52,8 +52,7 @@ void Renderer::SetSample(int x, int y) sampleColor = GetPixel(x, y); } -void Renderer::clearScreen() -{ +void Renderer::clearScreen() { if(display_mode & DISPLAY_PERS) { std::copy(persistentVid, persistentVid+(VIDXRES*YRES), vid); diff --git a/src/gui/preview/PreviewView.cpp b/src/gui/preview/PreviewView.cpp index 0dedf634e..e8c8e2a59 100644 --- a/src/gui/preview/PreviewView.cpp +++ b/src/gui/preview/PreviewView.cpp @@ -464,18 +464,8 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender) if(save->GetGameSave()) { savePreview = SaveRenderer::Ref().Render(save->GetGameSave(), false, true); - - if(savePreview && !(savePreview->Width == XRES/2 && savePreview->Height == YRES/2)) - { - float factorX = ((float)XRES/2)/((float)savePreview->Width); - float factorY = ((float)YRES/2)/((float)savePreview->Height); - float scaleFactor = factorY < factorX ? factorY : factorX; - pixel *data = Graphics::resample_img(savePreview->Buffer.data(), savePreview->Width, savePreview->Height, int(savePreview->Width*scaleFactor), int(savePreview->Height*scaleFactor)); - savePreview->Width = int(savePreview->Width * scaleFactor); - savePreview->Height = int(savePreview->Height * scaleFactor); - savePreview->Buffer.assign(data, data + savePreview->Width * savePreview->Height); - delete[] data; - } + if (savePreview) + savePreview->ResizeToFit(RES / 2, true); } else if (!sender->GetCanOpen()) openButton->Enabled = false;