@@ 1,444 0,0 @@
-#include <SDL2/SDL.h>
-#include <stdio.h>
-
-#define HOR 32
-#define VER 16
-#define PAD 32
-#define ZOOM 4
-#define color1 0x000000
-#define color2 0x72DEC2
-#define color3 0xFFFFFF
-#define color4 0x444444
-#define color0 0x111111
-
-#define SZ HOR* VER * 16
-
-typedef struct Point {
- int x;
- int y;
-} Point;
-
-typedef struct Brush {
- int color;
- int down;
- int edit;
- int mode;
- int size;
- int erase;
- Point pos;
- Point prev;
-} Brush;
-
-char* modes[] = {
- "line",
- "tone",
- "bold",
- "full",
- "hori",
- "veri",
- "exes"};
-
-unsigned char buffer[SZ];
-int colors[] = {color1, color2, color3, color4, color0};
-int WIDTH = 8 * HOR * ZOOM + PAD * 2;
-int HEIGHT = 8 * VER * ZOOM + PAD * 2;
-int FPS = 30;
-int GUIDES = 1;
-SDL_Window* gWindow = NULL;
-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
-inspt(Point* p, int w, int h)
-{
- return p->x >= 0 && p->y >= 0 && p->x < w && p->y < h;
-}
-
-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)
-{
- int h, v;
- for(h = 0; h < ZOOM; ++h)
- for(v = 0; v < ZOOM; ++v)
- dst[((y * ZOOM) + PAD + v) * WIDTH + ((x * ZOOM) + PAD + h)] = c;
-}
-
-void
-draw(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]);
-}
-
-void
-redraw(uint32_t* dst)
-{
- int b, i, j, id = 0, ch1, ch2, color;
- 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);
- id++;
- }
- SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(uint32_t));
- SDL_RenderClear(gRenderer);
- SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
- SDL_RenderPresent(gRenderer);
-}
-
-void
-write(int tx, int ty, int px, int py, int color)
-{
- int id = tx + ty * HOR;
- int row = py + (id * 16);
- if(row > SZ - 8)
- return;
- if(color == 0) {
- buffer[row] &= ~(1UL << (7 - px));
- buffer[row + 8] &= ~(1UL << (7 - px));
- } else if(color == 2) {
- buffer[row] |= 1UL << (7 - px);
- buffer[row + 8] &= ~(1UL << (7 - px));
- } else if(color == 1) {
- buffer[row] &= ~(1UL << (7 - px));
- buffer[row + 8] |= 1UL << (7 - px);
- } else if(color == 3) {
- buffer[row] |= 1UL << (7 - px);
- buffer[row + 8] |= 1UL << (7 - px);
- }
-}
-
-void
-edit(int x, int y, int color)
-{
- if(x < 0 || y < 0 || x > 8 * HOR || y > 8 * VER)
- return;
- write(x / 8, y / 8, x % 8, y % 8, color);
-}
-
-int
-patt(int x, int y, int mode, int size)
-{
- if(mode == 1)
- return ((x + y) % 4) == 0 && ((y - x) % 4) == 0;
- if(mode == 2)
- return ((x + y) % 2) == 0 && ((y - x) % 2) == 0;
- if(mode == 3)
- return 1;
- if(mode == 4)
- return y % size == 0;
- if(mode == 5)
- return x % size == 0;
- if(mode == 6)
- return (x + y) % size == 0 || (x - y) % size == 0;
- return 0;
-}
-
-void
-fill(Brush* b, int mode, int size, Point p0, 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)
- edit(p.x, p.y, color);
- }
- b->edit = 1;
- redraw(pixels);
-}
-
-void
-line(Point* p0, Point* p1, 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 err = dx + dy, e2;
- for(;;) {
- edit(p0->x, p0->y, color);
- if(p0->x == p1->x && p0->y == p1->y)
- break;
- e2 = 2 * err;
- if(e2 >= dy) {
- err += dy;
- p0->x += sx;
- }
- if(e2 <= dx) {
- err += dx;
- p0->y += sy;
- }
- }
- redraw(pixels);
-}
-
-void
-update(Brush* b)
-{
- char title[512];
- snprintf(title, 512, "%s%dc%d [%d:%dx%d]%c",
- modes[b->mode],
- b->size,
- b->color,
- HOR,
- VER,
- ZOOM,
- b->edit ? '*' : ' ');
- SDL_SetWindowTitle(gWindow, title);
-}
-
-int
-error(char* msg, const char* err)
-{
- printf("Error %s: %s\n", msg, err);
- return 0;
-}
-
-void
-create(void)
-{
- int i;
- for(i = 0; i < SZ; ++i)
- buffer[i] = 0x00;
- redraw(pixels);
-}
-
-void
-save(Brush* b)
-{
- FILE* f = fopen("export.chr", "wb");
- if(!fwrite(buffer, sizeof(buffer), 1, f))
- error("Save", "Invalid output file");
- fclose(f);
- b->edit = 0;
-}
-
-void
-load(char* path)
-{
- FILE* f = fopen(path, "rb");
- if(f == NULL)
- error("Load", "Invalid input file");
- if(!fread(buffer, sizeof(buffer), 1, f))
- error("Load", "Invalid input size");
- fclose(f);
- redraw(pixels);
-}
-
-void
-render(void)
-{
- SDL_Surface* surface = SDL_GetWindowSurface(gWindow);
- GUIDES = 0;
- redraw(pixels);
- SDL_RenderReadPixels(gRenderer,
- NULL,
- SDL_PIXELFORMAT_ARGB8888,
- surface->pixels,
- surface->pitch);
- SDL_SaveBMP(surface, "render.bmp");
- SDL_FreeSurface(surface);
-}
-
-void
-quit(void)
-{
- free(pixels);
- SDL_DestroyTexture(gTexture);
- gTexture = NULL;
- SDL_DestroyRenderer(gRenderer);
- gRenderer = NULL;
- SDL_DestroyWindow(gWindow);
- gWindow = NULL;
- SDL_Quit();
- exit(0);
-}
-
-void
-domouse(SDL_Event* event, Brush* b)
-{
- switch(event->type) {
- case SDL_MOUSEBUTTONUP:
- if(event->button.button == SDL_BUTTON_LEFT) {
- b->down = 0;
- setpt(&b->prev, 0, 0);
- }
- if(event->button.button == SDL_BUTTON_RIGHT)
- b->erase = 0;
- b->edit = 1;
- update(b);
- break;
- case SDL_MOUSEBUTTONDOWN:
- if(event->button.button == SDL_BUTTON_LEFT) {
- b->down = 1;
- setpt(&b->prev,
- (event->motion.x - PAD) / ZOOM,
- (event->motion.y - PAD) / 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,
- (event->motion.y - PAD) / ZOOM);
- if(b->mode == 0)
- line(&b->prev, &b->pos, b->erase ? 0 : b->color);
- else
- fill(b, b->mode, b->size, b->pos, b->erase ? 0 : b->color);
- setpt(&b->prev, b->pos.x, b->pos.y);
- }
- break;
- }
-}
-
-void
-dokey(SDL_Event* event, Brush* b)
-{
- switch(event->key.keysym.sym) {
- case SDLK_ESCAPE:
- quit();
- break;
- case SDLK_e:
- save(b);
- break;
- case SDLK_r:
- render();
- break;
- case SDLK_TAB:
- b->color = b->color > 2 ? 0 : b->color + 1;
- break;
- case SDLK_h:
- GUIDES = !GUIDES;
- redraw(pixels);
- break;
- case SDLK_n:
- create();
- break;
- case SDLK_1:
- b->mode = 0;
- break;
- case SDLK_2:
- b->mode = 1;
- break;
- case SDLK_3:
- b->mode = 2;
- break;
- case SDLK_4:
- b->mode = 3;
- break;
- case SDLK_5:
- b->mode = 4;
- break;
- case SDLK_6:
- b->mode = 5;
- break;
- case SDLK_7:
- b->mode = 6;
- break;
- case SDLK_z:
- if(b->size > 1)
- b->size -= 1;
- break;
- case SDLK_x:
- if(b->size < 30)
- b->size += 1;
- break;
- }
- update(b);
-}
-
-int
-init(void)
-{
- int i, j;
- if(SDL_Init(SDL_INIT_VIDEO) < 0)
- return error("Init", SDL_GetError());
- gWindow = SDL_CreateWindow("nasu",
- SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- WIDTH,
- HEIGHT,
- SDL_WINDOW_SHOWN);
- if(gWindow == NULL)
- return error("Window", SDL_GetError());
- gRenderer = SDL_CreateRenderer(gWindow, -1, 0);
- if(gRenderer == NULL)
- return error("Renderer", SDL_GetError());
- gTexture = SDL_CreateTexture(gRenderer,
- SDL_PIXELFORMAT_ARGB8888,
- SDL_TEXTUREACCESS_STATIC,
- WIDTH,
- HEIGHT);
- if(gTexture == NULL)
- return error("Texture", SDL_GetError());
- pixels = (uint32_t*)malloc(WIDTH * HEIGHT * sizeof(uint32_t));
- if(pixels == NULL)
- return error("Pixels", "Failed to allocate memory");
- for(i = 0; i < HEIGHT; i++)
- for(j = 0; j < WIDTH; j++)
- pixels[i * WIDTH + j] = color1;
- return 1;
-}
-
-int
-main(int argc, char** argv)
-{
- int ticknext = 0;
- Brush brush;
- brush.down = 0;
- brush.color = 1;
- brush.edit = 0;
- brush.size = 10;
- brush.mode = 2;
-
- if(!init())
- return error("Init", "Failure");
-
- if(argc > 1)
- load(argv[1]);
- else
- create();
- update(&brush);
-
- while(1) {
- int tick = SDL_GetTicks();
- SDL_Event event;
- if(event.type == SDL_QUIT)
- quit();
- if(tick < ticknext)
- SDL_Delay(ticknext - tick);
- ticknext = tick + (1000 / FPS);
- while(SDL_PollEvent(&event) != 0) {
- if(event.type == SDL_MOUSEBUTTONUP ||
- event.type == SDL_MOUSEBUTTONDOWN ||
- event.type == SDL_MOUSEMOTION) {
- domouse(&event, &brush);
- } else if(event.type == SDL_KEYDOWN)
- dokey(&event, &brush);
- }
- }
- quit();
- return 0;
-}