beginnings of binaryout
[henge/apc.git] / src / binaryout.c
1 /* Standard */
2 #include <stdlib.h> //exit, malloc
3 #include <stdio.h> //print
4 #include <stdarg.h> //va_args
5 #include <string.h> //memset, str*
6 #include <errno.h>
7 /* Unicode */
8 #include <unistd.h> //u8_* functions
9 #include <unitypes.h> //uint8_t as a char
10 #include <unistr.h> //u32_cpy
11 #include <unistdio.h> //ulc_fprintf
12 /* Local */
13 #include "print.h"
14 #include "apc.h"
15 #include "ir.h"
16 #include "pagenode.h"
17 #undef do_error
18 #define do_error(...) exit(-1)
19 #define XXH_PRIVATE_API
20 #include "../xxHash/xxhash.h"
21 #define STB_IMAGE_IMPLEMENTATION
22 #include "stb_image.h"
23
24 /* Public */
25 void ir_binout_init(struct ir_class_t*);
26
27 /* Memory Allocation */
28 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
29 static
30 struct pagelist_t linkpages, datapages;
31
32 enum model_type { SS };
33 /* Binaryout out structure definitions */
34 struct bin_img_info_t {
35 int height;
36 int width;
37 int fwidth; //map and frame width
38 int fheight; //map and frame height
39 int unaligned_width;
40 int unaligned_height;
41 };
42 struct bin_ht_header_t {
43 long start;
44 int entries;
45 };
46 struct bin_ht_entry_t {
47 uint32_t key;
48 long value;
49 };
50 struct bin_class_header_t {
51 struct bin_ht_header_t child_ht;
52 struct bin_ht_header_t rootset_ht;
53 int namelen;
54 };
55 struct bin_set_header_t {
56 struct bin_ht_header_t child_ht;
57 long sdat_start; //points to setdata_header
58 int namelen;
59 };
60 struct bin_setdata_header_t {
61 struct bin_ht_header_t variant_ht;
62 long attach_pos;
63 };
64 struct bin_model_header_t { //one for each framebox, currently
65 long facing_array_start;
66 enum model_type type;
67 };
68 struct bin_frame_header_t {
69 int width;
70 int height;
71 int frames;
72 long op_start;
73 };
74 struct bin_plink_t {
75 enum ltype type;
76 ir_set trg_set;
77 uint8_t* name;
78 long src_pos;
79 };
80 struct bin_pixel_t {
81 int x, y, z;
82 uint32_t ref;
83 };
84 struct bin_pixel_node_t {
85 struct bin_pixel_node_t* next;
86 struct bin_pixel_t data;
87 };
88 struct bin_op_t {
89 int x;
90 int y;
91 int attach_idx;
92 };
93 struct bin_attachment_header_t {
94 int num_attachment_lists;
95 int num_attachments;
96 };
97 struct bin_attachment_t {
98 int idx;
99 ir_set set;
100 };
101 /* Read out of the als, after first ir pass, resolves the
102 attach_pos of the src-set that created the attachment_list
103 to the header that describes the attachment_list */
104 struct bin_attachment_list_t {
105 int num_attachments;
106 struct bin_attachment_t** attachments;
107 long filepos;
108 };
109
110 struct bin_attachment_list_t **attachment_stack, **asp; //attachment_stack, attachment_stack_pointer
111 FILE* binaryout;
112
113
114
115 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
116
117 /* Given a position and a size, checks if the bytes are null and returns
118 the file position to where it started. 1 if not null, 0 if null*/
119 /* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
120 static inline
121 int bytes_null( int len, int pos )
122 { while(len--)
123 { if(fgetc(binaryout) > 0)
124 { fseek(binaryout, pos, SEEK_SET);
125 return 1;
126 }
127 }
128 fseek(binaryout, pos, SEEK_SET);
129 return 0;
130 }
131 /* Checks if the key at entrypos is the same as the parameter key. Returns
132 1 if so, 0 if not. */
133 static inline
134 int bin_keys_identical
135 ( long entry_pos,
136 uint32_t key
137 )
138 { uint32_t curr_key;
139 fseek(binaryout, entry_pos, SEEK_SET);
140 fscanf(binaryout, "%u", &curr_key);
141 if( curr_key == key)
142 return 1;
143 return 0;
144 }
145
146 long bin_traverse_class(ir_class);
147 /* Takes root class and begins processing */
148 void
149 ir_binout_init(ir_class root_class)
150 { binaryout = fopen("binaryout", "w+");
151 asp = attachment_stack;
152 pagelist_init(datapages, (size_t) SYS_PAGESIZE);
153 pagelist_init(linkpages, (size_t) SYS_PAGESIZE);
154 bin_traverse_class(root_class);
155 }
156
157 #define ENTRY_OCCUPIED() (bytes_null(sizeof(ht_entry->key), entry_pos))
158 #define WRITE_ENTRY() do { \
159 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
160 fwrite(&ht_entry, sizeof ht_entry, 1, binaryout); \
161 } while (0)
162 #define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
163 #define INC_ENTRY() do { \
164 entry_pos += sizeof(ht_entry); \
165 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
166 } while (0)
167 #define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
168 void
169 /* TODO: Should overwrite be a default? */
170 bin_insert_ht_entry
171 ( long ht_start,
172 long ht_size,
173 struct bin_ht_entry_t* ht_entry,
174 int overwrite
175 )
176 { long entry_pos, ht_end;
177
178 ht_end = ht_start + ht_size;
179 entry_pos = ht_start + sizeof(ht_entry) * ht_entry->key;
180 fseek(binaryout, entry_pos, SEEK_SET);
181
182 if (!ENTRY_OCCUPIED())
183 { uprintf("key not occupied\n");
184 WRITE_ENTRY();
185 }
186 while( ENTRY_OCCUPIED() )
187 { if(overwrite)
188 { if(bin_keys_identical(entry_pos, ht_entry->key))
189 break;
190 else
191 { eprintf("error in hashtable insertion, keys are identical");
192 }
193 }
194 if (HT_END(ht_end))
195 LOOP_ENTRY(ht_start);
196 else
197 INC_ENTRY();
198 }
199 WRITE_ENTRY();
200
201 }
202
203 /* | class header |
204 |--------------------|
205 | rootset ht |
206 |--------------------|
207 | rootsets data |
208 |--------------------|
209 | classchild ht |
210 |--------------------|
211 | classchild header |
212 | ... |
213 */
214
215 long bin_traverse_set(ir_set);
216 long
217 #define HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
218 _SIZE = _INIT_ENTRIES ? (_INIT_ENTRIES * (sizeof(struct bin_ht_entry_t) << 1)): 0; \
219 _START = ftell(binaryout); \
220 fseek(binaryout, _SIZE, SEEK_CUR); \
221 } while (0)
222 bin_traverse_class
223 ( ir_class class)
224 { ir_class citer;
225 ir_set siter;
226 struct bin_class_header_t class_header;
227 struct bin_ht_entry_t ht_entry;
228 long class_start, classht_start, classht_size, rootsetht_start, rootsetht_size;
229 int num_csibs, num_ssibs;
230 uint8_t* class_name;
231
232 class_start = ftell(binaryout);
233 class_name = get_class_name(class);
234
235 num_csibs = get_class_sibcount(class);
236 num_ssibs = get_set_sibcount(get_class_root_set(class));
237
238 /* alloc space (before hash tables) for class header */
239 class_header.namelen = u8_strlen(class_name);
240 fseek(binaryout, class_start + sizeof(class_header) + class_header.namelen ,SEEK_SET);
241
242 HT_INIT(classht_start, classht_size, num_csibs);
243 HT_INIT(rootsetht_start, rootsetht_size, num_ssibs);
244
245 /* TODO: Figure out generic way to output headers */
246 /* populate class header */
247 class_header.child_ht.entries = num_csibs;
248 class_header.child_ht.start = classht_start;
249 class_header.rootset_ht.entries = num_ssibs;
250 class_header.rootset_ht.start = rootsetht_start;
251 fseek(binaryout, class_start, SEEK_SET); //seek back to where we allocated header
252 fwrite(&class_header, sizeof(class_header), 1, binaryout);
253 fwrite(class_name, class_header.namelen, 1, binaryout);
254
255 /* Start populating root_set hash table */
256 for ( siter = get_class_root_set(class); siter != NULL; siter = get_set_nextsib(siter))
257 { fseek(binaryout, 0, SEEK_END);
258 ht_entry.key = NAMEHASH(get_set_name(siter), num_ssibs << 1);
259 ht_entry.value = bin_traverse_set(siter);
260 bin_insert_ht_entry(rootsetht_start, rootsetht_size, &ht_entry, 0);
261 }
262
263 /* Start populating class child hash table */
264 for ( citer = get_class_nextchild(class); citer != NULL; citer = get_class_nextsib(citer))
265 { fseek(binaryout, 0, SEEK_END);
266 ht_entry.key = NAMEHASH(get_class_name(citer), num_csibs << 1);
267 ht_entry.value = bin_traverse_class(citer);
268 bin_insert_ht_entry(classht_start, classht_size, &ht_entry, 0);
269 }
270
271 return class_start;
272 }
273
274 long bin_process_sdat( ir_set);
275
276 /* | set header |--|
277 |-----------------| |
278 | set data |<-|
279 |-----------------| |
280 ---| setchild ht |<--
281 | |-----------------|
282 |->| setchild header |
283 |->| ... |
284 */
285
286 long
287 bin_traverse_set
288 ( ir_set set )
289 { ir_set iter;
290 struct bin_set_header_t header;
291 struct bin_ht_entry_t ht_entry;
292 int num_child, setname_len;
293 long childht_start, childht_size, set_start;
294 uint8_t* set_name;
295
296 set_start = ftell(binaryout);
297 set_name = get_set_name(set);
298
299 /* alloc space for set header */
300 setname_len = u8_strlen(set_name);
301 fseek(binaryout, sizeof(struct bin_set_header_t) + setname_len , SEEK_CUR);
302
303 /* process the set data */
304 header.sdat_start = bin_process_sdat(set);
305
306 /* Setup child hash table for current sets children */
307 num_child = get_set_sibcount(get_set_nextchild(set));
308 HT_INIT(childht_start, childht_size, num_child);
309
310 /* populate header, write to file */
311 header.child_ht.entries = num_child;
312 header.child_ht.start = childht_start;
313 fseek(binaryout, set_start, SEEK_SET);
314 fwrite(&header, sizeof(struct bin_set_header_t), 1, binaryout);
315 fwrite(set_name, setname_len, 1, binaryout);
316
317 for(iter = get_set_nextchild(set); iter != NULL; iter = get_set_nextsib(iter))
318 { fseek(binaryout, 0, SEEK_END);
319 ht_entry.key = NAMEHASH(get_set_name(iter), num_child << 1);
320 ht_entry.value = bin_traverse_set(iter);
321 bin_insert_ht_entry(childht_start, childht_size, &ht_entry, 0);
322 }
323
324
325 set_set_filepos(set, set_start);
326 return set_start;
327
328 }
329 /* | sdat header |
330 |------------------|
331 | variant ht |
332 |------------------|
333 | 1st variant data | -- variant == framebox
334 |------------------|
335 | 2nd variant data |
336 |------------------|
337 | etc. |
338
339 */
340
341 void bin_insert_links(int, struct bin_ht_header_t*, long);
342 struct bin_pixel_node_t* bin_find_default_pixel_list(ir_set);
343 void bin_process_frameboxes(ir_set, struct bin_ht_header_t*, struct bin_pixel_node_t*);
344 int bin_process_links(ir_set, ir_setdata);
345
346 /* Init the variant hash table for the set, process the sets links and add them to link_stack
347 and variant hash table, and then output the actual framedata */
348 long
349 bin_process_sdat
350 ( ir_set set )
351 { struct bin_setdata_header_t header;
352 struct bin_attachment_list_t attachment_list;
353 struct bin_pixel_node_t *default_pixel_list;
354 struct bin_ht_header_t ht_header;
355 long varht_start, varht_size, sdat_start;
356 int num_entries, num_links;
357 ir_setdata olink_head;
358
359 sdat_start = ftell(binaryout);
360
361 /* Alloc position for sdat_header */
362 fseek(binaryout, sizeof(struct bin_setdata_header_t), SEEK_CUR);
363
364 num_links = bin_process_links(set, olink_head);
365 num_entries = get_set_variants(set) + num_links;
366
367 HT_INIT(varht_start, varht_size, num_entries);
368
369 /* Populate the sdat_header */
370 fseek(binaryout, 0, sdat_start);
371 header.variant_ht.start = ht_header.start = varht_start;
372 header.variant_ht.entries = ht_header.entries = num_entries;
373 attachment_list.filepos = header.attach_pos = ftell(binaryout) + sizeof(varht_start) + sizeof(num_entries);
374 fwrite(&header, sizeof(header), 1, binaryout);
375 fseek(binaryout, 0, SEEK_END);
376
377 /* insert the links that were processed into the variant hash table */
378 bin_insert_links(num_links, &ht_header, attachment_list.filepos);
379 /* Determine the default pixel list for all of the frameboxes */
380 default_pixel_list = bin_find_default_pixel_list(set);
381 /* Output each framebox, and insert it into the variant hash table */
382 bin_process_frameboxes(set, &ht_header, default_pixel_list);
383
384 /* TODO: Convert the default pixel list to an attachment_list and then push the */
385 /* sdats attachment_list onto the attachment_stack so it can be procesed */
386
387
388 return sdat_start;
389 }
390
391
392 /* Adds a vlink onto the stack_alloc to be popped during the processing of the
393 sets variant hash table. If the vlink has a name, its a vlink to a single
394 variant. if the vlink doesnt have a name, its the vlink to an entire variant
395 hash table, and each variant (framebox) needs to be added */
396 int
397 bin_process_vlink
398 ( ir_setdata vlink,
399 ir_set trg_set
400 )
401 { struct bin_plink_t* plp;
402 ir_setdata fiter;
403 uint8_t* link_name;
404 int num_links;
405
406 num_links = 0;
407
408 /* TODO: Macroize? or not worth? */
409 link_name = get_link_name(vlink);
410
411 if (link_name)
412 { plp = struct_alloc(bin_plink_t);
413 plp->src_pos = 0; // TBD @ process_setdata
414 plp->name = link_name;
415 plp->trg_set = trg_set;
416 plp->type = VLINK;
417 num_links++;
418 }
419 else // linking a variant hash table
420 for (fiter = get_set_frameboxes(trg_set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
421 { plp = struct_alloc(bin_plink_t);
422 plp->src_pos = 0; // TBD @ process_setdata
423 plp->name = get_framebox_name(fiter);
424 plp->trg_set = trg_set;
425 plp->type = VLINK;
426 num_links++;
427 }
428
429 return num_links;
430
431 }
432
433 /* Adds an mlink to the stack_alloc, to be processed later */
434 int
435 bin_process_mlink
436 ( ir_setdata mlink,
437 ir_set trg_set
438 )
439 { struct bin_plink_t* plp;
440 uint8_t* mlink_name;
441 mlink_name = get_link_name(mlink);
442 plp = struct_alloc(bin_plink_t);
443 plp->src_pos = 0; //TBD after resolving the childlist | TODO: attach_pos?
444 if(mlink_name) plp->name = mlink_name;
445 plp->trg_set = trg_set;
446 plp->type = MLINK;
447
448 return 1;
449 }
450
451 /* TODO: implement this */
452 /* Determine if olink is already part of the olink_list.
453 if it is, theres a cycle, return 1. Else return 0. */
454 static inline
455 int olink_cycle
456 ( ir_setdata olink,
457 ir_setdata olink_head )
458 { ir_setdata iter;
459
460
461
462 return 0;
463
464
465 }
466
467 /* Given a set, determine the number of links it has and process each link and
468 then add them to stack_alloc, where they will be popped off and further processed. */
469 int
470 bin_process_links
471 ( ir_set src_set,
472 ir_setdata olink_head
473 )
474 { int num_links;
475 ir_setdata liter; //link iter
476 ir_set trg_set;
477
478 num_links = 0;
479
480 for(liter = get_set_links(src_set); liter != NULL; liter = get_link_nextsib(liter))
481 { trg_set = get_set_from_ref(get_link_ref(liter));
482 switch (get_link_type(liter)) {
483 case OLINK:
484 if (olink_cycle(liter, olink_head)) //TODO: stack of olinks to iterate and check for cycles?
485 return num_links;
486 num_links += bin_process_vlink(liter, trg_set);
487 num_links += bin_process_mlink(liter, trg_set);
488 num_links += bin_process_links(trg_set, liter);
489 break;
490 case VLINK:
491 num_links += bin_process_vlink(liter, trg_set);
492 break;
493 case MLINK:
494 num_links += bin_process_mlink(liter, trg_set);
495 break;
496 case ALINK: //TODO: ?
497 break;
498 }
499 }
500 return num_links;
501 }
502
503 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
504 have an additional requirement of being added into the variant hash table */
505 #define pop_linkp() (*(struct bin_plink_t**) pagelist_pop(&datapages, sizeof(struct bin_plink_t*)))
506 #define PUSH_PLINK(_LINK) (*(struct bin_plink_t**) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
507 void
508 bin_insert_links
509 ( int num_links,
510 struct bin_ht_header_t* ht,
511 long attach_pos
512 )
513 { struct bin_plink_t* plp;
514 struct bin_ht_entry_t ht_entry;
515 int i;
516
517 /* Insert vlinks into hash table, put v/mlinks on link stack to be processed later */
518 for ( i = 0; i < num_links; i++)
519 { plp = pop_linkp();
520 switch (plp->type) {
521 case MLINK:
522 plp->trg_set = plp->trg_set;
523 plp->src_pos = attach_pos;
524 PUSH_PLINK(plp);
525 break;
526 case VLINK:
527 ht_entry.key = NAMEHASH(plp->name, ht->entries << 1);
528 ht_entry.value = 0;
529 bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 0);
530 plp->src_pos = ht_entry.key + sizeof(ht_entry.key);
531 PUSH_PLINK(plp);
532 break;
533 case OLINK:
534 break;
535 //shouldnt exist
536 case ALINK:
537 break;
538 //TBD
539 }
540 }
541 }
542
543 long bin_process_facing(ir_setdata, apc_facing, struct bin_pixel_node_t*);
544 /* |-------------------|
545 | framebox header |
546 |-------------------|
547 | SFACE framesheet |
548 |-------------------|
549 | SWFACE framesheet |
550 |-------------------|
551 | etc. |
552 */
553 long
554 bin_process_framebox
555 ( ir_set set,
556 ir_setdata framebox,
557 struct bin_pixel_node_t* default_pixel_list
558 )
559 { struct bin_model_header_t header;
560 long framebox_start, index_pos;
561 int i;
562
563 framebox_start = ftell(binaryout);
564
565 /* insert model header */
566 header.type = SS;
567 header.facing_array_start = framebox_start + sizeof(header);
568 fwrite(&header, sizeof(header), 1, binaryout);
569
570 /* Create the index array for framesheet of each direction */
571 for ( i = SFACE; i < FACING_MAX; i++)
572 { fseek(binaryout, 0, SEEK_END);
573 index_pos = bin_process_facing(framebox, i, default_pixel_list); //TODO: finish process_direction
574 fseek(binaryout, header.facing_array_start + i * sizeof(long), SEEK_SET);
575 fwrite(&index_pos, sizeof(long), 1, binaryout);
576 }
577
578 return framebox_start;
579 }
580 void
581 bin_process_frameboxes
582 ( ir_set set,
583 struct bin_ht_header_t* ht,
584 struct bin_pixel_node_t* default_pixel_list
585 )
586 { struct bin_ht_entry_t ht_entry;
587 ir_setdata fiter;
588
589 /* Insert variants into hash table to overwrite olink insertions*/
590 for ( fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
591 { fseek(binaryout, 0, SEEK_END);
592 ht_entry.key = NAMEHASH(get_framebox_name(fiter), ht->entries << 1);
593 ht_entry.value = bin_process_framebox(set, fiter, default_pixel_list);
594 bin_insert_ht_entry(ht->start, ht->entries * sizeof(ht_entry), &ht_entry, 1);
595 }
596
597 }
598 /* Determine clipping based on image height/width and frame height/width */
599 static inline
600 void bin_set_img_info
601 ( struct bin_img_info_t* img_info,
602 ir_setdata framedata
603 )
604 { img_info->fwidth = get_framedata_width(framedata);
605 img_info->fheight = get_framedata_height(framedata);
606 img_info->unaligned_height = img_info->height % img_info->fheight;
607 img_info->unaligned_width = img_info->width % img_info->fwidth;
608
609 }
610
611 /* TODO: Implement this */
612 long
613 bin_process_frame
614 ()
615 {}
616
617
618
619 /* Combine the framesheet and mapsheet to create
620 the output sheet */
621 /* |-------------------------|
622 | outputsheet header |
623 |-------------------------|
624 | pixel data for frame1 |
625 |-------------------------|
626 | op data for frame1 |
627 |-------------------------|
628 | etc. | */
629 //TODO: processing direction sounds dumb, but cant call it process_framesheet because
630 // its actually the mapsheet and the framesheet. rename to output sheet?
631 /* THIS FUNCTION IS NOT DONE */
632 long
633 bin_process_facing
634 ( ir_setdata framebox,
635 apc_facing facing,
636 struct bin_pixel_node_t* default_pixel_list
637 )
638 { struct bin_img_info_t mapsheet_info, framesheet_info;
639 int num_mapchannels, num_framechannels;
640 long facing_start;
641 unsigned char* mapdata, * framedata;
642
643 facing_start = ftell(binaryout);
644
645
646 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
647 mapdata = stbi_load(get_framedata_name(get_framebox_facing_mapdata(framebox,SFACE)), &mapsheet_info.width, &mapsheet_info.width, &num_framechannels , 0);
648 framedata = stbi_load(get_framedata_name(get_framebox_facing_framedata(framebox,SFACE)), &framesheet_info.width, &framesheet_info.height, &num_mapchannels, 0);
649 bin_set_img_info(&framesheet_info, get_framebox_facing_framedata(framebox, SFACE));
650 bin_set_img_info(&mapsheet_info, get_framebox_facing_mapdata(framebox, SFACE));
651
652 /* TODO: output framesheet/direction header */
653
654
655 /* For each frame and map i in framesheet + mapsheet */
656 /* output frame data */
657 /* output op space for frames */
658 /* determine ops in map */
659 /* check if ops are acceptable */
660 /* output ops */
661
662
663 return facing_start;
664
665 }
666
667
668
669
670
671 /* Insert pixel(s) into the list, z sorted */
672 void
673 bin_insert_node_into_list
674 ( struct bin_pixel_node_t* pixel_list_root,
675 struct bin_pixel_node_t* pixel_node
676 )
677 { struct bin_pixel_node_t* head_node, *prev_node;
678 int node_z;
679
680 head_node = pixel_list_root->next;
681 node_z = pixel_node->data.z;
682
683 if(head_node == NULL)
684 { head_node = pixel_node;
685 }
686 prev_node = pixel_list_root;
687 while(head_node != NULL)
688 { if(node_z > head_node->data.z)
689 { prev_node = head_node;
690 head_node = head_node->next;
691 }
692 else if (node_z < head_node->data.z || node_z == head_node->data.z)
693 { prev_node->next = pixel_node;
694 pixel_node->next = head_node;
695 break;
696 }
697 }
698
699
700 }
701
702 /* TODO: Finish this */
703 struct bin_pixel_node_t*
704 bin_process_pixel
705 ( unsigned char* data,
706 int x,
707 int y,
708 int init_height,
709 int init_width
710 )
711 { struct bin_pixel_node_t* pixel_node;
712
713
714 pixel_node = struct_alloc(bin_pixel_node_t);
715
716 if(data)
717 { /* get ref from 4 bytes of data */
718 pixel_node->data.ref = (int) data;
719 /* bitshift by ? to get Z ordering */
720
721 /* set x and y */
722 pixel_node->data.x = x + init_width ;
723 pixel_node->data.y = y + init_width;
724 data += 4;
725 }
726 else
727 { data += 4; //TODO: does this correctly increment past 0x00000000?
728 return NULL;
729 }
730
731
732
733 return pixel_node;
734
735 }
736
737 /* Returns the non null pixels of a single frame */
738 /* TODO: Finish this */
739 struct bin_pixel_node_t*
740 bin_map_to_pixel_list
741 ( struct bin_img_info_t* img_info,
742 int init_height,
743 int init_width,
744 unsigned char* data
745 )
746 { int x, y;
747 struct bin_pixel_node_t* pixel_list, * pixel_node;
748
749 pixel_list = NULL;
750
751 /* Check if frame clips */
752 if( img_info->unaligned_width )
753 ;
754 if (img_info->unaligned_height )
755 ;
756
757 /* Process the map*/
758 for (y = 0; y < img_info->fheight; y++)
759 { for ( x = 0; x < img_info->fwidth; x++ )
760 { pixel_node = bin_process_pixel(data, x, y, init_height, init_width);
761 bin_insert_node_into_list(pixel_list, pixel_node);
762 }
763 }
764
765 return pixel_node;
766 }
767
768 static inline
769 int bin_pixel_list_len
770 ( struct bin_pixel_node_t* pl )
771 { struct bin_pixel_node_t* plp;
772 int count;
773 count = 0;
774 plp = pl;
775 while(plp)
776 { count++;
777 plp = plp->next;
778 }
779 return count;
780 }
781
782 struct bin_pixel_node_t*
783 bin_cmp_default_pixel_lists
784 ( struct bin_pixel_node_t* pl1,
785 struct bin_pixel_node_t* pl2
786 )
787 { struct bin_pixel_node_t* pl1p, * pl2p;
788 int i, pl1_len, pl2_len;
789
790 pl1p = pl1;
791 pl2p = pl2;
792 pl1_len = bin_pixel_list_len(pl1);
793 pl2_len = bin_pixel_list_len(pl2);
794
795 if (pl1_len > pl2_len)
796 return pl1;
797 else if (pl1_len < pl2_len)
798 return pl2;
799 /* pl1 == pl2, make sure that all refs are the same */
800 /* TODO: what type of warning/error handling should occur here? */
801 for (i = 0; i < pl1_len; i++)
802 { if (pl1p->data.ref != pl2p->data.ref)
803 eprintf("Error in determining default pixel list\n");
804 pl1p = pl1p->next;
805 pl2p = pl2p->next;
806 }
807 return pl1; //doesnt matter which one you return
808 }
809
810 /* Find default framebox, based on the framebox with the most attachments*/
811 /* Search through first frame of S of each framebox */
812 struct bin_pixel_node_t*
813 bin_find_default_pixel_list
814 ( ir_set set)
815 { ir_setdata fiter;
816 struct bin_pixel_node_t* default_pixel_list, * curr_pixel_list;
817 unsigned char* data;
818 int num_channels;
819 struct bin_img_info_t img_info;
820
821 for (fiter = get_set_frameboxes(set); fiter != NULL; fiter = get_framebox_nextsib(fiter))
822 { /* TODO: Stringify the frame name with .png? */
823 /* TODO: Add directory changing */
824 data = stbi_load(get_framedata_name(get_framebox_facing_mapdata(fiter, SFACE)), &img_info.width, &img_info.width, &num_channels, 0);
825 bin_set_img_info(&img_info, get_framebox_facing_mapdata(fiter, SFACE));
826 curr_pixel_list = bin_map_to_pixel_list(&img_info, 0, 0, data);
827 default_pixel_list = bin_cmp_default_pixel_lists(curr_pixel_list, default_pixel_list);
828
829 free(data);
830 }
831
832 return default_pixel_list;
833 }