1 #include "../lib9.h" 2 3 #include "../libdraw/draw.h" 4 #include "../libmemdraw/memdraw.h" 5 6 void 7 memimagemove(void *from, void *to) 8 { 9 Memdata *md; 10 11 md = *(Memdata**)to; 12 if(md->base != from){ 13 print("compacted data not right: #%p\n", md->base); 14 abort(); 15 } 16 md->base = to; 17 18 /* if allocmemimage changes this must change too */ 19 md->bdata = (uchar*)&md->base[2]; 20 } 21 22 Memimage* 23 allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X) 24 { 25 int d; 26 ulong l; 27 Memimage *i; 28 29 if((d = chantodepth(chan)) == 0) { 30 werrstr("bad channel descriptor %.8lux", chan); 31 return nil; 32 } 33 34 l = wordsperline(r, d); 35 36 i = mallocz(sizeof(Memimage)); 37 if(i == nil) 38 return nil; 39 40 i->data = md; 41 i->zero = sizeof(ulong)*l*r.min.y; 42 43 if(r.min.x >= 0) 44 i->zero += (r.min.x*d)/8; 45 else 46 i->zero -= (-r.min.x*d+7)/8; 47 i->zero = -i->zero; 48 i->width = l; 49 i->r = r; 50 i->clipr = r; 51 i->flags = 0; 52 i->layer = nil; 53 i->cmap = memdefcmap; 54 if(memsetchan(i, chan) < 0){ 55 free(i); 56 return nil; 57 } 58 i->X = X; 59 return i; 60 } 61 62 Memimage* 63 _allocmemimage(Rectangle r, ulong chan) 64 { 65 int d; 66 ulong l, nw; 67 Memdata *md; 68 Memimage *i; 69 70 if((d = chantodepth(chan)) == 0) { 71 werrstr("bad channel descriptor %.8lux", chan); 72 return nil; 73 } 74 75 l = wordsperline(r, d); 76 nw = l*Dy(r); 77 md = malloc(sizeof(Memdata)); 78 if(md == nil) 79 return nil; 80 81 md->ref = 1; 82 md->base = mallocz((2+nw)*sizeof(ulong)); 83 if(md->base == nil){ 84 free(md); 85 return nil; 86 } 87 88 md->base[0] = (ulong)md; 89 md->base[1] = getcallerpc(&r); 90 91 /* if this changes, memimagemove must change too */ 92 md->bdata = (uchar*)&md->base[2]; 93 94 md->allocd = 1; 95 96 i = allocmemimaged(r, chan, md, nil); 97 if(i == nil){ 98 free(md); 99 return nil; 100 } 101 md->imref = i; 102 return i; 103 } 104 105 void 106 _freememimage(Memimage *i) 107 { 108 if(i == nil) 109 return; 110 if(i->data->ref-- == 1 && i->data->allocd){ 111 if(i->data->base) 112 free(i->data->base); 113 free(i->data); 114 } 115 free(i); 116 } 117 118 /* 119 * Wordaddr is deprecated. 120 */ 121 ulong* 122 wordaddr(Memimage *i, Point p) 123 { 124 return (ulong*) ((ulong)byteaddr(i, p) & ~(sizeof(ulong)-1)); 125 } 126 127 uchar* 128 byteaddr(Memimage *i, Point p) 129 { 130 uchar *a; 131 132 a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; 133 134 if(i->depth < 8){ 135 /* 136 * We need to always round down, 137 * but C rounds toward zero. 138 */ 139 int np; 140 np = 8/i->depth; 141 if(p.x < 0) 142 return a+(p.x-np+1)/np; 143 else 144 return a+p.x/np; 145 } 146 else 147 return a+p.x*(i->depth/8); 148 } 149 150 void 151 _memfillcolor(Memimage *i, ulong val) 152 { 153 static Memimage *paint; 154 uchar *data; 155 156 if(paint == nil){ 157 paint = allocmemimage(Rect(0,0,1,1), ARGB32); 158 if(paint == nil) 159 return; 160 paint->clipr = Rect(-0x3FFFFFF,-0x3FFFFFF,0x3FFFFFF,0x3FFFFFF); 161 paint->flags |= Frepl; 162 } 163 164 data = byteaddr(paint, Pt(0,0)); 165 data[0] = val>>8; /* blue */ 166 data[1] = val>>16; /* green */ 167 data[2] = val>>24; /* red */ 168 data[3] = val; /* alpha */ 169 170 memimagedraw(i, i->r, paint, ZP, nil, ZP); 171 } 172 173 int 174 memsetchan(Memimage *i, ulong chan) 175 { 176 int d; 177 int t, j, k; 178 ulong cc; 179 int bytes; 180 181 assert(i->X == nil); 182 if((d = chantodepth(chan)) == 0) { 183 werrstr("bad channel descriptor"); 184 return -1; 185 } 186 187 i->depth = d; 188 i->chan = chan; 189 i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); 190 bytes = 1; 191 for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ 192 t=TYPE(cc); 193 if(t < 0 || t >= NChan){ 194 werrstr("bad channel string"); 195 return -1; 196 } 197 if(t == CGrey) 198 i->flags |= Fgrey; 199 if(t == CAlpha) 200 i->flags |= Falpha; 201 if(t == CMap && i->cmap == nil){ 202 i->cmap = memdefcmap; 203 i->flags |= Fcmap; 204 } 205 206 i->shift[t] = j; 207 i->mask[t] = (1<<NBITS(cc))-1; 208 i->nbits[t] = NBITS(cc); 209 if(NBITS(cc) != 8) 210 bytes = 0; 211 } 212 i->nchan = k; 213 if(bytes) 214 i->flags |= Fbytes; 215 return 0; 216 } 217