📄 swf_parse.c
字号:
pts[ptj] = path->pts[pti]; pts[ptj+1] = path->pts[pti-1]; pti-=2; ptj+=2; break; case 1: assert(ptj<=path->nbPts-1); pts[ptj] = path->pts[pti]; pti--; ptj++; break; case 0: assert(ptj<=path->nbPts-1); pts[ptj] = path->pts[pti]; pti--; ptj++; break; } j++; } free(path->pts); path->pts = pts; free(path->types); path->types = types;}void swf_free_shape_rec(SWFShapeRec *ptr){ if (ptr->grad_col) free(ptr->grad_col); if (ptr->grad_ratio) free(ptr->grad_ratio); if (ptr->path) { if (ptr->path->pts) free(ptr->path->pts); if (ptr->path->types) free(ptr->path->types); free(ptr->path); } free(ptr);}void swf_free_rec_list(GF_List *recs){ while (gf_list_count(recs)) { SWFShapeRec *tmp = (SWFShapeRec *)gf_list_get(recs, 0); gf_list_rem(recs, 0); swf_free_shape_rec(tmp); } gf_list_del(recs);}void swf_append_path(SWFPath *a, SWFPath *b){ if (b->nbType<=1) return; a->pts = (SFVec2f*)realloc(a->pts, sizeof(SFVec2f) * (a->nbPts + b->nbPts)); memcpy(&a->pts[a->nbPts], b->pts, sizeof(SFVec2f)*b->nbPts); a->nbPts += b->nbPts; a->types = (u32*)realloc(a->types, sizeof(u32)*(a->nbType+ b->nbType)); memcpy(&a->types[a->nbType], b->types, sizeof(u32)*b->nbType); a->nbType += b->nbType;}void swf_path_add_type(SWFPath *path, u32 val){ path->types = (u32*)realloc(path->types, sizeof(u32) * (path->nbType + 1)); path->types[path->nbType] = val; path->nbType++;}void swf_resort_path(SWFPath *a, SWFReader *read){ u32 idx, i, j; GF_List *paths; SWFPath *sorted, *p, *np; if (!a->nbType) return; paths = gf_list_new(); GF_SAFEALLOC(sorted, SWFPath); swf_path_realloc_pts(sorted, 1); sorted->pts[sorted->nbPts] = a->pts[0]; sorted->nbPts++; swf_path_add_type(sorted, 0); gf_list_add(paths, sorted); /*1- split all paths*/ idx = 1; for (i=1; i<a->nbType; i++) { switch (a->types[i]) { case 2: swf_path_realloc_pts(sorted, 2); sorted->pts[sorted->nbPts] = a->pts[idx]; sorted->pts[sorted->nbPts+1] = a->pts[idx+1]; sorted->nbPts+=2; swf_path_add_type(sorted, 2); idx += 2; break; case 1: swf_path_realloc_pts(sorted, 1); sorted->pts[sorted->nbPts] = a->pts[idx]; sorted->nbPts+=1; swf_path_add_type(sorted, 1); idx += 1; break; case 0: GF_SAFEALLOC(sorted , SWFPath); swf_path_realloc_pts(sorted, 1); sorted->pts[sorted->nbPts] = a->pts[idx]; sorted->nbPts++; swf_path_add_type(sorted, 0); gf_list_add(paths, sorted); idx += 1; break; } }restart: for (i=0; i<gf_list_count(paths); i++) { p = (SWFPath*)gf_list_get(paths, i); j=i+1; for (j=i+1; j < gf_list_count(paths); j++) { np = (SWFPath*)gf_list_get(paths, j); /*check if any next subpath ends at the same place we're starting*/ if ((np->pts[np->nbPts-1].x == p->pts[0].x) && (np->pts[np->nbPts-1].y == p->pts[0].y)) { u32 k; idx = 1; for (k=1; k<p->nbType; k++) { switch (p->types[k]) { case 2: swf_path_realloc_pts(np, 2); np->pts[np->nbPts] = p->pts[idx]; np->pts[np->nbPts+1] = p->pts[idx+1]; np->nbPts+=2; swf_path_add_type(np, 2); idx += 2; break; case 1: swf_path_realloc_pts(np, 1); np->pts[np->nbPts] = p->pts[idx]; np->nbPts+=1; swf_path_add_type(np, 1); idx += 1; break; default: assert(0); break; } } free(p->pts); free(p->types); free(p); gf_list_rem(paths, i); goto restart; } /*check if any next subpath starts at the same place we're ending*/ else if ((p->pts[p->nbPts-1].x == np->pts[0].x) && (p->pts[p->nbPts-1].y == np->pts[0].y)) { u32 k; idx = 1; for (k=1; k<np->nbType; k++) { switch (np->types[k]) { case 2: swf_path_realloc_pts(p, 2); p->pts[p->nbPts] = np->pts[idx]; p->pts[p->nbPts+1] = np->pts[idx+1]; p->nbPts+=2; swf_path_add_type(p, 2); idx += 2; break; case 1: swf_path_realloc_pts(p, 1); p->pts[p->nbPts] = np->pts[idx]; p->nbPts+=1; swf_path_add_type(p, 1); idx += 1; break; default: assert(0); break; } } free(np->pts); free(np->types); free(np); gf_list_rem(paths, j); j--; } } } /*reassemble path*/ free(a->pts); free(a->types); memset(a, 0, sizeof(SWFPath)); while (gf_list_count(paths)) { sorted = (SWFPath*)gf_list_get(paths, 0); if (read->flat_limit==0) { swf_append_path(a, sorted); } else { Bool prev_is_line_to = 0; idx = 0; for (i=0; i<sorted->nbType; i++) { switch (sorted->types[i]) { case 2: swf_path_realloc_pts(a, 2); a->pts[a->nbPts] = sorted->pts[idx]; a->pts[a->nbPts+1] = sorted->pts[idx+1]; a->nbPts+=2; swf_path_add_type(a, 2); idx += 2; prev_is_line_to = 0; break; case 1: if (prev_is_line_to) { Fixed angle; Bool flatten = 0; SFVec2f v1, v2; v1.x = a->pts[a->nbPts-1].x - a->pts[a->nbPts-2].x; v1.y = a->pts[a->nbPts-1].y - a->pts[a->nbPts-2].y; v2.x = a->pts[a->nbPts-1].x - sorted->pts[idx].x; v2.y = a->pts[a->nbPts-1].y - sorted->pts[idx].y; angle = gf_mulfix(v1.x,v2.x) + gf_mulfix(v1.y,v2.y); /*get magnitudes*/ v1.x = gf_v2d_len(&v1); v2.x = gf_v2d_len(&v2); if (!v1.x || !v2.x) flatten = 1; else { Fixed h_pi = GF_PI / 2; angle = gf_divfix(angle, gf_mulfix(v1.x, v2.x)); if (angle + FIX_EPSILON >= FIX_ONE) angle = 0; else if (angle - FIX_EPSILON <= -FIX_ONE) angle = GF_PI; else angle = gf_acos(angle); if (angle<0) angle += h_pi; angle = ABSDIFF(angle, h_pi); if (angle < read->flat_limit) flatten = 1; } if (flatten) { a->pts[a->nbPts-1] = sorted->pts[idx]; idx++; read->flatten_points++; break; } } swf_path_realloc_pts(a, 1); a->pts[a->nbPts] = sorted->pts[idx]; a->nbPts+=1; swf_path_add_type(a, 1); idx += 1; prev_is_line_to = 1; break; case 0: swf_path_realloc_pts(a, 1); a->pts[a->nbPts] = sorted->pts[idx]; a->nbPts+=1; swf_path_add_type(a, 0); idx += 1; prev_is_line_to = 0; break; } } } free(sorted->pts); free(sorted->types); free(sorted); gf_list_rem(paths, 0); } gf_list_del(paths);}/* Notes on SWF->BIFS conversion - some ideas taken from libswfdec A single fillStyle has 2 associated path, one used for left fill, one for right fill This is then a 4 step process: 1- blindly parse swf shape, and add point/lines to the proper left/right path 2- for each fillStyles, revert the right path so that it becomes a left path 3- concatenate left and right paths 4- resort all subelements of the final path, making sure moveTo introduced by the SWF coding (due to style changes) are removed. Ex: if path is A->C, B->A, C->B = moveTo(A), lineTo(C), moveTo(B), lineTo (A), moveTo(C), lineTo(B) we restort and remove unneeded moves to get A->C->B = moveTo(A), lineTo(C), lineTo(B), lineTo(A)*/GF_Node *swf_parse_shape_def(SWFReader *read, Bool has_styles, u32 revision){ u32 ID, nbBits, comType, i, count; s32 x, y; SFVec2f orig, ctrl, end; Bool flag; u32 fill0, fill1, strike; SWFRec rc; u32 bits_fill, bits_line; SWFShape shape; Bool is_empty; GF_Node *n; u32 fill_base, line_base; SWFShapeRec *sf0, *sf1, *sl; memset(&shape, 0, sizeof(SWFShape)); shape.fill_left = gf_list_new(); shape.fill_right = gf_list_new(); shape.lines = gf_list_new(); ctrl.x = ctrl.y = 0; swf_align(read); ID = 0; /*get initial styles*/ if (has_styles) { ID = swf_get_16(read); /*don't care about that...*/ swf_get_rec(read, &rc); swf_parse_styles(read, revision, &shape, &bits_fill, &bits_line); } else { bits_fill = swf_read_int(read, 4); bits_line = swf_read_int(read, 4); /*fonts are usually defined without styles*/ if ((read->tag == SWF_DEFINEFONT) || (read->tag==SWF_DEFINEFONT2)) { sf0 = swf_new_shape_rec(); gf_list_add(shape.fill_right, sf0); sf0 = swf_new_shape_rec(); gf_list_add(shape.fill_left, sf0); sf0->solid_col = 0xFF000000; sf0->type = 0; } } fill_base = line_base = 0; is_empty = 1; comType = 0; /*parse all points*/ fill0 = fill1 = strike = 0; sf0 = sf1 = sl = NULL; x = y = 0; while (1) { flag = swf_read_int(read, 1); if (!flag) { Bool new_style = swf_read_int(read, 1); Bool set_strike = swf_read_int(read, 1); Bool set_fill1 = swf_read_int(read, 1); Bool set_fill0 = swf_read_int(read, 1); Bool move_to = swf_read_int(read, 1); /*end of shape*/ if (!new_style && !set_strike && !set_fill0 && !set_fill1 && !move_to) break; is_empty = 0; if (move_to) { nbBits = swf_read_int(read, 5); x = swf_read_sint(read, nbBits); y = swf_read_sint(read, nbBits); } if (set_fill0) fill0 = fill_base + swf_read_int(read, bits_fill); if (set_fill1) fill1 = fill_base + swf_read_int(read, bits_fill); if (set_strike) strike = line_base + swf_read_int(read, bits_line); /*looks like newStyle does not append styles but define a new set - old styles can no longer be referenced*/ if (new_style) { fill_base += gf_list_count(shape.fill_left); line_base += gf_list_count(shape.lines); swf_parse_styles(read, revision, &shape, &bits_fill, &bits_line); } if (read->flags & GF_SM_SWF_NO_LINE) strike = 0; /*moveto*/ comType = 0; orig.x = FLT2FIX( x * SWF_TWIP_SCALE ); orig.y = FLT2FIX( y * SWF_TWIP_SCALE ); end = orig; sf0 = fill0 ? (SWFShapeRec*)gf_list_get(shape.fill_left, fill0 - 1) : NULL; sf1 = fill1 ? (SWFShapeRec*)gf_list_get(shape.fill_right, fill1 - 1) : NULL; sl = strike ? (SWFShapeRec*)gf_list_get(shape.lines, strike - 1) : NULL; if (move_to) { swf_path_add_com(sf0, end, ctrl, 0); swf_path_add_com(sf1, end, ctrl, 0); swf_path_add_com(sl, end, ctrl, 0); } else { if (set_fill0) swf_path_add_com(sf0, end, ctrl, 0); if (set_fill1) swf_path_add_com(sf1, end, ctrl, 0); if (set_strike) swf_path_add_com(sl, end, ctrl, 0); } } else { flag = swf_read_int(read, 1); /*quadratic curve*/ if (!flag) { nbBits = 2 + swf_read_int(read, 4); x += swf_read_sint(read, nbBits); y += swf_read_sint(read, nbBits); ctrl.x = FLT2FIX( x * SWF_TWIP_SCALE ); ctrl.y = FLT2FIX( y * SWF_TWIP_SCALE ); x += swf_read_sint(read, nbBits); y += swf_read_sint(read, nbBits); end.x = FLT2FIX( x * SWF_TWIP_SCALE ); end.y = FLT2FIX( y * SWF_TWIP_SCALE ); /*curveTo*/ comType = 2; } /*straight line*/ else { nbBits = 2 + swf_read_int(read, 4); flag = swf_read_int(read, 1); if (flag) { x += swf_read_sint(read, nbBits); y += swf_read_sint(read, nbBits); } else { flag = swf_read_int(read, 1); if (flag) { y += swf_read_sint(read, nbBits); } else { x += swf_read_sint(read, nbBits); } } /*lineTo*/ comType = 1; end.x = FLT2FIX( x * SWF_TWIP_SCALE ); end.y = FLT2FIX( y * SWF_TWIP_SCALE ); } swf_path_add_com(sf0, end, ctrl, comType); swf_path_add_com(sf1, end, ctrl, comType); swf_path_add_com(sl, end, ctrl, comType); } } if (is_empty) { swf_free_rec_list(shape.fill_left); swf_free_rec_list(shape.fill_right); swf_free_rec_list(shape.lines); return NULL; } swf_align(read); count = gf_list_count(shape.fill_left); for (i=0; i<count; i++) { sf0 = (SWFShapeRec*)gf_list_get(shape.fill_left, i); sf1 = (SWFShapeRec*)gf_list_get(shape.fill_right, i); /*reverse right path*/ swf_referse_path(sf1->path); /*concatenate with left path*/ swf_append_path(sf0->path, sf1->path); /*resort all path curves*/ swf_resort_path(sf0->path, read); } /*remove dummy fill_left*/ for (i=0; i<gf_list_count(shape.fill_left); i++) { sf0 = (SWFShapeRec*)gf_list_get(shape.fill_left, i); if (sf0->path->nbType<=1) { gf_list_rem(shape.fill_left, i); swf_free_shape_rec(sf0); i--; } } /*remove dummy lines*/ for (i=0; i<gf_list_count(shape.lines); i++) { sl = (SWFShapeRec*)gf_list_get(shape.lines, i); if (sl->path->nbType<1) { gf_list_rem(shape.lines, i); swf_free_shape_rec(sl); i--; } else { swf_resort_path(sl->path, read); } } /*now translate a flash shape record into BIFS*/ shape.ID = ID; n = SWFShapeToBIFS(read, &shape); /*delete shape*/ swf_free_rec_list(shape.fill_left); swf_free_rec_list(shape.fill_right);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -