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.c169
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);
+})