Replace SDL image with stb_image

This commit is contained in:
Cong
2025-04-16 12:34:57 +10:00
parent 1352d94220
commit 046c30fe1f
17 changed files with 8938 additions and 228 deletions

View File

@@ -57,7 +57,7 @@ jobs:
run: |
sudo apt-get update
sudo apt install python3-pip libgl1-mesa-dev
sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev
sudo apt install libsdl2-dev libsdl2-mixer-dev
python3 -m pip install protobuf --break-system-packages
pip3 install --upgrade protobuf --break-system-packages
@@ -82,7 +82,7 @@ jobs:
- name: Install dependencies (Windows)
if: matrix.os == 'windows-latest'
run: C:\vcpkg\vcpkg.exe install --triplet x64-windows sdl2 sdl2-image sdl2-mixer[core,mpg123] protobuf --recurse
run: C:\vcpkg\vcpkg.exe install --triplet x64-windows sdl2 sdl2-mixer[core,mpg123] protobuf --recurse
- name: Configure CMake
env:
@@ -114,14 +114,6 @@ jobs:
file-name: 'sdl2.zip'
location: './dll'
- name: Download SDL2_image DLLs on tags (Windows)
if: startsWith(github.ref, 'refs/tags/') && matrix.os == 'windows-latest'
uses: carlosperate/download-file-action@v2
with:
file-url: 'https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.8.1-win32-x64.zip'
file-name: 'sdl2_image.zip'
location: './dll'
- name: Download SDL2_mixer DLLs on tags (Windows)
if: startsWith(github.ref, 'refs/tags/') && matrix.os == 'windows-latest'
uses: carlosperate/download-file-action@v2
@@ -135,7 +127,6 @@ jobs:
run: |
cd dll
7z x -y sdl2.zip
7z x -y sdl2_image.zip
7z x -y sdl2_mixer.zip
copy .\optional\*.dll .
dir

View File

@@ -57,7 +57,7 @@ jobs:
run: |
sudo apt-get update
sudo apt install python3-pip libgl1-mesa-dev
sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev
sudo apt install libsdl2-dev libsdl2-mixer-dev
python3 -m pip install protobuf --break-system-packages
pip3 install --upgrade protobuf --break-system-packages
@@ -82,7 +82,7 @@ jobs:
- name: Install dependencies (Windows)
if: matrix.os == 'windows-latest'
run: C:\vcpkg\vcpkg.exe install --triplet x64-windows sdl2 sdl2-image sdl2-mixer[core,mpg123] protobuf --recurse
run: C:\vcpkg\vcpkg.exe install --triplet x64-windows sdl2 sdl2-mixer[core,mpg123] protobuf --recurse
- name: Configure CMake
env:
@@ -114,14 +114,6 @@ jobs:
file-name: 'sdl2.zip'
location: './dll'
- name: Download SDL2_image DLLs on tags (Windows)
if: startsWith(github.ref, 'refs/tags/') && matrix.os == 'windows-latest'
uses: carlosperate/download-file-action@v2
with:
file-url: 'https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.8.1-win32-x64.zip'
file-name: 'sdl2_image.zip'
location: './dll'
- name: Download SDL2_mixer DLLs on tags (Windows)
if: startsWith(github.ref, 'refs/tags/') && matrix.os == 'windows-latest'
uses: carlosperate/download-file-action@v2
@@ -135,7 +127,6 @@ jobs:
run: |
cd dll
7z x -y sdl2.zip
7z x -y sdl2_image.zip
7z x -y sdl2_mixer.zip
copy .\optional\*.dll .
dir

View File

