📄 fad.morph.c
字号:
/** * libFAD - Flash Animation Decode library * Copyright (C) 2005-2006 VGSystem Technologies, Inc. * * libFAD is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: fad.morph.c,v 1.32 2006/03/07 10:17:57 wrxzzj Exp $ */#include "fad.morph.h"#include "fad.bits.h"typedef fill_style_array_t morph_fill_style_array_t;typedef line_style_array_t morph_line_style_array_t;typedef struct { u16_t fs_num, ls_num; dynarray_t* dict; morph_sr_node_list_t **array;} morph_shape_record_t;typedef struct { fad_object_t base; rect_t start_bound, end_bound; morph_fill_style_array_t mfsa; morph_line_style_array_t mlsa; morph_shape_record_t msr;} morph_shape_t;static cairo_pattern_t *pat = NULL;static cairo_surface_t *ips = NULL;static void _morph_line_style_do_render(fad_render_t* render, line_style_array_t* mlsa, u16_t idx, u16_t ratio) { u8_t *ptr = NULL; u16_t sw, ew; bits_t bits; u8_t r, g, b, a; if(mlsa && idx <= mlsa->count && idx) { ptr = mlsa->array + (idx-1)*12; bits_init(&bits); bits_buffer(&bits, ptr); sw = bits_get_u16(&bits); ew = bits_get_u16(&bits); sw = sw+(((ew-sw)*ratio+0x8000)>>16); if(sw < 2) sw = 2; cairo_set_line_width(render->cr, (double)sw/20); r = *(ptr+4); g = *(ptr+5); b = *(ptr+6); a = *(ptr+7); r += ((*(ptr+8)-r)*ratio+0x8000)>>16; g += ((*(ptr+9)-g)*ratio+0x8000)>>16; b += ((*(ptr+10)-b)*ratio+0x8000)>>16; a += ((*(ptr+11)-a)*ratio+0x8000)>>16; FAD_DEBUG("set morph line style, r = %d, g = %d, b = %d, a = %d\n", r, g, b, a); cairo_set_source_rgba(render->cr, (double)r/0xff, (double)g/0xff, (double)b/0xff, (double)a/0xff); }}static void _calc_matrix_by_ratio(bits_t* bits, cairo_matrix_t* mx, u16_t ratio) { cairo_matrix_t emx, smx; double rate = (double)ratio/0xffff; bits_get_matrix(bits, &smx); bits_get_matrix(bits, &emx); mx->xx = smx.xx + (emx.xx-smx.xx)*rate; mx->yy = smx.yy + (emx.yy-smx.yy)*rate; mx->yx = smx.yx + (emx.yx-smx.yx)*rate; mx->xy = smx.xy + (emx.xy-smx.xy)*rate; mx->x0 = smx.x0 + (emx.x0-smx.x0)*rate; mx->y0 = smx.y0 + (emx.y0-smx.y0)*rate;}static void _morph_fill_style_do_render(fad_render_t* render, fill_style_array_t* mfsa, u16_t idx, dynarray_t* dict, u16_t ratio) { u8_t* ptr = NULL; u8_t r, g, b, a, type; bits_t bits; cairo_matrix_t mx; if(mfsa && idx <= mfsa->count && idx) { bits_init(&bits); ptr = mfsa->array[idx-1]; switch(type = *ptr++) { case 0x00: r = *ptr; g = *(ptr+1); b = *(ptr+2); a = *(ptr+3); r += ((*(ptr+4)-r)*ratio+0x8000)>>16; g += ((*(ptr+5)-g)*ratio+0x8000)>>16; b += ((*(ptr+6)-b)*ratio+0x8000)>>16; a += ((*(ptr+7)-a)*ratio+0x8000)>>16; FAD_DEBUG("set morph fill color style, r = %d, g = %d, b = %d, a = %d\n", r, g, b, a); cairo_set_source_rgba(render->cr, (double)r/0xff, (double)g/0xff, (double)b/0xff, (double)a/0xff); break; case 0x10: case 0x12: { u8_t num = 0, sr, er, r, g, b, a; u32_t sc, ec; if(pat != NULL) cairo_pattern_destroy(pat); bits_buffer(&bits, ptr); _calc_matrix_by_ratio(&bits, &mx, ratio); if(type == 0x10) pat = cairo_pattern_create_linear(-16384.00/20.00, 0.00, 16384.00/20.00, 0.00); else pat = cairo_pattern_create_radial(0.00, 0.00, 0.00, 0.00, 0.00, 16384.00/20.00); for(num = bits_get_u8(&bits); num > 0; num--) { sr = bits_get_u8(&bits); sc = bits_get_u32(&bits); er = bits_get_u8(&bits); ec = bits_get_u32(&bits); sr += ((er-sr)*ratio>>16); sc += ((ec-sc)*ratio>>16); r = sc>>24; g = (sc&0xff0000)>>16; b = (sc&0xff00)>>8; a = sc&0xff; cairo_pattern_add_color_stop_rgba(pat, (double)sr/0xff, (double)r/0xff, (double)g/0xff, (double)b/0xff, (double)a/0xff); } cairo_matrix_invert(&mx); cairo_pattern_set_matrix(pat, &mx); cairo_set_source(render->cr, pat); bits_finish(&bits); } break; case 0x40: case 0x41: case 0x42: case 0x43: { fad_object_t* fo = NULL; bits_buffer(&bits, ptr); fo = dict->get(dict, bits_get_u16(&bits)); if(fo && fo->get_image) { s32_t w, h; void* image = fo->get_image(fo, &w, &h); if(pat != NULL) cairo_pattern_destroy(pat); if(ips != NULL) cairo_surface_destroy(ips); if(image) { _calc_matrix_by_ratio(&bits, &mx, ratio); mx.xx = mx.xx/20.00; mx.yy = mx.yy/20.00; ips = cairo_image_surface_create_for_data(image, CAIRO_FORMAT_ARGB32, w, h, w<<2); pat = cairo_pattern_create_for_surface(ips); if(type == 0x40 || type == 0x42) cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT); else cairo_pattern_set_extend(pat, CAIRO_EXTEND_NONE); cairo_matrix_invert(&mx); cairo_pattern_set_matrix(pat, &mx); cairo_set_source(render->cr, pat); } } } break; default: FAD_ERROR("morph.shape fill style error\n"); break; } bits_finish(&bits); }}static void _morph_line_style_array_decode(line_style_array_t* mlsa, bits_t* bits) { mlsa->count = bits_get_u8(bits); if(mlsa->count == 0xFF) mlsa->count = bits_get_u16(bits); mlsa->array = (u8_t* )bits_tell(bits); if(mlsa->count > 0) bits_seek_nbytes(bits, mlsa->count*12);}static void _morph_fill_style_array_decode(fill_style_array_t* mfsa, bits_t* bits) { u16_t idx = 0; u8_t style_flag; mfsa->count = bits_get_u8(bits); if(mfsa->count == 0xFF) mfsa->count = bits_get_u16(bits); if(mfsa->count > 0) { mfsa->array = calloc(mfsa->count, sizeof(u8_t* )); do { mfsa->array[idx] = (u8_t* )bits_tell(bits); switch(style_flag = bits_get_u8(bits)) { case 0x00: bits_seek_nbytes(bits, 8); break; case 0x10: case 0x12: bits_get_matrix(bits, NULL); bits_get_matrix(bits, NULL); bits_seek_nbytes(bits, 10*bits_get_u8(bits)); break; case 0x40: case 0x41: case 0x42: case 0x43: bits_seek_nbytes(bits, 2); bits_get_matrix(bits, NULL); bits_get_matrix(bits, NULL); break; } } while(++idx < mfsa->count); }}static void _morph_shape_record_render_node_list(morph_sr_node_list_t *mnl, fad_render_t *render, u16_t ratio) { morph_sr_node_t *hdr = NULL; s32_t x, y;#define RATIO(val) (((val*ratio)+0x8000)>>16) hdr = mnl->header; if(hdr == NULL) return; x = hdr->sx0+RATIO(hdr->ox0); y = hdr->sy0+RATIO(hdr->oy0);#ifdef LIBFAD_DO_RENDER cairo_move_to(render->cr, x/20.00, y/20.00); FAD_ERROR("move to(%f, %f)\n", x/20.00, y/20.00);#endif hdr = hdr->next; while(hdr != NULL) { if(hdr->type == FAD_SRT_LPT) { x = hdr->sx0+RATIO(hdr->ox0); y = hdr->sy0+RATIO(hdr->oy0);#ifdef LIBFAD_DO_RENDER cairo_line_to(render->cr, x/20.00, y/20.00); FAD_ERROR("line to(%f, %f)\n", x/20.00, y/20.00);#endif } else { s32_t x0, y0, x1, y1;#ifdef LIBFAD_DO_RENDER x0 = hdr->sx1+RATIO(hdr->ox1); y0 = hdr->sy1+RATIO(hdr->oy1); x1 = hdr->sx0+RATIO(hdr->ox0); y1 = hdr->sy0+RATIO(hdr->oy0); cairo_curve_to(render->cr, (x+((x0-x)<<1)/3)/20.00, (y+((y0-y)<<1)/3)/20.00, (x0+(x1-x0)/3)/20.00, (y0+(y1-y0)/3)/20.00, x1/20.00, y1/20.00); x = x1; y = y1;#endif } hdr = hdr->next; }}static void _morph_shape_core_do_render(fad_render_t* render, morph_shape_t *ms, dl_node_t *node) { u16_t idx, total = ms->msr.fs_num + ms->msr.ls_num+2; for(idx=1; idx<total; idx++) { morph_sr_node_list_t *mnlptr = ms->msr.array[idx]; if(mnlptr == NULL) continue; do { FAD_ERROR("render node list = %x, idx = %d\n", mnlptr, idx); _morph_shape_record_render_node_list(mnlptr, render, node->ratio); mnlptr = mnlptr->next; } while(mnlptr != ms->msr.array[idx]); if(node->flag&0x40) break;#ifdef LIBFAD_DO_RENDER if (idx <= ms->msr.fs_num) { _morph_fill_style_do_render(render, &ms->mfsa, idx, ms->msr.dict, node->ratio); cairo_fill(render->cr); } else { _morph_line_style_do_render(render, &ms->mlsa, idx-ms->mfsa.count, node->ratio); cairo_stroke(render->cr); }#endif }}static u8_t _morph_shape_do_render(fad_object_t* fo, fad_render_t* render, dl_node_t *node) { morph_shape_t* ms = (morph_shape_t* )fo; _morph_shape_core_do_render(render, ms, node); return FAD_TRUE;}static void _morph_shape_record_free(morph_shape_record_t *msr) {}static void morph_sr_node_list_destroy(morph_sr_node_list_t *nl) { morph_sr_node_t *ptr = NULL, *tmp = NULL; for(ptr = nl->header; ptr != NULL; ) { tmp = ptr; ptr = ptr->next; free(tmp); tmp = NULL; }}static void _morph_shape_do_free(fad_object_t* fo) { morph_shape_t* ms = (morph_shape_t* )fo; u16_t idx, total = 0; if(ms != NULL) { if(ms->mfsa.count > 0) free(ms->mfsa.array); total = ms->msr.fs_num + 1 + ms->msr.ls_num + 1; for(idx=0; idx<total; idx++) { if(ms->msr.array[idx]) { morph_sr_node_list_destroy(ms->msr.array[idx]); free(ms->msr.array[idx]); ms->msr.array[idx] = NULL; } } }}static s32_t _morph_shape_record_init(morph_shape_record_t *msr, u16_t fs_num, u16_t ls_num) { msr->fs_num = fs_num; msr->ls_num = ls_num; msr->array = (morph_sr_node_list_t **)calloc(fs_num+1+ls_num+1, sizeof(morph_sr_node_list_t*)); if(msr->array) { u16_t idx = 0; for(; idx<fs_num+1+ls_num+1; idx++) { msr->array[idx] = NULL; } return 0; } return -1;}morph_sr_node_t* morph_sr_node_copy(morph_sr_node_t *msn) { morph_sr_node_t *new = NULL; new = calloc(1, sizeof(morph_sr_node_t)); new->type = msn->type; new->sx0 = msn->sx0; new->sx1 = msn->sx1; new->sy0 = msn->sy0; new->sy1 = msn->sy1; new->ox0 = msn->ox0; new->ox1 = msn->ox1; new->oy0 = msn->oy0; new->oy1 = msn->oy1; return new;}morph_sr_node_t* morph_sr_node_lpt_new(s32_t sx, s32_t sy, s32_t ex, s32_t ey) { morph_sr_node_t *msn = NULL; msn = calloc(1, sizeof(morph_sr_node_t)); msn->sx0 = sx; msn->sy0 = sy; msn->ox0 = ex-sx; msn->oy0 = ey-sy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -