Beispiel #1
0
void
move(Point m)
{
	Point p, nm;
	int x, y;

	nm = subpt(m, screen->r.min);

	/* figure out where the click falls */
	p = pix2board(nm.x, nm.y);
	
	if(grid[p.x][p.y] >= 999)
		return;

	/* reset the board scores */
	grid[p.x][p.y] = 999;
	for(x = 0; x < SzX; x++)
		for(y = 0; y < SzY; y++)
			if(grid[x][y] != 999 && grid[x][y] != 1000)
				grid[x][y] = 100;
	
	nextglenda();
}
Beispiel #2
0
void
resize()
{
	Point p, q;
	Rectangle r;

	r = screen->r;
	draw(screen, r, light, nil, ZP);
	p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
		display->defaultfont, title);

	p.x = r.min.x+4;
	p.y += display->defaultfont->height+4;
	
	q = subpt(r.max, Pt(4,4));
	rbar = Rpt(p, q);
	border(screen, rbar, -2, dark, ZP);
	last = 0;
	lastp = -1;

	flushimage(display, 1);
	drawbar();	
}
Beispiel #3
0
/*
 * Translate the image in the window by delta.
 */
static void
translate(Point delta)
{
	Point u;
	Rectangle r, or;

	if(im == nil)
		return;

	u = pclip(addpt(ul, delta), ulrange);
	delta = subpt(u, ul);
	if(delta.x == 0 && delta.y == 0)
		return;

	/*
	 * The upper left corner of the image is currently at ul.
	 * We want to move it to u.
	 */
	or = rectaddpt(Rpt(ZP, Pt(Dx(im->r), Dy(im->r))), ul);
	r = rectaddpt(or, delta);

	drawop(screen, r, screen, nil, ul, S);
	ul = u;

	/* fill in gray where image used to be but isn't. */
	drawdiff(screen, insetrect(or, -2), insetrect(r, -2), gray, nil, ZP, S);

	/* fill in black border */
	drawdiff(screen, insetrect(r, -2), r, display->black, nil, ZP, S);

	/* fill in image where it used to be off the screen. */
	if(rectclip(&or, screen->r))
		drawdiff(screen, r, rectaddpt(or, delta), im, nil, im->r.min, S);
	else
		drawop(screen, r, im, nil, im->r.min, S);
	flushimage(display, 1);
}
Beispiel #4
0
void
drawscreen(int clear)
{
	int i;

	if(clear){
		geometry(screen->r);
		draw(screen, screen->r, bkgd, nil, ZP);
	}

	border(screen, rbig, -1, display->black, ZP);
	draw(screen, rbig, orig, nil, orig->r.min);

	border(screen, rramp, -1, display->black, ZP);
	draw(screen, rramp, ramp, nil, ramp->r.min);
	drawrampbar(red, &state);

	border(screen, rectaddpt(state.selr, subpt(rbig.min, orig->r.min)), -2, red, ZP);
	if(clear){
		drawface(-1);
		for(i=0; i<nelem(face); i++)
			drawface(i);
	}
}
Beispiel #5
0
static void polygon(int cnt[], double *pts[], Windrule w, int v) {
    Edge *edges, *ep, *nextep, **ylist, **eylist, **yp;
    Point p, q, p0, p1, p10;
    int i, dy, nbig, y, left, right, wind, nwind, nvert;
    int *cntp;
    double **ptsp, *xp;
    nvert=0;
    for(cntp=cnt; *cntp; cntp++) nvert+=*cntp;
    edges=(Edge *)malloc(nvert*sizeof(Edge));
    if(edges==0) {
NoSpace:
        sysfatal("polygon: no space");
    }
    ylist=(Edge **)malloc(Dy(screen->r)*sizeof(Edge *));
    if(ylist==0) goto NoSpace;
    eylist=ylist+Dy(screen->r);
    for(yp=ylist; yp!=eylist; yp++) *yp=0;
    ep=edges;
    for(cntp=cnt,ptsp=pts; *cntp; cntp++,ptsp++) {
        p.x=SCX((*ptsp)[*cntp*2-2]);
        p.y=SCY((*ptsp)[*cntp*2-1]);
        nvert=*cntp;
        for(xp=*ptsp,i=0; i!=nvert; xp+=2,i++) {
            q=p;
            p.x=SCX(xp[0]);
            p.y=SCY(xp[1]);
            if(p.y==q.y) continue;
            if(p.y<q.y) {
                p0=p;
                p1=q;
                ep->dwind=1;
            }
            else {
                p0=q;
                p1=p;
                ep->dwind=-1;
            }
            if(p1.y<=screen->r.min.y) continue;
            if(p0.y>=screen->r.max.y) continue;
            ep->p=p0;
            if(p1.y>screen->r.max.y)
                ep->maxy=screen->r.max.y;
            else
                ep->maxy=p1.y;
            p10=subpt(p1, p0);
            if(p10.x>=0) {
                ep->dx=p10.x/p10.y;
                ep->dx1=ep->dx+1;
            }
            else {
                p10.x=-p10.x;
                ep->dx=-(p10.x/p10.y); /* this nonsense rounds toward zero */
                ep->dx1=ep->dx-1;
            }
            ep->x=0;
            ep->num=p10.x%p10.y;
            ep->den=p10.y;
            if(ep->p.y<screen->r.min.y) {
                dy=screen->r.min.y-ep->p.y;
                ep->x+=dy*ep->num;
                nbig=ep->x/ep->den;
                ep->p.x+=ep->dx1*nbig+ep->dx*(dy-nbig);
                ep->x%=ep->den;
                ep->p.y=screen->r.min.y;
            }
            insert(ep, ylist+(ep->p.y-screen->r.min.y));
            ep++;
        }
    }
    left = 0;
    for(yp=ylist,y=screen->r.min.y; yp!=eylist; yp++,y++) {
        wind=0;
        for(ep=*yp; ep; ep=nextep) {
            nwind=wind+ep->dwind;
            if(nwind&w) {	/* inside */
                if(!(wind&w)) {
                    left=ep->p.x;
                    if(left<screen->r.min.x) left=screen->r.min.x;
                }
            }
            else if(wind&w) {
                right=ep->p.x;
                if(right>=screen->r.max.x) right=screen->r.max.x;
#define BART_BUG_FIXED	/* what goes on here?? -rob */
#ifdef BART_BUG_FIXED
                if(right>left)
                    line(screen, Pt(left, y), Pt(right, y), Endsquare, Endsquare, 0, getcolor(v), ZP);
#else
                if(right>left) {
                    switch(v) {
                    default:
                        segment(&screen, Pt(left, y), Pt(right, y),
                                ~0, D&~S);
                        segment(&screen, Pt(left, y), Pt(right, y),
                                v, f);
                        break;
                    case 0:
                        segment(&screen, Pt(left, y), Pt(right, y),
                                ~0, D&~S);
                        break;
                    case 3:
                        segment(&screen, Pt(left, y), Pt(right, y),
                                v, f);
                        break;
                    }
                }
#endif
            }
            wind=nwind;
            nextep=ep->next;
            if(++ep->p.y!=ep->maxy) {
                ep->x+=ep->num;
                if(ep->x>=ep->den) {
                    ep->x-=ep->den;
                    ep->p.x+=ep->dx1;
                }
                else
                    ep->p.x+=ep->dx;
                insert(ep, yp+1);
            }
        }
    }
    free((char *)edges);
    free((char *)ylist);
}
Beispiel #6
0
Rectangle
tktbbox(Tk *tk, TkTindex *ix)
{
	Rectangle r;
	int d, w;
	TkTitem *i;
	TkTline *l;
	TkEnv env;
	TkTtabstop *tb = nil;
	Tk *sub;
	TkText *tkt = TKobj(TkText, tk);
 	int opts[TkTnumopts];

	l = ix->line;

	/* r in V space */
	r.min = subpt(l->orig, tkt->deltatv);
	r.min.y += l->ascent;

	/* tabs dependon tags of first non-mark on display line */
	for(i = l->items; i->kind == TkTmark; )
		i = i->next;
	tkttagopts(tk, i, opts, &env, &tb, 1);

	for(i = l->items; i != nil; i = i->next) {
		if(i == ix->item) {
			tkttagopts(tk, i, opts, &env, nil, 1);
			r.min.y -= opts[TkToffset];
			switch(i->kind) {
			case TkTascii:
			case TkTrune:
				d = tktdispwidth(tk, tb, i, nil, r.min.x, 0, ix->pos);
				w = tktdispwidth(tk, tb, i, nil, r.min.x, ix->pos, 1);
				r.min.x += d;
				r.min.y -= env.font->ascent;
				r.max.x = r.min.x + w;
				r.max.y = r.min.y + env.font->height;
				break;
			case TkTwin:
				sub = i->iwin->sub;
				if(sub == nil)
					break;
				r.min.x += sub->act.x;
				r.min.y += sub->act.y;
				r.max.x = r.min.x + sub->act.width + 2*sub->borderwidth;
				r.max.y = r.min.y + sub->act.height + 2*sub->borderwidth;
				break;
			case TkTnewline:
				r.max.x = r.min.x;
				r.min.y -= l->ascent;
				r.max.y = r.min.y + l->height;
				break;
			default:
				d = tktdispwidth(tk, tb, i, nil, r.min.x, 0, -1);
				r.max.x = r.min.x + d;
				r.max.y = r.min.y;
				break;
			}
			return r;
		}
		r.min.x += tktdispwidth(tk, tb, i, nil, r.min.x, 0, -1);
	}
	r.min.x = 0;
	r.min.y = 0;
	r.max.x = 0;
	r.max.y = 0;
	return r;
}
Beispiel #7
0
char*
tkdrawcanv(Tk *tk, Point orig)
{
	Image *dst;
	TkCitem *i;
	Display *d;
	TkCanvas *c;
	Rectangle r, bufr, oclipr;
	int vis, alpha, buffer;
	Point rel, p;
	TkCimeth *imeth;

	c = TKobj(TkCanvas, tk);
	d = tk->env->top->display;
	dst = tkimageof(tk);
	/*
	 * translation from local to screen coords
	 */
	rel.x = orig.x + tk->act.x + tk->borderwidth;
	rel.y = orig.y + tk->act.y + tk->borderwidth;

	buffer = c->buffer;
	if (buffer == TkCbufauto)
		buffer = TkCbufvisible;
/*		buffer = (dst == TKobj(TkWin, tk->env->top->root)->image) ? TkCbufvisible : TkCbufnone; */

	if (buffer == TkCbufnone) {
		if(c->image != nil && c->ialloc)
			freeimage(c->image);
		c->image = dst;
		c->ialloc = 0;

		r = tkrect(tk, 0);
		bufr = r;
		rectclip(&bufr, tk->dirty);
		oclipr = dst->clipr;

		replclipr(dst, 0, rectaddpt(bufr, rel));
		draw(dst, rectaddpt(bufr, rel), tkgc(tk->env, TkCbackgnd), nil, ZP);

		p = subpt(rel, c->view);
		p.x = TKI2F(p.x);
		p.y = TKI2F(p.y);
		bufr = rectaddpt(bufr, c->view);
		for(i = c->head; i; i = i->next) {
			if(rectXrect(i->p.bb, bufr)) {
				imeth = &tkcimethod[i->type];
				imeth->coord(i, nil, p.x, p.y);
				imeth->draw(dst, i, tk->env);
				imeth->coord(i, nil, -p.x, -p.y);
			}
		}
		replclipr(dst, 0, oclipr);
	} else {
		if (c->buffer == TkCbufall)
			bufr = c->region;
		else {
			bufr.min = c->view;
			bufr.max.x = c->view.x + tk->act.width;
			bufr.max.y = c->view.y + tk->act.height;
		}
		alpha = (tk->env->colors[TkCbackgnd] & 0xff) != 0xff;
		if(c->image == nil || eqrect(bufr, c->image->r) == 0) {
			if(c->image != nil && c->ialloc)
				freeimage(c->image);
			c->image = allocimage(d, bufr, alpha?RGBA32:d->image->chan, 0, tk->env->colors[TkCbackgnd]);
			c->ialloc = 1;
			c->update = bufr;
			tkcvssetdirty(tk);		/* unnecessary? */
		}
	
		if(c->image == nil)
			return nil;
	
		r = c->update;
		if (rectclip(&r, c->image->r)) {
			if (alpha)
				drawop(c->image, c->update, nil, nil, ZP, Clear);
			draw(c->image, c->update, tkgc(tk->env, TkCbackgnd), nil, c->view);
			replclipr(c->image, 0, r);
			for(i = c->head; i; i = i->next) {
				if(rectXrect(i->p.bb, r))
					tkcimethod[i->type].draw(c->image, i, tk->env);
			}
			replclipr(c->image, 0, c->image->r);
		}
		/*
		 * if the visible area of the canvas image doesn't
		 * fit completely within the dirty rectangle,
		 * then we'll need to draw the background behind it
		 */
		r = tkrect(tk, 0);
		bufr = rectsubpt(bufr, c->view);
		vis = rectclip(&bufr, tkrect(tk, 0));
	
		if (!vis || !rectinrect(tk->dirty, bufr))
			draw(dst, rectaddpt(tk->dirty, rel), tkgc(tk->env, TkCbackgnd), nil, c->view);
	
		if (vis && rectclip(&bufr, tk->dirty))
			draw(dst, rectaddpt(bufr, rel), c->image, nil, addpt(bufr.min, c->view));
	}


	/*
	 * if the border is dirty too, then draw that
	 */
	if (!rectinrect(tk->dirty, bufr)) {
		r.min = addpt(r.min, rel);
		r.min.x -= tk->borderwidth;
		r.min.y -= tk->borderwidth;
		tkdrawrelief(dst, tk, r.min, TkCbackgnd, tk->relief);
	}
	c->update = bbnil;
	return nil;
}
Beispiel #8
0
static
void
_memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
{
	Rectangle r;
	struct Lline ll;
	Point d;
	int srcclipped;
	Memlayer *dl;

	if(radius < 0)
		return;
	if(src->layer)	/* can't draw line with layered source */
		return;
	srcclipped = 0;

   Top:
	dl = dst->layer;
	if(dl == nil){
		_memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op);
		return;
	}
	if(!srcclipped){
		d = subpt(sp, p0);
		if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
			return;
		if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
			return;
		srcclipped = 1;
	}

	/* dst is known to be a layer */
	p0.x += dl->delta.x;
	p0.y += dl->delta.y;
	p1.x += dl->delta.x;
	p1.y += dl->delta.y;
	clipr.min.x += dl->delta.x;
	clipr.min.y += dl->delta.y;
	clipr.max.x += dl->delta.x;
	clipr.max.y += dl->delta.y;
	if(dl->clear){
		dst = dst->layer->screen->image;
		goto Top;
	}

	/* XXX */
	/* this is not the correct set of tests */
