summaryrefslogtreecommitdiff
path: root/lib/hitomezashi.c
blob: 66f74404695dfae58c94815535562a15f0d3278d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "hitomezashi.h"
#include "SDL.h"
#include <assert.h>

SDL_Color HITOMEZASHI_FG_COLOUR = {.r = 0, .g = 0, .b = 0};
SDL_Color HITOMEZASHI_BG_COLOUR = {.r = 255, .g = 255, .b = 255};

enum Hitomezashi_State_Init_Result
hitomezashi_state_init(struct Hitomezashi_State *state, int x_pattern_len,
                       int y_pattern_len, char *x_pattern, char *y_pattern,
                       int gap, int line_thickness) {
  assert(x_pattern_len >= 0);
  assert(y_pattern_len >= 0);
  assert(gap >= 0);
  assert(line_thickness > 0);

  state->y_pattern_len = y_pattern_len;
  state->x_pattern_len = x_pattern_len;
  state->x_pattern = x_pattern;
  state->y_pattern = y_pattern;
  state->gap = gap;
  state->line_thickness = line_thickness;
  state->output_width = x_pattern_len * gap;
  state->output_height = y_pattern_len * gap;

  state->surface = SDL_CreateRGBSurface(0, state->output_width,
                                        state->output_height, 32, 0, 0, 0, 0);
  if (!state->surface) {
    return Hitomezashi_State_Init_Result_Err_Create_Surface;
  }
  return Hitomezashi_State_Init_Result_Success;
}

enum Hitomezashi_Draw_Result hitomezashi_draw(struct Hitomezashi_State *state) {
  if (SDL_LockSurface(state->surface) != 0) {
    return Hitomezashi_Draw_Result_Err_Lock_Surface;
  }

  Uint32 bg_colour =
      SDL_MapRGB(state->surface->format, HITOMEZASHI_BG_COLOUR.r,
                 HITOMEZASHI_BG_COLOUR.g, HITOMEZASHI_BG_COLOUR.b);
  Uint32 fg_colour =
      SDL_MapRGB(state->surface->format, HITOMEZASHI_FG_COLOUR.r,
                 HITOMEZASHI_FG_COLOUR.g, HITOMEZASHI_FG_COLOUR.b);

  SDL_FillRect(state->surface, NULL, bg_colour);

  SDL_Rect rect;
  // Draw y pattern (horizontal) lines
  for (int i = 0; i < state->y_pattern_len; ++i) {
    for (int j = 0; j < state->x_pattern_len; ++j) {
      if (j % 2 == state->y_pattern[i]) {
        rect.x = j * state->gap;
        rect.y = i * state->gap;
        rect.w = state->gap;
        rect.h = state->line_thickness;
        SDL_FillRect(state->surface, &rect, fg_colour);
      }
    }
  }
  // Draw x pattern (vertical) lines
  for (int i = 0; i < state->x_pattern_len; ++i) {
    for (int j = 0; j < state->y_pattern_len; ++j) {
      if (j % 2 == state->x_pattern[i]) {
        rect.x = i * state->gap;
        rect.y = j * state->gap;
        rect.w = state->line_thickness;
        rect.h = state->gap;
        SDL_FillRect(state->surface, &rect, fg_colour);
      }
    }
  }
  // Join up the lines to avoid leaving holes at the intersections
  // To understand how this works, try commenting it out and see the output
  for (int x = state->gap; x < state->output_width; x += state->gap) {
    for (int y = state->gap; y < state->output_height; y += state->gap) {
      rect.x = x;
      rect.y = y;
      rect.w = state->line_thickness;
      rect.h = state->line_thickness;
      SDL_FillRect(state->surface, &rect, fg_colour);
    }
  }

  SDL_UnlockSurface(state->surface);
  return Hitomezashi_Draw_Result_Success;
}