11052a86aSDavid du Colombier #include <u.h>
21052a86aSDavid du Colombier #include <libc.h>
31052a86aSDavid du Colombier #include <draw.h>
41052a86aSDavid du Colombier #include <event.h>
51052a86aSDavid du Colombier #include <cursor.h>
61052a86aSDavid du Colombier
71052a86aSDavid du Colombier #define initstate muginitstate
81052a86aSDavid du Colombier
91052a86aSDavid du Colombier typedef struct State State;
101052a86aSDavid du Colombier struct State {
111052a86aSDavid du Colombier double black;
121052a86aSDavid du Colombier double white;
131052a86aSDavid du Colombier double stretch;
141052a86aSDavid du Colombier double gamma;
151052a86aSDavid du Colombier int depth;
161052a86aSDavid du Colombier int gtab[1001];
171052a86aSDavid du Colombier Rectangle selr;
181052a86aSDavid du Colombier };
191052a86aSDavid du Colombier
201052a86aSDavid du Colombier typedef struct Face Face;
211052a86aSDavid du Colombier struct Face {
221052a86aSDavid du Colombier Rectangle r;
231052a86aSDavid du Colombier State state;
241052a86aSDavid du Colombier Image *small;
251052a86aSDavid du Colombier };
261052a86aSDavid du Colombier
271052a86aSDavid du Colombier double GAMMA = 1.0; /* theory tells me this should be 2.2, but 1.0 sure looks better */
281052a86aSDavid du Colombier enum {
291052a86aSDavid du Colombier Left=0,
301052a86aSDavid du Colombier Right,
311052a86aSDavid du Colombier Top,
321052a86aSDavid du Colombier Bottom,
331052a86aSDavid du Colombier
341052a86aSDavid du Colombier RTopLeft=0,
351052a86aSDavid du Colombier RTop,
361052a86aSDavid du Colombier RTopRight,
371052a86aSDavid du Colombier RLeft,
381052a86aSDavid du Colombier RMiddle,
391052a86aSDavid du Colombier RRight,
401052a86aSDavid du Colombier RBotLeft,
411052a86aSDavid du Colombier RBot,
421052a86aSDavid du Colombier RBotRight,
431052a86aSDavid du Colombier };
441052a86aSDavid du Colombier
451052a86aSDavid du Colombier void*
emalloc(ulong sz)461052a86aSDavid du Colombier emalloc(ulong sz)
471052a86aSDavid du Colombier {
481052a86aSDavid du Colombier void *v;
491052a86aSDavid du Colombier
501052a86aSDavid du Colombier v = malloc(sz);
511052a86aSDavid du Colombier if(v == nil)
5214cc0f53SDavid du Colombier sysfatal("malloc %lud fails", sz);
531052a86aSDavid du Colombier memset(v, 0, sz);
541052a86aSDavid du Colombier return v;
551052a86aSDavid du Colombier }
561052a86aSDavid du Colombier
571052a86aSDavid du Colombier Face *face[8];
581052a86aSDavid du Colombier int nface;
591052a86aSDavid du Colombier uchar grey2cmap[256];
601052a86aSDavid du Colombier Image *bkgd;
611052a86aSDavid du Colombier Image *orig;
621052a86aSDavid du Colombier Image *ramp, *small, *osmall, *tmp8, *red, *green, *blue;
631052a86aSDavid du Colombier State state, ostate;
641052a86aSDavid du Colombier uchar val2cmap[256];
651052a86aSDavid du Colombier uchar clamp[3*256];
661052a86aSDavid du Colombier Rectangle rbig, rramp, rface[nelem(face)], rsmall;
671052a86aSDavid du Colombier double *rdata;
681052a86aSDavid du Colombier int sdy, sdx;
691052a86aSDavid du Colombier
701052a86aSDavid du Colombier void
geometry(Rectangle r)711052a86aSDavid du Colombier geometry(Rectangle r)
721052a86aSDavid du Colombier {
731052a86aSDavid du Colombier int i;
741052a86aSDavid du Colombier Rectangle fr[9];
751052a86aSDavid du Colombier
761052a86aSDavid du Colombier rramp.min = addpt(r.min, Pt(4,4));
771052a86aSDavid du Colombier rramp.max = addpt(rramp.min, Pt(256,256));
781052a86aSDavid du Colombier
791052a86aSDavid du Colombier rbig.min = Pt(rramp.max.x+6, rramp.min.y);
801052a86aSDavid du Colombier rbig.max = addpt(rbig.min, Pt(Dx(orig->r), Dy(orig->r)));
811052a86aSDavid du Colombier
821052a86aSDavid du Colombier for(i=0; i<9; i++)
831052a86aSDavid du Colombier fr[i] = rectaddpt(Rect(0,0,48,48), Pt(rramp.min.x+48+56*(i%3), rramp.max.y+6+56*(i/3)));
841052a86aSDavid du Colombier
851052a86aSDavid du Colombier rsmall = fr[4];
861052a86aSDavid du Colombier for(i=0; i<4; i++)
871052a86aSDavid du Colombier rface[i] = fr[i];
881052a86aSDavid du Colombier for(i=4; i<8; i++)
891052a86aSDavid du Colombier rface[i] = fr[i+1];
901052a86aSDavid du Colombier }
911052a86aSDavid du Colombier
921052a86aSDavid du Colombier double
y2gamma(int y)931052a86aSDavid du Colombier y2gamma(int y)
941052a86aSDavid du Colombier {
951052a86aSDavid du Colombier double g;
961052a86aSDavid du Colombier
971052a86aSDavid du Colombier g = (double)y / 128.0;
981052a86aSDavid du Colombier return 0.5+g*g; /* gamma from 0.5 to 4.5, with 1.0 near the middle */
991052a86aSDavid du Colombier }
1001052a86aSDavid du Colombier
1011052a86aSDavid du Colombier int
gamma2y(double g)1021052a86aSDavid du Colombier gamma2y(double g)
1031052a86aSDavid du Colombier {
1041052a86aSDavid du Colombier g -= 0.5;
1051052a86aSDavid du Colombier return (int)(128.0*sqrt(g)+0.5);
1061052a86aSDavid du Colombier }
1071052a86aSDavid du Colombier
1081052a86aSDavid du Colombier void
drawface(int i)1091052a86aSDavid du Colombier drawface(int i)
1101052a86aSDavid du Colombier {
1111052a86aSDavid du Colombier if(i==-1){
1121052a86aSDavid du Colombier border(screen, rsmall, -3, blue, ZP);
1131052a86aSDavid du Colombier draw(screen, rsmall, small, nil, ZP);
1141052a86aSDavid du Colombier return;
1151052a86aSDavid du Colombier }
1161052a86aSDavid du Colombier border(screen, rface[i], -1, display->black, ZP);
1171052a86aSDavid du Colombier if(face[i])
1181052a86aSDavid du Colombier draw(screen, rface[i], face[i]->small, nil, ZP);
1191052a86aSDavid du Colombier else
1201052a86aSDavid du Colombier draw(screen, rface[i], display->white, nil, ZP);
1211052a86aSDavid du Colombier }
1221052a86aSDavid du Colombier
1231052a86aSDavid du Colombier void
drawrampbar(Image * color,State * s)1241052a86aSDavid du Colombier drawrampbar(Image *color, State *s)
1251052a86aSDavid du Colombier {
1261052a86aSDavid du Colombier Rectangle liner, r;
1271052a86aSDavid du Colombier static Rectangle br;
1281052a86aSDavid du Colombier
1291052a86aSDavid du Colombier if(Dx(br))
1301052a86aSDavid du Colombier draw(screen, br, ramp, nil, subpt(br.min, rramp.min));
1311052a86aSDavid du Colombier
1321052a86aSDavid du Colombier r = rramp;
1331052a86aSDavid du Colombier r.max.x = r.min.x + (int)(s->white*255.0);
1341052a86aSDavid du Colombier r.min.x += (int)(s->black*255.0);
1351052a86aSDavid du Colombier r.min.y += gamma2y(s->gamma);
1361052a86aSDavid du Colombier r.max.y = r.min.y+1;
1371052a86aSDavid du Colombier rectclip(&r, rramp);
1381052a86aSDavid du Colombier draw(screen, r, color, nil, ZP);
1391052a86aSDavid du Colombier br = r;
1401052a86aSDavid du Colombier
1411052a86aSDavid du Colombier r.min.y -= 2;
1421052a86aSDavid du Colombier r.max.y += 2;
1431052a86aSDavid du Colombier
1441052a86aSDavid du Colombier liner = r;
1451052a86aSDavid du Colombier r.min.x += Dx(liner)/3;
1461052a86aSDavid du Colombier r.max.x -= Dx(liner)/3;
1471052a86aSDavid du Colombier rectclip(&r, rramp);
1481052a86aSDavid du Colombier draw(screen, r, color, nil, ZP);
1491052a86aSDavid du Colombier combinerect(&br, r);
1501052a86aSDavid du Colombier
1511052a86aSDavid du Colombier r = liner;
1521052a86aSDavid du Colombier r.max.x = r.min.x+3;
1531052a86aSDavid du Colombier rectclip(&r, rramp);
1541052a86aSDavid du Colombier draw(screen, r, color, nil, ZP);
1551052a86aSDavid du Colombier combinerect(&br, r);
1561052a86aSDavid du Colombier
1571052a86aSDavid du Colombier r = liner;
1581052a86aSDavid du Colombier r.min.x = r.max.x-3;
1591052a86aSDavid du Colombier rectclip(&r, rramp);
1601052a86aSDavid du Colombier draw(screen, r, color, nil, ZP);
1611052a86aSDavid du Colombier combinerect(&br, r);
1621052a86aSDavid du Colombier }
1631052a86aSDavid du Colombier
1641052a86aSDavid du Colombier void
drawscreen(int clear)1651052a86aSDavid du Colombier drawscreen(int clear)
1661052a86aSDavid du Colombier {
1671052a86aSDavid du Colombier int i;
1681052a86aSDavid du Colombier
1691052a86aSDavid du Colombier if(clear){
1701052a86aSDavid du Colombier geometry(screen->r);
1711052a86aSDavid du Colombier draw(screen, screen->r, bkgd, nil, ZP);
1721052a86aSDavid du Colombier }
1731052a86aSDavid du Colombier
1741052a86aSDavid du Colombier border(screen, rbig, -1, display->black, ZP);
1751052a86aSDavid du Colombier draw(screen, rbig, orig, nil, orig->r.min);
1761052a86aSDavid du Colombier
1771052a86aSDavid du Colombier border(screen, rramp, -1, display->black, ZP);
1781052a86aSDavid du Colombier draw(screen, rramp, ramp, nil, ramp->r.min);
1791052a86aSDavid du Colombier drawrampbar(red, &state);
1801052a86aSDavid du Colombier
1811052a86aSDavid du Colombier border(screen, rectaddpt(state.selr, subpt(rbig.min, orig->r.min)), -2, red, ZP);
1821052a86aSDavid du Colombier if(clear){
1831052a86aSDavid du Colombier drawface(-1);
1841052a86aSDavid du Colombier for(i=0; i<nelem(face); i++)
1851052a86aSDavid du Colombier drawface(i);
1861052a86aSDavid du Colombier }
1871052a86aSDavid du Colombier }
1881052a86aSDavid du Colombier
1891052a86aSDavid du Colombier void
moveframe(Rectangle old,Rectangle new)1901052a86aSDavid du Colombier moveframe(Rectangle old, Rectangle new)
1911052a86aSDavid du Colombier {
1921052a86aSDavid du Colombier border(screen, rectaddpt(old, subpt(rbig.min, orig->r.min)), -2, orig, old.min);
1931052a86aSDavid du Colombier border(screen, rectaddpt(new, subpt(rbig.min, orig->r.min)), -2, red, ZP);
1941052a86aSDavid du Colombier }
1951052a86aSDavid du Colombier
1961052a86aSDavid du Colombier
1971052a86aSDavid du Colombier /*
1981052a86aSDavid du Colombier * Initialize gamma ramp; should dither for
1991052a86aSDavid du Colombier * benefit of non-true-color displays.
2001052a86aSDavid du Colombier */
2011052a86aSDavid du Colombier void
initramp(void)2021052a86aSDavid du Colombier initramp(void)
2031052a86aSDavid du Colombier {
2041052a86aSDavid du Colombier int k, x, y;
2051052a86aSDavid du Colombier uchar dat[256*256];
2061052a86aSDavid du Colombier double g;
2071052a86aSDavid du Colombier
2081052a86aSDavid du Colombier k = 0;
2091052a86aSDavid du Colombier for(y=0; y<256; y++) {
2101052a86aSDavid du Colombier g = y2gamma(y);
2111052a86aSDavid du Colombier for(x=0; x<256; x++)
2121052a86aSDavid du Colombier dat[k++] = 255.0 * pow(x/255.0, g);
2131052a86aSDavid du Colombier }
2141052a86aSDavid du Colombier assert(k == sizeof dat);
2151052a86aSDavid du Colombier
2161052a86aSDavid du Colombier ramp = allocimage(display, Rect(0,0,256,256), GREY8, 0, DNofill);
2171052a86aSDavid du Colombier if(ramp == nil)
2181052a86aSDavid du Colombier sysfatal("allocimage: %r");
2191052a86aSDavid du Colombier
2201052a86aSDavid du Colombier if(loadimage(ramp, ramp->r, dat, sizeof dat) != sizeof dat)
2211052a86aSDavid du Colombier sysfatal("loadimage: %r");
2221052a86aSDavid du Colombier }
2231052a86aSDavid du Colombier
2241052a86aSDavid du Colombier void
initclamp(void)2251052a86aSDavid du Colombier initclamp(void)
2261052a86aSDavid du Colombier {
2271052a86aSDavid du Colombier int i;
2281052a86aSDavid du Colombier
2291052a86aSDavid du Colombier for(i=0; i<256; i++) {
2301052a86aSDavid du Colombier clamp[i] = 0;
2311052a86aSDavid du Colombier clamp[256+i] = i;
2321052a86aSDavid du Colombier clamp[512+i] = 255;
2331052a86aSDavid du Colombier }
2341052a86aSDavid du Colombier }
2351052a86aSDavid du Colombier
2361052a86aSDavid du Colombier void
changestretch(double stretch)2371052a86aSDavid du Colombier changestretch(double stretch)
2381052a86aSDavid du Colombier {
2391052a86aSDavid du Colombier state.stretch = stretch;
2401052a86aSDavid du Colombier }
2411052a86aSDavid du Colombier
2421052a86aSDavid du Colombier /*
2431052a86aSDavid du Colombier * There is greyscale data for the rectangle datar in data;
2441052a86aSDavid du Colombier * extract square r and write it into the 48x48 pixel image small.
2451052a86aSDavid du Colombier */
2461052a86aSDavid du Colombier void
process(double * data,Rectangle datar,Rectangle r,Image * small)2471052a86aSDavid du Colombier process(double *data, Rectangle datar, Rectangle r, Image *small)
2481052a86aSDavid du Colombier {
2491052a86aSDavid du Colombier double black, center, delta, *k, shrink, sum, *tmp[48], *tt, w, white, x;
2501052a86aSDavid du Colombier int datadx, dp, dx, dy, error, i, ii, j, jj;
2511052a86aSDavid du Colombier int ksize, ksizeby2, sdata[48*48], sd, sh, sm, sv, u, uu, uuu, v, vv;
2521052a86aSDavid du Colombier uchar bdata[48*48];
2531052a86aSDavid du Colombier
2541052a86aSDavid du Colombier datadx = Dx(datar);
2551052a86aSDavid du Colombier dx = Dx(r);
2561052a86aSDavid du Colombier dy = Dy(r);
2571052a86aSDavid du Colombier shrink = dx/48.0;
2581052a86aSDavid du Colombier
2591052a86aSDavid du Colombier ksize = 1+2*(int)(shrink/2.0);
2601052a86aSDavid du Colombier if(ksize <= 2)
2611052a86aSDavid du Colombier return;
2621052a86aSDavid du Colombier
2631052a86aSDavid du Colombier k = emalloc(ksize*sizeof(k[0]));
2641052a86aSDavid du Colombier
2651052a86aSDavid du Colombier /* center of box */
2661052a86aSDavid du Colombier for(i=1; i<ksize-1; i++)
2671052a86aSDavid du Colombier k[i] = 1.0;
2681052a86aSDavid du Colombier
2691052a86aSDavid du Colombier /* edges */
2701052a86aSDavid du Colombier x = shrink - floor(shrink);
2711052a86aSDavid du Colombier k[0] = x;
2721052a86aSDavid du Colombier k[ksize-1] = x;
2731052a86aSDavid du Colombier
2741052a86aSDavid du Colombier sum = 0.0;
2751052a86aSDavid du Colombier for(i=0; i<ksize; i++)
2761052a86aSDavid du Colombier sum += k[i];
2771052a86aSDavid du Colombier
2781052a86aSDavid du Colombier for(i=0; i<ksize; i++)
2791052a86aSDavid du Colombier k[i] /= sum;
2801052a86aSDavid du Colombier
2811052a86aSDavid du Colombier ksizeby2 = ksize/2;
2821052a86aSDavid du Colombier
2831052a86aSDavid du Colombier for(i=0; i<48; i++)
2841052a86aSDavid du Colombier tmp[i] = emalloc(datadx*sizeof(tmp[i][0]));
2851052a86aSDavid du Colombier
2861052a86aSDavid du Colombier /* squeeze vertically */
2871052a86aSDavid du Colombier for(i=0; i<48; i++) {
2881052a86aSDavid du Colombier ii = r.min.y+i*dy/48;
2891052a86aSDavid du Colombier tt = tmp[i];
2901052a86aSDavid du Colombier uu = ii - ksizeby2;
2911052a86aSDavid du Colombier for(j=r.min.x-ksize; j<r.max.x+ksize; j++) {
2921052a86aSDavid du Colombier if(j<datar.min.x || j>=datar.max.x)
2931052a86aSDavid du Colombier continue;
2941052a86aSDavid du Colombier w = 0.0;
2951052a86aSDavid du Colombier
2961052a86aSDavid du Colombier uuu = uu*datadx+j;
2971052a86aSDavid du Colombier if(uu>=datar.min.y && uu+ksize<datar.max.y)
2981052a86aSDavid du Colombier for(u=0; u<ksize; u++){
2991052a86aSDavid du Colombier w += k[u]*data[uuu];
3001052a86aSDavid du Colombier uuu += datadx;
3011052a86aSDavid du Colombier }
3021052a86aSDavid du Colombier else
3031052a86aSDavid du Colombier for(u=0; u<ksize; u++){
3041052a86aSDavid du Colombier if(uu+u>=datar.min.y && uu+u<datar.max.y)
3051052a86aSDavid du Colombier w += k[u]*data[uuu];
3061052a86aSDavid du Colombier uuu+=datadx;
3071052a86aSDavid du Colombier }
3081052a86aSDavid du Colombier tt[j-datar.min.x] = w;
3091052a86aSDavid du Colombier }
3101052a86aSDavid du Colombier }
3111052a86aSDavid du Colombier
3121052a86aSDavid du Colombier /* stretch value scale */
3131052a86aSDavid du Colombier center = (state.black+state.white)/2;
3141052a86aSDavid du Colombier delta = state.stretch*(state.white-state.black)/2;
3151052a86aSDavid du Colombier black = center - delta;
3161052a86aSDavid du Colombier white = center + delta;
3171052a86aSDavid du Colombier
3181052a86aSDavid du Colombier /* squeeze horizontally */
3191052a86aSDavid du Colombier for(i=0; i<48; i++) {
3201052a86aSDavid du Colombier tt = tmp[i];
3211052a86aSDavid du Colombier for(j=0; j<48; j++) {
3221052a86aSDavid du Colombier jj = r.min.x+j*dx/48;
3231052a86aSDavid du Colombier w = 0.0;
3241052a86aSDavid du Colombier for(v=0; v<ksize; v++) {
3251052a86aSDavid du Colombier vv = jj - ksizeby2 + v;
3261052a86aSDavid du Colombier if(vv<datar.min.x || vv>=datar.max.x) {
3271052a86aSDavid du Colombier w += k[v]; /* assume white surround */
3281052a86aSDavid du Colombier continue;
3291052a86aSDavid du Colombier }
3301052a86aSDavid du Colombier w += k[v]*tt[vv-datar.min.x];
3311052a86aSDavid du Colombier }
3321052a86aSDavid du Colombier if(w < black || black==white)
3331052a86aSDavid du Colombier w = 0.0;
3341052a86aSDavid du Colombier else if(w > white)
3351052a86aSDavid du Colombier w = 1.0;
3361052a86aSDavid du Colombier else
3371052a86aSDavid du Colombier w = (w-black)/(white-black);
3381052a86aSDavid du Colombier sdata[i*48+j] = state.gtab[(int)(1000.0*w)];
3391052a86aSDavid du Colombier }
3401052a86aSDavid du Colombier }
3411052a86aSDavid du Colombier
3421052a86aSDavid du Colombier /* dither to lower depth before copying into GREY8 version */
3431052a86aSDavid du Colombier if(small->chan != GREY8) {
3441052a86aSDavid du Colombier u = 0;
3451052a86aSDavid du Colombier dp = small->depth;
3461052a86aSDavid du Colombier for(i=0; i<48; i++) {
3471052a86aSDavid du Colombier sm = 0xFF ^ (0xFF>>dp);
3481052a86aSDavid du Colombier sh = 0;
3491052a86aSDavid du Colombier v = 0;
3501052a86aSDavid du Colombier for(j=0; j<48; j++) {
3511052a86aSDavid du Colombier ii = 48*i+j;
3521052a86aSDavid du Colombier sd = clamp[sdata[ii]+256];
3531052a86aSDavid du Colombier sv = sd&sm;
3541052a86aSDavid du Colombier v |= sv>>sh;
3551052a86aSDavid du Colombier sh += dp;
3561052a86aSDavid du Colombier if(sh == 8) {
3571052a86aSDavid du Colombier bdata[u++] = v;
3581052a86aSDavid du Colombier v = 0;
3591052a86aSDavid du Colombier sh = 0;
3601052a86aSDavid du Colombier }
3611052a86aSDavid du Colombier
3621052a86aSDavid du Colombier /* propagate error, with decay (sum errors < 1) */
3631052a86aSDavid du Colombier error = sd - sv;
3641052a86aSDavid du Colombier if(ii+49 < 48*48) { /* one test is enough, really */
3651052a86aSDavid du Colombier sdata[ii+1] = sdata[ii+1]+((3*error)>>4);
3661052a86aSDavid du Colombier sdata[ii+48] = sdata[ii+48]+((3*error)>>4);
3671052a86aSDavid du Colombier sdata[ii+49] = sdata[ii+49]+((3*error)>>3);
3681052a86aSDavid du Colombier }
3691052a86aSDavid du Colombier
3701052a86aSDavid du Colombier /* produce correct color map value by copying bits */
3711052a86aSDavid du Colombier switch(dp){
3721052a86aSDavid du Colombier case 1:
3731052a86aSDavid du Colombier sv |= sv>>1;
3741052a86aSDavid du Colombier case 2:
3751052a86aSDavid du Colombier sv |= sv>>2;
3761052a86aSDavid du Colombier case 4:
3771052a86aSDavid du Colombier sv |= sv>>4;
3781052a86aSDavid du Colombier }
3791052a86aSDavid du Colombier sdata[ii] = sv;
3801052a86aSDavid du Colombier }
3811052a86aSDavid du Colombier }
3821052a86aSDavid du Colombier for(i=0; i<nelem(bdata); i++)
3831052a86aSDavid du Colombier bdata[i] = sdata[i];
3841052a86aSDavid du Colombier if(loadimage(tmp8, tmp8->r, bdata, sizeof bdata) != sizeof bdata)
3851052a86aSDavid du Colombier sysfatal("loadimage: %r");
3861052a86aSDavid du Colombier draw(small, small->r, tmp8, nil, tmp8->r.min);
3871052a86aSDavid du Colombier } else {
3881052a86aSDavid du Colombier for(i=0; i<nelem(bdata); i++)
3891052a86aSDavid du Colombier bdata[i] = sdata[i];
3901052a86aSDavid du Colombier if(loadimage(small, small->r, bdata, sizeof bdata) != sizeof bdata)
3911052a86aSDavid du Colombier sysfatal("loadimage: %r");
3921052a86aSDavid du Colombier }
3931052a86aSDavid du Colombier
3941052a86aSDavid du Colombier free(k);
3951052a86aSDavid du Colombier for(i=0; i<48; i++)
3961052a86aSDavid du Colombier free(tmp[i]);
3971052a86aSDavid du Colombier }
3981052a86aSDavid du Colombier
3991052a86aSDavid du Colombier void
initval2cmap(void)4001052a86aSDavid du Colombier initval2cmap(void)
4011052a86aSDavid du Colombier {
4021052a86aSDavid du Colombier int i;
4031052a86aSDavid du Colombier
4041052a86aSDavid du Colombier for(i=0; i<256; i++)
4051052a86aSDavid du Colombier val2cmap[i] = rgb2cmap(i, i, i);
4061052a86aSDavid du Colombier }
4071052a86aSDavid du Colombier
4081052a86aSDavid du Colombier void
setgtab(State * s)4091052a86aSDavid du Colombier setgtab(State *s)
4101052a86aSDavid du Colombier {
4111052a86aSDavid du Colombier int i;
4121052a86aSDavid du Colombier
4131052a86aSDavid du Colombier for(i=0; i<=1000; i++)
4141052a86aSDavid du Colombier s->gtab[i] = val2cmap[(int)(255.0*pow((i/1000.0), 1.0/s->gamma))];
4151052a86aSDavid du Colombier }
4161052a86aSDavid du Colombier
4171052a86aSDavid du Colombier int
section(int x)4181052a86aSDavid du Colombier section(int x)
4191052a86aSDavid du Colombier {
4201052a86aSDavid du Colombier int ib, iw;
4211052a86aSDavid du Colombier
4221052a86aSDavid du Colombier ib = state.black * 255.0;
4231052a86aSDavid du Colombier iw = state.white * 255.0;
4241052a86aSDavid du Colombier
4251052a86aSDavid du Colombier if(x<ib-5 || iw+5<x)
4261052a86aSDavid du Colombier return -1;
4271052a86aSDavid du Colombier
4281052a86aSDavid du Colombier iw -= ib;
4291052a86aSDavid du Colombier x -= ib;
4301052a86aSDavid du Colombier if(x < iw/3)
4311052a86aSDavid du Colombier return 0;
4321052a86aSDavid du Colombier if(x < 2*iw/3)
4331052a86aSDavid du Colombier return 1;
4341052a86aSDavid du Colombier return 2;
4351052a86aSDavid du Colombier }
4361052a86aSDavid du Colombier
4371052a86aSDavid du Colombier Image*
copyimage(Image * i)4381052a86aSDavid du Colombier copyimage(Image *i)
4391052a86aSDavid du Colombier {
4401052a86aSDavid du Colombier Image *n;
4411052a86aSDavid du Colombier
4421052a86aSDavid du Colombier if(i == nil)
4431052a86aSDavid du Colombier return nil;
4441052a86aSDavid du Colombier
4451052a86aSDavid du Colombier n = allocimage(display, i->r, i->chan, 0, DNofill);
4461052a86aSDavid du Colombier if(n == nil)
4471052a86aSDavid du Colombier sysfatal("allocimage: %r");
4481052a86aSDavid du Colombier
4491052a86aSDavid du Colombier draw(n, n->r, i, nil, i->r.min);
4501052a86aSDavid du Colombier return n;
4511052a86aSDavid du Colombier }
4521052a86aSDavid du Colombier
4531052a86aSDavid du Colombier Image*
grey8image(Image * i)4541052a86aSDavid du Colombier grey8image(Image *i)
4551052a86aSDavid du Colombier {
4561052a86aSDavid du Colombier Image *n;
4571052a86aSDavid du Colombier
4581052a86aSDavid du Colombier if(i->chan == GREY8)
4591052a86aSDavid du Colombier return i;
4601052a86aSDavid du Colombier
4611052a86aSDavid du Colombier n = allocimage(display, i->r, GREY8, 0, DNofill);
4621052a86aSDavid du Colombier if(n == nil)
4631052a86aSDavid du Colombier sysfatal("allocimage: %r");
4641052a86aSDavid du Colombier
4651052a86aSDavid du Colombier draw(n, n->r, i, nil, i->r.min);
4661052a86aSDavid du Colombier freeimage(i);
4671052a86aSDavid du Colombier return n;
4681052a86aSDavid du Colombier }
4691052a86aSDavid du Colombier
4701052a86aSDavid du Colombier
4711052a86aSDavid du Colombier void
mark(void)4721052a86aSDavid du Colombier mark(void)
4731052a86aSDavid du Colombier {
4741052a86aSDavid du Colombier if(osmall != small){
4751052a86aSDavid du Colombier freeimage(osmall);
4761052a86aSDavid du Colombier osmall = small;
4771052a86aSDavid du Colombier }
4781052a86aSDavid du Colombier ostate = state;
4791052a86aSDavid du Colombier }
4801052a86aSDavid du Colombier
4811052a86aSDavid du Colombier void
undo(void)4821052a86aSDavid du Colombier undo(void)
4831052a86aSDavid du Colombier {
4841052a86aSDavid du Colombier if(small != osmall){
4851052a86aSDavid du Colombier freeimage(small);
4861052a86aSDavid du Colombier small = osmall;
4871052a86aSDavid du Colombier }
4881052a86aSDavid du Colombier state = ostate;
4891052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
4901052a86aSDavid du Colombier drawface(-1);
4911052a86aSDavid du Colombier drawscreen(0);
4921052a86aSDavid du Colombier }
4931052a86aSDavid du Colombier
4941052a86aSDavid du Colombier void
saveface(Face * f,int slot)4951052a86aSDavid du Colombier saveface(Face *f, int slot)
4961052a86aSDavid du Colombier {
4971052a86aSDavid du Colombier if(slot == -1){
4981052a86aSDavid du Colombier mark();
4991052a86aSDavid du Colombier state = f->state;
5001052a86aSDavid du Colombier small = copyimage(f->small);
5011052a86aSDavid du Colombier drawface(-1);
5021052a86aSDavid du Colombier drawscreen(0);
5031052a86aSDavid du Colombier return;
5041052a86aSDavid du Colombier }
5051052a86aSDavid du Colombier
5061052a86aSDavid du Colombier if(face[slot]==nil)
5071052a86aSDavid du Colombier face[slot] = emalloc(sizeof(*face[slot]));
5081052a86aSDavid du Colombier else{
5091052a86aSDavid du Colombier freeimage(face[slot]->small);
5101052a86aSDavid du Colombier face[slot]->small = nil;
5111052a86aSDavid du Colombier }
5121052a86aSDavid du Colombier
5131052a86aSDavid du Colombier if(f == nil){
5141052a86aSDavid du Colombier face[slot]->small = copyimage(small);
5151052a86aSDavid du Colombier face[slot]->state = state;
5161052a86aSDavid du Colombier }else{
5171052a86aSDavid du Colombier face[slot]->small = copyimage(f->small);
5181052a86aSDavid du Colombier face[slot]->state = f->state;
5191052a86aSDavid du Colombier }
5201052a86aSDavid du Colombier drawface(slot);
5211052a86aSDavid du Colombier }
5221052a86aSDavid du Colombier
5231052a86aSDavid du Colombier int
writeface(char * outfile,Image * image)5241052a86aSDavid du Colombier writeface(char *outfile, Image *image)
5251052a86aSDavid du Colombier {
5261052a86aSDavid du Colombier int i, fd, rv, y;
5271052a86aSDavid du Colombier uchar data[48*48/2];
5281052a86aSDavid du Colombier
5291052a86aSDavid du Colombier if(outfile == nil)
5301052a86aSDavid du Colombier fd = 1;
5311052a86aSDavid du Colombier else{
5321052a86aSDavid du Colombier if((fd = create(outfile, OWRITE, 0666)) < 0)
5331052a86aSDavid du Colombier return -1;
5341052a86aSDavid du Colombier }
5351052a86aSDavid du Colombier
5361052a86aSDavid du Colombier switch(image->chan) {
5371052a86aSDavid du Colombier default:
5381052a86aSDavid du Colombier rv = -1;
5391052a86aSDavid du Colombier break;
5401052a86aSDavid du Colombier
5411052a86aSDavid du Colombier case GREY1:
5421052a86aSDavid du Colombier if(unloadimage(image, image->r, data, 48*48/8) != 48*48/8)
5431052a86aSDavid du Colombier sysfatal("unloadimage: %r");
5441052a86aSDavid du Colombier for(y=0; y<48; y++) {
5451052a86aSDavid du Colombier for(i=0; i<3; i++)
5461052a86aSDavid du Colombier fprint(fd, "0x%.2x%.2x,", data[y*6+i*2+0], data[y*6+i*2+1]);
5471052a86aSDavid du Colombier fprint(fd, "\n");
5481052a86aSDavid du Colombier }
5491052a86aSDavid du Colombier rv = 0;
5501052a86aSDavid du Colombier break;
5511052a86aSDavid du Colombier
5521052a86aSDavid du Colombier case GREY2:
5531052a86aSDavid du Colombier if(unloadimage(image, image->r, data, 48*48/4) != 48*48/4)
5541052a86aSDavid du Colombier sysfatal("unloadimage: %r");
5551052a86aSDavid du Colombier for(y=0; y<48; y++) {
5561052a86aSDavid du Colombier for(i=0; i<3; i++)
5571052a86aSDavid du Colombier fprint(fd, "0x%.2x%.2x,%.2x%.2x,",
5581052a86aSDavid du Colombier data[y*12+i*4+0], data[y*12+i*4+1],
5591052a86aSDavid du Colombier data[y*12+i*4+2], data[y*12+i*4+3]);
5601052a86aSDavid du Colombier fprint(fd, "\n");
5611052a86aSDavid du Colombier }
5621052a86aSDavid du Colombier rv = 0;
5631052a86aSDavid du Colombier break;
5641052a86aSDavid du Colombier
5651052a86aSDavid du Colombier case GREY4:
5661052a86aSDavid du Colombier case GREY8:
5671052a86aSDavid du Colombier rv = writeimage(fd, image, 0); /* dolock? */
5681052a86aSDavid du Colombier break;
5691052a86aSDavid du Colombier }
5701052a86aSDavid du Colombier
5711052a86aSDavid du Colombier if(outfile)
5721052a86aSDavid du Colombier close(fd);
5731052a86aSDavid du Colombier return rv;
5741052a86aSDavid du Colombier }
5751052a86aSDavid du Colombier
5761052a86aSDavid du Colombier void
room(Rectangle out,Rectangle in,int * a)5771052a86aSDavid du Colombier room(Rectangle out, Rectangle in, int *a)
5781052a86aSDavid du Colombier {
5791052a86aSDavid du Colombier a[Left] = out.min.x - in.min.x;
5801052a86aSDavid du Colombier a[Right] = out.max.x - in.max.x;
5811052a86aSDavid du Colombier a[Top] = out.min.y - in.min.y;
5821052a86aSDavid du Colombier a[Bottom] = out.max.y - in.max.y;
5831052a86aSDavid du Colombier }
5841052a86aSDavid du Colombier
5851052a86aSDavid du Colombier int
min(int a,int b)5861052a86aSDavid du Colombier min(int a, int b)
5871052a86aSDavid du Colombier {
5881052a86aSDavid du Colombier if(a < b)
5891052a86aSDavid du Colombier return a;
5901052a86aSDavid du Colombier return b;
5911052a86aSDavid du Colombier }
5921052a86aSDavid du Colombier
5931052a86aSDavid du Colombier int
max(int a,int b)5941052a86aSDavid du Colombier max(int a, int b)
5951052a86aSDavid du Colombier {
5961052a86aSDavid du Colombier if(a > b)
5971052a86aSDavid du Colombier return a;
5981052a86aSDavid du Colombier return b;
5991052a86aSDavid du Colombier }
6001052a86aSDavid du Colombier
6011052a86aSDavid du Colombier int
move(Rectangle r,Rectangle picr,Point d,int k,Rectangle * rp)6021052a86aSDavid du Colombier move(Rectangle r, Rectangle picr, Point d, int k, Rectangle *rp)
6031052a86aSDavid du Colombier {
6041052a86aSDavid du Colombier int a[4], i;
6051052a86aSDavid du Colombier Rectangle oldr;
6061052a86aSDavid du Colombier static int toggle;
6071052a86aSDavid du Colombier
6081052a86aSDavid du Colombier oldr = r;
6091052a86aSDavid du Colombier room(picr, r, a);
6101052a86aSDavid du Colombier switch(k){
6111052a86aSDavid du Colombier case RTopLeft:
6121052a86aSDavid du Colombier i = (d.x+d.y)/2;
6131052a86aSDavid du Colombier if(i>=Dx(r) || i>=Dy(r))
6141052a86aSDavid du Colombier break;
6151052a86aSDavid du Colombier i = max(i, a[Left]);
6161052a86aSDavid du Colombier i = max(i, a[Top]);
6171052a86aSDavid du Colombier r.min.x += i;
6181052a86aSDavid du Colombier r.min.y += i;
6191052a86aSDavid du Colombier break;
6201052a86aSDavid du Colombier case RTop:
6211052a86aSDavid du Colombier i = d.y;
6221052a86aSDavid du Colombier if(i < 0){
6231052a86aSDavid du Colombier /*
6241052a86aSDavid du Colombier * should really check i/2, but this is safe and feedback
6251052a86aSDavid du Colombier * makes the control feel right
6261052a86aSDavid du Colombier */
6271052a86aSDavid du Colombier i = -min(-i, a[Right]);
6281052a86aSDavid du Colombier i = max(i, a[Left]);
6291052a86aSDavid du Colombier }
6301052a86aSDavid du Colombier i = max(i, a[Top]);
6311052a86aSDavid du Colombier if(i >= Dy(r))
6321052a86aSDavid du Colombier break;
6331052a86aSDavid du Colombier r.min.y += i;
6341052a86aSDavid du Colombier /* divide the half bit equally */
6351052a86aSDavid du Colombier toggle = 1-toggle;
6361052a86aSDavid du Colombier if(toggle){
6371052a86aSDavid du Colombier r.min.x += i/2;
6381052a86aSDavid du Colombier r.max.x = r.min.x+Dy(r);
6391052a86aSDavid du Colombier }else{
6401052a86aSDavid du Colombier r.max.x -= i/2;
6411052a86aSDavid du Colombier r.min.x = r.max.x-Dy(r);
6421052a86aSDavid du Colombier }
6431052a86aSDavid du Colombier break;
6441052a86aSDavid du Colombier case RTopRight:
6451052a86aSDavid du Colombier i = (-d.x+d.y)/2;
6461052a86aSDavid du Colombier if(i>=Dx(r) || i>=Dy(r))
6471052a86aSDavid du Colombier break;
6481052a86aSDavid du Colombier i = -min(-i, a[Right]);
6491052a86aSDavid du Colombier i = max(i, a[Top]);
6501052a86aSDavid du Colombier r.max.x -= i;
6511052a86aSDavid du Colombier r.min.y += i;
6521052a86aSDavid du Colombier break;
6531052a86aSDavid du Colombier case RLeft:
6541052a86aSDavid du Colombier i = d.x;
6551052a86aSDavid du Colombier if(i < 0){
6561052a86aSDavid du Colombier i = -min(-i, a[Bottom]);
6571052a86aSDavid du Colombier i = max(i, a[Top]);
6581052a86aSDavid du Colombier }
6591052a86aSDavid du Colombier i = max(i, a[Left]);
6601052a86aSDavid du Colombier if(i >= Dx(r))
6611052a86aSDavid du Colombier break;
6621052a86aSDavid du Colombier r.min.x += i;
6631052a86aSDavid du Colombier /* divide the half bit equally */
6641052a86aSDavid du Colombier toggle = 1-toggle;
6651052a86aSDavid du Colombier if(toggle){
6661052a86aSDavid du Colombier r.min.y += i/2;
6671052a86aSDavid du Colombier r.max.y = r.min.y+Dx(r);
6681052a86aSDavid du Colombier }else{
6691052a86aSDavid du Colombier r.max.y -= i/2;
6701052a86aSDavid du Colombier r.min.y = r.max.y-Dx(r);
6711052a86aSDavid du Colombier }
6721052a86aSDavid du Colombier break;
6731052a86aSDavid du Colombier case RMiddle:
6741052a86aSDavid du Colombier if(d.x >= 0)
6751052a86aSDavid du Colombier d.x = min(d.x, a[Right]);
6761052a86aSDavid du Colombier else
6771052a86aSDavid du Colombier d.x = max(d.x, a[Left]);
6781052a86aSDavid du Colombier if(d.y >= 0)
6791052a86aSDavid du Colombier d.y = min(d.y, a[Bottom]);
6801052a86aSDavid du Colombier else
6811052a86aSDavid du Colombier d.y = max(d.y, a[Top]);
6821052a86aSDavid du Colombier r = rectaddpt(r, d);
6831052a86aSDavid du Colombier break;
6841052a86aSDavid du Colombier case RRight:
6851052a86aSDavid du Colombier i = d.x;
6861052a86aSDavid du Colombier if(i > 0){
6871052a86aSDavid du Colombier i = min(i, a[Bottom]);
6881052a86aSDavid du Colombier i = -max(-i, a[Top]);
6891052a86aSDavid du Colombier }
6901052a86aSDavid du Colombier i = min(i, a[Right]);
6911052a86aSDavid du Colombier if(-i >= Dx(r))
6921052a86aSDavid du Colombier break;
6931052a86aSDavid du Colombier r.max.x += i;
6941052a86aSDavid du Colombier /* divide the half bit equally */
6951052a86aSDavid du Colombier toggle = 1-toggle;
6961052a86aSDavid du Colombier if(toggle){
6971052a86aSDavid du Colombier r.min.y -= i/2;
6981052a86aSDavid du Colombier r.max.y = r.min.y+Dx(r);
6991052a86aSDavid du Colombier }else{
7001052a86aSDavid du Colombier r.max.y += i/2;
7011052a86aSDavid du Colombier r.min.y = r.max.y-Dx(r);
7021052a86aSDavid du Colombier }
7031052a86aSDavid du Colombier break;
7041052a86aSDavid du Colombier case RBotLeft:
7051052a86aSDavid du Colombier i = (d.x+-d.y)/2;
7061052a86aSDavid du Colombier if(i>=Dx(r) || i>=Dy(r))
7071052a86aSDavid du Colombier break;
7081052a86aSDavid du Colombier i = max(i, a[Left]);
7091052a86aSDavid du Colombier i = -min(-i, a[Bottom]);
7101052a86aSDavid du Colombier r.min.x += i;
7111052a86aSDavid du Colombier r.max.y -= i;
7121052a86aSDavid du Colombier break;
7131052a86aSDavid du Colombier case RBot:
7141052a86aSDavid du Colombier i = d.y;
7151052a86aSDavid du Colombier if(i > 0){
7161052a86aSDavid du Colombier i = min(i, a[Right]);
7171052a86aSDavid du Colombier i = -max(-i, a[Left]);
7181052a86aSDavid du Colombier }
7191052a86aSDavid du Colombier i = min(i, a[Bottom]);
7201052a86aSDavid du Colombier if(i >= Dy(r))
7211052a86aSDavid du Colombier break;
7221052a86aSDavid du Colombier r.max.y += i;
7231052a86aSDavid du Colombier /* divide the half bit equally */
7241052a86aSDavid du Colombier toggle = 1-toggle;
7251052a86aSDavid du Colombier if(toggle){
7261052a86aSDavid du Colombier r.min.x -= i/2;
7271052a86aSDavid du Colombier r.max.x = r.min.x+Dy(r);
7281052a86aSDavid du Colombier }else{
7291052a86aSDavid du Colombier r.max.x += i/2;
7301052a86aSDavid du Colombier r.min.x = r.max.x-Dy(r);
7311052a86aSDavid du Colombier }
7321052a86aSDavid du Colombier break;
7331052a86aSDavid du Colombier case RBotRight:
7341052a86aSDavid du Colombier i = (-d.x+-d.y)/2;
7351052a86aSDavid du Colombier if(i>=Dx(r) || i>=Dy(r))
7361052a86aSDavid du Colombier break;
7371052a86aSDavid du Colombier i = -min(-i, a[Right]);
7381052a86aSDavid du Colombier i = -min(-i, a[Bottom]);
7391052a86aSDavid du Colombier r.max.x -= i;
7401052a86aSDavid du Colombier r.max.y -= i;
7411052a86aSDavid du Colombier break;
7421052a86aSDavid du Colombier }
7431052a86aSDavid du Colombier if(Dx(r)<3 || Dy(r)<3){
7441052a86aSDavid du Colombier *rp = oldr;
7451052a86aSDavid du Colombier return 0;
7461052a86aSDavid du Colombier }
7471052a86aSDavid du Colombier *rp = r;
7481052a86aSDavid du Colombier return !eqrect(r, oldr);
7491052a86aSDavid du Colombier }
7501052a86aSDavid du Colombier
7511052a86aSDavid du Colombier void
rlist(Rectangle r,Rectangle * ra)7521052a86aSDavid du Colombier rlist(Rectangle r, Rectangle *ra)
7531052a86aSDavid du Colombier {
7541052a86aSDavid du Colombier Rectangle tr;
7551052a86aSDavid du Colombier
7561052a86aSDavid du Colombier tr = r;
7571052a86aSDavid du Colombier tr.max.y = r.min.y+Dy(r)/4;
7581052a86aSDavid du Colombier ra[0] = tr;
7591052a86aSDavid du Colombier ra[0].max.x = tr.min.x+Dx(tr)/4;
7601052a86aSDavid du Colombier ra[1] = tr;
7611052a86aSDavid du Colombier ra[1].min.x = ra[0].max.x;
7621052a86aSDavid du Colombier ra[1].max.x = tr.max.x-Dx(tr)/4;
7631052a86aSDavid du Colombier ra[2] = tr;
7641052a86aSDavid du Colombier ra[2].min.x = ra[1].max.x;
7651052a86aSDavid du Colombier
7661052a86aSDavid du Colombier tr.min.y = tr.max.y;
7671052a86aSDavid du Colombier tr.max.y = r.max.y-Dy(r)/4;
7681052a86aSDavid du Colombier ra[3] = tr;
7691052a86aSDavid du Colombier ra[3].max.x = tr.min.x+Dx(tr)/4;
7701052a86aSDavid du Colombier ra[4] = tr;
7711052a86aSDavid du Colombier ra[4].min.x = ra[3].max.x;
7721052a86aSDavid du Colombier ra[4].max.x = tr.max.x-Dx(tr)/4;
7731052a86aSDavid du Colombier ra[5] = tr;
7741052a86aSDavid du Colombier ra[5].min.x = ra[4].max.x;
7751052a86aSDavid du Colombier
7761052a86aSDavid du Colombier tr.min.y = tr.max.y;
7771052a86aSDavid du Colombier tr.max.y = r.max.y;
7781052a86aSDavid du Colombier ra[6] = tr;
7791052a86aSDavid du Colombier ra[6].max.x = tr.min.x+Dx(tr)/4;
7801052a86aSDavid du Colombier ra[7] = tr;
7811052a86aSDavid du Colombier ra[7].min.x = ra[6].max.x;
7821052a86aSDavid du Colombier ra[7].max.x = tr.max.x-Dx(tr)/4;
7831052a86aSDavid du Colombier ra[8] = tr;
7841052a86aSDavid du Colombier ra[8].min.x = ra[7].max.x;
7851052a86aSDavid du Colombier }
7861052a86aSDavid du Colombier
7871052a86aSDavid du Colombier int
abs(int a)7881052a86aSDavid du Colombier abs(int a)
7891052a86aSDavid du Colombier {
7901052a86aSDavid du Colombier if(a < 0)
7911052a86aSDavid du Colombier return -a;
7921052a86aSDavid du Colombier return a;
7931052a86aSDavid du Colombier }
7941052a86aSDavid du Colombier
7951052a86aSDavid du Colombier void
usage(void)7961052a86aSDavid du Colombier usage(void)
7971052a86aSDavid du Colombier {
7981052a86aSDavid du Colombier fprint(2, "usage: mug [file.bit]\n");
7991052a86aSDavid du Colombier exits("usage");
8001052a86aSDavid du Colombier }
8011052a86aSDavid du Colombier
8021052a86aSDavid du Colombier void
eresized(int new)8031052a86aSDavid du Colombier eresized(int new)
8041052a86aSDavid du Colombier {
8051052a86aSDavid du Colombier if(new && getwindow(display, Refmesg) < 0)
8061052a86aSDavid du Colombier fprint(2,"can't reattach to window");
8071052a86aSDavid du Colombier drawscreen(1);
8081052a86aSDavid du Colombier
8091052a86aSDavid du Colombier }
8101052a86aSDavid du Colombier
8111052a86aSDavid du Colombier /*
8121052a86aSDavid du Colombier interface notes
8131052a86aSDavid du Colombier
8141052a86aSDavid du Colombier cursor changes while in rbig to indicate region.
8151052a86aSDavid du Colombier only button 1 works for resizing region
8161052a86aSDavid du Colombier only button 1 works for moving thingy in ramp
8171052a86aSDavid du Colombier
8181052a86aSDavid du Colombier button-3 menu: Reset, Depth, Undo, Save, Write
8191052a86aSDavid du Colombier */
8201052a86aSDavid du Colombier
8211052a86aSDavid du Colombier Cursor tl = {
8221052a86aSDavid du Colombier {-4, -4},
8231052a86aSDavid du Colombier {0xfe, 0x00, 0x82, 0x00, 0x8c, 0x00, 0x87, 0xff,
8241052a86aSDavid du Colombier 0xa0, 0x01, 0xb0, 0x01, 0xd0, 0x01, 0x11, 0xff,
8251052a86aSDavid du Colombier 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
8261052a86aSDavid du Colombier 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x1f, 0x00, },
8271052a86aSDavid du Colombier {0x00, 0x00, 0x7c, 0x00, 0x70, 0x00, 0x78, 0x00,
8281052a86aSDavid du Colombier 0x5f, 0xfe, 0x4f, 0xfe, 0x0f, 0xfe, 0x0e, 0x00,
8291052a86aSDavid du Colombier 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
8301052a86aSDavid du Colombier 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, }
8311052a86aSDavid du Colombier };
8321052a86aSDavid du Colombier
8331052a86aSDavid du Colombier Cursor t = {
8341052a86aSDavid du Colombier {-7, -8},
8351052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x06, 0xc0,
8361052a86aSDavid du Colombier 0x1c, 0x70, 0x10, 0x10, 0x0c, 0x60, 0xfc, 0x7f,
8371052a86aSDavid du Colombier 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff,
8381052a86aSDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
8391052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
8401052a86aSDavid du Colombier 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, 0x03, 0x80,
8411052a86aSDavid du Colombier 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x00, 0x00,
8421052a86aSDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
8431052a86aSDavid du Colombier };
8441052a86aSDavid du Colombier
8451052a86aSDavid du Colombier Cursor tr = {
8461052a86aSDavid du Colombier {-11, -4},
8471052a86aSDavid du Colombier {0x00, 0x7f, 0x00, 0x41, 0x00, 0x31, 0xff, 0xe1,
8481052a86aSDavid du Colombier 0x80, 0x05, 0x80, 0x0d, 0x80, 0x0b, 0xff, 0x88,
8491052a86aSDavid du Colombier 0x00, 0x88, 0x0, 0x88, 0x00, 0x88, 0x00, 0x88,
8501052a86aSDavid du Colombier 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xf8, },
8511052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x3e, 0x00, 0x0e, 0x00, 0x1e,
8521052a86aSDavid du Colombier 0x7f, 0xfa, 0x7f, 0xf2, 0x7f, 0xf0, 0x00, 0x70,
8531052a86aSDavid du Colombier 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
8541052a86aSDavid du Colombier 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, }
8551052a86aSDavid du Colombier };
8561052a86aSDavid du Colombier
8571052a86aSDavid du Colombier Cursor r = {
8581052a86aSDavid du Colombier {-8, -7},
8591052a86aSDavid du Colombier {0x07, 0xc0, 0x04, 0x40, 0x04, 0x40, 0x04, 0x58,
8601052a86aSDavid du Colombier 0x04, 0x68, 0x04, 0x6c, 0x04, 0x06, 0x04, 0x02,
8611052a86aSDavid du Colombier 0x04, 0x06, 0x04, 0x6c, 0x04, 0x68, 0x04, 0x58,
8621052a86aSDavid du Colombier 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x07, 0xc0, },
8631052a86aSDavid du Colombier {0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80,
8641052a86aSDavid du Colombier 0x03, 0x90, 0x03, 0x90, 0x03, 0xf8, 0x03, 0xfc,
8651052a86aSDavid du Colombier 0x03, 0xf8, 0x03, 0x90, 0x03, 0x90, 0x03, 0x80,
8661052a86aSDavid du Colombier 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
8671052a86aSDavid du Colombier };
8681052a86aSDavid du Colombier
8691052a86aSDavid du Colombier Cursor br = {
8701052a86aSDavid du Colombier {-11, -11},
8711052a86aSDavid du Colombier {0x00, 0xf8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88,
8721052a86aSDavid du Colombier 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88,
8731052a86aSDavid du Colombier 0xff, 0x88, 0x80, 0x0b, 0x80, 0x0d, 0x80, 0x05,
8741052a86aSDavid du Colombier 0xff, 0xe1, 0x00, 0x31, 0x00, 0x41, 0x00, 0x7f, },
8751052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
8761052a86aSDavid du Colombier 0x0, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
8771052a86aSDavid du Colombier 0x00, 0x70, 0x7f, 0xf0, 0x7f, 0xf2, 0x7f, 0xfa,
8781052a86aSDavid du Colombier 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x3e, 0x00, 0x00, }
8791052a86aSDavid du Colombier };
8801052a86aSDavid du Colombier
8811052a86aSDavid du Colombier Cursor b = {
8821052a86aSDavid du Colombier {-7, -7},
8831052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8841052a86aSDavid du Colombier 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
8851052a86aSDavid du Colombier 0xfc, 0x7f, 0x0c, 0x60, 0x10, 0x10, 0x1c, 0x70,
8861052a86aSDavid du Colombier 0x06, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, },
8871052a86aSDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8881052a86aSDavid du Colombier 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe,
8891052a86aSDavid du Colombier 0x03, 0x80, 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80,
8901052a86aSDavid du Colombier 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
8911052a86aSDavid du Colombier };
8921052a86aSDavid du Colombier
8931052a86aSDavid du Colombier Cursor bl = {
8941052a86aSDavid du Colombier {-4, -11},
8951052a86aSDavid du Colombier {0x1f, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
8961052a86aSDavid du Colombier 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00,
8971052a86aSDavid du Colombier 0x11, 0xff, 0xd0, 0x01, 0xb0, 0x01, 0xa0, 0x01,
8981052a86aSDavid du Colombier 0x87, 0xff, 0x8c, 0x00, 0x82, 0x00, 0xfe, 0x00, },
8991052a86aSDavid du Colombier {0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
9001052a86aSDavid du Colombier 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00,
9011052a86aSDavid du Colombier 0x0e, 0x00, 0x0f, 0xfe, 0x4f, 0xfe, 0x5f, 0xfe,
9021052a86aSDavid du Colombier 0x78, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x00, 0x0, }
9031052a86aSDavid du Colombier };
9041052a86aSDavid du Colombier
9051052a86aSDavid du Colombier Cursor l = {
9061052a86aSDavid du Colombier {-7, -7},
9071052a86aSDavid du Colombier {0x03, 0xe0, 0x02, 0x20, 0x02, 0x20, 0x1a, 0x20,
9081052a86aSDavid du Colombier 0x16, 0x20, 0x36, 0x20, 0x60, 0x20, 0x40, 0x20,
9091052a86aSDavid du Colombier 0x60, 0x20, 0x36, 0x20, 0x16, 0x20, 0x1a, 0x20,
9101052a86aSDavid du Colombier 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x03, 0xe0, },
9111052a86aSDavid du Colombier {0x00, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
9121052a86aSDavid du Colombier 0x09, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0,
9131052a86aSDavid du Colombier 0x1f, 0xc0, 0x09, 0xc0, 0x09, 0xc0, 0x01, 0xc0,
9141052a86aSDavid du Colombier 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, }
9151052a86aSDavid du Colombier };
9161052a86aSDavid du Colombier
9171052a86aSDavid du Colombier Cursor boxcursor = {
9181052a86aSDavid du Colombier {-7, -7},
9191052a86aSDavid du Colombier {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
9201052a86aSDavid du Colombier 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
9211052a86aSDavid du Colombier 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
9221052a86aSDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
9231052a86aSDavid du Colombier {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
9241052a86aSDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
9251052a86aSDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
9261052a86aSDavid du Colombier 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, }
9271052a86aSDavid du Colombier };
9281052a86aSDavid du Colombier
9291052a86aSDavid du Colombier Cursor clearcursor;
9301052a86aSDavid du Colombier
9311052a86aSDavid du Colombier Cursor *corners[10] = {
9321052a86aSDavid du Colombier &tl, &t, &tr,
9331052a86aSDavid du Colombier &l, &boxcursor, &r,
9341052a86aSDavid du Colombier &bl, &b, &br,
9351052a86aSDavid du Colombier nil, /* default arrow */
9361052a86aSDavid du Colombier };
9371052a86aSDavid du Colombier
9381052a86aSDavid du Colombier char *item[] = {
9391052a86aSDavid du Colombier "Reset",
9401052a86aSDavid du Colombier "Depth",
9411052a86aSDavid du Colombier "Undo",
9421052a86aSDavid du Colombier "Write",
9431052a86aSDavid du Colombier "Exit",
9441052a86aSDavid du Colombier nil
9451052a86aSDavid du Colombier };
9461052a86aSDavid du Colombier
9471052a86aSDavid du Colombier Menu menu = {
9481052a86aSDavid du Colombier item,
9491052a86aSDavid du Colombier nil,
9501052a86aSDavid du Colombier 2
9511052a86aSDavid du Colombier };
9521052a86aSDavid du Colombier
9531052a86aSDavid du Colombier /*BUG make less flashy */
9541052a86aSDavid du Colombier void
moveface(Image * back,Point lastp,Image * face,Point p,Point d)9551052a86aSDavid du Colombier moveface(Image *back, Point lastp, Image *face, Point p, Point d)
9561052a86aSDavid du Colombier {
9571052a86aSDavid du Colombier draw(screen, rectaddpt(back->r, subpt(lastp, d)), back, nil, back->r.min);
9581052a86aSDavid du Colombier draw(back, back->r, screen, nil, addpt(back->r.min, subpt(p, d)));
9591052a86aSDavid du Colombier border(screen, rectaddpt(face->r, subpt(p, d)),
9601052a86aSDavid du Colombier -1, display->black, ZP);
9611052a86aSDavid du Colombier draw(screen, rectaddpt(face->r, subpt(p, d)),
9621052a86aSDavid du Colombier face, nil, face->r.min);
9631052a86aSDavid du Colombier }
9641052a86aSDavid du Colombier
9651052a86aSDavid du Colombier int
dragface(Mouse * m,Image * im,Point d,int x)9661052a86aSDavid du Colombier dragface(Mouse *m, Image *im, Point d, int x)
9671052a86aSDavid du Colombier {
9681052a86aSDavid du Colombier int i;
9691052a86aSDavid du Colombier Point lastp;
9701052a86aSDavid du Colombier static Image *back;
9711052a86aSDavid du Colombier
9721052a86aSDavid du Colombier if(back == nil){
9731052a86aSDavid du Colombier back = allocimage(display, Rect(-1,-1,49,49), display->image->chan, 0, DNofill);
9741052a86aSDavid du Colombier if(back == nil)
9751052a86aSDavid du Colombier sysfatal("dragface backing store: %r");
9761052a86aSDavid du Colombier }
9771052a86aSDavid du Colombier
9781052a86aSDavid du Colombier lastp = m->xy;
9791052a86aSDavid du Colombier draw(back, back->r, screen, nil, addpt(back->r.min, subpt(lastp, d)));
9801052a86aSDavid du Colombier esetcursor(&clearcursor);
9811052a86aSDavid du Colombier do{
9821052a86aSDavid du Colombier moveface(back, lastp, im, m->xy, d);
9831052a86aSDavid du Colombier lastp = m->xy;
9841052a86aSDavid du Colombier }while(*m=emouse(), m->buttons==1);
9851052a86aSDavid du Colombier
9861052a86aSDavid du Colombier draw(screen, rectaddpt(back->r, subpt(lastp, d)), back, nil, back->r.min);
9871052a86aSDavid du Colombier esetcursor(nil);
9881052a86aSDavid du Colombier if(m->buttons==0){
9891052a86aSDavid du Colombier for(i=0; i<nelem(face); i++)
9901052a86aSDavid du Colombier if(ptinrect(m->xy, rface[i]))
9911052a86aSDavid du Colombier return i;
9921052a86aSDavid du Colombier if(ptinrect(m->xy, rsmall))
9931052a86aSDavid du Colombier return -1;
9941052a86aSDavid du Colombier return x;
9951052a86aSDavid du Colombier }
9961052a86aSDavid du Colombier while(*m=emouse(), m->buttons)
9971052a86aSDavid du Colombier ;
9981052a86aSDavid du Colombier return x;
9991052a86aSDavid du Colombier }
10001052a86aSDavid du Colombier
10011052a86aSDavid du Colombier void
initstate(void)10021052a86aSDavid du Colombier initstate(void)
10031052a86aSDavid du Colombier {
10041052a86aSDavid du Colombier state.black = 0.0;
10051052a86aSDavid du Colombier state.white = 1.0;
10061052a86aSDavid du Colombier state.stretch = 1.0;
10071052a86aSDavid du Colombier state.depth = 4;
10081052a86aSDavid du Colombier state.gamma = 1.0;
10091052a86aSDavid du Colombier setgtab(&state);
10101052a86aSDavid du Colombier state.selr = insetrect(orig->r, 5);
10111052a86aSDavid du Colombier sdx = Dx(state.selr);
10121052a86aSDavid du Colombier sdy = Dy(state.selr);
10131052a86aSDavid du Colombier if(sdx > sdy)
10141052a86aSDavid du Colombier state.selr.max.x = state.selr.min.x+sdy;
10151052a86aSDavid du Colombier else
10161052a86aSDavid du Colombier state.selr.max.y = state.selr.min.y+sdx;
10171052a86aSDavid du Colombier }
10181052a86aSDavid du Colombier
10191052a86aSDavid du Colombier void
main(int argc,char ** argv)10201052a86aSDavid du Colombier main(int argc, char **argv)
10211052a86aSDavid du Colombier {
10221052a86aSDavid du Colombier int ccursor, i, fd, k, n, y;
10231052a86aSDavid du Colombier uchar *data;
10241052a86aSDavid du Colombier double gammatab[256];
10251052a86aSDavid du Colombier Event e;
10261052a86aSDavid du Colombier Mouse m;
10271052a86aSDavid du Colombier Point lastp, p;
10281052a86aSDavid du Colombier Rectangle nselr, rbig9[9];
10291052a86aSDavid du Colombier
10301052a86aSDavid du Colombier ARGBEGIN{
10311052a86aSDavid du Colombier default:
10321052a86aSDavid du Colombier usage();
10331052a86aSDavid du Colombier }ARGEND
10341052a86aSDavid du Colombier
10351052a86aSDavid du Colombier if(argc > 1)
10361052a86aSDavid du Colombier usage();
10371052a86aSDavid du Colombier if(argc == 1){
10381052a86aSDavid du Colombier if((fd = open(argv[0], OREAD)) < 0)
10391052a86aSDavid du Colombier sysfatal("open %s: %r", argv[0]);
10401052a86aSDavid du Colombier }else
10411052a86aSDavid du Colombier fd = 0;
10421052a86aSDavid du Colombier
1043*72061b92SDavid du Colombier if (initdraw(0, 0, "mug") < 0)
1044*72061b92SDavid du Colombier sysfatal("initdraw failed");
10451052a86aSDavid du Colombier
10461052a86aSDavid du Colombier if((orig = readimage(display, fd, 0)) == nil)
10471052a86aSDavid du Colombier sysfatal("readimage: %r");
10481052a86aSDavid du Colombier
10491052a86aSDavid du Colombier orig = grey8image(orig);
10501052a86aSDavid du Colombier
10511052a86aSDavid du Colombier initramp();
10521052a86aSDavid du Colombier initclamp();
10531052a86aSDavid du Colombier initval2cmap();
10541052a86aSDavid du Colombier bkgd = allocimagemix(display, DPaleyellow, DWhite);
10551052a86aSDavid du Colombier small = allocimage(display, Rect(0,0,48,48), GREY4, 0, DWhite);
10561052a86aSDavid du Colombier tmp8 = allocimage(display, Rect(0,0,48,48), GREY8, 0, DWhite);
10571052a86aSDavid du Colombier red = allocimage(display, Rect(0,0,1,1), display->image->chan, 1, DRed);
10581052a86aSDavid du Colombier green = allocimage(display, Rect(0,0,1,1), display->image->chan, 1, DGreen);
10591052a86aSDavid du Colombier blue = allocimage(display, Rect(0,0,1,1), display->image->chan, 1, DBlue);
10601052a86aSDavid du Colombier if(bkgd==nil || small==nil || tmp8==nil || red==nil || green==nil || blue==nil)
10611052a86aSDavid du Colombier sysfatal("allocimage: %r");
10621052a86aSDavid du Colombier
10631052a86aSDavid du Colombier n = Dx(orig->r)*Dy(orig->r);
10641052a86aSDavid du Colombier data = emalloc(n*sizeof data[0]);
10651052a86aSDavid du Colombier rdata = emalloc(n*sizeof rdata[0]);
10661052a86aSDavid du Colombier
10671052a86aSDavid du Colombier if(unloadimage(orig, orig->r, data, n) != n)
10681052a86aSDavid du Colombier sysfatal("unloadimage: %r");
10691052a86aSDavid du Colombier
10701052a86aSDavid du Colombier for(i=0; i<256; i++)
10711052a86aSDavid du Colombier gammatab[i] = pow((255-i)/(double)255.0, GAMMA);
10721052a86aSDavid du Colombier
10731052a86aSDavid du Colombier for(i=0; i<n; i++)
10741052a86aSDavid du Colombier rdata[i] = gammatab[255-data[i]];
10751052a86aSDavid du Colombier
10761052a86aSDavid du Colombier initstate();
10771052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
10781052a86aSDavid du Colombier drawscreen(1);
10791052a86aSDavid du Colombier flushimage(display, 1);
10801052a86aSDavid du Colombier einit(Emouse|Ekeyboard);
10811052a86aSDavid du Colombier ccursor = 9;
10821052a86aSDavid du Colombier for(;;){
10831052a86aSDavid du Colombier if((n=eread(Emouse|Ekeyboard, &e))==Ekeyboard)
10841052a86aSDavid du Colombier continue;
10851052a86aSDavid du Colombier if(n != Emouse)
10861052a86aSDavid du Colombier break;
10871052a86aSDavid du Colombier
10881052a86aSDavid du Colombier m = e.mouse;
10891052a86aSDavid du Colombier if(m.buttons&4){
10901052a86aSDavid du Colombier ccursor = 9;
10911052a86aSDavid du Colombier esetcursor(corners[ccursor]);
10921052a86aSDavid du Colombier switch(emenuhit(3, &m, &menu)){
10931052a86aSDavid du Colombier case -1:
10941052a86aSDavid du Colombier continue;
10951052a86aSDavid du Colombier case 0: /* Reset */
10961052a86aSDavid du Colombier mark();
10971052a86aSDavid du Colombier initstate();
10981052a86aSDavid du Colombier small = allocimage(display, Rect(0,0,48,48), CHAN1(CGrey, state.depth), 0, DWhite);
10991052a86aSDavid du Colombier if(small == nil)
11001052a86aSDavid du Colombier sysfatal("allocimage: %r");
11011052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
11021052a86aSDavid du Colombier drawface(-1);
11031052a86aSDavid du Colombier drawscreen(0);
11041052a86aSDavid du Colombier break;
11051052a86aSDavid du Colombier case 1: /* Depth */
11061052a86aSDavid du Colombier mark();
11071052a86aSDavid du Colombier /* osmall = small, so no freeimage */
11081052a86aSDavid du Colombier state.depth /= 2;
11091052a86aSDavid du Colombier if(state.depth == 0)
11101052a86aSDavid du Colombier state.depth = 8;
11111052a86aSDavid du Colombier small = allocimage(display, Rect(0,0,48,48), CHAN1(CGrey, state.depth), 0, DWhite);
11121052a86aSDavid du Colombier if(small == nil)
11131052a86aSDavid du Colombier sysfatal("allocimage: %r");
11141052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
11151052a86aSDavid du Colombier drawface(-1);
11161052a86aSDavid du Colombier break;
11171052a86aSDavid du Colombier case 2: /* Undo */
11181052a86aSDavid du Colombier undo();
11191052a86aSDavid du Colombier break;
11201052a86aSDavid du Colombier case 3: /* Write */
11211052a86aSDavid du Colombier writeface(nil, small);
11221052a86aSDavid du Colombier break;
11231052a86aSDavid du Colombier case 4: /* Exit */
11241052a86aSDavid du Colombier exits(nil);
11251052a86aSDavid du Colombier break;
11261052a86aSDavid du Colombier }
11271052a86aSDavid du Colombier }
11281052a86aSDavid du Colombier
11291052a86aSDavid du Colombier if(ptinrect(m.xy, rbig)){
11301052a86aSDavid du Colombier rlist(rectaddpt(state.selr, subpt(rbig.min, orig->r.min)), rbig9);
11311052a86aSDavid du Colombier for(i=0; i<9; i++)
11321052a86aSDavid du Colombier if(ptinrect(m.xy, rbig9[i]))
11331052a86aSDavid du Colombier break;
11341052a86aSDavid du Colombier if(i != ccursor){
11351052a86aSDavid du Colombier ccursor = i;
11361052a86aSDavid du Colombier esetcursor(corners[ccursor]);
11371052a86aSDavid du Colombier }
11381052a86aSDavid du Colombier if(i==9)
11391052a86aSDavid du Colombier continue;
11401052a86aSDavid du Colombier
11411052a86aSDavid du Colombier if(m.buttons & 1){
11421052a86aSDavid du Colombier mark();
11431052a86aSDavid du Colombier lastp = m.xy;
11441052a86aSDavid du Colombier while(m=emouse(), m.buttons&1){
11451052a86aSDavid du Colombier if(move(state.selr, orig->r, subpt(m.xy, lastp), i, &nselr)){
11461052a86aSDavid du Colombier moveframe(state.selr, nselr);
11471052a86aSDavid du Colombier state.selr = nselr;
11481052a86aSDavid du Colombier lastp = m.xy;
11491052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
11501052a86aSDavid du Colombier drawface(-1);
11511052a86aSDavid du Colombier }
11521052a86aSDavid du Colombier }
11531052a86aSDavid du Colombier }
11541052a86aSDavid du Colombier continue;
11551052a86aSDavid du Colombier }
11561052a86aSDavid du Colombier
11571052a86aSDavid du Colombier if(ccursor != 9){ /* default cursor */
11581052a86aSDavid du Colombier ccursor = 9;
11591052a86aSDavid du Colombier esetcursor(corners[ccursor]);
11601052a86aSDavid du Colombier }
11611052a86aSDavid du Colombier
11621052a86aSDavid du Colombier if(ptinrect(m.xy, rramp)){
11631052a86aSDavid du Colombier if(m.buttons != 1)
11641052a86aSDavid du Colombier continue;
11651052a86aSDavid du Colombier mark();
11661052a86aSDavid du Colombier y = gamma2y(state.gamma);
11671052a86aSDavid du Colombier if(abs(y-(m.xy.y-rramp.min.y)) > 5)
11681052a86aSDavid du Colombier continue;
11691052a86aSDavid du Colombier k = section(m.xy.x-rramp.min.x);
11701052a86aSDavid du Colombier drawrampbar(green, &state);
11711052a86aSDavid du Colombier lastp = m.xy;
11721052a86aSDavid du Colombier while(m=emouse(), m.buttons&1){
11731052a86aSDavid du Colombier if(!ptinrect(m.xy, rramp))
11741052a86aSDavid du Colombier continue;
11751052a86aSDavid du Colombier switch(k){
11761052a86aSDavid du Colombier case -1:
11771052a86aSDavid du Colombier continue;
11781052a86aSDavid du Colombier case 0:
11791052a86aSDavid du Colombier if((m.xy.x-rramp.min.x)/255.0 < state.white){
11801052a86aSDavid du Colombier state.black = (m.xy.x-rramp.min.x)/255.0;
11811052a86aSDavid du Colombier break;
11821052a86aSDavid du Colombier }
11831052a86aSDavid du Colombier continue;
11841052a86aSDavid du Colombier case 1:
11851052a86aSDavid du Colombier state.gamma = y2gamma(m.xy.y-rramp.min.y);
11861052a86aSDavid du Colombier setgtab(&state);
11871052a86aSDavid du Colombier break;
11881052a86aSDavid du Colombier case 2:
11891052a86aSDavid du Colombier if((m.xy.x-rramp.min.x)/255.0 > state.black){
11901052a86aSDavid du Colombier state.white = (m.xy.x-rramp.min.x)/255.0;
11911052a86aSDavid du Colombier break;
11921052a86aSDavid du Colombier }
11931052a86aSDavid du Colombier continue;
11941052a86aSDavid du Colombier case 10:
11951052a86aSDavid du Colombier state.black += (m.xy.x-lastp.x)/255.0;
11961052a86aSDavid du Colombier state.white += (m.xy.x-lastp.x)/255.0;
11971052a86aSDavid du Colombier state.gamma = y2gamma(p.y);
11981052a86aSDavid du Colombier break;
11991052a86aSDavid du Colombier }
12001052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
12011052a86aSDavid du Colombier drawface(-1);
12021052a86aSDavid du Colombier drawrampbar(green, &state);
12031052a86aSDavid du Colombier }
12041052a86aSDavid du Colombier if(m.buttons == 0){
12051052a86aSDavid du Colombier process(rdata, orig->r, state.selr, small);
12061052a86aSDavid du Colombier drawface(-1);
12071052a86aSDavid du Colombier drawrampbar(red, &state);
12081052a86aSDavid du Colombier }else
12091052a86aSDavid du Colombier undo();
12101052a86aSDavid du Colombier continue;
12111052a86aSDavid du Colombier }
12121052a86aSDavid du Colombier
12131052a86aSDavid du Colombier if(ptinrect(m.xy, rsmall)){
12141052a86aSDavid du Colombier if(m.buttons != 1)
12151052a86aSDavid du Colombier continue;
12161052a86aSDavid du Colombier n=dragface(&m, small, subpt(m.xy, rsmall.min), -1);
12171052a86aSDavid du Colombier if(n == -1)
12181052a86aSDavid du Colombier continue;
12191052a86aSDavid du Colombier saveface(nil, n);
12201052a86aSDavid du Colombier }
12211052a86aSDavid du Colombier
12221052a86aSDavid du Colombier for(i=0; i<nelem(face); i++)
12231052a86aSDavid du Colombier if(ptinrect(m.xy, rface[i]))
12241052a86aSDavid du Colombier break;
12251052a86aSDavid du Colombier if(i<nelem(face) && face[i] != nil){
12261052a86aSDavid du Colombier if(m.buttons != 1)
12271052a86aSDavid du Colombier continue;
12281052a86aSDavid du Colombier n=dragface(&m, face[i]->small, subpt(m.xy, rface[i].min), i);
12291052a86aSDavid du Colombier if(n == i)
12301052a86aSDavid du Colombier continue;
12311052a86aSDavid du Colombier saveface(face[i], n);
12321052a86aSDavid du Colombier continue;
12331052a86aSDavid du Colombier }
12341052a86aSDavid du Colombier
12351052a86aSDavid du Colombier do
12361052a86aSDavid du Colombier m = emouse();
12371052a86aSDavid du Colombier while(m.buttons==1);
12381052a86aSDavid du Colombier }
12391052a86aSDavid du Colombier exits(nil);
12401052a86aSDavid du Colombier }
1241