From 2aa35e2c108f954949ec001f1e33846379e7cc98 Mon Sep 17 00:00:00 2001 From: untir_l <87096069+untir-l@users.noreply.github.com> Date: Sat, 11 Jun 2022 21:13:23 +0530 Subject: Web: canvas now updates on the fly based on input Also some other minor changes to thw web README.md and the Makefile, and making some stuff const where they weren't throughout the lib/ tree as well. --- web/hitomezashi_web.c | 169 ++++++++++++++++++++++++-------------------------- 1 file changed, 80 insertions(+), 89 deletions(-) (limited to 'web/hitomezashi_web.c') diff --git a/web/hitomezashi_web.c b/web/hitomezashi_web.c index 0a36a2c..413f727 100644 --- a/web/hitomezashi_web.c +++ b/web/hitomezashi_web.c @@ -1,120 +1,111 @@ #include "hitomezashi_web.h" - -#include -#include -#include - #include "SDL2/SDL.h" #include "emscripten.h" #include "hitomezashi.h" #include "hitomezashi_utils.h" +#include +#include +#include -int EMSCRIPTEN_KEEPALIVE main(void) { - char *param_str = hitomezashi_web_get_args(); +SDL_Window *window; - if (param_str[0] == 'i') { - return Hitomezashi_Web_Result_Err_Get_Params; - } +int EMSCRIPTEN_KEEPALIVE main(void) { + if (SDL_Init(SDL_INIT_VIDEO) != 0) + return EXIT_FAILURE; - char *x_pattern_str = strtok(param_str, "\n"); - int x_pattern_len = strlen(x_pattern_str); - // We needn't bother checking whether - // hitomezashi_ascii_binary_str_to_ints() was successful as the strings - // passed to it are validated by hitomezashi_web_get_args() in JS. - char *x_pattern = - hitomezashi_ascii_binary_str_to_ints(x_pattern_str, x_pattern_len); + // Stop SDL from capturing all input and stopping input elements from working + SDL_SetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT, "#canvas"); - char *y_pattern_str = strtok(NULL, "\n"); - int y_pattern_len = strlen(y_pattern_str); - char *y_pattern = - hitomezashi_ascii_binary_str_to_ints(y_pattern_str, y_pattern_len); + if (!(window = SDL_CreateWindow("", 0, 0, 100, 100, SDL_WINDOW_RESIZABLE))) + return EXIT_FAILURE; - int gap = strtol(strtok(NULL, "\n"), NULL, 0); - int line_thickness = strtol(strtok(NULL, "\n"), NULL, 0); + emscripten_set_main_loop(main_loop, -1, true); - Uint32 fg_colour = strtol(strtok(NULL, "\n"), NULL, 0); - Uint32 bg_colour = strtol(strtok(NULL, "\n"), NULL, 0); + return EXIT_SUCCESS; +} - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - return Hitomezashi_Web_Result_Err_Sdl_Init; - } +void EMSCRIPTEN_KEEPALIVE main_loop(void) { + const char *x_pattern_raw = hitomezashi_web_get_x_pattern(); + const char *y_pattern_raw = hitomezashi_web_get_y_pattern(); + const int x_pattern_len = strlen(x_pattern_raw); + const int y_pattern_len = strlen(y_pattern_raw); + const char *x_pattern = + hitomezashi_ascii_binary_str_to_ints(x_pattern_raw, x_pattern_len); + const char *y_pattern = + hitomezashi_ascii_binary_str_to_ints(y_pattern_raw, y_pattern_len); - SDL_Window *window; - SDL_Renderer *renderer; - SDL_Texture *texture; + const int gap = hitomezashi_web_get_gap(); + const int line_thickness = hitomezashi_web_get_line_thickness(); - struct Hitomezashi_State state; - if (hitomezashi_state_init(&state, x_pattern_len, y_pattern_len, x_pattern, - y_pattern, gap, line_thickness, fg_colour, - bg_colour) != 0) { - return Hitomezashi_Web_Result_Err_State_Init; - } + const Uint32 fg_colour = hitomezashi_web_get_fg_colour(); + const Uint32 bg_colour = hitomezashi_web_get_bg_colour(); - // Stop SDL from capturing all input and stopping input elements from working - SDL_SetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT, "#canvas"); - SDL_CreateWindowAndRenderer(state.output_width, state.output_height, 0, - &window, &renderer); + // If any of these are 0, input was invalid + if (!(x_pattern_len && y_pattern_len && gap && line_thickness)) + return; + struct Hitomezashi_State state; + hitomezashi_state_init(&state, x_pattern_len, y_pattern_len, x_pattern, + y_pattern, gap, line_thickness, fg_colour, bg_colour); + SDL_SetWindowSize(window, state.output_width, state.output_height); hitomezashi_draw(&state); - texture = SDL_CreateTextureFromSurface(renderer, state.surface); - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, NULL, NULL); - SDL_RenderPresent(renderer); - - // Since this is a short-lived application which is only run on page load, - // we do not need to delay the exit of main by freeing memory - it will be - // reclaimed by the browser automatically. + SDL_BlitSurface(state.surface, NULL, SDL_GetWindowSurface(window), NULL); + SDL_UpdateWindowSurface(window); - return Hitomezashi_Web_Result_Success; + free((char *)x_pattern_raw); + free((char *)y_pattern_raw); + free((char *)x_pattern); + free((char *)y_pattern); + SDL_FreeSurface(state.surface); } -EM_JS(char *, hitomezashi_web_get_args, (void), { - function validate_pattern(pattern) { - let valid = true; - for (let c of pattern) { - if (c != "0" && c != "1") { - valid = false; - break; - } +EM_JS(char *, hitomezashi_web_get_x_pattern, (void), { + let result_js = document.querySelector("input[name=\"x_pattern\"]").value; + for (let c of result_js) { + if (c != "0" && c != "1") { + result_js = ""; + break; } - return valid; } + const result_length_bytes = lengthBytesUTF8(result_js) + 1; + let result_wasm_heap = _malloc(result_length_bytes); + stringToUTF8(result_js, result_wasm_heap, result_length_bytes); + return result_wasm_heap; +}) - let result_js = ""; - - let search_params = new URLSearchParams(window.location.search); - - const x_pattern = search_params.get("x_pattern"); - const y_pattern = search_params.get("y_pattern"); - const gap = search_params.get("gap"); - const line_thickness = search_params.get("line_thickness"); - let fg_colour = search_params.get("fg_colour"); - let bg_colour = search_params.get("bg_colour"); - if (!fg_colour) { - fg_colour = "#000000"; - } - if (!bg_colour) { - bg_colour = "#FFFFFF"; - } - fg_colour = "0x" + fg_colour.slice(1); - bg_colour = "0x" + bg_colour.slice(1); - - if (!(x_pattern && y_pattern && gap && line_thickness)) { - result_js = "i"; - } else { - const patterns_are_valid = - validate_pattern(x_pattern) && validate_pattern(y_pattern); - if (!patterns_are_valid) { - result_js = "i"; - } else { - result_js = x_pattern + "\n" + y_pattern + "\n" + gap + "\n" + - line_thickness + "\n" + fg_colour + "\n" + bg_colour + "\n"; +EM_JS(char *, hitomezashi_web_get_y_pattern, (void), { + let result_js = document.querySelector("input[name=\"y_pattern\"]").value; + for (let c of result_js) { + if (c != "0" && c != "1") { + result_js = ""; + break; } } - const result_length_bytes = lengthBytesUTF8(result_js) + 1; let result_wasm_heap = _malloc(result_length_bytes); stringToUTF8(result_js, result_wasm_heap, result_length_bytes); return result_wasm_heap; }) + +EM_JS(unsigned int, hitomezashi_web_get_gap, (void), { + const result = +document.querySelector("input[name=\"gap\"").value; + return (result > 0 ? result : 0); +}) + +EM_JS(unsigned int, hitomezashi_web_get_line_thickness, (void), { + const result = +document.querySelector("input[name=\"line_thickness\"").value; + return (result > 0 ? result : 0); +}) + +EM_JS(Uint32, hitomezashi_web_get_fg_colour, (void), { + const result = parseInt( + document.querySelector("input[name=\"fg_colour\"]").value.slice(1), 16); + return (result ? result : 0); +}) + +EM_JS(Uint32, hitomezashi_web_get_bg_colour, (void), { + const result = parseInt( + document.querySelector("input[name=\"bg_colour\"]").value.slice(1), 16); + return (result ? result : 0); +}) -- cgit v1.2.3-57-g22cb