|
|
|
|
@ -3,7 +3,7 @@
|
|
|
|
|
|
|
|
|
|
#define HOR 32 |
|
|
|
|
#define VER 16 |
|
|
|
|
#define PAD 16 |
|
|
|
|
#define PAD 8 |
|
|
|
|
#define ZOOM 4 |
|
|
|
|
#define color1 0x000000 |
|
|
|
|
#define color2 0x72DEC2 |
|
|
|
|
@ -13,20 +13,15 @@
|
|
|
|
|
|
|
|
|
|
#define SZ (HOR * VER * 16) |
|
|
|
|
|
|
|
|
|
typedef struct Point { |
|
|
|
|
int x; |
|
|
|
|
int y; |
|
|
|
|
} Point; |
|
|
|
|
|
|
|
|
|
typedef struct Brush { |
|
|
|
|
int x, y; |
|
|
|
|
int px, py; |
|
|
|
|
int mode; |
|
|
|
|
int size; |
|
|
|
|
int color; |
|
|
|
|
int down; |
|
|
|
|
int edit; |
|
|
|
|
int mode; |
|
|
|
|
int size; |
|
|
|
|
int erase; |
|
|
|
|
Point pos; |
|
|
|
|
Point prev; |
|
|
|
|
} Brush; |
|
|
|
|
|
|
|
|
|
char* modes[] = { |
|
|
|
|
@ -39,7 +34,7 @@ char* modes[] = {
|
|
|
|
|
"exes", |
|
|
|
|
"fixe"}; |
|
|
|
|
|
|
|
|
|
unsigned char buffer[SZ]; |
|
|
|
|
unsigned char chrbuf[SZ]; |
|
|
|
|
int colors[] = {color1, color2, color3, color4, color0}; |
|
|
|
|
int WIDTH = 8 * HOR + PAD * 2; |
|
|
|
|
int HEIGHT = 8 * VER + PAD * 2; |
|
|
|
|
@ -50,47 +45,33 @@ SDL_Renderer* gRenderer = NULL;
|
|
|
|
|
SDL_Texture* gTexture = NULL; |
|
|
|
|
uint32_t* pixels; |
|
|
|
|
|
|
|
|
|
Point* |
|
|
|
|
setpt(Point* p, int x, int y) |
|
|
|
|
{ |
|
|
|
|
p->x = x; |
|
|
|
|
p->y = y; |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
dispt(Point* a, Point* b) |
|
|
|
|
{ |
|
|
|
|
return (b->x - a->x) * (b->x - a->x) + (b->y - a->y) * (b->y - a->y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
pixel(uint32_t* dst, int x, int y, int c) |
|
|
|
|
distance(int ax, int ay, int bx, int by) |
|
|
|
|
{ |
|
|
|
|
dst[(y + PAD) * WIDTH + (x + PAD)] = c; |
|
|
|
|
return (bx - ax) * (bx - ax) + (by - ay) * (by - ay); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
draw(uint32_t* dst, int id, int color) |
|
|
|
|
edit(uint32_t* dst, int id, int color) |
|
|
|
|
{ |
|
|
|
|
int ti = id / 64; |
|
|
|
|
int odd = (ti + (ti / HOR + 2)) % 2 == 0; |
|
|
|
|
int px = (ti / (HOR * VER)) * (8 * HOR) + (ti % HOR) * 8 + (id % 8); |
|
|
|
|
int py = ((ti / HOR) * 8) + ((id % 64) / 8); |
|
|
|
|
pixel(dst, px, py, colors[GUIDES && odd && color == 0 ? 4 : color]); |
|
|
|
|
dst[(py + PAD) * WIDTH + (px + PAD)] = colors[GUIDES && odd && color == 0 ? 4 : color]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
redraw(uint32_t* dst) |
|
|
|
|
{ |
|
|
|
|
int b, i, j, id = 0, ch1, ch2, color; |
|
|
|
|
int b, i, j, id = 0; |
|
|
|
|
for(b = 0; b < SZ; b += 16) |
|
|
|
|
for(i = 0; i < 8; i++) |
|
|
|
|
for(j = 7; j >= 0; j--) { |
|
|
|
|
ch1 = buffer[b + i]; |
|
|
|
|
ch2 = buffer[b + i + 8]; |
|
|
|
|
color = ((ch1 >> j) & 0x1) + (((ch2 >> j) & 0x1) << 1); |
|
|
|
|
draw(dst, id, color); |
|
|
|
|
int ch1 = chrbuf[b + i]; |
|
|
|
|
int ch2 = chrbuf[b + i + 8]; |
|
|
|
|
int color = ((ch1 >> j) & 0x1) + (((ch2 >> j) & 0x1) << 1); |
|
|
|
|
edit(dst, id, color); |
|
|
|
|
id++; |
|
|
|
|
} |
|
|
|
|
SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(uint32_t)); |
|
|
|
|
@ -99,40 +80,44 @@ redraw(uint32_t* dst)
|
|
|
|
|
SDL_RenderPresent(gRenderer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
row(int x, int y) |
|
|
|
|
{ |
|
|
|
|
return (y % 8) + ((x / 8 + y / 8 * HOR) * 16); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
get(int x, int y) |
|
|
|
|
{ |
|
|
|
|
int ch1, ch2; |
|
|
|
|
int id = (x / 8) + (y / 8) * HOR; |
|
|
|
|
int row = (y % 8) + (id * 16); |
|
|
|
|
int r = row(x, y); |
|
|
|
|
int px = x % 8; |
|
|
|
|
if(row < 0 || row > SZ - 8) |
|
|
|
|
if(r < 0 || r > SZ - 8) |
|
|
|
|
return 0; |
|
|
|
|
ch1 = (buffer[row] >> (7 - px)) & 1; |
|
|
|
|
ch2 = (buffer[row + 8] >> (7 - px)) & 1; |
|
|
|
|
ch1 = (chrbuf[r] >> (7 - px)) & 1; |
|
|
|
|
ch2 = (chrbuf[r + 8] >> (7 - px)) & 1; |
|
|
|
|
return ch1 && !ch2 ? 1 : !ch1 && ch2 ? 2 : ch1 && ch2 ? 3 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
put(int x, int y, int color) |
|
|
|
|
{ |
|
|
|
|
int id = (x / 8) + (y / 8) * HOR; |
|
|
|
|
int row = (y % 8) + (id * 16); |
|
|
|
|
int r = row(x, y); |
|
|
|
|
int px = x % 8; |
|
|
|
|
if(x < 0 || y < 0 || x > 8 * HOR || y > 8 * VER || row > SZ - 8) |
|
|
|
|
if(x < 0 || y < 0 || x > 8 * HOR || y > 8 * VER || r > SZ - 8) |
|
|
|
|
return; |
|
|
|
|
if(color == 0) { |
|
|
|
|
buffer[row] &= ~(1UL << (7 - px)); |
|
|
|
|
buffer[row + 8] &= ~(1UL << (7 - px)); |
|
|
|
|
chrbuf[r] &= ~(1UL << (7 - px)); |
|
|
|
|
chrbuf[r + 8] &= ~(1UL << (7 - px)); |
|
|
|
|
} else if(color == 2) { |
|
|
|
|
buffer[row] |= 1UL << (7 - px); |
|
|
|
|
buffer[row + 8] &= ~(1UL << (7 - px)); |
|
|
|
|
chrbuf[r] |= 1UL << (7 - px); |
|
|
|
|
chrbuf[r + 8] &= ~(1UL << (7 - px)); |
|
|
|
|
} else if(color == 1) { |
|
|
|
|
buffer[row] &= ~(1UL << (7 - px)); |
|
|
|
|
buffer[row + 8] |= 1UL << (7 - px); |
|
|
|
|
chrbuf[r] &= ~(1UL << (7 - px)); |
|
|
|
|
chrbuf[r + 8] |= 1UL << (7 - px); |
|
|
|
|
} else if(color == 3) { |
|
|
|
|
buffer[row] |= 1UL << (7 - px); |
|
|
|
|
buffer[row + 8] |= 1UL << (7 - px); |
|
|
|
|
chrbuf[r] |= 1UL << (7 - px); |
|
|
|
|
chrbuf[r + 8] |= 1UL << (7 - px); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -174,56 +159,41 @@ patt(int x, int y, int mode, int size)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
fill(int mode, int size, Point p0, int color) |
|
|
|
|
fill(int x, int y, int mode, int size, int color) |
|
|
|
|
{ |
|
|
|
|
int x, y; |
|
|
|
|
Point p; |
|
|
|
|
for(x = -size / 2; x < size; ++x) |
|
|
|
|
for(y = -size / 2; y < size; ++y) { |
|
|
|
|
setpt(&p, p0.x + x, p0.y + y); |
|
|
|
|
if(patt(p.x, p.y, mode, size) && dispt(&p0, &p) < size) |
|
|
|
|
put(p.x, p.y, color); |
|
|
|
|
} |
|
|
|
|
int ox, oy; |
|
|
|
|
for(ox = x - (size / 2); ox < x + size; ++ox) |
|
|
|
|
for(oy = y - (size / 2); oy < y + size; ++oy) |
|
|
|
|
if(mode == 7 && jagg(ox, oy)) |
|
|
|
|
put(ox, oy, 0); |
|
|
|
|
else if(patt(ox, oy, mode, size) && distance(x, y, ox, oy) < size) |
|
|
|
|
put(ox, oy, color); |
|
|
|
|
redraw(pixels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
line(Point* p0, Point* p1, int color) |
|
|
|
|
line(int ax, int ay, int bx, int by, int color) |
|
|
|
|
{ |
|
|
|
|
int dx = abs(p1->x - p0->x), sx = p0->x < p1->x ? 1 : -1; |
|
|
|
|
int dy = -abs(p1->y - p0->y), sy = p0->y < p1->y ? 1 : -1; |
|
|
|
|
int dx = abs(bx - ax), sx = ax < bx ? 1 : -1; |
|
|
|
|
int dy = -abs(by - ay), sy = ay < by ? 1 : -1; |
|
|
|
|
int err = dx + dy, e2; |
|
|
|
|
for(;;) { |
|
|
|
|
put(p0->x, p0->y, color); |
|
|
|
|
if(p0->x == p1->x && p0->y == p1->y) |
|
|
|
|
put(ax, ay, color); |
|
|
|
|
if(ax == bx && ay == by) |
|
|
|
|
break; |
|
|
|
|
e2 = 2 * err; |
|
|
|
|
if(e2 >= dy) { |
|
|
|
|
err += dy; |
|
|
|
|
p0->x += sx; |
|
|
|
|
ax += sx; |
|
|
|
|
} |
|
|
|
|
if(e2 <= dx) { |
|
|
|
|
err += dx; |
|
|
|
|
p0->y += sy; |
|
|
|
|
ay += sy; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
redraw(pixels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
fixe(int size, Point p0) |
|
|
|
|
{ |
|
|
|
|
int x, y; |
|
|
|
|
Point p; |
|
|
|
|
for(x = -size / 2; x < size; ++x) |
|
|
|
|
for(y = -size / 2; y < size; ++y) { |
|
|
|
|
setpt(&p, p0.x + x, p0.y + y); |
|
|
|
|
if(jagg(p.x, p.y)) |
|
|
|
|
put(p.x, p.y, 0); |
|
|
|
|
} |
|
|
|
|
redraw(pixels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
update(Brush* b) |
|
|
|
|
{ |
|
|
|
|
@ -251,7 +221,7 @@ create(void)
|
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
for(i = 0; i < SZ; ++i) |
|
|
|
|
buffer[i] = 0x00; |
|
|
|
|
chrbuf[i] = 0x00; |
|
|
|
|
redraw(pixels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -259,7 +229,7 @@ void
|
|
|
|
|
save(Brush* b) |
|
|
|
|
{ |
|
|
|
|
FILE* f = fopen("export.chr", "wb"); |
|
|
|
|
if(!fwrite(buffer, sizeof(buffer), 1, f)) |
|
|
|
|
if(!fwrite(chrbuf, sizeof(chrbuf), 1, f)) |
|
|
|
|
error("Save", "Invalid output file"); |
|
|
|
|
fclose(f); |
|
|
|
|
b->edit = 0; |
|
|
|
|
@ -271,7 +241,7 @@ load(char* path)
|
|
|
|
|
FILE* f = fopen(path, "rb"); |
|
|
|
|
if(f == NULL) |
|
|
|
|
error("Load", "Invalid input file"); |
|
|
|
|
if(!fread(buffer, sizeof(buffer), 1, f)) |
|
|
|
|
if(!fread(chrbuf, sizeof(chrbuf), 1, f)) |
|
|
|
|
error("Load", "Invalid input size"); |
|
|
|
|
fclose(f); |
|
|
|
|
redraw(pixels); |
|
|
|
|
@ -313,7 +283,8 @@ domouse(SDL_Event* event, Brush* b)
|
|
|
|
|
case SDL_MOUSEBUTTONUP: |
|
|
|
|
if(event->button.button == SDL_BUTTON_LEFT) { |
|
|
|
|
b->down = 0; |
|
|
|
|
setpt(&b->prev, 0, 0); |
|
|
|
|
b->px = 0; |
|
|
|
|
b->py = 0; |
|
|
|
|
} |
|
|
|
|
if(event->button.button == SDL_BUTTON_RIGHT) |
|
|
|
|
b->erase = 0; |
|
|
|
|
@ -323,24 +294,21 @@ domouse(SDL_Event* event, Brush* b)
|
|
|
|
|
case SDL_MOUSEBUTTONDOWN: |
|
|
|
|
if(event->button.button == SDL_BUTTON_LEFT) { |
|
|
|
|
b->down = 1; |
|
|
|
|
setpt(&b->prev, |
|
|
|
|
(event->motion.x - (PAD * ZOOM)) / ZOOM, |
|
|
|
|
(event->motion.y - (PAD * ZOOM)) / ZOOM); |
|
|
|
|
b->px = (event->motion.x - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
b->py = (event->motion.y - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
} |
|
|
|
|
if(event->button.button == SDL_BUTTON_RIGHT) |
|
|
|
|
b->erase = 1; |
|
|
|
|
case SDL_MOUSEMOTION: |
|
|
|
|
if(b->down) { |
|
|
|
|
setpt(&b->pos, |
|
|
|
|
(event->motion.x - (PAD * ZOOM)) / ZOOM, |
|
|
|
|
(event->motion.y - (PAD * ZOOM)) / ZOOM); |
|
|
|
|
b->x = (event->motion.x - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
b->y = (event->motion.y - (PAD * ZOOM)) / ZOOM; |
|
|
|
|
if(b->mode == 0) |
|
|
|
|
line(&b->prev, &b->pos, b->erase ? 0 : b->color); |
|
|
|
|
else if(b->mode == 7) |
|
|
|
|
fixe(b->size, b->pos); |
|
|
|
|
line(b->px, b->py, b->x, b->y, b->erase ? 0 : b->color); |
|
|
|
|
else |
|
|
|
|
fill(b->mode, b->size, b->pos, b->erase ? 0 : b->color); |
|
|
|
|
setpt(&b->prev, b->pos.x, b->pos.y); |
|
|
|
|
fill(b->x, b->y, b->mode, b->size, b->erase ? 0 : b->color); |
|
|
|
|
b->px = b->x; |
|
|
|
|
b->py = b->y; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|