diff options
author | untir_l <87096069+untir-l@users.noreply.github.com> | 2022-02-24 14:57:35 +0000 |
---|---|---|
committer | untir-l <87096069+untir-l@users.noreply.github.com> | 2022-02-25 09:56:49 +0000 |
commit | c23118e8e48d043e4bb9b4d813a498af8d454d73 (patch) | |
tree | 265947d2a848e8a3fb27106be38c8ae95b2fffe0 /web/hitomezashi_web.c | |
parent | 8a7dde79de6edee01571d2eb4a333d8256f4c342 (diff) | |
download | hitomezashi-c23118e8e48d043e4bb9b4d813a498af8d454d73.tar hitomezashi-c23118e8e48d043e4bb9b4d813a498af8d454d73.tar.gz hitomezashi-c23118e8e48d043e4bb9b4d813a498af8d454d73.zip |
Add web app frontend, restructure almost everything
- Add web app frontend code
- Add .html, .js, .wasm to .gitignore
- Restructure Makefile to work with emmake, add build targets for web app,
add .html, .js, .wasm to make clean
- Explain the pattern in the README
- Add explanation of web frontend to README
- Restructure README generally for better clarity
- Remove "make web app version" from todos in README
- Set Doxygen to EXTRACT_ALL so trivial and useless doc comments are not
needed when the naming suffices to be explanatory.
- Move ascii_binary_str_to_ints to library code in new file
hitomezashi_utils.c (and corresponding header) as web app also needs it.
- Fix SDL2 include path so it also works with Emscripten
- Remove some cluttering and unnecessary doc comments
- Improve some doc comments
Diffstat (limited to 'web/hitomezashi_web.c')
-rw-r--r-- | web/hitomezashi_web.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/web/hitomezashi_web.c b/web/hitomezashi_web.c new file mode 100644 index 0000000..4859c20 --- /dev/null +++ b/web/hitomezashi_web.c @@ -0,0 +1,102 @@ +#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" + +int EMSCRIPTEN_KEEPALIVE main(void) { + char *param_str = hitomezashi_web_get_args(); + + if (param_str[0] == 'i') { + return Hitomezashi_Web_Result_Err_Get_Params; + } + + 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); + + 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); + + int gap = strtol(strtok(NULL, "\n"), NULL, 0); + int line_thickness = strtol(strtok(NULL, "\n"), NULL, 0); + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + return Hitomezashi_Web_Result_Err_Sdl_Init; + } + + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + + struct Hitomezashi_State state; + if (hitomezashi_state_init(&state, x_pattern_len, y_pattern_len, x_pattern, + y_pattern, gap, line_thickness) != 0) { + return Hitomezashi_Web_Result_Err_State_Init; + } + + // 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); + + hitomezashi_draw(&state); + + texture = SDL_CreateTextureFromSurface(renderer, state.surface); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + + return Hitomezashi_Web_Result_Success; +} + +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; + } + } + return valid; + } + + 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"); + + 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"; + } + } + + 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; +}) |