Note the default font color change in a few more places
[imager.git] / datatypes.c
CommitLineData
02d1d628
AMH
1#include <stdlib.h>
2#include <stdio.h>
35891892 3#include <string.h>
e310e5f9 4#include "imager.h"
02d1d628
AMH
5
6/*
7 2d bitmask with test and set operations
8*/
9
10struct i_bitmap*
8d14daab
TC
11btm_new(i_img_dim xsize,i_img_dim ysize) {
12 i_img_dim i;
13 size_t bytes;
02d1d628 14 struct i_bitmap *btm;
f0960b14
TC
15 btm=(struct i_bitmap*)mymalloc(sizeof(struct i_bitmap)); /* checked 4jul05 tonyc */
16 bytes = (xsize*ysize+8)/8;
17 if (bytes * 8 / ysize < xsize-1) { /* this is kind of rough */
8d14daab
TC
18 fprintf(stderr, "Integer overflow allocating bitmap (" i_DFp ")",
19 i_DFcp(xsize, ysize));
f0960b14
TC
20 exit(3);
21 }
22 btm->data=(char*)mymalloc(bytes); /* checked 4jul05 tonyc */
02d1d628
AMH
23 btm->xsize=xsize;
24 btm->ysize=ysize;
25 for(i=0;i<(xsize*ysize+8)/8;i++) btm->data[i]=0; /* Is this always needed */
26 return btm;
27}
28
29
30void
31btm_destroy(struct i_bitmap *btm) {
32 myfree(btm->data);
33 myfree(btm);
34}
35
36
37int
8d14daab
TC
38btm_test(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
39 i_img_dim btno;
02d1d628
AMH
40 if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) return 0;
41 btno=btm->xsize*y+x;
42 return (1<<(btno%8))&(btm->data[btno/8]);
43}
44
45void
8d14daab
TC
46btm_set(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
47 i_img_dim btno;
e25e59b1 48 if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) abort();
02d1d628
AMH
49 btno=btm->xsize*y+x;
50 btm->data[btno/8]|=1<<(btno%8);
51}
52
53
54
55
56
57/*
a73aeb5f 58 Bucketed linked list - stack type
02d1d628
AMH
59*/
60
8d14daab
TC
61static struct llink *
62llink_new(struct llink* p,size_t size);
63static int
64llist_llink_push(struct llist *lst, struct llink *lnk,const void *data);
65static void
66llink_destroy(struct llink* l);
02d1d628 67
8d14daab
TC
68/*
69=item llist_new()
70=synopsis struct llist *l = llist_new(100, sizeof(foo);
02d1d628 71
8d14daab 72Create a new stack structure. Implemented as a linked list of pools.
02d1d628 73
8d14daab 74Parameters:
02d1d628 75
8d14daab 76=over
02d1d628 77
8d14daab 78=item *
02d1d628 79
8d14daab
TC
80multip - number of entries in each pool
81
82=item *
83
84ssize - size of the objects being pushed/popped
85
86=back
87
88=cut
89*/
02d1d628
AMH
90
91struct llist *
8d14daab 92llist_new(int multip, size_t ssize) {
02d1d628 93 struct llist *l;
f0960b14 94 l = mymalloc(sizeof(struct llist)); /* checked 4jul05 tonyc */
a73aeb5f
AMH
95 l->h = NULL;
96 l->t = NULL;
97 l->multip = multip;
98 l->ssize = ssize;
99 l->count = 0;
02d1d628
AMH
100 return l;
101}
102
8d14daab
TC
103/*
104=item llist_push()
105=synopsis llist_push(l, &foo);
106
107Push an item on the stack.
108
109=cut
110*/
111
02d1d628 112void
8d14daab
TC
113llist_push(struct llist *l,const void *data) {
114 size_t ssize = l->ssize;
a73aeb5f 115 int multip = l->multip;
02d1d628 116
a73aeb5f
AMH
117 /* fprintf(stderr,"llist_push: data=0x%08X\n",data);
118 fprintf(stderr,"Chain size: %d\n", l->count); */
119
120 if (l->t == NULL) {
121 l->t = l->h = llink_new(NULL,ssize*multip); /* Tail is empty - list is empty */
122 /* fprintf(stderr,"Chain empty - extended\n"); */
123 }
02d1d628
AMH
124 else { /* Check for overflow in current tail */
125 if (l->t->fill >= l->multip) {
a73aeb5f 126 struct llink* nt = llink_new(l->t, ssize*multip);
02d1d628
AMH
127 l->t->n=nt;
128 l->t=nt;
129 /* fprintf(stderr,"Chain extended\n"); */
130 }
131 }
132 /* fprintf(stderr,"0x%08X\n",l->t); */
a73aeb5f 133 if (llist_llink_push(l,l->t,data)) {
b1e96952 134 i_fatal(3, "out of memory\n");
a73aeb5f 135 }
02d1d628
AMH
136}
137
8d14daab
TC
138/*
139=item llist_pop()
140
141Pop an item off the list, storing it at C<data> which must have enough room for an object of the size supplied to llist_new().
142
143returns 0 if the list is empty
144
145=cut
146*/
02d1d628
AMH
147
148int
149llist_pop(struct llist *l,void *data) {
150 /* int ssize=l->ssize;
151 int multip=l->multip;*/
152 if (l->t == NULL) return 0;
153 l->t->fill--;
154 l->count--;
02d1d628
AMH
155 memcpy(data,(char*)(l->t->data)+l->ssize*l->t->fill,l->ssize);
156
157 if (!l->t->fill) { /* This link empty */
a73aeb5f
AMH
158 if (l->t->p == NULL) { /* and it's the only link */
159 llink_destroy(l->t);
160 l->h = l->t = NULL;
161 }
02d1d628
AMH
162 else {
163 l->t=l->t->p;
164 llink_destroy(l->t->n);
165 }
166 }
167 return 1;
168}
169
170void
171llist_dump(struct llist *l) {
bc8930e3 172 int j;
02d1d628
AMH
173 int i=0;
174 struct llink *lnk;
175 lnk=l->h;
176 while(lnk != NULL) {
177 for(j=0;j<lnk->fill;j++) {
178 /* memcpy(&k,(char*)(lnk->data)+l->ssize*j,sizeof(void*));*/
bc8930e3 179 /*memcpy(&k,(char*)(lnk->data)+l->ssize*j,sizeof(void*));*/
5e2762ac 180 printf("%d - %p\n",i,*(void **)((char *)(lnk->data)+l->ssize*j));
02d1d628
AMH
181 i++;
182 }
183 lnk=lnk->n;
184 }
185}
186
8d14daab
TC
187/*
188=item llist_destroy()
189
190Destroy a linked-list based stack.
191
192=cut
193*/
194
02d1d628
AMH
195void
196llist_destroy(struct llist *l) {
197 struct llink *t,*lnk = l->h;
198 while( lnk != NULL ) {
199 t=lnk;
200 lnk=lnk->n;
201 myfree(t);
202 }
203 myfree(l);
204}
205
8d14daab
TC
206/* Links */
207
208static struct llink *
209llink_new(struct llink* p,size_t size) {
210 struct llink *l;
211 l = mymalloc(sizeof(struct llink)); /* checked 4jul05 tonyc */
212 l->n = NULL;
213 l->p = p;
214 l->fill = 0;
215 l->data = mymalloc(size); /* checked 4jul05 tonyc - depends on caller to llist_push */
216 return l;
217}
218
219/* free's the data pointer, itself, and sets the previous' next pointer to null */
220
221static void
222llink_destroy(struct llink* l) {
223 if (l->p != NULL) { l->p->n=NULL; }
224 myfree(l->data);
225 myfree(l);
226}
02d1d628
AMH
227
228
8d14daab
TC
229/* if it returns true there wasn't room for the
230 item on the link */
02d1d628 231
8d14daab
TC
232static int
233llist_llink_push(struct llist *lst, struct llink *lnk, const void *data) {
234 int multip;
235 multip = lst->multip;
02d1d628 236
8d14daab
TC
237 /* fprintf(stderr,"llist_llink_push: data=0x%08X -> 0x%08X\n",data,*(int*)data);
238 fprintf(stderr,"ssize = %d, multip = %d, fill = %d\n",lst->ssize,lst->multip,lnk->fill); */
239 if (lnk->fill == lst->multip) return 1;
240 /* memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize); */
241 memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize);
242
243 /* printf("data=%X res=%X\n",*(int*)data,*(int*)(lnk->data));*/
244 lnk->fill++;
245 lst->count++;
246 return 0;
247}
02d1d628
AMH
248
249/*
250 Oct-tree implementation
251*/
252
253struct octt *
254octt_new() {
255 int i;
256 struct octt *t;
257
f0960b14 258 t=(struct octt*)mymalloc(sizeof(struct octt)); /* checked 4jul05 tonyc */
02d1d628
AMH
259 for(i=0;i<8;i++) t->t[i]=NULL;
260 t->cnt=0;
261 return t;
262}
263
264
265/* returns 1 if the colors wasn't in the octtree already */
266
267
268int
269octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b) {
270 struct octt *c;
271 int i,cm;
fe622da1 272 int ci;
02d1d628
AMH
273 int rc;
274 rc=0;
275 c=ct;
276 /* printf("[r,g,b]=[%d,%d,%d]\n",r,g,b); */
02d1d628
AMH
277 for(i=7;i>-1;i--) {
278 cm=1<<i;
279 ci=((!!(r&cm))<<2)+((!!(g&cm))<<1)+!!(b&cm);
280 /* printf("idx[%d]=%d\n",i,ci); */
fe622da1
TC
281 if (c->t[ci] == NULL) {
282 c->t[ci]=octt_new();
283 rc=1;
284 }
02d1d628 285 c=c->t[ci];
02d1d628 286 }
fe622da1 287 c->cnt++; /* New. The only thing really needed (I think) */
02d1d628
AMH
288 return rc;
289}
290
291
292void
293octt_delete(struct octt *ct) {
294 int i;
295 for(i=0;i<8;i++) if (ct->t[i] != NULL) octt_delete(ct->t[i]); /* do not free instance here because it will free itself */
296 myfree(ct);
297}
298
299
300void
301octt_dump(struct octt *ct) {
302 int i;
303 /* printf("node [0x%08X] -> (%d)\n",ct,ct->cnt); */
8a2cd317
TC
304 for(i=0;i<8;i++)
305 if (ct->t[i] != NULL)
306 printf("[ %d ] -> %p\n", i, (void *)ct->t[i]);
307 for(i=0;i<8;i++)
308 if (ct->t[i] != NULL)
309 octt_dump(ct->t[i]);
02d1d628
AMH
310}
311
312/* note that all calls of octt_count are operating on the same overflow
313 variable so all calls will know at the same time if an overflow
314 has occured and stops there. */
315
316void
317octt_count(struct octt *ct,int *tot,int max,int *overflow) {
318 int i,c;
319 c=0;
320 if (!(*overflow)) return;
321 for(i=0;i<8;i++) if (ct->t[i]!=NULL) {
322 octt_count(ct->t[i],tot,max,overflow);
323 c++;
324 }
325 if (!c) (*tot)++;
326 if ( (*tot) > (*overflow) ) *overflow=0;
327}
fe622da1
TC
328
329/* This whole function is new */
330/* walk through the tree and for each colour, store its seen count in the
331 space pointed by *col_usage_it_adr */
332void
333octt_histo(struct octt *ct, unsigned int **col_usage_it_adr) {
334 int i,c;
335 c = 0;
336 for(i = 0; i < 8; i++)
337 if (ct->t[i] != NULL) {
338 octt_histo(ct->t[i], col_usage_it_adr);
339 c++;
340 }
341 if (!c) {
342 *(*col_usage_it_adr)++ = ct->cnt;
343 }
344}
345
346
8d14daab
TC
347i_img_dim
348i_abs(i_img_dim x) {
349 return x < 0 ? -x : x;
350}