static void svg2bifs_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes) { u32 i; SVG2BIFS_Converter *converter = (SVG2BIFS_Converter *)sax_cbck; SVGPropertiesPointers *backup_props; char *id_string = NULL; u32 tag; SVG_Element *elt; SVG_DeferedAnimation *anim = NULL; tag = gf_xml_get_element_tag(name, 0); elt = (SVG_Element*)gf_node_new(converter->svg_sg, tag); if (!gf_sg_get_root_node(converter->svg_sg)) { gf_node_register((GF_Node *)elt, NULL); gf_sg_set_root_node(converter->svg_sg, (GF_Node *)elt); } else { gf_node_register((GF_Node *)elt, converter->svg_parent); //gf_node_list_add_child(&((GF_ParentNode*)converter->svg_parent)->children, (GF_Node *)elt); } // fprintf(stdout, "Converting %s\n", gf_node_get_class_name((GF_Node *)elt)); // if (converter->bifs_parent) fprintf(stdout, "%s\n", gf_node_get_class_name(converter->bifs_parent)); if (gf_svg_is_animation_tag(tag)) { GF_SAFEALLOC(anim, SVG_DeferedAnimation); /*default anim target is parent node*/ anim->animation_elt = elt; if (converter->svg_parent) { anim->target = anim->anim_parent = (SVG_Element*) converter->svg_parent; } } 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")) { gf_svg_parse_element_id((GF_Node *)elt, att->value, 0); id_string = att->value; } else if (anim && !stricmp(att->name, "to")) { anim->to = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "from")) { anim->from = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "by")) { anim->by = gf_strdup(att->value); } else if (anim && !stricmp(att->name, "values")) { anim->values = gf_strdup(att->value); } else if (anim && (tag == TAG_SVG_animateTransform) && !stricmp(att->name, "type")) { anim->type = gf_strdup(att->value); } else { GF_FieldInfo info; 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); } else { fprintf(stdout, "Skipping attribute %s\n", att->name); } } } if (anim) { svg_parse_animation(converter->svg_sg, anim); } memset(&converter->all_atts, 0, sizeof(SVGAllAttributes)); gf_svg_flatten_attributes(elt, &converter->all_atts); backup_props = gf_malloc(sizeof(SVGPropertiesPointers)); memcpy(backup_props, &converter->svg_props, sizeof(SVGPropertiesPointers)); gf_node_set_private((GF_Node *)elt, backup_props); gf_svg_apply_inheritance(&converter->all_atts, &converter->svg_props); fprintf(stdout, "START\t%s\t%s\t%s", converter->svg_parent ? gf_node_get_class_name(converter->svg_parent) : "none", converter->bifs_parent ? gf_node_get_class_name(converter->bifs_parent) : "none", name); converter->svg_parent = (GF_Node *)elt; if (!gf_sg_get_root_node(converter->bifs_sg)) { if (tag == TAG_SVG_svg) { GF_Node *node, *child; converter->bifs_sg->usePixelMetrics = 1; if (converter->all_atts.width && converter->all_atts.width->type == SVG_NUMBER_VALUE) { converter->bifs_sg->width = FIX2INT(converter->all_atts.width->value); } else { converter->bifs_sg->width = 320; } if (converter->all_atts.height && converter->all_atts.height->type == SVG_NUMBER_VALUE) { converter->bifs_sg->height = FIX2INT(converter->all_atts.height->value); } else { converter->bifs_sg->height = 200; } node = gf_node_new(converter->bifs_sg, TAG_MPEG4_OrderedGroup); gf_node_register(node, NULL); gf_sg_set_root_node(converter->bifs_sg, node); child = gf_node_new(converter->bifs_sg, TAG_MPEG4_QuantizationParameter); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_QuantizationParameter *qp = (M_QuantizationParameter *)child; qp->useEfficientCoding = 1; } /* SVG to BIFS coordinate transformation */ child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Viewport); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Viewport *vp = (M_Viewport*)child; if (converter->all_atts.viewBox) { vp->size.x = converter->all_atts.viewBox->width; vp->size.y = converter->all_atts.viewBox->height; vp->position.x = converter->all_atts.viewBox->x+converter->all_atts.viewBox->width/2; vp->position.y = -(converter->all_atts.viewBox->y+converter->all_atts.viewBox->height/2); } else { vp->size.x = INT2FIX(converter->bifs_sg->width); vp->size.y = INT2FIX(converter->bifs_sg->height); vp->position.x = INT2FIX(converter->bifs_sg->width)/2; vp->position.y = -INT2FIX(converter->bifs_sg->height)/2; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Background2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Background2D *b = (M_Background2D *)child; b->backColor.red = FIX_ONE; b->backColor.green = FIX_ONE; b->backColor.blue = FIX_ONE; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Transform2D *tr = (M_Transform2D *)node; tr->scale.y = -FIX_ONE; } converter->bifs_parent = node; } } else { GF_Node *node, *child; node = converter->bifs_parent; switch(tag) { case TAG_SVG_g: { if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; } else { M_Group *g = (M_Group*)gf_node_new(converter->bifs_sg, TAG_MPEG4_Group); gf_node_register((GF_Node *)g, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, (GF_Node *)g); node = (GF_Node *)g; converter->bifs_parent = node; } } break; case TAG_SVG_rect: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value + (converter->all_atts.width?converter->all_atts.width->value/2:0); if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value + (converter->all_atts.height?converter->all_atts.height->value/2:0); } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_Rectangle); gf_node_register(shape->geometry, (GF_Node *)shape); { M_Rectangle *rect = (M_Rectangle *)shape->geometry; if (converter->all_atts.width) rect->size.x = converter->all_atts.width->value; if (converter->all_atts.height) rect->size.y = converter->all_atts.height->value; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_path: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.x || converter->all_atts.y) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } { M_Transform2D *tr = (M_Transform2D *)node; if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value; if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_XCurve2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.d) { M_Coordinate2D *c2d; M_XCurve2D *xc = (M_XCurve2D *)shape->geometry; u32 i, j, c, k; xc->point = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)xc->point; gf_node_register(xc->point, (GF_Node *)xc); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, converter->all_atts.d->n_points); gf_sg_vrml_mf_alloc(&xc->type, GF_SG_VRML_MFINT32, converter->all_atts.d->n_points); c = 0; k = 0; j = 0; c2d->point.vals[k] = converter->all_atts.d->points[0]; k++; xc->type.vals[0] = 0; for (i = 1; i < converter->all_atts.d->n_points; ) { switch(converter->all_atts.d->tags[i]) { case GF_PATH_CURVE_ON: c2d->point.vals[k] = converter->all_atts.d->points[i]; k++; if (i-1 == converter->all_atts.d->contours[c]) { xc->type.vals[j] = 0; c++; } else { xc->type.vals[j] = 1; } i++; break; case GF_PATH_CURVE_CUBIC: c2d->point.vals[k] = converter->all_atts.d->points[i]; c2d->point.vals[k+1] = converter->all_atts.d->points[i+1]; c2d->point.vals[k+2] = converter->all_atts.d->points[i+2]; k+=3; xc->type.vals[j] = 2; if (converter->all_atts.d->tags[i+2]==GF_PATH_CLOSE) { j++; xc->type.vals[j] = 6; } i+=3; break; case GF_PATH_CLOSE: xc->type.vals[j] = 6; i++; break; case GF_PATH_CURVE_CONIC: c2d->point.vals[k] = converter->all_atts.d->points[i]; c2d->point.vals[k+1] = converter->all_atts.d->points[i+1]; k+=2; xc->type.vals[j] = 7; if (converter->all_atts.d->tags[i+1]==GF_PATH_CLOSE) { j++; xc->type.vals[j] = 6; } i+=2; break; } j++; } xc->type.count = j; c2d->point.count = k; } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_polyline: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_IndexedFaceSet2D); gf_node_register(shape->geometry, (GF_Node *)shape); if (converter->all_atts.points) { M_Coordinate2D *c2d; M_IndexedFaceSet2D *ifs = (M_IndexedFaceSet2D *)shape->geometry; u32 i; ifs->coord = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D); c2d = (M_Coordinate2D *)ifs->coord; gf_node_register(ifs->coord, (GF_Node *)ifs); gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, gf_list_count(*converter->all_atts.points)); for (i = 0; i < gf_list_count(*converter->all_atts.points); i++) { SVG_Point *p = (SVG_Point *)gf_list_get(*converter->all_atts.points, i); c2d->point.vals[i].x = p->x; c2d->point.vals[i].y = p->y; } } shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_text: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.text_x) tr->translation.x = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_x, 0))->value; if (converter->all_atts.text_y) tr->translation.y = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_y, 0))->value; tr->scale.y = -FIX_ONE; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_FontStyle *fs; M_Text *text; M_Shape *shape = (M_Shape *)node; text = (M_Text *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Text); shape->geometry = (GF_Node *)text; converter->bifs_text_node = shape->geometry; gf_node_register(shape->geometry, (GF_Node *)shape); fs = (M_FontStyle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_XFontStyle); gf_node_register((GF_Node *)fs, (GF_Node*)text); text->fontStyle = (GF_Node *)fs; gf_sg_vrml_mf_alloc(&fs->family, GF_SG_VRML_MFSTRING, 1); fs->family.vals[0] = gf_strdup(converter->svg_props.font_family->value); fs->size = converter->svg_props.font_size->value; shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_ellipse: case TAG_SVG_circle: { Bool is_parent_set = 0; if (converter->all_atts.transform) { node = add_transform_matrix(converter, node); converter->bifs_parent = node; is_parent_set = 1; } if (converter->force_transform) { node = add_transform2d(converter, node); if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } if (converter->all_atts.cx || converter->all_atts.cy) { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); { M_Transform2D *tr = (M_Transform2D *)child; if (converter->all_atts.cx) tr->translation.x = converter->all_atts.cx->value; if (converter->all_atts.cy) tr->translation.y = converter->all_atts.cy->value; } node = child; child = NULL; if (!is_parent_set) { converter->bifs_parent = node; is_parent_set = 1; } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; if (!is_parent_set) converter->bifs_parent = node; { M_Shape *shape = (M_Shape *)node; if (tag == TAG_SVG_ellipse) { M_Ellipse *e = (M_Ellipse *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Ellipse); shape->geometry = (GF_Node *)e; e->radius.x = converter->all_atts.rx->value; e->radius.y = converter->all_atts.ry->value; } else { M_Circle *c = (M_Circle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Circle); shape->geometry = (GF_Node *)c; c->radius = converter->all_atts.r->value; } gf_node_register(shape->geometry, (GF_Node *)shape); shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg); gf_node_register(shape->appearance, (GF_Node *)shape); } } break; case TAG_SVG_defs: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Switch); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; { M_Switch *sw = (M_Switch *)node; sw->whichChoice = -1; } converter->bifs_parent = node; } break; case TAG_SVG_solidColor: { child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape); gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; case TAG_SVG_animateTransform: { GF_Node *child_ts; if (!gf_node_get_id(node)) { gf_node_set_id(node, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } child_ts = gf_node_new(converter->bifs_sg, TAG_MPEG4_TimeSensor); if (!gf_node_get_id(child_ts)) { gf_node_set_id(child_ts, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child_ts, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child_ts); { M_TimeSensor *ts = (M_TimeSensor *)child_ts; if (converter->all_atts.dur) { ts->cycleInterval = converter->all_atts.dur->clock_value; } if (converter->all_atts.repeatCount && converter->all_atts.repeatCount->type == SMIL_REPEATCOUNT_INDEFINITE) { ts->loop = 1; } } if (converter->all_atts.transform_type) { GF_FieldInfo fromField, toField; switch (*converter->all_atts.transform_type) { case SVG_TRANSFORM_ROTATE: child = gf_node_new(converter->bifs_sg, TAG_MPEG4_PositionInterpolator2D); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); gf_node_get_field_by_name(node, "rotationAngle", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_PositionInterpolator2D *pi2d = (M_PositionInterpolator2D *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&pi2d->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFVec2f *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point_Angle *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&pi2d->keyValue, GF_SG_VRML_MFVEC2F, &g); g->x = p->x; g->y = p->y; } } } child = gf_node_new(converter->bifs_sg, TAG_MPEG4_ScalarInterpolator); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); gf_node_get_field_by_name(node, "center", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_ScalarInterpolator *si = (M_ScalarInterpolator *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&si->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFFloat *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point_Angle *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&si->keyValue, GF_SG_VRML_MFFLOAT, &g); *g = p->angle; } } } break; case SVG_TRANSFORM_SCALE: case SVG_TRANSFORM_TRANSLATE: child = gf_node_new(converter->bifs_sg, TAG_MPEG4_PositionInterpolator2D); if (!gf_node_get_id(child)) { gf_node_set_id(child, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL); } gf_node_register(child, node); gf_node_list_add_child(&((GF_ParentNode *)node)->children, child); gf_node_get_field_by_name(child_ts, "fraction_changed", &fromField); gf_node_get_field_by_name(child, "set_fraction", &toField); gf_sg_route_new(converter->bifs_sg, child_ts, fromField.fieldIndex, child, toField.fieldIndex); gf_node_get_field_by_name(child, "value_changed", &fromField); if (*converter->all_atts.transform_type == SVG_TRANSFORM_SCALE) gf_node_get_field_by_name(node, "scale", &toField); else gf_node_get_field_by_name(node, "translation", &toField); gf_sg_route_new(converter->bifs_sg, child, fromField.fieldIndex, node, toField.fieldIndex); { M_PositionInterpolator2D *pi2d = (M_PositionInterpolator2D *)child; if (converter->all_atts.keyTimes) { SFFloat *g; u32 count, i; count = gf_list_count(*converter->all_atts.keyTimes); for (i = 0; i < count; i++) { Fixed *f = gf_list_get(*converter->all_atts.keyTimes, i); gf_sg_vrml_mf_append(&pi2d->key, GF_SG_VRML_MFFLOAT, &g); *g = *f; } } if (converter->all_atts.values) { SFVec2f *g; u32 count, i; count = gf_list_count(converter->all_atts.values->values); for (i = 0; i < count; i++) { SVG_Point *p; p = gf_list_get(converter->all_atts.values->values, i); gf_sg_vrml_mf_append(&pi2d->keyValue, GF_SG_VRML_MFVEC2F, &g); g->x = p->x; g->y = p->y; } } } break; default: fprintf(stdout, "Warning: transformation type not supported \n"); } } //converter->bifs_parent = node; } break; default: { fprintf(stdout, "Warning: element %s not supported \n", gf_node_get_class_name((GF_Node *)elt)); child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D); gf_node_register(child, node); //gf_node_list_add_child(&((GF_ParentNode*)node)->children, child); node = child; child = NULL; converter->bifs_parent = node; } break; } if (id_string) gf_node_set_id(converter->bifs_parent, gf_sg_get_next_available_node_id(converter->bifs_sg), NULL);//gf_node_get_name((GF_Node *)elt)); } fprintf(stdout, "\t%s\n", converter->bifs_parent ? gf_node_get_class_name(converter->bifs_parent) : "none"); }
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 GF_Err TTD_AttachStream(GF_BaseDecoder *plug, GF_ESD *esd) { TTDPriv *priv = (TTDPriv *)plug->privateStack; GF_Err e; GF_Node *root, *n1, *n2; const char *opt; /*no scalable, no upstream*/ if (priv->nb_streams || esd->decoderConfig->upstream) return GF_NOT_SUPPORTED; if (!esd->decoderConfig->decoderSpecificInfo || !esd->decoderConfig->decoderSpecificInfo->data) return GF_NON_COMPLIANT_BITSTREAM; priv->cfg = (GF_TextConfig *) gf_odf_desc_new(GF_ODF_TEXT_CFG_TAG); e = gf_odf_get_text_config(esd->decoderConfig->decoderSpecificInfo, (u8) esd->decoderConfig->objectTypeIndication, priv->cfg); if (e) { gf_odf_desc_del((GF_Descriptor *) priv->cfg); priv->cfg = NULL; return e; } priv->nb_streams++; if (!priv->cfg->timescale) priv->cfg->timescale = 1000; priv->sg = gf_sg_new_subscene(priv->inlineScene->graph); root = ttd_create_node(priv, TAG_MPEG4_OrderedGroup, NULL); gf_sg_set_root_node(priv->sg, root); gf_node_register(root, NULL); /*root transform*/ priv->tr_track = (M_Transform2D *)ttd_create_node(priv, TAG_MPEG4_Transform2D, NULL); add_child((GF_Node *) priv->tr_track, root); TTD_UpdateSizeInfo(priv); /*txt track background*/ n1 = ttd_create_node(priv, TAG_MPEG4_Shape, NULL); add_child(n1, (GF_Node *) priv->tr_track); ((M_Shape *)n1)->appearance = ttd_create_node(priv, TAG_MPEG4_Appearance, NULL); gf_node_register(((M_Shape *)n1)->appearance, n1); priv->mat_track = (M_Material2D *) ttd_create_node(priv, TAG_MPEG4_Material2D, NULL); priv->mat_track->filled = 1; priv->mat_track->transparency = 1; ((M_Appearance *) ((M_Shape *)n1)->appearance)->material = (GF_Node *) priv->mat_track; gf_node_register((GF_Node *) priv->mat_track, ((M_Shape *)n1)->appearance); n2 = ttd_create_node(priv, TAG_MPEG4_Rectangle, NULL); ((M_Rectangle *)n2)->size.x = 0; ((M_Rectangle *)n2)->size.y = 0; ((M_Shape *)n1)->geometry = n2; gf_node_register(n2, n1); priv->rec_track = (M_Rectangle *)n2; /*txt box background*/ priv->tr_box = (M_Transform2D *) ttd_create_node(priv, TAG_MPEG4_Transform2D, NULL); add_child((GF_Node*) priv->tr_box, (GF_Node*)priv->tr_track); n1 = ttd_create_node(priv, TAG_MPEG4_Shape, NULL); add_child(n1, (GF_Node*)priv->tr_box); ((M_Shape *)n1)->appearance = ttd_create_node(priv, TAG_MPEG4_Appearance, NULL); gf_node_register(((M_Shape *)n1)->appearance, n1); priv->mat_box = (M_Material2D *) ttd_create_node(priv, TAG_MPEG4_Material2D, NULL); priv->mat_box->filled = 1; priv->mat_box->transparency = 1; ((M_Appearance *) ((M_Shape *)n1)->appearance)->material = (GF_Node *)priv->mat_box; gf_node_register((GF_Node *)priv->mat_box, ((M_Shape *)n1)->appearance); priv->rec_box = (M_Rectangle *) ttd_create_node(priv, TAG_MPEG4_Rectangle, NULL); priv->rec_box->size.x = 0; priv->rec_box->size.y = 0; ((M_Shape *)n1)->geometry = (GF_Node *) priv->rec_box; gf_node_register((GF_Node *) priv->rec_box, n1); priv->dlist = (M_Layer2D *) ttd_create_node(priv, TAG_MPEG4_Layer2D, NULL); priv->dlist->size.x = priv->cfg->text_width; priv->dlist->size.y = priv->cfg->text_height; add_child((GF_Node *)priv->dlist, (GF_Node *)priv->tr_box); priv->blink_nodes = gf_list_new(); priv->ts_blink = (M_TimeSensor *) ttd_create_node(priv, TAG_MPEG4_TimeSensor, "TimerBlink"); priv->ts_blink->cycleInterval = 0.25; priv->ts_blink->startTime = 0.0; priv->ts_blink->loop = 1; priv->process_blink = (M_ScalarInterpolator *) ttd_create_node(priv, TAG_MPEG4_ScalarInterpolator, NULL); /*override set_fraction*/ priv->process_blink->on_set_fraction = ttd_set_blink_fraction; gf_node_set_private((GF_Node *) priv->process_blink, priv); /*route from fraction_changed to set_fraction*/ gf_sg_route_new(priv->sg, (GF_Node *) priv->ts_blink, 6, (GF_Node *) priv->process_blink, 0); priv->ts_scroll = (M_TimeSensor *) ttd_create_node(priv, TAG_MPEG4_TimeSensor, "TimerScroll"); priv->ts_scroll->cycleInterval = 0; priv->ts_scroll->startTime = -1; priv->ts_scroll->loop = 0; priv->process_scroll = (M_ScalarInterpolator *) ttd_create_node(priv, TAG_MPEG4_ScalarInterpolator, NULL); /*override set_fraction*/ priv->process_scroll->on_set_fraction = ttd_set_scroll_fraction; gf_node_set_private((GF_Node *) priv->process_scroll, priv); /*route from fraction_changed to set_fraction*/ gf_sg_route_new(priv->sg, (GF_Node *) priv->ts_scroll, 6, (GF_Node *) priv->process_scroll, 0); gf_node_register((GF_Node *) priv->ts_blink, NULL); gf_node_register((GF_Node *) priv->process_blink, NULL); gf_node_register((GF_Node *) priv->ts_scroll, NULL); gf_node_register((GF_Node *) priv->process_scroll, NULL); /*option setup*/ opt = gf_modules_get_option((GF_BaseInterface *)plug, "StreamingText", "UseTexturing"); priv->use_texture = (opt && !strcmp(opt, "yes")) ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "StreamingText", "OutlineText"); priv->outline = (opt && !strcmp(opt, "yes")) ? 1 : 0; return e; }