summaryrefslogtreecommitdiff
path: root/web/hitomezashi_web.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/hitomezashi_web.c')
-rw-r--r--web/hitomezashi_web.c102
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;
+})