#include #include #include #include #include #include "window.h" #include "sdl.h" #define UD_WINDOW "libluiml.window" struct window { SDL_Window *win; SDL_Renderer *ren; PangoContext *pc; }; /* window:destroy_window() */ static int destroy_window(lua_State *L) { struct window *w; w = luaL_checkudata(L, 1, UD_WINDOW); SDL_DestroyWindow(w->win); g_object_unref(w->pc); release_sdl(); return 0; } #include "window_wait_event.c" /* window:get_dimensions() -> width, height */ static int get_dimensions(lua_State *L) { struct window *w; int width, height; w = luaL_checkudata(L, 1, UD_WINDOW); SDL_GetWindowSize(w->win, &width, &height); lua_pushnumber(L, width); lua_pushnumber(L, height); return 2; } double clamp(double v, double min, double max) { if (v < min) return min; if (v > max) return max; return v; } /* window:draw_rect(x, y, width, height, r, g, b) */ static int draw_rect(lua_State *L) { struct window *w; SDL_Rect r; struct { Uint8 r, g, b; } colour; w = luaL_checkudata(L, 1, UD_WINDOW); r.x = luaL_checknumber(L, 2); r.y = luaL_checknumber(L, 3); r.w = luaL_checknumber(L, 4); r.h = luaL_checknumber(L, 5); colour.r = round(clamp(luaL_checknumber(L, 6), 0, 1) * 255.0); colour.g = round(clamp(luaL_checknumber(L, 7), 0, 1) * 255.0); colour.b = round(clamp(luaL_checknumber(L, 8), 0, 1) * 255.0); SDL_SetRenderDrawColor(w->ren, colour.r, colour.g, colour.b, SDL_ALPHA_OPAQUE); SDL_RenderFillRect(w->ren, &r); return 0; } static int draw_text(lua_State *L) { PangoRectangle extents; PangoLayout *layout; int width, height; struct window *w; const char *s; SDL_Rect r; size_t l; w = luaL_checkudata(L, 1, UD_WINDOW); r.x = luaL_checknumber(L, 2); r.y = luaL_checknumber(L, 3); r.w = luaL_checknumber(L, 4); r.h = luaL_checknumber(L, 5); s = luaL_checklstring(L, 6, &l); layout = pango_layout_new(w->pc); pango_layout_set_width(layout, r.w * PANGO_SCALE); pango_layout_set_height(layout, r.h * PANGO_SCALE); pango_layout_set_text(layout, s, l); pango_layout_get_extents(layout, NULL, &extents); width = PANGO_PIXELS(extents.width); height = PANGO_PIXELS(extents.height); return 0; } static int show(lua_State *L) { struct window *w; w = luaL_checkudata(L, 1, UD_WINDOW); SDL_RenderPresent(w->ren); return 0; } /* create_window(title) -> window */ int create_window(lua_State *L) { static const struct luaL_Reg window_metatable[] = { {"__gc", destroy_window}, {"wait_event", wait_event}, {"get_dimensions", get_dimensions}, {"draw_rect", draw_rect}, {"draw_text", draw_text}, {"show", show}, {NULL, NULL}, }; PangoFontMap *fontmap; const char *title, *failed; struct window *w; if (luaL_newmetatable(L, UD_WINDOW)) { lua_pushstring(L, "__index"); lua_pushvalue(L, -2); lua_settable(L, -3); luaL_register(L, NULL, window_metatable); lua_pop(L, 1); } title = luaL_checkstring(L, 1); acquire_sdl(); w = lua_newuserdata(L, sizeof *w); w->win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); if (w->win == NULL) { failed = "SDL_CreateWindow"; goto fail_win; } w->ren = SDL_CreateRenderer(w->win, 0, SDL_RENDERER_PRESENTVSYNC); if (w->ren == NULL) { failed = "SDL_CreateRenderer"; goto fail_ren; } fontmap = pango_ft2_font_map_new(); w->pc = pango_font_map_create_context(fontmap); g_object_unref(fontmap); luaL_getmetatable(L, UD_WINDOW); lua_setmetatable(L, -2); return 1; fail_ren: SDL_DestroyWindow(w->win); fail_win: release_sdl(); return sdl_error(L, failed); }