Exemple #1
0
/*
 * A draw operation that touches only the area contained in bot but not in top.
 * mp and sp get aligned with bot.min.
 */
static void
gendrawdiff(Image *dst, Rectangle bot, Rectangle top,
	Image *src, Point sp, Image *mask, Point mp, int op)
{
	Rectangle r;
	Point origin;
	Point delta;

	USED(op);

	if(Dx(bot)*Dy(bot) == 0)
		return;

	/* no points in bot - top */
	if(rectinrect(bot, top))
		return;

	/* bot - top ≡ bot */
	if(Dx(top)*Dy(top)==0 || rectXrect(bot, top)==0){
		gendrawop(dst, bot, src, sp, mask, mp, op);
		return;
	}

	origin = bot.min;
	/* split bot into rectangles that don't intersect top */
	/* left side */
	if(bot.min.x < top.min.x){
		r = Rect(bot.min.x, bot.min.y, top.min.x, bot.max.y);
		delta = subpt(r.min, origin);
		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
		bot.min.x = top.min.x;
	}

	/* right side */
	if(bot.max.x > top.max.x){
		r = Rect(top.max.x, bot.min.y, bot.max.x, bot.max.y);
		delta = subpt(r.min, origin);
		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
		bot.max.x = top.max.x;
	}

	/* top */
	if(bot.min.y < top.min.y){
		r = Rect(bot.min.x, bot.min.y, bot.max.x, top.min.y);
		delta = subpt(r.min, origin);
		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
		bot.min.y = top.min.y;
	}

	/* bottom */
	if(bot.max.y > top.max.y){
		r = Rect(bot.min.x, top.max.y, bot.max.x, bot.max.y);
		delta = subpt(r.min, origin);
		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);
		bot.max.y = top.max.y;
	}
}
Exemple #2
0
void
_memlsetclear(Memscreen *s)
{
	Memimage *i, *j;
	Memlayer *l;

	for(i=s->rearmost; i; i=i->layer->front){
		l = i->layer;
		l->clear = rectinrect(l->screenr, l->screen->image->clipr);
		if(l->clear)
			for(j=l->front; j; j=j->layer->front)
				if(rectXrect(l->screenr, j->layer->screenr)){
					l->clear = 0;
					break;
				}
	}
}
Exemple #3
0
static char*
tkdrawslaves1(Tk *tk, Point orig, Image *dst, int *dirty)
{
	Tk *f;
	char *e = nil;
	Point worig;
	Rectangle r, oclip;

	worig.x = orig.x + tk->act.x + tk->borderwidth;
	worig.y = orig.y + tk->act.y + tk->borderwidth;

	r = rectaddpt(tk->dirty, worig);
	if (Dx(r) > 0 && rectXrect(r, dst->clipr)) {
		e = tkmethod[tk->type]->draw(tk, orig);
		tk->dirty = bbnil;
		*dirty = 1;
	}
	if(e != nil)
		return e;

	/*
	 * grids need clipping
	 * XXX BUG: they can't, 'cos text widgets don't clip appropriately.
	 */
	if (tk->grid != nil) {
		r = rectaddpt(tkrect(tk, 0), worig);
		if (rectclip(&r, dst->clipr) == 0)
			return nil;
		oclip = dst->clipr;
		replclipr(dst, 0, r);
	}
	for(f = tk->slave; e == nil && f; f = f->next)
		e = tkdrawslaves1(f, worig, dst, dirty);
	if (tk->grid != nil)
		replclipr(dst, 0, oclip);
	return e;
}
Exemple #4
0
static void
swcursoravoid(Rectangle r)
{
	if(swvisible && rectXrect(r, swrect))
		swcursorhide();
}
Exemple #5
0
char*
tkcvstags(Tk *tk, char *arg, char **val, int af)
{
	TkTop *o;
	int x, y;
	TkName *f;
	TkCtag *t, *tt;
	char *fmt;
	TkCpoints p;
	TkCanvas *c;
	TkCitem *i, *b;
	int d, dist, dx, dy;
	char tag[Tkmaxitem], buf[Tkmaxitem];
	char *e;

	USED(val);

	c = TKobj(TkCanvas, tk);

	o = tk->env->top;
	if(af == TkCadd) {
		arg = tkword(o, arg, tag, tag+sizeof(tag), nil);
		if(tag[0] == '\0' || (tag[0] >= '0' && tag[0] <= '9'))
			return TkBadtg;
	}

	fmt = "%d";
	arg = tkword(o, arg, buf, buf+sizeof(buf), nil);
	if(strcmp(buf, "above") == 0) {
		tkword(o, arg, buf, buf+sizeof(buf), nil);
		f = tkctaglook(tk, nil, buf);
		if(f == nil)
			return TkBadtg;

		t = tkclasttag(c->head, f->obj);
		if(t == nil)
			return TkBadtg;

		for(i = t->item->next; i; i = i->next) {
			if(af == TkCadd) {
				i->tags = tkmkname(tag);
				if(i->tags == nil)
					return TkNomem;
				tkcaddtag(tk, i, 0);
			}
			else {
				e = tkvalue(val, fmt, i->id);
				if(e != nil)
					return e;
				fmt = " %d";
			}
		}
		return nil;
	}

	if(strcmp(buf, "all") == 0) {
		for(i = c->head; i; i = i->next) {
			if(af == TkCadd) {
				i->tags = tkmkname(tag);
				if(i->tags == nil)
					return TkNomem;
				tkcaddtag(tk, i, 0);
			}
			else {
				e = tkvalue(val, fmt, i->id);
				if(e != nil)
					return e;
				fmt = " %d";
			}
		}
		return nil;
	}

	if(strcmp(buf, "below") == 0) {
		tkword(o, arg, buf, buf+sizeof(buf), nil);
		f = tkctaglook(tk, nil, buf);
		if(f == nil)
			return TkBadtg;
		tt = f->obj;
		for(b = c->head; b; b = b->next) {
			for(t = tt; t; t = t->itemlist)
				if(t->item == b)
					goto found;
		}
	found:
		for(i = c->head; i != b; i = i->next) {
			if(af == TkCadd) {
				i->tags = tkmkname(tag);
				if(i->tags == nil)
					return TkNomem;
				tkcaddtag(tk, i, 0);
			}
			else {
				e = tkvalue(val, fmt, i->id);
				if(e != nil)
					return e;
				fmt = " %d";
			}
		}
		return nil;
	}

	if(strcmp(buf, "closest") == 0) {
		e = tkfracword(o, &arg, &x, nil);
		if (e == nil)
			e = tkfracword(o, &arg, &y, nil);
		if (e != nil)
			return e;
		if(*arg != '\0')
			return "!not implemented";

		x = TKF2I(x);
		y = TKF2I(y);
		i = nil;
		dist = 0;
		for(b = c->head; b != nil; b = b->next) {
			dx = x - (b->p.bb.min.x + Dx(b->p.bb)/2);
			dy = y - (b->p.bb.min.y + Dy(b->p.bb)/2);
			d = dx*dx + dy*dy;
			if(d < dist || dist == 0) {
				i = b;
				dist = d;
			}
		}
		if(i == nil)
			return nil;

		if(af == TkCadd) {
			i->tags = tkmkname(tag);
			if(i->tags == nil)
				e = TkNomem;
			else
				tkcaddtag(tk, i, 0);
		}
		else
			e = tkvalue(val, fmt, i->id);
		return e;
	}

	if(strcmp(buf, "withtag") == 0) {
		tkword(o, arg, buf, buf+sizeof(buf), nil);
		f = tkctaglook(tk, nil, buf);
		if(f == nil)
			return TkBadtg;
		for(t = f->obj; t; t = t->taglist) {
			i = t->item;
			if(af == TkCadd) {
				i->tags = tkmkname(tag);
				if(i->tags == nil)
					return TkNomem;
				tkcaddtag(tk, i, 0);
			}
			else {
				e = tkvalue(val, fmt, i->id);
				if(e != nil)
					return e;
				fmt = " %d";
			}
		}
		return nil;
	}

	if(strcmp(buf, "enclosed") == 0) {
		e = tkparsepts(o, &p, &arg, 0);
		if(e != nil)
			goto done;
		if(p.npoint != 2) {
			e = TkFewpt;
			goto done;
		}
		for(i = c->head; i; i = i->next) {
			if(rectinrect(i->p.bb, p.bb)) {
				if(af == TkCadd) {
					i->tags = tkmkname(tag);
					if(i->tags == nil) {
						e = TkNomem;
						goto done;
					}
					tkcaddtag(tk, i, 0);
				}
				else {
					e = tkvalue(val, fmt, i->id);
					if(e != nil)
						goto done;
					fmt = " %d";
				}
			}
		}
		goto done;
	}

	if(strcmp(buf, "overlapping") == 0) {
		e = tkparsepts(o, &p, &arg, 0);
		if(e != nil)
			goto done;
		if(p.npoint != 2) {
			e = TkFewpt;
			goto done;
		}
		for(i = c->head; i; i = i->next) {
			if(rectXrect(i->p.bb, p.bb)) {
				if(af == TkCadd) {
					i->tags = tkmkname(tag);
					if(i->tags == nil) {
						e = TkNomem;
						goto done;
					}
					tkcaddtag(tk, i, 0);
				}
				else {
					e = tkvalue(val, "%d ", i->id);
					if(e != nil)
						goto done;
				}
			}
		}
		goto done;
	}

	return TkBadcm;

done: 		 /* both no error and error do the same thing */
	tkfreepoint(&p);
	return e;
}
Exemple #6
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;
}
Exemple #7
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);
}