1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 5 extern ulong 6 drawld2chan[] = { 7 GREY1, 8 GREY2, 9 GREY4, 10 CMAP8, 11 }; 12 13 int log2[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5 }; 14 15 Image* 16 allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val) 17 { 18 return _allocimage(nil, d, r, chan, repl, val, 0, 0); 19 } 20 21 Image* 22 _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh) 23 { 24 uchar *a; 25 char *err; 26 Image *i; 27 Rectangle clipr; 28 int id; 29 int depth; 30 31 err = 0; 32 i = 0; 33 34 if(chan == 0){ 35 werrstr("bad channel descriptor"); 36 return nil; 37 } 38 39 depth = chantodepth(chan); 40 if(depth == 0){ 41 err = "bad channel descriptor"; 42 Error: 43 if(err) 44 werrstr("allocimage: %s", err); 45 else 46 werrstr("allocimage: %r"); 47 free(i); 48 return 0; 49 } 50 51 /* flush pending data so we don't get error allocating the image */ 52 flushimage(d, 0); 53 a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4); 54 if(a == 0) 55 goto Error; 56 d->imageid++; 57 id = d->imageid; 58 a[0] = 'b'; 59 BPLONG(a+1, id); 60 BPLONG(a+5, screenid); 61 a[9] = refresh; 62 BPLONG(a+10, chan); 63 a[14] = repl; 64 BPLONG(a+15, r.min.x); 65 BPLONG(a+19, r.min.y); 66 BPLONG(a+23, r.max.x); 67 BPLONG(a+27, r.max.y); 68 if(repl) 69 /* huge but not infinite, so various offsets will leave it huge, not overflow */ 70 clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF); 71 else 72 clipr = r; 73 BPLONG(a+31, clipr.min.x); 74 BPLONG(a+35, clipr.min.y); 75 BPLONG(a+39, clipr.max.x); 76 BPLONG(a+43, clipr.max.y); 77 BPLONG(a+47, val); 78 if(flushimage(d, 0) < 0) 79 goto Error; 80 81 if(ai) 82 i = ai; 83 else{ 84 i = malloc(sizeof(Image)); 85 if(i == nil){ 86 a = bufimage(d, 1+4); 87 if(a){ 88 a[0] = 'f'; 89 BPLONG(a+1, id); 90 flushimage(d, 0); 91 } 92 goto Error; 93 } 94 } 95 i->display = d; 96 i->id = id; 97 i->depth = depth; 98 i->chan = chan; 99 i->r = r; 100 i->clipr = clipr; 101 i->repl = repl; 102 i->screen = 0; 103 i->next = 0; 104 return i; 105 } 106 107 Image* 108 namedimage(Display *d, char *name) 109 { 110 uchar *a; 111 char *err, buf[12*12+1]; 112 Image *i; 113 int id, n; 114 ulong chan; 115 116 err = 0; 117 i = 0; 118 119 n = strlen(name); 120 if(n >= 256){ 121 err = "name too long"; 122 Error: 123 if(err) 124 werrstr("namedimage: %s", err); 125 else 126 werrstr("namedimage: %r"); 127 if(i) 128 free(i); 129 return 0; 130 } 131 /* flush pending data so we don't get error allocating the image */ 132 flushimage(d, 0); 133 a = bufimage(d, 1+4+1+n); 134 if(a == 0) 135 goto Error; 136 d->imageid++; 137 id = d->imageid; 138 a[0] = 'n'; 139 BPLONG(a+1, id); 140 a[5] = n; 141 memmove(a+6, name, n); 142 if(flushimage(d, 0) < 0) 143 goto Error; 144 145 if(read(d->ctlfd, buf, sizeof buf) < 12*12) 146 goto Error; 147 148 i = malloc(sizeof(Image)); 149 if(i == nil){ 150 Error1: 151 a = bufimage(d, 1+4); 152 if(a){ 153 a[0] = 'f'; 154 BPLONG(a+1, id); 155 flushimage(d, 0); 156 } 157 goto Error; 158 } 159 i->display = d; 160 i->id = id; 161 if((chan=strtochan(buf+2*12))==0){ 162 werrstr("bad channel from devdraw"); 163 goto Error1; 164 } 165 i->chan = chan; 166 i->depth = chantodepth(chan); 167 i->repl = atoi(buf+3*12); 168 i->r.min.x = atoi(buf+4*12); 169 i->r.min.y = atoi(buf+5*12); 170 i->r.max.x = atoi(buf+6*12); 171 i->r.max.y = atoi(buf+7*12); 172 i->clipr.min.x = atoi(buf+8*12); 173 i->clipr.min.y = atoi(buf+9*12); 174 i->clipr.max.x = atoi(buf+10*12); 175 i->clipr.max.y = atoi(buf+11*12); 176 i->screen = 0; 177 i->next = 0; 178 return i; 179 } 180 181 int 182 nameimage(Image *i, char *name, int in) 183 { 184 uchar *a; 185 int n; 186 187 n = strlen(name); 188 a = bufimage(i->display, 1+4+1+1+n); 189 if(a == 0) 190 return 0; 191 a[0] = 'N'; 192 BPLONG(a+1, i->id); 193 a[5] = in; 194 a[6] = n; 195 memmove(a+7, name, n); 196 if(flushimage(i->display, 0) < 0) 197 return 0; 198 return 1; 199 } 200 201 int 202 _freeimage1(Image *i) 203 { 204 uchar *a; 205 Display *d; 206 Image *w; 207 208 if(i == 0) 209 return 0; 210 /* make sure no refresh events occur on this if we block in the write */ 211 d = i->display; 212 /* flush pending data so we don't get error deleting the image */ 213 flushimage(d, 0); 214 a = bufimage(d, 1+4); 215 if(a == 0) 216 return -1; 217 a[0] = 'f'; 218 BPLONG(a+1, i->id); 219 if(i->screen){ 220 w = d->windows; 221 if(w == i) 222 d->windows = i->next; 223 else 224 while(w){ 225 if(w->next == i){ 226 w->next = i->next; 227 break; 228 } 229 w = w->next; 230 } 231 } 232 if(flushimage(d, i->screen!=0) < 0) 233 return -1; 234 235 return 0; 236 } 237 238 int 239 freeimage(Image *i) 240 { 241 int ret; 242 243 ret = _freeimage1(i); 244 free(i); 245 return ret; 246 } 247