diff options
author | aiju <devnull@localhost> | 2014-07-30 15:57:14 +0200 |
---|---|---|
committer | aiju <devnull@localhost> | 2014-07-30 15:57:14 +0200 |
commit | 712fd30652d29dc9e936f11d7837d1cb079575fc (patch) | |
tree | 2915c820a5c05761f1d2ac4d525067f701aa474b /sys/src/cmd/spred/pal.c | |
parent | 555a05018b60b28bdfd6ada0310848c68fe20e48 (diff) |
added sprite editor spred
Diffstat (limited to 'sys/src/cmd/spred/pal.c')
-rw-r--r-- | sys/src/cmd/spred/pal.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/sys/src/cmd/spred/pal.c b/sys/src/cmd/spred/pal.c new file mode 100644 index 000000000..fcc57726f --- /dev/null +++ b/sys/src/cmd/spred/pal.c @@ -0,0 +1,280 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <keyboard.h> +#include <frame.h> +#include "dat.h" +#include "fns.h" + +Pal * +newpal(char *f) +{ + Pal *p; + + p = emalloc(sizeof(*p)); + p->type = PAL; + p->sel = -1; + filinit(p, f); + return p; +} + +void +putpal(Pal *p) +{ + int i; + + for(i = 0; i < p->ncol; i++) + freeimage(p->ims[i]); + free(p->cols); + free(p->ims); +} + +int +readpal(Pal *p, Biobuf *bp) +{ + char *s, *sp; + char *args[8]; + int nc, i, c; + + s = nil; + if(tline(bp, &s, args, nelem(args)) != 2) + goto err; + if(strcmp(args[0], "pal") != 0) + goto err; + nc = strtol(args[1], &sp, 0); + if(*sp != 0 || nc < 0) + goto err; + free(s); + s = nil; + p->ncol = nc; + p->cols = emalloc(nc * sizeof(*p->cols)); + p->ims = emalloc(nc * sizeof(*p->ims)); + for(i = 0; i < nc; i++){ + if(tline(bp, &s, args, nelem(args)) != 1) + goto err; + c = strtol(args[0], &sp, 0); + if(*sp != 0 || c < 0 || c > 0xffffff) + goto err; + p->cols[i] = c; + free(s); + s = nil; + } + for(i = 0; i < nc; i++) + p->ims[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, p->cols[i] << 8 | 0xff); + p->id = getident(bp->fid); + return 0; +err: + if(s != nil) + free(s); + werrstr("invalid format"); + return -1; +} + +int +writepal(Pal *p, char *f) +{ + Biobuf *bp; + int i, rc, n; + + if(f == nil) + f = p->name; + bp = Bopen(f, OWRITE); + if(bp == nil){ + cmdprint("?%r\n"); + return -1; + } + n = 0; + rc = Bprint(bp, "pal %d\n", p->ncol); + if(rc < 0) goto err; + n += rc; + for(i = 0; i < p->ncol; i++){ + rc = Bprint(bp, "%#.6x\n", p->cols[i]); + if(rc < 0) goto err; + n += rc; + } + if(Bterm(bp) < 0){ + cmdprint("?%r\n"); + return -1; + } + p->change = 0; + cmdprint("%s: #%d\n", f, n); + return 0; +err: + cmdprint("?%r\n"); + Bterm(bp); + return -1; +} + +Pal * +findpal(char *sf, char *fn, int op) +{ + File *f; + char *s, *q; + Ident i; + int fd; + Biobuf *bp; + Pal *p; + + if(sf == nil) + sf = ""; + s = emalloc(strlen(sf) + strlen(fn) + 2); + strcpy(s, sf); + q = strrchr(s, '/'); + if(q != nil) + *++q = 0; + else + *s = 0; + strcpy(s, fn); + fd = open(s, OREAD); + if(fd < 0){ + free(s); + return nil; + } + i = getident(fd); + if(i.type == (uint)-1){ + close(fd); + return nil; + } + for(f = flist.next; f != &flist; f = f->next) + if(f->type == PAL && identcmp(&f->id, &i) == 0){ + close(fd); + putident(i); + return (Pal *) f; + } + putident(i); + if(op == 0){ + close(fd); + return nil; + } + bp = emalloc(sizeof(*bp)); + Binit(bp, fd, OREAD); + p = newpal(s); + if(readpal(p, bp) < 0){ + putfil(p); + p = nil; + goto end; + } +end: + Bterm(bp); + close(fd); + free(bp); + free(s); + return p; +} + +static void +palredraw(Pal *p) +{ + File *f; + + filredraw(p); + for(f = flist.next; f != &flist; f = f->next) + if(f->type == SPR && ((Spr *) f)->pal == p) + filredraw(f); +} + +void +palsize(Pal *p, int sz) +{ + int i; + + if(sz == p->ncol) + return; + p->cols = realloc(p->cols, sz * sizeof(*p->cols)); + p->ims = realloc(p->ims, sz * sizeof(*p->ims)); + if(sz > p->ncol){ + memset(p->cols + p->ncol, 0, sz); + for(i = p->ncol; i < sz; i++) + p->ims[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0); + } + p->ncol = sz; + p->change = 1; + quitok = 0; + palredraw(p); +} + +void +paldraw(Win *w) +{ + Pal *p; + int n, i; + Rectangle r; + + if(w->type != PAL || w->f == nil) + sysfatal("paldraw: phase error"); + p = (Pal *) w->f; + n = Dx(w->inner) / w->zoom; + draw(w->im, w->inner, w->tab->cols[BACK], nil, ZP); + for(i = 0; i < p->ncol; i++){ + r.min = addpt(w->inner.min, mulpt(Pt(i%n, i/n), w->zoom)); + r.max.x = r.min.x + w->zoom; + r.max.y = r.min.y + w->zoom; + draw(w->im, r, p->ims[i], nil, ZP); + if(p->sel == i) + border(w->im, r, SELSIZ, display->white, ZP); + } +} + +void +palset(Pal *p, int s, u32int c) +{ + if(s < 0 || s >= p->ncol || p->cols[s] == c) + return; + p->cols[s] = c; + freeimage(p->ims[s]); + p->ims[s] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, c << 8 | 0xff); + p->change = 1; + quitok = 0; + palredraw(p); +} + +static int +palinit(Win *w) +{ + w->zoom = 32; + return 0; +} + +static void +palzerox(Win *w, Win *v) +{ + v->zoom = w->zoom; +} + +static void +palclick(Win *w, Mousectl *mc) +{ + int n, i; + Point pt; + Pal *p; + + if(!ptinrect(mc->xy, w->inner)) + return; + if(w->f == nil) + sysfatal("palclick: phase error"); + p = (Pal *) w->f; + n = Dx(w->inner) / w->zoom; + pt = subpt(mc->xy, w->inner.min); + if(pt.x >= n * w->zoom) + return; + i = pt.x / w->zoom + pt.y / w->zoom * n; + if(i >= p->ncol) + return; + p->sel = i; + palredraw(p); +} + +Wintab paltab = { + .init = palinit, + .click = palclick, + .draw = paldraw, + .zerox = palzerox, + .hexcols = { + [BORD] 0xAA0000FF, + [DISB] 0xCC8888FF, + [BACK] 0xFFCCFFFF, + }, +}; |