//	if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3)
//		return;

	/* can't use sutherland-cohen clipping because lines are wide */
	r = memlinebbox(p0, p1, end0, end1, radius);
	/*
	 * r is now a bounding box for the line;
	 * use it as a clipping rectangle for subdivision
	 */
	if(rectclip(&r, clipr) == 0)
		return;
	ll.p0 = p0;
	ll.p1 = p1;
	ll.end0 = end0;
	ll.end1 = end1;
	ll.sp = sp;
	ll.dstlayer = dst->layer;
	ll.src = src;
	ll.radius = radius;
	ll.delta = dl->delta;
	ll.op = op;
	_memlayerop(llineop, dst, r, r, &ll);
}
Beispiel #9
0
int	in_poly(Ppoly_t argpoly, Ppoint_t q)
{
	int			i, i1;	/* point index; i1 = i-1 mod n */
	double		x;		/* x intersection of e with ray */
	int	crossings = 0;	/* 2 * number of edge/ray crossings */
	Ppoly_t		poly;	/* original O'Rourke code overwrites the arg polygon! */
	Ppoint_t 	*P;
	int			n;

	/* Shift so that q is the origin. */
	poly = copypoly(argpoly);
	P = poly.ps;
	n = poly.pn;
	for (i = 0; i < n; i++)
		poly.ps[i] = subpt(poly.ps[i],q);

	/* For each edge e=(i-1,i), see if crosses ray. */
	for (i = 0; i < n; i++ ) {
		i1 = ( i + n - 1 ) % n;

		/* if edge is horizontal, test to see if the point is on it */
		if ((P[i].y == 0 ) && ( P[i1].y == 0)) {
			if ((P[i].x * P[i1].x) < 0)
				return TRUE;
		       	else
				continue;
		}
		/* if e straddles the x-axis... */
		if (((P[i].y >= 0 ) && ( P[i1].y <= 0 ) ) ||
		    ( ( P[i1].y >= 0 ) && ( P[i].y <= 0 ) ) ) {
			/* e straddles ray, so compute intersection with ray. */
			x = (P[i].x * P[i1].y - P[i1].x * P[i].y)
				/ (double)(P[i1].y - P[i].y);

			/* if intersect at origin, we've found intersection */
			if (x == 0)
				return TRUE;

			/* crosses ray if strictly positive intersection. */
			if (x > 0)  {
				if ( P[i].y == 0 ) {
					if  ( P[(i-1+n)%n].y*P[(1+i)%n].y < 0) {
						/* count half a crossing */
						crossings++;
					}
					else if  ( P[i].y*P[(2+i)%n].y < 0) {
						/* count half a crossing */
						crossings++;
					}
				}
				else {
					/* count a full crossing */
					crossings += 2;
				}
			}
		}
	}

	freepoly(poly);

	/* q inside if an odd number of crossings. */
	if( (crossings % 4) >= 2 )
		return	TRUE;
	else
		return	FALSE;
}
Beispiel #10
0
void
memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
{
	struct Draw d;
	Rectangle srcr, tr, mr;
	Memlayer *dl, *sl;

	if(drawdebug)
		iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);

	if(mask == nil)
		mask = memopaque;

	if(mask->layer){
if(drawdebug)	iprint("mask->layer != nil\n");
		return;	/* too hard, at least for now */
	}

    Top:
	if(dst->layer==nil && src->layer==nil){
		memimagedraw(dst, r, src, p0, mask, p1, op);
		return;
	}

	if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
if(drawdebug)	iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
		return;
	}

	/*
 	 * Convert to screen coordinates.
	 */
	dl = dst->layer;
	if(dl != nil){
		r.min.x += dl->delta.x;
		r.min.y += dl->delta.y;
		r.max.x += dl->delta.x;
		r.max.y += dl->delta.y;
	}
    Clearlayer:
	if(dl!=nil && dl->clear){
		if(src == dst){
			p0.x += dl->delta.x;
			p0.y += dl->delta.y;
			src = dl->screen->image;
		}
		dst = dl->screen->image;
		goto Top;
	}

	sl = src->layer;
	if(sl != nil){
		p0.x += sl->delta.x;
		p0.y += sl->delta.y;
		srcr.min.x += sl->delta.x;
		srcr.min.y += sl->delta.y;
		srcr.max.x += sl->delta.x;
		srcr.max.y += sl->delta.y;
	}

	/*
	 * Now everything is in screen coordinates.
	 * mask is an image.  dst and src are images or obscured layers.
	 */

	/*
	 * if dst and src are the same layer, just draw in save area and expose.
	 */
	if(dl!=nil && dst==src){
		if(dl->save == nil)
			return;	/* refresh function makes this case unworkable */
		if(rectXrect(r, srcr)){
			tr = r;
			if(srcr.min.x < tr.min.x){
				p1.x += tr.min.x - srcr.min.x;
				tr.min.x = srcr.min.x;
			}
			if(srcr.min.y < tr.min.y){
				p1.y += tr.min.x - srcr.min.x;
				tr.min.y = srcr.min.y;
			}
			if(srcr.max.x > tr.max.x)
				tr.max.x = srcr.max.x;
			if(srcr.max.y > tr.max.y)
				tr.max.y = srcr.max.y;
			memlhide(dst, tr);
		}else{
			memlhide(dst, r);
			memlhide(dst, srcr);
		}
		memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
			subpt(srcr.min, src->layer->delta), mask, p1, op);
		memlexpose(dst, r);
		return;
	}

	if(sl){
		if(sl->clear){
			src = sl->screen->image;
			if(dl != nil){
				r.min.x -= dl->delta.x;
				r.min.y -= dl->delta.y;
				r.max.x -= dl->delta.x;
				r.max.y -= dl->delta.y;
			}
			goto Top;
		}
		/* relatively rare case; use save area */
		if(sl->save == nil)
			return;	/* refresh function makes this case unworkable */
		memlhide(src, srcr);
		/* convert back to logical coordinates */
		p0.x -= sl->delta.x;
		p0.y -= sl->delta.y;
		srcr.min.x -= sl->delta.x;
		srcr.min.y -= sl->delta.y;
		srcr.max.x -= sl->delta.x;
		srcr.max.y -= sl->delta.y;
		src = src->layer->save;
	}

	/*
	 * src is now an image.  dst may be an image or a clear layer
	 */
	if(dst->layer==nil)
		goto Top;
	if(dst->layer->clear)
		goto Clearlayer;

	/*
	 * dst is an obscured layer
	 */
	d.deltas = subpt(p0, r.min);
	d.deltam = subpt(p1, r.min);
	d.dstlayer = dl;
	d.src = src;
	d.op = op;
	d.mask = mask;
	_memlayerop(ldrawop, dst, r, r, &d);
}
Beispiel #11
0
void
lockscreen(void)
{
	enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, };
	char *s;
	char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen];
	int fd, dx, dy;
	Image *i;
	Point p;
	Rectangle r;
	Tm *tm;

	fd = open("/dev/screen", OREAD);
	if(fd < 0)
		error("can't open /dev/screen: %r");
	if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen)
		error("can't read /dev/screen: %r");
	close(fd);
	buf[sizeof buf-1] = 0;
	if(tokenize(buf, flds, Nfld) != Nfld)
		error("can't tokenize /dev/screen header");
	snprint(newcmd, sizeof newcmd, "-r %s %s %d %d",
		flds[1], flds[2], atoi(flds[3]) - 1, atoi(flds[4]) - 1);
	newwindow(newcmd);
	if (initdraw(nil, nil, "screenlock") < 0)
		sysfatal("initdraw failed");
	if(display == nil)
		error("no display");

	/* screen is now open and covered.  grab mouse and hold on tight */
	procrfork(grabmouse, nil, 4096, RFFDG);
	procrfork(blanker, nil, 4096, RFFDG);
	fd = open(pic, OREAD);
	if(fd > 0){
		i = readimage(display, fd, 0);
		if(i){
 			r = screen->r;
			p = Pt(r.max.x / 2, r.max.y * 2 / 3); 
			dx = (Dx(screen->r) - Dx(i->r)) / 2;
			r.min.x += dx;
			r.max.x -= dx;
			dy = (Dy(screen->r) - Dy(i->r)) / 2;
			r.min.y += dy;
			r.max.y -= dy;
			draw(screen, screen->r, display->black, nil, ZP);
			draw(screen, r, i, nil, i->r.min);
			flushimage(display, 1);
		}
		close(fd);

		/* identify the user on screen, centered */
		tm = localtime(time(0));
		s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
		p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0));
		screenstring(p, s);
	}

	/* clear the cursor */
	fd = open("/dev/cursor", OWRITE);
	if(fd > 0){
		memset(cbuf, 0, sizeof cbuf);
		write(fd, cbuf, sizeof cbuf);
		/* leave it open */
	}
}
Beispiel #12
0
static void
resample(Memimage *dst, Rectangle r, Memimage *src, Rectangle sr)
{
	Point sp, dp;
	Point _sp, qp;
	Point ssize, dsize;
	uchar *pdst0, *pdst, *psrc0, *psrc;
	ulong s00, s01, s10, s11;
	int tx, ty, bpp, bpl;

	ssize = subpt(subpt(sr.max, sr.min), Pt(1,1));
	dsize = subpt(subpt(r.max, r.min), Pt(1,1));
	pdst0 = byteaddr(dst, r.min);
	bpp = src->depth/8;
	bpl = src->width*sizeof(int);

	qp = Pt(0, 0);
	if(dsize.x > 0)
		qp.x = (ssize.x<<12)/dsize.x;
	if(dsize.y > 0)
		qp.y = (ssize.y<<12)/dsize.y;

	_sp.y = sr.min.y<<12;
	for(dp.y=0; dp.y<=dsize.y; dp.y++){
		sp.y = _sp.y>>12;
		ty = _sp.y&0xFFF;
		pdst = pdst0;
		sp.x = sr.min.x;
		psrc0 = byteaddr(src, sp);
		_sp.x = 0;
		for(dp.x=0; dp.x<=dsize.x; dp.x++){
			sp.x = _sp.x>>12;
			tx = _sp.x&0xFFF;
			psrc = psrc0 + sp.x*bpp;
			s00 = (0x1000-tx)*(0x1000-ty);
			s01 = tx*(0x1000-ty);
			s10 = (0x1000-tx)*ty;
			s11 = tx*ty;
			switch(bpp){
			case 4:
				pdst[3] = (s11*psrc[bpl+bpp+3] + 
					   s10*psrc[bpl+3] + 
					   s01*psrc[bpp+3] +
					   s00*psrc[3]) >>24;
			case 3:
				pdst[2] = (s11*psrc[bpl+bpp+2] + 
					   s10*psrc[bpl+2] + 
					   s01*psrc[bpp+2] +
					   s00*psrc[2]) >>24;
				pdst[1] = (s11*psrc[bpl+bpp+1] + 
					   s10*psrc[bpl+1] + 
					   s01*psrc[bpp+1] +
					   s00*psrc[1]) >>24;
			case 1:
				pdst[0] = (s11*psrc[bpl+bpp] + 
					   s10*psrc[bpl] + 
					   s01*psrc[bpp] +
					   s00*psrc[0]) >>24;
			}
			pdst += bpp;
			_sp.x += qp.x;
		}
		pdst0 += dst->width*sizeof(int);
		_sp.y += qp.y;
	}
}
Beispiel #13
0
	border(screen, rramp, -1, display->black, ZP);
	draw(screen, rramp, ramp, nil, ramp->r.min);
	drawrampbar(red, &state);

	border(screen, rectaddpt(state.selr, subpt(rbig.min, orig->r.min)), -2, red, ZP);
	if(clear){
		drawface(-1);
		for(i=0; i<nelem(face); i++)
			drawface(i);
	}
}

void
moveframe(Rectangle old, Rectangle new)
{
	border(screen, rectaddpt(old, subpt(rbig.min, orig->r.min)), -2, orig, old.min);
	border(screen, rectaddpt(new, subpt(rbig.min, orig->r.min)), -2, red, ZP);
}


/*
 * Initialize gamma ramp; should dither for
 * benefit of non-true-color displays.
 */
void
initramp(void)
{
	int k, x, y;
	uint8_t dat[256*256];
	double g;
Beispiel #14
0
void
viewer(Document *dd)
{
	int i, fd, n, oldpage;
	int nxt;
	Menu menu, midmenu;
	Mouse m;
	Event e;
	Point dxy, oxy, xy0;
	Image *tmp;

	static char *fwditems[] = { "this page", "next page", "exit", 0 };
 	static char *miditems[] = {
 		"orig size",
 		"zoom in",
 		"fit window",
 		"rotate 90",
 		"upside down",
 		"",
 		"next",
 		"prev",
		"zerox",
 		"",
 		"reverse",
 		"discard",
 		"write",
 		"",
 		"quit",
 		0
 	};
	char *s;
	enum { Eplumb = 4 };
	Plumbmsg *pm;

	doc = dd;    /* save global for menuhit */
	ul = screen->r.min;
	einit(Emouse|Ekeyboard);
	if(doc->addpage != nil)
		eplumb(Eplumb, "image");

	esetcursor(&reading);

	/*
	 * im is a global pointer to the current image.
	 * eventually, i think we will have a layer between
	 * the display routines and the ps/pdf/whatever routines
	 * to perhaps cache and handle images of different
	 * sizes, etc.
	 */
	im = 0;
	page = reverse ? doc->npage-1 : 0;

	if(doc->fwdonly) {
		menu.item = fwditems;
		menu.gen = 0;
		menu.lasthit = 0;
	} else {
		menu.item = 0;
		menu.gen = menugen;
		menu.lasthit = 0;
	}

	midmenu.item = miditems;
	midmenu.gen = 0;
	midmenu.lasthit = Next;

	if(doc->docname != nil)
		setlabel(doc->docname);
	showpage(page, &menu);
	esetcursor(nil);

	nxt = 0;
	for(;;) {
		/*
		 * throughout, if doc->fwdonly is set, we restrict the functionality
		 * a fair amount.  we don't care about doc->npage anymore, and
		 * all that can be done is select the next page.
		 */
		unlockdisplay(display);
		i = eread(Emouse|Ekeyboard|Eplumb, &e);
		lockdisplay(display);
		switch(i){
		case Ekeyboard:
			if(e.kbdc <= 0xFF && isdigit(e.kbdc)) {
				nxt = nxt*10+e.kbdc-'0';
				break;
			} else if(e.kbdc != '\n')
				nxt = 0;
			switch(e.kbdc) {
			case 'r':	/* reverse page order */
				if(doc->fwdonly)
					break;
				reverse = !reverse;
				menu.lasthit = doc->npage-1-menu.lasthit;

				/*
				 * the theory is that if we are reversing the
				 * document order and are on the first or last
				 * page then we're just starting and really want
		 	 	 * to view the other end.  maybe the if
				 * should be dropped and this should happen always.
				 */
				if(page == 0 || page == doc->npage-1) {
					page = doc->npage-1-page;
					showpage(page, &menu);
				}
				break;
			case 'w':	/* write bitmap of current screen */
				esetcursor(&reading);
				s = writebitmap();
				if(s)
					string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
						display->defaultfont, s);
				esetcursor(nil);
				flushimage(display, 1);
				break;
			case 'd':	/* remove image from working set */
				if(doc->rmpage && page < doc->npage) {
					if(doc->rmpage(doc, page) >= 0) {
						if(doc->npage < 0)
							wexits(0);
						if(page >= doc->npage)
							page = doc->npage-1;
						showpage(page, &menu);
					}
				}
				break;
			case 'q':
			case 0x04: /* ctrl-d */
				wexits(0);
			case 'u':
				if(im==nil)
					break;
				angle = (angle+180) % 360;
				showpage(page, &menu);
				break;
			case '-':
			case '\b':
			case Kleft:
				if(page > 0 && !doc->fwdonly) {
					--page;
					showpage(page, &menu);
				}
				break;
			case '\n':
				if(nxt) {
					nxt--;
					if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly)
						showpage(page=nxt, &menu);
					nxt = 0;
					break;
				}
				goto Gotonext;
			case Kright:
			case ' ':
			Gotonext:
				if(doc->npage && ++page >= doc->npage && !doc->fwdonly)
					wexits(0);
				showpage(page, &menu);
				break;

			/*
			 * The upper y coordinate of the image is at ul.y in screen->r.
			 * Panning up means moving the upper left corner down.  If the
			 * upper left corner is currently visible, we need to go back a page.
			 */
			case Kup:
				if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){
					if(page > 0 && !doc->fwdonly){
						--page;
						showbottom = 1;
						showpage(page, &menu);
					}
				} else {
					i = Dy(screen->r)/2;
					if(i > 10)
						i -= 10;
					if(i+ul.y > screen->r.min.y)
						i = screen->r.min.y - ul.y;
					translate(Pt(0, i));
				}
				break;

			/*
			 * If the lower y coordinate is on the screen, we go to the next page.
			 * The lower y coordinate is at ul.y + Dy(im->r).
			 */
			case Kdown:
				i = ul.y + Dy(im->r);
				if(screen->r.min.y <= i && i <= screen->r.max.y){
					ul.y = screen->r.min.y;
					goto Gotonext;
				} else {
					i = -Dy(screen->r)/2;
					if(i < -10)
						i += 10;
					if(i+ul.y+Dy(im->r) <= screen->r.max.y)
						i = screen->r.max.y - Dy(im->r) - ul.y - 1;
					translate(Pt(0, i));
				}
				break;
			default:
				esetcursor(&query);
				sleep(1000);
				esetcursor(nil);
				break;
			}
			break;

		case Emouse:
			m = e.mouse;
			switch(m.buttons){
			case Left:
				oxy = m.xy;
				xy0 = oxy;
				do {
					dxy = subpt(m.xy, oxy);
					oxy = m.xy;
					translate(dxy);
					unlockdisplay(display);
					m = emouse();
					lockdisplay(display);
				} while(m.buttons == Left);
				if(m.buttons) {
					dxy = subpt(xy0, oxy);
					translate(dxy);
				}
				break;

			case Middle:
				if(doc->npage == 0)
					break;

				unlockdisplay(display);
				n = emenuhit(Middle, &m, &midmenu);
				lockdisplay(display);
				if(n == -1)
					break;
				switch(n){
				case Next: 	/* next */
					if(reverse)
						page--;
					else
						page++;
					if(page < 0) {
						if(reverse) return;
						else page = 0;
					}

					if((page >= doc->npage) && !doc->fwdonly)
						return;

					showpage(page, &menu);
					nxt = 0;
					break;
				case Prev:	/* prev */
					if(reverse)
						page++;
					else
						page--;
					if(page < 0) {
						if(reverse) return;
						else page = 0;
					}

					if((page >= doc->npage) && !doc->fwdonly && !reverse)
						return;

					showpage(page, &menu);
					nxt = 0;
					break;
				case Zerox:	/* prev */
					zerox();
					break;
				case Zin:	/* zoom in */
					{
						double delta;
						Rectangle r;

						r = egetrect(Middle, &m);
						if((rectclip(&r, rectaddpt(im->r, ul)) == 0) ||
							Dx(r) == 0 || Dy(r) == 0)
							break;
						/* use the smaller side to expand */
						if(Dx(r) < Dy(r))
							delta = (double)Dx(im->r)/(double)Dx(r);
						else
							delta = (double)Dy(im->r)/(double)Dy(r);

						esetcursor(&reading);
						tmp = xallocimage(display,
								Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)),
								im->chan, 0, DBlack);
						if(tmp == nil) {
							fprint(2, "out of memory during zoom: %r\n");
							wexits("memory");
						}
						resample(im, tmp);
						im = tmp;
						delayfreeimage(tmp);
						esetcursor(nil);
						ul = screen->r.min;
						redraw(screen);
						flushimage(display, 1);
						break;
					}
				case Fit:	/* fit */
					{
						double delta;
						Rectangle r;

						delta = (double)Dx(screen->r)/(double)Dx(im->r);
						if((double)Dy(im->r)*delta > Dy(screen->r))
							delta = (double)Dy(screen->r)/(double)Dy(im->r);

						r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta));
						esetcursor(&reading);
						tmp = xallocimage(display, r, im->chan, 0, DBlack);
						if(tmp == nil) {
							fprint(2, "out of memory during fit: %r\n");
							wexits("memory");
						}
						resample(im, tmp);
						im = tmp;
						delayfreeimage(tmp);
						esetcursor(nil);
						ul = screen->r.min;
						redraw(screen);
						flushimage(display, 1);
						break;
					}
				case Rot:	/* rotate 90 */
					angle = (angle+90) % 360;
					showpage(page, &menu);
					break;
				case Upside: 	/* upside-down */
					angle = (angle+180) % 360;
					showpage(page, &menu);
					break;
				case Restore:	/* restore */
					showpage(page, &menu);
					break;
				case Reverse:	/* reverse */
					if(doc->fwdonly)
						break;
					reverse = !reverse;
					menu.lasthit = doc->npage-1-menu.lasthit;

					if(page == 0 || page == doc->npage-1) {
						page = doc->npage-1-page;
						showpage(page, &menu);
					}
					break;
				case Write: /* write */
					esetcursor(&reading);
					s = writebitmap();
					if(s)
						string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,
							display->defaultfont, s);
					esetcursor(nil);
					flushimage(display, 1);
					break;
				case Del: /* delete */
					if(doc->rmpage && page < doc->npage) {
						if(doc->rmpage(doc, page) >= 0) {
							if(doc->npage < 0)
								wexits(0);
							if(page >= doc->npage)
								page = doc->npage-1;
							showpage(page, &menu);
						}
					}
					break;
				case Exit:	/* exit */
					return;
				case Empty1:
				case Empty2:
				case Empty3:
					break;

				};



			case Right:
				if(doc->npage == 0)
					break;

				oldpage = page;
				unlockdisplay(display);
				n = emenuhit(RMenu, &m, &menu);
				lockdisplay(display);
				if(n == -1)
					break;

				if(doc->fwdonly) {
					switch(n){
					case 0:	/* this page */
						break;
					case 1:	/* next page */
						showpage(++page, &menu);
						break;
					case 2:	/* exit */
						return;
					}
					break;
				}

				if(n == doc->npage)
					return;
				else
					page = reverse ? doc->npage-1-n : n;

				if(oldpage != page)
					showpage(page, &menu);
				nxt = 0;
				break;
			}
			break;

		case Eplumb:
			pm = e.v;
			if(pm->ndata <= 0){
				plumbfree(pm);
				break;
			}
			if(plumbquit(pm))
				exits(nil);
			if(showdata(pm)) {
				s = estrdup("/tmp/pageplumbXXXXXXX");
				fd = opentemp(s);
				write(fd, pm->data, pm->ndata);
				/* lose fd reference on purpose; the file is open ORCLOSE */
			} else if(pm->data[0] == '/') {
				s = estrdup(pm->data);
			} else {
				s = emalloc(strlen(pm->wdir)+1+pm->ndata+1);
				sprint(s, "%s/%s", pm->wdir, pm->data);
				cleanname(s);
			}
			if((i = doc->addpage(doc, s)) >= 0) {
				page = i;
				unhide();
				showpage(page, &menu);
			}
			free(s);
			plumbfree(pm);
			break;
		}
	}
}
Beispiel #15
0
Datei: arc.c Projekt: 0intro/vx32
/*
 * make a "wedge" mask covering the desired angle and contained in
 * a surrounding square; draw a full ellipse; intersect that with the
 * wedge to make a mask through which to copy src to dst.
 */
void
memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op)
{
	int i, w, beta, tmp, c1, c2, m, m1;
	Rectangle rect;
	Point p,	bnd[8];
	Memimage *wedge, *figure, *mask;

	if(a < 0)
		a = -a;
	if(b < 0)
		b = -b;
	w = t;
	if(w < 0)
		w = 0;
	alpha = -alpha;		/* compensate for upside-down coords */
	phi = -phi;
	beta = alpha + phi;
	if(phi < 0){
		tmp = alpha;
		alpha = beta;
		beta = tmp;
		phi = -phi;
	}
	if(phi >= 360){
		memellipse(dst, c, a, b, t, src, sp, op);
		return;
	}
	while(alpha < 0)
		alpha += 360;
	while(beta < 0)
		beta += 360;
	c1 = alpha/90 & 3;	/* number of nearest corner */
	c2 = beta/90 & 3;
		/*
		 * icossin returns point at radius ICOSSCALE.
		 * multiplying by m1 moves it outside the ellipse
		*/
	rect = Rect(-a-w, -b-w, a+w+1, b+w+1);
	m = rect.max.x;	/* inradius of bounding square */
	if(m < rect.max.y)
		m = rect.max.y;
	m1 = (m+ICOSSCALE-1) >> 10;
	m = m1 << 10;		/* assure m1*cossin is inside */
	i = 0;
	bnd[i++] = Pt(0,0);
	icossin(alpha, &p.x, &p.y);
	bnd[i++] = mulpt(p, m1);
	for(;;) {
		bnd[i++] = mulpt(corners[c1], m);
		if(c1==c2 && phi<180)
			break;
		c1 = (c1+1) & 3;
		phi -= 90;
	}
	icossin(beta, &p.x, &p.y);
	bnd[i++] = mulpt(p, m1);

	figure = nil;
	mask = nil;
	wedge = allocmemimage(rect, GREY1);
	if(wedge == nil)
		goto Return;
	memfillcolor(wedge, DTransparent);
	memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S);
	figure = allocmemimage(rect, GREY1);
	if(figure == nil)
		goto Return;
	memfillcolor(figure, DTransparent);
	memellipse(figure, p00, a, b, t, memopaque, p00, S);
	mask = allocmemimage(rect, GREY1);
	if(mask == nil)
		goto Return;
	memfillcolor(mask, DTransparent);
	memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S);
	c = subpt(c, dst->r.min);
	memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op);

    Return:
	freememimage(wedge);
	freememimage(figure);
	freememimage(mask);
}
Beispiel #16
0
int pl_hitpopup(Panel *g, Mouse *m){
	Panel *p;
	Point d;
	Popup *pp;

	pp=g->data;
	if(g->state==UP){
		switch(m->buttons&7){
		case 0: p=g->child; break;
		case 1:	p=pp->pop[0]; g->state=DOWN1; break;
		case 2: p=pp->pop[1]; g->state=DOWN2; break;
		case 4: p=pp->pop[2]; g->state=DOWN3; break;
		default: p=0; break;
		}
		if(p==0){
			p=g->child;
			g->state=DOWN;
		}
		else if(g->state!=UP){
			plpack(p, screen->clipr);
			if(p->lastmouse)
				d=subpt(m->xy, divpt(addpt(p->lastmouse->r.min,
						     p->lastmouse->r.max), 2));
			else
				d=subpt(m->xy, divpt(addpt(p->r.min, p->r.max), 2));
			if(p->r.min.x+d.x<g->r.min.x) d.x=g->r.min.x-p->r.min.x;
			if(p->r.max.x+d.x>g->r.max.x) d.x=g->r.max.x-p->r.max.x;
			if(p->r.min.y+d.y<g->r.min.y) d.y=g->r.min.y-p->r.min.y;
			if(p->r.max.y+d.y>g->r.max.y) d.y=g->r.max.y-p->r.max.y;
			plmove(p, d);
			pp->save=allocimage(display, p->r, g->b->chan, 0, DNofill);
			if(pp->save!=0) draw(pp->save, p->r, g->b, 0, p->r.min);
			pl_invis(p, 0);
			pldraw(p, g->b);
		}
	}
	else{
		switch(g->state){
		default: SET(p); break;			/* can't happen! */
		case DOWN1: p=pp->pop[0]; break;
		case DOWN2: p=pp->pop[1]; break;
		case DOWN3: p=pp->pop[2]; break;
		case DOWN:  p=g->child;  break;
		}
		if((m->buttons&7)==0){
			if(g->state!=DOWN){
				if(pp->save!=0){
					draw(g->b, p->r, pp->save, 0, p->r.min);
					flushimage(display, 1);
					freeimage(pp->save);
					pp->save=0;
				}
				pl_invis(p, 1);
			}
			g->state=UP;
		}
	}
	plmouse(p, m);
	if((m->buttons&7)==0)
		g->state=UP;
	return (m->buttons&7)!=0;
}
Beispiel #17
0
/*
 * Place i so i->r.min = log, i->layer->screenr.min == scr.
*/
int
memlorigin(Memimage *i, Point log, Point scr)
{
	Memlayer *l;
	Memscreen *s;
	Memimage *t, *shad, *nsave;
	Rectangle x, newr, oldr;
	Point delta;
	int overlap, eqlog, eqscr, wasclear;

	l = i->layer;
	s = l->screen;
	oldr = l->screenr;
	newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
	eqscr = eqpt(scr, oldr.min);
	eqlog = eqpt(log, i->r.min);
	if(eqscr && eqlog)
		return 0;
	nsave = nil;
	if(eqlog==0 && l->save!=nil){
		nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
		if(nsave == nil)
			return -1;
	}

	/*
	 * Bring it to front and move logical coordinate system.
	 */
	memltofront(i);
	wasclear = l->clear;
	if(nsave){
		if(!wasclear)
			memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
		freememimage(l->save);
		l->save = nsave;
	}
	delta = subpt(log, i->r.min);
	i->r = rectaddpt(i->r, delta);
	i->clipr = rectaddpt(i->clipr, delta);
	l->delta = subpt(l->screenr.min, i->r.min);
	if(eqscr)
		return 0;

	/*
	 * To clean up old position, make a shadow window there, don't paint it,
	 * push it behind this one, and (later) delete it.  Because the refresh function
	 * for this fake window is a no-op, this will cause no graphics action except
	 * to restore the background and expose the windows previously hidden.
	 */
	shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
	if(shad == nil)
		return -1;
	s->frontmost = i;
	if(s->rearmost == i)
		s->rearmost = shad;
	else
		l->rear->layer->front = shad;
	shad->layer->front = i;
	shad->layer->rear = l->rear;
	l->rear = shad;
	l->front = nil;
	shad->layer->clear = 0;

	/*
	 * Shadow is now holding down the fort at the old position.
	 * Move the window and hide things obscured by new position.
	 */
	for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
		x = newr;
		overlap = rectclip(&x, t->layer->screenr);
		if(overlap){
			memlhide(t, x);
			t->layer->clear = 0;
		}
	}
	l->screenr = newr;
	l->delta = subpt(scr, i->r.min);
	l->clear = rectinrect(newr, l->screen->image->clipr);

	/*
	 * Everything's covered.  Copy to new position and delete shadow window.
	 */
	if(wasclear)
		memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
	else
		memlexpose(i, newr);
	memldelete(shad);

	return 1;
}
Beispiel #18
0
static int
xdraw(Memdrawparam *par)
{
	int dy, dx;
	unsigned m;
	Memimage *src, *dst, *mask;
	Xmem *dxm, *sxm, *mxm;
	GC gc;
	Rectangle r, sr, mr;
	ulong sdval;

	dx = Dx(par->r);
	dy = Dy(par->r);
	src = par->src;
	dst = par->dst;
	mask = par->mask;
	r = par->r;
	sr = par->sr;
	mr = par->mr;
	sdval = par->sdval;

return 0;
	if((dxm = dst->X) == nil)
		return 0;

	/*
	 * If we have an opaque mask and source is one opaque pixel we can convert to the
	 * destination format and just XFillRectangle.
	 */
	m = Simplesrc|Simplemask|Fullmask;
	if((par->state&m)==m){
		xfillcolor(dst, r, sdval);
		dirtyXdata(dst, par->r);
		return 1;
	}

	/*
	 * If no source alpha, an opaque mask, we can just copy the
	 * source onto the destination.  If the channels are the same and
	 * the source is not replicated, XCopyArea suffices.
	 */
	m = Simplemask|Fullmask;
	if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
		sxm = src->X;
		r = rectsubpt(r, dst->r.min);		
		sr = rectsubpt(sr, src->r.min);
		if(dst->chan == GREY1)
			gc = xgccopy0;
		else
			gc = xgccopy;
		XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, 
			sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
		dirtyXdata(dst, par->r);
		return 1;
	}
	
	/*
	 * If no source alpha, a 1-bit mask, and a simple source
	 * we can just copy through the mask onto the destination.
	 */
	if(dst->X && mask->X && !(mask->flags&Frepl)
	&& mask->chan == GREY1 && (par->state&Simplesrc)){
		Point p;

		mxm = mask->X;
		r = rectsubpt(r, dst->r.min);		
		mr = rectsubpt(mr, mask->r.min);
		p = subpt(r.min, mr.min);
		if(dst->chan == GREY1){
			gc = xgcsimplesrc0;
			if(xgcsimplecolor0 != sdval){
				XSetForeground(xdisplay, gc, sdval);
				xgcsimplecolor0 = sdval;
			}
			if(xgcsimplepm0 != mxm->pmid){
				XSetStipple(xdisplay, gc, mxm->pmid);
				xgcsimplepm0 = mxm->pmid;
			}
		}else{
		/* somehow this doesn't work on rob's mac 
			gc = xgcsimplesrc;
			if(dst->chan == CMAP8 && xtblbit)
				sdval = plan9tox11[sdval];
				
			if(xgcsimplecolor != sdval){
				XSetForeground(xdisplay, gc, sdval);
				xgcsimplecolor = sdval;
			}
			if(xgcsimplepm != mxm->pmid){
				XSetStipple(xdisplay, gc, mxm->pmid);
				xgcsimplepm = mxm->pmid;
			}
		*/
			return 0;
		}
		XSetTSOrigin(xdisplay, gc, p.x, p.y);
		XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
		dirtyXdata(dst, par->r);
		return 1;
	}
	return 0;
}