vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

draw.c (4063B)


      1 #include "u.h"
      2 #include "lib.h"
      3 #include "draw.h"
      4 #include "memdraw.h"
      5 #include "memlayer.h"
      6 
      7 struct Draw
      8 {
      9 	Point	deltas;
     10 	Point	deltam;
     11 	Memlayer		*dstlayer;
     12 	Memimage	*src;
     13 	Memimage	*mask;
     14 	int	op;
     15 };
     16 
     17 static
     18 void
     19 ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
     20 {
     21 	struct Draw *d;
     22 	Point p0, p1;
     23 	Rectangle oclipr, srcr, r, mr;
     24 	int ok;
     25 
     26 	d = etc;
     27 	if(insave && d->dstlayer->save==nil)
     28 		return;
     29 
     30 	p0 = addpt(screenr.min, d->deltas);
     31 	p1 = addpt(screenr.min, d->deltam);
     32 
     33 	if(insave){
     34 		r = rectsubpt(screenr, d->dstlayer->delta);
     35 		clipr = rectsubpt(clipr, d->dstlayer->delta);
     36 	}else
     37 		r = screenr;
     38 
     39 	/* now in logical coordinates */
     40 
     41 	/* clipr may have narrowed what we should draw on, so clip if necessary */
     42 	if(!rectinrect(r, clipr)){
     43 		oclipr = dst->clipr;
     44 		dst->clipr = clipr;
     45 		ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
     46 		dst->clipr = oclipr;
     47 		if(!ok)
     48 			return;
     49 	}
     50 	memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
     51 }
     52 
     53 void
     54 memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
     55 {
     56 	struct Draw d;
     57 	Rectangle srcr, tr, mr;
     58 	Memlayer *dl, *sl;
     59 
     60 	if(drawdebug)
     61 		iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
     62 
     63 	if(mask == nil)
     64 		mask = memopaque;
     65 
     66 	if(mask->layer){
     67 if(drawdebug)	iprint("mask->layer != nil\n");
     68 		return;	/* too hard, at least for now */
     69 	}
     70 
     71     Top:
     72 	if(dst->layer==nil && src->layer==nil){
     73 		memimagedraw(dst, r, src, p0, mask, p1, op);
     74 		return;
     75 	}
     76 
     77 	if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
     78 if(drawdebug)	iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
     79 		return;
     80 	}
     81 
     82 	/*
     83  	 * Convert to screen coordinates.
     84 	 */
     85 	dl = dst->layer;
     86 	if(dl != nil){
     87 		r.min.x += dl->delta.x;
     88 		r.min.y += dl->delta.y;
     89 		r.max.x += dl->delta.x;
     90 		r.max.y += dl->delta.y;
     91 	}
     92     Clearlayer:
     93 	if(dl!=nil && dl->clear){
     94 		if(src == dst){
     95 			p0.x += dl->delta.x;
     96 			p0.y += dl->delta.y;
     97 			src = dl->screen->image;
     98 		}
     99 		dst = dl->screen->image;
    100 		goto Top;
    101 	}
    102 
    103 	sl = src->layer;
    104 	if(sl != nil){
    105 		p0.x += sl->delta.x;
    106 		p0.y += sl->delta.y;
    107 		srcr.min.x += sl->delta.x;
    108 		srcr.min.y += sl->delta.y;
    109 		srcr.max.x += sl->delta.x;
    110 		srcr.max.y += sl->delta.y;
    111 	}
    112 
    113 	/*
    114 	 * Now everything is in screen coordinates.
    115 	 * mask is an image.  dst and src are images or obscured layers.
    116 	 */
    117 
    118 	/*
    119 	 * if dst and src are the same layer, just draw in save area and expose.
    120 	 */
    121 	if(dl!=nil && dst==src){
    122 		if(dl->save == nil)
    123 			return;	/* refresh function makes this case unworkable */
    124 		if(rectXrect(r, srcr)){
    125 			tr = r;
    126 			if(srcr.min.x < tr.min.x){
    127 				p1.x += tr.min.x - srcr.min.x;
    128 				tr.min.x = srcr.min.x;
    129 			}
    130 			if(srcr.min.y < tr.min.y){
    131 				p1.y += tr.min.x - srcr.min.x;
    132 				tr.min.y = srcr.min.y;
    133 			}
    134 			if(srcr.max.x > tr.max.x)
    135 				tr.max.x = srcr.max.x;
    136 			if(srcr.max.y > tr.max.y)
    137 				tr.max.y = srcr.max.y;
    138 			memlhide(dst, tr);
    139 		}else{
    140 			memlhide(dst, r);
    141 			memlhide(dst, srcr);
    142 		}
    143 		memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
    144 			subpt(srcr.min, src->layer->delta), mask, p1, op);
    145 		memlexpose(dst, r);
    146 		return;
    147 	}
    148 
    149 	if(sl){
    150 		if(sl->clear){
    151 			src = sl->screen->image;
    152 			if(dl != nil){
    153 				r.min.x -= dl->delta.x;
    154 				r.min.y -= dl->delta.y;
    155 				r.max.x -= dl->delta.x;
    156 				r.max.y -= dl->delta.y;
    157 			}
    158 			goto Top;
    159 		}
    160 		/* relatively rare case; use save area */
    161 		if(sl->save == nil)
    162 			return;	/* refresh function makes this case unworkable */
    163 		memlhide(src, srcr);
    164 		/* convert back to logical coordinates */
    165 		p0.x -= sl->delta.x;
    166 		p0.y -= sl->delta.y;
    167 		srcr.min.x -= sl->delta.x;
    168 		srcr.min.y -= sl->delta.y;
    169 		srcr.max.x -= sl->delta.x;
    170 		srcr.max.y -= sl->delta.y;
    171 		src = src->layer->save;
    172 	}
    173 
    174 	/*
    175 	 * src is now an image.  dst may be an image or a clear layer
    176 	 */
    177 	if(dst->layer==nil)
    178 		goto Top;
    179 	if(dst->layer->clear)
    180 		goto Clearlayer;
    181 
    182 	/*
    183 	 * dst is an obscured layer
    184 	 */
    185 	d.deltas = subpt(p0, r.min);
    186 	d.deltam = subpt(p1, r.min);
    187 	d.dstlayer = dl;
    188 	d.src = src;
    189 	d.op = op;
    190 	d.mask = mask;
    191 	_memlayerop(ldrawop, dst, r, r, &d);
    192 }