@@ -1,20 +0,0 @@
/*
SDL_image: An example image loading library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

View File

@@ -4,14 +4,11 @@ set -e
OSX_LIB_PATH="/Library/Frameworks"
OSX_SDL2_PATH_FULL="$OSX_LIB_PATH/SDL2.framework"
OSX_SDL2_IMAGE_PATH_FULL="$OSX_LIB_PATH/SDL2_image.framework"
OSX_SDL2_MIXER_PATH_FULL="$OSX_LIB_PATH/SDL2_mixer.framework"
SDL2_VERSION=2.26.4
SDL2_IMAGE_VERSION=2.8.1
SDL2_MIXER_VERSION=2.6.3
SDL2_URL=https://www.libsdl.org/release/SDL2-$SDL2_VERSION.dmg
SDL2_IMAGE_URL=https://www.libsdl.org/projects/SDL_image/release/SDL2_image-$SDL2_IMAGE_VERSION.dmg
SDL2_MIXER_URL=https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-$SDL2_MIXER_VERSION.dmg
function installDMG {
@@ -37,10 +34,6 @@ function getSdl2 {
installDMG $SDL2_URL
}
function getSdl2_image {
installDMG $SDL2_IMAGE_URL
}
function getSdl2_mixer {
installDMG $SDL2_MIXER_URL
}
@@ -49,7 +42,6 @@ if [[ "$1" == "--force" ]]
then
echo "Force build requested by --force."
getSdl2
getSdl2_image
getSdl2_mixer
exit
fi
@@ -68,19 +60,6 @@ else
getSdl2
fi
if [[ -d "$OSX_SDL2_IMAGE_PATH_FULL" ]]; then
if [[ -n "$(ls -A $OSX_SDL2_IMAGE_PATH_FULL)" ]]
then
echo "SDL2_image exists. Skip building..."
else
echo "SDL2_image dir exists buit it is empty..."
getSdl2_image
fi
else
echo "SDL2_image dir missing..."
getSdl2_image
fi
if [[ -d "$OSX_SDL2_MIXER_PATH_FULL" ]]; then
if [[ -n "$(ls -A $OSX_SDL2_MIXER_PATH_FULL)" ]]
then

View File

@@ -3,7 +3,6 @@ setlocal enabledelayedexpansion
set EXTRACT_COMMAND=7z x -y
set SDL2_VERSION=2.26.4
set SDL2_IMAGE_VERSION=2.8.1
set SDL2_MIXER_VERSION=2.6.3
@@ -16,9 +15,6 @@ rem PLEASE NO SPACES IN SDL2_* VARIABLES
set SDL2_ARCHIVE=SDL2-%SDL2_VERSION%-win32-x%BITS%.zip
set SDL2_URL=https://www.libsdl.org/release/%SDL2_ARCHIVE%
set SDL2_IMAGE_ARCHIVE=SDL2_image-%SDL2_IMAGE_VERSION%-win32-x%BITS%.zip
set SDL2_IMAGE_URL=https://www.libsdl.org/projects/SDL_image/release/%SDL2_IMAGE_ARCHIVE%
set SDL2_MIXER_ARCHIVE=SDL2_mixer-%SDL2_MIXER_VERSION%-win32-x%BITS%.zip
set SDL2_MIXER_URL=https://www.libsdl.org/projects/SDL_mixer/release/%SDL2_MIXER_ARCHIVE%
@@ -41,11 +37,9 @@ echo cd into "!DESTDIR!"
cd "!DESTDIR!"
call :downloadIfNeeded !SDL2_URL!
call :downloadIfNeeded !SDL2_IMAGE_URL!
call :downloadIfNeeded !SDL2_MIXER_URL!
%EXTRACT_COMMAND% !SDL2_ARCHIVE!
%EXTRACT_COMMAND% !SDL2_IMAGE_ARCHIVE!
%EXTRACT_COMMAND% !SDL2_MIXER_ARCHIVE!
rem Copy optional DLLs within the optional folders

View File

@@ -28,25 +28,17 @@
#include <stdio.h>
#include <string.h>
#ifdef __EMSCRIPTEN__
#include <SDL2/SDL_image.h>
#else
#include <SDL_image.h>
#endif
#include "blit.h"
#include "log.h"
#include "pic.h"
#include "sys_config.h"
#include "utils.h"
#define FIRST_CHAR 0
#define LAST_CHAR 255
Font gFont;
FontOpts FontOptsNew(void)
{
FontOpts opts;
@@ -61,13 +53,10 @@ void FontLoad(
{
char buf[CDOGS_PATH_MAX];
GetDataFilePath(buf, imgPath);
SDL_RWops *rwops = SDL_RWFromFile(buf, "rb");
CASSERT(IMG_isPNG(rwops), "Error: font file is not PNG");
SDL_Surface *image = IMG_Load_RW(rwops, 0);
rwops->close(rwops);
SDL_Surface *image = LoadImgToSurface(buf);
if (!image)
{
LOG(LM_GFX, LL_ERROR, "Cannot load font image: %s", IMG_GetError());
LOG(LM_GFX, LL_ERROR, "Cannot load font image");
return;
}
if (image->format->BytesPerPixel != 4)
@@ -88,10 +77,9 @@ void FontLoad(
LOG(LM_GFX, LL_ERROR,
"Error: font image not big enough for font data "
"Image %dx%d Size %dx%d Stride %d Padding %d,%d,%d,%d",
image->w, image->h,
f->Size.x, f->Size.y, f->Stride,
f->Padding.Left, f->Padding.Top,
f->Padding.Right, f->Padding.Bottom);
image->w, image->h, f->Size.x, f->Size.y, f->Stride,
f->Padding.Left, f->Padding.Top, f->Padding.Right,
f->Padding.Bottom);
return;
}
@@ -99,13 +87,12 @@ void FontLoad(
SDL_LockSurface(image);
int chars = 0;
for (struct vec2i pos = svec2i_zero();
pos.y + step.y <= image->h && chars < LAST_CHAR - FIRST_CHAR + 1;
pos.y += step.y)
pos.y + step.y <= image->h && chars < LAST_CHAR - FIRST_CHAR + 1;
pos.y += step.y)
{
int x = 0;
for (pos.x = 0;
x < f->Stride && chars < LAST_CHAR - FIRST_CHAR + 1;
pos.x += step.x, x++, chars++)
for (pos.x = 0; x < f->Stride && chars < LAST_CHAR - FIRST_CHAR + 1;
pos.x += step.x, x++, chars++)
{
Pic p;
// TODO: HD fonts
@@ -129,7 +116,7 @@ void FontLoad(
void FontTerminate(Font *f)
{
CA_FOREACH(Pic, p, f->Chars)
PicFree(p);
PicFree(p);
CA_FOREACH_END()
CArrayTerminate(&f->Chars);
}
@@ -217,7 +204,8 @@ struct vec2i FontCh(const char c, const struct vec2i pos)
{
return FontChMask(c, pos, colorWhite);
}
struct vec2i FontChMask(const char c, const struct vec2i pos, const color_t mask)
struct vec2i FontChMask(
const char c, const struct vec2i pos, const color_t mask)
{
int idx = (int)c - FIRST_CHAR;
if (idx < 0)
@@ -262,14 +250,16 @@ struct vec2i FontStrMask(const char *s, struct vec2i pos, const color_t mask)
}
return pos;
}
struct vec2i FontStrMaskWrap(const char *s, struct vec2i pos, color_t mask, const int width)
struct vec2i FontStrMaskWrap(
const char *s, struct vec2i pos, color_t mask, const int width)
{
char buf[1024];
CASSERT(strlen(s) < 1024, "string too long to wrap");
FontSplitLines(s, buf, width);
return FontStrMask(buf, pos, mask);
}
static struct vec2i GetStrPos(const char *s, struct vec2i pos, const FontOpts opts);
static struct vec2i GetStrPos(
const char *s, struct vec2i pos, const FontOpts opts);
void FontStrOpt(const char *s, struct vec2i pos, const FontOpts opts)
{
if (s == NULL)
@@ -280,9 +270,10 @@ void FontStrOpt(const char *s, struct vec2i pos, const FontOpts opts)
FontStrMask(s, pos, opts.Mask);
}
static int GetAlign(
const FontAlign align,
const int pos, const int pad, const int area, const int size);
static struct vec2i GetStrPos(const char *s, struct vec2i pos, const FontOpts opts)
const FontAlign align, const int pos, const int pad, const int area,
const int size);
static struct vec2i GetStrPos(
const char *s, struct vec2i pos, const FontOpts opts)
{
const struct vec2i textSize = FontStrSize(s);
return svec2i(
@@ -290,8 +281,8 @@ static struct vec2i GetStrPos(const char *s, struct vec2i pos, const FontOpts op
GetAlign(opts.VAlign, pos.y, opts.Pad.y, opts.Area.y, textSize.y));
}
static int GetAlign(
const FontAlign align,
const int pos, const int pad, const int area, const int size)
const FontAlign align, const int pos, const int pad, const int area,
const int size)
{
switch (align)
{
@@ -385,8 +376,8 @@ void FontSplitLines(const char *text, char *buf, const int width)
}
struct vec2i Vec2iAligned(
const struct vec2i v, const struct vec2i size,
const FontAlign hAlign, const FontAlign vAlign, const struct vec2i area)
const struct vec2i v, const struct vec2i size, const FontAlign hAlign,
const FontAlign vAlign, const struct vec2i area)
{
struct vec2i vAligned = v;
switch (hAlign)

View File

@@ -1,78 +1,72 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (C) 1995 Ronny Wester
Copyright (C) 2003 Jeremy Chin
Copyright (C) 2003-2007 Lucas Martin-King
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (C) 1995 Ronny Wester
Copyright (C) 2003 Jeremy Chin
Copyright (C) 2003-2007 Lucas Martin-King
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This file incorporates work covered by the following copyright and
permission notice:
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2019 Cong Xu
All rights reserved.
Copyright (c) 2013-2019 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "grafx.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <SDL_events.h>
#ifdef __EMSCRIPTEN__
#include <SDL2/SDL_image.h>
#else
#include <SDL_image.h>
#endif
#include <SDL_mouse.h>
#include "blit.h"
#include "config.h"
#include "defs.h"
#include "draw/drawtools.h"
#include "files.h"
#include "font_utils.h"
#include "grafx_bg.h"
#include "log.h"
#include "palette.h"
#include "files.h"
#include "utils.h"
GraphicsDevice gGraphicsDevice;
void GraphicsInit(GraphicsDevice *device, Config *c)
@@ -96,7 +90,7 @@ void GraphicsInitialize(GraphicsDevice *g)
{
char buf[CDOGS_PATH_MAX];
GetDataFilePath(buf, "graphics/cdogs_icon.bmp");
g->icon = IMG_Load(buf);
g->icon = LoadImgToSurface(buf);
g->IsWindowInitialized = true;
}
@@ -105,19 +99,17 @@ void GraphicsInitialize(GraphicsDevice *g)
const int w = g->cachedConfig.Res.x;
const int h = g->cachedConfig.Res.y;
const bool initWindow =
!!(g->cachedConfig.RestartFlags & RESTART_WINDOW);
const bool initTextures =
!!(g->cachedConfig.RestartFlags &
(RESTART_WINDOW | RESTART_SCALE_MODE));
const bool initWindow = !!(g->cachedConfig.RestartFlags & RESTART_WINDOW);
const bool initTextures = !!(
g->cachedConfig.RestartFlags & (RESTART_WINDOW | RESTART_SCALE_MODE));
const bool initBrightness =
!!(g->cachedConfig.RestartFlags &
(RESTART_WINDOW | RESTART_SCALE_MODE | RESTART_BRIGHTNESS));
(RESTART_WINDOW | RESTART_SCALE_MODE | RESTART_BRIGHTNESS));
if (initWindow)
{
LOG(LM_GFX, LL_INFO, "graphics mode(%dx%d %dx%s)",
w, h, g->cachedConfig.ScaleFactor,
LOG(LM_GFX, LL_INFO, "graphics mode(%dx%d %dx%s)", w, h,
g->cachedConfig.ScaleFactor,
g->cachedConfig.Fullscreen ? " fullscreen" : "");
Uint32 windowFlags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
@@ -125,9 +117,7 @@ void GraphicsInitialize(GraphicsDevice *g)
svec2i(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED),
svec2i(
ConfigGetInt(&gConfig, "Graphics.WindowWidth"),
ConfigGetInt(&gConfig, "Graphics.WindowHeight")
)
);
ConfigGetInt(&gConfig, "Graphics.WindowHeight")));
if (g->cachedConfig.Fullscreen)
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
@@ -139,9 +129,9 @@ void GraphicsInitialize(GraphicsDevice *g)
SDL_FreeFormat(g->Format);
char title[32];
sprintf(title, "C-Dogs SDL %s%s",
g->cachedConfig.IsEditor ? "Editor " : "",
CDOGS_SDL_VERSION);
sprintf(
title, "C-Dogs SDL %s%s",
g->cachedConfig.IsEditor ? "Editor " : "", CDOGS_SDL_VERSION);
if (!WindowContextCreate(
&g->gameWindow, windowDim, windowFlags, title, g->icon,
svec2i(w, h)))
@@ -315,16 +305,15 @@ int GraphicsGetMemSize(GraphicsConfig *config)
}
void GraphicsConfigSet(
GraphicsConfig *c,
struct vec2i windowSize, const bool fullscreen,
GraphicsConfig *c, struct vec2i windowSize, const bool fullscreen,
const int scaleFactor, const ScaleMode scaleMode, const int brightness,
const bool secondWindow)
{
#define SET(_lhs, _rhs, _flag) \
if ((_lhs) != (_rhs)) \
{ \
(_lhs) = (_rhs); \
c->RestartFlags |= (_flag); \
#define SET(_lhs, _rhs, _flag) \
if ((_lhs) != (_rhs)) \
{ \
(_lhs) = (_rhs); \
c->RestartFlags |= (_flag); \
}
SET(c->Fullscreen, fullscreen, RESTART_WINDOW);
if (c->Fullscreen)
@@ -371,7 +360,7 @@ void GraphicsConfigSetFromConfig(GraphicsConfig *gc, Config *c)
void GraphicsSetClip(SDL_Renderer *renderer, const Rect2i r)
{
const SDL_Rect rect = { r.Pos.x, r.Pos.y, r.Size.x, r.Size.y };
const SDL_Rect rect = {r.Pos.x, r.Pos.y, r.Size.x, r.Size.y};
if (SDL_RenderSetClipRect(renderer, Rect2iIsZero(r) ? NULL : &rect) != 0)
{
LOG(LM_MAIN, LL_ERROR, "Could not set clip rect: %s", SDL_GetError());
@@ -389,6 +378,7 @@ void GraphicsResetClip(SDL_Renderer *renderer)
{
if (SDL_RenderSetClipRect(renderer, NULL) != 0)
{
LOG(LM_MAIN, LL_ERROR, "Could not reset clip rect: %s", SDL_GetError());
LOG(LM_MAIN, LL_ERROR, "Could not reset clip rect: %s",
SDL_GetError());
}
}

View File

@@ -27,12 +27,6 @@
*/
#include "pic_manager.h"
#ifdef __EMSCRIPTEN__
#include <SDL2/SDL_image.h>
#else
#include <SDL_image.h>
#endif
#include <tinydir/tinydir.h>
#include "files.h"
@@ -45,11 +39,6 @@ PicManager gPicManager;
void PicManagerInit(PicManager *pm)
{
if (!IMG_Init(IMG_INIT_PNG))
{
perror("Cannot initialise SDL_Image");
return;
}
memset(pm, 0, sizeof *pm);
pm->pics = hashmap_new();
pm->sprites = hashmap_new();
@@ -214,35 +203,28 @@ void PicManagerLoadDir(
strerror(errno));
goto bail;
}
if (file.is_reg)
if (file.is_reg && Stricmp(file.extension, "png") == 0)
{
SDL_RWops *rwops = SDL_RWFromFile(file.path, "rb");
const bool isPng = IMG_isPNG(rwops);
if (isPng)
SDL_Surface *data = LoadImgToSurface(file.path);
if (!data)
{
SDL_Surface *data = IMG_Load_RW(rwops, 0);
if (!data)
LOG(LM_MAIN, LL_ERROR, "Cannot load image");
}
else
{
char buf[CDOGS_PATH_MAX];
if (prefix)
{
LOG(LM_MAIN, LL_ERROR, "Cannot load image IMG_Load: %s",
IMG_GetError());
char buf1[CDOGS_PATH_MAX];
sprintf(buf1, "%s/%s", prefix, file.name);
PathGetWithoutExtension(buf, buf1);
}
else
{
char buf[CDOGS_PATH_MAX];
if (prefix)
{
char buf1[CDOGS_PATH_MAX];
sprintf(buf1, "%s/%s", prefix, file.name);
PathGetWithoutExtension(buf, buf1);
}
else
{
PathGetBasenameWithoutExtension(buf, file.name);
}
PicManagerAdd(pics, sprites, buf, data, isHD);
PathGetBasenameWithoutExtension(buf, file.name);
}
PicManagerAdd(pics, sprites, buf, data, isHD);
}
rwops->close(rwops);
}
else if (file.is_dir && file.name[0] != '.')
{
@@ -501,7 +483,6 @@ void PicManagerTerminate(PicManager *pm)
StyleNamesDestroy(&pm->exitStyleNames);
StyleNamesDestroy(&pm->doorStyleNames);
StyleNamesDestroy(&pm->keyStyleNames);
IMG_Quit();
}
static void NamedPicDestroy(any_t data)
{

37
src/cdogs/stb/LICENSE.txt Normal file
View File

@@ -0,0 +1,37 @@
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,786 @@
/*
* A small header-only library to load an image into a RGB(A) SDL_Surface*,
* like a stripped down version of SDL_Image, but using stb_image.h to decode
* images and thus without any further external dependencies.
* Supports all filetypes supported by stb_image (JPEG, PNG, TGA, BMP, PSD, ...
* See stb_image.h for details).
*
* (C) 2015-2021 Daniel Gibson
*
* Homepage: https://github.com/DanielGibson/Snippets/
*
* Dependencies:
* libSDL2 http://www.libsdl.org
* stb_image.h https://github.com/nothings/stb
*
* Usage:
* Put this file and stb_image.h somewhere in your project.
* In *one* of your .c/.cpp files, do
* #define SDL_STBIMAGE_IMPLEMENTATION
* #include "SDL_stbimage.h"
* to create the implementation of this library in that file.
* You can just #include "SDL_stbimage.h" (without the #define) in other source
* files to use it there. (See also below this comment for an usage example)
* This header implicitly #includes <SDL.h> and "stb_image.h".
*
* NOTE: When using SDL3, either #include <SDL3/SDL.h> before this header,
* or #define SDL_STBIMG_SDL3 before including it.
*
* You can #define SDL_STBIMG_DEF before including this header if you want to
* prepend anything to the function signatures (like "static", "inline",
* "__declspec(dllexport)", ...)
* Example: #define SDL_STBIMG_DEF static inline
*
* By default, this deactivates stb_image's load from file functions via
* #define STBI_NO_STDIO, as they use stdio.h and that adds a dependency to the
* CRT on windows and with SDL you're better off using SDL_RWops, incl. SDL_RWFromFile()
* (or the SDL3 equivalents: SDL_IOStream, SDL_IOFromFile())
* If you wanna use stbi_load(), stbi_info(), stbi_load_from_file() etc anyway, do
* #define SDL_STBIMG_ALLOW_STDIO
* before including this header.
* (Note that all the STBIMG_* functions of this lib will work without it)
*
* stb_image.h uses assert.h by default. You can #define STBI_ASSERT(x)
* before the implementation-#include of SDL_stbimage.h to avoid that.
* By default stb_image supports HDR images, for that it needs pow() from libm.
* If you don't need HDR (it can't be loaded into a SDL_Surface anyway),
* #define STBI_NO_LINEAR and #define STBI_NO_HDR before including this header.
*
* License:
* This software is dual-licensed to the public domain and under the following
* license: you are granted a perpetual, irrevocable license to copy, modify,
* publish, and distribute this file as you see fit.
* No warranty implied; use at your own risk.
*
* So you can do whatever you want with this code, including copying it
* (or parts of it) into your own source.
* No need to mention me or this "license" in your code or docs, even though
* it would be appreciated, of course.
*/
#if 0 // Usage Example:
#define SDL_STBIMAGE_IMPLEMENTATION
#include "SDL_stbimage.h"
void yourFunction(const char* imageFilePath)
{
SDL_Surface* surf = STBIMG_Load(imageFilePath);
if(surf == NULL) {
printf("ERROR: Couldn't load %s, reason: %s\n", imageFilePath, SDL_GetError());
exit(1);
}
// ... do something with surf ...
SDL_FreeSurface(surf); // or SDL_DestroySurface(surf); for SDL3
}
#endif // 0 (usage example)
#ifndef _SDL_STBIMAGE_H
#define _SDL_STBIMAGE_H
// for SDL3, you either can #define SDL_STBIMG_SDL3 yourself
// OR #include <SDL3/SDL.h> yourself before this header
// (the following lines handle for the second case)
#ifndef SDL_VERSION_ATLEAST
#ifdef SDL_STBIMG_SDL3
// in SDL3 this is the official way to include SDL.h
#include <SDL3/SDL.h>
#else // SDL2 and SDL1.2
// if you really think you need <SDL2/SDL.h> here instead.. feel free to change it,
// but the cool kids have path/to/include/SDL2/ in their compilers include path.
// (meaning, that's how was supposed to be done for SDL2 and what sdl2-config supports)
#include <SDL.h>
#endif
// else if it *is* defined, SDL.h was already included before including this header.
// now, after including the headers, it definitely is available.
#endif // SDL_VERSION_ATLEAST not defined
#if !SDL_VERSION_ATLEAST(3, 0, 0) && !defined(__cpluscplus)
// allow using bool. In C++ it's a builtin type,
// in SDL3 SDL_stdinc.h (through SDL.h) makes sure it's available
#include <stdbool.h>
#endif
#ifndef SDL_STBIMG_ALLOW_STDIO
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
#endif
#include "stb_image.h"
// this allows you to prepend stuff to function signatures, e.g. "static"
#ifndef SDL_STBIMG_DEF
// by default it's empty
#define SDL_STBIMG_DEF
#endif // DG_MISC_DEF
#ifdef __cplusplus
extern "C" {
#endif
// loads the image file at the given path into a RGB(A) SDL_Surface
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file);
// loads the image file in the given memory buffer into a RGB(A) SDL_Surface
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length);
// loads an image file into a RGB(A) SDL_Surface from a seekable SDL_IOStream/SDL_RWops (src)
// if you set freesrc to true, SDL_CloseIO(src)/SDL_RWclose(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_IO(SDL_IOStream* src, bool freesrc);
#else // SDL2 or SDL1.2
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(SDL_RWops* src, bool freesrc);
#endif
// Creates an SDL_Surface* using the raw RGB(A) pixelData with given width/height
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
// If freeWithSurface is true, SDL_FreeSurface() will free the pixelData
// you passed with SDL_free() - NOTE that you should only do that if pixelData
// was allocated with SDL_malloc(), SDL_calloc() or SDL_realloc()!
// Returns NULL on error (in that case pixelData won't be freed!),
// use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height,
int bytesPerPixel, bool freeWithSurface);
#if SDL_MAJOR_VERSION > 1
// loads the image file at the given path into a RGB(A) SDL_Texture
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file);
// loads the image file in the given memory buffer into a RGB(A) SDL_Texture
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTextureFromMemory(SDL_Renderer* renderer, const unsigned char* buffer, int length);
// loads an image file into a RGB(A) SDL_Texture from a seekable SDL_IOStream/SDL_RWops (src)
// if you set freesrc to true, SDL_CloseIO(src)/SDL_RWclose(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_IO(SDL_Renderer* renderer, SDL_IOStream* src, bool freesrc);
#else // SDL2
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, SDL_RWops* src, bool freesrc);
#endif
// Creates an SDL_Texture* using the raw RGB(A) pixelData with given width/height
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
// Returns NULL on error, use SDL_GetError() to get more information.
SDL_STBIMG_DEF SDL_Texture*
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
int width, int height, int bytesPerPixel);
#endif // SDL_MAJOR_VERSION > 1
typedef struct {
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_IOStream* src;
#else
SDL_RWops* src;
#endif
stbi_io_callbacks stb_cbs;
int atEOF; // defaults to 0; 1: reached EOF or error on read, 2: error on seek
} STBIMG_stbio_RWops;
// creates stbi_io_callbacks and userdata to use stbi_*_from_callbacks() directly,
// especially useful to use SDL_IOStream/SDL_RWops with stb_image, without using SDL_Surface
// src must be readable and seekable!
// Returns false on error (SDL_GetError() will give you info), else true
// NOTE: If you want to use src twice (e.g. for info and load), remember to rewind
// it by seeking back to its initial position and resetting out->atEOF to 0
// inbetween the uses!
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF bool STBIMG_stbi_callback_from_IO(SDL_IOStream* src, STBIMG_stbio_RWops* out);
#else
SDL_STBIMG_DEF bool STBIMG_stbi_callback_from_RW(SDL_RWops* src, STBIMG_stbio_RWops* out);
#endif
#if 0 // Use STBIMG_stbi_callback_from_RW() like this:
SDL_RWops* src = ...; // wherever it's from
STBIMG_stbio_RWops io;
if(!STBIMG_stbi_callback_from_RW(src, &io)) {
printf("ERROR creating stbio callbacks: %s\n", SDL_GetError());
exit(1);
}
Sint64 origSrcPosition = SDL_RWtell(src);
int w, h, fmt;
if(!stbi_info_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt)) {
printf("stbi_info_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
exit(1);
}
printf("image is %d x %d pixels with %d bytes per pixel\n", w, h, fmt);
// rewind src before using it again in stbi_load_from_callbacks()
if(SDL_RWseek(src, origSrcPosition, RW_SEEK_SET) < 0)
{
printf("ERROR: src not be seekable!\n");
exit(1);
}
io.atEOF = 0; // remember to reset atEOF, too!
unsigned char* data;
data = stbi_load_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt, 0);
if(data == NULL) {
printf("stbi_load_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
exit(1);
}
// ... do something with data ...
stbi_image_free(data);
#endif // 0 (STBIMG_stbi_callback_from_RW() example)
#if SDL_MAJOR_VERSION > 1
// loads an image file into a RGB(A) SDL_Surface from a SDL_RWops/SDL_IOStream (src)
// - without using SDL_RWseek()/SDL_SeekIO, for streams that don't support or are slow
// at seeking. It reads everything into a buffer and calls STBIMG_LoadFromMemory()
// You should probably only use this if you *really* have performance problems
// because of seeking or your src doesn't support SDL_RWseek()/SDL_SeekIO, but SDL_RWsize()/SDL_GetIOSize
// src must at least support SDL_RWread()/SDL_ReadIO() and SDL_RWsize()/SDL_GetIOSize
// if you set freesrc to true, SDL_RWclose(src)/SDL_CloseIO(src) will be executed after reading.
// Returns NULL on error, use SDL_GetError() to get more information.
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_IO_noSeek(SDL_IOStream* src, bool freesrc);
#else
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(SDL_RWops* src, bool freesrc);
#endif
// the same for textures (you should probably not use this one, either..)
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Texture* STBIMG_LoadTexture_IO_noSeek(SDL_Renderer* renderer, SDL_IOStream* src, bool freesrc);
#else
SDL_STBIMG_DEF SDL_Texture* STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, SDL_RWops* src, bool freesrc);
#endif
#endif // SDL_MAJOR_VERSION > 1
#ifdef __cplusplus
} // extern "C"
#endif
// provide backwards-compatibility for the function names
#if SDL_VERSION_ATLEAST(3, 0, 0)
#define STBIMG_Load_RW STBIMG_Load_IO
#define STBIMG_LoadTexture_RW STBIMG_LoadTexture_IO
#define STBIMG_stbi_callback_from_RW STBIMG_stbi_callback_from_IO
#define STBIMG_Load_RW_noSeek STBIMG_Load_IO_noSeek
#define STBIMG_LoadTexture_RW_noSeek STBIMG_LoadTexture_IO_noSeek
#endif
#endif // _SDL_STBIMAGE_H
// ############# Below: Implementation ###############
#ifdef SDL_STBIMAGE_IMPLEMENTATION
// make stb_image use SDL_malloc etc, so SDL_FreeSurface() can SDL_free()
// the data allocated by stb_image
#define STBI_MALLOC SDL_malloc
#define STBI_REALLOC SDL_realloc
#define STBI_FREE SDL_free
#define STB_IMAGE_IMPLEMENTATION
#ifndef SDL_STBIMG_ALLOW_STDIO
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
#endif
#include "stb_image.h"
// Note: In the header part above I kept things simple, but here
// I'm using macros to unify SDL1.2/SDL2 and SDL3 RWops/IOStream code
#if SDL_VERSION_ATLEAST(3, 0, 0)
#define _STBIMG_RWops SDL_IOStream
#define _STBIMG_RW_SEEK_CUR SDL_IO_SEEK_CUR
#define _STBIMG_RW_SEEK_SET SDL_IO_SEEK_SET
#define _STBIMG_RWread(CTX, PTR, SIZE) SDL_ReadIO(CTX, PTR, SIZE)
#define _STBIMG_RWseek(CTX, OFFSET, WHENCE) SDL_SeekIO(CTX, OFFSET, WHENCE)
#define _STBIMG_RWtell(CTX) SDL_TellIO(CTX)
#define _STBIMG_RWclose(CTX) SDL_CloseIO(CTX)
#define _STBIMG_RWsize(CTX) SDL_GetIOSize(CTX)
#define _STBIMG_RWFromFile(FILENAME, MODE) SDL_IOFromFile(FILENAME, MODE)
#else // SDL2 or SDL1.2
#define _STBIMG_RWops SDL_RWops
#define _STBIMG_RW_SEEK_CUR RW_SEEK_CUR
#define _STBIMG_RW_SEEK_SET RW_SEEK_SET
#define _STBIMG_RWread(CTX, PTR, SIZE) SDL_RWread(CTX, PTR, 1, SIZE)
#define _STBIMG_RWseek(CTX, OFFSET, WHENCE) SDL_RWseek(CTX, OFFSET, WHENCE)
#define _STBIMG_RWtell(CTX) SDL_RWtell(CTX)
#define _STBIMG_RWclose(CTX) SDL_RWclose(CTX)
#define _STBIMG_RWsize(CTX) SDL_RWsize(CTX)
#define _STBIMG_RWFromFile(FILENAME, MODE) SDL_RWFromFile(FILENAME, MODE)
#endif
typedef struct {
unsigned char* data;
int w;
int h;
int format; // 3: RGB, 4: RGBA
} _STBIMG_image;
static SDL_Surface* _STBIMG_CreateSurfaceImpl(_STBIMG_image img, int freeWithSurface)
{
SDL_Surface* surf = NULL;
#if SDL_VERSION_ATLEAST(3, 0, 0)
Uint32 format = (img.format == STBI_rgb) ? SDL_PIXELFORMAT_RGB24 : SDL_PIXELFORMAT_RGBA32;
surf = SDL_CreateSurfaceFrom(img.w, img.h, format, img.data, img.format*img.w);
#elif SDL_VERSION_ATLEAST(2, 0, 5)
// SDL 2.0.5 introduced SDL_CreateRGBSurfaceWithFormatFrom() and SDL_PIXELFORMAT_RGBA32
// which makes this code much simpler.
Uint32 format = (img.format == STBI_rgb) ? SDL_PIXELFORMAT_RGB24 : SDL_PIXELFORMAT_RGBA32;
surf = SDL_CreateRGBSurfaceWithFormatFrom((void*)img.data, img.w, img.h,
img.format*8, img.format*img.w, format);
#else // older SDL2 version without SDL_CreateRGBSurfaceWithFormatFrom()
Uint32 rmask, gmask, bmask, amask;
// ok, the following is pretty stupid.. SDL_CreateRGBSurfaceFrom() pretends to use
// a void* for the data, but it's really treated as endian-specific Uint32*
// and there isn't even an SDL_PIXELFORMAT_* for 32bit byte-wise RGBA
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int shift = (img.format == STBI_rgb) ? 8 : 0;
rmask = 0xff000000 >> shift;
gmask = 0x00ff0000 >> shift;
bmask = 0x0000ff00 >> shift;
amask = 0x000000ff >> shift;
#else // little endian, like x86
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = (img.format == STBI_rgb) ? 0 : 0xff000000;
#endif
surf = SDL_CreateRGBSurfaceFrom((void*)img.data, img.w, img.h,
img.format*8, img.format*img.w,
rmask, gmask, bmask, amask);
#endif // SDL_VERSION_ATLEAST
if(surf == NULL)
{
// hopefully SDL_CreateRGBSurfaceFrom() has set an sdl error
return NULL;
}
if(freeWithSurface)
{
// SDL_Surface::flags is documented to be read-only.. but if the pixeldata
// has been allocated with SDL_malloc()/SDL_calloc()/SDL_realloc() this
// should work (and it currently does) + @icculus said it's reasonably safe:
// https://twitter.com/icculus/status/667036586610139137 :-)
// clear the SDL_PREALLOC flag, so SDL_FreeSurface() free()s the data passed from img.data
#if SDL_VERSION_ATLEAST(3, 0, 0)
// I hope that's still true for SDL3 :-p
surf->flags &= ~SDL_SURFACE_PREALLOCATED;
#else
surf->flags &= ~SDL_PREALLOC;
#endif
}
return surf;
}
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length)
{
_STBIMG_image img = {0};
int bppToUse = 0;
int inforet = 0;
SDL_Surface* ret = NULL;
if(buffer == NULL)
{
SDL_SetError("STBIMG_LoadFromMemory(): passed buffer was NULL!");
return NULL;
}
if(length <= 0)
{
SDL_SetError("STBIMG_LoadFromMemory(): passed invalid length: %d!", length);
return NULL;
}
inforet = stbi_info_from_memory(buffer, length, &img.w, &img.h, &img.format);
if(!inforet)
{
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't get image info: %s!\n", stbi_failure_reason());
return NULL;
}
// no alpha => use RGB, else use RGBA
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
img.data = stbi_load_from_memory(buffer, length, &img.w, &img.h, &img.format, bppToUse);
if(img.data == NULL)
{
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't load image: %s!\n", stbi_failure_reason());
return NULL;
}
img.format = bppToUse;
ret = _STBIMG_CreateSurfaceImpl(img, 1);
if(ret == NULL)
{
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
SDL_free(img.data);
return NULL;
}
return ret;
}
// fill 'data' with 'size' bytes. return number of bytes actually read
static int _STBIMG_io_read(void* user, char* data, int size)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
size_t ret = _STBIMG_RWread(io->src, data, size*sizeof(char));
if(ret == 0)
{
// we're at EOF or some error happend
io->atEOF = 1;
}
return (int)ret*sizeof(char);
}
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
static void _STBIMG_io_skip(void* user, int n)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
if(_STBIMG_RWseek(io->src, n, _STBIMG_RW_SEEK_CUR) == -1)
{
// an error happened during seeking, hopefully setting EOF will make stb_image abort
io->atEOF = 2; // set this to 2 for "aborting because seeking failed" (stb_image only cares about != 0)
}
}
// returns nonzero if we are at end of file/data
static int _STBIMG_io_eof(void* user)
{
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
return io->atEOF;
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF bool STBIMG_stbi_callback_from_IO(_STBIMG_RWops* src, STBIMG_stbio_RWops* out)
#else
SDL_STBIMG_DEF bool STBIMG_stbi_callback_from_RW(_STBIMG_RWops* src, STBIMG_stbio_RWops* out)
#endif
{
if(out == NULL)
{
SDL_SetError("STBIMG_stbi_callback_from_RW(): out must not be NULL!");
return false;
}
// make sure out is at least initialized to something deterministic
memset(out, 0, sizeof(*out));
if(src == NULL)
{
SDL_SetError("STBIMG_stbi_callback_from_RW(): src must not be NULL!");
return false;
}
out->src = src;
out->atEOF = 0;
out->stb_cbs.read = _STBIMG_io_read;
out->stb_cbs.skip = _STBIMG_io_skip;
out->stb_cbs.eof = _STBIMG_io_eof;
return true;
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_IO(_STBIMG_RWops* src, bool freesrc)
#else
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(_STBIMG_RWops* src, bool freesrc)
#endif
{
_STBIMG_image img = {0};
int bppToUse = 0;
int inforet = 0;
SDL_Surface* ret = NULL;
Sint64 srcOffset = 0;
STBIMG_stbio_RWops cbData;
if(src == NULL)
{
SDL_SetError("STBIMG_Load_RW(): src was NULL!");
return NULL;
}
srcOffset = _STBIMG_RWtell(src);
if(srcOffset < 0)
{
SDL_SetError("STBIMG_Load_RW(): src must be seekable, maybe use STBIMG_Load_RW_noSeek() instead!");
// TODO: or do that automatically? but I think the user should be aware of what they're doing
goto end;
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
if(!STBIMG_stbi_callback_from_IO(src, &cbData))
#else
if(!STBIMG_stbi_callback_from_RW(src, &cbData))
#endif
{
goto end;
}
inforet = stbi_info_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format);
if(!inforet)
{
if(cbData.atEOF == 2) SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
else SDL_SetError("STBIMG_Load_RW(): Couldn't get image info: %s!\n", stbi_failure_reason());
goto end;
}
// rewind src so stbi_load_from_callbacks() will start reading from the beginning again
if(_STBIMG_RWseek(src, srcOffset, _STBIMG_RW_SEEK_SET) < 0)
{
SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
goto end;
}
cbData.atEOF = 0; // we've rewinded (rewound?)
// no alpha => use RGB, else use RGBA
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
img.data = stbi_load_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format, bppToUse);
if(img.data == NULL)
{
SDL_SetError("STBIMG_Load_RW(): Couldn't load image: %s!\n", stbi_failure_reason());
goto end;
}
img.format = bppToUse;
ret = _STBIMG_CreateSurfaceImpl(img, 1);
if(ret == NULL)
{
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
SDL_free(img.data);
img.data = NULL;
goto end;
}
end:
if(freesrc)
{
_STBIMG_RWclose(src);
}
else if(img.data == NULL)
{
// if data is still NULL, there was an error and we should probably
// seek src back to where it was when this function was called
_STBIMG_RWseek(src, srcOffset, _STBIMG_RW_SEEK_SET);
}
return ret;
}
#if SDL_MAJOR_VERSION > 1
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_IO_noSeek(_STBIMG_RWops* src, bool freesrc)
#else
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(_STBIMG_RWops* src, bool freesrc)
#endif
{
unsigned char* buf = NULL;
Sint64 fileSize = 0, bytesRead=0;
SDL_Surface* ret = NULL;
if(src == NULL)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): src was NULL!");
return NULL;
}
fileSize = _STBIMG_RWsize(src);
if(fileSize < 0)
{
goto end; // SDL should have set an error already
}
else if(fileSize == 0)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) returned 0 => empty file/stream?!");
goto end;
}
else if(fileSize > 0x7FFFFFFF)
{
// stb_image.h uses ints for all sizes, so we can't support more
// (but >2GB images are insane anyway)
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) too big (> 2GB)!");
goto end;
}
buf = (unsigned char*)SDL_malloc(fileSize);
if(buf == NULL)
{
SDL_SetError("STBIMG_Load_RW_noSeek(): Couldn't allocate buffer to read src into!");
goto end;
}
while(bytesRead < fileSize) {
size_t read = _STBIMG_RWread(src, buf+bytesRead, fileSize-bytesRead);
if(read == 0) {
// TODO: set error? SDL_RWread/SDL_ReadIO should set one, I think?
goto end;
}
bytesRead += read;
}
// if that fails, STBIMG_LoadFromMemory() has set an SDL error
// and ret is NULL, so nothing special to do for us
ret = STBIMG_LoadFromMemory(buf, (int)fileSize);
end:
if(freesrc)
{
_STBIMG_RWclose(src);
}
SDL_free(buf);
return ret;
}
#endif // SDL_MAJOR_VERSION > 1
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file)
{
_STBIMG_RWops* src = _STBIMG_RWFromFile(file, "rb");
if(src == NULL) return NULL;
#if SDL_VERSION_ATLEAST(3, 0, 0)
return STBIMG_Load_IO(src, 1);
#else
return STBIMG_Load_RW(src, 1);
#endif
}
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height, int bytesPerPixel, bool freeWithSurface)
{
_STBIMG_image img;
if(pixelData == NULL)
{
SDL_SetError("STBIMG_CreateSurface(): passed pixelData was NULL!");
return NULL;
}
if(bytesPerPixel != 3 && bytesPerPixel != 4)
{
SDL_SetError("STBIMG_CreateSurface(): passed bytesPerPixel = %d, only 3 (24bit RGB) and 4 (32bit RGBA) are allowed!", bytesPerPixel);
return NULL;
}
if(width <= 0 || height <= 0)
{
SDL_SetError("STBIMG_CreateSurface(): width and height must be > 0!");
return NULL;
}
img.data = pixelData;
img.w = width;
img.h = height;
img.format = bytesPerPixel;
return _STBIMG_CreateSurfaceImpl(img, freeWithSurface);
}
#if SDL_MAJOR_VERSION > 1
static SDL_Texture* _STBIMG_SurfToTex(SDL_Renderer* renderer, SDL_Surface* surf)
{
SDL_Texture* ret = NULL;
if(surf != NULL)
{
ret = SDL_CreateTextureFromSurface(renderer, surf);
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_DestroySurface(surf); // not needed anymore, it's copied into tex
#else
SDL_FreeSurface(surf); // not needed anymore, it's copied into tex
#endif
}
// if surf is NULL, whatever tried to create it should have called SDL_SetError(),
// if SDL_CreateTextureFromSurface() returned NULL it should have set an error
// so whenever this returns NULL, the user should be able to get a useful
// error-message with SDL_GetError().
return ret;
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file)
{
return _STBIMG_SurfToTex(renderer, STBIMG_Load(file));
}
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTextureFromMemory(SDL_Renderer *renderer, const unsigned char* buffer, int length)
{
return _STBIMG_SurfToTex(renderer, STBIMG_LoadFromMemory(buffer, length));
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_IO(SDL_Renderer* renderer, _STBIMG_RWops* src, bool freesrc)
{
return _STBIMG_SurfToTex(renderer, STBIMG_Load_IO(src, freesrc));
}
#else
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, _STBIMG_RWops* src, bool freesrc)
{
return _STBIMG_SurfToTex(renderer, STBIMG_Load_RW(src, freesrc));
}
#endif
SDL_STBIMG_DEF SDL_Texture*
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
int width, int height, int bytesPerPixel)
{
SDL_Surface* surf = STBIMG_CreateSurface((unsigned char*)pixelData, width, height, bytesPerPixel, false);
return _STBIMG_SurfToTex(renderer, surf);
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_IO_noSeek(SDL_Renderer* renderer, _STBIMG_RWops* src, bool freesrc)
{
return _STBIMG_SurfToTex(renderer, STBIMG_Load_IO_noSeek(src, freesrc));
}
#else
SDL_STBIMG_DEF SDL_Texture*
STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, _STBIMG_RWops* src, bool freesrc)
{
return _STBIMG_SurfToTex(renderer, STBIMG_Load_RW_noSeek(src, freesrc));
}
#endif
#endif // SDL_MAJOR_VERSION > 1
#endif // SDL_STBIMAGE_IMPLEMENTATION

