From 6ac1673e15c4b8ec6dbc529f01642d512ee27ec5 Mon Sep 17 00:00:00 2001 From: iSage Date: Mon, 8 Apr 2019 16:21:51 +0300 Subject: [PATCH] Put back software prescaling, ugh --- src/graphics/Renderer.cpp | 26 +-- src/graphics/Surface.cpp | 18 +- src/graphics/zoom.cpp | 372 ++++++++++++++++++++++++++++++++++++++ src/graphics/zoom.h | 10 + win32/nx/nx.vcxproj | 2 + 5 files changed, 408 insertions(+), 20 deletions(-) create mode 100644 src/graphics/zoom.cpp create mode 100644 src/graphics/zoom.h diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index 01bb76ed..41cb325c 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -284,18 +284,18 @@ void Renderer::drawSurface(Surface *src, int dstx, int dsty, int srcx, int srcy, SDL_Rect srcrect, dstrect; - srcrect.x = srcx; - srcrect.y = srcy; - srcrect.w = wd; - srcrect.h = ht; + srcrect.x = srcx * scale; + srcrect.y = srcy * scale; + srcrect.w = wd * scale; + srcrect.h = ht * scale; dstrect.x = dstx * scale; dstrect.y = dsty * scale; - dstrect.w = srcrect.w * scale; - dstrect.h = srcrect.h * scale; + dstrect.w = srcrect.w; + dstrect.h = srcrect.h; if (_need_clip) - clip(srcrect, dstrect); + clipScaled(srcrect, dstrect); SDL_SetTextureAlphaMod(src->texture(), src->alpha); if (SDL_RenderCopy(_renderer, src->texture(), &srcrect, &dstrect)) @@ -310,12 +310,12 @@ void Renderer::blitPatternAcross(Surface *sfc, int x_dst, int y_dst, int y_src, SDL_Rect srcrect, dstrect; srcrect.x = 0; - srcrect.w = sfc->width(); - srcrect.y = (y_src); - srcrect.h = (height); + srcrect.w = sfc->width() * scale; + srcrect.y = (y_src * scale); + srcrect.h = (height * scale); - dstrect.w = srcrect.w * scale; - dstrect.h = srcrect.h * scale; + dstrect.w = srcrect.w; + dstrect.h = srcrect.h; int x = (x_dst * scale); int y = (y_dst * scale); @@ -328,7 +328,7 @@ void Renderer::blitPatternAcross(Surface *sfc, int x_dst, int y_dst, int y_src, dstrect.x = x; dstrect.y = y; SDL_RenderCopy(_renderer, sfc->texture(), &srcrect, &dstrect); - x += sfc->width() * scale; + x += sfc->width() * scale; } while (x < destwd); } diff --git a/src/graphics/Surface.cpp b/src/graphics/Surface.cpp index 7f87ce66..7ddebcf2 100644 --- a/src/graphics/Surface.cpp +++ b/src/graphics/Surface.cpp @@ -1,6 +1,7 @@ #include "Surface.h" #include "Renderer.h" #include "../common/stat.h" +#include "zoom.h" namespace NXE { @@ -31,17 +32,20 @@ bool Surface::loadImage(const std::string &pbm_name, bool use_colorkey) return false; } - _width = image->w; - _height = image->h; + _width = image->w * Renderer::getInstance()->scale; + _height = image->h * Renderer::getInstance()->scale; + + SDL_Surface *image_scaled = SDL_ZoomSurface(image, Renderer::getInstance()->scale); + SDL_FreeSurface(image); if (use_colorkey) { - SDL_SetColorKey(image, SDL_TRUE, SDL_MapRGB(image->format, 0, 0, 0)); + SDL_SetColorKey(image_scaled, SDL_TRUE, SDL_MapRGB(image_scaled->format, 0, 0, 0)); } - _texture = SDL_CreateTextureFromSurface(Renderer::getInstance()->renderer(), image); + _texture = SDL_CreateTextureFromSurface(Renderer::getInstance()->renderer(), image_scaled); - SDL_FreeSurface(image); + SDL_FreeSurface(image_scaled); if (!_texture) { @@ -66,12 +70,12 @@ Surface *Surface::fromFile(const std::string &pbm_name, bool use_colorkey) int Surface::width() { - return _width; + return _width / Renderer::getInstance()->scale; } int Surface::height() { - return _height; + return _height / Renderer::getInstance()->scale; } SDL_Texture* Surface::texture() diff --git a/src/graphics/zoom.cpp b/src/graphics/zoom.cpp new file mode 100644 index 00000000..a756d80d --- /dev/null +++ b/src/graphics/zoom.cpp @@ -0,0 +1,372 @@ +/* + * Based on SDL2_gfx + * http://www.ferzkopp.net/Software/SDL2_gfx/Docs/html/index.html + */ + +#ifdef WIN32 +#include +#endif + +#include "zoom.h" + +#include +#include + +typedef struct tColorRGBA +{ + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; +} tColorRGBA; + +typedef struct tColorY +{ + Uint8 y; +} tColorY; + +#define GUARD_ROWS (2) + +#define VALUE_LIMIT 0.001 + +Uint32 _colorkey(SDL_Surface *src) +{ + Uint32 key = 0; + SDL_GetColorKey(src, &key); + return key; +} + +int _zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst) +{ + int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, sstep; + tColorRGBA *sp, *csp, *dp; + int spixelgap, dgap; + + /* + * Allocate memory for row/column increments + */ + if ((sax = (int *)malloc((dst->w + 1) * sizeof(Uint32))) == NULL) + { + return (-1); + } + if ((say = (int *)malloc((dst->h + 1) * sizeof(Uint32))) == NULL) + { + free(sax); + return (-1); + } + + /* + * Precalculate row increments + */ + sx = (int)(65536.0 * (float)(src->w) / (float)(dst->w)); + sy = (int)(65536.0 * (float)(src->h) / (float)(dst->h)); + + /* Maximum scaled source size */ + ssx = (src->w << 16) - 1; + ssy = (src->h << 16) - 1; + + /* Precalculate horizontal row increments */ + csx = 0; + csax = sax; + for (x = 0; x <= dst->w; x++) + { + *csax = csx; + csax++; + csx += sx; + + /* Guard from overflows */ + if (csx > ssx) + { + csx = ssx; + } + } + + /* Precalculate vertical row increments */ + csy = 0; + csay = say; + for (y = 0; y <= dst->h; y++) + { + *csay = csy; + csay++; + csy += sy; + + /* Guard from overflows */ + if (csy > ssy) + { + csy = ssy; + } + } + + sp = (tColorRGBA *)src->pixels; + dp = (tColorRGBA *)dst->pixels; + dgap = dst->pitch - dst->w * 4; + spixelgap = src->pitch / 4; + + /* + * Non-Interpolating Zoom + */ + csay = say; + for (y = 0; y < dst->h; y++) + { + csp = sp; + csax = sax; + for (x = 0; x < dst->w; x++) + { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointer x + */ + salast = csax; + csax++; + sstep = (*csax >> 16) - (*salast >> 16); + sp += sstep; + /* + * Advance destination pointer x + */ + dp++; + } + /* + * Advance source pointer y + */ + salast = csay; + csay++; + sstep = (*csay >> 16) - (*salast >> 16); + sstep *= spixelgap; + sp = csp + sstep; + /* + * Advance destination pointer y + */ + dp = (tColorRGBA *)((Uint8 *)dp + dgap); + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +int _zoomSurfaceY(SDL_Surface *src, SDL_Surface *dst) +{ + int x, y; + Uint32 *sax, *say, *csax, *csay; + int csx, csy; + Uint8 *sp, *dp, *csp; + int dgap; + + /* + * Allocate memory for row increments + */ + if ((sax = (Uint32 *)malloc((dst->w + 1) * sizeof(Uint32))) == NULL) + { + return (-1); + } + if ((say = (Uint32 *)malloc((dst->h + 1) * sizeof(Uint32))) == NULL) + { + free(sax); + return (-1); + } + + /* + * Pointer setup + */ + sp = csp = (Uint8 *)src->pixels; + dp = (Uint8 *)dst->pixels; + dgap = dst->pitch - dst->w; + + /* + * Precalculate row increments + */ + csx = 0; + csax = sax; + for (x = 0; x < dst->w; x++) + { + csx += src->w; + *csax = 0; + while (csx >= dst->w) + { + csx -= dst->w; + (*csax)++; + } + csax++; + } + csy = 0; + csay = say; + for (y = 0; y < dst->h; y++) + { + csy += src->h; + *csay = 0; + while (csy >= dst->h) + { + csy -= dst->h; + (*csay)++; + } + csay++; + } + + /* + * Draw + */ + csay = say; + for (y = 0; y < dst->h; y++) + { + csax = sax; + sp = csp; + for (x = 0; x < dst->w; x++) + { + /* + * Draw + */ + *dp = *sp; + /* + * Advance source pointers + */ + sp += (*csax); + csax++; + /* + * Advance destination pointer + */ + dp++; + } + /* + * Advance source pointer (for row) + */ + csp += ((*csay) * src->pitch); + csay++; + + /* + * Advance destination pointers + */ + dp += dgap; + } + + /* + * Remove temp arrays + */ + free(sax); + free(say); + + return (0); +} + +void _zoomSurfaceSize(int width, int height, double zoom, int *dstwidth, int *dstheight) +{ + if (zoom < VALUE_LIMIT) + { + zoom = VALUE_LIMIT; + } + + *dstwidth = (int)floor(((double)width * zoom) + 0.5); + *dstheight = (int)floor(((double)height * zoom) + 0.5); + + if (*dstwidth < 1) + { + *dstwidth = 1; + } + if (*dstheight < 1) + { + *dstheight = 1; + } +} + +SDL_Surface *SDL_ZoomSurface(SDL_Surface *src, double zoom) +{ + SDL_Surface *rz_src; + SDL_Surface *rz_dst; + int dstwidth, dstheight; + int is32bit; + int i, src_converted; + + if (src == NULL) + return (NULL); + + is32bit = (src->format->BitsPerPixel == 32); + if ((is32bit) || (src->format->BitsPerPixel == 8)) + { + rz_src = src; + src_converted = 0; + } + else + { + rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 +#else + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff +#endif + ); + + if (rz_src == NULL) + { + return NULL; + } + + SDL_BlitSurface(src, NULL, rz_src, NULL); + src_converted = 1; + is32bit = 1; + } + + // Get size of target + _zoomSurfaceSize(rz_src->w, rz_src->h, zoom, &dstwidth, &dstheight); + + rz_dst = NULL; + if (is32bit) + { + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, rz_src->format->Rmask, + rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); + } + else + { + rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); + } + + if (rz_dst == NULL) + { + if (src_converted) + { + SDL_FreeSurface(rz_src); + } + return NULL; + } + + // Adjust for guard rows + rz_dst->h = dstheight; + + if (SDL_MUSTLOCK(rz_src)) + { + SDL_LockSurface(rz_src); + } + + if (is32bit) + { + _zoomSurfaceRGBA(rz_src, rz_dst); + } + else + { + // Copy palette and colorkey info + for (i = 0; i < rz_src->format->palette->ncolors; i++) + { + rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; + } + rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; + + _zoomSurfaceY(rz_src, rz_dst); + } + + if (SDL_MUSTLOCK(rz_src)) + { + SDL_UnlockSurface(rz_src); + } + + if (src_converted) + { + SDL_FreeSurface(rz_src); + } + + return (rz_dst); +} diff --git a/src/graphics/zoom.h b/src/graphics/zoom.h new file mode 100644 index 00000000..cd492b49 --- /dev/null +++ b/src/graphics/zoom.h @@ -0,0 +1,10 @@ +#ifndef _ZOOM_H +#define _ZOOM_H + +#include "SDL.h" + +#include + +SDL_Surface *SDL_ZoomSurface(SDL_Surface *src, double zoom); + +#endif /* _SDL2_rotozoom_h */ \ No newline at end of file diff --git a/win32/nx/nx.vcxproj b/win32/nx/nx.vcxproj index 6d8c43e8..9cee1946 100644 --- a/win32/nx/nx.vcxproj +++ b/win32/nx/nx.vcxproj @@ -255,6 +255,7 @@ + @@ -395,6 +396,7 @@ +