2 #include <stdlib.h> //exit, malloc
3 #include <stdio.h> //print
4 #include <stdarg.h> //va_args
5 #include <string.h> //memset, str*
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
18 #define do_error(...) exit(-1)
19 #define XXH_PRIVATE_API
20 #include "../xxHash/xxhash.h"
21 #define STB_IMAGE_IMPLEMENTATION
22 #include "../stb/stb_image.h"
23 #define STB_IMAGE_WRITE_IMPLEMENTATION
24 #include "../stb/stb_image_write.h"
27 void ir_binout_init(struct ir_class_t
*);
29 /* Memory Allocation */
30 #define struct_alloc(_T) ((struct _T*) stack_alloc(&datapages, sizeof(struct _T)))
32 struct pagelist_t linkpages
, datapages
, plinkpages
;
34 enum model_type
{ SS
};
35 /* Binaryout out structure definitions */
36 struct bin_img_info_t
{
39 int fwidth
; //map and frame width
40 int fheight
; //map and frame height
44 struct bin_ht_header_t
{
49 struct bin_default_ht_entry_t
{
53 struct bin_var_ht_entry_t
{
58 struct bin_class_header_t
{
59 struct bin_ht_header_t child_ht
;
60 struct bin_ht_header_t rootset_ht
;
63 struct bin_set_header_t
{
64 struct bin_ht_header_t child_ht
;
65 long sdat_start
; //points to setdata_header
68 struct bin_setdata_header_t
{
69 struct bin_ht_header_t variant_ht
;
72 struct bin_model_header_t
{ //one for each framebox, currently
73 long facing_array_start
;
76 struct bin_frame_header_t
{
88 struct bin_pixel_node_t
{
89 struct bin_pixel_node_t
* next
;
90 struct bin_pixel_t data
;
92 struct bin_attachment_header_t
{
93 int num_attachment_lists
;
96 struct bin_attachment_t
{
100 /* Read out of the als, after first ir pass, resolves the
101 attach_pos of the src-set that created the attachment_list
102 to the header that describes the attachment_list */
103 struct bin_attachment_list_t
{
105 struct bin_attachment_t
** attachments
;
108 struct bin_linklist_t
;
109 struct bin_linklist_t
110 { struct bin_linklist_t
* next
;
114 struct bin_processed_links_t
115 { struct bin_linklist_t
* vlink_list
;
117 struct bin_linklist_t
* mlink_list
;
119 struct bin_linklist_t
* olink_list
; //keep track of olink cycles
121 struct bin_linklist_t
* dlink_list
;
124 struct bin_pixel_ht_entry_t
129 struct bin_pixel_ht_t
130 { struct bin_pixel_ht_t
* next
;
131 struct bin_pixel_ht_entry_t
[] hash_entries
;
134 struct bin_attachment_list_t
**attachment_stack
, **asp
; //attachment_stack, attachment_stack_pointer
138 #define NAMEHASH(name, domain) (XXH32(name, u8_strlen(name), 0XCEED ) & domain)
139 #define REFHASH(ref, domain) (XXH32(&ref, sizeof(uint32_t), 0xCEED) & domain)
146 for (iter
= ir_set_framebox(set
); iter
!= NULL
; iter
= ir_setdata_nextsib(iter
))
152 int bin_class_sibcount
157 for (iter
= class; iter
!= NULL
; iter
= ir_class_nextsib(iter
))
168 for (iter
= set
; iter
!= NULL
; iter
= ir_set_nextsib(iter
))
173 /* Given a position and a size, checks if the bytes are null and returns
174 the file position to where it started. 1 if not null, 0 if null*/
175 /* TODO: Determine why fseeking file past end sets bytes to -1, and not 0 */
177 int bytes_null( int len
, int pos
)
179 { if(fgetc(binaryout
) > 0)
180 { fseek(binaryout
, pos
, SEEK_SET
);
184 fseek(binaryout
, pos
, SEEK_SET
);
187 /* Checks if the key at entrypos is the same as the parameter key. Returns
188 1 if so, 0 if not. */
190 int bin_keys_identical
195 fseek(binaryout
, entry_pos
, SEEK_SET
);
196 fscanf(binaryout
, "%u", &curr_key
);
203 typedef uint32_t RGBA_t
;
205 long bin_traverse_class(ir_class
);
206 /* Takes root class and begins processing */
208 ir_binout_init(ir_class root_class
)
209 { binaryout
= fopen("binaryout", "w+");
210 asp
= attachment_stack
;
211 pagelist_init(datapages
, (size_t) SYS_PAGESIZE
);
212 pagelist_init(linkpages
, (size_t) SYS_PAGESIZE
);
213 pagelist_init(plinkpages
, (size_t) SYS_PAGESIZE
);
214 bin_traverse_class(root_class
);
218 /* Returns the key position where the hash table entry was inserted. */
219 #define ENTRY_OCCUPIED() (bytes_null(uint32_t), entry_pos))
220 #define LOOP_ENTRY(_HTSTART) (entry_pos = _HTSTART)
221 #define WRITE_DEF_ENTRY() do { \
222 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
223 fwrite(&def_ht_entry, sizeof def_ht_entry, 1, binaryout); \
225 #define INC_DEF_ENTRY() do { \
226 entry_pos += sizeof(def_ht_entry); \
227 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
229 #define HT_END(_HTEND) (entry_pos >= _HTEND) //just in case at last entry
231 bin_insert_default_ht_entry
234 struct bin_def_ht_entry_t
* def_ht_entry
,
237 { long entry_pos
, ht_end
;
239 ht_end
= ht_start
+ ht_size
;
240 entry_pos
= ht_start
+ sizeof(ht_entry
) * ht_entry
->key
;
241 fseek(binaryout
, entry_pos
, SEEK_SET
);
243 if (!ENTRY_OCCUPIED())
244 { uprintf("key not occupied\n");
247 while( ENTRY_OCCUPIED() )
249 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
252 { eprintf("error in hashtable insertion, keys are identical");
256 LOOP_ENTRY(ht_start
);
266 #define WRITE_VAR_ENTRY() do { \
267 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) wprintf("fseek failed with %s", strerror(errno)); \
268 fwrite(&var_ht_entry, sizeof var_ht_entry, 1, binaryout); \
270 #define INC_VAR_ENTRY() do { \
271 entry_pos += sizeof(var_ht_entry); \
272 if(fseek(binaryout, entry_pos, SEEK_SET) == -1) eprintf("fseek failed with %s", strerror(errno)); \
274 bin_insert_var_ht_entry
277 struct bin_var_ht_entry_t
* var_ht_entry
,
280 { long entry_pos
, ht_end
;
282 ht_end
= ht_start
+ ht_size
;
283 entry_pos
= ht_start
+ sizeof(var_ht_entry
) * ht_entry
->key
;
284 fseek(binaryout
, entry_pos
, SEEK_SET
);
286 if (!ENTRY_OCCUPIED())
287 { uprintf("key not occupied\n");
290 while( ENTRY_OCCUPIED() )
292 { if(bin_keys_identical(entry_pos
, ht_entry
->key
))
295 { eprintf("error in hashtable insertion, keys are identical");
299 LOOP_ENTRY(ht_start
);
307 /** @see http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
309 int bin_calculate_ht_entries
311 { entries
= (entries
<< 1) - 1;
312 entries
|= entries
>> 1;
313 entries
|= entries
>> 2;
314 entries
|= entries
>> 4;
315 entries
|= entries
>> 8;
316 entries
|= entries
>> 16;
321 |--------------------|
323 |--------------------|
325 |--------------------|
327 |--------------------|
328 | classchild header |
332 long bin_traverse_set(ir_set
);
334 #define DEF_HT_INIT(_START, _SIZE, _INIT_ENTRIES) do { \
335 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
336 _START = ftell(binaryout); \
337 fseek(binaryout, _SIZE, SEEK_CUR); \
339 #define VAR_HT_INIT(_START, _SIZE, _ENTRIES) do { \
340 _SIZE = _ENTRIES * sizeof(var_ht_entry); \
341 _START = ftell(binaryout); \
342 fseek(binaryout, _SIZE, SEEK_CUR); \
348 struct bin_class_header_t class_header
;
349 struct bin_def_ht_entry_t ht_entry
;
350 long class_start
, classht_start
, classht_size
, rootsetht_start
, rootsetht_size
;
351 int num_class_entries
, num_rootset_entries
;
354 class_start
= ftell(binaryout
);
355 class_name
= ir_class_name(class);
357 num_class_entries
= bin_calculate_ht_entries(bin_class_sibcount(class));
358 num_rootset_entries
= bin_calculate_ht_entries(ir_class_rootset(class));
360 /* alloc space (before hash tables) for class header */
361 class_header
.namelen
= u8_strlen(class_name
);
362 fseek(binaryout
, class_start
+ sizeof(class_header
) + class_header
.namelen
,SEEK_SET
);
364 DEF_HT_INIT(classht_start
, classht_size
, num_class_entries
);
365 DEF_HT_INIT(rootsetht_start
, rootsetht_size
, num_rootset_entries
);
367 /* TODO: Figure out generic way to output headers */
368 /* populate class header */
369 class_header
.child_ht
.entries
= num_class_entries
;
370 class_header
.child_ht
.start
= classht_start
;
371 class_header
.child_ht
.size
= classht_size
;
372 class_header
.rootset_ht
.entries
= num_rootset_entries
;
373 class_header
.rootset_ht
.start
= rootsetht_start
;
374 class_header
.rootset_ht
.size
= rootsetht_size
;
375 fseek(binaryout
, class_start
, SEEK_SET
); //seek back to where we allocated header
376 fwrite(&class_header
, sizeof(class_header
), 1, binaryout
);
377 fwrite(class_name
, class_header
.namelen
, 1, binaryout
);
379 /* Start populating root_set hash table */
380 for ( siter
= ir_class_rootset(class); siter
!= NULL
; siter
= ir_set_nextsib(siter
))
381 { fseek(binaryout
, 0, SEEK_END
);
382 ht_entry
.key
= NAMEHASH(ir_set_name(siter
), num_rootset_entries
);
383 ht_entry
.value
= bin_traverse_set(siter
);
384 bin_insert_def_ht_entry(rootsetht_start
, rootsetht_size
, &ht_entry
, 0);
387 /* Start populating class child hash table */
388 for ( citer
= ir_class_nextchild(class); citer
!= NULL
; citer
= ir_class_nextsib(citer
))
389 { if(chdir((char*) class_name
))
390 eprintf("CHDIR %U from %s\n",(char*) class_name
,getcwd(NULL
,255));
391 fseek(binaryout
, 0, SEEK_END
);
392 ht_entry
.key
= NAMEHASH(ir_class_name(citer
), num_class_entries
);
393 ht_entry
.value
= bin_traverse_class(citer
);
394 bin_insert_def_ht_entry(classht_start
, classht_size
, &ht_entry
, 0);
396 eprintf("CHDIR ..\n");
402 long bin_process_sdat( ir_set
);
405 |-----------------| |
407 |-----------------| |
408 ---| setchild ht |<--
409 | |-----------------|
410 |->| setchild header |
418 struct bin_set_header_t header
;
419 struct bin_def_ht_entry_t ht_entry
;
420 int num_entries
, setname_len
;
421 long childht_start
, childht_size
, set_start
;
424 set_start
= ftell(binaryout
);
425 set_name
= ir_set_name(set
);
427 /* alloc space for set header */
428 setname_len
= u8_strlen(set_name
);
429 fseek(binaryout
, sizeof(struct bin_set_header_t
) + setname_len
, SEEK_CUR
);
431 /* process the set data */
432 header
.sdat_start
= bin_process_sdat(set
);
434 /* Setup child hash table for current sets children */
435 num_entries
= bin_calculate_ht_entries(bin_set_sibcount(ir_set_nextchild(set
)));
437 DEF_HT_INIT(childht_start
, childht_size
, num_child
);
439 /* populate header, write to file */
440 header
.child_ht
.entries
= num_entries
;
441 header
.child_ht
.start
= childht_start
;
442 header
.child_ht
.size
= childht_size
;
443 fseek(binaryout
, set_start
, SEEK_SET
);
444 fwrite(&header
, sizeof(struct bin_set_header_t
), 1, binaryout
);
445 fwrite(set_name
, setname_len
, 1, binaryout
);
447 for(iter
= ir_set_nextchild(set
); iter
!= NULL
; iter
= ir_set_nextsib(iter
))
448 { fseek(binaryout
, 0, SEEK_END
);
449 ht_entry
.key
= NAMEHASH(ir_set_name(iter
), num_entries
);
450 ht_entry
.value
= bin_traverse_set(iter
);
451 bin_insert_def_ht_entry(childht_start
, childht_size
, &ht_entry
, 0);
455 ir_set_assign_fpos(set
, set_start
);
469 | 1st variant data | -- variant == framebox
477 static inline void bin_insert_links(struct bin_processed_links_t
*, struct bin_ht_header_t
*, long);
478 static inline struct bin_pixel_node_t
* bin_find_default_pixel_list(ir_set
);
479 static inline void bin_process_frameboxes(ir_set
, struct bin_ht_header_t
*, struct bin_pixel_node_t
*);
480 static inline struct bin_processed_links_t
* bin_process_links(ir_set
, struct bin_processed_links_t
*);
481 static inline void bin_process_dlinks(struct bin_processed_links_t
*);
483 /* Init the variant hash table for the set, process the sets links and add them to link_stack
484 and variant hash table, and then output the actual framedata */
488 { struct bin_setdata_header_t header
;
489 struct bin_attachment_list_t attachment_list
;
490 struct bin_pixel_node_t
*default_pixel_list
;
491 struct bin_ht_header_t ht_header
;
492 struct bin_processed_links_t
* processed_links_root
;
493 long varht_start
, varht_size
, sdat_start
;
494 int num_entries
, num_links
;
496 sdat_start
= ftell(binaryout
);
498 /* Alloc position for sdat_header */
499 fseek(binaryout
, sizeof(struct bin_setdata_header_t
), SEEK_CUR
);
501 /* set up root for processed_links */
502 processed_links_root
= stack_alloc(&plinkpages
, sizeof(struct bin_processed_links_t
));
503 processed_links_root
->mlink_len
= processed_links_root
->vlink_len
= processed_links_root
->dlink_len
= processed_links_root
->olinks_len
= 0;
504 processed_links_root
= bin_process_links(set
, processed_links_root
);
506 num_links
= processed_links_root
->mlink_len
+ processed_links_root
->vlink_len
;
508 num_entries
= bin_calculate_ht_entries(bin_set_varcount(set
) + num_links
);
510 VAR_HT_INIT(varht_start
, varht_size
, num_entries
);
512 /* Populate the sdat_header */
513 fseek(binaryout
, 0, sdat_start
);
514 header
.variant_ht
.start
= varht_start
;
515 header
.variant_ht
.entries
= num_entries
;
516 header
.variant_ht
.size
= varht_size
;
517 attachment_list
.filepos
= header
.attach_pos
= ftell(binaryout
) + sizeof(varht_start
) + sizeof(num_entries
);
518 fwrite(&header
, sizeof(header
), 1, binaryout
);
519 fseek(binaryout
, 0, SEEK_ENDhttps
://en.wikipedia.org/wiki/Generic_programming);
522 bin_process_dlinks(processed_links_root
);
524 /* Determine the default pixel list for all of the frameboxes */
525 default_pixel_list
= bin_find_default_pixel_list(set
);
526 /* Output each framebox, and insert it into the variant hash table */
527 bin_process_frameboxes(set
, &ht_header
, default_pixel_list
);
529 /* insert the links that were processed into the variant hash table */
530 bin_insert_links(processed_links_root
, &ht_header
, attachment_list
.filepos
);
532 /* TODO: Convert the default pixel list to an attachment_list and then push the */
533 /* sdats attachment_list onto the attachment_stack so it can be procesed */
541 void bin_process_dlinks
542 ( struct bin_processed_links_t
* processed_links
)
543 { struct bin_linklist_t
* dlink_iter
;
544 for( dlink_iter
= processed_links
->dlink_list
; dlink_iter
!= NULL
; dlink_iter
= dlink_iter
->next
)
545 { /* TODO: Construct its fully qualified name based on its linkdata*/
547 /* Output an int for its length, and then output the name */
554 struct bin_linklist_t
* bin_linklist_head
555 ( struct bin_linklist_t
* root
)
556 { struct bin_linklist_t
* head
;
563 /* We dont know src_pos at this point because this is still in the control flow
564 of bin_process_links, which determines the number of links, which determines
567 #define PUSH_LINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof(linkdata)) = _LINK)
570 struct bin_processed_links_t
* processed_links
)
571 { struct bin_linklist_t
* llp
;
572 struct bin_linklist_t
* vlink_list_head
;
578 vlink_list_head
= bin_linklist_head(processed_links
->vlink_list
);
579 link_name
= ir_setdata_name(vlink
);
581 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
582 llp
->linkdata
= vlink
;
583 vlink_list_head
->next
= llp
;
584 processed_links
->vlink_len
++;
586 else // linking a variant hash table
587 { trg_set
= ir_linkdata_set(vlink
);
588 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
589 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
590 new_vlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
591 ir_data_assign_path(new_vlink
,ir_setdata_name(fiter
));
592 ir_linkdata_assign_set(new_vlink
,trg_set
);
593 ir_linkdata_assign_type(new_vlink
,VLINK
);
594 llp
->linkdata
= vlink
;
595 vlink_list_head
->next
= llp
;
596 processed_links
->vlink_len
++;
603 /* Adds an mlink to the stack_alloc, to be processed later */
608 struct bin_processed_links_t
* processed_links
610 { uint8_t* mlink_name
;
611 struct bin_linklist_t
* llp
;
612 struct bin_linklist_t
* mlink_list_head
;
618 mlink_list_head
= bin_linklist_head(processed_links
->mlink_list
);
619 mlink_name
= ir_setdata_name(mlink
);
622 { llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
623 llp
->linkdata
= mlink
;
624 mlink_list_head
->next
= llp
;
625 processed_links
->mlink_len
++;
628 { trg_set
= ir_linkdata_set(mlink
);
629 for (fiter
= ir_set_framebox(trg_set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
630 { //TODO: check here if illegal mlink(linking to a opsheet of a vdat not in src_set domain)?
631 llp
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
632 new_mlink
= stack_alloc(&plinkpages
, sizeof(linkdata
));
633 ir_data_assign_path(new_mlink
,ir_setdata_name(fiter
));//TODO: assign name
634 ir_linkdata_assign_set(new_vlink
,trg_set
);
635 ir_linkdata_assign_type(new_vlink
,VLINK
);
636 llp
->linkdata
= vlink
;
637 vlink_list_head
->next
= llp
;
638 processed_links
->vlink_len
++;
644 return processed_links
;
647 /* Determine if olink is already part of the olink_list.
648 if it is, theres a cycle, return 1. Else return 0. */
652 struct bin_processed_links_t
* processed_links
654 { struct bin_linklist_t
* iter
;
656 olink_set
= ir_linkdata_set(olink
);
657 for( iter
= processed_links
->olink_list
; iter
!= NULL
; iter
= iter
->next
)
658 if(ir_linkdata_set(iter
->linkdata
) == olink_set
)
663 /* if olink, process target sets frameboxes(turn into vlinks) and its attachment_list (turn into mlink),
664 else its a dlink so just add it to the processed_links list*/
666 void bin_process_olink
669 struct bin_processed_links_t
* processed_links_root
671 { struct bin_linklist_t
* link_list_head
;
672 struct bin_linklist_t
* new_link
;
674 new_link
= stack_alloc(&plinkpages
, sizeof(bin_linklist_t
));
675 if(trg_set
) //add olink to list so we can check for cycles
676 { bin_set_frameboxes_vlinks(trg_set
, processed_links_root
); //TODO:
677 bin_set_attachmentlist_mlink(trg_set
, processed_links_root
); //TODO:
678 link_list_head
= bin_linklist_head(processed_links_root
->olink_list
);
679 new_link
->linkdata
= olink
;
680 link_list_head
->next
= new_link
;
682 else // olink is actually a dynamic link
683 { link_list_head
= bin_linklist_head(processed_links_root
->dlink_list
);
684 new_link
->linkdata
= olink
;
685 link_list_head
->next
= new_link
;
691 /* Given a set, determine the number of links it has and process each link and
692 then add them to stack_alloc, where they will be popped off and further processed. */
693 struct bin_processed_links_t
* bin_process_links
695 struct bin_processed_links_t
* processed_links_root
699 for(linkdata
= ir_set_link(src_set
); linkdata
!= NULL
; linkdata
= ir_setdata_nextsib((ir_setdata
) linkdata
))
700 { switch (ir_linkdata_type(linkdata
)) {
702 if (olink_cycle(linkdata
, processed_links_root
))
703 return processed_links_root
; //TODO: what return value?
704 trg_set
= ir_linkdata_set(linkdata
);
705 bin_process_olink(trg_set
, linkdata
, processed_links_root
);
706 bin_process_links(trg_set
, processed_links_root
);
709 bin_process_vlink(linkdata
, processed_links_root
);
712 bin_process_mlink(linkdata
, processed_links_root
);
714 case ALINK
: //TODO: ?
718 return processed_links_root
;
721 /* Insert both mlinks and vlinks into the link stack, after determining their src_pos. Vlinks
722 have an additional requirement of being added into the variant hash table */
723 #define FRAME_POS() (entry_pos + sizeof(long))
724 #define MAP_POS() (entry_pos + sizeof(long)*2)
725 #define PUSH_PLINK(_LINK) (*(linkdata*) stack_alloc(&linkpages, sizeof (_LINK)) = _LINK )
728 ( struct bin_processed_links_t
* links
,
729 struct bin_ht_header_t
* ht
,
732 { struct bin_plink_t
* plp
;
733 struct bin_var_ht_entry_t ht_entry
;
734 struct bin_linklist_t
* vlinkiter
, *mlinkiter
;
738 /* Insert vlinks and mlinks into hash table, put v/mlinks on link stack to be processed later */
739 for ( vlinkiter
= links
->vlink_list
; vlinkiter
!= NULL
; vlinkiter
= vlinkiter
->next
)
740 { ht_entry
.key
= NAMEHASH(ir_setdata_name(vlinkiter
->linkdata
), ht
->entries
);
742 entry_pos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
743 ir_setdata_assign_fpos(vlinkiter
->linkdata
, FRAME_POS());
744 PUSH_PLINK(vlinkiter
->linkdata
);
746 /* TODO: If name exists in src_set, overwrite. if it dont, print a warning */
747 for ( mlinkiter
= links
->mlink_list
; mlinkiter
!= NULL
; mlinkiter
= mlinkiter
->next
)
748 { ht_entry
.key
= NAMEHASH(ir_setdata_name(mlinkiter
->linkdata
), ht
->size
);
750 entrypos
= bin_insert_var_ht_entry(ht
->start
, ht
->size
, &ht_entry
, 0);
751 ir_setdata_assign_fpos(mlinkiter
->linkdata
, MAP_POS());
752 PUSH_PLINK(mlinkiter
->linkdata
);
754 /* free all the processed links */
755 pagelist_free(plinkpages
);
760 long bin_process_facing(ir_setdata
, apc_facing
, struct bin_pixel_node_t
*);
761 /* |-------------------|
763 |-------------------|
765 |-------------------|
766 | SWFACE framesheet |
767 |-------------------|
774 struct bin_pixel_node_t
* default_pixel_list
776 { struct bin_model_header_t header
;
777 long framebox_start
, index_pos
;
780 framebox_start
= ftell(binaryout
);
782 /* insert model header */
784 header
.facing_array_start
= framebox_start
+ sizeof(header
);
785 fwrite(&header
, sizeof(header
), 1, binaryout
);
787 /* Create the index array for framesheet of each direction */
788 for ( i
= SFACE
; i
< FACING_MAX
; i
++)
789 { fseek(binaryout
, 0, SEEK_END
);
790 index_pos
= bin_process_facing(framebox
, i
, default_pixel_list
); //TODO: finish process_direction
791 fseek(binaryout
, header
.facing_array_start
+ i
* sizeof(long), SEEK_SET
);
792 fwrite(&index_pos
, sizeof(long), 1, binaryout
);
795 return framebox_start
;
798 struct bin_pixel_ht_t
* bin_pixel_ht_alloc
800 { struct bin_pixel_ht_t
* htp
;
801 if(!(htp
= (struct bin_pixel_ht_t
*) malloc(sizeof(bin_pixel_ht_t
) + )))
802 eprintf("error mallocing pixel_ht\n");
806 int bin_insert_pixel_ht_entry
807 ( struct bin_pixel_ht_t
* ht
,
808 struct bin_pixel_ht_entry_t
* ht_entry
815 bin_process_frameboxes
817 struct bin_ht_header_t
* ht
,
818 struct bin_pixel_node_t
* default_pixel_list
820 { struct bin_ht_entry_t ht_entry
;
821 struct bin_pixel_ht_t
* ht
;
822 struct bin_pixel_node_t
* pixeliter
;
825 /* create the default ht */
827 for(pixeliter
= default_pixel_list
; pixeliter
!= NULL
; pixeliter
= pixeliter
->next
)
829 ht_entry
.key
= pixel_iter
->data
.ref
;
830 bin_insert_pixel_ht_entry(&ht
, ;
836 /* Insert variants into hash table to overwrite olink insertions*/
837 for ( fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
838 { fseek(binaryout
, 0, SEEK_END
);
839 ht_entry
.key
= NAMEHASH(ir_setdata_name(fiter
), ht
->entries
);
840 /* create the copy, pass the copy */
841 ht_entry
.value
= bin_process_framebox(set
, fiter
, default_pixel_list
);
842 bin_insert_var_ht_entry(ht
->start
, ht
->entries
* sizeof(ht_entry
), &ht_entry
, 1);
846 /* Determine clipping based on image height/width and frame height/width */
848 void bin_set_img_info
849 ( struct bin_img_info_t
* img_info
,
850 ir_setdata frame_data
852 { ir_frameinfo frameinfo
;
853 frameinfo
= ir_framedata_frameinfo(frame_data
);
854 img_info
->fwidth
= frameinfo
->w
;
855 img_info
->fheight
= frameinfo
->h
;
856 img_info
->unaligned_height
= img_info
->height
% img_info
->fheight
;
857 img_info
->unaligned_width
= img_info
->width
% img_info
->fwidth
;
860 /* |-----------------------------|
862 |-----------------------------|
863 | pixel data for frame1 - n |
864 |-----------------------------|
865 | op data for frame1 - n |
866 |-----------------------------| */
869 //TODO: THIS SHOULD THE SET SPEC, NOT THE FRAMEBOX NAME
870 #define GENERATE_FILENAME(_N) ((char*) u8_strcat(_N, png_suffix))
872 ( ir_setdata framebox
,
874 struct bin_pixel_node_t
* default_pixel_list
876 { struct bin_img_info_t mapsheet_info
, framesheet_info
;
877 int num_mapchannels
, num_framechannels
, x
;
878 struct bin_frame_header_t header
;
880 RGBA_t
* mapdata
, * framedata
;
881 uint8_t* png_suffix
= ".png";
882 struct bin_pixel_node_t
* map_pixel_list
;
884 facing_start
= ftell(binaryout
);
887 /* Set up data pointers to mapsheet and framesheet, as well as their image infos */
888 mapdata
= (RGBA_t
*) stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(framebox
,SFACE
))), &mapsheet_info
.width
, &mapsheet_info
.width
, &num_framechannels
, 0);
889 framedata
= (RGBA_t
*) stbi_load(GENERATE_FILENAME(ir_setdata_name((ir_setdata
) ir_framebox_framesheet(framebox
,SFACE
))), &framesheet_info
.width
, &framesheet_info
.height
, &num_mapchannels
, 0);
890 bin_set_img_info(&framesheet_info
, ir_framebox_framesheet(framebox
, SFACE
));
891 bin_set_img_info(&mapsheet_info
, ir_framebox_mapsheet(framebox
, SFACE
));
893 /* Allocate space for header */
894 fseek(binaryout
, sizeof(header
), SEEK_CUR
);
897 /* Output framesheet */
898 if(!stbi_write_png(binaryout
, framesheet_info
.width
, framesheet_info
.height
, 4, mapdata
, framesheet_info
.fwidth
))
899 eprintf("error writing out framesheet\n");
901 /* Output framesheet header */
902 header
.width
= framesheet_info
.fwidth
;
903 header
.height
= framesheet_info
.fheight
;
904 header
.frames
= framesheet_info
.width
/ framesheet_info
.fwidth
; //TODO: division is bad
905 header
.op_start
= ftell(binaryout
);
906 fseek(binaryout
, facing_start
, SEEK_SET
);
907 fwrite(&header
, sizeof(header
), 1, binaryout
);
908 fseek(binaryout
, 0, SEEK_END
);
913 /* Assuming that fheight = image height */
914 /* For each mapframe in mapsheet */
915 for ( x
= 0; x
< header
.frames
; x
++)
916 { map_pixel_list
= bin_mapframe_to_pixel_list(mapsheet_info
, 0, x
* mapsheet_info
.fwidth
, mapdata
);
917 if(!bin_process_map_pixel_list(default_pixel_list
, map_pixel_list
))
918 eprintf("error processing map pixel list\n");
919 bin_output_pixel_list(map_pixel_list
);
920 mapdata
= mapsheet_info
.fwidth
* x
; //do we do this in mapframe to pixellist?
930 /* pixel_list == ops, output up to fwidth amount of them */
932 bin_output_pixel_list(struct bin_pixel_node_t
* map_pixel_list
);
934 /* TODO: Please rename all the functions jhc*/
936 void bin_number_pixel_list
937 ( struct bin_pixel_node_t
* pixel_list
)
939 struct bin_pixel_node_t
* iter
;
941 { iter
->data
.attach_idx
= num
++;
946 /* Assuming at this point that map_pixel_list is valid */
948 int bin_set_map_pixel_list_attach_idxs
949 ( struct bin_pixel_node_t
* default_pixel_list
,
950 struct bin_pixel_node_t
* map_pixel_list
952 { struct bin_pixel_node_t
* mapiter
, defaultiter
;
953 mapiter
= map_pixel_list
;
954 defaultiter
= default_pixel_list
;
955 while (mapiter
&& defaultiter
)
956 { /* if mapiter.data.ref == defaultiter.data.ref, assign mapiter index_idx to defaultiter */
957 if (mapiter
.data
.ref
== defauliter
.data
.ref
)
958 { defaultiter
.data
.attach_idx
= mapiter
.data
.attach_idx
;
959 mapiter
= mapiter
->next
;
960 defaultiter
= defaultiter
->next
;
963 defaultiter
= defaultiter
->next
;
966 int bin_ref_in_pixel_list
967 ( struct bin_pixel_node_t
* pixel_list
,
970 { struct bin_pixel_node_t
* iter
;
971 for(iter
= pixel_list
; iter
!= NULL
; iter
= iter
->next
)
972 { if(ref
== iter
.data
.ref
)
978 struct bin_pixel_ht_t
*
979 #define PIXEL_HT_SIZE() (sizeof(bin_pixel_ht_entry_t) * SYS_PAGESIZE + sizeof(bin_pixel_ht_t*))
982 { struct bin_pixel_ht_t
* ht
;
984 if(!(ht
= (struct bin_pixel_ht_t
*) malloc( PIXEL_HT_SIZE())))
985 eprintf("Memory allocation error in bin_pixel_ht_alloc\n");
986 memset(ht
, 0, PIXEL_HT_SIZE());
992 bin_insert_pixel_ht_entry
993 ( struct bin_pixel_ht_t
** ht
,
994 struct bin_pixel_ht_entry_t
* ht_entry
997 *ht
= bin_pixel_ht_alloc();
1001 /* Determines if the multiset map_pixel is a subset of the multiset default pixel list.
1002 0 if invalid, 1 if valid */
1004 int bin_valid_map_pixel_list
1005 ( struct bin_pixel_ht_t
* default_ht
,
1006 struct bin_pixel_node_t
* map_pixel_list
1008 { struct bin_pixel_node_t
* mapiter
, *defaultiter
, *tmpdefault
, tmpmap
;
1010 defaultiter
= default_pixel_list
;
1011 mapiter
= map_pixel_list
;
1013 while(mapiter
!= NULL
)
1015 /* compare against the default ht */
1016 /* decrement the value of the found ht_entry */
1017 /* if(value == 0) */
1028 int bin_process_map_pixel_list
1029 ( struct bin_pixel_node_t
* default_pixel_list
,
1030 struct bin_pixel_node_t
* map_pixel_list
1032 { /* Determine if pixel_list is valid */
1033 if(!bin_valid_map_pixel_list(default_pixel_list
, map_pixel_list
))
1036 /* Determine attach_idx of each pixel, as compared to default pixel list */
1042 bin_assign_pixel_idxs
1043 ( struct bin_pixel_node_t
* pixel_list
)
1047 /* Insert pixel(s) into the list, z sorted */
1048 /* number the pixels as you insert them */
1049 struct bin_pixel_node_t
*
1050 bin_insert_node_into_list
1051 ( struct bin_pixel_node_t
** pixel_list_root
,
1052 struct bin_pixel_node_t
* pixel_node
1054 { struct bin_pixel_node_t
** head_node
;
1056 head_node
= pixel_list_root
;
1058 while(*head_node
!= NULL
&& head_node
->data
.ref
< pixel_node
->data
.ref
)
1059 head_node
= &((*head_node
)->next
);
1061 pixel_node
->next
= *head_node
;
1062 *head_node
= pixel_node
;
1064 return pixel_list_root
;
1069 /* Returns the non null pixels of a single mapframe (unaligned or not)
1070 given any height and width */
1071 struct bin_pixel_node_t
*
1072 bin_mapframe_to_pixel_list
1073 ( struct bin_img_info_t
* img_info
,
1078 { int j
, i
, fheight
, fwidth
, fhsize
, fwsize
;
1080 struct bin_pixel_node_t
* pixel_list
,* pixel_node
;
1084 /* if frame clips, process unclippign frames */
1086 fwsize
= img_info
->unaligned_width
? img_info
->unaligned_width
: img_info
->fwidth
;
1087 fhsize
= img_info
->unaligned_height
? img_info
->unaligned_height
: img_info
->fwidth
;
1090 fwidth
= img_info
->fwidth
;
1091 fheight
= img_info
->fheight
;
1094 /* Process the map*/
1095 for (i
= init_height
; i
< fhsize
; i
++)
1096 { for ( j
= init_width
; j
< fwsize
; j
++ )
1097 { if (p
= data
[i
*img_info
->width
+j
])
1098 { pixel_node
= struct_alloc(bin_pixel_node_t
);
1099 /* get ref from 4 bytes of data */
1100 pixel_node
->data
.ref
= (*p
) >> 8;
1101 /* bitshift by ? to get Z */
1102 pixel_node
->data
.z
= (*p
& 0xFF);
1104 pixel_node
->data
.x
= j
;
1105 pixel_node
->data
.y
= i
;
1106 pixel_node
->data
.num
= 0;
1107 pixel_list
= bin_insert_node_into_list(&pixel_list
, pixel_node
);
1116 int bin_pixel_list_len
1117 ( struct bin_pixel_node_t
* pl
)
1118 { struct bin_pixel_node_t
* plp
;
1128 /* TODO: what are the qualifications for the default pixel list? len and __? */
1129 struct bin_pixel_node_t
*
1130 bin_cmp_default_pixel_lists
1131 ( struct bin_pixel_node_t
* pl1
,
1132 struct bin_pixel_node_t
* pl2
1134 { struct bin_pixel_node_t
* pl1p
, * pl2p
;
1135 int i
, pl1_len
, pl2_len
;
1139 pl1_len
= bin_pixel_list_len(pl1
);
1140 pl2_len
= bin_pixel_list_len(pl2
);
1142 if (pl1_len
> pl2_len
)
1144 else if (pl1_len
< pl2_len
)
1146 /* pl1 == pl2, make sure that all refs are the same */
1147 /* TODO: what type of warning/error handling should occur here? */
1148 for (i
= 0; i
< pl1_len
; i
++)
1149 { if (pl1p
->data
.ref
!= pl2p
->data
.ref
)
1150 eprintf("Error in determining default pixel list\n");
1154 return pl1
; //doesnt matter which one you return
1157 /* Find default framebox, based on the framebox with the most attachments*/
1158 /* Search through first frame of S of each framebox */
1159 struct bin_pixel_node_t
*
1160 bin_find_default_pixel_list
1163 struct bin_pixel_node_t
* default_pixel_list
, * curr_pixel_list
;
1166 struct bin_img_info_t img_info
;
1168 for (fiter
= ir_set_framebox(set
); fiter
!= NULL
; fiter
= ir_setdata_nextsib(fiter
))
1169 { /* TODO: Stringify the frame name with .png? */
1170 /* TODO: Add directory changing */
1171 data
= (RGBA_t
*) stbi_load(ir_setdata_name((ir_setdata
) ir_framebox_mapsheet(fiter
,SFACE
) ), &img_info
.width
, &img_info
.width
, &num_channels
, 0);
1172 bin_set_img_info(&img_info
, ir_framebox_mapsheet(fiter
, SFACE
));
1173 curr_pixel_list
= bin_mapframe_to_pixel_list(&img_info
, 0, 0, data
);
1174 default_pixel_list
= bin_cmp_default_pixel_lists(curr_pixel_list
, default_pixel_list
);
1179 return default_pixel_list
;