aboutsummaryrefslogtreecommitdiff
path: root/src/canvas.c
diff options
context:
space:
mode:
authorKrow Savcik <krow@savcik.xyz>2024-07-20 00:22:00 +0300
committerKrow Savcik <krow@savcik.xyz>2024-07-20 00:22:00 +0300
commitb486d1f47e0bbc1a0e3414df1f4f9193a3997300 (patch)
treef754d3939cffdcf68ab6a3e8bc87cc933368cee5 /src/canvas.c
parent689d8faa8638c1d14f79c7960afe3139bd042f96 (diff)
feature: added frames
Diffstat (limited to 'src/canvas.c')
-rw-r--r--src/canvas.c244
1 files changed, 167 insertions, 77 deletions
diff --git a/src/canvas.c b/src/canvas.c
index e24a404..9c860ae 100644
--- a/src/canvas.c
+++ b/src/canvas.c
@@ -17,11 +17,11 @@ uint8 is_drawing;
#define COORD(x,y) ((x) + (y) * c->w)
#define HNEXT(i) (i == HISTLENGTH-1 ? 0 : i+1)
#define HPREV(i) (i == 0 ? HISTLENGTH-1 : i-1)
+#define PIXEL(x, y) c->cells[c->layer_arr_cnt * c->cur_frame + c->cur_layer][COORD(x,y)]
typedef struct Layer Layer;
-static Layer *layer_create(uint, uint, uint);
-static void layer_destroy(Layer *);
+static uint8 canvas_add_cells(Canvas *, uint);
static uint canvas_fill_bfs(Canvas *, int, int, uint, uint);
static uint canvas_blend_color(uint, uint);
static void canvas_point_redraw(Canvas *, long int, long int);
@@ -47,6 +47,7 @@ canvas_coord_get(Canvas *c, long int tx, long int ty, long int *x, long int *y)
Canvas *
canvas_init(uint w, uint h, void *ren)
{
+ /* TODO: Add propper deffer */
Canvas *c;
int i, j;
SDL_Rect dest;
@@ -61,26 +62,37 @@ canvas_init(uint w, uint h, void *ren)
c->cur_frame = 0;
c->zoom = 1;
c->proj_path = NULL;
- c->layer_arr_cnt = 1;
+ c->layer_arr_cnt = 0;
c->layer_arr_sz = 1;
/* TEMP: TODO */
- c->frame_arr_cnt = 4;
- c->frame_arr_sz = 4;
+ c->frame_arr_cnt = 0;
+ c->frame_arr_sz = 1;
+ c->cell_arr_sz = 1;
c->x = c->y = 0;
c->hist_i = c->hist_s = c->hist_isend = 0;
c->hist_e = HNEXT(c->hist_s);
c->layers = malloc(sizeof(*(c->layers)));
+ c->frames = malloc(sizeof(*(c->frames)));
c->temp_pix = malloc(w * h * sizeof(* c->temp_pix));
+ c->cells = malloc(sizeof(* c->cells));
for (i = 0; i < HISTLENGTH; ++i)
c->history[i].type = ACT_NULL;
c->pres_pix = malloc(w * h * sizeof(* c->pres_pix));
-
- c->layers[0] = layer_create(w, h, 1);
+ if (c->cells != NULL)
+ c->cells[0] = NULL;
+ else
+ return NULL;
for (i = 0; i < c->w * c->h; ++i)
c->pres_pix[i] = 0;
- if (c->layers[0] == NULL) {
+ if (canvas_add_frame(c, 0)) {
+ fprintf(stderr, "Error while creating frame");
+ free(c);
+ return NULL;
+ }
+
+ if (canvas_add_layer(c, 0)) {
fprintf(stderr, "Error while creating layer");
free(c);
return NULL;
@@ -172,7 +184,7 @@ canvas_open1(FILE *fp, void *ren)
Canvas *c;
fscanf(fp, "%u;%u;", &w, &h);
c = canvas_init(w, h, ren);
- fread(c->layers[0]->pix, sizeof *(c->layers[0]->pix), c->w*c->h, fp);
+ fread(c->cells[0], sizeof *(c->cells[0]), c->w*c->h, fp);
return c;
}
@@ -188,13 +200,13 @@ canvas_open2(FILE *fp, void *ren)
for (i = 1; i < lc; i++)
canvas_add_layer(c, lc);
for (i = 0; i < lc; i++) {
- fread(c->layers[i]->name, sizeof *(c->layers[i]->name), LAYERNAMELEN, fp);
- c->layers[i]->name[LAYERNAMELEN] = '\0';
+ fread(c->layers[i].name, sizeof *(c->layers[i].name), LAYERNAMELEN, fp);
+ c->layers[i].name[LAYERNAMELEN] = '\0';
fscanf(fp, ";");
}
for (i = 0; i < lc; i++)
- fread(c->layers[i]->pix, sizeof *(c->layers[i]->pix), c->w*c->h, fp);
+ fread(c->cells[i], sizeof *(c->cells[i]), c->w*c->h, fp);
return c;
}
@@ -224,7 +236,7 @@ canvas_import_png(const char *path, void *ren)
rect.w = sur->w;
rect.h = sur->h;
SDL_RenderReadPixels(ren, &rect, SDL_PIXELFORMAT_RGBA8888,
- c->layers[0]->pix, (sizeof *(c->layers[0]->pix)) * c->w);
+ c->cells[0], (sizeof *(c->cells[0])) * c->w);
SDL_SetRenderTarget(ren, NULL);
SDL_DestroyTexture(tex);
@@ -242,11 +254,15 @@ canvas_destroy(Canvas *c)
SDL_DestroyTexture(c->pres);
SDL_DestroyTexture(c->back);
SDL_DestroyTexture(c->half_pres);
- for (i = 0; i < c->layer_arr_cnt; ++i)
- layer_destroy(c->layers[i]);
+ if (c->cells != NULL) {
+ for (i = 0; i < c->layer_arr_cnt * c->frame_arr_cnt; i++)
+ free(c->cells[i]);
+ free(c->cells);
+ }
for (i = 0; i < HISTLENGTH; ++i)
action_remove(&c->history[i]);
free(c->layers);
+ free(c->frames);
free(c->temp_pix);
free(c->pres_pix);
free(c->proj_path);
@@ -307,7 +323,7 @@ canvas_point_draw(Canvas *c, long int x, long int y)
unsigned int oldcol, newcol;
int i;
/* TODO: better */
- oldcol = c->layers[c->cur_layer]->pix[COORD(x,y)];
+ oldcol = PIXEL(x, y);
newcol = COLTOINTA(
((Palette *)def_palette)->clist[c->cur_col].r,
((Palette *)def_palette)->clist[c->cur_col].g,
@@ -324,16 +340,16 @@ canvas_point_draw(Canvas *c, long int x, long int y)
if (tool_array[tool_cur] == TOOL_TYPE_ERASER) {
c->temp_pix[c->temp_cnt].x = x;
c->temp_pix[c->temp_cnt].y = y;
- c->temp_pix[c->temp_cnt++].c = c->layers[c->cur_layer]->pix[COORD(x,y)];
- c->layers[c->cur_layer]->pix[COORD(x,y)] = 0;
+ c->temp_pix[c->temp_cnt++].c = PIXEL(x, y);
+ PIXEL(x, y) = 0;
canvas_point_redraw(c, x, y);
SDL_SetRenderDrawColor(ren, INTTOCOLA(c->pres_pix[COORD(x,y)]));
SDL_RenderDrawPoint(ren, x, y);
} else if (tool_array[tool_cur] == TOOL_TYPE_PENCIL) {
c->temp_pix[c->temp_cnt].x = x;
c->temp_pix[c->temp_cnt].y = y;
- c->temp_pix[c->temp_cnt++].c = c->layers[c->cur_layer]->pix[COORD(x,y)];
- c->layers[c->cur_layer]->pix[COORD(x,y)] = COLTOINTA(
+ c->temp_pix[c->temp_cnt++].c = PIXEL(x, y);
+ PIXEL(x, y) = COLTOINTA(
((Palette *)def_palette)->clist[c->cur_col].r,
((Palette *)def_palette)->clist[c->cur_col].g,
((Palette *)def_palette)->clist[c->cur_col].b,
@@ -363,7 +379,7 @@ canvas_mousel_down(Canvas *c, long int x, long int y)
switch (tool_array[tool_cur]) {
case TOOL_TYPE_CPICKER:
for (i = 0; i < ((Palette *)def_palette)->num; ++i) {
- if (c->layers[c->cur_layer]->pix[COORD(x,y)] == COLTOINTA(
+ if (PIXEL(x, y) == COLTOINTA(
((Palette *)def_palette)->clist[i].r,
((Palette *)def_palette)->clist[i].g,
((Palette *)def_palette)->clist[i].b,
@@ -436,11 +452,11 @@ canvas_save(Canvas *c, const char *path, short int s)
fprintf(fp, "2;%u;%u;%u;", c->w, c->h, c->layer_arr_cnt);
for (i = 0; i < c->layer_arr_cnt; i++) {
- fwrite(c->layers[i]->name, sizeof *(c->layers[i]->name), LAYERNAMELEN, fp);
+ fwrite(c->layers[i].name, sizeof *(c->layers[i].name), LAYERNAMELEN, fp);
fprintf(fp, ";");
}
for (i = 0; i < c->layer_arr_cnt; i++)
- fwrite(c->layers[i]->pix, sizeof *(c->layers[i]->pix), c->w*c->h, fp);
+ fwrite(c->cells[i], sizeof *(c->cells[i]), c->w*c->h, fp);
fclose(fp);
if (s)
canvas_set_proj_path(c, path);
@@ -482,12 +498,16 @@ canvas_export_png(Canvas *c, const char *path, void *ren)
return ret;
}
-void
+uint8
canvas_add_layer(Canvas *c, uint pos)
{
- int i;
+ int i, j;
+ uint *u;
if (c == NULL)
- return;
+ return 1;
+
+ if (canvas_add_cells(c, c->frame_arr_cnt))
+ return 1;
pos = (pos > c->layer_arr_cnt) ? c->layer_arr_cnt : pos;
if (c->layer_arr_cnt == c->layer_arr_sz) {
@@ -500,7 +520,77 @@ canvas_add_layer(Canvas *c, uint pos)
}
c->layer_arr_cnt++;
- c->layers[pos] = layer_create(c->w, c->h, c->layer_arr_cnt);
+ c->layers[pos].visible = 1;
+ strcpy(c->layers[pos].name, "Layer ");
+ i = 10000000;
+ while (i) {
+ if (c->layer_arr_cnt / i) {
+ c->layers[pos].name[strlen(c->layers[pos].name)+1] = '\0';
+ c->layers[pos].name[strlen(c->layers[pos].name)] = ((c->layer_arr_cnt/i)%10) + '0';
+ }
+ i /= 10;
+ }
+
+ if (c->layer_arr_cnt > 1) {
+ for (i = c->frame_arr_cnt - 1; i >= 0; i--) {
+ for (j = c->layer_arr_cnt - 2; j >= 0; j--) {
+ if (j >= pos) {
+ u = c->cells[i*c->layer_arr_cnt - i + j];
+ c->cells[i*c->layer_arr_cnt - i + j] = c->cells[i*c->layer_arr_cnt + j + 1];
+ c->cells[i*c->layer_arr_cnt + j + 1] = u;
+ } else {
+ u = c->cells[i*c->layer_arr_cnt - i + j];
+ c->cells[i*c->layer_arr_cnt - i + j] = c->cells[i*c->layer_arr_cnt + j];
+ c->cells[i*c->layer_arr_cnt + j] = u;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < c->frame_arr_cnt; i++)
+ for (j = 0; j < c->w * c->h; j++)
+ c->cells[i*c->layer_arr_cnt + pos][j] = 0;
+ return 0;
+}
+
+uint8
+canvas_add_frame(Canvas *c, uint pos)
+{
+ int i, j;
+ uint *u;
+ if (c == NULL)
+ return 1;
+
+ if (canvas_add_cells(c, c->layer_arr_cnt))
+ return 1;
+ pos = (pos > c->frame_arr_cnt) ? c->frame_arr_cnt : pos;
+
+ if (c->frame_arr_cnt == c->frame_arr_sz) {
+ c->frame_arr_sz *= 2;
+ c->frames = realloc(c->frames, c->frame_arr_sz * sizeof(* c->frames));
+ }
+
+ for (i = c->frame_arr_cnt; i > pos; i--) {
+ c->frames[i] = c->frames[i-1];
+ }
+
+ c->frame_arr_cnt++;
+ c->frames[pos].state = 0;
+
+ if (c->layer_arr_cnt && c->frame_arr_cnt > 1) {
+ for (i = c->frame_arr_cnt - 2; i >= pos; i--) {
+ for (j = c->layer_arr_cnt - 1; j >= 0; j--) {
+ u = c->cells[i * c->layer_arr_cnt + j];
+ c->cells[i*c->layer_arr_cnt + j] = c->cells[(i+1)*c->layer_arr_cnt + j];
+ c->cells[(i+1)*c->layer_arr_cnt + j] = u;
+ }
+ }
+ }
+
+ for (i = 0; i < c->layer_arr_cnt; i++)
+ for (j = 0; j < c->w * c->h; j++)
+ c->cells[pos*c->layer_arr_cnt + i][j] = 0;
+ return 0;
}
void
@@ -525,6 +615,16 @@ canvas_change_layer(Canvas *c, unsigned int l)
c->cur_layer = l;
}
+void
+canvas_change_frame(Canvas *c, unsigned int l)
+{
+ if (l < c->frame_arr_cnt && l != c->cur_frame) {
+ c->cur_frame = l;
+ canvas_refresh(c);
+ ui_redraw_panel(UI_PANELTYPE_CANVAS);
+ }
+}
+
static void
canvas_set_proj_path(Canvas *c, const char *path)
@@ -544,46 +644,34 @@ canvas_set_proj_path(Canvas *c, const char *path)
free(title);
}
-static Layer *
-layer_create(uint w, uint h, uint cnt)
-{
- Layer *res;
- int i;
- /* TODO: better error handling and maybe allocating together? */
- res = malloc(sizeof *res);
- if (res == NULL)
- return NULL;
-
- res->visible = 1;
- res->pix = malloc(h * w * sizeof(* res->pix));
- if (res->pix == NULL) {
- fprintf(stderr, "Error creating layer\n");
- layer_destroy(res);
- return NULL;
+static uint8
+canvas_add_cells(Canvas * c, uint k)
+{
+ if (c == NULL) return 1;
+ uint **cells;
+ uint i, s;
+ s = c->layer_arr_cnt * c->frame_arr_cnt;
+ while (s + k > c->cell_arr_sz) {
+ cells = realloc(c->cells, 2 * c->cell_arr_sz * sizeof(* cells));
+ if (cells == NULL) return 1;
+ c->cells = cells;
+ c->cell_arr_sz *= 2;
}
- for (i = 0; i < w*h; ++i)
- res->pix[i] = 0;
- strcpy(res->name, "Layer ");
- i = 10000000;
- while (i) {
- if (cnt / i) {
- res->name[strlen(res->name)+1] = '\0';
- res->name[strlen(res->name)] = ((cnt/i)%10) + '0';
+ cells = c->cells;
+
+ for (i = s; i < c->cell_arr_sz; i++)
+ cells[i] = NULL;
+ for (i = s; i < s + k; i++) {
+ cells[i] = malloc(c->w * c->h * sizeof(* cells[i]));
+ if (cells[i] == NULL) {
+ for (k = s; k < i; k++)
+ free(cells[i]);
+ return 1;
}
- i /= 10;
}
-
- return res;
-}
-
-static void
-layer_destroy(Layer *lay)
-{
- if (lay->pix != NULL)
- free(lay->pix);
- free(lay);
+ return 0;
}
static uint
@@ -599,35 +687,35 @@ canvas_fill_bfs(Canvas *c, int x, int y, uint oldcol, uint newcol)
c->temp_pix[0].x = x;
c->temp_pix[0].y = y;
- c->layers[c->cur_layer]->pix[COORD(x,y)] = newcol;
+ PIXEL(x, y) = newcol;
for (; pnt != &(c->temp_pix)[c->temp_cnt]; ++pnt) {
pnt[0].c = oldcol;
x = pnt[0].x;
y = pnt[0].y;
- if (x > 0 && c->layers[c->cur_layer]->pix[COORD(x - 1,y)] == oldcol) {
- c->layers[c->cur_layer]->pix[COORD(x-1, y)] = newcol;
+ if (x > 0 && PIXEL(x-1, y) == oldcol) {
+ PIXEL(x-1, y) = newcol;
c->temp_pix[c->temp_cnt].x = x - 1;
c->temp_pix[c->temp_cnt].y = y;
++c->temp_cnt;
}
- if (x < c->w - 1 && c->layers[c->cur_layer]->pix[COORD(x+1, y)] == oldcol) {
- c->layers[c->cur_layer]->pix[COORD(x+1, y)] = newcol;
+ if (x < c->w - 1 && PIXEL(x+1, y) == oldcol) {
+ PIXEL(x+1, y) = newcol;
c->temp_pix[c->temp_cnt].x = x + 1;
c->temp_pix[c->temp_cnt].y = y;
++c->temp_cnt;
}
- if (y > 0 && c->layers[c->cur_layer]->pix[COORD(x, y-1)] == oldcol) {
- c->layers[c->cur_layer]->pix[COORD(x, y-1)] = newcol;
+ if (y > 0 && PIXEL(x, y-1) == oldcol) {
+ PIXEL(x, y-1) = newcol;
c->temp_pix[c->temp_cnt].x = x;
c->temp_pix[c->temp_cnt].y = y - 1;
++c->temp_cnt;
}
- if (y < c->h - 1 && c->layers[c->cur_layer]->pix[COORD(x, y+1)] == oldcol) {
- c->layers[c->cur_layer]->pix[COORD(x, y+1)] = newcol;
+ if (y < c->h - 1 && PIXEL(x, y+1) == oldcol) {
+ PIXEL(x, y+1) = newcol;
c->temp_pix[c->temp_cnt].x = x;
c->temp_pix[c->temp_cnt].y = y + 1;
++c->temp_cnt;
@@ -652,8 +740,8 @@ canvas_point_redraw(Canvas *c, long int x, long int y)
c->pres_pix[COORD(x, y)] = 0;
for (i = 0; i < c->layer_arr_cnt; i++)
- if (c->layers[i]->visible)
- c->pres_pix[COORD(x, y)] = canvas_blend_color(c->pres_pix[COORD(x, y)], c->layers[i]->pix[COORD(x, y)]);
+ if (c->layers[i].visible)
+ c->pres_pix[COORD(x, y)] = canvas_blend_color(c->pres_pix[COORD(x, y)], c->cells[c->layer_arr_cnt * c->cur_frame + i][COORD(x, y)]);
}
static void
@@ -662,7 +750,8 @@ action_do(Canvas *c)
action_remove(&c->history[c->hist_i]);
c->history[c->hist_i].type = ACT_PIXELSCOLORS;
c->history[c->hist_i].act.px.cnt = c->temp_cnt;
- c->history[c->hist_i].act.px.lyr = c->cur_layer;
+ c->history[c->hist_i].act.px.layer = c->cur_layer;
+ c->history[c->hist_i].act.px.frame = c->cur_frame;
c->history[c->hist_i].act.px.pix = malloc(c->temp_cnt * sizeof(struct action_pixcol));
memcpy(c->history[c->hist_i].act.px.pix, c->temp_pix, c->temp_cnt * sizeof(struct action_pixcol));
if (c->hist_i == c->hist_e)
@@ -725,15 +814,16 @@ action_pixcols_redo(Canvas *c, Action *a)
{
struct action_pixcol *pnt, *end;
unsigned int col;
- canvas_change_layer(c, a->act.px.lyr);
+ canvas_change_layer(c, a->act.px.layer);
+ canvas_change_frame(c, a->act.px.frame);
ui_redraw_panel(UI_PANELTYPE_TIMELINE);
pnt = a->act.px.pix;
end = &pnt[a->act.px.cnt];
SDL_SetRenderTarget(ren, c->half_pres);
for (; pnt != end; pnt++) {
- col = c->layers[c->cur_layer]->pix[COORD(pnt->x, pnt->y)];
- c->layers[c->cur_layer]->pix[COORD(pnt->x, pnt->y)] = pnt->c;
+ col = PIXEL(pnt->x, pnt->y);
+ PIXEL(pnt->x, pnt->y) = pnt->c;
pnt->c = col;
canvas_point_redraw(c, pnt->x, pnt->y);
SDL_SetRenderDrawColor(ren, INTTOCOLA(c->pres_pix[COORD(pnt->x, pnt->y)]));