+8
.editorconfig
+8
.editorconfig
-19
LICENSE
-19
LICENSE
···
1
-
Copyright (c) 2020 rxi
2
-
3
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
4
-
this software and associated documentation files (the "Software"), to deal in
5
-
the Software without restriction, including without limitation the rights to
6
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
-
of the Software, and to permit persons to whom the Software is furnished to do
8
-
so, subject to the following conditions:
9
-
10
-
The above copyright notice and this permission notice shall be included in all
11
-
copies or substantial portions of the Software.
12
-
13
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
-
SOFTWARE.
-12
README.md
doc/original-readme.md
-12
README.md
doc/original-readme.md
···
1
-
# lite (emmeline's fork)
2
-
3
-
A fork of the [lite](https://github.com/rxi/lite) editor by rxi.
4
-
5
-
## Changes
6
-
7
-
- [ ] Reformat to my code style :p
8
-
- [/] Update to SDL 3
9
-
- [ ] Use LuaJIT
10
-
11
-
---
12
-
13
1
# lite
14
2

15
3
+1
-1
data/user/init.lua
+1
-1
data/user/init.lua
+53
license
+53
license
···
1
+
=== emmeline/lite: MIT License ===
2
+
3
+
Copyright (c) 2025 emmeline
4
+
5
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+
this software and associated documentation files (the "Software"), to deal in
7
+
the Software without restriction, including without limitation the rights to
8
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+
of the Software, and to permit persons to whom the Software is furnished to do
10
+
so, subject to the following conditions:
11
+
12
+
The above copyright notice and this permission notice shall be included in all
13
+
copies or substantial portions of the Software.
14
+
15
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+
SOFTWARE.
22
+
23
+
=== rxi/lite: MIT License ===
24
+
25
+
Copyright (c) 2020 rxi
26
+
27
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
28
+
this software and associated documentation files (the "Software"), to deal in
29
+
the Software without restriction, including without limitation the rights to
30
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
31
+
of the Software, and to permit persons to whom the Software is furnished to do
32
+
so, subject to the following conditions:
33
+
34
+
The above copyright notice and this permission notice shall be included in all
35
+
copies or substantial portions of the Software.
36
+
37
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43
+
SOFTWARE.
44
+
45
+
=== lua 5.4.8: MIT License ===
46
+
47
+
Copyright © 1994–2025 Lua.org, PUC-Rio.
48
+
49
+
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:
50
+
51
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
52
+
53
+
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.
+29
readme
+29
readme
···
1
+
lite (emmeline's fork)
2
+
======================
3
+
4
+
A fork of the [lite](https://github.com/rxi/lite) editor by rxi.
5
+
6
+
A lightweight editor written in Lua.
7
+
8
+
Usage: <doc/usage.md>
9
+
Plugins: <https://github.com/rxi/lite-plugins>
10
+
Themes: <https://github.com/rxi/lite-colors>
11
+
12
+
Build
13
+
-----
14
+
15
+
$ git clone https://tangled.org/emmeline.girlkisser.top/lite
16
+
$ cd lite
17
+
$ ./build.sh
18
+
$ ln -s $(pwd)/lite ~/.local/bin/
19
+
$ lite .
20
+
21
+
Changes
22
+
-------
23
+
24
+
- [x] Reformat to my code style :p
25
+
- [x] Update to SDL 3
26
+
- [ ] Use LuaJIT
27
+
28
+
License
29
+
-------
+9
-7
src/api/api.c
+9
-7
src/api/api.c
···
6
6
7
7
8
8
static const luaL_Reg libs[] = {
9
-
{ "system", luaopen_system },
10
-
{ "renderer", luaopen_renderer },
11
-
{ NULL, NULL }
9
+
{ "system", luaopen_system },
10
+
{ "renderer", luaopen_renderer },
11
+
{ NULL, NULL }
12
12
};
13
13
14
-
void api_load_libs(lua_State *L) {
15
-
for (int i = 0; libs[i].name; i++) {
16
-
luaL_requiref(L, libs[i].name, libs[i].func, 1);
17
-
}
14
+
void api_load_libs(lua_State *L)
15
+
{
16
+
for (int i = 0 ; libs[i].name ; i++)
17
+
{
18
+
luaL_requiref(L, libs[i].name, libs[i].func, 1);
19
+
}
18
20
}
+78
-70
src/api/renderer.c
+78
-70
src/api/renderer.c
···
3
3
#include "rencache.h"
4
4
5
5
6
-
static RenColor checkcolor(lua_State *L, int idx, int def) {
7
-
RenColor color;
8
-
if (lua_isnoneornil(L, idx)) {
9
-
return (RenColor) { def, def, def, 255 };
10
-
}
11
-
lua_rawgeti(L, idx, 1);
12
-
lua_rawgeti(L, idx, 2);
13
-
lua_rawgeti(L, idx, 3);
14
-
lua_rawgeti(L, idx, 4);
15
-
color.r = luaL_checknumber(L, -4);
16
-
color.g = luaL_checknumber(L, -3);
17
-
color.b = luaL_checknumber(L, -2);
18
-
color.a = luaL_optnumber(L, -1, 255);
19
-
lua_pop(L, 4);
20
-
return color;
6
+
static RenColor checkcolor(lua_State *L, int idx, int def)
7
+
{
8
+
RenColor color;
9
+
if (lua_isnoneornil(L, idx))
10
+
return (RenColor){ def, def, def, 255 };
11
+
lua_rawgeti(L, idx, 1);
12
+
lua_rawgeti(L, idx, 2);
13
+
lua_rawgeti(L, idx, 3);
14
+
lua_rawgeti(L, idx, 4);
15
+
color.r = luaL_checknumber(L, -4);
16
+
color.g = luaL_checknumber(L, -3);
17
+
color.b = luaL_checknumber(L, -2);
18
+
color.a = luaL_optnumber(L, -1, 255);
19
+
lua_pop(L, 4);
20
+
return color;
21
21
}
22
22
23
23
24
-
static int f_show_debug(lua_State *L) {
25
-
luaL_checkany(L, 1);
26
-
rencache_show_debug(lua_toboolean(L, 1));
27
-
return 0;
24
+
static int f_show_debug(lua_State *L)
25
+
{
26
+
luaL_checkany(L, 1);
27
+
rencache_show_debug(lua_toboolean(L, 1));
28
+
return 0;
28
29
}
29
30
30
31
31
-
static int f_get_size(lua_State *L) {
32
-
int w, h;
33
-
ren_get_size(&w, &h);
34
-
lua_pushnumber(L, w);
35
-
lua_pushnumber(L, h);
36
-
return 2;
32
+
static int f_get_size(lua_State *L)
33
+
{
34
+
int w, h;
35
+
ren_get_size(&w, &h);
36
+
lua_pushnumber(L, w);
37
+
lua_pushnumber(L, h);
38
+
return 2;
37
39
}
38
40
39
41
40
-
static int f_begin_frame(lua_State *L) {
41
-
rencache_begin_frame();
42
-
return 0;
42
+
static int f_begin_frame(lua_State *L)
43
+
{
44
+
rencache_begin_frame();
45
+
return 0;
43
46
}
44
47
45
48
46
-
static int f_end_frame(lua_State *L) {
47
-
rencache_end_frame();
48
-
return 0;
49
+
static int f_end_frame(lua_State *L)
50
+
{
51
+
rencache_end_frame();
52
+
return 0;
49
53
}
50
54
51
55
52
-
static int f_set_clip_rect(lua_State *L) {
53
-
RenRect rect;
54
-
rect.x = luaL_checknumber(L, 1);
55
-
rect.y = luaL_checknumber(L, 2);
56
-
rect.width = luaL_checknumber(L, 3);
57
-
rect.height = luaL_checknumber(L, 4);
58
-
rencache_set_clip_rect(rect);
59
-
return 0;
56
+
static int f_set_clip_rect(lua_State *L)
57
+
{
58
+
RenRect rect;
59
+
rect.x = luaL_checknumber(L, 1);
60
+
rect.y = luaL_checknumber(L, 2);
61
+
rect.width = luaL_checknumber(L, 3);
62
+
rect.height = luaL_checknumber(L, 4);
63
+
rencache_set_clip_rect(rect);
64
+
return 0;
60
65
}
61
66
62
67
63
-
static int f_draw_rect(lua_State *L) {
64
-
RenRect rect;
65
-
rect.x = luaL_checknumber(L, 1);
66
-
rect.y = luaL_checknumber(L, 2);
67
-
rect.width = luaL_checknumber(L, 3);
68
-
rect.height = luaL_checknumber(L, 4);
69
-
RenColor color = checkcolor(L, 5, 255);
70
-
rencache_draw_rect(rect, color);
71
-
return 0;
68
+
static int f_draw_rect(lua_State *L)
69
+
{
70
+
RenRect rect;
71
+
rect.x = luaL_checknumber(L, 1);
72
+
rect.y = luaL_checknumber(L, 2);
73
+
rect.width = luaL_checknumber(L, 3);
74
+
rect.height = luaL_checknumber(L, 4);
75
+
RenColor color = checkcolor(L, 5, 255);
76
+
rencache_draw_rect(rect, color);
77
+
return 0;
72
78
}
73
79
74
80
75
-
static int f_draw_text(lua_State *L) {
76
-
RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT);
77
-
const char *text = luaL_checkstring(L, 2);
78
-
int x = luaL_checknumber(L, 3);
79
-
int y = luaL_checknumber(L, 4);
80
-
RenColor color = checkcolor(L, 5, 255);
81
-
x = rencache_draw_text(*font, text, x, y, color);
82
-
lua_pushnumber(L, x);
83
-
return 1;
81
+
static int f_draw_text(lua_State *L)
82
+
{
83
+
RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT);
84
+
const char *text = luaL_checkstring(L, 2);
85
+
int x = luaL_checknumber(L, 3);
86
+
int y = luaL_checknumber(L, 4);
87
+
RenColor color = checkcolor(L, 5, 255);
88
+
x = rencache_draw_text(*font, text, x, y, color);
89
+
lua_pushnumber(L, x);
90
+
return 1;
84
91
}
85
92
86
93
87
94
static const luaL_Reg lib[] = {
88
-
{ "show_debug", f_show_debug },
89
-
{ "get_size", f_get_size },
90
-
{ "begin_frame", f_begin_frame },
91
-
{ "end_frame", f_end_frame },
92
-
{ "set_clip_rect", f_set_clip_rect },
93
-
{ "draw_rect", f_draw_rect },
94
-
{ "draw_text", f_draw_text },
95
-
{ NULL, NULL }
95
+
{ "show_debug", f_show_debug },
96
+
{ "get_size", f_get_size },
97
+
{ "begin_frame", f_begin_frame },
98
+
{ "end_frame", f_end_frame },
99
+
{ "set_clip_rect", f_set_clip_rect },
100
+
{ "draw_rect", f_draw_rect },
101
+
{ "draw_text", f_draw_text },
102
+
{ NULL, NULL }
96
103
};
97
104
98
105
99
106
int luaopen_renderer_font(lua_State *L);
100
107
101
-
int luaopen_renderer(lua_State *L) {
102
-
luaL_newlib(L, lib);
103
-
luaopen_renderer_font(L);
104
-
lua_setfield(L, -2, "font");
105
-
return 1;
108
+
int luaopen_renderer(lua_State *L)
109
+
{
110
+
luaL_newlib(L, lib);
111
+
luaopen_renderer_font(L);
112
+
lua_setfield(L, -2, "font");
113
+
return 1;
106
114
}
+46
-38
src/api/renderer_font.c
+46
-38
src/api/renderer_font.c
···
3
3
#include "rencache.h"
4
4
5
5
6
-
static int f_load(lua_State *L) {
7
-
const char *filename = luaL_checkstring(L, 1);
8
-
float size = luaL_checknumber(L, 2);
9
-
RenFont **self = lua_newuserdata(L, sizeof(*self));
10
-
luaL_setmetatable(L, API_TYPE_FONT);
11
-
*self = ren_load_font(filename, size);
12
-
if (!*self) { luaL_error(L, "failed to load font"); }
13
-
return 1;
6
+
static int f_load(lua_State *L)
7
+
{
8
+
const char *filename = luaL_checkstring(L, 1);
9
+
float size = luaL_checknumber(L, 2);
10
+
RenFont **self = lua_newuserdata(L, sizeof(*self));
11
+
luaL_setmetatable(L, API_TYPE_FONT);
12
+
*self = ren_load_font(filename, size);
13
+
if (!*self)
14
+
luaL_error(L, "failed to load font");
15
+
return 1;
14
16
}
15
17
16
18
17
-
static int f_set_tab_width(lua_State *L) {
18
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
19
-
int n = luaL_checknumber(L, 2);
20
-
ren_set_font_tab_width(*self, n);
21
-
return 0;
19
+
static int f_set_tab_width(lua_State *L)
20
+
{
21
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
22
+
int n = luaL_checknumber(L, 2);
23
+
ren_set_font_tab_width(*self, n);
24
+
return 0;
22
25
}
23
26
24
27
25
-
static int f_gc(lua_State *L) {
26
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
27
-
if (*self) { rencache_free_font(*self); }
28
-
return 0;
28
+
static int f_gc(lua_State *L)
29
+
{
30
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
31
+
if (*self)
32
+
rencache_free_font(*self);
33
+
return 0;
29
34
}
30
35
31
36
32
-
static int f_get_width(lua_State *L) {
33
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
34
-
const char *text = luaL_checkstring(L, 2);
35
-
lua_pushnumber(L, ren_get_font_width(*self, text) );
36
-
return 1;
37
+
static int f_get_width(lua_State *L)
38
+
{
39
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
40
+
const char *text = luaL_checkstring(L, 2);
41
+
lua_pushnumber(L, ren_get_font_width(*self, text) );
42
+
return 1;
37
43
}
38
44
39
45
40
-
static int f_get_height(lua_State *L) {
41
-
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
42
-
lua_pushnumber(L, ren_get_font_height(*self) );
43
-
return 1;
46
+
static int f_get_height(lua_State *L)
47
+
{
48
+
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
49
+
lua_pushnumber(L, ren_get_font_height(*self) );
50
+
return 1;
44
51
}
45
52
46
53
47
54
static const luaL_Reg lib[] = {
48
-
{ "__gc", f_gc },
49
-
{ "load", f_load },
50
-
{ "set_tab_width", f_set_tab_width },
51
-
{ "get_width", f_get_width },
52
-
{ "get_height", f_get_height },
53
-
{ NULL, NULL }
55
+
{ "__gc", f_gc },
56
+
{ "load", f_load },
57
+
{ "set_tab_width", f_set_tab_width },
58
+
{ "get_width", f_get_width },
59
+
{ "get_height", f_get_height },
60
+
{ NULL, NULL }
54
61
};
55
62
56
-
int luaopen_renderer_font(lua_State *L) {
57
-
luaL_newmetatable(L, API_TYPE_FONT);
58
-
luaL_setfuncs(L, lib, 0);
59
-
lua_pushvalue(L, -1);
60
-
lua_setfield(L, -2, "__index");
61
-
return 1;
63
+
int luaopen_renderer_font(lua_State *L)
64
+
{
65
+
luaL_newmetatable(L, API_TYPE_FONT);
66
+
luaL_setfuncs(L, lib, 0);
67
+
lua_pushvalue(L, -1);
68
+
lua_setfield(L, -2, "__index");
69
+
return 1;
62
70
}
+328
-286
src/api/system.c
+328
-286
src/api/system.c
···
9
9
#include "api.h"
10
10
#include "rencache.h"
11
11
#ifdef _WIN32
12
-
#include <windows.h>
12
+
# include <windows.h>
13
13
#endif
14
14
15
15
extern SDL_Window *window;
16
16
17
17
18
-
static const char* button_name(int button) {
19
-
switch (button) {
20
-
case 1 : return "left";
21
-
case 2 : return "middle";
22
-
case 3 : return "right";
23
-
default : return "?";
24
-
}
18
+
static const char* button_name(int button)
19
+
{
20
+
switch (button)
21
+
{
22
+
case 1 : return "left";
23
+
case 2 : return "middle";
24
+
case 3 : return "right";
25
+
default : return "?";
26
+
}
25
27
}
26
28
27
29
28
-
static char* key_name(char *dst, int sym) {
29
-
strcpy(dst, SDL_GetKeyName(sym));
30
-
char *p = dst;
31
-
while (*p) {
32
-
*p = tolower(*p);
33
-
p++;
34
-
}
35
-
return dst;
30
+
static char* key_name(char *dst, int sym)
31
+
{
32
+
strcpy(dst, SDL_GetKeyName(sym));
33
+
char *p = dst;
34
+
while (*p)
35
+
{
36
+
*p = tolower(*p);
37
+
p++;
38
+
}
39
+
return dst;
36
40
}
37
41
38
42
39
-
static int f_poll_event(lua_State *L) {
40
-
char buf[16];
41
-
float mx, my;
42
-
int wx, wy;
43
-
SDL_Event e;
43
+
static int f_poll_event(lua_State *L)
44
+
{
45
+
char buf[16];
46
+
float mx, my;
47
+
int wx, wy;
48
+
SDL_Event e;
44
49
45
50
top:
46
-
if ( !SDL_PollEvent(&e) ) {
47
-
return 0;
48
-
}
51
+
if (!SDL_PollEvent(&e))
52
+
return 0;
49
53
50
-
switch (e.type) {
51
-
case SDL_EVENT_QUIT :
52
-
lua_pushstring(L, "quit");
53
-
return 1;
54
+
switch (e.type)
55
+
{
56
+
case SDL_EVENT_QUIT :
57
+
lua_pushstring(L, "quit");
58
+
return 1;
54
59
55
-
case SDL_EVENT_WINDOW_RESIZED:
56
-
lua_pushstring(L, "resized");
57
-
lua_pushnumber(L, e.window.data1);
58
-
lua_pushnumber(L, e.window.data2);
59
-
return 3;
60
+
case SDL_EVENT_WINDOW_RESIZED:
61
+
lua_pushstring(L, "resized");
62
+
lua_pushnumber(L, e.window.data1);
63
+
lua_pushnumber(L, e.window.data2);
64
+
return 3;
60
65
61
-
case SDL_EVENT_WINDOW_EXPOSED:
62
-
rencache_invalidate();
63
-
lua_pushstring(L, "exposed");
64
-
return 1;
66
+
case SDL_EVENT_WINDOW_EXPOSED:
67
+
rencache_invalidate();
68
+
lua_pushstring(L, "exposed");
69
+
return 1;
65
70
66
-
case SDL_EVENT_WINDOW_FOCUS_GAINED:
67
-
/* on some systems, when alt-tabbing to the window SDL will queue up
68
-
** several KEYDOWN events for the `tab` key; we flush all keydown
69
-
** events on focus so these are discarded */
70
-
SDL_FlushEvent(SDL_EVENT_KEY_DOWN);
71
-
goto top;
71
+
case SDL_EVENT_WINDOW_FOCUS_GAINED:
72
+
/* on some systems, when alt-tabbing to the window SDL will queue up
73
+
** several KEYDOWN events for the `tab` key; we flush all keydown
74
+
** events on focus so these are discarded */
75
+
SDL_FlushEvent(SDL_EVENT_KEY_DOWN);
76
+
goto top;
72
77
73
-
case SDL_EVENT_DROP_FILE :
74
-
SDL_GetGlobalMouseState(&mx, &my);
75
-
SDL_GetWindowPosition(window, &wx, &wy);
76
-
lua_pushstring(L, "filedropped");
77
-
lua_pushstring(L, e.drop.data);
78
-
lua_pushnumber(L, mx - wx);
79
-
lua_pushnumber(L, my - wy);
80
-
return 4;
78
+
case SDL_EVENT_DROP_FILE :
79
+
SDL_GetGlobalMouseState(&mx, &my);
80
+
SDL_GetWindowPosition(window, &wx, &wy);
81
+
lua_pushstring(L, "filedropped");
82
+
lua_pushstring(L, e.drop.data);
83
+
lua_pushnumber(L, mx - wx);
84
+
lua_pushnumber(L, my - wy);
85
+
return 4;
81
86
82
-
case SDL_EVENT_KEY_DOWN :
83
-
lua_pushstring(L, "keypressed");
84
-
lua_pushstring(L, key_name(buf, e.key.key));
85
-
return 2;
87
+
case SDL_EVENT_KEY_DOWN :
88
+
lua_pushstring(L, "keypressed");
89
+
lua_pushstring(L, key_name(buf, e.key.key));
90
+
return 2;
86
91
87
-
case SDL_EVENT_KEY_UP :
88
-
lua_pushstring(L, "keyreleased");
89
-
lua_pushstring(L, key_name(buf, e.key.key));
90
-
return 2;
92
+
case SDL_EVENT_KEY_UP :
93
+
lua_pushstring(L, "keyreleased");
94
+
lua_pushstring(L, key_name(buf, e.key.key));
95
+
return 2;
91
96
92
-
case SDL_EVENT_TEXT_INPUT :
93
-
lua_pushstring(L, "textinput");
94
-
lua_pushstring(L, e.text.text);
95
-
return 2;
97
+
case SDL_EVENT_TEXT_INPUT :
98
+
lua_pushstring(L, "textinput");
99
+
lua_pushstring(L, e.text.text);
100
+
return 2;
96
101
97
-
case SDL_EVENT_MOUSE_BUTTON_DOWN :
98
-
if (e.button.button == 1) { SDL_CaptureMouse(1); }
99
-
lua_pushstring(L, "mousepressed");
100
-
lua_pushstring(L, button_name(e.button.button));
101
-
lua_pushnumber(L, e.button.x);
102
-
lua_pushnumber(L, e.button.y);
103
-
lua_pushnumber(L, e.button.clicks);
104
-
return 5;
102
+
case SDL_EVENT_MOUSE_BUTTON_DOWN :
103
+
if (e.button.button == 1)
104
+
SDL_CaptureMouse(1);
105
+
lua_pushstring(L, "mousepressed");
106
+
lua_pushstring(L, button_name(e.button.button));
107
+
lua_pushnumber(L, e.button.x);
108
+
lua_pushnumber(L, e.button.y);
109
+
lua_pushnumber(L, e.button.clicks);
110
+
return 5;
105
111
106
-
case SDL_EVENT_MOUSE_BUTTON_UP :
107
-
if (e.button.button == 1) { SDL_CaptureMouse(0); }
108
-
lua_pushstring(L, "mousereleased");
109
-
lua_pushstring(L, button_name(e.button.button));
110
-
lua_pushnumber(L, e.button.x);
111
-
lua_pushnumber(L, e.button.y);
112
-
return 4;
112
+
case SDL_EVENT_MOUSE_BUTTON_UP :
113
+
if (e.button.button == 1)
114
+
SDL_CaptureMouse(0);
115
+
lua_pushstring(L, "mousereleased");
116
+
lua_pushstring(L, button_name(e.button.button));
117
+
lua_pushnumber(L, e.button.x);
118
+
lua_pushnumber(L, e.button.y);
119
+
return 4;
113
120
114
-
case SDL_EVENT_MOUSE_MOTION :
115
-
lua_pushstring(L, "mousemoved");
116
-
lua_pushnumber(L, e.motion.x);
117
-
lua_pushnumber(L, e.motion.y);
118
-
lua_pushnumber(L, e.motion.xrel);
119
-
lua_pushnumber(L, e.motion.yrel);
120
-
return 5;
121
+
case SDL_EVENT_MOUSE_MOTION :
122
+
lua_pushstring(L, "mousemoved");
123
+
lua_pushnumber(L, e.motion.x);
124
+
lua_pushnumber(L, e.motion.y);
125
+
lua_pushnumber(L, e.motion.xrel);
126
+
lua_pushnumber(L, e.motion.yrel);
127
+
return 5;
121
128
122
-
case SDL_EVENT_MOUSE_WHEEL :
123
-
lua_pushstring(L, "mousewheel");
124
-
lua_pushnumber(L, e.wheel.y);
125
-
return 2;
129
+
case SDL_EVENT_MOUSE_WHEEL :
130
+
lua_pushstring(L, "mousewheel");
131
+
lua_pushnumber(L, e.wheel.y);
132
+
return 2;
126
133
127
-
default:
128
-
goto top;
129
-
}
134
+
default:
135
+
goto top;
136
+
}
130
137
131
-
return 0;
138
+
return 0;
132
139
}
133
140
134
141
135
-
static int f_wait_event(lua_State *L) {
136
-
double n = luaL_checknumber(L, 1);
137
-
lua_pushboolean(L, SDL_WaitEventTimeout(NULL, n * 1000));
138
-
return 1;
142
+
static int f_wait_event(lua_State *L)
143
+
{
144
+
double n = luaL_checknumber(L, 1);
145
+
lua_pushboolean(L, SDL_WaitEventTimeout(NULL, n * 1000));
146
+
return 1;
139
147
}
140
148
141
149
142
150
static SDL_Cursor* cursor_cache[SDL_SYSTEM_CURSOR_POINTER + 1];
143
151
144
152
static const char *cursor_opts[] = {
145
-
"arrow",
146
-
"ibeam",
147
-
"sizeh",
148
-
"sizev",
149
-
"hand",
150
-
NULL
153
+
"arrow",
154
+
"ibeam",
155
+
"sizeh",
156
+
"sizev",
157
+
"hand",
158
+
NULL
151
159
};
152
160
153
161
static const int cursor_enums[] = {
154
-
SDL_SYSTEM_CURSOR_DEFAULT,
155
-
SDL_SYSTEM_CURSOR_TEXT,
156
-
SDL_SYSTEM_CURSOR_EW_RESIZE,
157
-
SDL_SYSTEM_CURSOR_NS_RESIZE,
158
-
SDL_SYSTEM_CURSOR_POINTER
162
+
SDL_SYSTEM_CURSOR_DEFAULT,
163
+
SDL_SYSTEM_CURSOR_TEXT,
164
+
SDL_SYSTEM_CURSOR_EW_RESIZE,
165
+
SDL_SYSTEM_CURSOR_NS_RESIZE,
166
+
SDL_SYSTEM_CURSOR_POINTER
159
167
};
160
168
161
-
static int f_set_cursor(lua_State *L) {
162
-
int opt = luaL_checkoption(L, 1, "arrow", cursor_opts);
163
-
int n = cursor_enums[opt];
164
-
SDL_Cursor *cursor = cursor_cache[n];
165
-
if (!cursor) {
166
-
cursor = SDL_CreateSystemCursor(n);
167
-
cursor_cache[n] = cursor;
168
-
}
169
-
SDL_SetCursor(cursor);
170
-
return 0;
169
+
static int f_set_cursor(lua_State *L)
170
+
{
171
+
int opt = luaL_checkoption(L, 1, "arrow", cursor_opts);
172
+
int n = cursor_enums[opt];
173
+
SDL_Cursor *cursor = cursor_cache[n];
174
+
if (!cursor)
175
+
{
176
+
cursor = SDL_CreateSystemCursor(n);
177
+
cursor_cache[n] = cursor;
178
+
}
179
+
SDL_SetCursor(cursor);
180
+
return 0;
171
181
}
172
182
173
183
174
-
static int f_set_window_title(lua_State *L) {
175
-
const char *title = luaL_checkstring(L, 1);
176
-
SDL_SetWindowTitle(window, title);
177
-
return 0;
184
+
static int f_set_window_title(lua_State *L)
185
+
{
186
+
const char *title = luaL_checkstring(L, 1);
187
+
SDL_SetWindowTitle(window, title);
188
+
return 0;
178
189
}
179
190
180
191
181
192
static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 };
182
193
enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN };
183
194
184
-
static int f_set_window_mode(lua_State *L) {
185
-
int n = luaL_checkoption(L, 1, "normal", window_opts);
186
-
SDL_SetWindowFullscreen(window, n == WIN_FULLSCREEN ? SDL_GetWindowFullscreenMode(window) : 0);
187
-
if (n == WIN_NORMAL) { SDL_RestoreWindow(window); }
188
-
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window); }
189
-
return 0;
195
+
static int f_set_window_mode(lua_State *L)
196
+
{
197
+
int n = luaL_checkoption(L, 1, "normal", window_opts);
198
+
SDL_SetWindowFullscreen(window, n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN : 0);
199
+
if (n == WIN_NORMAL)
200
+
SDL_RestoreWindow(window);
201
+
if (n == WIN_MAXIMIZED)
202
+
SDL_MaximizeWindow(window);
203
+
return 0;
190
204
}
191
205
192
206
193
-
static int f_window_has_focus(lua_State *L) {
194
-
unsigned flags = SDL_GetWindowFlags(window);
195
-
lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS);
196
-
return 1;
207
+
static int f_window_has_focus(lua_State *L)
208
+
{
209
+
unsigned flags = SDL_GetWindowFlags(window);
210
+
lua_pushboolean(L, flags & SDL_WINDOW_INPUT_FOCUS);
211
+
return 1;
197
212
}
198
213
199
214
200
-
static int f_show_confirm_dialog(lua_State *L) {
201
-
const char *title = luaL_checkstring(L, 1);
202
-
const char *msg = luaL_checkstring(L, 2);
215
+
static int f_show_confirm_dialog(lua_State *L)
216
+
{
217
+
const char *title = luaL_checkstring(L, 1);
218
+
const char *msg = luaL_checkstring(L, 2);
203
219
204
-
#if _WIN32
205
-
int id = MessageBox(0, msg, title, MB_YESNO | MB_ICONWARNING);
206
-
lua_pushboolean(L, id == IDYES);
220
+
# if _WIN32
221
+
int id = MessageBox(0, msg, title, MB_YESNO | MB_ICONWARNING);
222
+
lua_pushboolean(L, id == IDYES);
207
223
208
-
#else
209
-
SDL_MessageBoxButtonData buttons[] = {
210
-
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Yes" },
211
-
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "No" },
212
-
};
213
-
SDL_MessageBoxData data = {
214
-
.title = title,
215
-
.message = msg,
216
-
.numbuttons = 2,
217
-
.buttons = buttons,
218
-
};
219
-
int buttonid;
220
-
SDL_ShowMessageBox(&data, &buttonid);
221
-
lua_pushboolean(L, buttonid == 1);
222
-
#endif
223
-
return 1;
224
+
# else
225
+
SDL_MessageBoxButtonData buttons[] = {
226
+
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Yes" },
227
+
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "No" },
228
+
};
229
+
SDL_MessageBoxData data = {
230
+
.title = title,
231
+
.message = msg,
232
+
.numbuttons = 2,
233
+
.buttons = buttons,
234
+
};
235
+
int buttonid;
236
+
SDL_ShowMessageBox(&data, &buttonid);
237
+
lua_pushboolean(L, buttonid == 1);
238
+
# endif
239
+
return 1;
224
240
}
225
241
226
242
227
-
static int f_chdir(lua_State *L) {
228
-
const char *path = luaL_checkstring(L, 1);
229
-
int err = chdir(path);
230
-
if (err) { luaL_error(L, "chdir() failed"); }
231
-
return 0;
243
+
static int f_chdir(lua_State *L)
244
+
{
245
+
const char *path = luaL_checkstring(L, 1);
246
+
int err = chdir(path);
247
+
if (err)
248
+
luaL_error(L, "chdir() failed");
249
+
return 0;
232
250
}
233
251
234
252
235
-
static int f_list_dir(lua_State *L) {
236
-
const char *path = luaL_checkstring(L, 1);
253
+
static int f_list_dir(lua_State *L)
254
+
{
255
+
const char *path = luaL_checkstring(L, 1);
237
256
238
-
DIR *dir = opendir(path);
239
-
if (!dir) {
240
-
lua_pushnil(L);
241
-
lua_pushstring(L, strerror(errno));
242
-
return 2;
243
-
}
257
+
DIR *dir = opendir(path);
258
+
if (!dir)
259
+
{
260
+
lua_pushnil(L);
261
+
lua_pushstring(L, strerror(errno));
262
+
return 2;
263
+
}
244
264
245
-
lua_newtable(L);
246
-
int i = 1;
247
-
struct dirent *entry;
248
-
while ( (entry = readdir(dir)) ) {
249
-
if (strcmp(entry->d_name, "." ) == 0) { continue; }
250
-
if (strcmp(entry->d_name, "..") == 0) { continue; }
251
-
lua_pushstring(L, entry->d_name);
252
-
lua_rawseti(L, -2, i);
253
-
i++;
254
-
}
265
+
lua_newtable(L);
266
+
int i = 1;
267
+
struct dirent *entry;
268
+
while ((entry = readdir(dir)))
269
+
{
270
+
if (strcmp(entry->d_name, "." ) == 0 || strcmp(entry->d_name, "..") == 0)
271
+
continue;
272
+
lua_pushstring(L, entry->d_name);
273
+
lua_rawseti(L, -2, i);
274
+
i++;
275
+
}
255
276
256
-
closedir(dir);
257
-
return 1;
277
+
closedir(dir);
278
+
return 1;
258
279
}
259
280
260
281
261
282
#ifdef _WIN32
262
-
#include <windows.h>
263
-
#define realpath(x, y) _fullpath(y, x, MAX_PATH)
283
+
# include <windows.h>
284
+
# define realpath(x, y) _fullpath(y, x, MAX_PATH)
264
285
#endif
265
286
266
-
static int f_absolute_path(lua_State *L) {
267
-
const char *path = luaL_checkstring(L, 1);
268
-
char *res = realpath(path, NULL);
269
-
if (!res) { return 0; }
270
-
lua_pushstring(L, res);
271
-
free(res);
272
-
return 1;
287
+
static int f_absolute_path(lua_State *L)
288
+
{
289
+
const char *path = luaL_checkstring(L, 1);
290
+
char *res = realpath(path, NULL);
291
+
if (!res)
292
+
return 0;
293
+
lua_pushstring(L, res);
294
+
free(res);
295
+
return 1;
273
296
}
274
297
275
298
276
-
static int f_get_file_info(lua_State *L) {
277
-
const char *path = luaL_checkstring(L, 1);
299
+
static int f_get_file_info(lua_State *L)
300
+
{
301
+
const char *path = luaL_checkstring(L, 1);
278
302
279
-
struct stat s;
280
-
int err = stat(path, &s);
281
-
if (err < 0) {
282
-
lua_pushnil(L);
283
-
lua_pushstring(L, strerror(errno));
284
-
return 2;
285
-
}
303
+
struct stat s;
304
+
int err = stat(path, &s);
305
+
if (err < 0)
306
+
{
307
+
lua_pushnil(L);
308
+
lua_pushstring(L, strerror(errno));
309
+
return 2;
310
+
}
286
311
287
-
lua_newtable(L);
288
-
lua_pushnumber(L, s.st_mtime);
289
-
lua_setfield(L, -2, "modified");
312
+
lua_newtable(L);
313
+
lua_pushnumber(L, s.st_mtime);
314
+
lua_setfield(L, -2, "modified");
290
315
291
-
lua_pushnumber(L, s.st_size);
292
-
lua_setfield(L, -2, "size");
316
+
lua_pushnumber(L, s.st_size);
317
+
lua_setfield(L, -2, "size");
293
318
294
-
if (S_ISREG(s.st_mode)) {
295
-
lua_pushstring(L, "file");
296
-
} else if (S_ISDIR(s.st_mode)) {
297
-
lua_pushstring(L, "dir");
298
-
} else {
299
-
lua_pushnil(L);
300
-
}
301
-
lua_setfield(L, -2, "type");
319
+
if (S_ISREG(s.st_mode))
320
+
lua_pushstring(L, "file");
321
+
else if (S_ISDIR(s.st_mode))
322
+
lua_pushstring(L, "dir");
323
+
else
324
+
lua_pushnil(L);
325
+
lua_setfield(L, -2, "type");
302
326
303
-
return 1;
327
+
return 1;
304
328
}
305
329
306
330
307
-
static int f_get_clipboard(lua_State *L) {
308
-
char *text = SDL_GetClipboardText();
309
-
if (!text) { return 0; }
310
-
lua_pushstring(L, text);
311
-
SDL_free(text);
312
-
return 1;
331
+
static int f_get_clipboard(lua_State *L)
332
+
{
333
+
char *text = SDL_GetClipboardText();
334
+
if (!text)
335
+
return 0;
336
+
lua_pushstring(L, text);
337
+
SDL_free(text);
338
+
return 1;
313
339
}
314
340
315
341
316
-
static int f_set_clipboard(lua_State *L) {
317
-
const char *text = luaL_checkstring(L, 1);
318
-
SDL_SetClipboardText(text);
319
-
return 0;
342
+
static int f_set_clipboard(lua_State *L)
343
+
{
344
+
const char *text = luaL_checkstring(L, 1);
345
+
SDL_SetClipboardText(text);
346
+
return 0;
320
347
}
321
348
322
349
323
-
static int f_get_time(lua_State *L) {
324
-
double n = SDL_GetPerformanceCounter() / (double) SDL_GetPerformanceFrequency();
325
-
lua_pushnumber(L, n);
326
-
return 1;
350
+
static int f_get_time(lua_State *L)
351
+
{
352
+
double n = SDL_GetPerformanceCounter() / (double) SDL_GetPerformanceFrequency();
353
+
lua_pushnumber(L, n);
354
+
return 1;
327
355
}
328
356
329
357
330
-
static int f_sleep(lua_State *L) {
331
-
double n = luaL_checknumber(L, 1);
332
-
SDL_Delay(n * 1000);
333
-
return 0;
358
+
static int f_sleep(lua_State *L)
359
+
{
360
+
double n = luaL_checknumber(L, 1);
361
+
SDL_Delay(n * 1000);
362
+
return 0;
334
363
}
335
364
336
365
337
-
static int f_exec(lua_State *L) {
338
-
size_t len;
339
-
const char *cmd = luaL_checklstring(L, 1, &len);
340
-
char *buf = malloc(len + 32);
341
-
if (!buf) { luaL_error(L, "buffer allocation failed"); }
342
-
#if _WIN32
343
-
sprintf(buf, "cmd /c \"%s\"", cmd);
344
-
WinExec(buf, SW_HIDE);
345
-
#else
346
-
sprintf(buf, "%s &", cmd);
347
-
int res = system(buf);
348
-
(void) res;
349
-
#endif
350
-
free(buf);
351
-
return 0;
366
+
static int f_exec(lua_State *L)
367
+
{
368
+
size_t len;
369
+
const char *cmd = luaL_checklstring(L, 1, &len);
370
+
char *buf = malloc(len + 32);
371
+
if (!buf)
372
+
luaL_error(L, "buffer allocation failed");
373
+
374
+
# if _WIN32
375
+
sprintf(buf, "cmd /c \"%s\"", cmd);
376
+
WinExec(buf, SW_HIDE);
377
+
# else
378
+
sprintf(buf, "%s &", cmd);
379
+
int res = system(buf);
380
+
(void)res;
381
+
# endif
382
+
383
+
free(buf);
384
+
return 0;
352
385
}
353
386
354
387
355
-
static int f_fuzzy_match(lua_State *L) {
356
-
const char *str = luaL_checkstring(L, 1);
357
-
const char *ptn = luaL_checkstring(L, 2);
358
-
int score = 0;
359
-
int run = 0;
388
+
static int f_fuzzy_match(lua_State *L)
389
+
{
390
+
const char *str = luaL_checkstring(L, 1);
391
+
const char *ptn = luaL_checkstring(L, 2);
392
+
int score = 0;
393
+
int run = 0;
360
394
361
-
while (*str && *ptn) {
362
-
while (*str == ' ') { str++; }
363
-
while (*ptn == ' ') { ptn++; }
364
-
if (tolower(*str) == tolower(*ptn)) {
365
-
score += run * 10 - (*str != *ptn);
366
-
run++;
367
-
ptn++;
368
-
} else {
369
-
score -= 10;
370
-
run = 0;
371
-
}
372
-
str++;
373
-
}
374
-
if (*ptn) { return 0; }
395
+
while (*str && *ptn)
396
+
{
397
+
while (*str == ' ')
398
+
str++;
399
+
while (*ptn == ' ')
400
+
ptn++;
401
+
if (tolower(*str) == tolower(*ptn))
402
+
{
403
+
score += run * 10 - (*str != *ptn);
404
+
run++;
405
+
ptn++;
406
+
}
407
+
else
408
+
{
409
+
score -= 10;
410
+
run = 0;
411
+
}
412
+
str++;
413
+
}
414
+
if (*ptn)
415
+
return 0;
375
416
376
-
lua_pushnumber(L, score - (int) strlen(str));
377
-
return 1;
417
+
lua_pushnumber(L, score - (int) strlen(str));
418
+
return 1;
378
419
}
379
420
380
421
381
422
static const luaL_Reg lib[] = {
382
-
{ "poll_event", f_poll_event },
383
-
{ "wait_event", f_wait_event },
384
-
{ "set_cursor", f_set_cursor },
385
-
{ "set_window_title", f_set_window_title },
386
-
{ "set_window_mode", f_set_window_mode },
387
-
{ "window_has_focus", f_window_has_focus },
388
-
{ "show_confirm_dialog", f_show_confirm_dialog },
389
-
{ "chdir", f_chdir },
390
-
{ "list_dir", f_list_dir },
391
-
{ "absolute_path", f_absolute_path },
392
-
{ "get_file_info", f_get_file_info },
393
-
{ "get_clipboard", f_get_clipboard },
394
-
{ "set_clipboard", f_set_clipboard },
395
-
{ "get_time", f_get_time },
396
-
{ "sleep", f_sleep },
397
-
{ "exec", f_exec },
398
-
{ "fuzzy_match", f_fuzzy_match },
399
-
{ NULL, NULL }
423
+
{ "poll_event", f_poll_event },
424
+
{ "wait_event", f_wait_event },
425
+
{ "set_cursor", f_set_cursor },
426
+
{ "set_window_title", f_set_window_title },
427
+
{ "set_window_mode", f_set_window_mode },
428
+
{ "window_has_focus", f_window_has_focus },
429
+
{ "show_confirm_dialog", f_show_confirm_dialog },
430
+
{ "chdir", f_chdir },
431
+
{ "list_dir", f_list_dir },
432
+
{ "absolute_path", f_absolute_path },
433
+
{ "get_file_info", f_get_file_info },
434
+
{ "get_clipboard", f_get_clipboard },
435
+
{ "set_clipboard", f_set_clipboard },
436
+
{ "get_time", f_get_time },
437
+
{ "sleep", f_sleep },
438
+
{ "exec", f_exec },
439
+
{ "fuzzy_match", f_fuzzy_match },
440
+
{ NULL, NULL }
400
441
};
401
442
402
443
403
-
int luaopen_system(lua_State *L) {
404
-
luaL_newlib(L, lib);
405
-
return 1;
444
+
int luaopen_system(lua_State *L)
445
+
{
446
+
luaL_newlib(L, lib);
447
+
return 1;
406
448
}
+101
-99
src/main.c
+101
-99
src/main.c
···
5
5
#include "renderer.h"
6
6
7
7
#ifdef _WIN32
8
-
#include <windows.h>
8
+
# include <windows.h>
9
9
#elif __linux__
10
-
#include <unistd.h>
10
+
# include <unistd.h>
11
11
#elif __APPLE__
12
-
#include <mach-o/dyld.h>
12
+
# include <mach-o/dyld.h>
13
13
#endif
14
14
15
15
16
16
SDL_Window *window;
17
17
18
18
19
-
static double get_scale(void) {
20
-
return (double)SDL_min(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()), 1.0);
19
+
static double get_scale(void)
20
+
{
21
+
return (double)SDL_min(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()), 1.0);
21
22
}
22
23
23
-
24
-
static void get_exe_filename(char *buf, int sz) {
25
-
#if _WIN32
26
-
int len = GetModuleFileName(NULL, buf, sz - 1);
27
-
buf[len] = '\0';
28
-
#elif __linux__
29
-
char path[512];
30
-
sprintf(path, "/proc/%d/exe", getpid());
31
-
int len = readlink(path, buf, sz - 1);
32
-
buf[len] = '\0';
33
-
#elif __APPLE__
34
-
unsigned size = sz;
35
-
_NSGetExecutablePath(buf, &size);
36
-
#else
37
-
strcpy(buf, "./lite");
38
-
#endif
24
+
static void get_exe_filename(char *buf, int sz)
25
+
{
26
+
# if _WIN32
27
+
int len = GetModuleFileName(NULL, buf, sz - 1);
28
+
buf[len] = '\0';
29
+
# elif __linux__
30
+
char path[512];
31
+
sprintf(path, "/proc/%d/exe", getpid());
32
+
int len = readlink(path, buf, sz - 1);
33
+
buf[len] = '\0';
34
+
# elif __APPLE__
35
+
unsigned size = sz;
36
+
_NSGetExecutablePath(buf, &size);
37
+
# else
38
+
strcpy(buf, "./lite");
39
+
# endif
39
40
}
40
41
41
42
42
-
static void init_window_icon(void) {
43
-
#ifndef _WIN32
44
-
#include "../icon.inl"
45
-
(void) icon_rgba_len; /* unused */
46
-
SDL_Surface *surf = SDL_CreateSurfaceFrom(64, 64, SDL_PIXELFORMAT_ABGR8888, icon_rgba, 64 * 4);
47
-
SDL_SetWindowIcon(window, surf);
48
-
SDL_DestroySurface(surf);
49
-
#endif
43
+
static void init_window_icon(void)
44
+
{
45
+
# ifndef _WIN32
46
+
# include "../icon.inl"
47
+
(void) icon_rgba_len; /* unused */
48
+
SDL_Surface *surf = SDL_CreateSurfaceFrom(64, 64, SDL_PIXELFORMAT_ABGR8888, icon_rgba, 64 * 4);
49
+
SDL_SetWindowIcon(window, surf);
50
+
SDL_DestroySurface(surf);
51
+
# endif
50
52
}
51
53
52
54
53
-
int main(int argc, char **argv) {
54
-
#ifdef _WIN32
55
-
HINSTANCE lib = LoadLibrary("user32.dll");
56
-
int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware");
57
-
SetProcessDPIAware();
58
-
#endif
59
-
60
-
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
61
-
SDL_EnableScreenSaver();
62
-
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, true);
63
-
atexit(SDL_Quit);
64
-
65
-
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
66
-
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
55
+
int main(int argc, char **argv)
56
+
{
57
+
# ifdef _WIN32
58
+
HINSTANCE lib = LoadLibrary("user32.dll");
59
+
int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware");
60
+
SetProcessDPIAware();
61
+
# endif
67
62
68
-
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
69
-
window = SDL_CreateWindow("", (int)(dm->w * 0.8), (int)(dm->h * 0.8), SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN);
70
-
if (!window)
71
-
{
72
-
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window: %s\n", SDL_GetError());
73
-
return EXIT_FAILURE;
74
-
}
75
-
init_window_icon();
76
-
ren_init(window);
63
+
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
64
+
SDL_EnableScreenSaver();
65
+
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, true);
66
+
atexit(SDL_Quit);
77
67
78
-
if (!SDL_StartTextInput(window))
79
-
{
80
-
#ifndef _WIN32
81
-
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR: failed SDL_StartTextInput() - text entry may not work");
82
-
#endif
83
-
}
68
+
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
69
+
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
84
70
71
+
const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
72
+
window = SDL_CreateWindow("", (int)(dm->w * 0.8), (int)(dm->h * 0.8), SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN);
73
+
if (!window)
74
+
{
75
+
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window: %s\n", SDL_GetError());
76
+
return EXIT_FAILURE;
77
+
}
78
+
init_window_icon();
79
+
ren_init(window);
85
80
86
-
lua_State *L = luaL_newstate();
87
-
luaL_openlibs(L);
88
-
api_load_libs(L);
81
+
if (!SDL_StartTextInput(window))
82
+
{
83
+
# ifndef _WIN32
84
+
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR: failed SDL_StartTextInput() - text entry may not work");
85
+
# endif
86
+
}
89
87
90
88
91
-
lua_newtable(L);
92
-
for (int i = 0; i < argc; i++) {
93
-
lua_pushstring(L, argv[i]);
94
-
lua_rawseti(L, -2, i + 1);
95
-
}
96
-
lua_setglobal(L, "ARGS");
89
+
lua_State *L = luaL_newstate();
90
+
luaL_openlibs(L);
91
+
api_load_libs(L);
97
92
98
-
lua_pushstring(L, "1.11");
99
-
lua_setglobal(L, "VERSION");
93
+
lua_newtable(L);
94
+
for (int i = 0 ; i < argc ; i++)
95
+
{
96
+
lua_pushstring(L, argv[i]);
97
+
lua_rawseti(L, -2, i + 1);
98
+
}
99
+
lua_setglobal(L, "ARGS");
100
100
101
-
lua_pushstring(L, SDL_GetPlatform());
102
-
lua_setglobal(L, "PLATFORM");
101
+
lua_pushstring(L, "1.11");
102
+
lua_setglobal(L, "VERSION");
103
103
104
-
lua_pushnumber(L, get_scale());
105
-
lua_setglobal(L, "SCALE");
104
+
lua_pushstring(L, SDL_GetPlatform());
105
+
lua_setglobal(L, "PLATFORM");
106
106
107
-
char exename[2048];
108
-
get_exe_filename(exename, sizeof(exename));
109
-
lua_pushstring(L, exename);
110
-
lua_setglobal(L, "EXEFILE");
107
+
lua_pushnumber(L, get_scale());
108
+
lua_setglobal(L, "SCALE");
111
109
110
+
char exename[2048];
111
+
get_exe_filename(exename, sizeof(exename));
112
+
lua_pushstring(L, exename);
113
+
lua_setglobal(L, "EXEFILE");
112
114
113
-
(void) luaL_dostring(L,
114
-
"local core\n"
115
-
"xpcall(function()\n"
116
-
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
117
-
" PATHSEP = package.config:sub(1, 1)\n"
118
-
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
119
-
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
120
-
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
121
-
" core = require('core')\n"
122
-
" core.init()\n"
123
-
" core.run()\n"
124
-
"end, function(err)\n"
125
-
" print('Error: ' .. tostring(err))\n"
126
-
" print(debug.traceback(nil, 2))\n"
127
-
" if core and core.on_error then\n"
128
-
" pcall(core.on_error, err)\n"
129
-
" end\n"
130
-
" os.exit(1)\n"
131
-
"end)");
115
+
(void) luaL_dostring(L,
116
+
"local core\n"
117
+
"xpcall(function()\n"
118
+
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
119
+
" PATHSEP = package.config:sub(1, 1)\n"
120
+
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
121
+
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
122
+
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
123
+
" core = require('core')\n"
124
+
" core.init()\n"
125
+
" core.run()\n"
126
+
"end, function(err)\n"
127
+
" print('Error: ' .. tostring(err))\n"
128
+
" print(debug.traceback(nil, 2))\n"
129
+
" if core and core.on_error then\n"
130
+
" pcall(core.on_error, err)\n"
131
+
" end\n"
132
+
" os.exit(1)\n"
133
+
"end)");
132
134
133
135
134
-
lua_close(L);
135
-
SDL_DestroyWindow(window);
136
+
lua_close(L);
137
+
SDL_DestroyWindow(window);
136
138
137
-
return EXIT_SUCCESS;
139
+
return EXIT_SUCCESS;
138
140
}
+265
-197
src/rencache.c
+265
-197
src/rencache.c
···
11
11
#define CELL_SIZE 96
12
12
#define COMMAND_BUF_SIZE (1024 * 512)
13
13
14
-
enum { FREE_FONT, SET_CLIP, DRAW_TEXT, DRAW_RECT };
14
+
enum
15
+
{
16
+
FREE_FONT,
17
+
SET_CLIP,
18
+
DRAW_TEXT,
19
+
DRAW_RECT
20
+
};
15
21
16
-
typedef struct {
17
-
int type, size;
18
-
RenRect rect;
19
-
RenColor color;
20
-
RenFont *font;
21
-
int tab_width;
22
-
char text[0];
22
+
typedef struct
23
+
{
24
+
int type, size;
25
+
RenRect rect;
26
+
RenColor color;
27
+
RenFont *font;
28
+
int tab_width;
29
+
char text[0];
23
30
} Command;
24
31
25
32
···
40
47
/* 32bit fnv-1a hash */
41
48
#define HASH_INITIAL 2166136261
42
49
43
-
static void hash(unsigned *h, const void *data, int size) {
44
-
const unsigned char *p = data;
45
-
while (size--) {
46
-
*h = (*h ^ *p++) * 16777619;
47
-
}
50
+
static void hash(unsigned *h, const void *data, int size)
51
+
{
52
+
const unsigned char *p = data;
53
+
while (size--)
54
+
{
55
+
*h = (*h ^ *p++) * 16777619;
56
+
}
48
57
}
49
58
50
59
51
-
static inline int cell_idx(int x, int y) {
52
-
return x + y * CELLS_X;
60
+
static inline int cell_idx(int x, int y)
61
+
{
62
+
return x + y * CELLS_X;
53
63
}
54
64
55
65
56
-
static inline bool rects_overlap(RenRect a, RenRect b) {
57
-
return b.x + b.width >= a.x && b.x <= a.x + a.width
58
-
&& b.y + b.height >= a.y && b.y <= a.y + a.height;
66
+
static inline bool rects_overlap(RenRect a, RenRect b)
67
+
{
68
+
return b.x + b.width >= a.x &&
69
+
b.x <= a.x + a.width &&
70
+
b.y + b.height >= a.y &&
71
+
b.y <= a.y + a.height;
59
72
}
60
73
61
74
62
-
static RenRect intersect_rects(RenRect a, RenRect b) {
63
-
int x1 = max(a.x, b.x);
64
-
int y1 = max(a.y, b.y);
65
-
int x2 = min(a.x + a.width, b.x + b.width);
66
-
int y2 = min(a.y + a.height, b.y + b.height);
67
-
return (RenRect) { x1, y1, max(0, x2 - x1), max(0, y2 - y1) };
75
+
static RenRect intersect_rects(RenRect a, RenRect b)
76
+
{
77
+
int x1 = max(a.x, b.x);
78
+
int y1 = max(a.y, b.y);
79
+
int x2 = min(a.x + a.width, b.x + b.width);
80
+
int y2 = min(a.y + a.height, b.y + b.height);
81
+
return (RenRect){ x1, y1, max(0, x2 - x1), max(0, y2 - y1) };
68
82
}
69
83
70
84
71
-
static RenRect merge_rects(RenRect a, RenRect b) {
72
-
int x1 = min(a.x, b.x);
73
-
int y1 = min(a.y, b.y);
74
-
int x2 = max(a.x + a.width, b.x + b.width);
75
-
int y2 = max(a.y + a.height, b.y + b.height);
76
-
return (RenRect) { x1, y1, x2 - x1, y2 - y1 };
85
+
static RenRect merge_rects(RenRect a, RenRect b)
86
+
{
87
+
int x1 = min(a.x, b.x);
88
+
int y1 = min(a.y, b.y);
89
+
int x2 = max(a.x + a.width, b.x + b.width);
90
+
int y2 = max(a.y + a.height, b.y + b.height);
91
+
return (RenRect){ x1, y1, x2 - x1, y2 - y1 };
77
92
}
78
93
79
94
80
-
static Command* push_command(int type, int size) {
81
-
Command *cmd = (Command*) (command_buf + command_buf_idx);
82
-
int n = command_buf_idx + size;
83
-
if (n > COMMAND_BUF_SIZE) {
84
-
fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n");
85
-
return NULL;
86
-
}
87
-
command_buf_idx = n;
88
-
memset(cmd, 0, sizeof(Command));
89
-
cmd->type = type;
90
-
cmd->size = size;
91
-
return cmd;
95
+
static Command* push_command(int type, int size)
96
+
{
97
+
Command *cmd = (Command *)(command_buf + command_buf_idx);
98
+
int n = command_buf_idx + size;
99
+
if (n > COMMAND_BUF_SIZE)
100
+
{
101
+
fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n");
102
+
return NULL;
103
+
}
104
+
command_buf_idx = n;
105
+
memset(cmd, 0, sizeof(Command));
106
+
cmd->type = type;
107
+
cmd->size = size;
108
+
return cmd;
92
109
}
93
110
94
111
95
-
static bool next_command(Command **prev) {
96
-
if (*prev == NULL) {
97
-
*prev = (Command*) command_buf;
98
-
} else {
99
-
*prev = (Command*) (((char*) *prev) + (*prev)->size);
100
-
}
101
-
return *prev != ((Command*) (command_buf + command_buf_idx));
112
+
static bool next_command(Command **prev)
113
+
{
114
+
if (*prev == NULL)
115
+
{
116
+
*prev = (Command *)command_buf;
117
+
}
118
+
else
119
+
{
120
+
*prev = (Command *)(((char*) *prev) + (*prev)->size);
121
+
}
122
+
123
+
return *prev != ((Command *)(command_buf + command_buf_idx));
102
124
}
103
125
104
126
105
-
void rencache_show_debug(bool enable) {
106
-
show_debug = enable;
127
+
void rencache_show_debug(bool enable)
128
+
{
129
+
show_debug = enable;
107
130
}
108
131
109
132
110
-
void rencache_free_font(RenFont *font) {
111
-
Command *cmd = push_command(FREE_FONT, sizeof(Command));
112
-
if (cmd) { cmd->font = font; }
133
+
void rencache_free_font(RenFont *font)
134
+
{
135
+
Command *cmd = push_command(FREE_FONT, sizeof(Command));
136
+
if (cmd)
137
+
{
138
+
cmd->font = font;
139
+
}
113
140
}
114
141
115
142
116
-
void rencache_set_clip_rect(RenRect rect) {
117
-
Command *cmd = push_command(SET_CLIP, sizeof(Command));
118
-
if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); }
143
+
void rencache_set_clip_rect(RenRect rect)
144
+
{
145
+
Command *cmd = push_command(SET_CLIP, sizeof(Command));
146
+
if (cmd)
147
+
{
148
+
cmd->rect = intersect_rects(rect, screen_rect);
149
+
}
119
150
}
120
151
121
152
122
-
void rencache_draw_rect(RenRect rect, RenColor color) {
123
-
if (!rects_overlap(screen_rect, rect)) { return; }
124
-
Command *cmd = push_command(DRAW_RECT, sizeof(Command));
125
-
if (cmd) {
126
-
cmd->rect = rect;
127
-
cmd->color = color;
128
-
}
153
+
void rencache_draw_rect(RenRect rect, RenColor color)
154
+
{
155
+
if (!rects_overlap(screen_rect, rect))
156
+
{
157
+
return;
158
+
}
159
+
Command *cmd = push_command(DRAW_RECT, sizeof(Command));
160
+
if (cmd)
161
+
{
162
+
cmd->rect = rect;
163
+
cmd->color = color;
164
+
}
129
165
}
130
166
131
167
132
-
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) {
133
-
RenRect rect;
134
-
rect.x = x;
135
-
rect.y = y;
136
-
rect.width = ren_get_font_width(font, text);
137
-
rect.height = ren_get_font_height(font);
168
+
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color)
169
+
{
170
+
RenRect rect;
171
+
rect.x = x;
172
+
rect.y = y;
173
+
rect.width = ren_get_font_width(font, text);
174
+
rect.height = ren_get_font_height(font);
138
175
139
-
if (rects_overlap(screen_rect, rect)) {
140
-
int sz = strlen(text) + 1;
141
-
Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz);
142
-
if (cmd) {
143
-
memcpy(cmd->text, text, sz);
144
-
cmd->color = color;
145
-
cmd->font = font;
146
-
cmd->rect = rect;
147
-
cmd->tab_width = ren_get_font_tab_width(font);
148
-
}
149
-
}
176
+
if (rects_overlap(screen_rect, rect))
177
+
{
178
+
int sz = strlen(text) + 1;
179
+
Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz);
180
+
if (cmd)
181
+
{
182
+
memcpy(cmd->text, text, sz);
183
+
cmd->color = color;
184
+
cmd->font = font;
185
+
cmd->rect = rect;
186
+
cmd->tab_width = ren_get_font_tab_width(font);
187
+
}
188
+
}
150
189
151
-
return x + rect.width;
190
+
return x + rect.width;
152
191
}
153
192
154
193
155
-
void rencache_invalidate(void) {
156
-
memset(cells_prev, 0xff, sizeof(cells_buf1));
194
+
void rencache_invalidate(void)
195
+
{
196
+
memset(cells_prev, 0xff, sizeof(cells_buf1));
157
197
}
158
198
159
199
160
-
void rencache_begin_frame(void) {
161
-
/* reset all cells if the screen width/height has changed */
162
-
int w, h;
163
-
ren_get_size(&w, &h);
164
-
if (screen_rect.width != w || h != screen_rect.height) {
165
-
screen_rect.width = w;
166
-
screen_rect.height = h;
167
-
rencache_invalidate();
168
-
}
200
+
void rencache_begin_frame(void)
201
+
{
202
+
/* reset all cells if the screen width/height has changed */
203
+
int w, h;
204
+
ren_get_size(&w, &h);
205
+
if (screen_rect.width != w || h != screen_rect.height)
206
+
{
207
+
screen_rect.width = w;
208
+
screen_rect.height = h;
209
+
rencache_invalidate();
210
+
}
169
211
}
170
212
171
213
172
-
static void update_overlapping_cells(RenRect r, unsigned h) {
173
-
int x1 = r.x / CELL_SIZE;
174
-
int y1 = r.y / CELL_SIZE;
175
-
int x2 = (r.x + r.width) / CELL_SIZE;
176
-
int y2 = (r.y + r.height) / CELL_SIZE;
214
+
static void update_overlapping_cells(RenRect r, unsigned h)
215
+
{
216
+
int x1 = r.x / CELL_SIZE;
217
+
int y1 = r.y / CELL_SIZE;
218
+
int x2 = (r.x + r.width) / CELL_SIZE;
219
+
int y2 = (r.y + r.height) / CELL_SIZE;
177
220
178
-
for (int y = y1; y <= y2; y++) {
179
-
for (int x = x1; x <= x2; x++) {
180
-
int idx = cell_idx(x, y);
181
-
hash(&cells[idx], &h, sizeof(h));
182
-
}
183
-
}
221
+
for (int y = y1; y <= y2; y++)
222
+
{
223
+
for (int x = x1; x <= x2; x++)
224
+
{
225
+
int idx = cell_idx(x, y);
226
+
hash(&cells[idx], &h, sizeof(h));
227
+
}
228
+
}
184
229
}
185
230
186
231
187
-
static void push_rect(RenRect r, int *count) {
188
-
/* try to merge with existing rectangle */
189
-
for (int i = *count - 1; i >= 0; i--) {
190
-
RenRect *rp = &rect_buf[i];
191
-
if (rects_overlap(*rp, r)) {
192
-
*rp = merge_rects(*rp, r);
193
-
return;
194
-
}
195
-
}
196
-
/* couldn't merge with previous rectangle: push */
197
-
rect_buf[(*count)++] = r;
232
+
static void push_rect(RenRect r, int *count)
233
+
{
234
+
/* try to merge with existing rectangle */
235
+
for (int i = *count - 1; i >= 0; i--)
236
+
{
237
+
RenRect *rp = &rect_buf[i];
238
+
if (rects_overlap(*rp, r))
239
+
{
240
+
*rp = merge_rects(*rp, r);
241
+
return;
242
+
}
243
+
}
244
+
/* couldn't merge with previous rectangle: push */
245
+
rect_buf[(*count)++] = r;
198
246
}
199
247
200
248
201
-
void rencache_end_frame(void) {
202
-
/* update cells from commands */
203
-
Command *cmd = NULL;
204
-
RenRect cr = screen_rect;
205
-
while (next_command(&cmd)) {
206
-
if (cmd->type == SET_CLIP) { cr = cmd->rect; }
207
-
RenRect r = intersect_rects(cmd->rect, cr);
208
-
if (r.width == 0 || r.height == 0) { continue; }
209
-
unsigned h = HASH_INITIAL;
210
-
hash(&h, cmd, cmd->size);
211
-
update_overlapping_cells(r, h);
212
-
}
249
+
void rencache_end_frame(void)
250
+
{
251
+
/* update cells from commands */
252
+
Command *cmd = NULL;
253
+
RenRect cr = screen_rect;
254
+
while (next_command(&cmd))
255
+
{
256
+
if (cmd->type == SET_CLIP)
257
+
{
258
+
cr = cmd->rect;
259
+
}
260
+
RenRect r = intersect_rects(cmd->rect, cr);
261
+
if (r.width == 0 || r.height == 0)
262
+
{
263
+
continue;
264
+
}
265
+
unsigned h = HASH_INITIAL;
266
+
hash(&h, cmd, cmd->size);
267
+
update_overlapping_cells(r, h);
268
+
}
213
269
214
-
/* push rects for all cells changed from last frame, reset cells */
215
-
int rect_count = 0;
216
-
int max_x = screen_rect.width / CELL_SIZE + 1;
217
-
int max_y = screen_rect.height / CELL_SIZE + 1;
218
-
for (int y = 0; y < max_y; y++) {
219
-
for (int x = 0; x < max_x; x++) {
220
-
/* compare previous and current cell for change */
221
-
int idx = cell_idx(x, y);
222
-
if (cells[idx] != cells_prev[idx]) {
223
-
push_rect((RenRect) { x, y, 1, 1 }, &rect_count);
224
-
}
225
-
cells_prev[idx] = HASH_INITIAL;
226
-
}
227
-
}
270
+
/* push rects for all cells changed from last frame, reset cells */
271
+
int rect_count = 0;
272
+
int max_x = screen_rect.width / CELL_SIZE + 1;
273
+
int max_y = screen_rect.height / CELL_SIZE + 1;
274
+
for (int y = 0; y < max_y; y++)
275
+
{
276
+
for (int x = 0; x < max_x; x++)
277
+
{
278
+
/* compare previous and current cell for change */
279
+
int idx = cell_idx(x, y);
280
+
if (cells[idx] != cells_prev[idx])
281
+
{
282
+
push_rect((RenRect) { x, y, 1, 1 }, &rect_count);
283
+
}
284
+
cells_prev[idx] = HASH_INITIAL;
285
+
}
286
+
}
228
287
229
-
/* expand rects from cells to pixels */
230
-
for (int i = 0; i < rect_count; i++) {
231
-
RenRect *r = &rect_buf[i];
232
-
r->x *= CELL_SIZE;
233
-
r->y *= CELL_SIZE;
234
-
r->width *= CELL_SIZE;
235
-
r->height *= CELL_SIZE;
236
-
*r = intersect_rects(*r, screen_rect);
237
-
}
288
+
/* expand rects from cells to pixels */
289
+
for (int i = 0; i < rect_count; i++)
290
+
{
291
+
RenRect *r = &rect_buf[i];
292
+
r->x *= CELL_SIZE;
293
+
r->y *= CELL_SIZE;
294
+
r->width *= CELL_SIZE;
295
+
r->height *= CELL_SIZE;
296
+
*r = intersect_rects(*r, screen_rect);
297
+
}
238
298
239
-
/* redraw updated regions */
240
-
bool has_free_commands = false;
241
-
for (int i = 0; i < rect_count; i++) {
242
-
/* draw */
243
-
RenRect r = rect_buf[i];
244
-
ren_set_clip_rect(r);
299
+
/* redraw updated regions */
300
+
bool has_free_commands = false;
301
+
for (int i = 0; i < rect_count; i++)
302
+
{
303
+
/* draw */
304
+
RenRect r = rect_buf[i];
305
+
ren_set_clip_rect(r);
245
306
246
-
cmd = NULL;
247
-
while (next_command(&cmd)) {
248
-
switch (cmd->type) {
249
-
case FREE_FONT:
250
-
has_free_commands = true;
251
-
break;
252
-
case SET_CLIP:
253
-
ren_set_clip_rect(intersect_rects(cmd->rect, r));
254
-
break;
255
-
case DRAW_RECT:
256
-
ren_draw_rect(cmd->rect, cmd->color);
257
-
break;
258
-
case DRAW_TEXT:
259
-
ren_set_font_tab_width(cmd->font, cmd->tab_width);
260
-
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color);
261
-
break;
262
-
}
263
-
}
307
+
cmd = NULL;
308
+
while (next_command(&cmd))
309
+
{
310
+
switch (cmd->type)
311
+
{
312
+
case FREE_FONT:
313
+
has_free_commands = true;
314
+
break;
315
+
case SET_CLIP:
316
+
ren_set_clip_rect(intersect_rects(cmd->rect, r));
317
+
break;
318
+
case DRAW_RECT:
319
+
ren_draw_rect(cmd->rect, cmd->color);
320
+
break;
321
+
case DRAW_TEXT:
322
+
ren_set_font_tab_width(cmd->font, cmd->tab_width);
323
+
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color);
324
+
break;
325
+
}
326
+
}
264
327
265
-
if (show_debug) {
266
-
RenColor color = { rand(), rand(), rand(), 50 };
267
-
ren_draw_rect(r, color);
268
-
}
269
-
}
328
+
if (show_debug)
329
+
{
330
+
RenColor color = { rand(), rand(), rand(), 50 };
331
+
ren_draw_rect(r, color);
332
+
}
333
+
}
270
334
271
-
/* update dirty rects */
272
-
if (rect_count > 0) {
273
-
ren_update_rects(rect_buf, rect_count);
274
-
}
335
+
/* update dirty rects */
336
+
if (rect_count > 0)
337
+
{
338
+
ren_update_rects(rect_buf, rect_count);
339
+
}
275
340
276
-
/* free fonts */
277
-
if (has_free_commands) {
278
-
cmd = NULL;
279
-
while (next_command(&cmd)) {
280
-
if (cmd->type == FREE_FONT) {
281
-
ren_free_font(cmd->font);
282
-
}
283
-
}
284
-
}
341
+
/* free fonts */
342
+
if (has_free_commands)
343
+
{
344
+
cmd = NULL;
345
+
while (next_command(&cmd))
346
+
{
347
+
if (cmd->type == FREE_FONT)
348
+
{
349
+
ren_free_font(cmd->font);
350
+
}
351
+
}
352
+
}
285
353
286
-
/* swap cell buffer and reset */
287
-
unsigned *tmp = cells;
288
-
cells = cells_prev;
289
-
cells_prev = tmp;
290
-
command_buf_idx = 0;
354
+
/* swap cell buffer and reset */
355
+
unsigned *tmp = cells;
356
+
cells = cells_prev;
357
+
cells_prev = tmp;
358
+
command_buf_idx = 0;
291
359
}
+299
-249
src/renderer.c
+299
-249
src/renderer.c
···
7
7
8
8
#define MAX_GLYPHSET 256
9
9
10
-
struct RenImage {
11
-
RenColor *pixels;
12
-
int width, height;
10
+
struct RenImage
11
+
{
12
+
RenColor *pixels;
13
+
int width, height;
13
14
};
14
15
15
-
typedef struct {
16
-
RenImage *image;
17
-
stbtt_bakedchar glyphs[256];
16
+
typedef struct
17
+
{
18
+
RenImage *image;
19
+
stbtt_bakedchar glyphs[256];
18
20
} GlyphSet;
19
21
20
-
struct RenFont {
21
-
void *data;
22
-
stbtt_fontinfo stbfont;
23
-
GlyphSet *sets[MAX_GLYPHSET];
24
-
float size;
25
-
int height;
22
+
struct RenFont
23
+
{
24
+
void *data;
25
+
stbtt_fontinfo stbfont;
26
+
GlyphSet *sets[MAX_GLYPHSET];
27
+
float size;
28
+
int height;
26
29
};
27
30
28
31
29
32
static SDL_Window *window;
30
-
static struct { int left, top, right, bottom; } clip;
33
+
static struct
34
+
{
35
+
int left, top, right, bottom;
36
+
} clip;
31
37
32
38
33
-
static void* check_alloc(void *ptr) {
34
-
if (!ptr) {
35
-
fprintf(stderr, "Fatal error: memory allocation failed\n");
36
-
exit(EXIT_FAILURE);
37
-
}
38
-
return ptr;
39
+
static void* check_alloc(void *ptr)
40
+
{
41
+
if (!ptr)
42
+
{
43
+
fprintf(stderr, "Fatal error: memory allocation failed\n");
44
+
exit(EXIT_FAILURE);
45
+
}
46
+
return ptr;
39
47
}
40
48
41
49
42
-
static const char* utf8_to_codepoint(const char *p, unsigned *dst) {
43
-
unsigned res, n;
44
-
switch (*p & 0xf0) {
45
-
case 0xf0 : res = *p & 0x07; n = 3; break;
46
-
case 0xe0 : res = *p & 0x0f; n = 2; break;
47
-
case 0xd0 :
48
-
case 0xc0 : res = *p & 0x1f; n = 1; break;
49
-
default : res = *p; n = 0; break;
50
-
}
51
-
while (n--) {
52
-
res = (res << 6) | (*(++p) & 0x3f);
53
-
}
54
-
*dst = res;
55
-
return p + 1;
50
+
static const char* utf8_to_codepoint(const char *p, unsigned *dst)
51
+
{
52
+
unsigned res, n;
53
+
switch (*p & 0xf0)
54
+
{
55
+
case 0xf0 : res = *p & 0x07; n = 3; break;
56
+
case 0xe0 : res = *p & 0x0f; n = 2; break;
57
+
case 0xd0 :
58
+
case 0xc0 : res = *p & 0x1f; n = 1; break;
59
+
default : res = *p; n = 0; break;
60
+
}
61
+
while (n--)
62
+
res = (res << 6) | (*(++p) & 0x3f);
63
+
*dst = res;
64
+
return p + 1;
56
65
}
57
66
58
67
59
-
void ren_init(SDL_Window *win) {
60
-
assert(win);
61
-
window = win;
62
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
63
-
ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } );
68
+
void ren_init(SDL_Window *win)
69
+
{
70
+
assert(win);
71
+
window = win;
72
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
73
+
ren_set_clip_rect((RenRect){ 0, 0, surf->w, surf->h });
64
74
}
65
75
66
76
67
-
void ren_update_rects(RenRect *rects, int count) {
68
-
SDL_UpdateWindowSurfaceRects(window, (SDL_Rect*) rects, count);
69
-
static bool initial_frame = true;
70
-
if (initial_frame) {
71
-
SDL_ShowWindow(window);
72
-
initial_frame = false;
73
-
}
77
+
void ren_update_rects(RenRect *rects, int count)
78
+
{
79
+
SDL_UpdateWindowSurfaceRects(window, (SDL_Rect *)rects, count);
80
+
static bool initial_frame = true;
81
+
if (initial_frame)
82
+
{
83
+
SDL_ShowWindow(window);
84
+
initial_frame = false;
85
+
}
74
86
}
75
87
76
88
77
-
void ren_set_clip_rect(RenRect rect) {
78
-
clip.left = rect.x;
79
-
clip.top = rect.y;
80
-
clip.right = rect.x + rect.width;
81
-
clip.bottom = rect.y + rect.height;
89
+
void ren_set_clip_rect(RenRect rect)
90
+
{
91
+
clip.left = rect.x;
92
+
clip.top = rect.y;
93
+
clip.right = rect.x + rect.width;
94
+
clip.bottom = rect.y + rect.height;
82
95
}
83
96
84
97
85
-
void ren_get_size(int *x, int *y) {
86
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
87
-
*x = surf->w;
88
-
*y = surf->h;
98
+
void ren_get_size(int *x, int *y)
99
+
{
100
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
101
+
*x = surf->w;
102
+
*y = surf->h;
89
103
}
90
104
91
105
92
-
RenImage* ren_new_image(int width, int height) {
93
-
assert(width > 0 && height > 0);
94
-
RenImage *image = malloc(sizeof(RenImage) + width * height * sizeof(RenColor));
95
-
check_alloc(image);
96
-
image->pixels = (void*) (image + 1);
97
-
image->width = width;
98
-
image->height = height;
99
-
return image;
106
+
RenImage* ren_new_image(int width, int height)
107
+
{
108
+
assert(width > 0 && height > 0);
109
+
RenImage *image = malloc(sizeof(RenImage) + width * height * sizeof(RenColor));
110
+
check_alloc(image);
111
+
image->pixels = (void *)(image + 1);
112
+
image->width = width;
113
+
image->height = height;
114
+
return image;
100
115
}
101
116
102
117
103
-
void ren_free_image(RenImage *image) {
104
-
free(image);
118
+
void ren_free_image(RenImage *image)
119
+
{
120
+
free(image);
105
121
}
106
122
107
123
108
-
static GlyphSet* load_glyphset(RenFont *font, int idx) {
109
-
GlyphSet *set = check_alloc(calloc(1, sizeof(GlyphSet)));
124
+
static GlyphSet* load_glyphset(RenFont *font, int idx)
125
+
{
126
+
GlyphSet *set = check_alloc(calloc(1, sizeof(GlyphSet)));
110
127
111
-
/* init image */
112
-
int width = 128;
113
-
int height = 128;
128
+
/* init image */
129
+
int width = 128;
130
+
int height = 128;
114
131
retry:
115
-
set->image = ren_new_image(width, height);
132
+
set->image = ren_new_image(width, height);
116
133
117
-
/* load glyphs */
118
-
float s =
119
-
stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) /
120
-
stbtt_ScaleForPixelHeight(&font->stbfont, 1);
121
-
int res = stbtt_BakeFontBitmap(
122
-
font->data, 0, font->size * s, (void*) set->image->pixels,
123
-
width, height, idx * 256, 256, set->glyphs);
134
+
/* load glyphs */
135
+
float s =
136
+
stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) /
137
+
stbtt_ScaleForPixelHeight(&font->stbfont, 1);
138
+
int res = stbtt_BakeFontBitmap(
139
+
font->data, 0, font->size * s, (void *)set->image->pixels,
140
+
width, height, idx * 256, 256, set->glyphs);
124
141
125
-
/* retry with a larger image buffer if the buffer wasn't large enough */
126
-
if (res < 0) {
127
-
width *= 2;
128
-
height *= 2;
129
-
ren_free_image(set->image);
130
-
goto retry;
131
-
}
142
+
/* retry with a larger image buffer if the buffer wasn't large enough */
143
+
if (res < 0)
144
+
{
145
+
width *= 2;
146
+
height *= 2;
147
+
ren_free_image(set->image);
148
+
goto retry;
149
+
}
132
150
133
-
/* adjust glyph yoffsets and xadvance */
134
-
int ascent, descent, linegap;
135
-
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
136
-
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size);
137
-
int scaled_ascent = ascent * scale + 0.5;
138
-
for (int i = 0; i < 256; i++) {
139
-
set->glyphs[i].yoff += scaled_ascent;
140
-
set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance);
141
-
}
151
+
/* adjust glyph yoffsets and xadvance */
152
+
int ascent, descent, linegap;
153
+
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
154
+
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size);
155
+
int scaled_ascent = ascent * scale + 0.5;
156
+
for (int i = 0; i < 256; i++)
157
+
{
158
+
set->glyphs[i].yoff += scaled_ascent;
159
+
set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance);
160
+
}
142
161
143
-
/* convert 8bit data to 32bit */
144
-
for (int i = width * height - 1; i >= 0; i--) {
145
-
uint8_t n = *((uint8_t*) set->image->pixels + i);
146
-
set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n };
147
-
}
162
+
/* convert 8bit data to 32bit */
163
+
for (int i = width * height - 1; i >= 0; i--)
164
+
{
165
+
uint8_t n = *((uint8_t*) set->image->pixels + i);
166
+
set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n };
167
+
}
148
168
149
-
return set;
169
+
return set;
150
170
}
151
171
152
172
153
-
static GlyphSet* get_glyphset(RenFont *font, int codepoint) {
154
-
int idx = (codepoint >> 8) % MAX_GLYPHSET;
155
-
if (!font->sets[idx]) {
156
-
font->sets[idx] = load_glyphset(font, idx);
157
-
}
158
-
return font->sets[idx];
173
+
static GlyphSet* get_glyphset(RenFont *font, int codepoint)
174
+
{
175
+
int idx = (codepoint >> 8) % MAX_GLYPHSET;
176
+
if (!font->sets[idx])
177
+
font->sets[idx] = load_glyphset(font, idx);
178
+
return font->sets[idx];
159
179
}
160
180
161
181
162
-
RenFont* ren_load_font(const char *filename, float size) {
163
-
RenFont *font = NULL;
164
-
FILE *fp = NULL;
182
+
RenFont* ren_load_font(const char *filename, float size)
183
+
{
184
+
RenFont *font = NULL;
185
+
FILE *fp = NULL;
165
186
166
-
/* init font */
167
-
font = check_alloc(calloc(1, sizeof(RenFont)));
168
-
font->size = size;
187
+
/* init font */
188
+
font = check_alloc(calloc(1, sizeof(RenFont)));
189
+
font->size = size;
169
190
170
-
/* load font into buffer */
171
-
fp = fopen(filename, "rb");
172
-
if (!fp) { return NULL; }
173
-
/* get size */
174
-
fseek(fp, 0, SEEK_END); int buf_size = ftell(fp); fseek(fp, 0, SEEK_SET);
175
-
/* load */
176
-
font->data = check_alloc(malloc(buf_size));
177
-
int _ = fread(font->data, 1, buf_size, fp); (void) _;
178
-
fclose(fp);
179
-
fp = NULL;
191
+
/* load font into buffer */
192
+
fp = fopen(filename, "rb");
193
+
if (!fp)
194
+
return NULL;
195
+
/* get size */
196
+
fseek(fp, 0, SEEK_END);
197
+
int buf_size = ftell(fp);
198
+
fseek(fp, 0, SEEK_SET);
199
+
/* load */
200
+
font->data = check_alloc(malloc(buf_size));
201
+
(void)fread(font->data, 1, buf_size, fp);
202
+
fclose(fp);
203
+
fp = NULL;
180
204
181
-
/* init stbfont */
182
-
int ok = stbtt_InitFont(&font->stbfont, font->data, 0);
183
-
if (!ok) { goto fail; }
205
+
/* init stbfont */
206
+
int ok = stbtt_InitFont(&font->stbfont, font->data, 0);
207
+
if (!ok)
208
+
goto fail;
184
209
185
-
/* get height and scale */
186
-
int ascent, descent, linegap;
187
-
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
188
-
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size);
189
-
font->height = (ascent - descent + linegap) * scale + 0.5;
210
+
/* get height and scale */
211
+
int ascent, descent, linegap;
212
+
stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap);
213
+
float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size);
214
+
font->height = (ascent - descent + linegap) * scale + 0.5;
190
215
191
-
/* make tab and newline glyphs invisible */
192
-
stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs;
193
-
g['\t'].x1 = g['\t'].x0;
194
-
g['\n'].x1 = g['\n'].x0;
216
+
/* make tab and newline glyphs invisible */
217
+
stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs;
218
+
g['\t'].x1 = g['\t'].x0;
219
+
g['\n'].x1 = g['\n'].x0;
195
220
196
-
return font;
221
+
return font;
197
222
198
223
fail:
199
-
if (fp) { fclose(fp); }
200
-
if (font) { free(font->data); }
201
-
free(font);
202
-
return NULL;
224
+
if (fp)
225
+
fclose(fp);
226
+
if (font)
227
+
free(font->data);
228
+
free(font);
229
+
return NULL;
203
230
}
204
231
205
232
206
-
void ren_free_font(RenFont *font) {
207
-
for (int i = 0; i < MAX_GLYPHSET; i++) {
208
-
GlyphSet *set = font->sets[i];
209
-
if (set) {
210
-
ren_free_image(set->image);
211
-
free(set);
212
-
}
213
-
}
214
-
free(font->data);
215
-
free(font);
233
+
void ren_free_font(RenFont *font)
234
+
{
235
+
for (int i = 0; i < MAX_GLYPHSET; i++)
236
+
{
237
+
GlyphSet *set = font->sets[i];
238
+
if (set)
239
+
{
240
+
ren_free_image(set->image);
241
+
free(set);
242
+
}
243
+
}
244
+
free(font->data);
245
+
free(font);
216
246
}
217
247
218
248
219
-
void ren_set_font_tab_width(RenFont *font, int n) {
220
-
GlyphSet *set = get_glyphset(font, '\t');
221
-
set->glyphs['\t'].xadvance = n;
249
+
void ren_set_font_tab_width(RenFont *font, int n)
250
+
{
251
+
GlyphSet *set = get_glyphset(font, '\t');
252
+
set->glyphs['\t'].xadvance = n;
222
253
}
223
254
224
255
225
-
int ren_get_font_tab_width(RenFont *font) {
226
-
GlyphSet *set = get_glyphset(font, '\t');
227
-
return set->glyphs['\t'].xadvance;
256
+
int ren_get_font_tab_width(RenFont *font)
257
+
{
258
+
GlyphSet *set = get_glyphset(font, '\t');
259
+
return set->glyphs['\t'].xadvance;
228
260
}
229
261
230
262
231
-
int ren_get_font_width(RenFont *font, const char *text) {
232
-
int x = 0;
233
-
const char *p = text;
234
-
unsigned codepoint;
235
-
while (*p) {
236
-
p = utf8_to_codepoint(p, &codepoint);
237
-
GlyphSet *set = get_glyphset(font, codepoint);
238
-
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
239
-
x += g->xadvance;
240
-
}
241
-
return x;
263
+
int ren_get_font_width(RenFont *font, const char *text)
264
+
{
265
+
int x = 0;
266
+
const char *p = text;
267
+
unsigned codepoint;
268
+
while (*p)
269
+
{
270
+
p = utf8_to_codepoint(p, &codepoint);
271
+
GlyphSet *set = get_glyphset(font, codepoint);
272
+
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
273
+
x += g->xadvance;
274
+
}
275
+
return x;
242
276
}
243
277
244
278
245
-
int ren_get_font_height(RenFont *font) {
246
-
return font->height;
279
+
int ren_get_font_height(RenFont *font)
280
+
{
281
+
return font->height;
247
282
}
248
283
249
284
250
-
static inline RenColor blend_pixel(RenColor dst, RenColor src) {
251
-
int ia = 0xff - src.a;
252
-
dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8;
253
-
dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8;
254
-
dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8;
255
-
return dst;
285
+
static inline RenColor blend_pixel(RenColor dst, RenColor src)
286
+
{
287
+
int ia = 0xff - src.a;
288
+
dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8;
289
+
dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8;
290
+
dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8;
291
+
return dst;
256
292
}
257
293
258
294
259
-
static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) {
260
-
src.a = (src.a * color.a) >> 8;
261
-
int ia = 0xff - src.a;
262
-
dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8);
263
-
dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8);
264
-
dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8);
265
-
return dst;
295
+
static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color)
296
+
{
297
+
src.a = (src.a * color.a) >> 8;
298
+
int ia = 0xff - src.a;
299
+
dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8);
300
+
dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8);
301
+
dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8);
302
+
return dst;
266
303
}
267
304
268
305
269
-
#define rect_draw_loop(expr) \
270
-
for (int j = y1; j < y2; j++) { \
271
-
for (int i = x1; i < x2; i++) { \
272
-
*d = expr; \
273
-
d++; \
274
-
} \
275
-
d += dr; \
276
-
}
306
+
#define rect_draw_loop(expr) do { \
307
+
for (int j = y1; j < y2; j++) \
308
+
{ \
309
+
for (int i = x1; i < x2; i++) \
310
+
{ \
311
+
*d = expr; \
312
+
d++; \
313
+
} \
314
+
d += dr; \
315
+
} \
316
+
} while (0)
277
317
278
-
void ren_draw_rect(RenRect rect, RenColor color) {
279
-
if (color.a == 0) { return; }
318
+
void ren_draw_rect(RenRect rect, RenColor color)
319
+
{
320
+
if (color.a == 0)
321
+
return;
280
322
281
-
int x1 = rect.x < clip.left ? clip.left : rect.x;
282
-
int y1 = rect.y < clip.top ? clip.top : rect.y;
283
-
int x2 = rect.x + rect.width;
284
-
int y2 = rect.y + rect.height;
285
-
x2 = x2 > clip.right ? clip.right : x2;
286
-
y2 = y2 > clip.bottom ? clip.bottom : y2;
323
+
int x1 = rect.x < clip.left ? clip.left : rect.x;
324
+
int y1 = rect.y < clip.top ? clip.top : rect.y;
325
+
int x2 = rect.x + rect.width;
326
+
int y2 = rect.y + rect.height;
327
+
x2 = x2 > clip.right ? clip.right : x2;
328
+
y2 = y2 > clip.bottom ? clip.bottom : y2;
287
329
288
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
289
-
RenColor *d = (RenColor*) surf->pixels;
290
-
d += x1 + y1 * surf->w;
291
-
int dr = surf->w - (x2 - x1);
330
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
331
+
RenColor *d = (RenColor *)surf->pixels;
332
+
d += x1 + y1 * surf->w;
333
+
int dr = surf->w - (x2 - x1);
292
334
293
-
if (color.a == 0xff) {
294
-
rect_draw_loop(color);
295
-
} else {
296
-
rect_draw_loop(blend_pixel(*d, color));
297
-
}
335
+
if (color.a == 0xff)
336
+
rect_draw_loop(color);
337
+
else
338
+
rect_draw_loop(blend_pixel(*d, color));
298
339
}
299
340
300
341
301
-
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) {
302
-
if (color.a == 0) { return; }
342
+
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color)
343
+
{
344
+
if (color.a == 0)
345
+
return;
303
346
304
-
/* clip */
305
-
int n;
306
-
if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; }
307
-
if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; }
308
-
if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; }
309
-
if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; }
347
+
/* clip */
348
+
int n;
349
+
if ((n = clip.left - x) > 0)
350
+
sub->width -= n; sub->x += n; x += n;
351
+
if ((n = clip.top - y) > 0)
352
+
sub->height -= n; sub->y += n; y += n;
353
+
if ((n = x + sub->width - clip.right ) > 0)
354
+
sub->width -= n;
355
+
if ((n = y + sub->height - clip.bottom) > 0)
356
+
sub->height -= n;
310
357
311
-
if (sub->width <= 0 || sub->height <= 0) {
312
-
return;
313
-
}
358
+
if (sub->width <= 0 || sub->height <= 0)
359
+
return;
314
360
315
-
/* draw */
316
-
SDL_Surface *surf = SDL_GetWindowSurface(window);
317
-
RenColor *s = image->pixels;
318
-
RenColor *d = (RenColor*) surf->pixels;
319
-
s += sub->x + sub->y * image->width;
320
-
d += x + y * surf->w;
321
-
int sr = image->width - sub->width;
322
-
int dr = surf->w - sub->width;
361
+
/* draw */
362
+
SDL_Surface *surf = SDL_GetWindowSurface(window);
363
+
RenColor *s = image->pixels;
364
+
RenColor *d = (RenColor *)surf->pixels;
365
+
s += sub->x + sub->y * image->width;
366
+
d += x + y * surf->w;
367
+
int sr = image->width - sub->width;
368
+
int dr = surf->w - sub->width;
323
369
324
-
for (int j = 0; j < sub->height; j++) {
325
-
for (int i = 0; i < sub->width; i++) {
326
-
*d = blend_pixel2(*d, *s, color);
327
-
d++;
328
-
s++;
329
-
}
330
-
d += dr;
331
-
s += sr;
332
-
}
370
+
for (int j = 0; j < sub->height; j++)
371
+
{
372
+
for (int i = 0; i < sub->width; i++)
373
+
{
374
+
*d = blend_pixel2(*d, *s, color);
375
+
d++;
376
+
s++;
377
+
}
378
+
d += dr;
379
+
s += sr;
380
+
}
333
381
}
334
382
335
383
336
-
int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) {
337
-
RenRect rect;
338
-
const char *p = text;
339
-
unsigned codepoint;
340
-
while (*p) {
341
-
p = utf8_to_codepoint(p, &codepoint);
342
-
GlyphSet *set = get_glyphset(font, codepoint);
343
-
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
344
-
rect.x = g->x0;
345
-
rect.y = g->y0;
346
-
rect.width = g->x1 - g->x0;
347
-
rect.height = g->y1 - g->y0;
348
-
ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color);
349
-
x += g->xadvance;
350
-
}
351
-
return x;
384
+
int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color)
385
+
{
386
+
RenRect rect;
387
+
const char *p = text;
388
+
unsigned codepoint;
389
+
while (*p)
390
+
{
391
+
p = utf8_to_codepoint(p, &codepoint);
392
+
GlyphSet *set = get_glyphset(font, codepoint);
393
+
stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff];
394
+
rect.x = g->x0;
395
+
rect.y = g->y0;
396
+
rect.width = g->x1 - g->x0;
397
+
rect.height = g->y1 - g->y0;
398
+
ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color);
399
+
x += g->xadvance;
400
+
}
401
+
return x;
352
402
}
+9
-2
src/renderer.h
+9
-2
src/renderer.h
···
8
8
typedef struct RenImage RenImage;
9
9
typedef struct RenFont RenFont;
10
10
11
-
typedef struct { uint8_t b, g, r, a; } RenColor;
12
-
typedef struct { int x, y, width, height; } RenRect;
11
+
typedef struct
12
+
{
13
+
uint8_t b, g, r, a;
14
+
} RenColor;
15
+
16
+
typedef struct
17
+
{
18
+
int x, y, width, height;
19
+
} RenRect;
13
20
14
21
15
22
void ren_init(SDL_Window *win);