📄 loader_svg_da.c
字号:
free(iri->string); iri->string = NULL; gf_list_rem(parser->defered_hrefs, i); i--; count--; } } /*check unresolved listeners */ count = gf_list_count(parser->defered_listeners); for (i=0; i<count; i++) { GF_FieldInfo info; GF_Node *par; SVG_Element *listener = (SVG_Element *)gf_list_get(parser->defered_listeners, i); par = NULL; if (gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_observer, 0, 0, &info) == GF_OK) { XMLRI *observer = info.far_ptr; if (observer->type == XMLRI_ELEMENTID) { if (!observer->target && observer->string && !strcmp(observer->string, nodeID) ) { observer->target = gf_sg_find_node_by_name(sg, (char*) nodeID); } } if (observer->type == XMLRI_ELEMENTID) par = observer->target; if (!par) continue; } if (gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_listener_target, 0, 0, &info) == GF_OK) { XMLRI *target = info.far_ptr; if (target->type == XMLRI_ELEMENTID) { if (!target->target) continue; else { if (!par) par = (GF_Node*)target->target; } } } assert(par); gf_dom_listener_add((GF_Node *)par, (GF_Node *) listener); gf_list_rem(parser->defered_listeners, i); i--; count--; } /*check unresolved anims*/ count = gf_list_count(parser->defered_animations); for (i=0; i<count; i++) { SVG_DeferedAnimation *anim = (SVG_DeferedAnimation *)gf_list_get(parser->defered_animations, i); /*resolve it - we don't check the name since it may be used in SMIL times, which we don't track at anim level*/ if (svg_parse_animation(parser, sg, anim, nodeID)) { svg_delete_defered_anim(anim, parser->defered_animations); i--; count--; } }}static void svg_init_root_element(GF_SVG_Parser *parser, SVG_Element *root_svg){ GF_FieldInfo width_info, height_info; u32 svg_w, svg_h; svg_w = svg_h = 0; if (!gf_svg_get_attribute_by_tag((GF_Node *)root_svg, TAG_SVG_ATT_width, 0, 0, &width_info) && !gf_svg_get_attribute_by_tag((GF_Node *)root_svg, TAG_SVG_ATT_height, 0, 0, &height_info)) { SVG_Length * w = width_info.far_ptr; SVG_Length * h = height_info.far_ptr; if (w->type == SVG_NUMBER_VALUE) svg_w = FIX2INT(w->value); if (h->type == SVG_NUMBER_VALUE) svg_h = FIX2INT(h->value); gf_sg_set_scene_size_info(parser->load->scene_graph, svg_w, svg_h, 1); if (parser->load->ctx) { parser->load->ctx->scene_width = svg_w; parser->load->ctx->scene_height = svg_h; } } if (parser->load->type == GF_SM_LOAD_XSR) { assert(parser->command); assert(parser->command->tag == GF_SG_LSR_NEW_SCENE); parser->command->node = (GF_Node *)root_svg; } gf_sg_set_root_node(parser->load->scene_graph, (GF_Node *)root_svg); parser->has_root = 1;}static SVG_Element *svg_parse_element(GF_SVG_Parser *parser, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes, SVG_NodeStack *parent){ GF_FieldInfo info; u32 tag, i, count; Bool needs_init, has_id; SVG_Element *elt = NULL; const char *node_name = NULL; const char *ev_event, *ev_observer; SVG_DeferedAnimation *anim = NULL; /* Translates the node type (called name) from a String into a unique numeric identifier in GPAC */ tag = gf_svg_get_element_tag(name); if (tag == TAG_UndefinedNode) { //svg_report(parser, GF_OK, "Unknown element %s - skipping\n", name); GF_LOG(GF_LOG_DEBUG, GF_LOG_PARSER, ("[SVG Parsing] line %d - Unknown element %s - skipping\n", gf_xml_sax_get_line(parser->sax_parser), name)); return NULL; } has_id = 0; count = gf_list_count(parser->peeked_nodes); if (count) { char *ID = NULL; for (i=0; i<nb_attributes; i++) { GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i]; if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) { ID = att->value; break; } } if (ID) { for (i=0; i<count;i++) { GF_Node *n = gf_list_get(parser->peeked_nodes, i); const char *n_id = gf_node_get_name(n); if (n_id && !strcmp(n_id, ID)) { gf_list_rem(parser->peeked_nodes, i); has_id = 1; elt = (SVG_Element*)n; break; } } } } if (!has_id) { /* Creates a node in the current scene graph */ elt = (SVG_Element*)gf_node_new(parser->load->scene_graph, tag); if (!elt) { parser->last_error = GF_SG_UNKNOWN_NODE; return NULL; } /*set root BEFORE processing attributes in order to have it setup for script init*/ if ((tag == TAG_SVG_svg) && !parser->has_root) svg_init_root_element(parser, elt); } gf_node_register((GF_Node *)elt, (parent ? (GF_Node *)parent->node : NULL)); if (parent && elt) gf_node_list_add_child_last( & parent->node->children, (GF_Node*)elt, & parent->last_child); needs_init = 1; if (gf_svg_is_animation_tag(tag)) { GF_SAFEALLOC(anim, SVG_DeferedAnimation); /*default anim target is parent node*/ anim->animation_elt = elt; if (!parent) { if (parser->command) { anim->target = anim->anim_parent = (SVG_Element*) parser->command->node; } } else { anim->target = anim->anim_parent = parent->node; } } else if (tag == TAG_SVG_video || tag == TAG_SVG_audio || tag == TAG_SVG_animation) { /* warning: we use the SVG_DeferedAnimation structure for some timing nodes which are not animations, but we put the parse stage at 1 (timing) see svg_parse_animation. */ GF_SAFEALLOC(anim, SVG_DeferedAnimation); /*default anim target is parent node*/ anim->animation_elt = elt; if (!parent) { if (parser->command) { anim->anim_parent = (SVG_Element*) parser->command->node; } } else { anim->anim_parent = parent->node; } anim->resolve_stage = 1; } else if ((tag == TAG_SVG_script) || (tag==TAG_SVG_handler)) { needs_init = 0; } ev_event = ev_observer = NULL; /*parse all att*/ for (i=0; i<nb_attributes; i++) { GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i]; if (!att->value || !strlen(att->value)) continue; if (!stricmp(att->name, "style")) { gf_svg_parse_style((GF_Node *)elt, att->value); } else if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) { if (!has_id) gf_svg_parse_element_id((GF_Node *)elt, att->value, parser->command_depth ? 1 : 0); node_name = att->value; } else if (anim && !stricmp(att->name, "to")) { anim->to = strdup(att->value); } else if (anim && !stricmp(att->name, "from")) { anim->from = strdup(att->value); } else if (anim && !stricmp(att->name, "by")) { anim->by = strdup(att->value); } else if (anim && !stricmp(att->name, "values")) { anim->values = strdup(att->value); } else if (anim && (tag == TAG_SVG_animateTransform) && !stricmp(att->name, "type")) { anim->type = strdup(att->value); } else if (!stricmp(att->name, "xlink:href") ) { if (gf_svg_is_animation_tag(tag)) { assert(anim); anim->target_id = strdup(att->value); /*may be NULL*/ anim->target = (SVG_Element *) gf_sg_find_node_by_name(parser->load->scene_graph, anim->target_id + 1); } else { GF_FieldInfo info; XMLRI *iri = NULL; if (gf_node_get_field_by_name((GF_Node *)elt, att->name, &info)==GF_OK) { gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0); iri = info.far_ptr; } else { svg_report(parser, GF_OK, "Skipping %s", att->name); } if ((tag==TAG_SVG_image) || (tag==TAG_SVG_video) || (tag==TAG_SVG_audio)) { svg_process_media_href(parser, iri); } svg_post_process_href(parser, iri); } } else if (!stricmp(att->name, "ev:event") && tag == TAG_SVG_handler) { ev_event = att->value; } else if (!stricmp(att->name, "ev:observer") && tag == TAG_SVG_handler) { ev_observer = att->value; } /*laser specific stuff*/ else if (!stricmp(att->name, "lsr:scale") ) { if (gf_svg_get_attribute_by_tag((GF_Node *)elt, TAG_SVG_ATT_transform, 1, 1, &info)==GF_OK) { SVG_Point pt; SVG_Transform *mat = info.far_ptr; svg_parse_point(&pt, att->value); gf_mx2d_add_scale(&mat->mat, pt.x, pt.y); } } else if (!stricmp(att->name, "lsr:translation") ) { if (gf_svg_get_attribute_by_tag((GF_Node *)elt, TAG_SVG_ATT_transform, 1, 1, &info)==GF_OK) { SVG_Point pt; SVG_Transform *mat = info.far_ptr; svg_parse_point(&pt, att->value); gf_mx2d_add_translation(&mat->mat, pt.x, pt.y); } } else if (!strncmp(att->name, "xmlns", 5)) { } else if (gf_node_get_field_by_name((GF_Node *)elt, att->name, &info)==GF_OK) { gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0); switch (info.fieldIndex) { case TAG_SVG_ATT_syncMaster: case TAG_SVG_ATT_focusHighlight: case TAG_SVG_ATT_initialVisibility: case TAG_SVG_ATT_fullscreen: case TAG_SVG_ATT_requiredFonts: /*switch to v2*/ svg_lsr_set_v2(parser); break; } } else if (!strncmp(att->name, "on", 2)) { u32 evtType = gf_dom_event_type_by_name(att->name + 2); if (evtType != GF_EVENT_UNKNOWN) { SVG_handlerElement *handler = gf_dom_listener_build((GF_Node *) elt, evtType, 0, NULL); gf_dom_add_text_node((GF_Node *)handler, strdup(att->value) ); gf_node_init((GF_Node *)handler); } else { svg_report(parser, GF_OK, "Skipping unknown event handler %s on node %s", att->name, name); } } else { svg_report(parser, GF_OK, "Skipping attribute %s on node %s", att->name, name); } } if (ev_event) { /* When the handler element specifies the event attribute, an implicit listener is defined */ GF_Node *node = (GF_Node *)elt; SVG_Element *listener; u32 type; GF_FieldInfo info; listener = (SVG_Element *) gf_node_new(node->sgprivate->scenegraph, TAG_SVG_listener); gf_node_register((GF_Node *)listener, node); gf_node_list_add_child( & ((GF_ParentNode *)node)->children, (GF_Node*) listener); /* this listener listens to the given type of event */ type = gf_dom_event_type_by_name(ev_event); gf_svg_get_attribute_by_tag(node, TAG_SVG_ATT_ev_event, 1, 0, &info); ((XMLEV_Event *)info.far_ptr)->type = type; gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_event, 1, 0, &info); ((XMLEV_Event *)info.far_ptr)->type = type; gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_handler, 1, 0, &info); ((XMLRI *)info.far_ptr)->target = node; if (ev_observer) { gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_observer, 1, 0, &info); gf_svg_parse_attribute((GF_Node *)elt, &info, (char*)ev_observer, 0); } else { /* this listener listens with the parent of the handler as the event target */ gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_listener_target, 1, 0, &info); ((XMLRI *)info.far_ptr)->target = parent->node; } if ( ((XMLRI *)info.far_ptr)->target) gf_dom_listener_add(((XMLRI *)info.far_ptr)->target, (GF_Node *) listener); else gf_list_add(parser->defered_listeners, listener); } if (anim) { if (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) { needs_init = 0; if (svg_parse_animation(parser, parser->load->scene_graph, anim, NULL)) { svg_delete_defered_anim(anim, NULL); } else { gf_list_add(parser->defered_animations, anim); } } else { svg_delete_defered_anim(anim, NULL); } } /* if the new element has an id, we try to resolve defered references */ if (node_name) { svg_resolved_refs(parser, parser->load->scene_graph, node_name); } if (needs_init) gf_node_init((GF_Node *)elt); /*register listener element*/ if ((parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) && elt && (tag==TAG_SVG_listener)) { GF_FieldInfo info; Bool post_pone = 0; SVG_Element *par = NULL; SVG_Element *listener = (SVG_Element *)elt; if (gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_observer, 0, 0, &info) == GF_OK) { XMLRI *observer = info.far_ptr; if (observer->type == XMLRI_ELEMENTID) { if (!observer->target) post_pone = 1; else par = observer->target; } } if (gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_listener_target, 0, 0, &info) == GF_OK) { XMLRI *target = info.far_ptr; if (!par && (target->type == XMLRI_ELEMENTID)) { if (!target->target) post_pone = 1; else par = target->target; } } /*check handler, create it if not specified*/ if (gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_handler, 1, 0, &info) == GF_OK) { XMLRI *handler = info.far_ptr; if (!handler->target) { if (!handler->string) handler->target = parent->node; } } /*if event is a key event, register it with root*/ if (!par && gf_svg_get_attribute_by_tag((GF_Node *)listener, TAG_SVG_ATT_event, 0, 0, &info) == GF_OK) { XMLEV_Event *ev = info.far_ptr; if (ev->type>GF_EVENT_MOUSEWHEEL) par = (SVG_Element*) listener->sgprivate->scenegraph->RootNode; } if (post_pone) { gf_list_add(parser->defered_listeners, listener); } else { if (!par) par = parent->node; gf_dom_listener_add((GF_Node *)par, (GF_Node *) listener); } } return elt;}static GF_Err lsr_parse_command(GF_SVG_Parser *parser, const GF_XMLAttribute *attributes, u32 nb_attributes){ GF_FieldInfo info; GF_Node *opNode; Bool is_replace = 0; char *atNode = NULL; char *atAtt = NULL; char *atOperandNode = NULL; char *atOperandAtt = NULL; char *atValue = NULL; GF_CommandField *field; s32 index = -1; u32 i; switch (parser->command->tag) { case GF_SG_LSR_NEW_SCENE: return GF_OK; case GF_SG_LSR_DELETE: for (i=0; i<nb_attributes; i++) { GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i]; if (!strcmp(att->name, "ref")) atNode = att->value; else if (!strcmp(att->name, "attributeName")) atAtt = att->value; else if (!strcmp(att->name, "index")) index = atoi(att->value); } if (!atNode) return svg_report(parser, GF_BAD_PARAM, "Missing node ref for command"); /*should be a XML IDREF, not an XML IRI*/ if (atNode[0]=='#') atNode++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -