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