2 +----------------------------------------------------------------------+
3 | Author: yoya@awm.jp |
4 +----------------------------------------------------------------------+
10 #include "swf_shape_record.h"
11 #include "swf_tag_shape.h"
12 #include "swf_object.h"
14 swf_tag_detail_handler_t shape_detail_handler;
16 swf_tag_detail_handler_t *
17 swf_tag_shape_detail_handler(void) {
18 shape_detail_handler.create = swf_tag_shape_create_detail;
19 shape_detail_handler.input = swf_tag_shape_input_detail;
20 shape_detail_handler.get_cid = swf_tag_shape_get_cid_detail;
21 shape_detail_handler.replace_cid = swf_tag_shape_replace_cid_detail;
22 shape_detail_handler.output = swf_tag_shape_output_detail;
23 shape_detail_handler.print = swf_tag_shape_print_detail;
24 shape_detail_handler.destroy = swf_tag_shape_destroy_detail;
25 return &shape_detail_handler;
28 swf_tag_detail_handler_t *
29 swf_tag_shape_cid_handler(void) {
30 shape_detail_handler.create = NULL;
31 shape_detail_handler.input = NULL;
32 shape_detail_handler.get_cid = swf_tag_shape_get_cid_detail;
33 shape_detail_handler.replace_cid = swf_tag_shape_replace_cid_detail;
34 shape_detail_handler.output = NULL;
35 shape_detail_handler.print = NULL;
36 shape_detail_handler.destroy = NULL;
37 return &shape_detail_handler;
41 swf_tag_shape_create_detail(void) {
42 swf_tag_shape_detail_t *swf_tag_shape;
43 swf_tag_shape = calloc(sizeof(*swf_tag_shape), 1);
44 if (swf_tag_shape == NULL) {
45 fprintf(stderr, "ERROR: swf_tag_shape_create_detail: can't calloc\n");
52 swf_tag_shape_input_detail(swf_tag_t *tag, struct swf_object_ *swf) {
53 swf_tag_shape_detail_t *swf_tag_shape = tag->detail;
54 unsigned char *data = tag->data;
55 unsigned long length = tag->length;
59 if (swf_tag_shape == NULL) {
60 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape == NULL\n");
64 swf_tag_shape->_current_x = 0;
65 swf_tag_shape->_current_y = 0;
66 swf_tag_shape->_parse_condition = 0;
68 bs = bitstream_open();
69 bitstream_input(bs, data, length);
71 swf_tag_shape->shape_id = bitstream_getbytesLE(bs, 2);
72 ret = swf_rect_parse(bs, &(swf_tag_shape->rect));
74 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->rect parse failed. shape_id=%d\n", swf_tag_shape->shape_id);
79 // DefineMorphShape, DefineMorphShape2
80 swf_tag_shape->is_morph = (tag->code == 46) || (tag->code == 84);
81 // DefineShape4, DefineMorphShape2
82 swf_tag_shape->has_strokes = (tag->code == 83) || (tag->code == 84);
84 if (swf_tag_shape->is_morph) {
85 ret = swf_rect_parse(bs, &(swf_tag_shape->rect_morph));
87 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->rect_morph parse failed. shape_id=%d\n", swf_tag_shape->shape_id);
92 if (swf_tag_shape->has_strokes) {
93 ret = swf_rect_parse(bs, &(swf_tag_shape->stroke_rect));
95 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->stroke_rect parse failed. shape_id=%d\n", swf_tag_shape->shape_id);
99 if (swf_tag_shape->is_morph) {
100 ret = swf_rect_parse(bs, &(swf_tag_shape->stroke_rect_morph));
102 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->stroke_rect_morph parse failed. shape_id=%d\n", swf_tag_shape->shape_id);
107 swf_tag_shape->define_shape_reserved = bitstream_getbits(bs, 6);
108 swf_tag_shape->define_shape_non_scaling_strokes = bitstream_getbits(bs, 1);
109 swf_tag_shape->define_shape_scaling_strokes = bitstream_getbits(bs, 1);
111 if (swf_tag_shape->is_morph) {
113 swf_tag_shape->offset_morph = bitstream_getbytesLE(bs, 4);
114 ret = swf_morph_shape_with_style_parse(bs, &swf_tag_shape->morph_shape_with_style, tag);
116 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_shape_with_style_parse swf_tag_shape->morph_shape_with_style failed. shape_id=%d\n", swf_tag_shape->shape_id);
121 ret = swf_shape_with_style_parse(bs, &swf_tag_shape->shape_with_style, tag);
123 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_shape_with_style_parse swf_tag_shape->shape_with_style failed. shape_id=%d\n", swf_tag_shape->shape_id);
133 int swf_tag_shape_get_cid_detail(swf_tag_t *tag) {
134 unsigned char *data = tag->data;
136 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
137 return swf_tag_shape->shape_id;
140 fprintf(stderr, "swf_tag_shape_get_cid_detail: data == NULL\n");
143 return GetUShortLE(data); // shape_id;
146 int swf_tag_shape_replace_cid_detail(swf_tag_t *tag, int id) {
147 unsigned char *data = tag->data;
149 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
150 swf_tag_shape->shape_id = id;
153 PutUShortLE(data, id);
155 return 0; // always 0
158 static swf_shape_record_t *
159 _swf_tag_shape_search_new_style_in_shape_records(swf_shape_record_t *shape_records) {
160 for ( ; shape_records ; shape_records = shape_records->next) {
161 if ((shape_records->first_6bits) &&
162 ((shape_records->first_6bits & 0x20) == 0)) {
163 if (shape_records->shape.shape_setup.shape_has_new_styles) {
168 return shape_records;
172 swf_tag_shape_bitmap_get_refcid_list(swf_tag_t *tag, int *cid_list_num) {
173 swf_tag_shape_detail_t *swf_tag_shape;
175 int *cid_list, cid_list_alloc;
176 swf_styles_t *styles = NULL;
177 swf_shape_record_t *shape_records = NULL;
180 fprintf(stderr, "swf_tag_shape_bitmap_get_refcid: tag == NULL\n");
183 if (! isShapeTag(tag->code)) {
184 fprintf(stderr, "swf_tag_shape_bitmap_get_refcid: ! isShapeTag(%d)\n",
188 if (tag->detail == NULL) {
189 tag->detail = swf_tag_shape_create_detail();
190 swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
191 // swf_tag_shape->_parse_condition = SWF_TAG_SHAPE_PARSE_CONDITION_BITMAP;
192 ret = swf_tag_shape_input_detail(tag, NULL);
194 swf_tag_shape_destroy_detail(tag);
195 return NULL; // no shape bitmap
198 swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
203 cid_list = malloc(sizeof(int) * cid_list_alloc);
205 if (tag->code == 46) { // DefineMorphShape
206 styles = &(swf_tag_shape->morph_shape_with_style.styles);
207 shape_records = &(swf_tag_shape->morph_shape_with_style.shape_records);
209 styles = &(swf_tag_shape->shape_with_style.styles);
210 shape_records = &(swf_tag_shape->shape_with_style.shape_records);
213 for (i = 0 ; i < styles->fill_styles.count ; i++) {
214 swf_fill_style_t *fill_style;
215 fill_style = &(styles->fill_styles.fill_style[i]);
216 if (fill_style == NULL) {
217 fprintf(stderr, "swf_tag_shape_bitmap_get_refcid: fill_style == NULL i=%d\n", i);
219 return NULL; // Illegal!!!
221 switch (fill_style->type) {
223 case 0x40: // tilled bitmap fill with smoothed edges
224 case 0x41: // clipped bitmap fill with smoothed edges
225 case 0x42: // tilled bitmap fill with hard edges
226 case 0x43: // clipped bitmap fill with hard edges
227 if (fill_style->bitmap.bitmap_ref != 0xffff) {
228 if (cid_list_alloc <= *cid_list_num) {
230 tmp = realloc(cid_list, cid_list_alloc);
232 fprintf(stderr, "swf_tag_shape_bitmap_get_refcid_list: Can't realloc memory (%p, %d)\n", cid_list, cid_list_alloc);
238 cid_list[*cid_list_num] = fill_style->bitmap.bitmap_ref;
239 *cid_list_num = (*cid_list_num) + 1;
247 shape_records = _swf_tag_shape_search_new_style_in_shape_records(shape_records);
250 styles = &(shape_records->shape.shape_setup.styles);
251 shape_records = shape_records->next; // next
257 if (*cid_list_num == 0) {
261 return cid_list; // not found
264 int swf_tag_shape_bitmap_replace_refcid_list(swf_tag_t *tag, int from_cid, int to_cid) {
265 swf_tag_shape_detail_t *swf_tag_shape;
267 swf_styles_t *styles = NULL;
268 swf_shape_record_t *shape_records = NULL;
269 int morph_shape_check = 0;
271 fprintf(stderr, "swf_tag_shape_bitmap_replace_refcid: tag == NULL\n");
274 if (! isShapeTag(tag->code)) {
275 fprintf(stderr, "swf_tag_shape_bitmap_replace_refcid: ! isShapeTag(%d)\n",
279 if (tag->detail == NULL) {
280 tag->detail = swf_tag_shape_create_detail();
281 swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
282 // swf_tag_shape->_parse_condition = SWF_TAG_SHAPE_PARSE_CONDITION_BITMAP;
283 ret = swf_tag_shape_input_detail(tag, NULL);
285 swf_tag_shape_destroy_detail(tag);
286 return 1; // no shape bitmap
289 swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
292 if (tag->code == 46) { // DefineMorphShape
293 morph_shape_check = 1;
294 styles = &(swf_tag_shape->morph_shape_with_style.styles);
295 shape_records = &(swf_tag_shape->morph_shape_with_style.shape_records);
296 // shape_records = &(swf_tag_shape->morph_shape_with_style.shape_records_morph);
298 styles = &(swf_tag_shape->shape_with_style.styles);
299 shape_records = &(swf_tag_shape->shape_with_style.shape_records);
302 for (i = 0 ; i < styles->fill_styles.count ; i++) {
303 swf_fill_style_t *fill_style;
304 fill_style = &(styles->fill_styles.fill_style[i]);
305 if (fill_style == NULL) {
306 fprintf(stderr, "swf_tag_shape_bitmap_replace_refcid: fill_style == NULL i=%d\n", i);
307 return 1; // Illegal!!!
309 switch (fill_style->type) {
310 case 0x40: // tilled bitmap fill with smoothed edges
311 case 0x41: // clipped bitmap fill with smoothed edges
312 case 0x42: // tilled bitmap fill with hard edges
313 case 0x43: // clipped bitmap fill with hard edges
314 if (fill_style->bitmap.bitmap_ref == from_cid) {
315 fill_style->bitmap.bitmap_ref = to_cid;
321 return 0; // success!
329 for ( ; shape_records ; shape_records = shape_records->next) {
330 if ((shape_records->first_6bits) &&
331 ((shape_records->first_6bits & 0x20) == 0)) {
332 if (shape_records->shape.shape_setup.shape_has_new_styles) {
333 styles = &(shape_records->shape.shape_setup.styles);
338 shape_records = _swf_tag_shape_search_new_style_in_shape_records(shape_records);
341 styles = &(shape_records->shape.shape_setup.styles);
342 shape_records = shape_records->next; // next
344 morph_shape_check = 0;
345 if (morph_shape_check) {
346 shape_records = &(swf_tag_shape->morph_shape_with_style.shape_records);
347 shape_records = _swf_tag_shape_search_new_style_in_shape_records(shape_records);
349 styles = &(shape_records->shape.shape_setup.styles);
350 morph_shape_check = 0;
359 return 1; // not found
363 swf_tag_shape_output_detail(swf_tag_t *tag, unsigned long *length,
364 struct swf_object_ *swf) {
365 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
370 long offset_of_offset_morph = 0;
371 long tmp_offset_byte = 0;
372 long tmp_offset_bit = 0;
375 swf_tag_shape->_current_fill_style_num = 0;
376 swf_tag_shape->_current_line_style_num = 0;
377 swf_tag_shape->_current_x = 0;
378 swf_tag_shape->_current_y = 0;
381 bs = bitstream_open();
382 bitstream_putbytesLE(bs, swf_tag_shape->shape_id, 2);
383 swf_rect_build(bs, &(swf_tag_shape->rect));
385 // DefineMorphShape, DefineMorphShape2
386 swf_tag_shape->is_morph = (tag->code == 46) || (tag->code == 84);
387 // DefineShape4, DefineMorphShape2
388 swf_tag_shape->has_strokes = (tag->code == 83) || (tag->code == 84);
390 if (swf_tag_shape->is_morph) {
391 ret = swf_rect_build(bs, &(swf_tag_shape->rect_morph));
393 fprintf(stderr, "ERROR: swf_tag_shape_output_detail: swf_tag_shape->rect_morph build failed\n");
398 if (swf_tag_shape->has_strokes) {
399 ret = swf_rect_build(bs, &(swf_tag_shape->stroke_rect));
401 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->stroke_rect build failed\n");
405 if (swf_tag_shape->is_morph) {
406 ret = swf_rect_build(bs, &(swf_tag_shape->stroke_rect_morph));
408 fprintf(stderr, "ERROR: swf_tag_shape_input_detail: swf_tag_shape->stroke_rect_morph build failed\n");
413 bitstream_putbits(bs, 6, swf_tag_shape->define_shape_reserved );
414 bitstream_putbits(bs, 1, swf_tag_shape->define_shape_non_scaling_strokes );
415 bitstream_putbits(bs, 1, swf_tag_shape->define_shape_scaling_strokes);
417 if (swf_tag_shape->is_morph) {
419 // 後で上書きするので、offset を覚えておく
420 offset_of_offset_morph = bitstream_getbytepos(bs);
421 bitstream_putbytesLE(bs, swf_tag_shape->offset_morph, 4);
422 swf_morph_shape_with_style_build(bs, &swf_tag_shape->morph_shape_with_style, tag);
423 // offset_morph のフィールドに戻って上書きする
424 // offset_morph の後ろからの offset 差なので、- 4 する
425 swf_tag_shape->offset_morph = swf_tag_shape->morph_shape_with_style.offset_of_end_edges - offset_of_offset_morph - 4;
426 tmp_offset_byte = bitstream_getbytepos(bs); // offset を退避
427 tmp_offset_bit = bitstream_getbitpos(bs);
428 bitstream_setpos(bs, offset_of_offset_morph, 0);
429 bitstream_putbytesLE(bs, swf_tag_shape->offset_morph , 4);
430 bitstream_setpos(bs, tmp_offset_byte, tmp_offset_bit); // 元に戻す
432 ret = swf_shape_with_style_build(bs, &swf_tag_shape->shape_with_style, tag);
434 fprintf(stderr, "swf_tag_shape_output_detail: swf_shape_with_style_build failed\n");
440 data = bitstream_steal(bs, length);
446 swf_tag_shape_print_detail(swf_tag_t *tag,
447 struct swf_object_ *swf, int indent_depth) {
448 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
450 print_indent(indent_depth);
451 printf("shape_id=%d\n", swf_tag_shape->shape_id);
452 swf_rect_print(&(swf_tag_shape->rect), indent_depth);
453 // print_indent(indent_depth);
454 // printf("is_morph=%d has_strokes=%d\n",
455 // swf_tag_shape->is_morph, swf_tag_shape->has_strokes);
456 if (swf_tag_shape->is_morph) {
457 swf_rect_print(&(swf_tag_shape->rect_morph), indent_depth);
459 if (swf_tag_shape->has_strokes) {
460 swf_rect_print(&(swf_tag_shape->stroke_rect), indent_depth);
461 if (swf_tag_shape->is_morph) {
462 swf_rect_print(&(swf_tag_shape->stroke_rect_morph), indent_depth);
464 print_indent(indent_depth);
465 printf("define_shape_non_scaling_strokes=%d define_shape_scaling_strokes=%d\n",
466 swf_tag_shape->define_shape_non_scaling_strokes,
467 swf_tag_shape->define_shape_scaling_strokes);
469 if (swf_tag_shape->is_morph) {
470 print_indent(indent_depth);
471 printf("offset_morph=%lu\n", swf_tag_shape->offset_morph);
472 swf_morph_shape_with_style_print(&swf_tag_shape->morph_shape_with_style,
475 swf_shape_with_style_print(&swf_tag_shape->shape_with_style,
482 swf_tag_shape_destroy_detail(swf_tag_t *tag) {
483 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) tag->detail;
485 swf_morph_shape_with_style_delete(&(swf_tag_shape->morph_shape_with_style));
486 swf_shape_with_style_delete(&(swf_tag_shape->shape_with_style));
494 swf_tag_shape_apply_matrix_factor(void *detail, int shape_id,
495 double scale_x, double scale_y,
498 signed int trans_y) {
500 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) detail;
501 if (detail == NULL) {
502 fprintf(stderr, "swf_tag_shape_apply_matrix_factor: detail == NULL\n");
505 swf_fill_style_t *fill_style;
506 if (shape_id != swf_tag_shape->shape_id) {
509 for (i = 0 ; i < swf_tag_shape->shape_with_style.styles.fill_styles.count ; i++) {
510 fill_style = &(swf_tag_shape->shape_with_style.styles.fill_styles.fill_style[i]);
511 switch (fill_style->type) {
512 case 0x10: // linear gradient fill
513 case 0x12: // radial gradient fill
514 case 0x13: // focal gradient fill
515 swf_matrix_apply_factor(&(fill_style->gradient.gradient_matrix), scale_x, scale_y,
516 rotate_rad, trans_x, trans_y);
518 case 0x40: // tilled bitmap fill with smoothed edges
519 case 0x41: // clipped bitmap fill with smoothed edges
520 case 0x42: // tilled bitmap fill with hard edges
521 case 0x43: // clipped bitmap fill with hard edges
522 swf_matrix_apply_factor(&(fill_style->bitmap.bitmap_matrix),
523 scale_x, scale_y, rotate_rad,
527 fprintf(stderr, "swf_tag_shape_apply_matrix_factor: unknown fill_style->type=%d\n",
536 swf_tag_shape_apply_rect_factor(void *detail, int shape_id,
537 double scale_x, double scale_y,
539 signed int trans_y) {
541 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) detail;
542 if (detail == NULL) {
543 fprintf(stderr, "swf_tag_shape_apply_rect_factor: detail == NULL\n");
546 if (shape_id != swf_tag_shape->shape_id) {
549 swf_rect_apply_factor(&(swf_tag_shape->rect),
550 scale_x, scale_y, trans_x, trans_y);
552 swf_shape_record_edge_apply_factor(&(swf_tag_shape->shape_with_style.shape_records),
553 scale_x, scale_y, trans_x, trans_y);
558 swf_tag_shape_apply_type_tilled(void *detail, int shape_id) {
560 swf_tag_shape_detail_t *swf_tag_shape = (swf_tag_shape_detail_t *) detail;
561 if (detail == NULL) {
562 fprintf(stderr, "swf_tag_shape_apply_type_tilled: detail == NULL\n");
565 if (shape_id != swf_tag_shape->shape_id) {
566 fprintf(stderr, "swf_tag_shape_apply_type_tilled: shape_id(%d) != shape->shape_id(%d)\n",
567 shape_id, swf_tag_shape->shape_id);
570 count = swf_tag_shape->shape_with_style.styles.fill_styles.count;
571 for (i = 0 ; i < count ; i++) {
572 swf_fill_style_t *fill_style = &(swf_tag_shape->shape_with_style.styles.fill_styles.fill_style[i]);
573 switch (fill_style->type) {
574 case 0x41: // clipped bitmap fill with smoothed edges
575 fill_style->type = 0x40; // tilled bitmap fill with smoothed edges
577 case 0x43: // clipped bitmap fill with hard edges
578 fill_style->type = 0x42; // tilled bitmap fill with hard edges