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 swf = (swf_object_t *) calloc(sizeof(*swf), 1);
42 swf->shape_adjust_mode = 0;
43 swf->compress_level = Z_DEFAULT_COMPRESSION;
48 _swf_object_tag_close(swf_tag_t *tag_head) {
49 swf_tag_t *tag, *next_tag;
50 for (tag = tag_head ; tag ; tag = next_tag) {
58 swf_object_close(swf_object_t *swf) {
60 _swf_object_tag_close(swf->tag_head);
66 malloc_debug_end(); /* DEBUG XXX */
67 #endif // MALLOC_DEBUG
72 swf_object_input(swf_object_t *swf, unsigned char *data,
73 unsigned long data_len) {
76 swf_tag_t *tag, *prev_tag;
77 // delete old tag if twice call
78 _swf_object_tag_close(swf->tag_head);
80 bs = bitstream_open();
81 bitstream_input(bs, data, data_len);
82 result = swf_header_parse(bs, &swf->header);
87 if (memcmp(swf->header.magic, "FWS", 3) == 0) {
89 } else if (memcmp(swf->header.magic, "CWS", 3) == 0) {
91 unsigned char *old_buff_ref, *new_buff;
92 unsigned long origsize;
93 old_buff_ref = bitstream_buffer(bs, SWF_HEADER_SIZE);
94 origsize = swf->header.file_length - SWF_HEADER_SIZE;
95 new_buff = malloc(origsize);
96 result = uncompress(new_buff, &origsize, old_buff_ref, bs->data_len - SWF_HEADER_SIZE);
98 if (result == Z_MEM_ERROR) {
99 fprintf(stderr, "swf_object_input: uncompress Z_MEM_ERROR: can't malloc\n");
100 } else if (result == Z_BUF_ERROR) {
101 fprintf(stderr, "swf_object_input: uncompress Z_BUF_ERROR: not enough buff size\n");
103 fprintf(stderr, "swf_object_input: uncompress failed by unknown reason\n");
109 bitstream_putstring(bs, new_buff, origsize);
111 bitstream_setpos(bs, SWF_HEADER_SIZE, 0);
113 fprintf(stderr, "swf_object_input: unknown magic %s\n", swf->header.magic);
117 result = swf_header_movie_parse(bs, &swf->header_movie);
122 swf->tag_head = NULL;
126 pos = bitstream_getbytepos(bs);
127 if ((pos == -1) || ((long) swf->header.file_length <= pos)) {
130 tag = swf_tag_create(bs);
133 for (tag = swf->tag_head ; tag ; tag = next_tag) {
134 next_tag = tag->next;
135 swf_tag_destroy(tag);
140 if (prev_tag == NULL) {
142 tag->prev = tag->next = NULL;
144 prev_tag->next = tag;
145 tag->prev = prev_tag;
149 if (tag->code == 0) { // END Tag
159 swf_object_output(swf_object_t *swf, unsigned long *length) {
161 swf_tag_t *tag = NULL;
162 unsigned char *data = NULL;
163 bitstream_t *bs = NULL;
165 fprintf(stderr, "swf_object_output: swf == NULL\n");
168 if (length == NULL) {
169 fprintf(stderr, "swf_object_output: length == NULL\n");
173 bs = bitstream_open();
174 result = swf_header_build(bs, &swf->header);
179 result = swf_header_movie_build(bs, &swf->header_movie);
184 for (tag = swf->tag_head ; tag ; tag = tag->next) {
185 swf_tag_build(bs, tag, swf);
187 swf->header.file_length = bitstream_getbytepos(bs);
188 bitstream_setpos(bs, SWF_MAGIC_SIZE, 0);
189 bitstream_putbytesLE(bs, swf->header.file_length,
190 SWF_FILE_LENGTH_SIZE);
191 if (memcmp(swf->header.magic, "FWS", SWF_MAGIC_SIZE) == 0) {
193 } else if (memcmp(swf->header.magic, "CWS", SWF_MAGIC_SIZE) == 0) {
195 unsigned long compsize, old_size;
196 unsigned char *new_buff, *old_buff_ref;
197 bitstream_setpos(bs, SWF_HEADER_SIZE, 0);
198 old_buff_ref = bitstream_buffer(bs, SWF_HEADER_SIZE);
199 old_size = bs->data_len - SWF_HEADER_SIZE;
200 compsize = old_size * 1.001 + 12; // increasing, rarely situation
201 new_buff = malloc(compsize);
202 result = compress2(new_buff, &compsize, old_buff_ref, old_size, swf->compress_level);
203 if (result != Z_OK) {
204 if (result == Z_MEM_ERROR) {
205 fprintf(stderr, "swf_object_output: compress Z_MEM_ERROR: can't malloc\n");
206 } else if (result == Z_BUF_ERROR) {
207 fprintf(stderr, "swf_object_output: compress Z_BUF_ERROR: not enough buff size\n");
209 fprintf(stderr, "swf_object_output: compress failed by unknown reason\n");
212 return NULL; // FAILURE
214 bitstream_putstring(bs, new_buff, compsize);
217 fprintf(stderr, "swf_object_output: unknown magic %s\n", swf->header.magic);
219 return NULL; // FAILURE
221 data = bitstream_steal(bs, length);
227 swf_object_print(swf_object_t *swf) {
230 swf_header_print(&swf->header);
231 swf_header_movie_print(&swf->header_movie);
234 for (tag = swf->tag_head; tag ; tag = tag->next) {
236 swf_tag_print(tag, swf, 0);
237 if (tag->code == 0) { // END Tag
247 swf_object_rebuild(swf_object_t *swf) {
250 for (tag = swf->tag_head; tag ; tag = tag->next) {
251 ret = swf_tag_rebuild(tag, swf);
260 swf_object_purge_contents(swf_object_t *swf) {
262 trans_table_t *refcid_trans_table;
264 fprintf(stderr, "swf_object_purge_contents: swf == NULL\n");
267 refcid_trans_table = trans_table_open();
268 if (refcid_trans_table == NULL) {
269 fprintf(stderr, "swf_object_purge_contents: trans_table_open failed\n");
273 for (tag = swf->tag_tail; tag ; tag = tag->prev) {
275 int refcid = swf_tag_get_refcid(tag);
277 // register ref id in control tag
278 trans_table_set(refcid_trans_table, refcid, TRANS_TABLE_RESERVE_ID);
281 cid = swf_tag_get_cid(tag);
285 // contents tag routine is here.
286 if (trans_table_get(refcid_trans_table, cid) == TRANS_TABLE_RESERVE_ID) {
288 if (isShapeTag(tag->code)) {
289 int *bitmap_id_list, bitmap_id_list_num;
290 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
291 if (bitmap_id_list) {
293 for (i = 0 ; i < bitmap_id_list_num; i++) {
294 trans_table_set(refcid_trans_table, bitmap_id_list[i], TRANS_TABLE_RESERVE_ID);
296 free(bitmap_id_list);
298 } else if (isButtonTag(tag->code)) {
299 int *character_id_list, character_id_list_num;
300 character_id_list = swf_tag_button_character_get_refcid_list(tag, &character_id_list_num);
301 if (character_id_list) {
303 for (i = 0 ; i < character_id_list_num; i++) {
304 trans_table_set(refcid_trans_table, character_id_list[i], TRANS_TABLE_RESERVE_ID);
306 free(character_id_list);
308 } else if (isSpriteTag(tag->code)) {
310 swf_tag_sprite_detail_t *tag_sprite;
311 tag_sprite = swf_tag_create_input_detail(tag, swf);
312 if (tag_sprite == NULL) {
313 fprintf(stderr, "swf_object_purge_contents: tag_sprite == NULL\n");
315 for (t = tag_sprite->tag ; t ; t = t->next) {
316 if (isButtonTag(tag->code)) {
317 int *character_id_list, character_id_list_num;
318 character_id_list = swf_tag_button_character_get_refcid_list(tag, &character_id_list_num);
319 if (character_id_list) {
321 for (i = 0 ; i < character_id_list_num; i++) {
322 trans_table_set(refcid_trans_table, character_id_list[i], TRANS_TABLE_RESERVE_ID);
324 free(character_id_list);
327 int rid = swf_tag_get_refcid(t);
329 trans_table_set(refcid_trans_table, rid, TRANS_TABLE_RESERVE_ID);
336 if (isShapeTag(tag->code) || isBitmapTag(tag->code)) {
337 // TODO: tag == head ? tag == tail ? OK?
338 swf_tag_t *next_tag = tag->next;
339 tag->prev->next = tag->next;
340 tag->next->prev = tag->prev;
341 swf_tag_destroy(tag);
346 trans_table_close(refcid_trans_table);
352 swf_object_get_tagdata(swf_object_t *swf, int tag_seqno,
353 unsigned long *length) {
355 unsigned char *data = NULL;
356 tag = swf_object_search_tag_byseqno(swf, tag_seqno);
358 bitstream_t *bs = bitstream_open();
359 swf_tag_build(bs, tag, swf);
360 data = bitstream_steal(bs, length);
367 swf_object_replace_tagdata(swf_object_t *swf, int tag_seqno,
368 unsigned char *data, unsigned long length) {
369 swf_tag_t *old_tag, *new_tag;
370 old_tag = swf_object_search_tag_byseqno(swf, tag_seqno);
372 bitstream_t *bs = bitstream_open();
373 bitstream_input(bs, data,length);
374 new_tag = swf_tag_create(bs);
377 _swf_object_replace_tag(swf, old_tag, new_tag);
378 swf_tag_destroy(old_tag);
386 swf_object_get_tagdata_bycid(swf_object_t *swf, int cid,
387 unsigned long *length) {
389 unsigned char *data = NULL;
390 tag = swf_object_search_tag_bycid(swf, cid);
392 bitstream_t *bs = bitstream_open();
393 swf_tag_build(bs, tag, swf);
394 data = bitstream_steal(bs, length);
401 swf_object_replace_tagdata_bycid(swf_object_t *swf, int cid,
402 unsigned char *data, unsigned long length) {
403 swf_tag_t *old_tag, *new_tag;
404 old_tag = swf_object_search_tag_bycid(swf, cid);
406 bitstream_t *bs = bitstream_open();
407 bitstream_input(bs, data,length);
408 new_tag = swf_tag_create(bs);
410 swf_tag_replace_cid(new_tag, cid); // keep cid in SWF
412 // re-join to new tag
413 _swf_object_replace_tag(swf, old_tag, new_tag);
414 swf_tag_destroy(old_tag);
422 swf_object_get_tagcontents_bycid(swf_object_t *swf, int cid,
423 unsigned long *length) {
425 tag = swf_object_search_tag_bycid(swf, cid);
427 // rebuild detail to (raw)data if modified
428 if ((tag->data == NULL) && tag->detail) {
430 bs = bitstream_open();
431 swf_tag_build(bs, tag, swf);
432 tag->data = bitstream_steal(bs, &(tag->length));
436 *length = tag->length - 2;
437 return tag->data + 2; // success
441 return NULL; // failed
445 swf_object_replace_tagcontents_bycid(swf_object_t *swf, int cid,
447 unsigned long length) {
449 tag = swf_object_search_tag_bycid(swf, cid);
452 swf_tag_destroy_detail(tag);
459 tag->length = length + 2;
460 tag->data = malloc(length + 2);
461 PutUShortLE(tag->data, cid);
462 memcpy(tag->data + 2, data, length);
469 swf_object_remove_tag(swf_object_t *swf, int tag_seqno,
470 int tag_seqno_in_sprite) {
474 tag = swf_object_search_tag_byseqno(swf, tag_seqno);
476 if (tag_seqno_in_sprite >= 0) {
477 if (isSpriteTag(tag->code)) {
478 swf_tag_sprite_detail_t *tag_sprite;
479 swf_tag_t *tag_in_sprite;
480 tag_sprite = swf_tag_create_input_detail(tag, swf);
482 tag_in_sprite = swf_object_search_tag_in_sprite_byseqno(tag_sprite, tag_seqno_in_sprite);
484 ret = _swf_object_remove_tag_in_sprite(tag_sprite, tag_in_sprite);
493 fprintf(stderr, "swf_object_remove_tag: not SpriteTag seqno=%d\n", tag_seqno);
496 ret = _swf_object_remove_tag(swf, tag);
503 swf_object_print_tagdata(swf_object_t *swf, unsigned char *data,
504 unsigned long length) {
507 bs = bitstream_open();
508 bitstream_input(bs, data, length);
509 tag = swf_tag_create(bs);
512 fprintf(stderr, "swf_object_print_tagdata: swf_tag_create failed\n");
515 swf_tag_print(tag, swf, 0);
516 swf_tag_destroy(tag);
523 _swf_object_remove_tag(swf_object_t *swf, swf_tag_t *tag) {
525 if (tag->next) { // prev:O next:O
526 tag->prev->next = tag->next;
527 tag->next->prev = tag->prev;
528 } else { // prev:O next:X
529 tag->prev->next = NULL;
530 swf->tag_tail = tag->prev;
533 if (tag->next) { // prev:X next:O
534 tag->next->prev = NULL;
535 swf->tag_head = tag->next;
536 } else { // prev:X next:X
537 swf->tag_head = NULL;
538 swf->tag_tail = NULL;
541 swf_tag_destroy(tag);
546 _swf_object_remove_tag_in_sprite(swf_tag_sprite_detail_t *sprite_tag, swf_tag_t *tag) {
548 if (tag->next) { // prev:O next:O
549 tag->prev->next = tag->next;
550 tag->next->prev = tag->prev;
551 } else { // prev:O next:X
552 tag->prev->next = NULL;
553 // swf->tag_tail = tag->prev;
556 if (tag->next) { // prev:X next:O
557 sprite_tag->tag = tag->next;
558 tag->next->prev = NULL;
559 // swf->tag_heat = tag->next;
560 } else { // prev:X next:X
561 sprite_tag->tag = NULL;
562 // swf->tag_head = NULL;
563 // swf->tag_tail = NULL;
566 swf_tag_destroy(tag);
573 swf_object_get_shapedata(swf_object_t *swf, int cid, unsigned long *length) {
575 unsigned char *data = NULL;
577 tag = swf_object_search_tag_bycid(swf, cid);
580 if (! isShapeTag(tag->code)) {
581 fprintf(stderr, "swf_object_get_shapedata: not isShapeTag(%d)\n", tag->code);
585 bs = bitstream_open();
586 swf_tag_build(bs, tag, swf);
587 data = bitstream_steal(bs, length);
597 swf_object_replace_shapedata(swf_object_t *swf, int cid,
599 unsigned long length) {
600 swf_tag_t *old_tag, *new_tag;
601 old_tag = swf_object_search_tag_bycid(swf, cid);
604 if (! isShapeTag(old_tag->code)) {
605 fprintf(stderr, "swf_object_replace_shapedata: ! isShapeTag(%d)", old_tag->code);
608 bs = bitstream_open();
609 bitstream_input(bs, data, length);
610 new_tag = swf_tag_create(bs);
612 if ((new_tag == NULL) || (! isShapeTag(new_tag->code))) {
613 fprintf(stderr, "swf_object_replace_shapedata: fallback to read old shape data\n");
614 // fallback reading Shape v0.37 and before
616 swf_tag_destroy(new_tag);
618 new_tag = swf_tag_move(old_tag);
619 swf_tag_destroy_detail(new_tag);
620 new_tag->length = length + 2;
624 new_tag->data = malloc(length + 2);
625 PutUShortLE(new_tag->data, cid);
626 memcpy(new_tag->data + 2, data, length);
629 if (swf_tag_create_input_detail(new_tag, swf)) {
631 swf_tag_replace_cid(new_tag, cid);
632 _swf_object_replace_tag(swf, old_tag, new_tag);
633 swf_tag_destroy(old_tag);
634 // information modified so remove raw data.
636 new_tag->data = NULL;
647 swf_object_search_tag_byseqno(swf_object_t *swf, int tag_seqno) {
651 fprintf(stderr, "swf_object_search_tag_by_seqno: swf == NULL\n");
655 for (tag = swf->tag_head ; tag ; tag = tag->next) {
656 if (i >= tag_seqno) {
665 swf_object_search_tag_in_sprite_byseqno(swf_tag_sprite_detail_t *sprite, int tag_seqno) {
668 if (sprite == NULL) {
669 fprintf(stderr, "swf_object_search_tag_by_seqno: sprite == NULL\n");
673 for (tag = sprite->tag ; tag ; tag = tag->next) {
674 if (i >= tag_seqno) {
683 swf_object_search_tag_bycid(swf_object_t *swf, int cid) {
686 fprintf(stderr, "swf_object_search_tag_bycid: swf == NULL\n");
689 for (tag = swf->tag_head ; tag ; tag = tag->next) {
690 if (swf_tag_get_cid(tag) == cid) {
698 swf_object_search_bitmap_tag(swf_object_t *swf, int bitmap_id) {
701 fprintf(stderr, "swf_object_search_bitmap_tag: swf == NULL\n");
704 for (tag = swf->tag_head ; tag ; tag = tag->next) {
705 register int tag_code = tag->code;
706 if (isBitmapTag(tag_code)) {
707 if (swf_tag_get_cid(tag) == bitmap_id) {
716 swf_object_search_cid_by_bitmap_condition(swf_object_t *swf,
717 int width, int height,
718 int red, int green, int blue) {
722 fprintf(stderr, "swf_object_search_cid_by_bitmap_condition: swf == NULL\n");
725 for (tag = swf->tag_head ; tag ; tag = tag->next) {
726 register int tag_code = tag->code;
727 if (isBitmapTag(tag_code)) {
728 cid = swf_tag_search_cid_by_bitmap_condition(tag, width, height,
735 return -1; // Not Found
741 swf_object_set_shape_adjust_mode(swf_object_t *swf, unsigned mode) {
745 swf->shape_adjust_mode = mode;
750 swf_object_adjust_shapebitmap(swf_object_t *swf, int bitmap_id,
751 int old_width, int old_height,
752 int new_width, int new_height) {
753 swf_tag_t *tag = NULL;
754 double width_scale = 0, height_scale = 0;
755 int *bitmap_id_list, bitmap_id_list_num;
756 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_MATRIX_RESCALE) {
757 width_scale = (double) old_width / new_width;
758 height_scale = (double) old_height / new_height;
759 for (tag = swf->tag_head ; tag ; tag=tag->next) {
760 register int tag_code = tag->code;
761 if (isShapeTag(tag_code)) {
762 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
763 if (bitmap_id_list) {
765 for (i = 0 ; i < bitmap_id_list_num ; i++) {
766 if (bitmap_id_list[i] == bitmap_id) {
767 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
768 swf_tag_apply_shape_matrix_factor(tag, swf_tag_shape->shape_id,
769 width_scale, height_scale,
774 free(bitmap_id_list);
780 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_RECT_RESIZE) {
781 width_scale = (double) new_width / old_width;
782 height_scale = (double) new_height / old_height;
783 for (tag = swf->tag_head ; tag ; tag=tag->next) {
784 register int tag_code = tag->code;
785 if (isShapeTag(tag_code)) {
786 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
787 if (bitmap_id_list) {
789 for (i = 0 ; i < bitmap_id_list_num ; i++) {
790 if (bitmap_id_list[i] == bitmap_id) {
791 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
792 swf_tag_apply_shape_rect_factor(tag, swf_tag_shape->shape_id,
793 width_scale, height_scale,
798 free(bitmap_id_list);
803 if (swf->shape_adjust_mode & SWFED_SHAPE_BITMAP_TYPE_TILLED) {
804 for (tag = swf->tag_head ; tag ; tag=tag->next) {
805 register int tag_code = tag->code;
806 if (isShapeTag(tag_code)) {
807 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
808 if (bitmap_id_list) {
810 for (i = 0 ; i < bitmap_id_list_num ; i++) {
811 if (bitmap_id_list[i] == bitmap_id) {
812 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
813 swf_tag_apply_shape_type_tilled(tag, swf_tag_shape->shape_id, swf);
816 free(bitmap_id_list);
825 swf_object_get_bitmap_size(swf_object_t *swf, int bitmap_id,
826 int *width, int *height) {
829 tag = swf_object_search_bitmap_tag(swf, bitmap_id);
833 ret = swf_tag_get_bitmap_size(tag, width, height);
840 swf_object_get_jpegdata(swf_object_t *swf, unsigned long *length, int image_id) {
841 swf_tag_t *tag, *tag_jpegtables = NULL;
842 unsigned char *data = NULL;
845 fprintf(stderr, "swf_object_get_jpegdata: swf == NULL\n");
848 for (tag=swf->tag_head ; tag ; tag=tag->next) {
849 if (tag->code == 8) { // JPEGTables
850 tag_jpegtables = tag;
853 // ! DefineBitsJPEG(1),2,3
854 if ((tag->code != 6) && (tag->code != 21) && (tag->code != 35)) {
857 data = swf_tag_get_jpeg_data(tag, length, image_id, tag_jpegtables);
866 swf_object_get_alphadata(swf_object_t *swf, unsigned long *length, int image_id) {
868 unsigned char *data = NULL;
871 fprintf(stderr, "swf_object_get_alphadata: swf == NULL\n");
874 for (tag=swf->tag_head ; tag ; tag=tag->next) {
875 if (tag->code != 35) { // ! DefineBitsJPEG3
878 data = swf_tag_get_alpha_data(tag, length, image_id);
887 swf_object_replace_jpegdata(swf_object_t *swf, int image_id,
888 unsigned char *jpeg_data,
889 unsigned long jpeg_data_len,
890 unsigned char *alpha_data,
891 unsigned long alpha_data_len,
892 int without_converting) {
895 int old_width, old_height, new_width, new_height;
897 fprintf(stderr, "swf_object_replace_jpegdata: swf == NULL\n");
900 tag = swf_object_search_bitmap_tag(swf, image_id);
902 fprintf(stderr, "swf_object_replace_jpegdata: tag == NULL\n");
905 if (swf->shape_adjust_mode) {
906 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
907 bitmap_size(jpeg_data, jpeg_data_len, &new_width, &new_height);
909 result = swf_tag_replace_jpeg_data(tag, image_id,
910 jpeg_data, jpeg_data_len,
911 alpha_data, alpha_data_len,
914 fprintf(stderr, "swf_object_replace_jpegdata: swf_tag_replace_jpeg_data failed\n");
917 if (swf->shape_adjust_mode) {
918 swf_object_adjust_shapebitmap(swf, image_id,
919 old_width, old_height,
920 new_width, new_height);
928 swf_object_get_pngdata(swf_object_t *swf, unsigned long *length, int image_id) {
930 unsigned char *data = NULL;
932 fprintf(stderr, "swf_object_get_pngdata: swf == NULL\n");
935 if (length == NULL) {
936 fprintf(stderr, "swf_object_get_pngdata: length == NULL\n");
940 for (tag=swf->tag_head ; tag ; tag=tag->next) {
941 // DefineBitsLossless(1),2
942 if ((tag->code != 20) && (tag->code != 36)) {
945 data = swf_tag_get_png_data(tag, length, image_id);
954 swf_object_replace_pngdata(swf_object_t *swf, int image_id,
955 unsigned char *png_data,
956 unsigned long png_data_len, int rgb15) {
959 int old_width, old_height, new_width, new_height;
961 fprintf(stderr, "swf_object_replace_pngdata: swf == NULL\n");
964 if (png_data == NULL) {
965 fprintf(stderr, "swf_object_replace_pngdata: png_data == NULL\n");
968 tag = swf_object_search_bitmap_tag(swf, image_id);
970 fprintf(stderr, "swf_object_replace_pngdata: tag == NULL\n");
973 if (swf->shape_adjust_mode) {
974 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
975 png_size(png_data, png_data_len, &new_width, &new_height);
977 result = swf_tag_replace_png_data(tag, image_id,
978 png_data, png_data_len, rgb15);
980 fprintf(stderr, "swf_object_replace_pngdata: swf_tag_replace_png_data failed\n");
983 if (swf->shape_adjust_mode) {
984 swf_object_adjust_shapebitmap(swf, image_id,
985 old_width, old_height,
986 new_width, new_height);
991 #endif /* HAVE_PNG */
996 swf_object_replace_gifdata(swf_object_t *swf, int image_id,
997 unsigned char *gif_data,
998 unsigned long gif_data_len) {
1001 int old_width, old_height, new_width, new_height;
1003 fprintf(stderr, "swf_object_replace_gifdata: swf == NULL\n");
1006 if (gif_data == NULL) {
1007 fprintf(stderr, "swf_object_replace_gifdata: gif_data == NULL\n");
1010 tag = swf_object_search_bitmap_tag(swf, image_id);
1012 fprintf(stderr, "swf_object_replace_gifdata: tag == NULL\n");
1015 if (swf->shape_adjust_mode) {
1016 swf_tag_get_bitmap_size(tag, &old_width, &old_height);
1017 gif_size(gif_data, gif_data_len, &new_width, &new_height);
1019 result = swf_tag_replace_gif_data(tag, image_id,
1020 gif_data, gif_data_len);
1022 fprintf(stderr, "swf_object_replace_pngdata: swf_tag_replace_png_data failed\n");
1025 if (swf->shape_adjust_mode) {
1026 swf_object_adjust_shapebitmap(swf, image_id,
1027 old_width, old_height,
1028 new_width, new_height);
1033 #endif /* HAVE_GIF */
1036 swf_object_convert_bitmapdata_tojpegtag(swf_object_t *swf) {
1039 fprintf(stderr, "swf_object_convert_bitmapdata_tojpegtag: swf == NULL\n");
1042 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1043 swf_tag_convert_bitmap_data_tojpegtag(tag);
1049 swf_object_get_sounddata(swf_object_t *swf, unsigned long *length, int sound_id) {
1051 unsigned char *data = NULL;
1054 fprintf(stderr, "swf_object_get_sounddata: swf == NULL\n");
1057 if (length == NULL) {
1058 fprintf(stderr, "swf_object_get_sounddata: length == NULL\n");
1061 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1063 if (tag->code != 14) {
1066 data = swf_tag_get_sound_data(tag, length, sound_id);
1075 swf_object_replace_melodata(swf_object_t *swf, int sound_id,
1076 unsigned char *melo_data,
1077 unsigned long melo_data_len) {
1081 fprintf(stderr, "swf_object_replace_melodata: swf == NULL\n");
1084 if (melo_data == NULL) {
1085 fprintf(stderr, "swf_object_replace_melodata: melo_data == NULL\n");
1088 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1089 result = swf_tag_replace_melo_data(tag, sound_id,
1090 melo_data, melo_data_len);
1099 swf_object_get_editstring(swf_object_t *swf,
1100 char *variable_name, int variable_name_len,
1105 fprintf(stderr, "swf_object_get_editstring: swf == NULL\n");
1108 if (variable_name == NULL) {
1109 fprintf(stderr, "swf_object_get_editstring: variable_name == NULL\n");
1112 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1113 data = swf_tag_get_edit_string(tag, variable_name,
1114 variable_name_len, error, swf);
1115 if (data || (*error == 0)) {
1123 swf_object_replace_editstring(swf_object_t *swf,
1124 char *variable_name,
1125 int variable_name_len,
1127 int initial_text_len) {
1131 fprintf(stderr, "swf_object_replace_editstring: swf == NULL\n");
1134 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1135 result = swf_tag_replace_edit_string(tag, variable_name,
1148 swf_object_get_actiondata(swf_object_t *swf, unsigned long *length, int tag_seqno) {
1150 swf_tag_action_detail_t *swf_tag_action;
1152 unsigned char *data;
1155 fprintf(stderr, "swf_object_get_actiondata: swf == NULL\n");
1158 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1159 if (i == tag_seqno) {
1167 if ((tag->code != 12) && (tag->code != 59)) { // DoAction, DoInitAction
1170 swf_tag_action = (swf_tag_action_detail_t *) swf_tag_create_input_detail(tag, swf);
1171 if (swf_tag_action == NULL) {
1172 fprintf(stderr, "swf_object_get_actiondata: swf_tag_create_input_detail failed");
1175 bs = bitstream_open();
1176 swf_action_list_build(bs,swf_tag_action->action_list);
1177 data = bitstream_steal(bs, length);
1178 bitstream_close(bs);
1183 swf_object_insert_action_setvariables(swf_object_t *swf,
1185 swf_tag_t *tag, *prev = NULL;
1186 swf_tag_t *action_tag = NULL, *prev_tag = NULL;
1188 if ((swf == NULL) || (swf->tag_head == NULL)) {
1189 fprintf(stderr, "swf_object_insert_action_setvariables: swf or swf->tag_head is NULL\n");
1192 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1193 switch (tag->code) {
1194 case 1: // ShowFrame
1195 if (prev_tag == NULL) {
1196 // no candidate point before ShowFrame so prev It.
1201 case 12: // DoAction
1202 // DoAction found so merge ActionByteCode to it.
1206 case 69: // FileAttributs
1207 case 9: // SetBackgroundColor
1209 // put image after there tags.
1213 if (prev_tag == NULL) {
1223 if (action_tag) { // apppend setvariable image to top of DoAction
1224 ret = swf_tag_put_action_setvariables(action_tag,
1228 fprintf(stderr, "swf_object_insert_action_setvariables: swf_tag_put_action_setvariables failed\n");
1231 } else { // insert new DoAction
1232 tag = swf_tag_create_action_setvariables(kv);
1234 fprintf(stderr, "swf_object_insert_action_setvariables: swf_tag_create_action_setvariables failed\n");
1237 if (prev_tag == NULL) { // to make sure. abnormal situation.
1238 tag->next = swf->tag_head;
1239 tag->next->prev = tag;
1240 swf->tag_head = tag;
1243 tag->next = prev_tag->next;
1244 tag->next->prev = tag;
1245 prev_tag->next = tag;
1246 tag->prev = prev_tag;
1249 return 0; // SUCCESS
1253 swf_object_replace_action_strings(swf_object_t *swf, y_keyvalue_t *kv) {
1258 fprintf(stderr, "swf_object_replace_action_strings: swf == NULL\n");
1262 fprintf(stderr, "swf_object_replace_action_strings: kv == NULL\n");
1265 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1266 if (isActionTag(tag->code)) {
1267 ret = swf_tag_replace_action_strings(tag, kv, &m, swf);
1269 fprintf(stderr, "swf_object_replace_action_strings: swf_tag_replace_action_string failed\n");
1272 if (m && tag->data) { // action tag modified
1276 } else if (isSpriteTag(tag->code)) {
1277 swf_tag_sprite_detail_t *tag_sprite;
1278 tag_sprite = swf_tag_create_input_detail(tag, swf);
1279 if (tag_sprite == NULL) {
1280 fprintf(stderr, "swf_object_replace_action_strings: tag_sprite == NULL\n");
1284 for (t = tag_sprite->tag ; t ; t = t->next) {
1285 if (isActionTag(t->code)) {
1286 ret = swf_tag_replace_action_strings(t, kv, &m, swf);
1288 fprintf(stderr, "swf_object_replace_action_strings: replace_action_string failed\n");
1295 modified = 1; // action tag modified
1298 if (modified) { // sprite tag rebuild
1311 * replacce reference side CID value
1314 trans_table_replace_refcid_recursive(swf_tag_t *tag, trans_table_t *cid_trans_table) {
1315 for ( ; tag ; tag=tag->next) {
1316 int tag_no = tag->code;
1317 if (isSpriteTag(tag_no)) {
1318 swf_tag_sprite_detail_t *tag_sprite;
1319 tag_sprite = swf_tag_create_input_detail(tag, NULL);
1320 if (tag_sprite == NULL) {
1321 fprintf(stderr, "trans_table_replace_refcid_recursive: tag_sprite swf_tag_create_input_detail failed");
1323 trans_table_replace_refcid_recursive(tag_sprite->tag, cid_trans_table);
1324 } else if (isPlaceTag(tag_no)) {
1325 int refcid = swf_tag_get_refcid(tag);
1327 int to_refcid = trans_table_get(cid_trans_table, refcid);
1328 if (refcid != to_refcid) {
1329 swf_tag_replace_refcid(tag, to_refcid);
1336 // return Sprite tag mapped target path
1338 swf_object_saerch_sprite_by_target_path(swf_tag_t *tag_head,
1339 unsigned char *target_path,
1340 int target_path_len,
1341 swf_object_t *swf) {
1342 swf_tag_t *tag, *sprite_tag = NULL;
1343 unsigned char *instance_name, *next_instance_name;
1344 int instance_name_len;
1347 next_instance_name = (unsigned char *) strchr((char *) target_path, '/');
1348 if (next_instance_name != NULL) {
1349 next_instance_name[0] = '\0'; // null terminate
1350 next_instance_name++;
1353 instance_name = target_path;
1354 instance_name_len = strlen((char *) instance_name);
1356 // search PlaceObject by instance_name and get ref CID
1357 for (tag = tag_head ; tag ; tag=tag->next) {
1359 if (tag->code == 26) { // PlaceObject2
1360 cid = swf_tag_place_get_cid_by_instance_name(tag, instance_name, instance_name_len, swf);
1368 "swf_object_saerch_sprite_by_target_path: not found place target_path=%s (cid=%d)\n",
1370 return NULL; // not found instance name;
1373 // search DefineSprite by CID
1374 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1375 if (isSpriteTag(tag->code)) {
1376 if (swf_tag_get_cid(tag) == cid) {
1382 if (next_instance_name) { // nested sprite
1384 swf_tag_sprite_detail_t *tag_sprite;
1385 tag_sprite = swf_tag_create_input_detail(sprite_tag, swf);
1386 if (tag_sprite == NULL) {
1387 fprintf(stderr, "swf_object_saerch_sprite_by_target_path: tag_sprite swf_tag_create_input_detail failed\n");
1389 sprite_tag = swf_object_saerch_sprite_by_target_path(tag_sprite->tag, next_instance_name, target_path_len - instance_name_len - 1, swf);
1397 swf_object_replace_movieclip(swf_object_t *swf,
1398 unsigned char *instance_name, int instance_name_len,
1399 unsigned char *swf_data, int swf_data_len) {
1400 int cid = 0, sprite_cid = 0, ret = 0;
1401 swf_tag_t *tag = NULL;
1402 swf_tag_t *sprite_tag = NULL, *prev_sprite_tag = NULL;
1403 swf_tag_t *sprite_tag_tail = NULL; // last tag in sprite.
1404 swf_tag_sprite_detail_t *swf_tag_sprite = NULL;
1405 swf_object_t *swf4sprite = NULL;
1406 swf_tag_info_t *tag_info = NULL;
1407 swf_tag_detail_handler_t *detail_handler = NULL;
1408 trans_table_t *cid_trans_table = NULL;
1411 fprintf(stderr, "swf_object_replace_movieclip: swf == NULL\n");
1415 // search symbol(SpriteTag) mapped instance_name(target path)
1416 sprite_tag = swf_object_saerch_sprite_by_target_path(tag=swf->tag_head,
1421 if (sprite_tag == NULL) {
1422 fprintf(stderr, "swf_object_replace_movieclip: sprite_tag == NULL\n");
1423 return 1; // not found instance name;
1425 prev_sprite_tag = sprite_tag->prev;
1426 sprite_cid = swf_tag_get_cid(sprite_tag);
1428 // swf data that MC replace to
1429 swf4sprite = swf_object_open();
1430 ret = swf_object_input(swf4sprite, swf_data, swf_data_len);
1432 fprintf(stderr, "swf_object_replace_movieclip: swf_object_input (swf_data_len=%d) failed\n", swf_data_len);
1437 cid_trans_table = trans_table_open();
1438 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1440 cid = swf_tag_get_cid(tag);
1442 trans_table_set(cid_trans_table, cid, TRANS_TABLE_RESERVE_ID);
1445 // trans_table_print(cid_trans_table);
1447 // clean up innner SpriteTag
1448 tag_info = get_swf_tag_info(sprite_tag->code);
1449 detail_handler = tag_info->detail_handler();
1450 free(sprite_tag->data);
1451 sprite_tag->data = NULL;
1452 sprite_tag->length = 0;
1453 if (sprite_tag->detail) {
1454 detail_handler->destroy(sprite_tag);
1456 sprite_tag->detail = detail_handler->create();
1457 swf_tag_sprite = sprite_tag->detail;
1458 swf_tag_sprite->sprite_id = sprite_cid;
1460 // extract tag each that type in SWF
1461 for (tag = swf4sprite->tag_head ; tag ; tag = tag->next) {
1462 int tag_no = tag->code;
1466 case 3: // FreeCharacter
1467 case 9: // SetBackgroundColor
1470 case 69: // FileAttributes
1471 case 74: // CSMTextSettings
1472 case 8: // JPEGTables // XXX
1476 case 2: // DefineShape
1477 case 6: // DefineBitsJPEG
1478 case 7: // DefineButton
1479 case 10: // DefineFont
1480 case 11: // DefineText
1481 case 13: // DefineFontInfo
1482 case 14: // DefineSound
1483 case 17: // DefineButtonSound
1484 case 18: // SoundStreamHead"
1485 case 19: // SoundStreamBlock
1486 case 20: // DefineBitsLossless
1487 case 21: // DefineBitsJPEG2
1488 case 22: // DefineShape2
1489 case 32: // DefineShape3
1490 case 33: // DefineText2
1491 case 34: // DefineButton2
1492 case 35: // DefineBitsJPEG3
1493 case 36: // DefineBitsLossless2
1494 case 37: // DefineEditText
1495 case 39: // DefineSprite
1496 case 46: // DefineMorphShape
1497 case 48: // DefineFont2
1498 case 73: // DefineFontAlignZones
1499 case 75: // DefineFont3
1500 case 83: // DefineShape4
1501 case 84: // DefineMorphShape2
1502 case 88: // DefineFontName
1504 cid = swf_tag_get_cid(tag);
1507 to_cid = trans_table_get(cid_trans_table, cid);
1508 if (to_cid == TRANS_TABLE_RESERVE_ID) {
1509 to_cid = trans_table_get_freeid(cid_trans_table);
1510 trans_table_set(cid_trans_table, cid, to_cid);
1511 trans_table_set(cid_trans_table, to_cid, TRANS_TABLE_RESERVE_ID);
1512 } else if (to_cid == 0) {
1513 trans_table_set(cid_trans_table, cid, cid);
1516 if (cid != to_cid) {
1517 if (swf_tag_replace_cid(tag, to_cid)) {
1518 fprintf(stderr, "swf_object_replace_movieclip: swf_tag_replace_cid %d => %d failed\n", cid, to_cid);
1523 if (isShapeTag(tag_no)) {
1524 int *bitmap_id_list, bitmap_id_list_num;
1525 bitmap_id_list = swf_tag_shape_bitmap_get_refcid_list(tag, &bitmap_id_list_num);
1526 if (bitmap_id_list) {
1528 for (i = 0 ; i < bitmap_id_list_num; i++) {
1529 int bitmap_id = bitmap_id_list[i];
1530 int to_bitmap_id = trans_table_get(cid_trans_table, bitmap_id);
1531 if ((to_bitmap_id > 0) && (bitmap_id != to_bitmap_id)) {
1532 swf_tag_shape_bitmap_replace_refcid_list(tag, bitmap_id, to_bitmap_id);
1535 free(bitmap_id_list);
1537 } else if (isSpriteTag(tag_no)){
1538 swf_tag_sprite_detail_t *s;
1539 s = swf_tag_create_input_detail(tag, swf);
1541 fprintf(stderr, "swf_object_replace_movieclip: s swf_tag_create_input_detail failed\n");
1543 trans_table_replace_refcid_recursive(s->tag, cid_trans_table);
1547 // extract tag before SpriteTag
1548 prev_sprite_tag->next = swf_tag_move(tag);
1549 prev_sprite_tag = prev_sprite_tag->next;
1550 prev_sprite_tag->next = sprite_tag;
1554 case 1: // ShowFrame
1555 case 4: // PlaceObject
1556 case 5: // RemoveObject
1557 case 12: // DoAction
1558 case 15: // StartSound
1559 case 26: // PlaceObject2
1560 case 28: // RemoveObject2
1561 case 43: // FrameLabel
1562 case 59: // DoInitAction
1563 // insert into Sprite
1564 // follow Character ID change
1566 int refcid, to_refcid;
1567 case 4: // PlaceObject
1568 case 26: // PlaceObject2
1569 refcid = swf_tag_get_refcid(tag);
1571 to_refcid = trans_table_get(cid_trans_table, refcid);
1572 if (refcid != to_refcid) {
1573 swf_tag_replace_refcid(tag, to_refcid);
1578 // inplant tag to Sprite
1579 if (sprite_tag_tail == NULL) {
1580 swf_tag_sprite->tag = swf_tag_move(tag);
1581 sprite_tag_tail = swf_tag_sprite->tag;
1583 sprite_tag_tail->next = swf_tag_move(tag);
1584 sprite_tag_tail = sprite_tag_tail->next;
1586 sprite_tag_tail->next = NULL;
1587 if (tag_no == 1) { // ShowFrame
1588 swf_tag_sprite->frame_count += 1;
1593 trans_table_close(cid_trans_table);
1594 swf_object_close(swf4sprite);
1599 swf_object_apply_shapematrix_factor(swf_object_t *swf, int shape_id,
1600 double scale_x, double scale_y,
1602 signed int trans_x, signed int trans_y) {
1606 fprintf(stderr, "swf_object_apply_shapematrix_factor: swf == NULL\n");
1609 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1610 result = swf_tag_apply_shape_matrix_factor(tag, shape_id,
1623 swf_object_apply_shaperect_factor(swf_object_t *swf, int shape_id,
1624 double scale_x, double scale_y,
1625 signed int trans_x, signed int trans_y) {
1629 fprintf(stderr, "swf_object_apply_shaperect_factor: swf == NULL\n");
1632 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1633 result = swf_tag_apply_shape_rect_factor(tag, shape_id,
1645 swf_object_apply_shapetype_tilled(swf_object_t *swf,int shape_id) {
1649 fprintf(stderr, "swf_object_apply_shaperect_factor: swf == NULL\n");
1652 for (tag=swf->tag_head ; tag ; tag=tag->next) {
1653 result = swf_tag_apply_shape_type_tilled(tag, shape_id, swf);
1662 swf_object_is_shape_tagdata(unsigned char *data, int data_len) {
1665 int ret = 0; // default FALSE;
1667 bs = bitstream_open();
1668 bitstream_input(bs, data, data_len);
1669 tag = swf_tag_create(bs);
1671 if (isShapeTag(tag->code)) {
1675 bitstream_close(bs);
1680 swf_object_is_bitmap_tagdata(unsigned char *data, int data_len) {
1683 int ret = 0; // default FALSE;
1685 bs = bitstream_open();
1686 bitstream_input(bs, data, data_len);
1687 tag = swf_tag_create(bs);
1689 if (isBitmapTag(tag->code)) {
1693 bitstream_close(bs);
1698 _swf_object_replace_tag(swf_object_t *swf,
1699 swf_tag_t *old_tag, swf_tag_t *new_tag) {
1700 old_tag->prev->next = new_tag;
1701 old_tag->next->prev = new_tag;
1702 new_tag->prev = old_tag->prev;
1703 new_tag->next = old_tag->next;
1704 if (new_tag->prev == NULL) {
1705 swf->tag_head = new_tag;
1707 if (new_tag->next == NULL) {
1708 swf->tag_tail = new_tag;
1710 old_tag->prev = NULL;
1711 old_tag->next = NULL;