mirror of
https://github.com/raysan5/raylib.git
synced 2026-07-11 16:21:57 -04:00
Compare commits
19 Commits
d631a5a466
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f00317bead | |||
| 8805ab3ee2 | |||
| ebec978443 | |||
| cfe56d97ea | |||
| 97d2b0146c | |||
| c31666fe2a | |||
| ab35e0f712 | |||
| c85cd07db0 | |||
| f458296a07 | |||
| 8df2f13962 | |||
| cba8f4286d | |||
| 86c7edfd74 | |||
| caadb48e25 | |||
| 3e9fb4757f | |||
| d159739a8b | |||
| f20f61d754 | |||
| 81b740403a | |||
| 3cb8a3d782 | |||
| f8e42cb509 |
@ -52,7 +52,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
|||||||
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
|
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
|
||||||
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||||
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||||
| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
|
||||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
|
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
|
||||||
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||||
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||||
|
|||||||
@ -11,8 +11,4 @@ Most considerations of errors and defects can be handled using the project Issue
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
|
Discovered vulnerability can be directly reported using the project Issues and/or Discussions. They will be reviewed as soon as possible.
|
||||||
|
|
||||||
_TODO: Tell them where to go, how often they can expect to get an update on a
|
|
||||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
|
||||||
declined, etc._
|
|
||||||
|
|||||||
21
src/external/tinyobj_loader_c.h
vendored
21
src/external/tinyobj_loader_c.h
vendored
@ -1020,7 +1020,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
|||||||
int triangulate) {
|
int triangulate) {
|
||||||
char linebuf[4096];
|
char linebuf[4096];
|
||||||
const char *token;
|
const char *token;
|
||||||
assert(p_len < 4095);
|
|
||||||
|
// @raysan5:
|
||||||
|
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||||
|
// be present in the compiled binary, replacing by a runtime check
|
||||||
|
//assert(p_len < 4095);
|
||||||
|
if (p_len > 4095) return 0;
|
||||||
|
|
||||||
memcpy(linebuf, p, p_len);
|
memcpy(linebuf, p, p_len);
|
||||||
linebuf[p_len] = '\0';
|
linebuf[p_len] = '\0';
|
||||||
@ -1102,7 +1107,11 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
|||||||
tinyobj_vertex_index_t i1;
|
tinyobj_vertex_index_t i1;
|
||||||
tinyobj_vertex_index_t i2 = f[1];
|
tinyobj_vertex_index_t i2 = f[1];
|
||||||
|
|
||||||
assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
// @raysan5:
|
||||||
|
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||||
|
// be present in the compiled binary, replacing by a runtime check
|
||||||
|
//assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||||
|
if (3*num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
|
||||||
|
|
||||||
for (k = 2; k < num_f; k++) {
|
for (k = 2; k < num_f; k++) {
|
||||||
i1 = i2;
|
i1 = i2;
|
||||||
@ -1119,7 +1128,13 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
unsigned int k = 0;
|
unsigned int k = 0;
|
||||||
assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
|
||||||
|
// @raysan5:
|
||||||
|
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||||
|
// be present in the compiled binary, replacing by a runtime check
|
||||||
|
//assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||||
|
if (num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
|
||||||
|
|
||||||
for (k = 0; k < num_f; k++) {
|
for (k = 0; k < num_f; k++) {
|
||||||
command->f[k] = f[k];
|
command->f[k] = f[k];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -663,13 +663,22 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if the provided URL is safe
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Avoid calling this function with user input non-validated strings
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JNIEnv *env = NULL;
|
JNIEnv *env = NULL;
|
||||||
|
|||||||
@ -1181,17 +1181,25 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if you control the URL given
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
// REF: https://github.com/raysan5/raylib/issues/686
|
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
|
char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char));
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
sprintf(cmd, "explorer \"%s\"", url);
|
sprintf(cmd, "explorer \"%s\"", url);
|
||||||
#endif
|
#endif
|
||||||
@ -1201,7 +1209,9 @@ void OpenURL(const char *url)
|
|||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
sprintf(cmd, "open '%s'", url);
|
sprintf(cmd, "open '%s'", url);
|
||||||
#endif
|
#endif
|
||||||
|
// TODO: Replace system() call by custom process
|
||||||
int result = system(cmd);
|
int result = system(cmd);
|
||||||
|
|
||||||
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
|
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
|
||||||
RL_FREE(cmd);
|
RL_FREE(cmd);
|
||||||
}
|
}
|
||||||
@ -1683,6 +1693,14 @@ int InitPlatform(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
// AppKit can constrain the requested window size to the visible work area during creation
|
||||||
|
int windowWidth = 0;
|
||||||
|
int windowHeight = 0;
|
||||||
|
glfwGetWindowSize(platform.handle, &windowWidth, &windowHeight);
|
||||||
|
if ((windowWidth > 0) && (windowHeight > 0)) CORE.Window.screen = (Size){ windowWidth, windowHeight };
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: Not considering scale factor now, considered below
|
// NOTE: Not considering scale factor now, considered below
|
||||||
CORE.Window.render.width = CORE.Window.screen.width;
|
CORE.Window.render.width = CORE.Window.screen.width;
|
||||||
CORE.Window.render.height = CORE.Window.screen.height;
|
CORE.Window.render.height = CORE.Window.screen.height;
|
||||||
|
|||||||
@ -1471,15 +1471,25 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if you control the URL given
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
|
char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char));
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
sprintf(cmd, "explorer \"%s\"", url);
|
sprintf(cmd, "explorer \"%s\"", url);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1341,14 +1341,22 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if the provided URL is safe
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Avoid calling this function with user input non-validated strings
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
// REF: https://github.com/raysan5/raylib/issues/686
|
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else SDL_OpenURL(url);
|
else SDL_OpenURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1247,19 +1247,28 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if the provided URL is safe
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Avoid calling this function with user input non-validated strings
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
// REF: https://github.com/raysan5/raylib/issues/686
|
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int len = strlen(url) + 32;
|
int len = strlen(url) + 16;
|
||||||
char *cmd = (char *)RL_CALLOC(len, sizeof(char));
|
char *cmd = (char *)RL_CALLOC(len, sizeof(char));
|
||||||
snprintf(cmd, len, "explorer \"%s\"", url);
|
snprintf(cmd, len, "explorer \"%s\"", url);
|
||||||
|
|
||||||
int result = system(cmd);
|
int result = system(cmd);
|
||||||
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
|
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
|
||||||
RL_FREE(cmd);
|
RL_FREE(cmd);
|
||||||
|
|||||||
@ -1014,9 +1014,8 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if the provided URL is safe
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Avoid calling this function with user input non-validated strings
|
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
|
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
|
||||||
@ -1446,7 +1445,9 @@ int InitPlatform(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs))
|
// WARNING: Providing framebufferAttribs is not logically necessary,
|
||||||
|
// but it may prevent segfaults on some nvidia drivers
|
||||||
|
if (!eglChooseConfig(platform.device, framebufferAttribs, NULL, 0, &numConfigs))
|
||||||
{
|
{
|
||||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -352,14 +352,22 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if you control the URL given.
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action.
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Only call this function yourself not with user input or make sure to check the string yourself.
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
// Ref: https://github.com/raysan5/raylib/issues/686
|
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Load url using default browser
|
// TODO: Load url using default browser
|
||||||
|
|||||||
@ -968,13 +968,22 @@ double GetTime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open URL with default system browser (if available)
|
// Open URL with default system browser (if available)
|
||||||
// NOTE: This function is only safe to use if the provided URL is safe
|
// WARNING: This function is only safe to use if you control the URL given,
|
||||||
// A user could craft a malicious string performing another action
|
// a user could craft a malicious string to perform and undesired action
|
||||||
// Avoid calling this function with user input non-validated strings
|
// NOTE: Some safety checks have been added to mitigate security issues
|
||||||
void OpenURL(const char *url)
|
void OpenURL(const char *url)
|
||||||
{
|
{
|
||||||
// Security check to (partially) avoid malicious code on target platform
|
// Security check to (partially) avoid malicious code
|
||||||
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
|
if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
|
||||||
|
{
|
||||||
|
// Filter characters: ' and "
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
|
||||||
|
}
|
||||||
|
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
|
||||||
|
{
|
||||||
|
// Only allow URL starting with "http://" or "https://" protocols
|
||||||
|
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
|
||||||
|
}
|
||||||
else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
|
else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -822,7 +822,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||||||
wave.sampleRate = wav.sampleRate;
|
wave.sampleRate = wav.sampleRate;
|
||||||
wave.sampleSize = 16;
|
wave.sampleSize = 16;
|
||||||
wave.channels = wav.channels;
|
wave.channels = wav.channels;
|
||||||
wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
|
wave.data = (short *)RL_CALLOC((size_t)wave.frameCount*wave.channels, sizeof(short));
|
||||||
|
|
||||||
// NOTE: Forcing conversion to 16bit sample size on reading
|
// NOTE: Forcing conversion to 16bit sample size on reading
|
||||||
drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data);
|
drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data);
|
||||||
@ -845,7 +845,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
|||||||
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
|
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
|
||||||
wave.channels = info.channels;
|
wave.channels = info.channels;
|
||||||
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
|
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
|
||||||
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
wave.data = (short *)RL_CALLOC(wave.frameCount*wave.channels, sizeof(short));
|
||||||
|
|
||||||
// NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!)
|
// NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!)
|
||||||
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
|
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
|
||||||
@ -1258,7 +1258,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *data = RL_MALLOC(frameCount*channels*(sampleSize/8));
|
void *data = RL_CALLOC(frameCount*channels*(sampleSize/8), 1);
|
||||||
|
|
||||||
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
||||||
if (frameCount == 0)
|
if (frameCount == 0)
|
||||||
@ -1772,7 +1772,7 @@ void UnloadMusicStream(Music music)
|
|||||||
{
|
{
|
||||||
if (false) { }
|
if (false) { }
|
||||||
#if SUPPORT_FILEFORMAT_WAV
|
#if SUPPORT_FILEFORMAT_WAV
|
||||||
else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
|
else if (music.ctxType == MUSIC_AUDIO_WAV) { drwav_uninit((drwav *)music.ctxData); RL_FREE(music.ctxData); }
|
||||||
#endif
|
#endif
|
||||||
#if SUPPORT_FILEFORMAT_OGG
|
#if SUPPORT_FILEFORMAT_OGG
|
||||||
else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
|
else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
|
||||||
|
|||||||
12
src/rcore.c
12
src/rcore.c
@ -1844,8 +1844,6 @@ void SetConfigFlags(unsigned int flags)
|
|||||||
FLAG_SET(CORE.Window.flags, flags);
|
FLAG_SET(CORE.Window.flags, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void OpenURL(const char *url); // Defined per platform
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition: Logging system
|
// Module Functions Definition: Logging system
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -3275,7 +3273,7 @@ unsigned int *ComputeMD5(const unsigned char *data, int dataSize)
|
|||||||
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
|
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
|
||||||
|
|
||||||
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
|
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
|
||||||
for (int offset = 0; offset < newDataSize; offset += (512/8))
|
for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
|
||||||
{
|
{
|
||||||
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
||||||
unsigned int *w = (unsigned int *)(msg + offset);
|
unsigned int *w = (unsigned int *)(msg + offset);
|
||||||
@ -3372,7 +3370,7 @@ unsigned int *ComputeSHA1(const unsigned char *data, int dataSize)
|
|||||||
msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56);
|
msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56);
|
||||||
|
|
||||||
// Process the message in successive 512-bit chunks
|
// Process the message in successive 512-bit chunks
|
||||||
for (int offset = 0; offset < newDataSize; offset += (512/8))
|
for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
|
||||||
{
|
{
|
||||||
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
||||||
unsigned int w[80] = { 0 };
|
unsigned int w[80] = { 0 };
|
||||||
@ -3603,10 +3601,14 @@ AutomationEventList LoadAutomationEventList(const char *fileName)
|
|||||||
case 'c': sscanf(buffer, "c %i", &list.count); break;
|
case 'c': sscanf(buffer, "c %i", &list.count); break;
|
||||||
case 'e':
|
case 'e':
|
||||||
{
|
{
|
||||||
sscanf(buffer, "e %d %d %d %d %d %d %[^\n]s", &list.events[counter].frame, &list.events[counter].type,
|
if (counter < list.capacity)
|
||||||
|
{
|
||||||
|
sscanf(buffer, "e %d %d %d %d %d %d %63[^\n]s", &list.events[counter].frame, &list.events[counter].type,
|
||||||
&list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
|
&list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "AUTOMATION: Event goes beyond automated list capacity (MAX: %i): %s", buffer, list.capacity);
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/rlgl.h
19
src/rlgl.h
@ -910,6 +910,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
|||||||
#include <stdlib.h> // Required for: calloc(), free()
|
#include <stdlib.h> // Required for: calloc(), free()
|
||||||
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
||||||
#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
|
#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
|
||||||
|
#include <limits.h> // Required for: INT_MAX
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
@ -5236,7 +5237,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
|||||||
{
|
{
|
||||||
int blockWidth = (width + 3)/4;
|
int blockWidth = (width + 3)/4;
|
||||||
int blockHeight = (height + 3)/4;
|
int blockHeight = (height + 3)/4;
|
||||||
dataSize = blockWidth*blockHeight*8;
|
unsigned long long dataSizeBytes = blockWidth*blockHeight*8;
|
||||||
|
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
|
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
|
||||||
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
|
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
|
||||||
@ -5245,13 +5248,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
|||||||
{
|
{
|
||||||
int blockWidth = (width + 3)/4;
|
int blockWidth = (width + 3)/4;
|
||||||
int blockHeight = (height + 3)/4;
|
int blockHeight = (height + 3)/4;
|
||||||
dataSize = blockWidth*blockHeight*16;
|
unsigned long long dataSizeBytes = blockWidth*blockHeight*16;
|
||||||
|
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
|
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
|
||||||
{
|
{
|
||||||
int blockWidth = (width + 3)/4;
|
int blockWidth = (width + 3)/4;
|
||||||
int blockHeight = (height + 3)/4;
|
int blockHeight = (height + 3)/4;
|
||||||
dataSize = blockWidth*blockHeight*4;
|
unsigned long long dataSizeBytes = blockWidth*blockHeight*4;
|
||||||
|
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -5260,10 +5267,12 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
|||||||
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
|
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
|
||||||
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
||||||
{
|
{
|
||||||
double bytesPerPixel = (double)bpp/8.0;
|
unsigned long long dataSizeBytes = (width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
|
||||||
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
|
||||||
|
|
||||||
return dataSize;
|
return dataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2320,7 +2320,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, float frame)
|
|||||||
Matrix currentPoseMatrix = { 0 };
|
Matrix currentPoseMatrix = { 0 };
|
||||||
|
|
||||||
// Update all bones and bone matrices of model
|
// Update all bones and bone matrices of model
|
||||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||||
{
|
{
|
||||||
// Compute interpolated pose between current and next frame
|
// Compute interpolated pose between current and next frame
|
||||||
// NOTE: Storing animation frame data in model.currentPose
|
// NOTE: Storing animation frame data in model.currentPose
|
||||||
@ -2390,7 +2390,7 @@ void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, Mod
|
|||||||
Matrix bindPoseMatrix = { 0 };
|
Matrix bindPoseMatrix = { 0 };
|
||||||
Matrix currentPoseMatrix = { 0 };
|
Matrix currentPoseMatrix = { 0 };
|
||||||
|
|
||||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||||
{
|
{
|
||||||
// Get frame-interpolation for first animation
|
// Get frame-interpolation for first animation
|
||||||
Vector3 frameATranslation = Vector3Lerp(
|
Vector3 frameATranslation = Vector3Lerp(
|
||||||
@ -5013,7 +5013,7 @@ static Model LoadIQM(const char *fileName)
|
|||||||
// Initialize runtime animation data: current pose and bone matrices
|
// Initialize runtime animation data: current pose and bone matrices
|
||||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||||
|
|
||||||
UnloadFileData(fileData);
|
UnloadFileData(fileData);
|
||||||
|
|
||||||
@ -5241,7 +5241,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
|
|||||||
// Build frameposes
|
// Build frameposes
|
||||||
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
|
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < animations[a].boneCount; i++)
|
for (unsigned int i = 0; i < animations[a].boneCount; i++)
|
||||||
{
|
{
|
||||||
if (bones[i].parent >= 0)
|
if (bones[i].parent >= 0)
|
||||||
{
|
{
|
||||||
@ -5316,8 +5316,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||||||
{
|
{
|
||||||
int base64Size = (int)strlen(cgltfImage->uri + i + 1);
|
int base64Size = (int)strlen(cgltfImage->uri + i + 1);
|
||||||
while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
|
while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
|
||||||
int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
int numberOfEncodedBits = base64Size*6 - (base64Size*6)%8; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
||||||
int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes
|
int outSize = numberOfEncodedBits >> 3; // Actual encoded bytes
|
||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
|
|
||||||
cgltf_options options = { 0 };
|
cgltf_options options = { 0 };
|
||||||
@ -5371,7 +5371,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||||||
// Load bone info from GLTF skin data
|
// Load bone info from GLTF skin data
|
||||||
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount)
|
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount)
|
||||||
{
|
{
|
||||||
*boneCount = skin.joints_count;
|
*boneCount = (unsigned int)skin.joints_count;
|
||||||
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
|
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < skin.joints_count; i++)
|
for (unsigned int i = 0; i < skin.joints_count; i++)
|
||||||
@ -6144,7 +6144,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount);
|
model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount);
|
||||||
model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||||
|
|
||||||
for (int i = 0; i < model.skeleton.boneCount; i++)
|
for (unsigned int i = 0; i < model.skeleton.boneCount; i++)
|
||||||
{
|
{
|
||||||
Matrix bindMatrix = { 0 };
|
Matrix bindMatrix = { 0 };
|
||||||
cgltf_float inverseBindTransform[16] = { 0 };
|
cgltf_float inverseBindTransform[16] = { 0 };
|
||||||
@ -6309,7 +6309,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
|
if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
|
||||||
{
|
{
|
||||||
int parentBoneId = -1;
|
int parentBoneId = -1;
|
||||||
for (int joint = 0; joint < model.skeleton.boneCount; joint++)
|
for (unsigned int joint = 0; joint < model.skeleton.boneCount; joint++)
|
||||||
{
|
{
|
||||||
if (data->skins[0].joints[joint] == node->parent)
|
if (data->skins[0].joints[joint] == node->parent)
|
||||||
{
|
{
|
||||||
@ -6347,7 +6347,7 @@ static Model LoadGLTF(const char *fileName)
|
|||||||
// Initialize runtime animation data: current pose and bone matrices
|
// Initialize runtime animation data: current pose and bone matrices
|
||||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Free unused allocated memory in case of no bones defined
|
// Free unused allocated memory in case of no bones defined
|
||||||
@ -6670,7 +6670,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||||||
animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform));
|
animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform));
|
||||||
float time = (float)j / GLTF_FRAMERATE;
|
float time = (float)j / GLTF_FRAMERATE;
|
||||||
|
|
||||||
for (int k = 0; k < animations[a].boneCount; k++)
|
for (unsigned int k = 0; k < animations[a].boneCount; k++)
|
||||||
{
|
{
|
||||||
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
|
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
|
||||||
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
|
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
|
||||||
@ -7204,7 +7204,7 @@ static Model LoadM3D(const char *fileName)
|
|||||||
// Initialize runtime animation data: current pose and bone matrices
|
// Initialize runtime animation data: current pose and bone matrices
|
||||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
m3d_free(m3d);
|
m3d_free(m3d);
|
||||||
|
|||||||
24
src/rtext.c
24
src/rtext.c
@ -1699,7 +1699,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
if (text != NULL)
|
if ((text != NULL) && (position > 0) && (length > 0))
|
||||||
{
|
{
|
||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
||||||
@ -1975,10 +1975,11 @@ char *TextInsert(const char *text, const char *insert, int position)
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
if ((text != NULL) && (insert != NULL))
|
|
||||||
{
|
|
||||||
int textLen = TextLength(text);
|
int textLen = TextLength(text);
|
||||||
|
|
||||||
|
if ((text != NULL) && (insert != NULL) && (position >= 0))
|
||||||
|
{
|
||||||
|
if (position > textLen) position = textLen; // End of text string
|
||||||
int insertLen = TextLength(insert);
|
int insertLen = TextLength(insert);
|
||||||
|
|
||||||
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||||
@ -1987,7 +1988,7 @@ char *TextInsert(const char *text, const char *insert, int position)
|
|||||||
|
|
||||||
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
||||||
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
||||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
|
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i - insertLen];
|
||||||
|
|
||||||
buffer[textLen + insertLen] = '\0'; // Add EOL
|
buffer[textLen + insertLen] = '\0'; // Add EOL
|
||||||
}
|
}
|
||||||
@ -2002,17 +2003,18 @@ char *TextInsert(const char *text, const char *insert, int position)
|
|||||||
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
|
|
||||||
if ((text != NULL) && (insert != NULL))
|
|
||||||
{
|
|
||||||
int textLen = TextLength(text);
|
int textLen = TextLength(text);
|
||||||
|
|
||||||
|
if ((text != NULL) && (insert != NULL) && (position >= 0))
|
||||||
|
{
|
||||||
|
if (position > textLen) position = textLen; // End of text string
|
||||||
int insertLen = TextLength(insert);
|
int insertLen = TextLength(insert);
|
||||||
|
|
||||||
result = (char *)RL_MALLOC(textLen + insertLen + 1);
|
result = (char *)RL_MALLOC(textLen + insertLen + 1);
|
||||||
|
|
||||||
for (int i = 0; i < position; i++) result[i] = text[i];
|
for (int i = 0; i < position; i++) result[i] = text[i];
|
||||||
for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position];
|
for (int i = position; i < (insertLen + position); i++) result[i] = insert[i - position];
|
||||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
|
for (int i = (insertLen + position); i < (textLen + insertLen + position); i++) result[i] = text[i - insertLen];
|
||||||
|
|
||||||
result[textLen + insertLen] = '\0'; // Add EOL
|
result[textLen + insertLen] = '\0'; // Add EOL
|
||||||
}
|
}
|
||||||
@ -2036,7 +2038,7 @@ char *TextJoin(char **textList, int count, const char *delimiter)
|
|||||||
int textLength = TextLength(textList[i]);
|
int textLength = TextLength(textList[i]);
|
||||||
|
|
||||||
// Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
|
// Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
|
||||||
if ((totalLength + textLength) < MAX_TEXT_BUFFER_LENGTH)
|
if ((totalLength + textLength + delimiterLen) < MAX_TEXT_BUFFER_LENGTH)
|
||||||
{
|
{
|
||||||
memcpy(textPtr, textList[i], textLength);
|
memcpy(textPtr, textList[i], textLength);
|
||||||
totalLength += textLength;
|
totalLength += textLength;
|
||||||
|
|||||||
@ -70,6 +70,7 @@
|
|||||||
#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()]
|
#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()]
|
||||||
#include <math.h> // Required for: fabsf() [Used in DrawTextureRec()]
|
#include <math.h> // Required for: fabsf() [Used in DrawTextureRec()]
|
||||||
#include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()]
|
#include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()]
|
||||||
|
#include <limits.h> // Required for: INT_MAX
|
||||||
|
|
||||||
// Support only desired texture formats on stb_image
|
// Support only desired texture formats on stb_image
|
||||||
#if !SUPPORT_FILEFORMAT_BMP
|
#if !SUPPORT_FILEFORMAT_BMP
|
||||||
@ -843,9 +844,10 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
|||||||
// Generate image: plain color
|
// Generate image: plain color
|
||||||
Image GenImageColor(int width, int height, Color color)
|
Image GenImageColor(int width, int height, Color color)
|
||||||
{
|
{
|
||||||
Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color));
|
int dataSize = GetPixelDataSize(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
|
||||||
|
Color *pixels = (Color *)RL_CALLOC(dataSize, 1);
|
||||||
|
|
||||||
for (int i = 0; i < width*height; i++) pixels[i] = color;
|
for (int i = 0; (pixels != NULL) && (i < width*height); i++) pixels[i] = color;
|
||||||
|
|
||||||
Image image = {
|
Image image = {
|
||||||
.data = pixels,
|
.data = pixels,
|
||||||
@ -1228,6 +1230,11 @@ Image ImageFromImage(Image image, Rectangle rec)
|
|||||||
{
|
{
|
||||||
Image result = { 0 };
|
Image result = { 0 };
|
||||||
|
|
||||||
|
// Basic rectangle validation: size smaller than image size
|
||||||
|
if ((rec.x > 0) && (rec.y > 0) && (rec.width > 0) && (rec.height > 0) &&
|
||||||
|
(((int)rec.x + (int)rec.width) < image.width) &&
|
||||||
|
(((int)rec.y + (int)rec.height) < image.height))
|
||||||
|
{
|
||||||
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
||||||
|
|
||||||
result.width = (int)rec.width;
|
result.width = (int)rec.width;
|
||||||
@ -1240,6 +1247,8 @@ Image ImageFromImage(Image image, Rectangle rec)
|
|||||||
{
|
{
|
||||||
memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
|
memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "IMAGE: Rectangle provided for ImageToImage not valid");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2684,9 +2693,11 @@ void ImageRotate(Image *image, int degrees)
|
|||||||
int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius));
|
int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius));
|
||||||
int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius));
|
int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius));
|
||||||
|
|
||||||
int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
|
int bytesPerPixel = GetPixelDataSize(width, height, image->format);
|
||||||
unsigned char *rotatedData = (unsigned char *)RL_CALLOC(width*height, bytesPerPixel);
|
unsigned char *rotatedData = (unsigned char *)RL_CALLOC(bytesPerPixel, 1);
|
||||||
|
|
||||||
|
if (rotatedData != NULL)
|
||||||
|
{
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x++)
|
for (int x = 0; x < width; x++)
|
||||||
@ -2724,6 +2735,7 @@ void ImageRotate(Image *image, int degrees)
|
|||||||
image->width = width;
|
image->width = width;
|
||||||
image->height = height;
|
image->height = height;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate image clockwise 90deg
|
// Rotate image clockwise 90deg
|
||||||
@ -5502,8 +5514,11 @@ int GetPixelDataSize(int width, int height, int format)
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
double bytesPerPixel = (double)bpp/8.0;
|
unsigned long long dataSizeBytes = (width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
|
||||||
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
|
||||||
|
if (dataSizeBytes < INT_MAX)
|
||||||
|
{
|
||||||
|
dataSize = (int)dataSizeBytes;
|
||||||
|
|
||||||
// Most compressed formats works on 4x4 blocks,
|
// Most compressed formats works on 4x4 blocks,
|
||||||
// if texture is smaller, minimum dataSize is 8 or 16
|
// if texture is smaller, minimum dataSize is 8 or 16
|
||||||
@ -5512,6 +5527,10 @@ int GetPixelDataSize(int width, int height, int format)
|
|||||||
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
|
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
|
||||||
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
|
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: In case required image data larger than 2GB, no memory allocated at all (NULL)
|
||||||
|
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
|
||||||
|
|
||||||
return dataSize;
|
return dataSize;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user