diff options
Diffstat (limited to 'web/hitomezashi_web.c')
-rw-r--r-- | web/hitomezashi_web.c | 169 |
1 files changed, 80 insertions, 89 deletions
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 <stdbool.h> -#include <stdio.h> -#include <string.h> - #include "SDL2/SDL.h" #include "emscripten.h" #include "hitomezashi.h" #include "hitomezashi_utils.h" +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> -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); +}) |