7988
src/cdogs/stb/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2017, 2019-2022, 2024 Cong Xu
Copyright (c) 2013-2017, 2019-2022, 2024-2025 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -58,6 +58,11 @@
#include <stdlib.h>
#include <string.h>
#define SDL_STBIMAGE_IMPLEMENTATION
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#include <stb/SDL_stbimage.h>
#pragma GCC diagnostic pop
#include <tinydir/tinydir.h>
#include "events.h"
@@ -682,3 +687,8 @@ end:
}
return buf;
}
SDL_Surface *LoadImgToSurface(const char *path)
{
return STBIMG_Load(path);
}

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2017, 2019-2024 Cong Xu
Copyright (c) 2013-2017, 2019-2025 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -54,6 +54,8 @@
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "color.h"
#include "sys_specifics.h"
@@ -140,7 +142,7 @@ extern bool gFalse;
x = y; \
y = _tmp; \
} while (0)
#define DIV_ROUND_UP(a, b) (((a) + ((b)-1)) / (b))
#define DIV_ROUND_UP(a, b) (((a) + ((b) - 1)) / (b))
const char *StrGetFileExt(const char *filename);
@@ -212,7 +214,7 @@ bool IntsEqual(const void *v1, const void *v2);
#define RAND_FLOAT(_low, _high) (float)RAND_DOUBLE(_low, _high)
#define RAND_DOUBLE(_low, _high) \
((_low) + ((double)rand() / RAND_MAX * ((_high) - (_low))))
#define RAND_BOOL() (rand()>RAND_MAX/2)
#define RAND_BOOL() (rand() > RAND_MAX / 2)
typedef enum
{
@@ -221,7 +223,7 @@ typedef enum
HEAD_PART_HAT,
HEAD_PART_GLASSES,
HEAD_PART_COUNT
} HeadPart; // cranial accessories
} HeadPart; // cranial accessories
const char *HeadPartStr(const HeadPart hp);
@@ -251,3 +253,5 @@ typedef enum
int Pulse256(const int t);
char *ReadFileIntoBuf(const char *path, const char *mode);
SDL_Surface *LoadImgToSurface(const char *path);

View File

@@ -29,8 +29,6 @@
#include <assert.h>
#include <SDL_image.h>
#include <cdogs/algorithms.h>
#include <cdogs/map.h>
#include <cdogs/map_build.h>
@@ -347,7 +345,8 @@ EditorResult EditorBrushStartPainting(EditorBrush *b, Mission *m, int isMain)
if (isMain)
{
const Tile *tile = MapGetTile(&gMap, b->Pos);
const Tile *tileAbove = MapGetTile(&gMap, svec2i(b->Pos.x, b->Pos.y - 1));
const Tile *tileAbove =
MapGetTile(&gMap, svec2i(b->Pos.x, b->Pos.y - 1));
if (MapObjectIsTileOK(b->u.MapObject, tile, tileAbove) &&
MissionStaticTryAddItem(&m->u.Static, b->u.MapObject, b->Pos))
@@ -423,8 +422,8 @@ EditorResult EditorBrushStartPainting(EditorBrush *b, Mission *m, int isMain)
if (isMain)
{
const Tile *tile = MapGetTile(&gMap, b->Pos);
if (TileCanWalk(tile) && MissionStaticTryAddPickup(
&m->u.Static, b->u.Pickup, b->Pos))
if (TileCanWalk(tile) &&
MissionStaticTryAddPickup(&m->u.Static, b->u.Pickup, b->Pos))
{
return EDITOR_RESULT_CHANGED_AND_RELOAD;
}
@@ -663,7 +662,7 @@ EditorResult EditorBrushStopPainting(EditorBrush *b, Mission *m)
bool EditorBrushTryLoadGuideImage(EditorBrush *b, const char *filename)
{
PicFree(&b->GuideImagePic);
SDL_Surface *s = IMG_Load(filename);
SDL_Surface *s = LoadImgToSurface(filename);
if (s == NULL)
return false;
SDL_Surface *sc = SDL_ConvertSurface(s, gGraphicsDevice.Format, 0);

View File

@@ -29,8 +29,6 @@
#include <assert.h>
#include <SDL_image.h>
#include <cdogs/draw/draw.h>
#include <cdogs/draw/draw_actor.h>
#include <cdogs/events.h>

View File

@@ -29,7 +29,6 @@
#include <stdio.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <SDL_version.h>
@@ -45,9 +44,6 @@ void PrintTitle(void)
printf(
"SDL version %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION,
SDL_PATCHLEVEL);
printf(
"SDL_image version %d.%d.%d\n", SDL_IMAGE_MAJOR_VERSION,
SDL_IMAGE_MINOR_VERSION, SDL_IMAGE_PATCHLEVEL);
printf(
"SDL_mixer version %d.%d.%d\n", SDL_MIXER_MAJOR_VERSION,
SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL);

View File

@@ -2,8 +2,6 @@
#include <cbehave/cbehave.h>
#include <pic.h>
#include <SDL_image.h>
#include <config.h>
#include <grafx.h>
@@ -22,9 +20,7 @@ FEATURE(PicLoad, "Pic load")
GraphicsInitialize(&gGraphicsDevice);
ASSERT(gGraphicsDevice.IsInitialized, 1);
AND("a single pixel PNG")
SDL_RWops *rwops = SDL_RWFromFile("r64g128b192.png", "rb");
ASSERT(IMG_isPNG(rwops), 1);
SDL_Surface *image = IMG_Load_RW(rwops, 0);
SDL_Surface *image = LoadImgToSurface("r64g128b192.png");
SDL_LockSurface(image);
WHEN("I load the pic")
@@ -40,7 +36,6 @@ FEATURE(PicLoad, "Pic load")
SHOULD_INT_EQUAL(c.b, 192);
SDL_UnlockSurface(image);
SDL_FreeSurface(image);
rwops->close(rwops);
SCENARIO_END
FEATURE_END