xref: /plan9/sys/src/cmd/unix/drawterm/libmemlayer/line.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include "../lib9.h"
2*7dd7cddfSDavid du Colombier 
3*7dd7cddfSDavid du Colombier #include "../libdraw/draw.h"
4*7dd7cddfSDavid du Colombier #include "../libmemdraw/memdraw.h"
5*7dd7cddfSDavid du Colombier #include "../libmemlayer/memlayer.h"
6*7dd7cddfSDavid du Colombier 
7*7dd7cddfSDavid du Colombier struct Lline
8*7dd7cddfSDavid du Colombier {
9*7dd7cddfSDavid du Colombier 	Point			p0;
10*7dd7cddfSDavid du Colombier 	Point			p1;
11*7dd7cddfSDavid du Colombier 	Point			delta;
12*7dd7cddfSDavid du Colombier 	int			end0;
13*7dd7cddfSDavid du Colombier 	int			end1;
14*7dd7cddfSDavid du Colombier 	int			radius;
15*7dd7cddfSDavid du Colombier 	Point			sp;
16*7dd7cddfSDavid du Colombier 	Memlayer		*dstlayer;
17*7dd7cddfSDavid du Colombier 	Memimage	*src;
18*7dd7cddfSDavid du Colombier };
19*7dd7cddfSDavid du Colombier 
20*7dd7cddfSDavid du Colombier static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
21*7dd7cddfSDavid du Colombier 
22*7dd7cddfSDavid du Colombier static
23*7dd7cddfSDavid du Colombier void
24*7dd7cddfSDavid du Colombier _memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr)
25*7dd7cddfSDavid du Colombier {
26*7dd7cddfSDavid du Colombier 	Rectangle r;
27*7dd7cddfSDavid du Colombier 	struct Lline ll;
28*7dd7cddfSDavid du Colombier 	Point d;
29*7dd7cddfSDavid du Colombier 	int srcclipped;
30*7dd7cddfSDavid du Colombier 	Memlayer *dl;
31*7dd7cddfSDavid du Colombier 
32*7dd7cddfSDavid du Colombier 	if(radius < 0)
33*7dd7cddfSDavid du Colombier 		return;
34*7dd7cddfSDavid du Colombier 	if(src->layer)	/* can't draw line with layered source */
35*7dd7cddfSDavid du Colombier 		return;
36*7dd7cddfSDavid du Colombier 	srcclipped = 0;
37*7dd7cddfSDavid du Colombier 
38*7dd7cddfSDavid du Colombier    Top:
39*7dd7cddfSDavid du Colombier 	dl = dst->layer;
40*7dd7cddfSDavid du Colombier 	if(dl == nil){
41*7dd7cddfSDavid du Colombier 		_memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr);
42*7dd7cddfSDavid du Colombier 		return;
43*7dd7cddfSDavid du Colombier 	}
44*7dd7cddfSDavid du Colombier 	if(!srcclipped){
45*7dd7cddfSDavid du Colombier 		d = subpt(sp, p0);
46*7dd7cddfSDavid du Colombier 		if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
47*7dd7cddfSDavid du Colombier 			return;
48*7dd7cddfSDavid du Colombier 		if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
49*7dd7cddfSDavid du Colombier 			return;
50*7dd7cddfSDavid du Colombier 		srcclipped = 1;
51*7dd7cddfSDavid du Colombier 	}
52*7dd7cddfSDavid du Colombier 
53*7dd7cddfSDavid du Colombier 	/* dst is known to be a layer */
54*7dd7cddfSDavid du Colombier 	p0.x += dl->delta.x;
55*7dd7cddfSDavid du Colombier 	p0.y += dl->delta.y;
56*7dd7cddfSDavid du Colombier 	p1.x += dl->delta.x;
57*7dd7cddfSDavid du Colombier 	p1.y += dl->delta.y;
58*7dd7cddfSDavid du Colombier 	clipr.min.x += dl->delta.x;
59*7dd7cddfSDavid du Colombier 	clipr.min.y += dl->delta.y;
60*7dd7cddfSDavid du Colombier 	clipr.max.x += dl->delta.x;
61*7dd7cddfSDavid du Colombier 	clipr.max.y += dl->delta.y;
62*7dd7cddfSDavid du Colombier 	if(dl->clear){
63*7dd7cddfSDavid du Colombier 		dst = dst->layer->screen->image;
64*7dd7cddfSDavid du Colombier 		goto Top;
65*7dd7cddfSDavid du Colombier 	}
66*7dd7cddfSDavid du Colombier 
67*7dd7cddfSDavid du Colombier 	/* XXX */
68*7dd7cddfSDavid du Colombier 	/* this is not the correct set of tests */
69*7dd7cddfSDavid du Colombier /*
70*7dd7cddfSDavid du Colombier 	if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3)
71*7dd7cddfSDavid du Colombier 		return;
72*7dd7cddfSDavid du Colombier */
73*7dd7cddfSDavid du Colombier 
74*7dd7cddfSDavid du Colombier 	/* can't use sutherland-cohen clipping because lines are wide */
75*7dd7cddfSDavid du Colombier 	r = memlinebbox(p0, p1, end0, end1, radius);
76*7dd7cddfSDavid du Colombier 	/*
77*7dd7cddfSDavid du Colombier 	 * r is now a bounding box for the line;
78*7dd7cddfSDavid du Colombier 	 * use it as a clipping rectangle for subdivision
79*7dd7cddfSDavid du Colombier 	 */
80*7dd7cddfSDavid du Colombier 	if(rectclip(&r, clipr) == 0)
81*7dd7cddfSDavid du Colombier 		return;
82*7dd7cddfSDavid du Colombier 	ll.p0 = p0;
83*7dd7cddfSDavid du Colombier 	ll.p1 = p1;
84*7dd7cddfSDavid du Colombier 	ll.end0 = end0;
85*7dd7cddfSDavid du Colombier 	ll.end1 = end1;
86*7dd7cddfSDavid du Colombier 	ll.sp = sp;
87*7dd7cddfSDavid du Colombier 	ll.dstlayer = dst->layer;
88*7dd7cddfSDavid du Colombier 	ll.src = src;
89*7dd7cddfSDavid du Colombier 	ll.radius = radius;
90*7dd7cddfSDavid du Colombier 	ll.delta = dl->delta;
91*7dd7cddfSDavid du Colombier 	memlayerop(llineop, dst, r, r, &ll);
92*7dd7cddfSDavid du Colombier }
93*7dd7cddfSDavid du Colombier 
94*7dd7cddfSDavid du Colombier static
95*7dd7cddfSDavid du Colombier void
96*7dd7cddfSDavid du Colombier llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
97*7dd7cddfSDavid du Colombier {
98*7dd7cddfSDavid du Colombier 	struct Lline *ll;
99*7dd7cddfSDavid du Colombier 	Point p0, p1;
100*7dd7cddfSDavid du Colombier 
101*7dd7cddfSDavid du Colombier 	USED(screenr.min.x);
102*7dd7cddfSDavid du Colombier 	ll = etc;
103*7dd7cddfSDavid du Colombier 	if(insave && ll->dstlayer->save==nil)
104*7dd7cddfSDavid du Colombier 		return;
105*7dd7cddfSDavid du Colombier 	if(!rectclip(&clipr, screenr))
106*7dd7cddfSDavid du Colombier 		return;
107*7dd7cddfSDavid du Colombier 	if(insave){
108*7dd7cddfSDavid du Colombier 		p0 = subpt(ll->p0, ll->delta);
109*7dd7cddfSDavid du Colombier 		p1 = subpt(ll->p1, ll->delta);
110*7dd7cddfSDavid du Colombier 		clipr = rectsubpt(clipr, ll->delta);
111*7dd7cddfSDavid du Colombier 	}else{
112*7dd7cddfSDavid du Colombier 		p0 = ll->p0;
113*7dd7cddfSDavid du Colombier 		p1 = ll->p1;
114*7dd7cddfSDavid du Colombier 	}
115*7dd7cddfSDavid du Colombier 	_memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr);
116*7dd7cddfSDavid du Colombier }
117*7dd7cddfSDavid du Colombier 
118*7dd7cddfSDavid du Colombier void
119*7dd7cddfSDavid du Colombier memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp)
120*7dd7cddfSDavid du Colombier {
121*7dd7cddfSDavid du Colombier 	_memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr);
122*7dd7cddfSDavid du Colombier }
123