📄 swf_parse.c
字号:
/*flush AU*/ read->current_frame ++; ts = read->current_frame * 100; is_rap = read->current_sprite_id ? 1 : 0; /*if we use ctrl stream, same thing*/ read->bifs_au = gf_sm_stream_au_new(read->bifs_es, ts, 0, /*all frames in sprites are RAP (define is not allowed in sprites) if we use a ctrl stream, all AUs are RAP (defines are placed in a static dictionary) */ (read->current_sprite_id || (read->flags & GF_SM_SWF_SPLIT_TIMELINE)) ? 1 : 0); return GF_OK;}GF_Err swf_def_font(SWFReader *read, u32 revision){ u32 i, count; GF_Err e; GF_Node *glyph; SWFFont *ft; u32 *offset_table; u32 start; GF_SAFEALLOC(ft, SWFFont); ft->glyphs = gf_list_new(); ft->fontID = swf_get_16(read); e = GF_OK; if (revision==0) { u32 count; start = swf_get_file_pos(read); count = swf_get_16(read); ft->nbGlyphs = count / 2; offset_table = (u32*)malloc(sizeof(u32) * ft->nbGlyphs); offset_table[0] = 0; for (i=1; i<ft->nbGlyphs; i++) offset_table[i] = swf_get_16(read); for (i=0; i<ft->nbGlyphs; i++) { swf_align(read); e = swf_seek_file_to(read, start + offset_table[i]); if (e) break; while (1) { glyph = swf_parse_shape_def(read, 0, 0); /*not a mistake, that's likelly space char*/ if (!glyph) glyph = SWF_NewNode(read, TAG_MPEG4_Shape); gf_list_add(ft->glyphs, glyph); gf_node_register(glyph, NULL); break; } } free(offset_table); if (e) return e; } else if (revision==1) { SWFRec rc; Bool wide_offset, wide_codes; ft->has_layout = swf_read_int(read, 1); ft->has_shiftJIS = swf_read_int(read, 1); ft->is_unicode = swf_read_int(read, 1); ft->is_ansi = swf_read_int(read, 1); wide_offset = swf_read_int(read, 1); wide_codes = swf_read_int(read, 1); ft->is_italic = swf_read_int(read, 1); ft->is_bold = swf_read_int(read, 1); swf_read_int(read, 8); count = swf_read_int(read, 8); ft->fontName = (char*)malloc(sizeof(u8)*count+1); ft->fontName[count] = 0; for (i=0; i<count; i++) ft->fontName[i] = swf_read_int(read, 8); ft->nbGlyphs = swf_get_16(read); start = swf_get_file_pos(read); if (ft->nbGlyphs) { u32 code_offset, checkpos; offset_table = (u32*)malloc(sizeof(u32) * ft->nbGlyphs); for (i=0; i<ft->nbGlyphs; i++) { if (wide_offset) offset_table[i] = swf_get_32(read); else offset_table[i] = swf_get_16(read); } if (wide_offset) { code_offset = swf_get_32(read); } else { code_offset = swf_get_16(read); } for (i=0; i<ft->nbGlyphs; i++) { swf_align(read); e = swf_seek_file_to(read, start + offset_table[i]); if (e) break; while (1) { glyph = swf_parse_shape_def(read, 0, 0); if (!glyph) continue; gf_list_add(ft->glyphs, glyph); gf_node_register(glyph, NULL); break; } } free(offset_table); if (e) return e; checkpos = swf_get_file_pos(read); if (checkpos != start + code_offset) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[SWF Parsing] bad code offset in font\n")); return GF_NON_COMPLIANT_BITSTREAM; } ft->glyph_codes = (u16*)malloc(sizeof(u16) * ft->nbGlyphs); for (i=0; i<ft->nbGlyphs; i++) { if (wide_codes) ft->glyph_codes[i] = swf_get_16(read); else ft->glyph_codes[i] = swf_read_int(read, 8); } } if (ft->has_layout) { ft->ascent = swf_get_s16(read); ft->descent = swf_get_s16(read); ft->leading = swf_get_s16(read); if (ft->nbGlyphs) { ft->glyph_adv = (s16*)malloc(sizeof(s16) * ft->nbGlyphs); for (i=0; i<ft->nbGlyphs; i++) ft->glyph_adv[i] = swf_get_s16(read); for (i=0; i<ft->nbGlyphs; i++) swf_get_rec(read, &rc); } /*kerning info*/ count = swf_get_16(read); for (i=0; i<count; i++) { if (wide_codes) { swf_get_16(read); swf_get_16(read); } else { swf_read_int(read, 8); swf_read_int(read, 8); } swf_get_s16(read); } } } gf_list_add(read->fonts, ft); return GF_OK;}GF_Err swf_def_font_info(SWFReader *read){ SWFFont *ft; Bool wide_chars; u32 i, count; i = swf_get_16(read); ft = SWF_FindFont(read, i); if (!ft) { swf_report(read, GF_BAD_PARAM, "Cannot locate font ID %d", i); return GF_BAD_PARAM; } /*overwrite font info*/ if (ft->fontName) free(ft->fontName); count = swf_read_int(read, 8); ft->fontName = (char*)malloc(sizeof(char) * (count+1)); ft->fontName[count] = 0; for (i=0; i<count; i++) ft->fontName[i] = swf_read_int(read, 8); swf_read_int(read, 2); ft->is_unicode = swf_read_int(read, 1); ft->has_shiftJIS = swf_read_int(read, 1); ft->is_ansi = swf_read_int(read, 1); ft->is_italic = swf_read_int(read, 1); ft->is_bold = swf_read_int(read, 1); /*TODO - this should be remapped to a font data stream, we currently only assume the glyph code table is the same as the original font file...*/ wide_chars = swf_read_int(read, 1); if (ft->glyph_codes) free(ft->glyph_codes); ft->glyph_codes = (u16*)malloc(sizeof(u16) * ft->nbGlyphs); for (i=0; i<ft->nbGlyphs; i++) { if (wide_chars) ft->glyph_codes[i] = swf_get_16(read); else ft->glyph_codes[i] = swf_read_int(read, 8); } return GF_OK;}GF_Err swf_def_text(SWFReader *read, u32 revision){ SWFRec rc; SWFText txt; Bool flag; GF_Node *n; u32 ID, nbits_adv, nbits_glyph, i, col, fontID, count; Fixed offX, offY, fontHeight; GF_Err e; ID = swf_get_16(read); swf_get_rec(read, &rc); swf_get_matrix(read, &txt.mat, 0); txt.text = gf_list_new(); swf_align(read); nbits_glyph = swf_read_int(read, 8); nbits_adv = swf_read_int(read, 8); fontID = 0; offX = offY = fontHeight = 0; col = 0xFF000000; e = GF_OK; while (1) { flag = swf_read_int(read, 1); /*regular glyph record*/ if (!flag) { SWFGlyphRec *gr; count = swf_read_int(read, 7); if (!count) break; if (!fontID) { e = GF_BAD_PARAM; swf_report(read, GF_BAD_PARAM, "Defining text %d without assigning font", fontID); break; } GF_SAFEALLOC(gr, SWFGlyphRec); gf_list_add(txt.text, gr); gr->fontID = fontID; gr->fontHeight = fontHeight; gr->col = col; gr->orig_x = offX; gr->orig_y = offY; gr->nbGlyphs = count; gr->indexes = (u32*)malloc(sizeof(u32) * gr->nbGlyphs); gr->dx = (Fixed*)malloc(sizeof(Fixed) * gr->nbGlyphs); for (i=0; i<gr->nbGlyphs; i++) { gr->indexes[i] = swf_read_int(read, nbits_glyph); gr->dx[i] = FLT2FIX( swf_read_int(read, nbits_adv) * SWF_TWIP_SCALE ); } swf_align(read); } /*text state change*/ else { Bool has_font, has_col, has_y_off, has_x_off; /*reserved*/ swf_read_int(read, 3); has_font = swf_read_int(read, 1); has_col = swf_read_int(read, 1); has_y_off = swf_read_int(read, 1); has_x_off = swf_read_int(read, 1); /*end of rec*/ if (!has_font && !has_col && !has_y_off && !has_x_off) break; if (has_font) fontID = swf_get_16(read); if (has_col) { if (revision==0) col = swf_get_color(read); else col = swf_get_argb(read); } /*openSWF spec seems to have wrong order here*/ if (has_x_off) offX = FLT2FIX( swf_get_s16(read) * SWF_TWIP_SCALE ); if (has_y_off) offY = FLT2FIX( swf_get_s16(read) * SWF_TWIP_SCALE ); if (has_font) fontHeight = FLT2FIX( swf_get_16(read) * SWF_TEXT_SCALE ); } } if (e) goto exit; if (! (read->flags & GF_SM_SWF_NO_TEXT) ) { n = SWFTextToBIFS(read, &txt); if (n) { char szDEF[1024]; sprintf(szDEF, "Text%d", ID); read->load->ctx->max_node_id++; ID = read->load->ctx->max_node_id; gf_node_set_id(n, ID, szDEF); SWF_InsertNode(read, n); } }exit: while (gf_list_count(txt.text)) { SWFGlyphRec *gr = (SWFGlyphRec *)gf_list_get(txt.text, 0); gf_list_rem(txt.text, 0); if (gr->indexes) free(gr->indexes); if (gr->dx) free(gr->dx); free(gr); } gf_list_del(txt.text); return e;}GF_Err swf_init_od(SWFReader *read){ GF_ESD *esd; if (read->od_es) return GF_OK; read->od_es = gf_sm_stream_new(read->load->ctx, 2, 1, 1); if (!read->od_es) return GF_OUT_OF_MEM; if (!read->load->ctx->root_od) { GF_BIFSConfig *bc; read->load->ctx->root_od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG); /*add BIFS stream*/ esd = (GF_ESD *) gf_odf_desc_esd_new(0); if (!esd) return GF_OUT_OF_MEM; esd->decoderConfig->streamType = GF_STREAM_SCENE; esd->decoderConfig->objectTypeIndication = 1; esd->slConfig->timestampResolution = read->bifs_es->timeScale; esd->ESID = 1; gf_list_add(read->load->ctx->root_od->ESDescriptors, esd); read->load->ctx->root_od->objectDescriptorID = 1; gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); bc = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); bc->pixelMetrics = 1; bc->pixelWidth = (u16) read->width; bc->pixelHeight = (u16) read->height; esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) bc; } if (!read->load->ctx->root_od) return GF_OUT_OF_MEM; esd = (GF_ESD *) gf_odf_desc_esd_new(0); if (!esd) return GF_OUT_OF_MEM; esd->decoderConfig->streamType = GF_STREAM_OD; esd->decoderConfig->objectTypeIndication = 1; esd->slConfig->timestampResolution = read->od_es->timeScale = read->bifs_es->timeScale; esd->ESID = 2; esd->OCRESID = 1; gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = NULL; return gf_list_add(read->load->ctx->root_od->ESDescriptors, esd);}GF_Err swf_insert_od(SWFReader *read, u32 at_time, GF_ObjectDescriptor *od){ u32 i; GF_ODUpdate *com; read->od_au = gf_sm_stream_au_new(read->od_es, at_time, 0, 1); if (!read->od_au) return GF_OUT_OF_MEM; i=0; while ((com = (GF_ODUpdate *)gf_list_enum(read->od_au->commands, &i))) { if (com->tag == GF_ODF_OD_UPDATE_TAG) { gf_list_add(com->objectDescriptors, od); return GF_OK; } } com = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG); gf_list_add(com->objectDescriptors, od); return gf_list_add(read->od_au->commands, com);}void swf_delete_sound_stream(SWFReader *read){ if (!read->sound_stream) return; if (read->sound_stream->output) fclose(read->sound_stream->output); if (read->sound_stream->szFileName) free(read->sound_stream->szFileName); free(read->sound_stream); read->sound_stream = NULL;}GF_Err swf_def_sprite(SWFReader *read){ GF_Err SWF_ParseTag(SWFReader *read); GF_Err e; GF_ObjectDescriptor *od; GF_ESD *esd; u32 spriteID, ID; u32 frame_count; Bool prev_sprite; u32 prev_frame; GF_Node *n, *par; GF_FieldInfo info; char szDEF[100]; SWFSound *snd; GF_StreamContext *prev_sc; GF_AUContext *prev_au; spriteID = swf_get_16(read); frame_count = swf_get_16(read); /*init OD*/ e = swf_init_od(read); if (e) return e; /*create animationStream object*/ od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); if (!od) return GF_OUT_OF_MEM; od->objectDescriptorID = swf_get_od_id(read); esd = (GF_ESD *) gf_odf_desc_esd_new(0); if (!esd) return GF_OUT_OF_MEM; esd->ESID = swf_get_es_id(read); /*sprite runs on its own timeline*/ esd->OCRESID = esd->ESID; /*always depends on main scene*/ esd->dependsOnESID = 1; esd->decoderConfig->streamType = GF_STREAM_SCENE; esd->decoderConfig->objectTypeIndication = 1; esd->slConfig->timestampResolution = read->bifs_es->timeScale; gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo); esd->decoderConfig->decoderSpecificInfo = NULL; gf_list_add(od->ESDescriptors, esd); /*by default insert OD at begining*/ e = swf_insert_od(read, 0, od); if (e) { gf_odf_desc_del((GF_Descriptor *) od); return e; } /*create AS for sprite - all AS are created in initial scene replace*/ n = SWF_NewNode(read, TAG_MPEG4_AnimationStream); sprintf(szDEF, "Sprite%d_ctrl", spriteID); read->load->ctx->max_node_id++; ID = read->load->ctx->max_node_id; gf_node_set_id(n, ID, szDEF); gf_node_insert_child(read->root, n, 0); gf_node_register(n, read->root); /*assign URL*/ gf_node_get_field_by_name(n, "url", &info); gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); ((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; /*inactive by default (until inserted)*/ ((M_AnimationStream *)n)->startTime = -1; /*loop by default - not 100% sure from SWF spec, I believe a sprite loops until removed from DList*/ ((M_AnimationStream *)n)->loop = 0; /*create sprite grouping node*/ n = SWF_NewNode(read, TAG_MPEG4_Group); sprintf(szDEF, "Sprite%d_root", spriteID); read->load->ctx->max_node_id++; ID = read->load->ctx->max_node_id; gf_node_set_id(n, ID, szDEF); par = gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY"); assert(par); gf_node_list_add_child(&((M_Switch *)par)->choice, n); gf_node_register(n, par); par = gf_sg_find_node_by_name(read->load->scene_graph, "EMPTYSHAPE"); gf_node_insert_child(n, par, -1); gf_node_register(par, n); /*store BIFS context*/ prev_frame = read->current_frame; prev_sc = read->bifs_es; prev_au = read->bifs_au; prev_sprite = read->current_sprite_id; /*create new BIFS stream*/ read->bifs_es = gf_sm_stream_new(read->load->ctx, esd->ESID, GF_STREAM_SCENE, 1); read->bifs_es->timeScale = prev_sc->timeScale; read->current_frame = 0; /*create first AU*/ read->bifs_au = gf_sm_stream_au_new(read->bifs_es, 0, 0, 1); read->current_sprite_id = spriteID; /*store soundStream*/ snd = read->sound_stream; read->sound_stream = NULL; /*and parse*/ while (1) { e = SWF_ParseTag(read); if (e<0) return e; /*done with sprite*/ if (read->tag==SWF_END) break; } /*restore BIFS context*/ read->current_frame = prev_frame; read->bifs_es = prev_sc; read->bifs_au = prev_au; read->current_sprite_id = prev_sprite; /*close sprite soundStream*/ swf_delete_sound_stream(read); /*restore sound stream*/ read->sound_stream = snd; read->tag = SWF_DEFINESPRITE; return GF_OK;}GF_Err swf_def_sound(SWFReader *read){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -