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 int 151 memsetchan(Memimage *i, ulong chan) 152 { 153 int d; 154 int t, j, k; 155 ulong cc; 156 int bytes; 157 158 assert(i->X == nil); 159 if((d = chantodepth(chan)) == 0) { 160 werrstr("bad channel descriptor"); 161 return -1; 162 } 163 164 i->depth = d; 165 i->chan = chan; 166 i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); 167 bytes = 1; 168 for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ 169 t=TYPE(cc); 170 if(t < 0 || t >= NChan){ 171 werrstr("bad channel string"); 172 return -1; 173 } 174 if(t == CGrey) 175 i->flags |= Fgrey; 176 if(t == CAlpha) 177 i->flags |= Falpha; 178 if(t == CMap && i->cmap == nil){ 179 i->cmap = memdefcmap; 180 i->flags |= Fcmap; 181 } 182 183 i->shift[t] = j; 184 i->mask[t] = (1<<NBITS(cc))-1; 185 i->nbits[t] = NBITS(cc); 186 if(NBITS(cc) != 8) 187 bytes = 0; 188 } 189 i->nchan = k; 190 if(bytes) 191 i->flags |= Fbytes; 192 return 0; 193 } 194