From d76287cd9c0db1176c59740b5d1e17b168746bef Mon Sep 17 00:00:00 2001 From: kdx Date: Sun, 16 Jul 2023 05:04:18 +0200 Subject: draw image --- demo.cpp | 4 +-- src/FLD.hpp | 11 +++++--- src/drawImage.cpp | 10 ------- src/image.cpp | 13 +++++----- src/imageDraw.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++ src/imageSetScaleMode.cpp | 11 ++++++++ 6 files changed, 93 insertions(+), 22 deletions(-) delete mode 100644 src/drawImage.cpp create mode 100644 src/imageDraw.cpp create mode 100644 src/imageSetScaleMode.cpp diff --git a/demo.cpp b/demo.cpp index f335402..7e31b34 100644 --- a/demo.cpp +++ b/demo.cpp @@ -13,10 +13,10 @@ main_loop(FLD& fld, [[maybe_unused]] void *udata) fld.drawRectangle({ 16, 32, 64, 32 }); fld.image("res/smile.bmp").draw({ - .p = {}, + .p = { 128, 128 }, .sx = 1.5f, .sy = 0.5f, - .f = FLD::FLIP_X | FLD::FLIP_Y, + .f = FLD::FLIP_X | FLD::FLIP_Y | FLD::CENTER, }); if (fld.drawEnd()) diff --git a/src/FLD.hpp b/src/FLD.hpp index d4bf4bf..329cc72 100644 --- a/src/FLD.hpp +++ b/src/FLD.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #define READONLY(T, X, V) private: T _##X = V; public: decltype(_##X) const& X = _##X @@ -40,22 +41,24 @@ public: const Point& p; int ix = 0; int iy = 0; - int w = -1; - int h = -1; + int w = INT_MIN; + int h = INT_MIN; float r = 0.0f; float sx = 1.0f; float sy = 1.0f; Uint f = NONE; }; struct Image { + FLD *fld = nullptr; std::string path = ""; bool valid = true; SDL_Texture *ptr = nullptr; int width = 0; int height = 0; - Error invalid() const; + [[nodiscard]] Error invalid() const; Error draw(const DrawImageOpts& opts) const; + Error setScaleMode(SDL_ScaleMode scale_mode) const; }; enum DrawFlag { NONE = 0, @@ -97,7 +100,7 @@ public: Error drawLine(const Point& p0, const Point& p1) const; Error drawRectangle(const Rectangle& rect, Uint flags=NONE) const; - Image& image(const std::string& path); + [[nodiscard]] Image& image(const std::string& path); private: bool shouldQuit = false; struct { diff --git a/src/drawImage.cpp b/src/drawImage.cpp deleted file mode 100644 index a7f8867..0000000 --- a/src/drawImage.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "FLD.hpp" - -FLD::Error -FLD::Image::draw(const DrawImageOpts &opts) const -{ - if (invalid()) - return -1; - - return 0; -} diff --git a/src/image.cpp b/src/image.cpp index 177968a..5adaf6a 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -1,9 +1,9 @@ #include "FLD.hpp" static FLD::Image& -invalid_image() +invalid_image(FLD *fld) { - static FLD::Image image = { .valid = false }; + static FLD::Image image = { .fld = fld, .valid = false }; return image; } @@ -16,30 +16,31 @@ FLD::image(const std::string &path) const auto surf = SDL_LoadBMP(path.c_str()); if (surf == nullptr) { sdlError(path); - return invalid_image(); + return invalid_image(this); } const auto tex = SDL_CreateTextureFromSurface(_renderer, surf); SDL_FreeSurface(surf); if (tex == nullptr) { sdlError(path); - return invalid_image(); + return invalid_image(this); } if (SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND) < 0) { SDL_DestroyTexture(tex); sdlError(path); - return invalid_image(); + return invalid_image(this); } int width, height; if (SDL_QueryTexture(tex, nullptr, nullptr, &width, &height) < 0) { SDL_DestroyTexture(tex); sdlError(path); - return invalid_image(); + return invalid_image(this); } images[path] = { + .fld = this, .path = path, .ptr = tex, .width = width, diff --git a/src/imageDraw.cpp b/src/imageDraw.cpp new file mode 100644 index 0000000..cd40c4a --- /dev/null +++ b/src/imageDraw.cpp @@ -0,0 +1,66 @@ +#include "FLD.hpp" + +FLD::Error +FLD::Image::draw(const DrawImageOpts &opts) const +{ + if (invalid()) + return -1; + + const bool center = opts.f & CENTER; + const bool flip_x = opts.f & FLIP_X; + const bool flip_y = opts.f & FLIP_Y; + + const Uint8 r = fld->drawColor.r * 0xff; + const Uint8 g = fld->drawColor.g * 0xff; + const Uint8 b = fld->drawColor.b * 0xff; + const Uint8 a = fld->drawColor.a * 0xff; + if (SDL_SetTextureColorMod(ptr, r, g, b) < 0) + return fld->sdlError(); + if (SDL_SetTextureAlphaMod(ptr, a) < 0) + return fld->sdlError(); + + auto scale_x = opts.sx; + auto simg_width = (opts.w == INT_MIN) ? width : opts.w; + if (simg_width < 0) { + simg_width *= -1; + scale_x *= -1; + } + if (simg_width + opts.ix > width) + simg_width = width - opts.ix; + + auto scale_y = opts.sy; + auto simg_height = (opts.h == INT_MIN) ? height : opts.h; + if (simg_height < 0) { + simg_height *= -1; + scale_y *= -1; + } + if (simg_height + opts.iy > height) + simg_height = height - opts.iy; + + int flip = 0; + flip |= SDL_FLIP_HORIZONTAL * ((scale_x < 0) ^ flip_x); + flip |= SDL_FLIP_VERTICAL * ((scale_y < 0) ^ flip_y); + + const int w = simg_width * fabs(scale_x); + const int h = simg_height * fabs(scale_y); + const int x = opts.p.x - ((scale_x < 0) ? w : 0); + const int y = opts.p.y - ((scale_y < 0) ? h : 0); + + const SDL_Rect src { + .x = opts.ix, + .y = opts.iy, + .w = simg_width, + .h = simg_height + }; + const SDL_Rect dst { + .x = x - (center ? (int)(simg_width * scale_x / 2) : 0), + .y = y - (center ? (int)(simg_height * scale_y / 2) : 0), + .w = w, + .h = h + }; + + if (SDL_RenderCopyEx(fld->renderer, ptr, &src, &dst, opts.r * 360, + nullptr, static_cast(flip)) < 0) + return fld->sdlError(); + return 0; +} diff --git a/src/imageSetScaleMode.cpp b/src/imageSetScaleMode.cpp new file mode 100644 index 0000000..5b04c5f --- /dev/null +++ b/src/imageSetScaleMode.cpp @@ -0,0 +1,11 @@ +#include "FLD.hpp" + +FLD::Error +FLD::Image::setScaleMode(SDL_ScaleMode scale_mode) const +{ + if (invalid()) + return -1; + if (SDL_SetTextureScaleMode(ptr, scale_mode) < 0) + return fld->sdlError(); + return 0; +} -- cgit v1.2.3