Compare commits

..

10 Commits

Author SHA1 Message Date
3e6fcfeb72 correccions en el makefile de macos 2026-05-03 18:03:30 +02:00
2474283e07 afegit suppress a cppcheck 2026-04-18 12:28:19 +02:00
d58c0303e9 surface: hallazgo 1 — SurfaceData::width/height de float a int
Las dimensiones en píxeles son enteros por naturaleza. Convertidos los
miembros y constructores a int, y ajustados getWidth()/getHeight() para
devolver int. Eliminados los static_cast<int>(...->width/height) y
static_cast<int>(surface->getWidth/getHeight()) redundantes que sólo
existían para compensar el tipo erróneo.

Los callers que inicializan SDL_FRect directamente con getWidth/getHeight
requieren static_cast<float> explícito (sprite.cpp, animated_sprite.cpp,
notifier.cpp, title.cpp) por las reglas de narrowing de list-init.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:22:19 +02:00
5f0b4355e4 surface: hallazgo 4 — elimina render(6 floats) sin callers
La sobrecarga render(float dx, float dy, float sx, float sy, float w,
float h) no tenía un solo caller en el proyecto. Las otras dos
sobrecargas (con SDL_FRect) cubren todos los casos de uso reales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:16:46 +02:00
40ac657f74 surface: hallazgo 8 — elimina setSurfaceData muerto y documenta shared_ptr
setSurfaceData() no tenía callers. El shared_ptr<SurfaceData> se queda
porque render() puede aliasar el SurfaceData propio con el del renderer
surface (self-blit). Migrar a unique_ptr requeriría tocar Screen y
dissolve_sprite sin simplificación real.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 12:01:51 +02:00
6a12294a36 surface: hallazgo 5 — renderWithColorReplace aplica sub_palette_
Coherencia con render() y renderWithVerticalFade(): el píxel no
sustituido pasa por sub_palette_ en vez de copiarse crudo. Hoy es
no-op (las surfaces que usan color replace no hacen fadeSubPalette)
pero cierra la divergencia de API y previene regresiones futuras.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 11:58:46 +02:00
1f5b1ad1ab surface: hallazgo 2 — drawLine con Bresenham en enteros
El bucle usaba floats con comparación de igualdad exacta (x1==x2 &&
y1==y2) como condición de parada, con incrementos ±1.0f acumulados:
bug latente. Convertidos los endpoints de entrada con std::lround y
reescrito el algoritmo con ints. Firma pública float preservada para
no tocar callers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 11:55:12 +02:00
b1413bbf8a surface: hallazgo 3 — sustituye sizeof check por static_assert en fade*Palette
palette_ y sub_palette_ son std::array de tamaño fijo, así que el check
en runtime nunca podía fallar. Movido a static_assert sobre tuple_size_v.
El throw asociado era código muerto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 11:54:33 +02:00
eaf9d87d6d surface: hallazgo 6 — elimina doble std::min en render(int,int,...)
Las dos líneas de clamp contra el destino estaban duplicadas. Fusionado
el comentario y dejado un único bloque que limita contra origen y destino.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 11:53:59 +02:00
60adfc8fbb surface: hallazgo 7 — elimina NOLINT obsoleto en loadSurface
loadSurface es static en declaración y definición, así que el
NOLINT(readability-convert-member-functions-to-static) era dead noise.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 11:53:33 +02:00
11 changed files with 152 additions and 153 deletions

View File

