GF_Command *gf_sg_command_clone(GF_Command *com, GF_SceneGraph *inGraph) { u32 i, count; GF_Command *dest; if (com->tag==GF_SG_SCENE_REPLACE) return NULL; /*FIXME - to do*/ if (gf_list_count(com->new_proto_list)) return NULL; dest = gf_sg_command_new(inGraph, com->tag); /*node the command applies to - may be NULL*/ dest->node = gf_node_clone(inGraph, com->node, NULL); /*route insert, replace and delete*/ dest->RouteID = com->RouteID; if (com->def_name) dest->def_name = strdup(com->def_name); dest->fromNodeID = com->fromNodeID; dest->fromFieldIndex = com->fromFieldIndex; dest->toNodeID = com->toNodeID; dest->toFieldIndex = com->toFieldIndex; dest->del_proto_list_size = com->del_proto_list_size; if (com->del_proto_list_size) { dest->del_proto_list = (u32*)malloc(sizeof(u32) * com->del_proto_list_size); memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size); } count = gf_list_count(com->command_fields); for (i=0; i<count; i++) { GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i); GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest); fd->fieldIndex = fo->fieldIndex; fd->fieldType = fo->fieldType; fd->pos = fo->pos; if (fo->field_ptr) { fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType); gf_sg_vrml_field_copy(fd->field_ptr, fo->field_ptr, fo->fieldType); } if (fo->new_node) { fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node); fd->field_ptr = &fd->new_node; } if (fo->node_list) { GF_ChildNodeItem *child, *cur, *prev; prev = NULL; child = fo->node_list; while (child) { cur = (GF_ChildNodeItem*) malloc(sizeof(GF_ChildNodeItem)); cur->node = gf_node_clone(inGraph, child->node, dest->node); cur->next = NULL; if (prev) prev->next = cur; else fd->node_list = cur; prev = cur; child = child->next; } fd->field_ptr = &fd->node_list; } } return dest; }
GF_Node *gf_xml_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *cloned_parent, char *inst_id, Bool deep) { GF_DOMAttribute *att; GF_Node *clone = gf_node_new(inScene, orig->sgprivate->tag); if (!clone) return NULL; if (orig->sgprivate->tag == TAG_DOMText) { GF_DOMText *n_src,*n_dst; n_src = (GF_DOMText *)orig; n_dst = (GF_DOMText *)clone; n_dst->type = n_src->type; n_dst->textContent = gf_strdup(n_src->textContent); } else { if (orig->sgprivate->tag == TAG_DOMFullNode) { GF_DOMFullNode *n_src,*n_dst; n_src = (GF_DOMFullNode *)orig; n_dst = (GF_DOMFullNode *)clone; n_dst->ns = n_src->ns; n_dst->name = gf_strdup(n_dst->name); } att = ((GF_DOMNode *)orig)->attributes; while (att) { GF_FieldInfo dst, src; /*create by name*/ if (att->tag==TAG_DOM_ATT_any) { gf_node_get_attribute_by_name(clone, ((GF_DOMFullAttribute*)att)->name, 0, 1, 0, &dst); } else { gf_node_get_attribute_by_tag(clone, att->tag, 1, 0, &dst); } src.far_ptr = att->data; src.fieldType = att->data_type; src.fieldIndex = att->tag; gf_svg_attributes_copy(&dst, &src, 0); if (att->tag==TAG_XLINK_ATT_href) { XMLRI *iri = (XMLRI *)att->data; if (iri->target == gf_node_get_parent(orig, 0)) { ((XMLRI *)dst.far_ptr)->target = cloned_parent; } else { ((XMLRI *)dst.far_ptr)->target = NULL; } } att = att->next; } } if (cloned_parent) { gf_node_list_add_child( & ((GF_ParentNode*)cloned_parent)->children, clone); gf_node_register(clone, cloned_parent); /*TO CLARIFY: can we init the node right now or should we wait for insertion in the scene tree ?*/ gf_node_init(clone); } if (deep) { GF_ChildNodeItem *child = ((GF_ParentNode *)orig)->children; while (child) { gf_node_clone(inScene, child->node, clone, inst_id, 1); child = child->next; } } return clone; }
GF_Command *gf_sg_vrml_command_clone(GF_Command *com, GF_SceneGraph *inGraph, Bool force_clone) { u32 i, count; GF_Command *dest; /*FIXME - to do*/ if (gf_list_count(com->new_proto_list)) return NULL; dest = gf_sg_command_new(inGraph, com->tag); if (com->in_scene!=inGraph) force_clone = 1; /*node the command applies to - may be NULL*/ if (force_clone) { dest->node = gf_node_clone(inGraph, com->node, NULL, "", 0); } else { dest->node = com->node; gf_node_register(dest->node, NULL); } /*route insert, replace and delete*/ dest->RouteID = com->RouteID; if (com->def_name) dest->def_name = gf_strdup(com->def_name); dest->fromNodeID = com->fromNodeID; dest->fromFieldIndex = com->fromFieldIndex; dest->toNodeID = com->toNodeID; dest->toFieldIndex = com->toFieldIndex; dest->send_event_integer = com->send_event_integer; dest->send_event_x = com->send_event_x; dest->send_event_y = com->send_event_y; if (com->send_event_string) dest->send_event_string = gf_strdup(com->send_event_string); dest->del_proto_list_size = com->del_proto_list_size; if (com->del_proto_list_size) { dest->del_proto_list = (u32*)gf_malloc(sizeof(u32) * com->del_proto_list_size); memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size); } count = gf_list_count(com->command_fields); for (i=0; i<count; i++) { GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i); GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest); fd->fieldIndex = fo->fieldIndex; fd->fieldType = fo->fieldType; fd->pos = fo->pos; /*FIXME - this can also be LASeR commands, not supported for now*/ if (fo->field_ptr) { fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType); gf_sg_vrml_field_clone(fd->field_ptr, fo->field_ptr, fo->fieldType, dest->in_scene); } if (fo->new_node) { if (force_clone) { fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node, "", 0); } else { fd->new_node = fo->new_node; gf_node_register(fd->new_node, NULL); } fd->field_ptr = &fd->new_node; } if (fo->node_list) { GF_ChildNodeItem *child, *cur, *prev; prev = NULL; child = fo->node_list; while (child) { cur = (GF_ChildNodeItem*) gf_malloc(sizeof(GF_ChildNodeItem)); if (force_clone) { cur->node = gf_node_clone(inGraph, child->node, dest->node, "", 0); } else { cur->node = child->node; gf_node_register(cur->node, NULL); } cur->next = NULL; if (prev) prev->next = cur; else fd->node_list = cur; prev = cur; child = child->next; } fd->field_ptr = &fd->node_list; } } return dest; }
static void TTD_NewTextChunk(TTDPriv *priv, GF_TextSampleDescriptor *tsd, M_Form *form, u16 *utf16_txt, TTDTextChunk *tc) { GF_Node *txt_model, *n2, *txt_material; M_Text *text; M_FontStyle *fs; char *fontName; char szStyle[1024]; u32 fontSize, styleFlags, color, i, start_char; if (!tc->srec) { fontName = TTD_FindFont(tsd, tsd->default_style.fontID); fontSize = tsd->default_style.font_size; styleFlags = tsd->default_style.style_flags; color = tsd->default_style.text_color; } else { fontName = TTD_FindFont(tsd, tc->srec->fontID); fontSize = tc->srec->font_size; styleFlags = tc->srec->style_flags; color = tc->srec->text_color; } /*create base model for text node. It will then be cloned for each text item*/ txt_model = ttd_create_node(priv, TAG_MPEG4_Shape, NULL); gf_node_register(txt_model, NULL); n2 = ttd_create_node(priv, TAG_MPEG4_Appearance, NULL); ((M_Shape *)txt_model)->appearance = n2; gf_node_register(n2, txt_model); txt_material = ttd_create_node(priv, TAG_MPEG4_Material2D, NULL); ((M_Appearance *)n2)->material = txt_material; gf_node_register(txt_material, n2); ((M_Material2D *)txt_material)->filled = 1; ((M_Material2D *)txt_material)->transparency = FIX_ONE - INT2FIX((color>>24) & 0xFF) / 255; ((M_Material2D *)txt_material)->emissiveColor.red = INT2FIX((color>>16) & 0xFF) / 255; ((M_Material2D *)txt_material)->emissiveColor.green = INT2FIX((color>>8) & 0xFF) / 255; ((M_Material2D *)txt_material)->emissiveColor.blue = INT2FIX((color) & 0xFF) / 255; /*force 0 lineWidth if blinking (the stupid MPEG-4 default values once again..)*/ if (tc->has_blink) { ((M_Material2D *)txt_material)->lineProps = ttd_create_node(priv, TAG_MPEG4_LineProperties, NULL); ((M_LineProperties *)((M_Material2D *)txt_material)->lineProps)->width = 0; gf_node_register(((M_Material2D *)txt_material)->lineProps, txt_material); } n2 = ttd_create_node(priv, TAG_MPEG4_Text, NULL); ((M_Shape *)txt_model)->geometry = n2; gf_node_register(n2, txt_model); text = (M_Text *) n2; fs = (M_FontStyle *) ttd_create_node(priv, TAG_MPEG4_FontStyle, NULL); gf_free(fs->family.vals[0]); /*translate default fonts to MPEG-4/VRML names*/ if (!stricmp(fontName, "Serif")) fs->family.vals[0] = gf_strdup("SERIF"); else if (!stricmp(fontName, "Sans-Serif")) fs->family.vals[0] = gf_strdup("SANS"); else if (!stricmp(fontName, "Monospace")) fs->family.vals[0] = gf_strdup("TYPEWRITER"); else fs->family.vals[0] = gf_strdup(fontName); fs->size = INT2FIX(fontSize); gf_free(fs->style.buffer); strcpy(szStyle, ""); if (styleFlags & GF_TXT_STYLE_BOLD) { if (styleFlags & GF_TXT_STYLE_ITALIC) strcpy(szStyle, "BOLDITALIC"); else strcpy(szStyle, "BOLD"); } else if (styleFlags & GF_TXT_STYLE_ITALIC) strcat(szStyle, "ITALIC"); if (!strlen(szStyle)) strcpy(szStyle, "PLAIN"); /*also underline for URLs*/ if ((styleFlags & GF_TXT_STYLE_UNDERLINED) || (tc->hlink && tc->hlink->URL)) strcat(szStyle, " UNDERLINED"); if (tc->is_hilight) { if (tc->hilight_col) { char szTxt[50]; sprintf(szTxt, " HIGHLIGHT#%x", tc->hilight_col); strcat(szStyle, szTxt); } else { strcat(szStyle, " HIGHLIGHT#RV"); } } /*a better way would be to draw the entire text box in a composite texture & bitmap but we can't really rely on text box size (in MP4Box, it actually defaults to the entire video area) and drawing a too large texture & bitmap could slow down rendering*/ if (priv->use_texture) strcat(szStyle, " TEXTURED"); if (priv->outline) strcat(szStyle, " OUTLINED"); fs->style.buffer = gf_strdup(szStyle); fs->horizontal = (tsd->displayFlags & GF_TXT_VERTICAL) ? 0 : 1; text->fontStyle = (GF_Node *) fs; gf_node_register((GF_Node *)fs, (GF_Node *)text); gf_sg_vrml_mf_reset(&text->string, GF_SG_VRML_MFSTRING); if (tc->hlink && tc->hlink->URL) { SFURL *s; M_Anchor *anc = (M_Anchor *) ttd_create_node(priv, TAG_MPEG4_Anchor, NULL); gf_sg_vrml_mf_append(&anc->url, GF_SG_VRML_MFURL, (void **) &s); s->OD_ID = 0; s->url = gf_strdup(tc->hlink->URL); if (tc->hlink->URL_hint) anc->description.buffer = gf_strdup(tc->hlink->URL_hint); gf_node_list_add_child(& anc->children, txt_model); gf_node_register(txt_model, (GF_Node *)anc); txt_model = (GF_Node *)anc; gf_node_register((GF_Node *)anc, NULL); } start_char = tc->start_char; for (i=tc->start_char; i<tc->end_char; i++) { Bool new_line = 0; if ((utf16_txt[i] == '\n') || (utf16_txt[i] == '\r') || (utf16_txt[i] == 0x85) || (utf16_txt[i] == 0x2028) || (utf16_txt[i] == 0x2029)) new_line = 1; if (new_line || (i+1==tc->end_char) ) { SFString *st; if (i+1==tc->end_char) i++; if (i!=start_char) { char szLine[5000]; u32 len; s16 wsChunk[5000], *sp; /*spliting lines, duplicate node*/ n2 = gf_node_clone(priv->sg, txt_model, NULL, "", 1); if (tc->hlink && tc->hlink->URL) { GF_Node *t = ((M_Anchor *)n2)->children->node; text = (M_Text *) ((M_Shape *)t)->geometry; txt_material = ((M_Appearance *) ((M_Shape *)t)->appearance)->material; } else { text = (M_Text *) ((M_Shape *)n2)->geometry; txt_material = ((M_Appearance *) ((M_Shape *)n2)->appearance)->material; } gf_sg_vrml_mf_reset(&text->string, GF_SG_VRML_MFSTRING); gf_node_list_add_child( &form->children, n2); gf_node_register(n2, (GF_Node *) form); ttd_add_item(form); /*clone node always register by default*/ gf_node_unregister(n2, NULL); if (tc->has_blink && txt_material) gf_list_add(priv->blink_nodes, txt_material); memcpy(wsChunk, &utf16_txt[start_char], sizeof(s16)*(i-start_char)); wsChunk[i-start_char] = 0; sp = &wsChunk[0]; len = gf_utf8_wcstombs(szLine, 5000, (const unsigned short **) &sp); szLine[len] = 0; gf_sg_vrml_mf_append(&text->string, GF_SG_VRML_MFSTRING, (void **) &st); st->buffer = gf_strdup(szLine); } start_char = i+1; if (new_line) { ttd_add_line(form); if ((utf16_txt[i]=='\r') && (utf16_txt[i+1]=='\n')) i++; } } } gf_node_unregister(txt_model, NULL); return; }