/*activate all routes in the order they where triggered*/ GF_EXPORT void gf_sg_activate_routes(GF_SceneGraph *sg) { GF_Route *r; GF_Node *targ; if (!sg) return; sg->simulation_tick++; while (gf_list_count(sg->routes_to_activate)) { r = (GF_Route *)gf_list_get(sg->routes_to_activate, 0); gf_list_rem(sg->routes_to_activate, 0); if (r) { targ = r->ToNode; if (gf_sg_route_activate(r)) { #ifdef GF_SELF_REPLACE_ENABLE if (sg->graph_has_been_reset) { sg->graph_has_been_reset = 0; return; } #endif if (r->is_setup) gf_node_changed(targ, &r->ToField); } } } gf_sg_destroy_routes(sg); }
static void Node_on_remove_children(GF_Node *node) { GF_ChildNodeItem *list; GF_FieldInfo field; GF_VRMLParent *n = (GF_VRMLParent *)node; if (!n->removeChildren) return; list = n->removeChildren; while (list) { if (gf_node_list_del_child(& n->children, list->node)) { gf_node_unregister(list->node, node); } list = list->next; } gf_node_unregister_children(node, n->removeChildren); n->removeChildren = NULL; /*signal children field is modified*/ field.name = "children"; field.eventType = GF_SG_EVENT_EXPOSED_FIELD; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = 0; field.fieldIndex = 2; field.far_ptr = & n->children; gf_node_changed(node, &field); }
static void TTD_ResetDisplay(TTDPriv *priv) { gf_list_reset(priv->blink_nodes); gf_node_unregister_children((GF_Node*)priv->dlist, priv->dlist->children); priv->dlist->children = NULL; gf_node_changed((GF_Node *) priv->dlist, NULL); priv->tr_scroll = NULL; }
static void ttd_set_scroll_fraction(GF_Node *node, GF_Route *route) { Fixed frac; TTDPriv *priv = (TTDPriv *)gf_node_get_private(node); frac = priv->process_scroll->set_fraction; if (frac==FIX_ONE) priv->is_active = 0; if (!priv->tr_scroll) return; switch (priv->scroll_type - 1) { case GF_TXT_SCROLL_CREDITS: case GF_TXT_SCROLL_DOWN: priv->tr_scroll->translation.x = 0; if (priv->scroll_mode & GF_TXT_SCROLL_IN) { if (frac>priv->scroll_time) { priv->scroll_mode &= ~GF_TXT_SCROLL_IN; priv->tr_scroll->translation.y = 0; } else { priv->tr_scroll->translation.y = gf_muldiv(priv->dlist->size.y, frac, priv->scroll_time) - priv->dlist->size.y; } } else if (priv->scroll_mode & GF_TXT_SCROLL_OUT) { if (frac < FIX_ONE - priv->scroll_time) return; frac -= FIX_ONE - priv->scroll_time; if (priv->scroll_type - 1 == GF_TXT_SCROLL_DOWN) { priv->tr_scroll->translation.y = gf_muldiv(priv->dlist->size.y, frac, priv->scroll_time); } else { priv->tr_scroll->translation.y = gf_muldiv(priv->dlist->size.y, frac, priv->scroll_time); } } if (priv->scroll_type - 1 == GF_TXT_SCROLL_DOWN) priv->tr_scroll->translation.y *= -1; break; case GF_TXT_SCROLL_MARQUEE: case GF_TXT_SCROLL_RIGHT: priv->tr_scroll->translation.y = 0; if (priv->scroll_mode & GF_TXT_SCROLL_IN) { if (! (priv->scroll_mode & GF_TXT_SCROLL_OUT)) { if (frac<priv->scroll_delay) return; frac-=priv->scroll_delay; } if (frac>priv->scroll_time) { priv->scroll_mode &= ~GF_TXT_SCROLL_IN; priv->tr_scroll->translation.x = 0; } else { priv->tr_scroll->translation.x = gf_muldiv(priv->dlist->size.x, frac, priv->scroll_time) - priv->dlist->size.x; } } else if (priv->scroll_mode & GF_TXT_SCROLL_OUT) { if (frac < FIX_ONE - priv->scroll_time) return; frac -= FIX_ONE - priv->scroll_time; priv->tr_scroll->translation.x = gf_muldiv(priv->dlist->size.x, frac, priv->scroll_time); } if (priv->scroll_type - 1 == GF_TXT_SCROLL_MARQUEE) priv->tr_scroll->translation.x *= -1; break; default: break; } gf_node_changed((GF_Node *)priv->tr_scroll, NULL); }
static void SG_CheckFieldChange(GF_Node *node, GF_FieldInfo *field) { /*and propagate eventIn if any*/ if (field->on_event_in) { field->on_event_in(node); } else if ((field->eventType==GF_SG_EVENT_IN) && (gf_node_get_tag(node) == TAG_MPEG4_Script)) { gf_sg_script_event_in(node, field); } else { /*Notify eventOut in all cases to handle protos*/ gf_node_event_out(node, field->fieldIndex); } /*signal node modif*/ gf_node_changed(node, field); }
void gf_bifs_check_field_change(GF_Node *node, GF_FieldInfo *field) { if (field->fieldType==GF_SG_VRML_MFNODE) node->sgprivate->flags |= GF_SG_CHILD_DIRTY; /*signal node modif*/ gf_node_changed(node, field); /*Notify eventOut in all cases to handle protos*/ gf_node_event_out(node, field->fieldIndex); /*and propagate eventIn if any*/ if (field->on_event_in) { field->on_event_in(node, NULL); } else if ((gf_node_get_tag(node) == TAG_MPEG4_Script) && (field->eventType==GF_SG_EVENT_IN)) { gf_sg_script_event_in(node, field); } }
static void ttd_set_blink_fraction(GF_Node *node, GF_Route *route) { M_Material2D *m; u32 i; TTDPriv *priv = (TTDPriv *)gf_node_get_private(node); Bool blink_on = 1; if (priv->process_blink->set_fraction>FIX_ONE/2) blink_on = 0; i=0; while ((m = (M_Material2D*)gf_list_enum(priv->blink_nodes, &i))) { if (m->filled != blink_on) { m->filled = blink_on; gf_node_changed((GF_Node *) m, NULL); } } }
static void Node_on_remove_children(GF_Node *node, GF_Route *route) { GF_ChildNodeItem *list; GF_FieldInfo field; GF_VRMLParent *n = (GF_VRMLParent *)node; if (!n->removeChildren) return; list = n->removeChildren; while (list) { if (gf_node_list_del_child(& n->children, list->node)) { gf_node_unregister(list->node, node); } list = list->next; } gf_node_unregister_children(node, n->removeChildren); n->removeChildren = NULL; /*signal children field is modified*/ field.name = "children"; field.eventType = GF_SG_EVENT_EXPOSED_FIELD; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = -1; if ( node->sgprivate->tag == TAG_MPEG4_Transform ) field.fieldIndex = 3; else field.fieldIndex = 2; field.far_ptr = & n->children; gf_node_event_out(node, field.fieldIndex); gf_node_changed(node, &field); if (node->sgprivate->scenegraph->on_node_modified) { field.name = "removeChildren"; field.eventType = GF_SG_EVENT_IN; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = -1; field.fieldIndex = 1; field.far_ptr = & n->removeChildren; node->sgprivate->scenegraph->on_node_modified(node->sgprivate->scenegraph, node, &field, NULL); } }
/* Inserts a new resolved time instant in the begin or end attribute. The insertion preserves the sorting and removes the previous insertions which have become obsolete WARNING: Only used for inserting time when an <a> element, whose target is a timed element, is activated. */ GF_EXPORT void gf_smil_timing_insert_clock(GF_Node *elt, Bool is_end, Double clock) { u32 i, count, found; SVGTimedAnimBaseElement *timed = (SVGTimedAnimBaseElement*)elt; SMIL_Time *begin; GF_List *l; GF_SAFEALLOC(begin, SMIL_Time); begin->type = GF_SMIL_TIME_EVENT_RESOLVED; begin->clock = clock; l = is_end ? *timed->timingp->end : *timed->timingp->begin; found = 0; count = gf_list_count(l); for (i=0; i<count; i++) { SMIL_Time *first = (SMIL_Time *)gf_list_get(l, i); /*remove past instanciations*/ if ((first->type==GF_SMIL_TIME_EVENT_RESOLVED) && (first->clock < begin->clock)) { gf_list_rem(l, i); gf_free(first); i--; count--; continue; } if ( (first->type == GF_SMIL_TIME_INDEFINITE) || ( (first->type == GF_SMIL_TIME_CLOCK) && (first->clock > begin->clock) ) ) { gf_list_insert(l, begin, i); found = 1; break; } } if (!found) gf_list_add(l, begin); /* call gf_smil_timing_modified */ gf_node_changed(elt, NULL); }
static void Node_on_add_children(GF_Node *node, GF_Route *route) { GF_ChildNodeItem *list; GF_FieldInfo field; GF_VRMLParent *n = (GF_VRMLParent *)node; if (n->children) { list = n->children; while (list->next) list = list->next; list->next = n->addChildren; } else { n->children = n->addChildren; } n->addChildren = NULL; /*signal children field is modified*/ field.name = "children"; field.eventType = GF_SG_EVENT_EXPOSED_FIELD; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = -1; if ( node->sgprivate->tag == TAG_MPEG4_Transform ) field.fieldIndex = 3; else field.fieldIndex = 2; field.far_ptr = & n->children; gf_node_event_out(node, field.fieldIndex); gf_node_changed(node, &field); if (node->sgprivate->scenegraph->on_node_modified) { field.name = "addChildren"; field.eventType = GF_SG_EVENT_IN; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = -1; field.fieldIndex = 0; field.far_ptr = & n->addChildren; node->sgprivate->scenegraph->on_node_modified(node->sgprivate->scenegraph, node, &field, NULL); } }
static void Node_on_add_children(GF_Node *node) { GF_ChildNodeItem *list; GF_FieldInfo field; GF_VRMLParent *n = (GF_VRMLParent *)node; if (n->children) { list = n->children; while (list->next) list = list->next; list->next = n->addChildren; } else { n->children = n->addChildren; } n->addChildren = NULL; /*signal children field is modified*/ field.name = "children"; field.eventType = GF_SG_EVENT_EXPOSED_FIELD; field.fieldType = GF_SG_VRML_MFNODE; field.NDTtype = 0; field.fieldIndex = 2; field.far_ptr = & n->children; gf_node_changed(node, &field); }
static void gf_storage_load(M_Storage *storage) { const char *opt; char szID[20]; u32 i, count; u32 sec, exp, frac; GF_Config *cfg = storage_get_cfg(storage); char *section = storage_get_section(storage); if (!cfg || !section) return; if (!gf_cfg_get_key_count(cfg, section)) { gf_free(section); return; } opt = gf_cfg_get_key(cfg, section, "expireAfterNTP"); gf_net_get_ntp(&sec, &frac); sscanf(opt, "%u", &exp); if (exp && (exp<=sec)) { gf_cfg_del_section(cfg, section); gf_free(section); return; } count = gf_cfg_get_key_count(cfg, section)-1; if (!count || (count!=storage->storageList.count)) { gf_cfg_del_section(cfg, section); gf_free(section); return; } for (i=0; i<count; i++) { GF_FieldInfo info; sprintf(szID, "%d", i); opt = gf_cfg_get_key(cfg, section, szID); if (!opt) break; if (!storage->storageList.vals[i].node) break; if (gf_node_get_field(storage->storageList.vals[i].node, storage->storageList.vals[i].fieldIndex, &info) != GF_OK) break; if (gf_sg_vrml_is_sf_field(info.fieldType)) { storage_parse_sf(info.far_ptr, info.fieldType, (char *) opt); } else { u32 sftype = gf_sg_vrml_get_sf_type(info.fieldType); char *sep, *val; void *slot; gf_sg_vrml_mf_reset(info.far_ptr, info.fieldType); while (1) { val = strchr(opt, '\''); sep = val ? strchr(val+1, '\'') : NULL; if (!val || !sep) break; sep[0] = 0; gf_sg_vrml_mf_append(info.far_ptr, info.fieldType, &slot); storage_parse_sf(slot, sftype, val+1); sep[0] = '\''; opt = sep+1; } } gf_node_changed(storage->storageList.vals[i].node, &info); } gf_free(section); }
GF_EXPORT GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset) { GF_Err e; GF_CommandField *inf; GF_FieldInfo field; GF_Node *def, *node; void *slot_ptr; if (!com || !graph) return GF_BAD_PARAM; e = GF_OK; switch (com->tag) { case GF_SG_SCENE_REPLACE: /*unregister root*/ gf_node_unregister(graph->RootNode, NULL); /*remove all protos and routes*/ while (gf_list_count(graph->routes_to_activate)) gf_list_rem(graph->routes_to_activate, 0); /*destroy all routes*/ while (gf_list_count(graph->Routes)) { GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0); /*this will unregister the route from the graph, so don't delete the chain entry*/ gf_sg_route_del(r); } /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } /*DO NOT TOUCH node registry*/ /*DO NOT TOUCH UNREGISTERED PROTOS*/ /*move all protos in graph*/ while (gf_list_count(com->new_proto_list)) { GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0); gf_list_rem(com->new_proto_list, 0); gf_list_del_item(graph->unregistered_protos, p); gf_list_add(graph->protos, p); } /*assign new root (no need to register/unregister)*/ graph->RootNode = com->node; com->node = NULL; break; case GF_SG_NODE_REPLACE: if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_replace(com->node, inf->new_node, 0); if (inf->new_node) gf_node_register(inf->new_node, NULL); break; case GF_SG_MULTIPLE_REPLACE: case GF_SG_FIELD_REPLACE: { u32 j; GF_ChildNodeItem *list, *cur, *prev; j=0; while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) { e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; switch (field.fieldType) { case GF_SG_VRML_SFNODE: { node = *((GF_Node **) field.far_ptr); e = gf_node_unregister(node, com->node); *((GF_Node **) field.far_ptr) = inf->new_node; if (!e) gf_node_register(inf->new_node, com->node); break; } case GF_SG_VRML_MFNODE: gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr)); * ((GF_ChildNodeItem **) field.far_ptr) = NULL; list = * ((GF_ChildNodeItem **) inf->field_ptr); prev=NULL; while (list) { cur = malloc(sizeof(GF_ChildNodeItem)); cur->next = NULL; cur->node = list->node; if (prev) { prev->next = cur; } else { * ((GF_ChildNodeItem **) field.far_ptr) = cur; } gf_node_register(list->node, com->node); prev = cur; list = list->next; } break; default: /*this is a regular field, reset it and clone - we cannot switch pointers since the original fields are NOT pointers*/ if (!gf_sg_vrml_is_sf_field(field.fieldType)) { e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType); } if (e) return e; gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType); if (field.fieldType==GF_SG_VRML_SFTIME) *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset; break; } SG_CheckFieldChange(com->node, &field); } break; } case GF_SG_MULTIPLE_INDEXED_REPLACE: case GF_SG_INDEXED_REPLACE: { u32 sftype, i=0; while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) { e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; /*if MFNode remove the child and set new node*/ if (field.fieldType == GF_SG_VRML_MFNODE) { /*we must remove the node before in case the new node uses the same ID (not forbidden) and this command removes the last instance of the node with the same ID*/ gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node); if (inf->new_node) gf_node_register(inf->new_node, NULL); } /*erase the field item*/ else { if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) { inf->pos = ((GenMFField *)field.far_ptr)->count - 1; /*may happen with text and default value*/ if (inf->pos < 0) { inf->pos = 0; gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1); } } e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos); if (e) return e; sftype = gf_sg_vrml_get_sf_type(field.fieldType); gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype); /*note we don't add time offset, since there's no MFTime*/ } SG_CheckFieldChange(com->node, &field); } break; } case GF_SG_ROUTE_REPLACE: { GF_Route *r; char *name; r = gf_sg_route_find(graph, com->RouteID); def = gf_sg_find_node(graph, com->fromNodeID); node = gf_sg_find_node(graph, com->toNodeID); if (!node || !def) return GF_SG_UNKNOWN_NODE; name = NULL; if (r) { name = r->name; r->name = NULL; gf_sg_route_del(r); } r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex); gf_sg_route_set_id(r, com->RouteID); if (name) { gf_sg_route_set_name(r, name); free(name); } break; } case GF_SG_NODE_DELETE_EX: case GF_SG_NODE_DELETE: { if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0); break; } case GF_SG_ROUTE_DELETE: { return gf_sg_route_del_by_id(graph, com->RouteID); } case GF_SG_INDEXED_DELETE: { if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM; /*then we need special handling in case of a node*/ if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) { e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL); } else { if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) { inf->pos = ((GenMFField *)field.far_ptr)->count - 1; } /*this is a regular MFField, just remove the item (realloc)*/ e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos); } /*deletion -> node has changed*/ if (!e) SG_CheckFieldChange(com->node, &field); break; } case GF_SG_NODE_INSERT: { if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_insert_child(com->node, inf->new_node, inf->pos); if (!e) gf_node_register(inf->new_node, com->node); if (!e) gf_node_event_out(com->node, inf->fieldIndex); if (!e) gf_node_changed(com->node, NULL); break; } case GF_SG_ROUTE_INSERT: { GF_Route *r; def = gf_sg_find_node(graph, com->fromNodeID); node = gf_sg_find_node(graph, com->toNodeID); if (!node || !def) return GF_SG_UNKNOWN_NODE; r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex); if (com->RouteID) gf_sg_route_set_id(r, com->RouteID); if (com->def_name) { gf_sg_route_set_name(r, com->def_name); free(com->def_name); com->def_name = NULL; } break; } case GF_SG_INDEXED_INSERT: { u32 sftype; if (!gf_list_count(com->command_fields)) return GF_OK; inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); e = gf_node_get_field(com->node, inf->fieldIndex, &field); if (e) return e; /*rescale the MFField and parse the SFField*/ if (field.fieldType != GF_SG_VRML_MFNODE) { if (inf->pos == -1) { e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr); } else { e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos); } if (e) return e; sftype = gf_sg_vrml_get_sf_type(field.fieldType); gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype); } else { if (inf->new_node) { if (inf->pos == -1) { gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node); } else { gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos); } gf_node_register(inf->new_node, com->node); } } if (!e) SG_CheckFieldChange(com->node, &field); break; } case GF_SG_PROTO_INSERT: /*destroy all proto*/ while (gf_list_count(com->new_proto_list)) { GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0); gf_list_rem(com->new_proto_list, 0); gf_list_del_item(graph->unregistered_protos, p); gf_list_add(graph->protos, p); } return GF_OK; case GF_SG_PROTO_DELETE: { u32 i; for (i=0; i<com->del_proto_list_size; i++) { /*note this will check for unregistered protos, but since IDs are unique we are sure we will not destroy an unregistered one*/ GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL); if (proto) gf_sg_proto_del(proto); } } return GF_OK; case GF_SG_PROTO_DELETE_ALL: /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); gf_list_rem(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } /*DO NOT TOUCH UNREGISTERED PROTOS*/ return GF_OK; /*only used by BIFS*/ case GF_SG_GLOBAL_QUANTIZER: return GF_OK; #ifndef GPAC_DISABLE_SVG /*laser commands*/ case GF_SG_LSR_NEW_SCENE: /*DO NOT TOUCH node registry*/ /*assign new root (no need to register/unregister)*/ graph->RootNode = com->node; com->node = NULL; break; case GF_SG_LSR_DELETE: if (!com->node) return GF_NON_COMPLIANT_BITSTREAM; if (!gf_list_count(com->command_fields)) { gf_node_replace(com->node, NULL, 0); gf_node_deactivate(com->node); return GF_OK; } inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos); if (node) { e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL); gf_node_deactivate(node); } break; case GF_SG_LSR_INSERT: inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM; if (inf->new_node) { if (inf->pos<0) gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node); else gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos); gf_node_register(inf->new_node, com->node); gf_node_activate(inf->new_node); gf_node_changed(com->node, NULL); } else { /*NOT SUPPORTED*/ GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n")); } break; case GF_SG_LSR_ADD: case GF_SG_LSR_REPLACE: inf = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM; if (inf->new_node) { if (inf->pos<0) { /*if fieldIndex (eg attributeName) is set, this is children replacement*/ if (inf->fieldIndex>0) { gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children); ((SVG_Element *)com->node)->children = NULL; gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node); gf_node_register(inf->new_node, com->node); gf_node_activate(inf->new_node); } else { e = gf_node_replace(com->node, inf->new_node, 0); gf_node_activate(inf->new_node); } } else { node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos); gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node); gf_node_register(inf->new_node, com->node); if (node) gf_node_deactivate(node); gf_node_activate(inf->new_node); } /*signal node modif*/ gf_node_changed(com->node, NULL); return e; } else if (inf->node_list) { GF_ChildNodeItem *child, *cur, *prev; gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children); ((SVG_Element *)com->node)->children = NULL; prev = NULL; child = inf->node_list; while (child) { cur = (GF_ChildNodeItem*)malloc(sizeof(GF_ChildNodeItem)); cur->next = NULL; cur->node = child->node; gf_node_register(child->node, com->node); gf_node_activate(child->node); if (prev) prev->next = cur; else ((SVG_Element *)com->node)->children = cur; prev = cur; child = child->next; } /*signal node modif*/ gf_node_changed(com->node, NULL); return GF_OK; } /*attribute modif*/ else if (inf->field_ptr) { GF_FieldInfo a, b; if (inf->fieldIndex==(u32) -2) { GF_Point2D scale, translate; Fixed rotate; GF_Matrix2D *dest; gf_node_get_field_by_name(com->node, "transform", &a); dest = (GF_Matrix2D*)a.far_ptr; if (com->tag==GF_SG_LSR_REPLACE) { if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) { gf_mx2d_init(*dest); if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle; gf_mx2d_add_scale(dest, scale.x, scale.y); gf_mx2d_add_rotation(dest, 0, 0, rotate); gf_mx2d_add_translation(dest, translate.x, translate.y); } } else { GF_Point2D *pt = (GF_Point2D *)inf->field_ptr; if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y); else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y); else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle); } } else { if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==SVG_String_datatype)) { char *str = *(SVG_String*)inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; if (t && (t->sgprivate->tag==TAG_DOMText)) { if (t->textContent) free(t->textContent); t->textContent = NULL; if (str) t->textContent = strdup(str); } } else { if (str) gf_dom_add_text_node(com->node, strdup(str)); } } else if ((inf->fieldIndex==TAG_LSR_ATT_scale) || (inf->fieldIndex==TAG_LSR_ATT_translation) || (inf->fieldIndex==TAG_LSR_ATT_rotation) ) { SVG_Transform *mx; gf_svg_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a); mx = a.far_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_Point2D scale, translate; SVG_Point_Angle rotate; if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) { gf_mx2d_init(mx->mat); if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr; else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr; gf_mx2d_add_scale(&mx->mat, scale.x, scale.y); gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle); gf_mx2d_add_translation(&mx->mat, translate.x, translate.y); } } else { if (inf->fieldIndex==TAG_LSR_ATT_scale) gf_mx2d_add_scale(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y); if (inf->fieldIndex==TAG_LSR_ATT_translation) gf_mx2d_add_translation(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y); if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle); } } else if (gf_svg_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) { b = a; b.far_ptr = inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { gf_svg_attributes_copy(&a, &b, 0); } else { gf_svg_attributes_add(&a, &b, &a, 0); } } b = a; b.far_ptr = inf->field_ptr; } /*signal node modif*/ gf_node_changed(com->node, &a); } else if (com->fromNodeID) { GF_FieldInfo a, b; GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID); if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM; if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM; if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==SVG_String_datatype)) { char *str = *(SVG_String*)inf->field_ptr; if (com->tag == GF_SG_LSR_REPLACE) { GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL; if (t && (t->sgprivate->tag==TAG_DOMText)) { if (t->textContent) free(t->textContent); t->textContent = NULL; if (str) t->textContent = strdup(str); } } else { if (str) gf_dom_add_text_node(com->node, strdup(str)); } } else { gf_node_get_field(com->node, inf->fieldIndex, &a); if (com->tag == GF_SG_LSR_REPLACE) { e = gf_svg_attributes_copy(&a, &b, 0); } else { e = gf_svg_attributes_add(&a, &b, &a, 0); } } gf_node_changed(com->node, &a); return e; } else { return GF_NON_COMPLIANT_BITSTREAM; } break; case GF_SG_LSR_ACTIVATE: gf_node_activate(com->node); break; case GF_SG_LSR_DEACTIVATE: gf_node_deactivate(com->node); gf_node_changed(com->node, NULL); break; #endif default: return GF_NOT_SUPPORTED; } if (e) return e; if (com->scripts_to_load) { while (gf_list_count(com->scripts_to_load)) { GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0); gf_list_rem(com->scripts_to_load, 0); gf_sg_script_load(script); } gf_list_del(com->scripts_to_load); com->scripts_to_load = NULL; } return GF_OK; }
static void svg_sani_a_HandleEvent(GF_Node *handler, GF_DOM_Event *event) { GF_Renderer *compositor; GF_Event evt; SVG_SANI_aElement *a; assert(gf_node_get_tag(event->currentTarget)==TAG_SVG_SANI_a); a = (SVG_SANI_aElement *) event->currentTarget; compositor = (GF_Renderer *)gf_node_get_private(handler); if (!compositor->user->EventProc) return; evt.type = GF_EVENT_NAVIGATE; if (a->xlink->href.type == XMLRI_STRING) { evt.navigate.to_url = a->xlink->href.iri; if (evt.navigate.to_url) { evt.navigate.param_count = 1; evt.navigate.parameters = (const char **) &a->target; compositor->user->EventProc(compositor->user->opaque, &evt); } } else { u32 tag; if (!a->xlink->href.target) { /* TODO: check if href can be resolved */ return; } tag = gf_node_get_tag((GF_Node *)a->xlink->href.target); if (tag == TAG_SVG_SANI_set || tag == TAG_SVG_SANI_animate || tag == TAG_SVG_SANI_animateColor || tag == TAG_SVG_SANI_animateTransform || tag == TAG_SVG_SANI_animateMotion || tag == TAG_SVG_SANI_discard) { u32 i, count, found; SVG_SANI_setElement *set = (SVG_SANI_setElement *)a->xlink->href.target; SMIL_Time *begin; GF_SAFEALLOC(begin, SMIL_Time); begin->type = GF_SMIL_TIME_EVENT_RESOLVED; begin->clock = gf_node_get_scene_time((GF_Node *)set); found = 0; count = gf_list_count(set->timing->begin); for (i=0; i<count; i++) { SMIL_Time *first = (SMIL_Time *)gf_list_get(set->timing->begin, i); /*remove past instanciations*/ if ((first->type==GF_SMIL_TIME_EVENT_RESOLVED) && (first->clock < begin->clock)) { gf_list_rem(set->timing->begin, i); free(first); i--; count--; continue; } if ( (first->type == GF_SMIL_TIME_INDEFINITE) || ( (first->type == GF_SMIL_TIME_CLOCK) && (first->clock > begin->clock) ) ) { gf_list_insert(set->timing->begin, begin, i); found = 1; break; } } if (!found) gf_list_add(set->timing->begin, begin); gf_node_changed((GF_Node *)a->xlink->href.target, NULL); } } return; }
static void TTD_ApplySample(TTDPriv *priv, GF_TextSample *txt, u32 sdi, Bool is_utf_16, u32 sample_duration) { u32 i, nb_lines, start_idx, count; s32 *id, thw, thh, tw, th, offset; Bool vertical; MFInt32 idx; SFString *s; GF_BoxRecord br; M_Material2D *n; M_Form *form; u16 utf16_text[5000]; u32 char_offset, char_count; GF_List *chunks; TTDTextChunk *tc; GF_Box *a; GF_TextSampleDescriptor *td = NULL; /*stop timer sensor*/ if (gf_list_count(priv->blink_nodes)) { priv->ts_blink->stopTime = gf_node_get_scene_time((GF_Node *) priv->ts_blink); gf_node_changed((GF_Node *) priv->ts_blink, NULL); } priv->ts_scroll->stopTime = gf_node_get_scene_time((GF_Node *) priv->ts_scroll); gf_node_changed((GF_Node *) priv->ts_scroll, NULL); /*flush routes to avoid getting the set_fraction of the scroll sensor deactivation*/ gf_sg_activate_routes(priv->inlineScene->graph); TTD_ResetDisplay(priv); if (!sdi || !txt || !txt->len) return; i=0; while ((td = (GF_TextSampleDescriptor *)gf_list_enum(priv->cfg->sample_descriptions, &i))) { if (td->sample_index==sdi) break; td = NULL; } if (!td) return; vertical = (td->displayFlags & GF_TXT_VERTICAL) ? 1 : 0; /*set back color*/ /*do we fill the text box or the entire text track region*/ if (td->displayFlags & GF_TXT_FILL_REGION) { priv->mat_box->transparency = FIX_ONE; n = priv->mat_track; } else { priv->mat_track->transparency = FIX_ONE; n = priv->mat_box; } n->transparency = FIX_ONE - INT2FIX((td->back_color>>24) & 0xFF) / 255; n->emissiveColor.red = INT2FIX((td->back_color>>16) & 0xFF) / 255; n->emissiveColor.green = INT2FIX((td->back_color>>8) & 0xFF) / 255; n->emissiveColor.blue = INT2FIX((td->back_color) & 0xFF) / 255; gf_node_changed((GF_Node *) n, NULL); if (txt->box) { br = txt->box->box; } else { br = td->default_pos; } if (!br.right || !br.bottom) { br.top = br.left = 0; br.right = priv->cfg->text_width; br.bottom = priv->cfg->text_height; } thw = br.right - br.left; thh = br.bottom - br.top; if (!thw || !thh) { br.top = br.left = 0; thw = priv->cfg->text_width; thh = priv->cfg->text_height; } priv->dlist->size.x = INT2FIX(thw); priv->dlist->size.y = INT2FIX(thh); /*disable backgrounds if not used*/ if (priv->mat_track->transparency<FIX_ONE) { if (priv->rec_track->size.x != priv->cfg->text_width) { priv->rec_track->size.x = priv->cfg->text_width; priv->rec_track->size.y = priv->cfg->text_height; gf_node_changed((GF_Node *) priv->rec_track, NULL); } } else if (priv->rec_track->size.x) { priv->rec_track->size.x = priv->rec_track->size.y = 0; gf_node_changed((GF_Node *) priv->rec_box, NULL); } if (priv->mat_box->transparency<FIX_ONE) { if (priv->rec_box->size.x != priv->dlist->size.x) { priv->rec_box->size.x = priv->dlist->size.x; priv->rec_box->size.y = priv->dlist->size.y; gf_node_changed((GF_Node *) priv->rec_box, NULL); } } else if (priv->rec_box->size.x) { priv->rec_box->size.x = priv->rec_box->size.y = 0; gf_node_changed((GF_Node *) priv->rec_box, NULL); } form = (M_Form *) ttd_create_node(priv, TAG_MPEG4_Form, NULL); form->size.x = INT2FIX(thw); form->size.y = INT2FIX(thh); thw /= 2; thh /= 2; tw = priv->cfg->text_width; th = priv->cfg->text_height; /*check translation, we must not get out of scene size - not supported in GPAC*/ offset = br.left - tw/2 + thw; if (offset + thw < - tw/2) offset = - tw/2 + thw; else if (offset - thw > tw/2) offset = tw/2 - thw; priv->tr_box->translation.x = INT2FIX(offset); offset = th/2 - br.top - thh; if (offset + thh > th/2) offset = th/2 - thh; else if (offset - thh < -th/2) offset = -th/2 + thh; priv->tr_box->translation.y = INT2FIX(offset); gf_node_dirty_set((GF_Node *)priv->tr_box, 0, 1); if (priv->scroll_type) { priv->ts_scroll->stopTime = gf_node_get_scene_time((GF_Node *) priv->ts_scroll); gf_node_changed((GF_Node *) priv->ts_scroll, NULL); } priv->scroll_mode = 0; if (td->displayFlags & GF_TXT_SCROLL_IN) priv->scroll_mode |= GF_TXT_SCROLL_IN; if (td->displayFlags & GF_TXT_SCROLL_OUT) priv->scroll_mode |= GF_TXT_SCROLL_OUT; priv->scroll_type = 0; if (priv->scroll_mode) { priv->scroll_type = (td->displayFlags & GF_TXT_SCROLL_DIRECTION)>>7; priv->scroll_type ++; }
/*the WORST thing about 3GP in MPEG4 is positioning of the text track...*/ static void TTD_UpdateSizeInfo(TTDPriv *priv) { u32 w, h; Bool has_size; s32 offset, thw, thh, vw, vh; has_size = gf_sg_get_scene_size_info(priv->inlineScene->graph, &w, &h); /*no size info is given in main scene, override by associated video size if any, or by text track size*/ if (!has_size) { if (priv->cfg->has_vid_info && priv->cfg->video_width && priv->cfg->video_height) { gf_sg_set_scene_size_info(priv->sg, priv->cfg->video_width, priv->cfg->video_height, 1); } else { gf_sg_set_scene_size_info(priv->sg, priv->cfg->text_width, priv->cfg->text_height, 1); } gf_sg_get_scene_size_info(priv->sg, &w, &h); if (!w || !h) return; gf_scene_force_size(priv->inlineScene, w, h); } if (!w || !h) return; /*apply*/ gf_sg_set_scene_size_info(priv->sg, w, h, 1); /*make sure the scene size is big enough to contain the text track after positioning. RESULTS ARE UNDEFINED if offsets are negative: since MPEG-4 uses centered coord system, we must assume video is aligned to top-left*/ if (priv->cfg->has_vid_info) { Bool set_size = 0; vw = priv->cfg->horiz_offset; if (vw<0) vw = 0; vh = priv->cfg->vert_offset; if (vh<0) vh = 0; if (priv->cfg->text_width + (u32) vw > w) { w = priv->cfg->text_width+vw; set_size = 1; } if (priv->cfg->text_height + (u32) vh > h) { h = priv->cfg->text_height+vh; set_size = 1; } if (set_size) { gf_sg_set_scene_size_info(priv->sg, w, h, 1); gf_scene_force_size(priv->inlineScene, w, h); } } else { /*otherwise override (mainly used for SRT & TTXT file direct loading*/ priv->cfg->text_width = w; priv->cfg->text_height = h; } /*ok override video size with main scene size*/ priv->cfg->video_width = w; priv->cfg->video_height = h; vw = (s32) w; vh = (s32) h; thw = priv->cfg->text_width / 2; thh = priv->cfg->text_height / 2; /*check translation, we must not get out of scene size - not supported in GPAC*/ offset = priv->cfg->horiz_offset - vw/2 + thw; /*safety checks ? if (offset + thw < - vw/2) offset = - vw/2 + thw; else if (offset - thw > vw/2) offset = vw/2 - thw; */ priv->tr_track->translation.x = INT2FIX(offset); offset = vh/2 - priv->cfg->vert_offset - thh; /*safety checks ? if (offset + thh > vh/2) offset = vh/2 - thh; else if (offset - thh < -vh/2) offset = -vh/2 + thh; */ priv->tr_track->translation.y = INT2FIX(offset); gf_node_changed((GF_Node *)priv->tr_track, NULL); }