]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/swcursor.c
merge
[plan9front.git] / sys / src / 9 / port / swcursor.c
1 #include        "u.h"
2 #include        "../port/lib.h"
3 #include        "mem.h"
4 #include        "dat.h"
5 #include        "fns.h"
6 #include        "../port/error.h"
7
8 #define Image   IMAGE
9 #include        <draw.h>
10 #include        <memdraw.h>
11 #include        <cursor.h>
12 #include        "screen.h"
13
14 extern Memimage* gscreen;
15
16 /*
17  * Software cursor. 
18  */
19 static Memimage*        swback;         /* screen under cursor */
20 static Memimage*        swimg;          /* cursor image */
21 static Memimage*        swmask;         /* cursor mask */
22 static Memimage*        swimg1;
23 static Memimage*        swmask1;
24
25 static Point            swoffset;
26 static Rectangle        swrect;         /* screen rectangle in swback */
27 static Point            swvispt;        /* actual cursor location */
28 static int              swvisible;      /* is the cursor visible? */
29
30 /*
31  * called with drawlock locked for us, most of the time.
32  * kernel prints at inopportune times might mean we don't
33  * hold the lock, but memimagedraw is now reentrant so
34  * that should be okay: worst case we get cursor droppings.
35  */
36 void
37 swcursorhide(void)
38 {
39         if(swvisible == 0)
40                 return;
41         if(swback == nil || gscreen == nil)
42                 return;
43         swvisible = 0;
44         memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
45         flushmemscreen(swrect);
46 }
47
48 void
49 swcursoravoid(Rectangle r)
50 {
51         if(swvisible && rectXrect(r, swrect)){
52                 swcursorhide();
53                 mouseredraw();  /* schedule cursor redraw after we release drawlock */
54         }
55 }
56
57 void
58 swcursordraw(Point p)
59 {
60         if(swvisible)
61                 return;
62         if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil)
63                 return;
64         assert(!canqlock(&drawlock));
65         swvispt = addpt(swoffset, p);
66         swrect = rectaddpt(Rect(0,0,16,16), swvispt);
67         memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S);
68         memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
69         flushmemscreen(swrect);
70         swvisible = 1;
71 }
72
73 void
74 swcursorload(Cursor *curs)
75 {
76         uchar *ip, *mp;
77         int i, j, set, clr;
78
79         if(swimg == nil || swmask == nil || swimg1 == nil || swmask1 == nil)
80                 return;
81         /*
82          * Build cursor image and mask.
83          * Image is just the usual cursor image
84          * but mask is a transparent alpha mask.
85          * 
86          * The 16x16x8 memimages do not have
87          * padding at the end of their scan lines.
88          */
89         ip = byteaddr(swimg, ZP);
90         mp = byteaddr(swmask, ZP);
91         for(i=0; i<32; i++){
92                 set = curs->set[i];
93                 clr = curs->clr[i];
94                 for(j=0x80; j; j>>=1){
95                         *ip++ = set&j ? 0x00 : 0xFF;
96                         *mp++ = (clr|set)&j ? 0xFF : 0x00;
97                 }
98         }
99         swoffset = curs->offset;
100         memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
101         memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
102
103         mouseredraw();
104 }
105
106 void
107 swcursorinit(void)
108 {
109         if(gscreen == nil)
110                 return;
111
112         if(swback){
113                 freememimage(swback);
114                 freememimage(swmask);
115                 freememimage(swmask1);
116                 freememimage(swimg);
117                 freememimage(swimg1); 
118         }
119         swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
120         swmask = allocmemimage(Rect(0,0,16,16), GREY8);
121         swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
122         swimg = allocmemimage(Rect(0,0,16,16), GREY8);
123         swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
124         if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){
125                 print("software cursor: allocmemimage fails\n");
126                 return;
127         }
128         memfillcolor(swback, DTransparent);
129         memfillcolor(swmask, DOpaque);
130         memfillcolor(swmask1, DOpaque);
131         memfillcolor(swimg, DBlack);
132         memfillcolor(swimg1, DBlack);
133 }