text: #include <lib9.h>
  #include <image.h>
  #include <memimage.h>
  #include <memlayer.h>
  
  struct Lline
  {
  	Point			p0;
  	Point			p1;
  	Point			delta;
  	int			end0;
  	int			end1;
  	int			radius;
  	Point			sp;
  	Memlayer		*dstlayer;
  	Memimage	*src;
  };
  
  static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
  
  static
  void
  _memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr)
  {
  	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);
  		return;
  	}
  	if(!srcclipped){
  		d = subpt(sp, p0);
  		if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
  			return;
  		if(src->repl==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;
  	}
  
  	/* this is not the correct set of tests */
  	if(dst->ldepth != src->ldepth || dst->ldepth!=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;
  	memlayerop(llineop, dst, r, r, &ll);
  }
  
  static
  void
  llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
  {
  	struct Lline *ll;
  	Point p0, p1;
  
  	USED(screenr.min.x);
  	ll = etc;
  	if(insave && ll->dstlayer->save==nil)
  		return;
  	if(!rectclip(&clipr, screenr))
  		return;
  	if(insave){
  		p0 = subpt(ll->p0, ll->delta);
  		p1 = subpt(ll->p1, ll->delta);
  		clipr = rectsubpt(clipr, ll->delta);
  	}else{
  		p0 = ll->p0;
  		p1 = ll->p1;
  	}
  	_memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr);
  }
  
  void
  memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp)
  {
  	_memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr);
  }
  