summaryrefslogtreecommitdiff
path: root/sys/src/cmd/spred/pal.c
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2014-07-30 15:57:14 +0200
committeraiju <devnull@localhost>2014-07-30 15:57:14 +0200
commit712fd30652d29dc9e936f11d7837d1cb079575fc (patch)
tree2915c820a5c05761f1d2ac4d525067f701aa474b /sys/src/cmd/spred/pal.c
parent555a05018b60b28bdfd6ada0310848c68fe20e48 (diff)
added sprite editor spred
Diffstat (limited to 'sys/src/cmd/spred/pal.c')
-rw-r--r--sys/src/cmd/spred/pal.c280
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,
+ },
+};