2 +----------------------------------------------------------------------+
3 | Author: yoya@awm.jp |
4 +----------------------------------------------------------------------+
9 #include <string.h> // memcmp, strchr
11 #include "bitstream.h"
12 #include "swf_define.h"
14 #include "swf_tag_action.h"
15 #include "swf_tag_jpeg.h"
16 #include "swf_tag_lossless.h"
17 #include "swf_tag_shape.h"
18 #include "swf_tag_button.h"
19 #include "swf_tag_place.h"
20 #include "swf_tag_sprite.h"
21 #include "swf_action.h"
22 #include "swf_object.h"
23 #include "bitmap_util.h"
24 #include "trans_table.h"
26 static int _swf_object_remove_tag(swf_object_t *swf, swf_tag_t *tag);
27 static int _swf_object_remove_tag_in_sprite(swf_tag_sprite_detail_t *sprite, swf_tag_t *tag);
28 static int _swf_object_replace_tag(swf_object_t *swf,
29 swf_tag_t *old_tag, swf_tag_t *new_tag);
30 static void _swf_object_tag_close(swf_tag_t *tag_head);
33 swf_object_open(void) {
36 malloc_debug_start(); /* DEBUG XXX */
37 #endif // MALLOC_DEBUG
38 #ifdef BITSTREAM_DEBUG /* bitstream debug */
39 bitstream_debug_start();
40 #endif // BITSTREAM_DEBUG
42 swf = (swf_object_t *) calloc(sizeof(*swf), 1);
46 swf->shape_adjust_mode = 0;
47 swf->compress_level = Z_DEFAULT_COMPRESSION;
52 _swf_object_tag_close(swf_tag_t *tag_head) {
53 swf_tag_t *tag, *next_tag;
54 for (tag = tag_head ; tag ; tag = next_tag) {
62 swf_object_close(swf_object_t *swf) {
64 _swf_object_tag_close(swf->tag_head);
70 malloc_debug_end(); /* DEBUG XXX */
71 #endif // MALLOC_DEBUG
72 #ifdef BITSTREAM_DEBUG /* bitstream debug */
73 bitstream_debug_end();
74 #endif // BITSTREAM_DEBUG
79 swf_object_input(swf_object_t *swf, unsigned char *data,
80 unsigned long data_len) {
83 swf_tag_t *tag, *prev_tag;
84 // delete old tag if twice call
85 _swf_object_tag_close(swf->tag_head);
87 bs = bitstream_open();
88 bitstream_input(bs, data, data_len);
89 result = swf_header_parse(bs, &swf->header);
94 if (memcmp(swf->header.magic, "FWS", 3) == 0) {
96 } else if (memcmp(swf->header.magic, "CWS", 3) == 0) {
98 unsigned char *old_buff_ref, *new_buff;
99 unsigned long origsize;
100 old_buff_ref = bitstream_buffer(bs, SWF_HEADER_SIZE);
101 origsize = swf->header.file_length - SWF_HEADER_SIZE;
102 new_buff = malloc(origsize);
103 result = uncompress(new_buff, &origsize, old_buff_ref, bs->data_len - SWF_HEADER_SIZE);
104 if (result != Z_OK) {
105 if (result == Z_MEM_ERROR) {
106 fprintf(stderr, "swf_object_input: uncompress Z_MEM_ERROR: can't malloc\n");
107 } else if (result == Z_BUF_ERROR) {
108 fprintf(stderr, "swf_object_input: uncompress Z_BUF_ERROR: not enough buff size\n");
110 fprintf(stderr, "swf_object_input: uncompress failed by unknown reason\n");
116 bitstream_putstring(bs, new_buff, origsize);
118 bitstream_setpos(bs, SWF_HEADER_SIZE, 0);
120 fprintf(stderr, "swf_object_input: unknown magic %s\n", swf->header.magic);
124 result = swf_header_movie_parse(bs, &swf->header_movie);
129 swf->tag_head = NULL;
134 pos = bitstream_getbytepos(bs);
135 if ((pos == -1) || ((long) swf->header.file_length <= pos)) {
138 tag = swf_tag_create(bs);
140 break; // finish (no end tag in _root)
142 if (prev_tag == NULL) {
144 tag->prev = tag->next = NULL;
146 prev_tag->next = tag;
147 tag->prev = prev_tag;
151 if (tag->code == 0) { // END Tag
161 swf_object_output(swf_object_t *swf, unsigned long *length) {
163 swf_tag_t *tag = NULL;
164 unsigned char *data = NULL;
165 bitstream_t *bs = NULL;
167 fprintf(stderr, "swf_object_output: swf == NULL\n");
170 if (length == NULL) {
171 fprintf(stderr, "swf_object_output: length == NULL\n");
175 bs = bitstream_open();
176 result = swf_header_build(bs, &swf->header);
181 result = swf_header_movie_build(bs, &swf->header_movie);
186 for (tag = swf->tag_head ; tag ; tag = tag->next) {
187 swf_tag_build(bs, tag, swf);
189 swf->header.file_length = bitstream_getbytepos(bs);
190 bitstream_setpos(bs, SWF_MAGIC_SIZE, 0);
191 bitstream_putbytesLE(bs, swf->header.file_length,
192 SWF_FILE_LENGTH_SIZE);
193 if (memcmp(swf->header.magic, "FWS", SWF_MAGIC_SIZE) == 0) {
195 } else if (memcmp(swf->header.magic, "CWS", SWF_MAGIC_SIZE) == 0) {
197 unsigned long compsize, old_size;
198 unsigned char *new_buff, *old_buff_ref;
199 bitstream_setpos(bs, SWF_HEADER_SIZE, 0);
200 old_buff_ref = bitstream_buffer(bs, SWF_HEADER_SIZE);
201 old_size = bs->data_len - SWF_HEADER_SIZE;
202 compsize = old_size * 1.001 + 12; // increasing, rarely situation
203 new_buff = malloc(compsize);
204 result = compress2(new_buff, &compsize, old_buff_ref, old_size, swf->compress_level);
205 if (result != Z_OK) {
206 if (result == Z_MEM_ERROR) {
207 fprintf(stderr, "swf_object_output: compress Z_MEM_ERROR: can't malloc\n");
208 } else if (result == Z_BUF_ERROR) {
209 fprintf(stderr, "swf_object_output: compress Z_BUF_ERROR: not enough buff size\n");
211 fprintf(stderr, "swf_object_output: compress failed by unknown reason\n");
214 return NULL; // FAILURE
216 bitstream_putstring(bs, new_buff, compsize);
219 fprintf(stderr, "swf_object_output: unknown magic %s\n", swf->header.magic);
221 return NULL; // FAILURE
223 data = bitstream_steal(bs, length);
229 swf_object_print(swf_object_t *swf) {
232 swf_header_print(&swf->header);
233 swf_header_movie_print(&swf->header_movie);
236 for (tag = swf->tag_head; tag ; tag = tag->next) {
238 swf_tag_print(tag, swf, 0);
239 if (tag->code == 0) { // END Tag
249 swf_object_rebuild(swf_object_t *swf) {
252 for (tag = swf->tag_head; tag ; tag = tag->next) {
253 ret = swf_tag_rebuild(tag, swf);
262 swf_object_purge_contents(swf_object_t *swf) {
264 trans_table_t *refcid_trans_table;
266 fprintf(stderr, "swf_object_purge_contents: swf == NULL\n");
269 refcid_trans_table = trans_table_open();
270 if (refcid_trans_table == NULL) {
271 fprintf(stderr, "swf_object_purge_contents: trans_table_open failed\n");
275 for (tag = swf->tag_tail; tag ; tag = tag->prev) {
277 int refcid = swf_tag_get_refcid(tag);
279 // register ref id in control tag
280 trans_table_set(refcid_trans_table, refcid, TRANS_TABLE_RESERVE_ID);
283 cid = swf_tag_get_cid(tag);
287 // contents tag routine is here.
288 if (trans_table_get(refcid_trans_table, cid) == TRANS_TABLE_RESERVE_ID) {
290 if (isShapeTag(tag->code)) {
291 int *bitmap_id_list, bitmap_id_list_num;
292 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
293 if (bitmap_id_list) {
295 for (i = 0 ; i < bitmap_id_list_num; i++) {
296 trans_table_set(refcid_trans_table, bitmap_id_list[i], TRANS_TABLE_RESERVE_ID);
298 free(bitmap_id_list);
300 } else if (isButtonTag(tag->code)) {
301 int *character_id_list, character_id_list_num;
302 character_id_list = swf_tag_button_character_get_refcid_list(tag, &character_id_list_num);
303 if (character_id_list) {
305 for (i = 0 ; i < character_id_list_num; i++) {
306 trans_table_set(refcid_trans_table, character_id_list[i], TRANS_TABLE_RESERVE_ID);
308 free(character_id_list);
310 } else if (isSpriteTag(tag->code)) {
312 swf_tag_sprite_detail_t *tag_sprite;
313 tag_sprite = swf_tag_create_input_detail(tag, swf);
314 if (tag_sprite == NULL) {
315 fprintf(stderr, "swf_object_purge_contents: tag_sprite == NULL\n");
317 for (t = tag_sprite->tag ; t ; t = t->next) {
318 if (isButtonTag(tag->code)) {
319 int *character_id_list, character_id_list_num;
320 character_id_list = swf_tag_button_character_get_refcid_list(tag, &character_id_list_num);
321 if (character_id_list) {
323 for (i = 0 ; i < character_id_list_num; i++) {
324 trans_table_set(refcid_trans_table, character_id_list[i], TRANS_TABLE_RESERVE_ID);
326 free(character_id_list);
329 int rid = swf_tag_get_refcid(t);
331 trans_table_set(refcid_trans_table, rid, TRANS_TABLE_RESERVE_ID);
338 if (isShapeTag(tag->code) || isBitmapTag(tag->code)) {
339 // TODO: tag == head ? tag == tail ? OK?
340 swf_tag_t *next_tag = tag->next;
341 tag->prev->next = tag->next;
342 tag->next->prev = tag->prev;
343 swf_tag_destroy(tag);
348 trans_table_close(refcid_trans_table);
354 swf_object_get_tagdata(swf_object_t *swf, int tag_seqno,
355 unsigned long *length) {
357 unsigned char *data = NULL;
358 tag = swf_object_search_tag_byseqno(swf, tag_seqno);
360 bitstream_t *bs = bitstream_open();
361 swf_tag_build(bs, tag, swf);
362 data = bitstream_steal(bs, length);
369 swf_object_replace_tagdata(swf_object_t *swf, int tag_seqno,
370 unsigned char *data, unsigned long length) {
371 swf_tag_t *old_tag, *new_tag;
372 old_tag = swf_object_search_tag_byseqno(swf, tag_seqno);
374 bitstream_t *bs = bitstream_open();
375 bitstream_input(bs, data,length);
376 new_tag = swf_tag_create(bs);
379 _swf_object_replace_tag(swf, old_tag, new_tag);
380 swf_tag_destroy(old_tag);
388 swf_object_get_tagdata_bycid(swf_object_t *swf, int cid,
389 unsigned long *length) {
391 unsigned char *data = NULL;
392 tag = swf_object_search_tag_bycid(swf, cid);
394 bitstream_t *bs = bitstream_open();
395 swf_tag_build(bs, tag, swf);
396 data = bitstream_steal(bs, length);
403 swf_object_replace_tagdata_bycid(swf_object_t *swf, int cid,
404 unsigned char *data, unsigned long length) {
405 swf_tag_t *old_tag, *new_tag;
406 old_tag = swf_object_search_tag_bycid(swf, cid);
408 bitstream_t *bs = bitstream_open();
409 bitstream_input(bs, data,length);
410 new_tag = swf_tag_create(bs);
412 swf_tag_replace_cid(new_tag, cid); // keep cid in SWF
414 // re-join to new tag
415 _swf_object_replace_tag(swf, old_tag, new_tag);
416 swf_tag_destroy(old_tag);
424 swf_object_get_tagcontents_bycid(swf_object_t *swf, int cid,
425 unsigned long *length) {
427 tag = swf_object_search_tag_bycid(swf, cid);
429 // rebuild detail to (raw)data if modified
430 if ((tag->data == NULL) && tag->detail) {
432 bs = bitstream_open();
433 swf_tag_build(bs, tag, swf);
434 tag->data = bitstream_steal(bs, &(tag->length));
438 *length = tag->length - 2;
439 return tag->data + 2; // success
443 return NULL; // failed
447 swf_object_replace_tagcontents_bycid(swf_object_t *swf, int cid,
449 unsigned long length) {
451 tag = swf_object_search_tag_bycid(swf, cid);
454 swf_tag_destroy_detail(tag);
461 tag->length = length + 2;
462 tag->data = malloc(length + 2);
463 PutUShortLE(tag->data, cid);
464 memcpy(tag->data + 2, data, length);
471 swf_object_remove_tag(swf_object_t *swf, int tag_seqno,
472 int tag_seqno_in_sprite) {
476 tag = swf_object_search_tag_byseqno(swf, tag_seqno);
478 if (tag_seqno_in_sprite >= 0) {
479 if (isSpriteTag(tag->code)) {
480 swf_tag_sprite_detail_t *tag_sprite;
481 swf_tag_t *tag_in_sprite;
482 tag_sprite = swf_tag_create_input_detail(tag, swf);
484 tag_in_sprite = swf_object_search_tag_in_sprite_byseqno(tag_sprite, tag_seqno_in_sprite);
486 ret = _swf_object_remove_tag_in_sprite(tag_sprite, tag_in_sprite);
495 fprintf(stderr, "swf_object_remove_tag: not SpriteTag seqno=%d\n", tag_seqno);
498 ret = _swf_object_remove_tag(swf, tag);
505 swf_object_print_tagdata(swf_object_t *swf, unsigned char *data,
506 unsigned long length) {
509 bs = bitstream_open();
510 bitstream_input(bs, data, length);
511 tag = swf_tag_create(bs);
514 fprintf(stderr, "swf_object_print_tagdata: swf_tag_create failed\n");
517 swf_tag_print(tag, swf, 0);
518 swf_tag_destroy(tag);
525 _swf_object_remove_tag(swf_object_t *swf, swf_tag_t *tag) {
527 if (tag->next) { // prev:O next:O
528 tag->prev->next = tag->next;
529 tag->next->prev = tag->prev;
530 } else { // prev:O next:X
531 tag->prev->next = NULL;
532 swf->tag_tail = tag->prev;
535 if (tag->next) { // prev:X next:O
536 tag->next->prev = NULL;
537 swf->tag_head = tag->next;
538 } else { // prev:X next:X
539 swf->tag_head = NULL;
540 swf->tag_tail = NULL;
543 swf_tag_destroy(tag);
548 _swf_object_remove_tag_in_sprite(swf_tag_sprite_detail_t *sprite_tag, swf_tag_t *tag) {
550 if (tag->next) { // prev:O next:O
551 tag->prev->next = tag->next;
552 tag->next->prev = tag->prev;
553 } else { // prev:O next:X
554 tag->prev->next = NULL;
555 // swf->tag_tail = tag->prev;
558 if (tag->next) { // prev:X next:O
559 sprite_tag->tag = tag->next;
560 tag->next->prev = NULL;
561 // swf->tag_heat = tag->next;
562 } else { // prev:X next:X
563 sprite_tag->tag = NULL;
564 // swf->tag_head = NULL;
565 // swf->tag_tail = NULL;
568 swf_tag_destroy(tag);
575 swf_object_get_shapedata(swf_object_t *swf, int cid, unsigned long *length) {
577 unsigned char *data = NULL;
579 tag = swf_object_search_tag_bycid(swf, cid);
582 if (! isShapeTag(tag->code)) {
583 fprintf(stderr, "swf_object_get_shapedata: not isShapeTag(%d)\n", tag->code);
587 bs = bitstream_open();
588 swf_tag_build(bs, tag, swf);
589 data = bitstream_steal(bs, length);
599 swf_object_replace_shapedata(swf_object_t *swf, int cid,
601 unsigned long length) {
602 swf_tag_t *old_tag, *new_tag;
603 old_tag = swf_object_search_tag_bycid(swf, cid);
606 if (! isShapeTag(old_tag->code)) {
607 fprintf(stderr, "swf_object_replace_shapedata: ! isShapeTag(%d)", old_tag->code);
610 bs = bitstream_open();
611 bitstream_input(bs, data, length);
612 new_tag = swf_tag_create(bs);
614 if ((new_tag == NULL) || (! isShapeTag(new_tag->code))) {
615 fprintf(stderr, "swf_object_replace_shapedata: fallback to read old shape data\n");
616 // fallback reading Shape v0.37 and before
618 swf_tag_destroy(new_tag);
620 new_tag = swf_tag_move(old_tag);
621 swf_tag_destroy_detail(new_tag);
622 new_tag->length = length + 2;
626 new_tag->data = malloc(length + 2);
627 PutUShortLE(new_tag->data, cid);
628 memcpy(new_tag->data + 2, data, length);
631 if (swf_tag_create_input_detail(new_tag, swf)) {
633 swf_tag_replace_cid(new_tag, cid);
634 _swf_object_replace_tag(swf, old_tag, new_tag);
635 swf_tag_destroy(old_tag);
636 // information modified so remove raw data.
638 new_tag->data = NULL;
649 swf_object_search_tag_byseqno(swf_object_t *swf, int tag_seqno) {
653 fprintf(stderr, "swf_object_search_tag_by_seqno: swf == NULL\n");
657 for (tag = swf->tag_head ; tag ; tag = tag->next) {
658 if (i >= tag_seqno) {
667 swf_object_search_tag_in_sprite_byseqno(swf_tag_sprite_detail_t *sprite, int tag_seqno) {
670 if (sprite == NULL) {
671 fprintf(stderr, "swf_object_search_tag_by_seqno: sprite == NULL\n");
675 for (tag = sprite->tag ; tag ; tag = tag->next) {
676 if (i >= tag_seqno) {
685 swf_object_search_tag_bycid(swf_object_t *swf, int cid) {
688 fprintf(stderr, "swf_object_search_tag_bycid: swf == NULL\n");
691 for (tag = swf->tag_head ; tag ; tag = tag->next) {
692 if (swf_tag_get_cid(tag) == cid) {
700 swf_object_search_bitmap_tag(swf_object_t *swf, int bitmap_id) {
703 fprintf(stderr, "swf_object_search_bitmap_tag: swf == NULL\n");
706 for (tag = swf->tag_head ; tag ; tag = tag->next) {
707 register int tag_code = tag->code;
708 if (isBitmapTag(tag_code)) {
709 if (swf_tag_get_cid(tag) == bitmap_id) {
718 swf_object_search_cid_by_bitmap_condition(swf_object_t *swf,
719 int width, int height,
720 int red, int green, int blue) {
724 fprintf(stderr, "swf_object_search_cid_by_bitmap_condition: swf == NULL\n");
727 for (tag = swf->tag_head ; tag ; tag = tag->next) {
728 register int tag_code = tag->code;
729 if (isBitmapTag(tag_code)) {
730 cid = swf_tag_search_cid_by_bitmap_condition(tag, width, height,
737 return -1; // Not Found
743 swf_object_set_shape_adjust_mode(swf_object_t *swf, unsigned mode) {
747 swf->shape_adjust_mode = mode;
752 swf_object_adjust_shapebitmap(swf_object_t *swf, int bitmap_id,
753 int old_width, int old_height,
754 int new_width, int new_height) {
755 swf_tag_t *tag = NULL;
756 double width_scale = 0, height_scale = 0;
757 int *bitmap_id_list, bitmap_id_list_num;
758 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_MATRIX_RESCALE) {
759 width_scale = (double) old_width / new_width;
760 height_scale = (double) old_height / new_height;
761 for (tag = swf->tag_head ; tag ; tag=tag->next) {
762 register int tag_code = tag->code;
763 if (isShapeTag(tag_code)) {
764 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
765 if (bitmap_id_list) {
767 for (i = 0 ; i < bitmap_id_list_num ; i++) {
768 if (bitmap_id_list[i] == bitmap_id) {
769 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
770 swf_tag_apply_shape_matrix_factor(tag, swf_tag_shape->shape_id,
772 width_scale, height_scale,
777 free(bitmap_id_list);
783 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_RECT_RESIZE) {
784 width_scale = (double) new_width / old_width;
785 height_scale = (double) new_height / old_height;
786 for (tag = swf->tag_head ; tag ; tag=tag->next) {
787 register int tag_code = tag->code;
788 if (isShapeTag(tag_code)) {
789 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
790 if (bitmap_id_list) {
792 for (i = 0 ; i < bitmap_id_list_num ; i++) {
793 if (bitmap_id_list[i] == bitmap_id) {
794 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
795 swf_tag_apply_shape_rect_factor(tag, swf_tag_shape->shape_id,
797 width_scale, height_scale,
802 free(bitmap_id_list);
807 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_TYPE_TILLED) {
808 for (tag = swf->tag_head ; tag ; tag=tag->next) {
809 register int tag_code = tag->code;
810 if (isShapeTag(tag_code)) {
811 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
812 if (bitmap_id_list) {
814 for (i = 0 ; i < bitmap_id_list_num ; i++) {
815 if (bitmap_id_list[i] == bitmap_id) {
816 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
817 swf_tag_apply_shape_type_tilled(tag, swf_tag_shape->shape_id, bitmap_id, swf);
820 free(bitmap_id_list);
829 swf_object_get_bitmap_size(swf_object_t *swf, int bitmap_id,
830 int *width, int *height) {
833 tag = swf_object_search_bitmap_tag(swf, bitmap_id);
837 ret = swf_tag_get_bitmap_size(tag, width, height);
844 swf_object_get_jpegdata(swf_object_t *swf, unsigned long *length, int image_id) {
845 swf_tag_t *tag, *tag_jpegtables = NULL;
846 unsigned char *data = NULL;
849 fprintf(stderr, "swf_object_get_jpegdata: swf == NULL\n");
852 for (tag=swf->tag_head ; tag ; tag=tag->next) {
853 if (tag->code == 8) { // JPEGTables
854 tag_jpegtables = tag;
857 // ! DefineBitsJPEG(1),2,3
858 if ((tag->code != 6) && (tag->code != 21) && (tag->code != 35)) {
861 data = swf_tag_get_jpeg_data(tag, length, image_id, tag_jpegtables);
870 swf_object_get_alphadata(swf_object_t *swf, unsigned long *length, int image_id) {
872 unsigned char *data = NULL;
875 fprintf(stderr, "swf_object_get_alphadata: swf == NULL\n");
878 for (tag=swf->tag_head ; tag ; tag=tag->next) {
879 if (tag->code != 35) { // ! DefineBitsJPEG3
882 data = swf_tag_get_alpha_data(tag, length, image_id);
891 swf_object_replace_jpegdata(swf_object_t *swf, int image_id,
892 unsigned char *jpeg_data,
893 unsigned long jpeg_data_len,
894 unsigned char *alpha_data,
895 unsigned long alpha_data_len,
896 int without_converting) {
899 int old_width, old_height, new_width, new_height;
901 fprintf(stderr, "swf_object_replace_jpegdata: swf == NULL\n");
904 tag = swf_object_search_bitmap_tag(swf, image_id);
906 fprintf(stderr, "swf_object_replace_jpegdata: tag == NULL\n");
909 if (swf->shape_adjust_mode) {
910 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
911 bitmap_size(jpeg_data, jpeg_data_len, &new_width, &new_height);
913 result = swf_tag_replace_jpeg_data(tag, image_id,
914 jpeg_data, jpeg_data_len,
915 alpha_data, alpha_data_len,
918 fprintf(stderr, "swf_object_replace_jpegdata: swf_tag_replace_jpeg_data failed\n");
921 if (swf->shape_adjust_mode) {
922 swf_object_adjust_shapebitmap(swf, image_id,
923 old_width, old_height,
924 new_width, new_height);
932 swf_object_get_pngdata(swf_object_t *swf, unsigned long *length, int image_id) {
934 unsigned char *data = NULL;
936 fprintf(stderr, "swf_object_get_pngdata: swf == NULL\n");
939 if (length == NULL) {
940 fprintf(stderr, "swf_object_get_pngdata: length == NULL\n");
944 for (tag=swf->tag_head ; tag ; tag=tag->next) {
945 // DefineBitsLossless(1),2
946 if ((tag->code != 20) && (tag->code != 36)) {
949 data = swf_tag_get_png_data(tag, length, image_id);
958 swf_object_replace_pngdata(swf_object_t *swf, int image_id,
959 unsigned char *png_data,
960 unsigned long png_data_len, int rgb15) {
963 int old_width, old_height, new_width, new_height;
965 fprintf(stderr, "swf_object_replace_pngdata: swf == NULL\n");
968 if (png_data == NULL) {
969 fprintf(stderr, "swf_object_replace_pngdata: png_data == NULL\n");
972 tag = swf_object_search_bitmap_tag(swf, image_id);
974 fprintf(stderr, "swf_object_replace_pngdata: tag == NULL\n");
977 if (swf->shape_adjust_mode) {
978 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
979 png_size(png_data, png_data_len, &new_width, &new_height);
981 result = swf_tag_replace_png_data(tag, image_id,
982 png_data, png_data_len, rgb15);
984 fprintf(stderr, "swf_object_replace_pngdata: swf_tag_replace_png_data failed\n");
987 if (swf->shape_adjust_mode) {
988 swf_object_adjust_shapebitmap(swf, image_id,
989 old_width, old_height,
990 new_width, new_height);
995 #endif /* HAVE_PNG */
1000 swf_object_replace_gifdata(swf_object_t *swf, int image_id,
1001 unsigned char *gif_data,
1002 unsigned long gif_data_len) {
1005 int old_width, old_height, new_width, new_height;
1007 fprintf(stderr, "swf_object_replace_gifdata: swf == NULL\n");
1010 if (gif_data == NULL) {
1011 fprintf(stderr, "swf_object_replace_gifdata: gif_data == NULL\n");
1014 tag = swf_object_search_bitmap_tag(swf, image_id);
1016 fprintf(stderr, "swf_object_replace_gifdata: tag == NULL\n");
1019 if (swf->shape_adjust_mode) {
1020 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
1021 gif_size(gif_data, gif_data_len, &new_width, &new_height);
1023 result = swf_tag_replace_gif_data(tag, image_id,
1024 gif_data, gif_data_len);
1026 fprintf(stderr, "swf_object_replace_pngdata: swf_tag_replace_png_data failed\n");
1029 if (swf->shape_adjust_mode) {
1030 swf_object_adjust_shapebitmap(swf, image_id,
1031 old_width, old_height,
1032 new_width, new_height);
1037 #endif /* HAVE_GIF */
1040 swf_object_convert_bitmapdata_tojpegtag(swf_object_t *swf) {
1043 fprintf(stderr, "swf_object_convert_bitmapdata_tojpegtag: swf == NULL\n");
1046 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1047 swf_tag_convert_bitmap_data_tojpegtag(tag);
1053 swf_object_get_sounddata(swf_object_t *swf, unsigned long *length, int sound_id) {
1055 unsigned char *data = NULL;
1058 fprintf(stderr, "swf_object_get_sounddata: swf == NULL\n");
1061 if (length == NULL) {
1062 fprintf(stderr, "swf_object_get_sounddata: length == NULL\n");
1065 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1067 if (tag->code != 14) {
1070 data = swf_tag_get_sound_data(tag, length, sound_id);
1079 swf_object_replace_melodata(swf_object_t *swf, int sound_id,
1080 unsigned char *melo_data,
1081 unsigned long melo_data_len) {
1085 fprintf(stderr, "swf_object_replace_melodata: swf == NULL\n");
1088 if (melo_data == NULL) {
1089 fprintf(stderr, "swf_object_replace_melodata: melo_data == NULL\n");
1092 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1093 result = swf_tag_replace_melo_data(tag, sound_id,
1094 melo_data, melo_data_len);
1103 swf_object_get_editstring(swf_object_t *swf,
1104 char *variable_name, int variable_name_len,
1109 fprintf(stderr, "swf_object_get_editstring: swf == NULL\n");
1112 if (variable_name == NULL) {
1113 fprintf(stderr, "swf_object_get_editstring: variable_name == NULL\n");
1116 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1117 data = swf_tag_get_edit_string(tag, variable_name,
1118 variable_name_len, error, swf);
1119 if (data || (*error == 0)) {
1127 swf_object_replace_editstring(swf_object_t *swf,
1128 char *variable_name,
1129 int variable_name_len,
1131 int initial_text_len) {
1135 fprintf(stderr, "swf_object_replace_editstring: swf == NULL\n");
1138 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1139 result = swf_tag_replace_edit_string(tag, variable_name,
1152 swf_object_get_actiondata(swf_object_t *swf, unsigned long *length, int tag_seqno) {
1154 swf_tag_action_detail_t *swf_tag_action;
1156 unsigned char *data;
1159 fprintf(stderr, "swf_object_get_actiondata: swf == NULL\n");
1162 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1163 if (i == tag_seqno) {
1171 if ((tag->code != 12) && (tag->code != 59)) { // DoAction, DoInitAction
1174 swf_tag_action = (swf_tag_action_detail_t *) swf_tag_create_input_detail(tag, swf);
1175 if (swf_tag_action == NULL) {
1176 fprintf(stderr, "swf_object_get_actiondata: swf_tag_create_input_detail failed");
1179 bs = bitstream_open();
1180 swf_action_list_build(bs,swf_tag_action->action_list);
1181 data = bitstream_steal(bs, length);
1182 bitstream_close(bs);
1187 swf_object_insert_action_setvariables(swf_object_t *swf,
1189 swf_tag_t *tag, *prev = NULL;
1190 swf_tag_t *action_tag = NULL, *prev_tag = NULL;
1192 if ((swf == NULL) || (swf->tag_head == NULL)) {
1193 fprintf(stderr, "swf_object_insert_action_setvariables: swf or swf->tag_head is NULL\n");
1196 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1197 switch (tag->code) {
1198 case 1: // ShowFrame
1199 if (prev_tag == NULL) {
1200 // no candidate point before ShowFrame so prev It.
1205 case 12: // DoAction
1206 // DoAction found so merge ActionByteCode to it.
1210 case 69: // FileAttributs
1211 case 9: // SetBackgroundColor
1213 // put image after there tags.
1217 if (prev_tag == NULL) {
1227 if (action_tag) { // apppend setvariable image to top of DoAction
1228 ret = swf_tag_put_action_setvariables(action_tag,
1232 fprintf(stderr, "swf_object_insert_action_setvariables: swf_tag_put_action_setvariables failed\n");
1235 } else { // insert new DoAction
1236 tag = swf_tag_create_action_setvariables(kv);
1238 fprintf(stderr, "swf_object_insert_action_setvariables: swf_tag_create_action_setvariables failed\n");
1241 if (prev_tag == NULL) { // to make sure. abnormal situation.
1242 tag->next = swf->tag_head;
1243 tag->next->prev = tag;
1244 swf->tag_head = tag;
1247 tag->next = prev_tag->next;
1248 tag->next->prev = tag;
1249 prev_tag->next = tag;
1250 tag->prev = prev_tag;
1253 return 0; // SUCCESS
1257 swf_object_replace_action_strings(swf_object_t *swf, y_keyvalue_t *kv) {
1262 fprintf(stderr, "swf_object_replace_action_strings: swf == NULL\n");
1266 fprintf(stderr, "swf_object_replace_action_strings: kv == NULL\n");
1269 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1270 if (isActionTag(tag->code)) {
1271 ret = swf_tag_replace_action_strings(tag, kv, &m, swf);
1273 fprintf(stderr, "swf_object_replace_action_strings: swf_tag_replace_action_string failed\n");
1276 if (m && tag->data) { // action tag modified
1280 } else if (isSpriteTag(tag->code)) {
1281 swf_tag_sprite_detail_t *tag_sprite;
1282 tag_sprite = swf_tag_create_input_detail(tag, swf);
1283 if (tag_sprite == NULL) {
1284 fprintf(stderr, "swf_object_replace_action_strings: tag_sprite == NULL\n");
1288 for (t = tag_sprite->tag ; t ; t = t->next) {
1289 if (isActionTag(t->code)) {
1290 ret = swf_tag_replace_action_strings(t, kv, &m, swf);
1292 fprintf(stderr, "swf_object_replace_action_strings: replace_action_string failed\n");
1299 modified = 1; // action tag modified
1302 if (modified) { // sprite tag rebuild
1315 * replacce reference side CID value
1318 trans_table_replace_refcid_recursive(swf_tag_t *tag, trans_table_t *cid_trans_table) {
1319 for ( ; tag ; tag=tag->next) {
1320 int tag_no = tag->code;
1321 if (isSpriteTag(tag_no)) {
1322 swf_tag_sprite_detail_t *tag_sprite;
1323 tag_sprite = swf_tag_create_input_detail(tag, NULL);
1324 if (tag_sprite == NULL) {
1325 fprintf(stderr, "trans_table_replace_refcid_recursive: tag_sprite swf_tag_create_input_detail failed");
1327 trans_table_replace_refcid_recursive(tag_sprite->tag, cid_trans_table);
1328 } else if (isPlaceTag(tag_no)) {
1329 int refcid = swf_tag_get_refcid(tag);
1331 int to_refcid = trans_table_get(cid_trans_table, refcid);
1332 if (refcid != to_refcid) {
1333 swf_tag_replace_refcid(tag, to_refcid);
1340 // return Sprite tag mapped target path
1342 swf_object_saerch_sprite_by_target_path2(swf_tag_t *tag_head,
1343 unsigned char *target_path,
1344 int target_path_len,
1345 swf_object_t *swf) {
1346 swf_tag_t *tag, *sprite_tag = NULL;
1347 unsigned char *instance_name, *next_instance_name;
1348 int instance_name_len;
1351 next_instance_name = (unsigned char *) strchr((char *) target_path, '/');
1352 if (next_instance_name != NULL) {
1353 next_instance_name[0] = '\0'; // null terminate
1354 next_instance_name++;
1357 instance_name = target_path;
1358 instance_name_len = strlen((char *) instance_name);
1360 // search PlaceObject by instance_name and get ref CID
1361 for (tag = tag_head ; tag ; tag=tag->next) {
1363 if (tag->code == 26) { // PlaceObject2
1364 cid = swf_tag_place_get_cid_by_instance_name(tag, instance_name, instance_name_len, swf);
1372 "swf_object_saerch_sprite_by_target_path2: not found place target_path=%s (cid=%d)\n",
1374 return NULL; // not found instance name;
1377 // search DefineSprite by CID
1378 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1379 if (isSpriteTag(tag->code)) {
1380 if (swf_tag_get_cid(tag) == cid) {
1386 if (next_instance_name) { // nested sprite
1388 swf_tag_sprite_detail_t *tag_sprite;
1389 tag_sprite = swf_tag_create_input_detail(sprite_tag, swf);
1390 if (tag_sprite == NULL) {
1391 fprintf(stderr, "swf_object_saerch_sprite_by_target_path2: tag_sprite swf_tag_create_input_detail failed\n");
1393 sprite_tag = swf_object_saerch_sprite_by_target_path(tag_sprite->tag, next_instance_name, target_path_len - instance_name_len - 1, swf);
1400 swf_object_saerch_sprite_by_target_path(swf_tag_t *tag_head,
1401 unsigned char *target_path,
1402 int target_path_len,
1403 swf_object_t *swf) {
1405 unsigned char* target_path2 = (unsigned char*)malloc(target_path_len+1);
1406 memcpy(target_path2, target_path, target_path_len+1);
1408 tag = swf_object_saerch_sprite_by_target_path2(tag_head,
1417 swf_object_replace_movieclip(swf_object_t *swf,
1418 unsigned char *instance_name, int instance_name_len,
1419 unsigned char *swf_data, int swf_data_len) {
1420 int cid = 0, sprite_cid = 0, ret = 0;
1421 swf_tag_t *tag = NULL;
1422 swf_tag_t *sprite_tag = NULL, *prev_sprite_tag = NULL;
1423 swf_tag_t *sprite_tag_tail = NULL; // last tag in sprite.
1424 swf_tag_sprite_detail_t *swf_tag_sprite = NULL;
1425 swf_object_t *swf4sprite = NULL;
1426 swf_tag_info_t *tag_info = NULL;
1427 swf_tag_detail_handler_t *detail_handler = NULL;
1428 trans_table_t *cid_trans_table = NULL;
1431 fprintf(stderr, "swf_object_replace_movieclip: swf == NULL\n");
1435 // search symbol(SpriteTag) mapped instance_name(target path)
1436 sprite_tag = swf_object_saerch_sprite_by_target_path(tag=swf->tag_head,
1441 if (sprite_tag == NULL) {
1442 fprintf(stderr, "swf_object_replace_movieclip: sprite_tag == NULL\n");
1443 return 1; // not found instance name;
1445 prev_sprite_tag = sprite_tag->prev;
1446 sprite_cid = swf_tag_get_cid(sprite_tag);
1448 // swf data that MC replace to
1449 swf4sprite = swf_object_open();
1450 ret = swf_object_input(swf4sprite, swf_data, swf_data_len);
1452 fprintf(stderr, "swf_object_replace_movieclip: swf_object_input (swf_data_len=%d) failed\n", swf_data_len);
1457 cid_trans_table = trans_table_open();
1458 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1460 cid = swf_tag_get_cid(tag);
1462 trans_table_set(cid_trans_table, cid, TRANS_TABLE_RESERVE_ID);
1465 // trans_table_print(cid_trans_table);
1467 // clean up innner SpriteTag
1468 tag_info = get_swf_tag_info(sprite_tag->code);
1469 detail_handler = tag_info->detail_handler();
1470 free(sprite_tag->data);
1471 sprite_tag->data = NULL;
1472 sprite_tag->length = 0;
1473 if (sprite_tag->detail) {
1474 detail_handler->destroy(sprite_tag);
1476 sprite_tag->detail = detail_handler->create();
1477 swf_tag_sprite = sprite_tag->detail;
1478 swf_tag_sprite->sprite_id = sprite_cid;
1480 // extract tag each that type in SWF
1481 for (tag = swf4sprite->tag_head ; tag ; tag = tag->next) {
1482 int tag_no = tag->code;
1486 case 3: // FreeCharacter
1487 case 9: // SetBackgroundColor
1490 case 69: // FileAttributes
1491 case 74: // CSMTextSettings
1492 case 8: // JPEGTables // XXX
1496 case 2: // DefineShape
1497 case 6: // DefineBitsJPEG
1498 case 7: // DefineButton
1499 case 10: // DefineFont
1500 case 11: // DefineText
1501 case 13: // DefineFontInfo
1502 case 14: // DefineSound
1503 case 17: // DefineButtonSound
1504 case 18: // SoundStreamHead"
1505 case 19: // SoundStreamBlock
1506 case 20: // DefineBitsLossless
1507 case 21: // DefineBitsJPEG2
1508 case 22: // DefineShape2
1509 case 32: // DefineShape3
1510 case 33: // DefineText2
1511 case 34: // DefineButton2
1512 case 35: // DefineBitsJPEG3
1513 case 36: // DefineBitsLossless2
1514 case 37: // DefineEditText
1515 case 39: // DefineSprite
1516 case 46: // DefineMorphShape
1517 case 48: // DefineFont2
1518 case 73: // DefineFontAlignZones
1519 case 75: // DefineFont3
1520 case 83: // DefineShape4
1521 case 84: // DefineMorphShape2
1522 case 88: // DefineFontName
1524 cid = swf_tag_get_cid(tag);
1527 to_cid = trans_table_get(cid_trans_table, cid);
1528 if (to_cid == TRANS_TABLE_RESERVE_ID) {
1529 to_cid = trans_table_get_freeid(cid_trans_table);
1530 trans_table_set(cid_trans_table, cid, to_cid);
1531 trans_table_set(cid_trans_table, to_cid, TRANS_TABLE_RESERVE_ID);
1532 } else if (to_cid == 0) {
1533 trans_table_set(cid_trans_table, cid, cid);
1536 if (cid != to_cid) {
1537 if (swf_tag_replace_cid(tag, to_cid)) {
1538 fprintf(stderr, "swf_object_replace_movieclip: swf_tag_replace_cid %d => %d failed\n", cid, to_cid);
1543 if (isShapeTag(tag_no)) {
1544 int *bitmap_id_list, bitmap_id_list_num;
1545 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
1546 if (bitmap_id_list) {
1548 for (i = 0 ; i < bitmap_id_list_num; i++) {
1549 int bitmap_id = bitmap_id_list[i];
1550 int to_bitmap_id = trans_table_get(cid_trans_table, bitmap_id);
1551 if ((to_bitmap_id > 0) && (bitmap_id != to_bitmap_id)) {
1552 swf_tag_shape_bitmap_replace_refcid_list(tag, bitmap_id, to_bitmap_id);
1555 free(bitmap_id_list);
1557 } else if (isSpriteTag(tag_no)){
1558 swf_tag_sprite_detail_t *s;
1559 s = swf_tag_create_input_detail(tag, swf);
1561 fprintf(stderr, "swf_object_replace_movieclip: s swf_tag_create_input_detail failed\n");
1563 trans_table_replace_refcid_recursive(s->tag, cid_trans_table);
1567 int refcid, to_refcid;
1568 refcid = swf_tag_get_refcid(tag);
1570 to_refcid = trans_table_get(cid_trans_table, refcid);
1571 if (refcid != to_refcid) {
1572 swf_tag_replace_refcid(tag, to_refcid);
1576 // extract tag before SpriteTag
1577 prev_sprite_tag->next = swf_tag_move(tag);
1578 prev_sprite_tag->next->prev = prev_sprite_tag;
1579 prev_sprite_tag = prev_sprite_tag->next;
1580 prev_sprite_tag->next = sprite_tag;
1581 sprite_tag->prev = prev_sprite_tag;
1585 case 1: // ShowFrame
1586 case 4: // PlaceObject
1587 case 5: // RemoveObject
1588 case 12: // DoAction
1589 case 15: // StartSound
1590 case 26: // PlaceObject2
1591 case 28: // RemoveObject2
1592 case 43: // FrameLabel
1593 case 59: // DoInitAction
1594 // insert into Sprite
1595 // follow Character ID change
1597 int refcid, to_refcid;
1598 case 4: // PlaceObject
1599 case 26: // PlaceObject2
1600 refcid = swf_tag_get_refcid(tag);
1602 to_refcid = trans_table_get(cid_trans_table, refcid);
1603 if (refcid != to_refcid) {
1604 swf_tag_replace_refcid(tag, to_refcid);
1609 // inplant tag to Sprite
1610 if (sprite_tag_tail == NULL) {
1611 swf_tag_sprite->tag = swf_tag_move(tag);
1612 sprite_tag_tail = swf_tag_sprite->tag;
1614 sprite_tag_tail->next = swf_tag_move(tag);
1615 sprite_tag_tail = sprite_tag_tail->next;
1617 sprite_tag_tail->next = NULL;
1618 if (tag_no == 1) { // ShowFrame
1619 swf_tag_sprite->frame_count += 1;
1624 trans_table_close(cid_trans_table);
1625 swf_object_close(swf4sprite);
1630 swf_object_apply_shapematrix_factor(swf_object_t *swf, int shape_id,
1632 double scale_x, double scale_y,
1634 signed int trans_x, signed int trans_y) {
1638 fprintf(stderr, "swf_object_apply_shapematrix_factor: swf == NULL\n");
1641 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1642 result = swf_tag_apply_shape_matrix_factor(tag, shape_id,
1656 swf_object_apply_shaperect_factor(swf_object_t *swf, int shape_id,
1658 double scale_x, double scale_y,
1659 signed int trans_x, signed int trans_y) {
1663 fprintf(stderr, "swf_object_apply_shaperect_factor: swf == NULL\n");
1666 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1667 result = swf_tag_apply_shape_rect_factor(tag, shape_id, bitmap_id,
1679 swf_object_apply_shapetype_tilled(swf_object_t *swf,int shape_id,
1684 fprintf(stderr, "swf_object_apply_shaperect_factor: swf == NULL\n");
1687 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1688 result = swf_tag_apply_shape_type_tilled(tag, shape_id, bitmap_id, swf);
1697 swf_object_is_shape_tagdata(unsigned char *data, int data_len) {
1700 int ret = 0; // default FALSE;
1702 bs = bitstream_open();
1703 bitstream_input(bs, data, data_len);
1704 tag = swf_tag_create(bs);
1706 if (isShapeTag(tag->code)) {
1710 bitstream_close(bs);
1715 swf_object_is_bitmap_tagdata(unsigned char *data, int data_len) {
1718 int ret = 0; // default FALSE;
1720 bs = bitstream_open();
1721 bitstream_input(bs, data, data_len);
1722 tag = swf_tag_create(bs);
1724 if (isBitmapTag(tag->code)) {
1728 bitstream_close(bs);
1733 _swf_object_replace_tag(swf_object_t *swf,
1734 swf_tag_t *old_tag, swf_tag_t *new_tag) {
1735 old_tag->prev->next = new_tag;
1736 old_tag->next->prev = new_tag;
1737 new_tag->prev = old_tag->prev;
1738 new_tag->next = old_tag->next;
1739 if (new_tag->prev == NULL) {
1740 swf->tag_head = new_tag;
1742 if (new_tag->next == NULL) {
1743 swf->tag_tail = new_tag;
1745 old_tag->prev = NULL;
1746 old_tag->next = NULL;