diff --git a/src/api/process.c b/src/api/process.c
index ecbe076e..1be1286c 100644
--- a/src/api/process.c
+++ b/src/api/process.c
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#if _WIN32
// https://stackoverflow.com/questions/60645/overlapped-i-o-on-anonymous-pipe
@@ -21,19 +22,23 @@
#define READ_BUF_SIZE 2048
+#if _WIN32
+typedef HANDLE process_handle;
+#else
+typedef int process_handle;
+#endif
+
typedef struct {
bool running;
int returncode, deadline;
long pid;
#if _WIN32
PROCESS_INFORMATION process_information;
- HANDLE child_pipes[3][2];
OVERLAPPED overlapped[2];
bool reading[2];
char buffer[2][READ_BUF_SIZE];
- #else
- int child_pipes[3][2];
#endif
+ process_handle child_pipes[3][2];
} process_t;
typedef enum {
@@ -91,7 +96,7 @@ static bool poll_process(process_t* proc, int timeout) {
#endif
if (timeout)
SDL_Delay(5);
- } while (timeout == WAIT_INFINITE || SDL_GetTicks() - ticks < timeout);
+ } while (timeout == WAIT_INFINITE || (int)SDL_GetTicks() - ticks < timeout);
return proc->running;
}
@@ -117,8 +122,9 @@ static bool signal_process(process_t* proc, signal_e sig) {
}
static int process_start(lua_State* L) {
+ int retval = 1;
size_t env_len = 0, key_len, val_len;
- const char *cmd[256], *env_names[256] = { NULL }, *env_values[256] = { NULL }, *cwd = NULL;
+ const char *cmd[256] = { NULL }, *env_names[256] = { NULL }, *env_values[256] = { NULL }, *cwd = NULL;
bool detach = false;
int deadline = 10, new_fds[3] = { STDIN_FD, STDOUT_FD, STDERR_FD };
luaL_checktype(L, 1, LUA_TTABLE);
@@ -134,7 +140,11 @@ static int process_start(lua_State* L) {
lua_rawget(L, 1);
cmd[i-1] = luaL_checkstring(L, -1);
}
- cmd[cmd_len] = NULL;
+
+ // this should never trip
+ // but if it does we are in deep trouble
+ assert(cmd[0]);
+
if (arg_len > 1) {
lua_getfield(L, 2, "env");
if (!lua_isnil(L, -1)) {
@@ -158,8 +168,14 @@ static int process_start(lua_State* L) {
lua_getfield(L, 2, "stdout"); new_fds[STDOUT_FD] = luaL_optnumber(L, -1, STDOUT_FD);
lua_getfield(L, 2, "stderr"); new_fds[STDERR_FD] = luaL_optnumber(L, -1, STDERR_FD);
for (int stream = STDIN_FD; stream <= STDERR_FD; ++stream) {
- if (new_fds[stream] > STDERR_FD || new_fds[stream] < REDIRECT_PARENT)
- return luaL_error(L, "redirect to handles, FILE* and paths are not supported");
+ if (new_fds[stream] > STDERR_FD || new_fds[stream] < REDIRECT_PARENT) {
+ for (size_t i = 0; i < env_len; ++i) {
+ free((char*)env_names[i]);
+ free((char*)env_values[i]);
+ }
+ retval = luaL_error(L, "redirect to handles, FILE* and paths are not supported");
+ goto cleanup;
+ }
}
}
@@ -188,16 +204,21 @@ static int process_start(lua_State* L) {
sprintf(pipeNameBuffer, "\\\\.\\Pipe\\RemoteExeAnon.%08lx.%08lx", GetCurrentProcessId(), InterlockedIncrement(&PipeSerialNumber));
self->child_pipes[i][0] = CreateNamedPipeA(pipeNameBuffer, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT, 1, READ_BUF_SIZE, READ_BUF_SIZE, 0, NULL);
- if (self->child_pipes[i][0] == INVALID_HANDLE_VALUE)
- return luaL_error(L, "Error creating read pipe: %d.", GetLastError());
+ if (self->child_pipes[i][0] == INVALID_HANDLE_VALUE) {
+ retval = luaL_error(L, "Error creating read pipe: %d.", GetLastError());
+ goto cleanup;
+ }
self->child_pipes[i][1] = CreateFileA(pipeNameBuffer, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (self->child_pipes[i][1] == INVALID_HANDLE_VALUE) {
CloseHandle(self->child_pipes[i][0]);
- return luaL_error(L, "Error creating write pipe: %d.", GetLastError());
+ retval = luaL_error(L, "Error creating write pipe: %d.", GetLastError());
+ goto cleanup;
}
if (!SetHandleInformation(self->child_pipes[i][i == STDIN_FD ? 1 : 0], HANDLE_FLAG_INHERIT, 0) ||
- !SetHandleInformation(self->child_pipes[i][i == STDIN_FD ? 0 : 1], HANDLE_FLAG_INHERIT, 1))
- return luaL_error(L, "Error inheriting pipes: %d.", GetLastError());
+ !SetHandleInformation(self->child_pipes[i][i == STDIN_FD ? 0 : 1], HANDLE_FLAG_INHERIT, 1)) {
+ retval = luaL_error(L, "Error inheriting pipes: %d.", GetLastError());
+ goto cleanup;
+ }
}
} break;
}
@@ -237,24 +258,25 @@ static int process_start(lua_State* L) {
environmentBlock[offset++] = 0;
if (env_len > 0)
MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, environmentBlock, offset, (LPWSTR)wideEnvironmentBlock, sizeof(wideEnvironmentBlock));
- if (!CreateProcess(NULL, commandLine, NULL, NULL, true, (detach ? DETACHED_PROCESS : CREATE_NO_WINDOW) | CREATE_UNICODE_ENVIRONMENT, env_len > 0 ? wideEnvironmentBlock : NULL, cwd, &siStartInfo, &self->process_information))
- return luaL_error(L, "Error creating a process: %d.", GetLastError());
+ if (!CreateProcess(NULL, commandLine, NULL, NULL, true, (detach ? DETACHED_PROCESS : CREATE_NO_WINDOW) | CREATE_UNICODE_ENVIRONMENT, env_len > 0 ? wideEnvironmentBlock : NULL, cwd, &siStartInfo, &self->process_information)) {
+ retval = luaL_error(L, "Error creating a process: %d.", GetLastError());
+ goto cleanup;
+ }
self->pid = (long)self->process_information.dwProcessId;
if (detach)
CloseHandle(self->process_information.hProcess);
CloseHandle(self->process_information.hThread);
#else
for (int i = 0; i < 3; ++i) { // Make only the parents fd's non-blocking. Children should block.
- if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1)
- return luaL_error(L, "Error creating pipes: %s", strerror(errno));
+ if (pipe(self->child_pipes[i]) || fcntl(self->child_pipes[i][i == STDIN_FD ? 1 : 0], F_SETFL, O_NONBLOCK) == -1) {
+ retval = luaL_error(L, "Error creating pipes: %s", strerror(errno));
+ goto cleanup;
+ }
}
self->pid = (long)fork();
if (self->pid < 0) {
- for (int i = 0; i < 3; ++i) {
- close(self->child_pipes[i][0]);
- close(self->child_pipes[i][1]);
- }
- return luaL_error(L, "Error running fork: %s.", strerror(errno));
+ retval = luaL_error(L, "Error running fork: %s.", strerror(errno));
+ goto cleanup;
} else if (!self->pid) {
setpgrp();
for (int stream = 0; stream < 3; ++stream) {
@@ -265,23 +287,28 @@ static int process_start(lua_State* L) {
dup2(self->child_pipes[new_fds[stream]][new_fds[stream] == STDIN_FD ? 0 : 1], stream);
close(self->child_pipes[stream][stream == STDIN_FD ? 1 : 0]);
}
- int set;
+ size_t set;
for (set = 0; set < env_len && setenv(env_names[set], env_values[set], 1) == 0; ++set);
if (set == env_len && (!detach || setsid() != -1) && (!cwd || chdir(cwd) != -1))
- execvp((const char*)cmd[0], (char* const*)cmd);
+ execvp(cmd[0], (char** const)cmd);
const char* msg = strerror(errno);
- int result = write(STDERR_FD, msg, strlen(msg)+1);
+ size_t result = write(STDERR_FD, msg, strlen(msg)+1);
_exit(result == strlen(msg)+1 ? -1 : -2);
}
#endif
+ cleanup:
for (size_t i = 0; i < env_len; ++i) {
free((char*)env_names[i]);
free((char*)env_values[i]);
}
- for (int stream = 0; stream < 3; ++stream)
- close_fd(&self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]);
+ for (int stream = 0; stream < 3; ++stream) {
+ process_handle* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1];
+ if (*pipe) {
+ close_fd(pipe);
+ }
+ }
self->running = true;
- return 1;
+ return retval;
}
static int g_read(lua_State* L, int stream, unsigned long read_size) {
diff --git a/src/api/renderer.c b/src/api/renderer.c
index 0fc21707..3ab33b1a 100644
--- a/src/api/renderer.c
+++ b/src/api/renderer.c
@@ -1,3 +1,4 @@
+#include
#include "api.h"
#include "../renderer.h"
#include "../rencache.h"
@@ -166,14 +167,14 @@ static int f_get_size(lua_State *L) {
}
-static int f_begin_frame(lua_State *L) {
- rencache_begin_frame(L);
+static int f_begin_frame(UNUSED lua_State *L) {
+ rencache_begin_frame();
return 0;
}
-static int f_end_frame(lua_State *L) {
- rencache_end_frame(L);
+static int f_end_frame(UNUSED lua_State *L) {
+ rencache_end_frame();
return 0;
}
@@ -214,7 +215,7 @@ static int f_draw_text(lua_State *L) {
float x = luaL_checknumber(L, 3);
int y = luaL_checknumber(L, 4);
RenColor color = checkcolor(L, 5, 255);
- x = rencache_draw_text(L, fonts, text, x, y, color);
+ x = rencache_draw_text(fonts, text, x, y, color);
lua_pushnumber(L, x);
return 1;
}
diff --git a/src/api/system.c b/src/api/system.c
index f1f9c3c7..45231d0b 100644
--- a/src/api/system.c
+++ b/src/api/system.c
@@ -45,7 +45,7 @@ struct HitTestInfo {
};
typedef struct HitTestInfo HitTestInfo;
-static HitTestInfo window_hit_info[1] = {{0, 0}};
+static HitTestInfo window_hit_info[1] = {{0, 0, 0}};
#define RESIZE_FROM_TOP 0
#define RESIZE_FROM_RIGHT 0
@@ -705,13 +705,15 @@ static int f_set_window_opacity(lua_State *L) {
return 1;
}
+typedef void (*fptr)(void);
+
typedef struct lua_function_node {
const char *symbol;
- void *address;
+ fptr address;
} lua_function_node;
-#define P(FUNC) { "lua_" #FUNC, (void*)(lua_##FUNC) }
-#define U(FUNC) { "luaL_" #FUNC, (void*)(luaL_##FUNC) }
+#define P(FUNC) { "lua_" #FUNC, (fptr)(lua_##FUNC) }
+#define U(FUNC) { "luaL_" #FUNC, (fptr)(luaL_##FUNC) }
static void* api_require(const char* symbol) {
static lua_function_node nodes[] = {
P(atpanic), P(checkstack),
@@ -749,9 +751,9 @@ static void* api_require(const char* symbol) {
#endif
};
- for (int i = 0; i < sizeof(nodes) / sizeof(lua_function_node); ++i) {
+ for (size_t i = 0; i < sizeof(nodes) / sizeof(lua_function_node); ++i) {
if (strcmp(nodes[i].symbol, symbol) == 0)
- return nodes[i].address;
+ return *(void**)(&nodes[i].address);
}
return NULL;
}
@@ -775,10 +777,12 @@ static int f_load_native_plugin(lua_State *L) {
const char *basename = strrchr(name, '.');
basename = !basename ? name : basename + 1;
snprintf(entrypoint_name, sizeof(entrypoint_name), "luaopen_lite_xl_%s", basename);
- int (*ext_entrypoint) (lua_State *L, void*) = SDL_LoadFunction(library, entrypoint_name);
+ int (*ext_entrypoint) (lua_State *L, void* (*)(const char*));
+ *(void**)(&ext_entrypoint) = SDL_LoadFunction(library, entrypoint_name);
if (!ext_entrypoint) {
snprintf(entrypoint_name, sizeof(entrypoint_name), "luaopen_%s", basename);
- int (*entrypoint)(lua_State *L) = SDL_LoadFunction(library, entrypoint_name);
+ int (*entrypoint)(lua_State *L);
+ *(void**)(&entrypoint) = SDL_LoadFunction(library, entrypoint_name);
if (!entrypoint)
return luaL_error(L, "Unable to load %s: Can't find %s(lua_State *L, void *XL)", name, entrypoint_name);
result = entrypoint(L);
diff --git a/src/rencache.c b/src/rencache.c
index 5686d984..c847ce34 100644
--- a/src/rencache.c
+++ b/src/rencache.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include "rencache.h"
@@ -28,7 +29,7 @@ typedef struct {
RenColor color;
RenFont *fonts[FONT_FALLBACK_MAX];
float text_x;
- char text[0];
+ char text[];
} Command;
static unsigned cells_buf1[CELLS_X * CELLS_Y];
@@ -134,7 +135,7 @@ void rencache_draw_rect(RenRect rect, RenColor color) {
}
}
-float rencache_draw_text(lua_State *L, RenFont **fonts, const char *text, float x, int y, RenColor color)
+float rencache_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor color)
{
float width = ren_font_group_get_width(fonts, text);
RenRect rect = { x, y, (int)width, ren_font_group_get_height(fonts) };
@@ -159,7 +160,7 @@ void rencache_invalidate(void) {
}
-void rencache_begin_frame(lua_State *L) {
+void rencache_begin_frame() {
/* reset all cells if the screen width/height has changed */
int w, h;
ren_get_size(&w, &h);
@@ -200,7 +201,7 @@ static void push_rect(RenRect r, int *count) {
}
-void rencache_end_frame(lua_State *L) {
+void rencache_end_frame() {
/* update cells from commands */
Command *cmd = NULL;
RenRect cr = screen_rect;
diff --git a/src/rencache.h b/src/rencache.h
index 75bb5051..fedbada6 100644
--- a/src/rencache.h
+++ b/src/rencache.h
@@ -8,10 +8,9 @@
void rencache_show_debug(bool enable);
void rencache_set_clip_rect(RenRect rect);
void rencache_draw_rect(RenRect rect, RenColor color);
-float rencache_draw_text(lua_State *L, RenFont **font,
- const char *text, float x, int y, RenColor color);
+float rencache_draw_text(RenFont **font, const char *text, float x, int y, RenColor color);
void rencache_invalidate(void);
-void rencache_begin_frame(lua_State *L);
-void rencache_end_frame(lua_State *L);
+void rencache_begin_frame();
+void rencache_end_frame();
#endif
diff --git a/src/renderer.c b/src/renderer.c
index c2fa233e..f5f08045 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -18,6 +18,9 @@
static RenWindow window_renderer = {0};
static FT_Library library;
+// draw_rect_surface is used as a 1x1 surface to simplify ren_draw_rect with blending
+static SDL_Surface *draw_rect_surface;
+
static void* check_alloc(void *ptr) {
if (!ptr) {
fprintf(stderr, "Fatal error: memory allocation failed\n");
@@ -43,27 +46,28 @@ typedef struct RenFont {
FT_Face face;
GlyphSet* sets[SUBPIXEL_BITMAPS_CACHED][MAX_LOADABLE_GLYPHSETS];
float size, space_advance, tab_advance;
- short max_height, baseline, height;
+ unsigned short max_height, baseline, height;
ERenFontAntialiasing antialiasing;
ERenFontHinting hinting;
unsigned char style;
- char path[0];
+ char path[1];
} RenFont;
static const char* utf8_to_codepoint(const char *p, unsigned *dst) {
+ const unsigned char *up = (unsigned char*)p;
unsigned res, n;
switch (*p & 0xf0) {
- case 0xf0 : res = *p & 0x07; n = 3; break;
- case 0xe0 : res = *p & 0x0f; n = 2; break;
+ case 0xf0 : res = *up & 0x07; n = 3; break;
+ case 0xe0 : res = *up & 0x0f; n = 2; break;
case 0xd0 :
- case 0xc0 : res = *p & 0x1f; n = 1; break;
- default : res = *p; n = 0; break;
+ case 0xc0 : res = *up & 0x1f; n = 1; break;
+ default : res = *up; n = 0; break;
}
while (n--) {
- res = (res << 6) | (*(++p) & 0x3f);
+ res = (res << 6) | (*(++up) & 0x3f);
}
*dst = res;
- return p + 1;
+ return (const char*)up + 1;
}
static int font_set_load_options(RenFont* font) {
@@ -136,7 +140,7 @@ static void font_load_glyphset(RenFont* font, int idx) {
if (pen_x == 0)
continue;
set->surface = check_alloc(SDL_CreateRGBSurface(0, pen_x, font->max_height, font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? 24 : 8, 0, 0, 0, 0));
- unsigned char* pixels = set->surface->pixels;
+ uint8_t* pixels = set->surface->pixels;
for (int i = 0; i < MAX_GLYPHSET; ++i) {
int glyph_index = FT_Get_Char_Index(font->face, i + idx * MAX_GLYPHSET);
if (!glyph_index || FT_Load_Glyph(font->face, glyph_index, load_option))
@@ -145,11 +149,11 @@ static void font_load_glyphset(RenFont* font, int idx) {
font_set_style(&slot->outline, (64 / bitmaps_cached) * j, font->style);
if (FT_Render_Glyph(slot, render_option))
continue;
- for (int line = 0; line < slot->bitmap.rows; ++line) {
+ for (unsigned int line = 0; line < slot->bitmap.rows; ++line) {
int target_offset = set->surface->pitch * line + set->metrics[i].x0 * byte_width;
int source_offset = line * slot->bitmap.pitch;
if (font->antialiasing == FONT_ANTIALIASING_NONE) {
- for (int column = 0; column < slot->bitmap.width; ++column) {
+ for (unsigned int column = 0; column < slot->bitmap.width; ++column) {
int current_source_offset = source_offset + (column / 8);
int source_pixel = slot->bitmap.buffer[current_source_offset];
pixels[++target_offset] = ((source_pixel >> (7 - (column % 8))) & 0x1) << 7;
@@ -169,6 +173,9 @@ static GlyphSet* font_get_glyphset(RenFont* font, unsigned int codepoint, int su
}
static RenFont* font_group_get_glyph(GlyphSet** set, GlyphMetric** metric, RenFont** fonts, unsigned int codepoint, int bitmap_index) {
+ if (!metric) {
+ return NULL;
+ }
if (bitmap_index < 0)
bitmap_index += SUBPIXEL_BITMAPS_CACHED;
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
@@ -177,7 +184,7 @@ static RenFont* font_group_get_glyph(GlyphSet** set, GlyphMetric** metric, RenFo
if ((*metric)->loaded || codepoint < 0xFF)
return fonts[i];
}
- if (!(*metric)->loaded && codepoint > 0xFF && codepoint != 0x25A1)
+ if (*metric && !(*metric)->loaded && codepoint > 0xFF && codepoint != 0x25A1)
return font_group_get_glyph(set, metric, fonts, 0x25A1, bitmap_index);
return fonts[0];
}
@@ -195,7 +202,7 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial
font->face = face;
font->size = size;
font->height = (short)((face->height / (float)face->units_per_EM) * font->size);
- font->baseline = (short)((face->bbox.yMax / (float)face->units_per_EM) * font->size);
+ font->baseline = (short)((face->ascender / (float)face->units_per_EM) * font->size);
font->antialiasing = antialiasing;
font->hinting = hinting;
font->style = style;
@@ -233,7 +240,11 @@ void ren_font_group_set_tab_size(RenFont **fonts, int n) {
}
int ren_font_group_get_tab_size(RenFont **fonts) {
- return font_get_glyphset(fonts[0], '\t', 0)->metrics['\t'].xadvance / fonts[0]->space_advance;
+ int advance = font_get_glyphset(fonts[0], '\t', 0)->metrics['\t'].xadvance;
+ if (fonts[0]->space_advance) {
+ advance /= fonts[0]->space_advance;
+ }
+ return advance;
}
float ren_font_group_get_size(RenFont **fonts) {
@@ -251,6 +262,8 @@ float ren_font_group_get_width(RenFont **fonts, const char *text) {
unsigned int codepoint;
text = utf8_to_codepoint(text, &codepoint);
RenFont* font = font_group_get_glyph(&set, &metric, fonts, codepoint, 0);
+ if (!metric)
+ break;
width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance;
}
const int surface_scale = renwin_surface_scale(&window_renderer);
@@ -266,7 +279,7 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor
y *= surface_scale;
int bytes_per_pixel = surface->format->BytesPerPixel;
const char* end = text + strlen(text);
- unsigned char* destination_pixels = surface->pixels;
+ uint8_t* destination_pixels = surface->pixels;
int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height;
while (text < end) {
@@ -274,13 +287,15 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor
text = utf8_to_codepoint(text, &codepoint);
GlyphSet* set = NULL; GlyphMetric* metric = NULL;
RenFont* font = font_group_get_glyph(&set, &metric, fonts, codepoint, (int)(fmod(pen_x, 1.0) * SUBPIXEL_BITMAPS_CACHED));
+ if (!metric)
+ break;
int start_x = floor(pen_x) + metric->bitmap_left;
int end_x = (metric->x1 - metric->x0) + start_x;
int glyph_end = metric->x1, glyph_start = metric->x0;
if (!metric->loaded && codepoint > 0xFF)
ren_draw_rect((RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color);
if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) {
- unsigned char* source_pixels = set->surface->pixels;
+ uint8_t* source_pixels = set->surface->pixels;
for (int line = metric->y0; line < metric->y1; ++line) {
int target_y = line + y - metric->bitmap_top + font->baseline * surface_scale;
if (target_y < clip.y)
@@ -294,15 +309,30 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor
start_x += offset;
glyph_start += offset;
}
- unsigned int* destination_pixel = (unsigned int*)&destination_pixels[surface->pitch * target_y + start_x * bytes_per_pixel];
- unsigned char* source_pixel = &source_pixels[line * set->surface->pitch + glyph_start * (font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? 3 : 1)];
+ uint32_t* destination_pixel = (uint32_t*)&(destination_pixels[surface->pitch * target_y + start_x * bytes_per_pixel]);
+ uint8_t* source_pixel = &source_pixels[line * set->surface->pitch + glyph_start * (font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? 3 : 1)];
for (int x = glyph_start; x < glyph_end; ++x) {
- unsigned int destination_color = *destination_pixel;
+ uint32_t destination_color = *destination_pixel;
+ // the standard way of doing this would be SDL_GetRGBA, but that introduces a performance regression. needs to be investigated
SDL_Color dst = { (destination_color & surface->format->Rmask) >> surface->format->Rshift, (destination_color & surface->format->Gmask) >> surface->format->Gshift, (destination_color & surface->format->Bmask) >> surface->format->Bshift, (destination_color & surface->format->Amask) >> surface->format->Ashift };
- SDL_Color src = { *(font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? source_pixel++ : source_pixel), *(font->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? source_pixel++ : source_pixel), *source_pixel++ };
+ SDL_Color src;
+
+ if (font->antialiasing == FONT_ANTIALIASING_SUBPIXEL) {
+ src.r = *(source_pixel++);
+ src.g = *(source_pixel++);
+ }
+ else {
+ src.r = *(source_pixel);
+ src.g = *(source_pixel);
+ }
+
+ src.b = *(source_pixel++);
+ src.a = 0xFF;
+
r = (color.r * src.r * color.a + dst.r * (65025 - src.r * color.a) + 32767) / 65025;
g = (color.g * src.g * color.a + dst.g * (65025 - src.g * color.a) + 32767) / 65025;
b = (color.b * src.b * color.a + dst.b * (65025 - src.b * color.a) + 32767) / 65025;
+ // the standard way of doing this would be SDL_GetRGBA, but that introduces a performance regression. needs to be investigated
*destination_pixel++ = dst.a << surface->format->Ashift | r << surface->format->Rshift | g << surface->format->Gshift | b << surface->format->Bshift;
}
}
@@ -343,31 +373,21 @@ void ren_draw_rect(RenRect rect, RenColor color) {
y2 = y2 > clip.y + clip.height ? clip.y + clip.height : y2;
SDL_Surface *surface = renwin_get_surface(&window_renderer);
- uint32_t *d = surface->pixels;
- d += x1 + y1 * surface->w;
- int dr = surface->w - (x2 - x1);
+ SDL_Rect dest_rect = { x1, y1, x2 - x1, y2 - y1 };
if (color.a == 0xff) {
uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b);
- SDL_Rect rect = { x1, y1, x2 - x1, y2 - y1 };
- SDL_FillRect(surface, &rect, translated);
+ SDL_FillRect(surface, &dest_rect, translated);
} else {
- RenColor current_color;
- RenColor blended_color;
- for (int j = y1; j < y2; j++) {
- for (int i = x1; i < x2; i++, d++)
- {
- SDL_GetRGB(*d, surface->format, ¤t_color.r, ¤t_color.g, ¤t_color.b);
- blended_color = blend_pixel(current_color, color);
- *d = SDL_MapRGB(surface->format, blended_color.r, blended_color.g, blended_color.b);
- }
- d += dr;
- }
+ uint32_t *pixel = (uint32_t *)draw_rect_surface->pixels;
+ *pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a);
+ SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect);
}
}
/*************** Window Management ****************/
void ren_free_window_resources() {
renwin_free(&window_renderer);
+ SDL_FreeSurface(draw_rect_surface);
}
void ren_init(SDL_Window *win) {
@@ -380,6 +400,8 @@ void ren_init(SDL_Window *win) {
window_renderer.window = win;
renwin_init_surface(&window_renderer);
renwin_clip_to_surface(&window_renderer);
+ draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32,
+ 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
}
diff --git a/src/renderer.h b/src/renderer.h
index a97706ff..89c70d5e 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -5,6 +5,12 @@
#include
#include
+#ifdef __GNUC__
+#define UNUSED __attribute__((__unused__))
+#else
+#define UNUSED
+#endif
+
#define FONT_FALLBACK_MAX 4
typedef struct RenFont RenFont;
typedef enum { FONT_HINTING_NONE, FONT_HINTING_SLIGHT, FONT_HINTING_FULL } ERenFontHinting;
diff --git a/src/renwindow.c b/src/renwindow.c
index f67002f8..c2aa0096 100644
--- a/src/renwindow.c
+++ b/src/renwindow.c
@@ -27,7 +27,7 @@ static void setup_renderer(RenWindow *ren, int w, int h) {
#endif
-void renwin_init_surface(RenWindow *ren) {
+void renwin_init_surface(UNUSED RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER
if (ren->surface) {
SDL_FreeSurface(ren->surface);
@@ -39,7 +39,7 @@ void renwin_init_surface(RenWindow *ren) {
#endif
}
-int renwin_surface_scale(RenWindow *ren) {
+int renwin_surface_scale(UNUSED RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER
return ren->surface_scale;
#else
@@ -72,7 +72,7 @@ SDL_Surface *renwin_get_surface(RenWindow *ren) {
#endif
}
-void renwin_resize_surface(RenWindow *ren) {
+void renwin_resize_surface(UNUSED RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER
int new_w, new_h;
SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h);
diff --git a/subprojects/sdl2.wrap b/subprojects/sdl2.wrap
index 9ef9e1d3..b1affeb5 100644
--- a/subprojects/sdl2.wrap
+++ b/subprojects/sdl2.wrap
@@ -1,11 +1,11 @@
[wrap-file]
-directory = SDL2-2.0.18
-source_url = https://www.libsdl.org/release/SDL2-2.0.18.tar.gz
-source_filename = SDL2-2.0.18.tar.gz
-source_hash = 94d40cd73dbfa10bb6eadfbc28f355992bb2d6ef6761ad9d4074eff95ee5711c
-patch_filename = sdl2_2.0.18-2_patch.zip
-patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.0.18-2/get_patch
-patch_hash = cd77f33395d3d019bb89217b9da41fc640ed8c78cbbbebc5c662155a25e2820e
+directory = SDL2-2.0.20
+source_url = https://libsdl.org/release/SDL2-2.0.20.tar.gz
+source_filename = SDL2-2.0.20.tar.gz
+source_hash = c56aba1d7b5b0e7e999e4a7698c70b63a3394ff9704b5f6e1c57e0c16f04dd06
+patch_filename = sdl2_2.0.20-3_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.0.20-3/get_patch
+patch_hash = ade644ba46cefa4f1f9e57aa23bacc5dabf762d1f90d8416a1e1e4b0b7a188c4
[provide]
sdl2 = sdl2_dep