-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprocess_intent.c
115 lines (102 loc) · 2.56 KB
/
process_intent.c
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdlib.h>
#include <string.h>
#include "process_intent.h"
#include "draw.h"
#define SATURATION 0.7
#define VALUE 0.7
typedef enum {
color,
pointcount,
points
} state_t;
typedef struct {
unsigned char nbits;
unsigned short bits;
} bitbuffer_t;
typedef struct {
state_t state;
unsigned char npoints;
unsigned char current_point;
bitbuffer_t bitbuffer;
} context_t;
hsv_t get_color(bitbuffer_t* bitbuffer) {
hsv_t hsv;
hsv.s = SATURATION;
hsv.v = VALUE;
hsv.h = (float)((unsigned char)(bitbuffer->bits & 0xff)) / 256 * 360;
bitbuffer->bits >>= 8;
bitbuffer->nbits -=8;
return hsv;
}
unsigned char numpoints(bitbuffer_t* bitbuffer) {
unsigned char n = (bitbuffer->bits & 0xf) + 1;
bitbuffer->nbits -= 4;
bitbuffer->bits >>= 4;
return n;
}
point_t get_point(context_t* ctx) {
point_t p;
p.x = (unsigned char)(ctx->bitbuffer.bits & 0xf) * (float)(IMAGE_WIDTH-10) / 16;
ctx->bitbuffer.bits >>= 4;
ctx->bitbuffer.nbits -= 4;
p.y = (unsigned char)(ctx->bitbuffer.bits & 0xf) * (float)(IMAGE_HEIGHT-10) / 16;
ctx->bitbuffer.bits >>= 4;
ctx->bitbuffer.nbits -= 4;
return p;
}
void parse_step(context_t* ctx, shapedef_t* shape) {
switch(ctx->state) {
case color:
shape->color = get_color(&ctx->bitbuffer);
ctx->state = pointcount;
break;
case pointcount:
shape->numpoints = numpoints(&ctx->bitbuffer);
shape->points = malloc(shape->numpoints * sizeof(point_t));
ctx->npoints = shape->numpoints;
ctx->current_point = 0;
ctx->state = points;
break;
case points:
shape->points[ctx->current_point] = get_point(ctx);
ctx->current_point++;
break;
}
}
sigil_t process_intent(char const * intent) {
int len = strlen(intent);
int idx;
context_t ctx;
sigil_t sigil;
ctx.bitbuffer.bits = *intent;
ctx.bitbuffer.nbits = 8;
// just allocate for worst-case scenario of having all single points
sigil.shapes = malloc((len/4+1) * sizeof(shapedef_t));
sigil.nshapes = 0;
for(idx=1;; idx++) {
int i = idx % len;
if(ctx.bitbuffer.nbits <= 8) {
ctx.bitbuffer.bits |= (intent[i] << ctx.bitbuffer.bits);
ctx.bitbuffer.nbits += 8;
}
parse_step(&ctx, sigil.shapes+sigil.nshapes);
if(ctx.state == points && ctx.current_point == ctx.npoints) {
sigil.nshapes++;
ctx.state = color;
// if we wrapped around we have all shapes we want
if(idx > i) break;
}
}
return sigil;
}
void free_sigil(sigil_t* sigil) {
int i;
for(i=0; i<sigil->nshapes; i++) {
free(sigil->shapes[i].points);
sigil->shapes[i].numpoints = 0;
sigil->shapes[i].points = NULL;
}
free(sigil->shapes);
sigil->nshapes = 0;
sigil->shapes = NULL;
}