diff options
Diffstat (limited to 'src/canvas.c')
-rw-r--r-- | src/canvas.c | 244 |
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)])); |