@@ -382,6 +382,8 @@ if(CPPCHECK_EXE)
--inline-suppr --inline-suppr
--suppress=missingIncludeSystem --suppress=missingIncludeSystem
--suppress=toomanyconfigs --suppress=toomanyconfigs
--suppress=*:*/source/external/*
--suppress=*:*/source/core/rendering/sdl3gpu/spv/*
--quiet --quiet
-I ${CMAKE_SOURCE_DIR}/source -I ${CMAKE_SOURCE_DIR}/source
${CPPCHECK_SOURCES} ${CPPCHECK_SOURCES}

View File

@@ -186,12 +186,28 @@ _windows_release:
_macos_release: _macos_release:
@echo "Creando release para macOS - Version: $(VERSION)" @echo "Creando release para macOS - Version: $(VERSION)"
# Verificar e instalar create-dmg si es necesario # Verifica dependencias necesarias (create-dmg). Si falta, intenta instalarla
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg) # con brew; si brew tampoco está, indica el comando exacto al usuario.
@command -v create-dmg >/dev/null 2>&1 || { \
# Compila la versión para procesadores Intel con cmake (genera shaders y resources.pack) echo ""; \
@cmake -S . -B build/intel -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH) echo "============================================"; \
@cmake --build build/intel echo " Falta la dependencia: create-dmg"; \
echo "============================================"; \
if command -v brew >/dev/null 2>&1; then \
echo " Instalando con: brew install create-dmg"; \
brew install create-dmg || { \
echo ""; \
echo " ERROR: 'brew install create-dmg' ha fallado."; \
echo " Ejecuta el comando manualmente y vuelve a probar."; \
exit 1; \
}; \
else \
echo " Homebrew no está instalado."; \
echo " Instálalo desde https://brew.sh y luego ejecuta:"; \
echo " brew install create-dmg"; \
exit 1; \
fi; \
}
# Elimina datos de compilaciones anteriores # Elimina datos de compilaciones anteriores
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
@@ -205,12 +221,11 @@ _macos_release:
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
# Copia carpetas y ficheros # Copia carpetas y ficheros del bundle (resources.pack se generará al compilar)
cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks" cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
cp release/icons/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" cp release/icons/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents" cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
cp gamecontrollerdb.txt "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp LICENSE "$(RELEASE_FOLDER)" cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)" cp README.md "$(RELEASE_FOLDER)"
@@ -220,32 +235,53 @@ _macos_release:
sed -i '' '/<key>CFBundleShortVersionString<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \ sed -i '' '/<key>CFBundleShortVersionString<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
sed -i '' '/<key>CFBundleVersion<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist" sed -i '' '/<key>CFBundleVersion<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"
# Copia el ejecutable Intel al bundle # Compila y empaqueta la versión Intel (best-effort: si falla, se omite el
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" # DMG Intel y continúa con la build de Apple Silicon).
@echo ""
# Firma la aplicación @echo "============================================"
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app" @echo " Compilando version Intel (x86_64)"
@echo "============================================"
# Empaqueta el .dmg de la versión Intel con create-dmg @if cmake -S . -B build/intel -DCMAKE_BUILD_TYPE=Release \
@echo "Creando DMG Intel con iconos de 96x96..." -DCMAKE_OSX_ARCHITECTURES=x86_64 \
create-dmg \ -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
--volname "$(APP_NAME)" \ -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH) \
--window-pos 200 120 \ && cmake --build build/intel; then \
--window-size 720 300 \ cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"; \
--icon-size 96 \ cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"; \
--text-size 12 \ codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"; \
--icon "$(APP_NAME).app" 278 102 \ echo "Creando DMG Intel con iconos de 96x96..."; \
--icon "LICENSE" 441 102 \ create-dmg \
--icon "README.md" 604 102 \ --volname "$(APP_NAME)" \
--app-drop-link 115 102 \ --window-pos 200 120 \
--hide-extension "$(APP_NAME).app" \ --window-size 720 300 \
"$(MACOS_INTEL_RELEASE)" \ --icon-size 96 \
"$(RELEASE_FOLDER)" || true --text-size 12 \
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)" --icon "$(APP_NAME).app" 278 102 \
--icon "LICENSE" 441 102 \
--icon "README.md" 604 102 \
--app-drop-link 115 102 \
--hide-extension "$(APP_NAME).app" \
"$(MACOS_INTEL_RELEASE)" \
"$(RELEASE_FOLDER)" || true; \
echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"; \
else \
echo ""; \
echo "============================================"; \
echo " WARNING: la build Intel ha fallado."; \
echo " Se omite el DMG Intel y se continúa con"; \
echo " la build de Apple Silicon."; \
echo "============================================"; \
echo ""; \
fi
# Compila la versión para procesadores Apple Silicon con cmake # Compila la versión para procesadores Apple Silicon con cmake
@echo ""
@echo "============================================"
@echo " Compilando version Apple Silicon (arm64)"
@echo "============================================"
@cmake -S . -B build/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH) @cmake -S . -B build/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH)
@cmake --build build/arm @cmake --build build/arm
cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"
# Firma la aplicación # Firma la aplicación

View File

@@ -219,7 +219,7 @@ AnimatedSprite::AnimatedSprite(std::shared_ptr<Surface> surface, SDL_FRect pos)
: MovingSprite(std::move(surface), pos) { : MovingSprite(std::move(surface), pos) {
// animations_ queda buit (protegit per el guard de animate()) // animations_ queda buit (protegit per el guard de animate())
if (surface_) { if (surface_) {
clip_ = {.x = 0, .y = 0, .w = surface_->getWidth(), .h = surface_->getHeight()}; clip_ = {.x = 0, .y = 0, .w = static_cast<float>(surface_->getWidth()), .h = static_cast<float>(surface_->getHeight())};
} }
} }

View File

@@ -35,8 +35,8 @@ auto DissolveSprite::computePixelRank(int col, int row, int frame_h, DissolveDir
DissolveSprite::DissolveSprite(std::shared_ptr<Surface> surface, SDL_FRect pos) DissolveSprite::DissolveSprite(std::shared_ptr<Surface> surface, SDL_FRect pos)
: AnimatedSprite(std::move(surface), pos) { : AnimatedSprite(std::move(surface), pos) {
if (surface_) { if (surface_) {
const int W = static_cast<int>(surface_->getWidth()); const int W = surface_->getWidth();
const int H = static_cast<int>(surface_->getHeight()); const int H = surface_->getHeight();
surface_display_ = std::make_shared<Surface>(W, H); surface_display_ = std::make_shared<Surface>(W, H);
surface_display_->setTransparentColor(surface_->getTransparentColor()); surface_display_->setTransparentColor(surface_->getTransparentColor());
surface_display_->clear(surface_->getTransparentColor()); surface_display_->clear(surface_->getTransparentColor());
@@ -47,8 +47,8 @@ DissolveSprite::DissolveSprite(std::shared_ptr<Surface> surface, SDL_FRect pos)
DissolveSprite::DissolveSprite(const AnimationResource& data) DissolveSprite::DissolveSprite(const AnimationResource& data)
: AnimatedSprite(data) { : AnimatedSprite(data) {
if (surface_) { if (surface_) {
const int W = static_cast<int>(surface_->getWidth()); const int W = surface_->getWidth();
const int H = static_cast<int>(surface_->getHeight()); const int H = surface_->getHeight();
surface_display_ = std::make_shared<Surface>(W, H); surface_display_ = std::make_shared<Surface>(W, H);
surface_display_->setTransparentColor(surface_->getTransparentColor()); surface_display_->setTransparentColor(surface_->getTransparentColor());
// Inicialitza tots els píxels com a transparents // Inicialitza tots els píxels com a transparents
@@ -75,8 +75,8 @@ void DissolveSprite::rebuildDisplaySurface() {
auto src_data = surface_->getSurfaceData(); auto src_data = surface_->getSurfaceData();
auto dst_data = surface_display_->getSurfaceData(); auto dst_data = surface_display_->getSurfaceData();
const int SRC_W = static_cast<int>(src_data->width); const int SRC_W = src_data->width;
const int DST_W = static_cast<int>(dst_data->width); const int DST_W = dst_data->width;
const Uint8 TRANSPARENT = surface_->getTransparentColor(); const Uint8 TRANSPARENT = surface_->getTransparentColor();
// Esborra frame anterior si ha canviat // Esborra frame anterior si ha canviat

View File

@@ -19,7 +19,7 @@ Sprite::Sprite() = default;
Sprite::Sprite(std::shared_ptr<Surface> surface) Sprite::Sprite(std::shared_ptr<Surface> surface)
: surface_(std::move(surface)), : surface_(std::move(surface)),
pos_{0.0F, 0.0F, surface_->getWidth(), surface_->getHeight()}, pos_{0.0F, 0.0F, static_cast<float>(surface_->getWidth()), static_cast<float>(surface_->getHeight())},
clip_(pos_) {} clip_(pos_) {}
// Muestra el sprite por pantalla // Muestra el sprite por pantalla

View File

@@ -104,7 +104,7 @@ Surface::Surface(const std::string& file_path)
} }
// Carga una superficie desde un archivo // Carga una superficie desde un archivo
auto Surface::loadSurface(const std::string& file_path) -> SurfaceData { // NOLINT(readability-convert-member-functions-to-static) auto Surface::loadSurface(const std::string& file_path) -> SurfaceData {
// Load file using ResourceHelper (supports both filesystem and pack) // Load file using ResourceHelper (supports both filesystem and pack)
std::vector<Uint8> buffer = Resource::Helper::loadFile(file_path); std::vector<Uint8> buffer = Resource::Helper::loadFile(file_path);
if (buffer.empty()) { if (buffer.empty()) {
@@ -129,7 +129,7 @@ auto Surface::loadSurface(const std::string& file_path) -> SurfaceData { // NOL
// Crear y devolver directamente el objeto SurfaceData // Crear y devolver directamente el objeto SurfaceData
printWithDots("Surface : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]"); printWithDots("Surface : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
return {static_cast<float>(w), static_cast<float>(h), pixels}; return {static_cast<int>(w), static_cast<int>(h), pixels};
} }
// Carga una paleta desde un archivo // Carga una paleta desde un archivo
@@ -149,7 +149,7 @@ void Surface::setColor(int index, Uint32 color) {
// Rellena la superficie con un color // Rellena la superficie con un color
void Surface::clear(Uint8 color) { // NOLINT(readability-convert-member-functions-to-static) void Surface::clear(Uint8 color) { // NOLINT(readability-convert-member-functions-to-static)
const size_t TOTAL_PIXELS = surface_data_->width * surface_data_->height; const size_t TOTAL_PIXELS = static_cast<size_t>(surface_data_->width) * static_cast<size_t>(surface_data_->height);
Uint8* data_ptr = surface_data_->data.get(); Uint8* data_ptr = surface_data_->data.get();
std::fill(data_ptr, data_ptr + TOTAL_PIXELS, color); std::fill(data_ptr, data_ptr + TOTAL_PIXELS, color);
} }
@@ -165,19 +165,19 @@ void Surface::putPixel(int x, int y, Uint8 color) { // NOLINT(readability-conve
} }
// Obtiene el color de un pixel de la surface_data // Obtiene el color de un pixel de la surface_data
auto Surface::getPixel(int x, int y) -> Uint8 { return surface_data_->data.get()[x + (y * static_cast<int>(surface_data_->width))]; } auto Surface::getPixel(int x, int y) -> Uint8 { return surface_data_->data.get()[x + (y * surface_data_->width)]; }
// Dibuja un rectangulo relleno // Dibuja un rectangulo relleno
void Surface::fillRect(const SDL_FRect* rect, Uint8 color) { // NOLINT(readability-convert-member-functions-to-static) void Surface::fillRect(const SDL_FRect* rect, Uint8 color) { // NOLINT(readability-convert-member-functions-to-static)
// Limitar los valores del rectángulo al tamaño de la superficie // Limitar los valores del rectángulo al tamaño de la superficie
float x_start = std::max(0.0F, rect->x); float x_start = std::max(0.0F, rect->x);
float y_start = std::max(0.0F, rect->y); float y_start = std::max(0.0F, rect->y);
float x_end = std::min(rect->x + rect->w, surface_data_->width); float x_end = std::min(rect->x + rect->w, static_cast<float>(surface_data_->width));
float y_end = std::min(rect->y + rect->h, surface_data_->height); float y_end = std::min(rect->y + rect->h, static_cast<float>(surface_data_->height));
// Rellenar fila a fila con memset (memoria contigua por fila) // Rellenar fila a fila con memset (memoria contigua por fila)
Uint8* data_ptr = surface_data_->data.get(); Uint8* data_ptr = surface_data_->data.get();
const int SURF_WIDTH = static_cast<int>(surface_data_->width); const int SURF_WIDTH = surface_data_->width;
const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start); const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start);
for (int y = static_cast<int>(y_start); y < static_cast<int>(y_end); ++y) { for (int y = static_cast<int>(y_start); y < static_cast<int>(y_end); ++y) {
std::memset(data_ptr + (y * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + (y * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
@@ -189,12 +189,12 @@ void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) { // NOLINT(re
// Limitar los valores del rectángulo al tamaño de la superficie // Limitar los valores del rectángulo al tamaño de la superficie
float x_start = std::max(0.0F, rect->x); float x_start = std::max(0.0F, rect->x);
float y_start = std::max(0.0F, rect->y); float y_start = std::max(0.0F, rect->y);
float x_end = std::min(rect->x + rect->w, surface_data_->width); float x_end = std::min(rect->x + rect->w, static_cast<float>(surface_data_->width));
float y_end = std::min(rect->y + rect->h, surface_data_->height); float y_end = std::min(rect->y + rect->h, static_cast<float>(surface_data_->height));
// Dibujar bordes horizontales con memset (líneas contiguas en memoria) // Dibujar bordes horizontales con memset (líneas contiguas en memoria)
Uint8* data_ptr = surface_data_->data.get(); Uint8* data_ptr = surface_data_->data.get();
const int SURF_WIDTH = static_cast<int>(surface_data_->width); const int SURF_WIDTH = surface_data_->width;
const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start); const int ROW_WIDTH = static_cast<int>(x_end) - static_cast<int>(x_start);
std::memset(data_ptr + (static_cast<int>(y_start) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + (static_cast<int>(y_start) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
std::memset(data_ptr + ((static_cast<int>(y_end) - 1) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH); std::memset(data_ptr + ((static_cast<int>(y_end) - 1) * SURF_WIDTH) + static_cast<int>(x_start), color, ROW_WIDTH);
@@ -211,68 +211,38 @@ void Surface::drawRectBorder(const SDL_FRect* rect, Uint8 color) { // NOLINT(re
} }
} }
// Dibuja una linea // Dibuja una linea (Bresenham en enteros)
void Surface::drawLine(float x1, float y1, float x2, float y2, Uint8 color) { // NOLINT(readability-convert-member-functions-to-static) void Surface::drawLine(float x1, float y1, float x2, float y2, Uint8 color) { // NOLINT(readability-convert-member-functions-to-static)
// Calcula las diferencias int ix1 = static_cast<int>(std::lround(x1));
float dx = std::abs(x2 - x1); int iy1 = static_cast<int>(std::lround(y1));
float dy = std::abs(y2 - y1); const int IX2 = static_cast<int>(std::lround(x2));
const int IY2 = static_cast<int>(std::lround(y2));
// Determina la dirección del incremento const int DX = std::abs(IX2 - ix1);
float sx = (x1 < x2) ? 1 : -1; const int DY = std::abs(IY2 - iy1);
float sy = (y1 < y2) ? 1 : -1; const int SX = (ix1 < IX2) ? 1 : -1;
const int SY = (iy1 < IY2) ? 1 : -1;
float err = dx - dy; const int SURF_W = surface_data_->width;
const int SURF_H = surface_data_->height;
Uint8* data_ptr = surface_data_->data.get();
int err = DX - DY;
while (true) { while (true) {
// Asegúrate de no dibujar fuera de los límites de la superficie if (ix1 >= 0 && ix1 < SURF_W && iy1 >= 0 && iy1 < SURF_H) {
if (x1 >= 0 && x1 < surface_data_->width && y1 >= 0 && y1 < surface_data_->height) { data_ptr[ix1 + (iy1 * SURF_W)] = color;
surface_data_->data.get()[static_cast<size_t>(x1 + (y1 * surface_data_->width))] = color;
} }
if (ix1 == IX2 && iy1 == IY2) {
// Si alcanzamos el punto final, salimos
if (x1 == x2 && y1 == y2) {
break; break;
} }
int e2 = 2 * err; int e2 = 2 * err;
if (e2 > -dy) { if (e2 > -DY) {
err -= dy; err -= DY;
x1 += sx; ix1 += SX;
} }
if (e2 < dx) { if (e2 < DX) {
err += dx; err += DX;
y1 += sy; iy1 += SY;
}
}
}
void Surface::render(float dx, float dy, float sx, float sy, float w, float h) { // NOLINT(readability-make-member-function-const)
auto surface_data = Screen::get()->getRendererSurface()->getSurfaceData();
// Limitar la región para evitar accesos fuera de rango en origen
w = std::min(w, surface_data_->width - sx);
h = std::min(h, surface_data_->height - sy);
// Limitar la región para evitar accesos fuera de rango en destino
w = std::min(w, surface_data->width - dx);
h = std::min(h, surface_data->height - dy);
const Uint8* src_ptr = surface_data_->data.get();
Uint8* dst_ptr = surface_data->data.get();
for (int iy = 0; iy < h; ++iy) {
for (int ix = 0; ix < w; ++ix) {
// Verificar que las coordenadas de destino están dentro de los límites
if (int dest_x = dx + ix; dest_x >= 0 && dest_x < surface_data->width) {
if (int dest_y = dy + iy; dest_y >= 0 && dest_y < surface_data->height) {
int src_x = sx + ix;
int src_y = sy + iy;
Uint8 color = src_ptr[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
if (color != static_cast<Uint8>(transparent_color_)) {
dst_ptr[static_cast<size_t>(dest_x + (dest_y * surface_data->width))] = sub_palette_[color];
}
}
}
} }
} }
} }
@@ -283,18 +253,14 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) { //
// Determina la región de origen (clip) a renderizar // Determina la región de origen (clip) a renderizar
float sx = (src_rect != nullptr) ? src_rect->x : 0; float sx = (src_rect != nullptr) ? src_rect->x : 0;
float sy = (src_rect != nullptr) ? src_rect->y : 0; float sy = (src_rect != nullptr) ? src_rect->y : 0;
float w = (src_rect != nullptr) ? src_rect->w : surface_data_->width; float w = (src_rect != nullptr) ? src_rect->w : static_cast<float>(surface_data_->width);
float h = (src_rect != nullptr) ? src_rect->h : surface_data_->height; float h = (src_rect != nullptr) ? src_rect->h : static_cast<float>(surface_data_->height);
// Limitar la región para evitar accesos fuera de rango en origen // Limitar la región para evitar accesos fuera de rango (origen y destino)
w = std::min(w, surface_data_->width - sx); w = std::min(w, static_cast<float>(surface_data_->width) - sx);
h = std::min(h, surface_data_->height - sy); h = std::min(h, static_cast<float>(surface_data_->height) - sy);
w = std::min(w, surface_data_dest->width - x); w = std::min(w, static_cast<float>(surface_data_dest->width - x));
h = std::min(h, surface_data_dest->height - y); h = std::min(h, static_cast<float>(surface_data_dest->height - y));
// Limitar la región para evitar accesos fuera de rango en destino
w = std::min(w, surface_data_dest->width - x);
h = std::min(h, surface_data_dest->height - y);
// Renderiza píxel por píxel aplicando el flip si es necesario // Renderiza píxel por píxel aplicando el flip si es necesario
const Uint8* src_ptr = surface_data_->data.get(); const Uint8* src_ptr = surface_data_->data.get();
@@ -322,7 +288,7 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) { //
} }
// Helper para calcular coordenadas con flip // Helper para calcular coordenadas con flip
void Surface::calculateFlippedCoords(int ix, int iy, float sx, float sy, float w, float h, SDL_FlipMode flip, int& src_x, int& src_y) { void Surface::calculateFlippedCoords(int ix, int iy, int sx, int sy, int w, int h, SDL_FlipMode flip, int& src_x, int& src_y) {
src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + w - 1 - ix) : (sx + ix); src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + w - 1 - ix) : (sx + ix);
src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + h - 1 - iy) : (sy + iy); src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + h - 1 - iy) : (sy + iy);
} }
@@ -418,11 +384,11 @@ void Surface::renderWithColorReplace(int x, int y, Uint8 source_color, Uint8 tar
continue; // Saltar píxeles fuera del rango del destino continue; // Saltar píxeles fuera del rango del destino
} }
// Copia el píxel si no es transparente // Copia el píxel si no es transparente; aplica sub_palette_ como el resto de render*
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))]; Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
if (color != static_cast<Uint8>(transparent_color_)) { if (color != static_cast<Uint8>(transparent_color_)) {
surface_data->data[dest_x + (dest_y * surface_data->width)] = surface_data->data[dest_x + (dest_y * surface_data->width)] =
(color == source_color) ? target_color : color; (color == source_color) ? target_color : sub_palette_[color];
} }
} }
} }
@@ -452,14 +418,14 @@ static auto computeFadeDensity(int screen_y, int fade_h, int canvas_height) -> f
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect) const { void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect) const {
const int SX = (src_rect != nullptr) ? static_cast<int>(src_rect->x) : 0; const int SX = (src_rect != nullptr) ? static_cast<int>(src_rect->x) : 0;
const int SY = (src_rect != nullptr) ? static_cast<int>(src_rect->y) : 0; const int SY = (src_rect != nullptr) ? static_cast<int>(src_rect->y) : 0;
const int SW = (src_rect != nullptr) ? static_cast<int>(src_rect->w) : static_cast<int>(surface_data_->width); const int SW = (src_rect != nullptr) ? static_cast<int>(src_rect->w) : surface_data_->width;
const int SH = (src_rect != nullptr) ? static_cast<int>(src_rect->h) : static_cast<int>(surface_data_->height); const int SH = (src_rect != nullptr) ? static_cast<int>(src_rect->h) : surface_data_->height;
auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData(); auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData();
for (int row = 0; row < SH; row++) { for (int row = 0; row < SH; row++) {
const int SCREEN_Y = y + row; const int SCREEN_Y = y + row;
if (SCREEN_Y < 0 || SCREEN_Y >= static_cast<int>(surface_data_dest->height)) { if (SCREEN_Y < 0 || SCREEN_Y >= surface_data_dest->height) {
continue; continue;
} }
@@ -467,11 +433,11 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
for (int col = 0; col < SW; col++) { for (int col = 0; col < SW; col++) {
const int SCREEN_X = x + col; const int SCREEN_X = x + col;
if (SCREEN_X < 0 || SCREEN_X >= static_cast<int>(surface_data_dest->width)) { if (SCREEN_X < 0 || SCREEN_X >= surface_data_dest->width) {
continue; continue;
} }
const Uint8 COLOR = surface_data_->data[((SY + row) * static_cast<int>(surface_data_->width)) + (SX + col)]; const Uint8 COLOR = surface_data_->data[((SY + row) * surface_data_->width) + (SX + col)];
if (COLOR == static_cast<Uint8>(transparent_color_)) { if (COLOR == static_cast<Uint8>(transparent_color_)) {
continue; continue;
} }
@@ -480,7 +446,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
continue; // Pixel tapat per la zona de fade continue; // Pixel tapat per la zona de fade
} }
surface_data_dest->data[SCREEN_X + (SCREEN_Y * static_cast<int>(surface_data_dest->width))] = sub_palette_[COLOR]; surface_data_dest->data[SCREEN_X + (SCREEN_Y * surface_data_dest->width)] = sub_palette_[COLOR];
} }
} }
} }
@@ -489,14 +455,14 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect) const { void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect) const {
const int SX = (src_rect != nullptr) ? static_cast<int>(src_rect->x) : 0; const int SX = (src_rect != nullptr) ? static_cast<int>(src_rect->x) : 0;
const int SY = (src_rect != nullptr) ? static_cast<int>(src_rect->y) : 0; const int SY = (src_rect != nullptr) ? static_cast<int>(src_rect->y) : 0;
const int SW = (src_rect != nullptr) ? static_cast<int>(src_rect->w) : static_cast<int>(surface_data_->width); const int SW = (src_rect != nullptr) ? static_cast<int>(src_rect->w) : surface_data_->width;
const int SH = (src_rect != nullptr) ? static_cast<int>(src_rect->h) : static_cast<int>(surface_data_->height); const int SH = (src_rect != nullptr) ? static_cast<int>(src_rect->h) : surface_data_->height;
auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData(); auto surface_data_dest = Screen::get()->getRendererSurface()->getSurfaceData();
for (int row = 0; row < SH; row++) { for (int row = 0; row < SH; row++) {
const int SCREEN_Y = y + row; const int SCREEN_Y = y + row;
if (SCREEN_Y < 0 || SCREEN_Y >= static_cast<int>(surface_data_dest->height)) { if (SCREEN_Y < 0 || SCREEN_Y >= surface_data_dest->height) {
continue; continue;
} }
@@ -504,11 +470,11 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
for (int col = 0; col < SW; col++) { for (int col = 0; col < SW; col++) {
const int SCREEN_X = x + col; const int SCREEN_X = x + col;
if (SCREEN_X < 0 || SCREEN_X >= static_cast<int>(surface_data_dest->width)) { if (SCREEN_X < 0 || SCREEN_X >= surface_data_dest->width) {
continue; continue;
} }
const Uint8 COLOR = surface_data_->data[((SY + row) * static_cast<int>(surface_data_->width)) + (SX + col)]; const Uint8 COLOR = surface_data_->data[((SY + row) * surface_data_->width) + (SX + col)];
if (COLOR == static_cast<Uint8>(transparent_color_)) { if (COLOR == static_cast<Uint8>(transparent_color_)) {
continue; continue;
} }
@@ -518,7 +484,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
} }
const Uint8 OUT_COLOR = (COLOR == source_color) ? target_color : sub_palette_[COLOR]; const Uint8 OUT_COLOR = (COLOR == source_color) ? target_color : sub_palette_[COLOR];
surface_data_dest->data[SCREEN_X + (SCREEN_Y * static_cast<int>(surface_data_dest->width))] = OUT_COLOR; surface_data_dest->data[SCREEN_X + (SCREEN_Y * surface_data_dest->width)] = OUT_COLOR;
} }
} }
} }
@@ -527,8 +493,8 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height
void Surface::toARGBBuffer(Uint32* buffer) const { void Surface::toARGBBuffer(Uint32* buffer) const {
if (!surface_data_ || !surface_data_->data || (buffer == nullptr)) { return; } if (!surface_data_ || !surface_data_->data || (buffer == nullptr)) { return; }
const int WIDTH = static_cast<int>(surface_data_->width); const int WIDTH = surface_data_->width;
const int HEIGHT = static_cast<int>(surface_data_->height); const int HEIGHT = surface_data_->height;
const Uint8* src = surface_data_->data.get(); const Uint8* src = surface_data_->data.get();
// Obtenemos el tamaño de la paleta para evitar accesos fuera de rango // Obtenemos el tamaño de la paleta para evitar accesos fuera de rango
@@ -639,11 +605,8 @@ void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FR
// Realiza un efecto de fundido en la paleta principal // Realiza un efecto de fundido en la paleta principal
auto Surface::fadePalette() -> bool { // NOLINT(readability-convert-member-functions-to-static) auto Surface::fadePalette() -> bool { // NOLINT(readability-convert-member-functions-to-static)
// Verificar que el tamaño mínimo de palette_ sea adecuado
static constexpr int PALETTE_SIZE = 19; static constexpr int PALETTE_SIZE = 19;
if (sizeof(palette_) / sizeof(palette_[0]) < PALETTE_SIZE) { static_assert(std::tuple_size_v<Palette> >= PALETTE_SIZE, "Palette size is insufficient for fadePalette operation.");
throw std::runtime_error("Palette size is insufficient for fadePalette operation.");
}
// Desplazar colores (pares e impares) // Desplazar colores (pares e impares)
for (int i = 18; i > 1; --i) { for (int i = 18; i > 1; --i) {
@@ -673,11 +636,8 @@ auto Surface::fadeSubPalette(Uint32 delay) -> bool { // NOLINT(readability-conv
// Actualizar el último tick // Actualizar el último tick
last_tick_ = current_tick; last_tick_ = current_tick;
// Verificar que el tamaño mínimo de sub_palette_ sea adecuado
static constexpr int SUB_PALETTE_SIZE = 19; static constexpr int SUB_PALETTE_SIZE = 19;
if (sizeof(sub_palette_) / sizeof(sub_palette_[0]) < SUB_PALETTE_SIZE) { static_assert(std::tuple_size_v<SubPalette> >= SUB_PALETTE_SIZE, "Sub-palette size is insufficient for fadeSubPalette operation.");
throw std::runtime_error("Palette size is insufficient for fadePalette operation.");
}
// Desplazar colores (pares e impares) // Desplazar colores (pares e impares)
for (int i = 18; i > 1; --i) { for (int i = 18; i > 1; --i) {

View File

@@ -22,8 +22,8 @@ auto readPalFile(const std::string& file_path) -> Palette;
struct SurfaceData { struct SurfaceData {
std::shared_ptr<Uint8[]> data; // Usa std::shared_ptr para gestión automática std::shared_ptr<Uint8[]> data; // Usa std::shared_ptr para gestión automática
float width; // Ancho de la imagen int width; // Ancho de la imagen
float height; // Alto de la imagen int height; // Alto de la imagen
// Constructor por defecto // Constructor por defecto
SurfaceData() SurfaceData()
@@ -32,13 +32,13 @@ struct SurfaceData {
height(0) {} height(0) {}
// Constructor que inicializa dimensiones y asigna memoria // Constructor que inicializa dimensiones y asigna memoria
SurfaceData(float w, float h) SurfaceData(int w, int h)
: data(std::shared_ptr<Uint8[]>(new Uint8[static_cast<size_t>(w * h)](), std::default_delete<Uint8[]>())), : data(std::shared_ptr<Uint8[]>(new Uint8[static_cast<size_t>(w) * static_cast<size_t>(h)](), std::default_delete<Uint8[]>())),
width(w), width(w),
height(h) {} height(h) {}
// Constructor para inicializar directamente con datos // Constructor para inicializar directamente con datos
SurfaceData(float w, float h, std::shared_ptr<Uint8[]> pixels) SurfaceData(int w, int h, std::shared_ptr<Uint8[]> pixels)
: data(std::move(pixels)), : data(std::move(pixels)),
width(w), width(w),
height(h) {} height(h) {}
@@ -56,6 +56,9 @@ struct SurfaceData {
class Surface { class Surface {
private: private:
// shared_ptr porque render() accede al SurfaceData propio y al del renderer
// surface (ver getRendererSurface()) de forma efímera; con self-blit ambos
// pueden alias y el refcount evita free accidental durante el recorrido.
std::shared_ptr<SurfaceData> surface_data_; // Datos a dibujar std::shared_ptr<SurfaceData> surface_data_; // Datos a dibujar
Palette palette_; // Paleta para volcar la SurfaceData a una Textura Palette palette_; // Paleta para volcar la SurfaceData a una Textura
SubPalette sub_palette_; // Paleta para reindexar colores SubPalette sub_palette_; // Paleta para reindexar colores
@@ -77,7 +80,6 @@ class Surface {
void loadPalette(const Palette& palette); void loadPalette(const Palette& palette);
// Copia una región de la SurfaceData de origen a la SurfaceData de destino // Copia una región de la SurfaceData de origen a la SurfaceData de destino
void render(float dx, float dy, float sx, float sy, float w, float h);
void render(int x, int y, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); void render(int x, int y, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
void render(SDL_FRect* src_rect = nullptr, SDL_FRect* dst_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); void render(SDL_FRect* src_rect = nullptr, SDL_FRect* dst_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
@@ -127,11 +129,10 @@ class Surface {
// Metodos para gestionar surface_data_ // Metodos para gestionar surface_data_
[[nodiscard]] auto getSurfaceData() const -> std::shared_ptr<SurfaceData> { return surface_data_; } [[nodiscard]] auto getSurfaceData() const -> std::shared_ptr<SurfaceData> { return surface_data_; }
void setSurfaceData(std::shared_ptr<SurfaceData> new_data) { surface_data_ = std::move(new_data); }
// Obtien ancho y alto // Obtien ancho y alto
[[nodiscard]] auto getWidth() const -> float { return surface_data_->width; } [[nodiscard]] auto getWidth() const -> int { return surface_data_->width; }
[[nodiscard]] auto getHeight() const -> float { return surface_data_->height; } [[nodiscard]] auto getHeight() const -> int { return surface_data_->height; }
// Color transparente // Color transparente
[[nodiscard]] auto getTransparentColor() const -> Uint8 { return transparent_color_; } [[nodiscard]] auto getTransparentColor() const -> Uint8 { return transparent_color_; }
@@ -146,7 +147,7 @@ class Surface {
private: private:
// Helper para calcular coordenadas con flip // Helper para calcular coordenadas con flip
static void calculateFlippedCoords(int ix, int iy, float sx, float sy, float w, float h, SDL_FlipMode flip, int& src_x, int& src_y); static void calculateFlippedCoords(int ix, int iy, int sx, int sy, int w, int h, SDL_FlipMode flip, int& src_x, int& src_y);
// Helper para copiar un pixel si no es transparente // Helper para copiar un pixel si no es transparente
void copyPixelIfNotTransparent(Uint8* dest_data, int dest_x, int dest_y, int dest_width, int src_x, int src_y) const; void copyPixelIfNotTransparent(Uint8* dest_data, int dest_x, int dest_y, int dest_width, int src_x, int src_y) const;

View File

@@ -39,9 +39,9 @@ void MiniMap::buildTileColorTable(const std::string& tileset_name) {
auto tileset = Resource::Cache::get()->getSurface(tileset_name); auto tileset = Resource::Cache::get()->getSurface(tileset_name);
if (!tileset) { return; } if (!tileset) { return; }
tileset_width_ = static_cast<int>(tileset->getWidth()) / Tile::SIZE; tileset_width_ = tileset->getWidth() / Tile::SIZE;
tileset_transparent_ = tileset->getTransparentColor(); tileset_transparent_ = tileset->getTransparentColor();
int tileset_height = static_cast<int>(tileset->getHeight()) / Tile::SIZE; int tileset_height = tileset->getHeight() / Tile::SIZE;
int total_tiles = tileset_width_ * tileset_height; int total_tiles = tileset_width_ * tileset_height;
tile_colors_.resize(total_tiles, 0); tile_colors_.resize(total_tiles, 0);

View File

@@ -26,8 +26,8 @@ void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_
// Calcular dimensiones del tileset en tiles (teniendo en cuenta spacing de entrada) // Calcular dimensiones del tileset en tiles (teniendo en cuenta spacing de entrada)
int src_cell = Tile::SIZE + spacing_in_; int src_cell = Tile::SIZE + spacing_in_;
tileset_width_ = static_cast<int>(tileset_->getWidth()) / src_cell; tileset_width_ = tileset_->getWidth() / src_cell;
tileset_height_ = static_cast<int>(tileset_->getHeight()) / src_cell; tileset_height_ = tileset_->getHeight() / src_cell;
// Corregir si el último tile cabe sin spacing // Corregir si el último tile cabe sin spacing
if (tileset_width_ == 0 && tileset_->getWidth() >= Tile::SIZE) { tileset_width_ = 1; } if (tileset_width_ == 0 && tileset_->getWidth() >= Tile::SIZE) { tileset_width_ = 1; }
if (tileset_height_ == 0 && tileset_->getHeight() >= Tile::SIZE) { tileset_height_ = 1; } if (tileset_height_ == 0 && tileset_->getHeight() >= Tile::SIZE) { tileset_height_ = 1; }

View File

@@ -502,7 +502,7 @@ void Title::createCheevosTexture() { // NOLINT(readability-convert-member-funct
// Crea el sprite para el listado de logros (usa la zona del menu) // Crea el sprite para el listado de logros (usa la zona del menu)
cheevos_sprite_ = std::make_unique<Sprite>(cheevos_surface_, (GameCanvas::WIDTH - cheevos_surface_->getWidth()) / 2, MENU_ZONE_Y, cheevos_surface_->getWidth(), cheevos_surface_->getHeight()); cheevos_sprite_ = std::make_unique<Sprite>(cheevos_surface_, (GameCanvas::WIDTH - cheevos_surface_->getWidth()) / 2, MENU_ZONE_Y, cheevos_surface_->getWidth(), cheevos_surface_->getHeight());
cheevos_surface_view_ = {.x = 0, .y = 0, .w = cheevos_surface_->getWidth(), .h = CHEEVOS_TEXTURE_VIEW_HEIGHT}; cheevos_surface_view_ = {.x = 0, .y = 0, .w = static_cast<float>(cheevos_surface_->getWidth()), .h = CHEEVOS_TEXTURE_VIEW_HEIGHT};
cheevos_sprite_->setClip(cheevos_surface_view_); cheevos_sprite_->setClip(cheevos_surface_view_);
} }

View File

@@ -225,7 +225,7 @@ void Notifier::show(std::vector<std::string> texts, const Style& style, int icon
else if (SHAPE == Shape::SQUARED) { else if (SHAPE == Shape::SQUARED) {
n.surface->clear(style.bg_color); n.surface->clear(style.bg_color);
SDL_FRect squared_rect = {.x = 0, .y = 0, .w = n.surface->getWidth(), .h = n.surface->getHeight()}; SDL_FRect squared_rect = {.x = 0, .y = 0, .w = static_cast<float>(n.surface->getWidth()), .h = static_cast<float>(n.surface->getHeight())};
n.surface->drawRectBorder(&squared_rect, style.border_color); n.surface->drawRectBorder(&squared_rect, style.border_color);
} }