void gf_storage_save(M_Storage *storage) { char szID[20]; u32 i; GF_Config *cfg = storage_get_cfg(storage); char *section = storage_get_section(storage); if (!cfg || !section) return; gf_cfg_del_section(cfg, section); if (storage->expireAfter) { u32 sec, frac; char szNTP[100]; gf_net_get_ntp(&sec, &frac); sec += storage->expireAfter; sprintf(szNTP, "%u", sec); gf_cfg_set_key(cfg, section, "expireAfterNTP", szNTP); } else { gf_cfg_set_key(cfg, section, "expireAfterNTP", "0"); } for (i=0; i<storage->storageList.count; i++) { char *val; GF_FieldInfo info; sprintf(szID, "%d", i); 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)) { val = storage_serialize_sf(info.far_ptr, info.fieldType); } else { //u32 sftype = gf_sg_vrml_get_sf_type(info.fieldType); char *slotval; void *slot; val = NULL; for (i=0; i<((GenMFField *)info.far_ptr)->count; i++) { if (gf_sg_vrml_mf_get_item(info.far_ptr, info.fieldType, &slot, i) != GF_OK) break; slotval = storage_serialize_sf(info.far_ptr, info.fieldType); if (!slotval) break; if (val) { val = gf_realloc(val, strlen(val) + 3 + strlen(slot)); } else { val = gf_malloc(3 + strlen(slot)); val[0] = 0; } strcat(val, "'"); strcat(val, slotval); strcat(val, "'"); gf_free(slot); } } if (val) { gf_cfg_set_key(cfg, section, szID, val); gf_free(val); } } gf_free(section); }
GF_Err PMF_Unquantize(PredMF *pmf, GF_FieldInfo *field) { void *slot; if (pmf->QType == QC_NORMALS) { return PMF_UnquantizeNormal(pmf, field); } if (pmf->QType == QC_ROTATION) { return PMF_UnquantizeRotation(pmf, field); } /*regular*/ gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &slot, pmf->cur_field); switch (field->fieldType) { case GF_SG_VRML_MFVEC3F: ((SFVec3f *) slot)->x = PMF_UnquantizeFloat(pmf->current_val[0], pmf->BMin.x, pmf->BMax.x, pmf->QNbBits, 0); ((SFVec3f *) slot)->y = PMF_UnquantizeFloat(pmf->current_val[1], pmf->BMin.y, pmf->BMax.y, pmf->QNbBits, 0); ((SFVec3f *) slot)->z = PMF_UnquantizeFloat(pmf->current_val[2], pmf->BMin.z, pmf->BMax.z, pmf->QNbBits, 0); break; case GF_SG_VRML_MFVEC2F: ((SFVec2f *) slot)->x = PMF_UnquantizeFloat(pmf->current_val[0], pmf->BMin.x, pmf->BMax.x, pmf->QNbBits, 0); ((SFVec2f *) slot)->y = PMF_UnquantizeFloat(pmf->current_val[1], pmf->BMin.y, pmf->BMax.y, pmf->QNbBits, 0); break; case GF_SG_VRML_MFFLOAT: *((SFFloat *) slot) = PMF_UnquantizeFloat(pmf->current_val[0], pmf->BMin.x, pmf->BMax.x, pmf->QNbBits, 0); break; case GF_SG_VRML_MFCOLOR: ((SFColor *) slot)->red = PMF_UnquantizeFloat(pmf->current_val[0], pmf->BMin.x, pmf->BMax.x, pmf->QNbBits, 0); ((SFColor *) slot)->green = PMF_UnquantizeFloat(pmf->current_val[1], pmf->BMin.y, pmf->BMax.y, pmf->QNbBits, 0); ((SFColor *) slot)->blue = PMF_UnquantizeFloat(pmf->current_val[2], pmf->BMin.z, pmf->BMax.z, pmf->QNbBits, 0); break; case GF_SG_VRML_MFINT32: switch (pmf->QType) { case QC_LINEAR_SCALAR: case QC_COORD_INDEX: *((SFInt32 *) slot) = pmf->current_val[0] + (s32) pmf->BMin.x; break; } break; } return GF_OK; }
GF_Err PMF_UnquantizeRotation(PredMF *pmf, GF_FieldInfo *field) { u32 i; void *slot; Fixed comp[4]; Fixed tang[3]; Fixed sine, delta = FIX_ONE; for (i=0; i<3; i++) { Fixed v = PMF_UnquantizeFloat(pmf->current_val[i] - (1<<(pmf->QNbBits - 1)), 0, FIX_ONE, pmf->QNbBits, 1); tang[i] = gf_tan(gf_mulfix(GF_PI / 4, v)); delta += gf_mulfix(tang[i], tang[i]); } delta = gf_divfix(pmf->direction , gf_sqrt(delta) ); comp[(pmf->orientation)%4] = delta; for (i=0; i<3; i++) comp[(pmf->orientation + i+1)%4] = gf_mulfix(tang[i], delta); gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &slot, pmf->cur_field); delta = 2 * gf_acos(comp[0]); sine = gf_sin(delta / 2); if (sine != 0) { for(i=1; i<4; i++) comp[i] = gf_divfix(comp[i], sine); ((SFRotation *)slot)->x = comp[1]; ((SFRotation *)slot)->y = comp[2]; ((SFRotation *)slot)->z = comp[3]; } else { ((SFRotation *)slot)->x = FIX_ONE; ((SFRotation *)slot)->y = 0; ((SFRotation *)slot)->z = 0; } ((SFRotation *)slot)->q = delta; return GF_OK; }
GF_Err PMF_UnquantizeNormal(PredMF *pmf, GF_FieldInfo *field) { void *slot; Fixed comp[3]; Fixed tang[2]; u32 i; Fixed delta=FIX_ONE; for (i=0; i<2; i++) { Fixed v = PMF_UnquantizeFloat(pmf->current_val[i] - (1<< (pmf->QNbBits -1) ), 0 , FIX_ONE, pmf->QNbBits, 1); tang[i]= gf_tan(gf_mulfix(GF_PI * 4, v)); delta += gf_mulfix(tang[i], tang[i]); } delta = gf_divfix(pmf->direction, gf_sqrt(delta) ); comp[(pmf->orientation) % 3] = delta; for (i=0; i<2; i++) comp[(pmf->orientation + i+1)%3] = gf_mulfix(tang[i], delta); gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &slot, pmf->cur_field); ((SFVec3f *)slot)->x = comp[0]; ((SFVec3f *)slot)->y = comp[1]; ((SFVec3f *)slot)->z = comp[2]; return GF_OK; }
GF_EXPORT Bool gf_sg_vrml_field_equal(void *dest, void *orig, u32 field_type) { u32 size, i, sf_type; void *dst_field, *orig_field; Bool changed = 0; if (!dest || !orig) return 0; switch (field_type) { case GF_SG_VRML_SFBOOL: changed = memcmp(dest, orig, sizeof(SFBool)); break; case GF_SG_VRML_SFCOLOR: if (((SFColor *)dest)->red != ((SFColor *)orig)->red) changed = 1; else if (((SFColor *)dest)->green != ((SFColor *)orig)->green) changed = 1; else if (((SFColor *)dest)->blue != ((SFColor *)orig)->blue) changed = 1; break; case GF_SG_VRML_SFFLOAT: if ( (*(SFFloat *)dest) != (*(SFFloat *)orig) ) changed = 1; break; case GF_SG_VRML_SFINT32: changed = memcmp(dest, orig, sizeof(SFInt32)); break; case GF_SG_VRML_SFROTATION: if (((SFRotation *)dest)->x != ((SFRotation *)orig)->x) changed = 1; else if (((SFRotation *)dest)->y != ((SFRotation *)orig)->y) changed = 1; else if (((SFRotation *)dest)->z != ((SFRotation *)orig)->z) changed = 1; else if (((SFRotation *)dest)->q != ((SFRotation *)orig)->q) changed = 1; break; case GF_SG_VRML_SFTIME: if ( (*(SFTime *)dest) != (*(SFTime*)orig) ) changed = 1; break; case GF_SG_VRML_SFVEC2F: if (((SFVec2f *)dest)->x != ((SFVec2f *)orig)->x) changed = 1; else if (((SFVec2f *)dest)->y != ((SFVec2f *)orig)->y) changed = 1; break; case GF_SG_VRML_SFVEC3F: if (((SFVec3f *)dest)->x != ((SFVec3f *)orig)->x) changed = 1; else if (((SFVec3f *)dest)->y != ((SFVec3f *)orig)->y) changed = 1; else if (((SFVec3f *)dest)->z != ((SFVec3f *)orig)->z) changed = 1; break; case GF_SG_VRML_SFSTRING: if ( ((SFString*)dest)->buffer && ((SFString*)orig)->buffer) { changed = strcmp(((SFString*)dest)->buffer, ((SFString*)orig)->buffer); } else { changed = ( !((SFString*)dest)->buffer && !((SFString*)orig)->buffer) ? 0 : 1; } break; case GF_SG_VRML_SFURL: if (((SFURL *)dest)->OD_ID > 0 || ((SFURL *)orig)->OD_ID > 0) { if ( ((SFURL *)orig)->OD_ID != ((SFURL *)dest)->OD_ID) changed = 1; } else { if ( ((SFURL *)orig)->url && ! ((SFURL *)dest)->url) changed = 1; else if ( ! ((SFURL *)orig)->url && ((SFURL *)dest)->url) changed = 1; else if ( strcmp( ((SFURL *)orig)->url , ((SFURL *)dest)->url) ) changed = 1; } break; case GF_SG_VRML_SFIMAGE: case GF_SG_VRML_SFATTRREF: case GF_SG_VRML_SFSCRIPT: case GF_SG_VRML_SFCOMMANDBUFFER: changed = 1; break; //MFFields case GF_SG_VRML_MFATTRREF: changed = 1; break; case GF_SG_VRML_MFBOOL: case GF_SG_VRML_MFFLOAT: case GF_SG_VRML_MFTIME: case GF_SG_VRML_MFINT32: case GF_SG_VRML_MFSTRING: case GF_SG_VRML_MFVEC3F: case GF_SG_VRML_MFVEC2F: case GF_SG_VRML_MFCOLOR: case GF_SG_VRML_MFROTATION: case GF_SG_VRML_MFIMAGE: case GF_SG_VRML_MFURL: case GF_SG_VRML_MFSCRIPT: if ( ((GenMFField *)orig)->count != ((GenMFField *)dest)->count) changed = 1; else { size = ((GenMFField *)orig)->count; sf_type = gf_sg_vrml_get_sf_type(field_type); for (i=0; i<size; i++) { gf_sg_vrml_mf_get_item(dest, field_type, &dst_field, i); gf_sg_vrml_mf_get_item(orig, field_type, &orig_field, i); if (! gf_sg_vrml_field_equal(dst_field, orig_field, sf_type) ) { changed = 1; break; } } } break; } return changed ? 0 : 1; }
GF_EXPORT void gf_sg_vrml_field_clone(void *dest, void *orig, u32 field_type, GF_SceneGraph *inScene) { u32 size, i, sf_type; void *dst_field, *orig_field; if (!dest || !orig) return; switch (field_type) { case GF_SG_VRML_SFBOOL: memcpy(dest, orig, sizeof(SFBool)); break; case GF_SG_VRML_SFCOLOR: memcpy(dest, orig, sizeof(SFColor)); break; case GF_SG_VRML_SFFLOAT: memcpy(dest, orig, sizeof(SFFloat)); break; case GF_SG_VRML_SFINT32: memcpy(dest, orig, sizeof(SFInt32)); break; case GF_SG_VRML_SFROTATION: memcpy(dest, orig, sizeof(SFRotation)); break; case GF_SG_VRML_SFTIME: memcpy(dest, orig, sizeof(SFTime)); break; case GF_SG_VRML_SFVEC2F: memcpy(dest, orig, sizeof(SFVec2f)); break; case GF_SG_VRML_SFVEC3F: memcpy(dest, orig, sizeof(SFVec3f)); break; case GF_SG_VRML_SFATTRREF: memcpy(dest, orig, sizeof(SFAttrRef)); break; case GF_SG_VRML_SFSTRING: if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer); if ( ((SFString*)orig)->buffer ) ((SFString*)dest)->buffer = gf_strdup(((SFString*)orig)->buffer); else ((SFString*)dest)->buffer = NULL; break; case GF_SG_VRML_SFURL: if ( ((SFURL *)dest)->url ) gf_free( ((SFURL *)dest)->url ); ((SFURL *)dest)->OD_ID = ((SFURL *)orig)->OD_ID; if (((SFURL *)orig)->url) ((SFURL *)dest)->url = gf_strdup(((SFURL *)orig)->url); else ((SFURL *)dest)->url = NULL; break; case GF_SG_VRML_SFIMAGE: if (((SFImage *)dest)->pixels) gf_free(((SFImage *)dest)->pixels); ((SFImage *)dest)->width = ((SFImage *)orig)->width; ((SFImage *)dest)->height = ((SFImage *)orig)->height; ((SFImage *)dest)->numComponents = ((SFImage *)orig)->numComponents; size = ((SFImage *)dest)->width * ((SFImage *)dest)->height * ((SFImage *)dest)->numComponents; ((SFImage *)dest)->pixels = (u8*)gf_malloc(sizeof(char)*size); memcpy(((SFImage *)dest)->pixels, ((SFImage *)orig)->pixels, sizeof(char)*size); break; case GF_SG_VRML_SFCOMMANDBUFFER: { SFCommandBuffer *cb_dst = (SFCommandBuffer *)dest; SFCommandBuffer *cb_src = (SFCommandBuffer *)orig; cb_dst->bufferSize = cb_src->bufferSize; if (cb_dst->bufferSize && !gf_list_count(cb_src->commandList) ) { cb_dst->buffer = (u8*)gf_realloc(cb_dst->buffer, sizeof(char)*cb_dst->bufferSize); memcpy(cb_dst->buffer, cb_src->buffer, sizeof(char)*cb_src->bufferSize); } else { u32 j, c2; if (cb_dst->buffer) gf_free(cb_dst->buffer); cb_dst->buffer = NULL; /*clone command list*/ c2 = gf_list_count(cb_src->commandList); for (j=0; j<c2;j++) { GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, j); GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, inScene, 0); gf_list_add(cb_dst->commandList, new_com); } } } break; /*simply copy text string*/ case GF_SG_VRML_SFSCRIPT: if (((SFScript*)dest)->script_text) gf_free(((SFScript*)dest)->script_text); ((SFScript*)dest)->script_text = NULL; if ( ((SFScript*)orig)->script_text) ((SFScript *)dest)->script_text = (char *)gf_strdup( (char*) ((SFScript*)orig)->script_text ); break; //simple MFFields, do a memcpy case GF_SG_VRML_MFBOOL: case GF_SG_VRML_MFFLOAT: case GF_SG_VRML_MFTIME: case GF_SG_VRML_MFINT32: case GF_SG_VRML_MFVEC3F: case GF_SG_VRML_MFVEC2F: case GF_SG_VRML_MFCOLOR: case GF_SG_VRML_MFROTATION: case GF_SG_VRML_MFATTRREF: size = gf_sg_vrml_get_sf_size(field_type) * ((GenMFField *)orig)->count; if (((GenMFField *)orig)->count != ((GenMFField *)dest)->count) { ((GenMFField *)dest)->array = gf_realloc(((GenMFField *)dest)->array, size); ((GenMFField *)dest)->count = ((GenMFField *)orig)->count; } memcpy(((GenMFField *)dest)->array, ((GenMFField *)orig)->array, size); break; //complex MFFields case GF_SG_VRML_MFSTRING: case GF_SG_VRML_MFIMAGE: case GF_SG_VRML_MFURL: case GF_SG_VRML_MFSCRIPT: size = ((GenMFField *)orig)->count; gf_sg_vrml_mf_reset(dest, field_type); gf_sg_vrml_mf_alloc(dest, field_type, size); sf_type = gf_sg_vrml_get_sf_type(field_type); //duplicate all items for (i=0; i<size; i++) { gf_sg_vrml_mf_get_item(dest, field_type, &dst_field, i); gf_sg_vrml_mf_get_item(orig, field_type, &orig_field, i); gf_sg_vrml_field_copy(dst_field, orig_field, sf_type); } break; } }
/*special cloning with type-casting from SF/MF strings to URL conversion since proto URL doesn't exist as a field type (it's just a stupid encoding trick) */ void VRML_FieldCopyCast(void *dest, u32 dst_field_type, void *orig, u32 ori_field_type) { SFURL *url; char tmp[50]; u32 size, i, sf_type_ori, sf_type_dst; void *dst_field, *orig_field; if (!dest || !orig) return; switch (dst_field_type) { case GF_SG_VRML_SFSTRING: if (ori_field_type == GF_SG_VRML_SFURL) { url = ((SFURL *)orig); if (url->OD_ID>0) { sprintf(tmp, "%d", url->OD_ID); if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer); ((SFString*)dest)->buffer = gf_strdup(tmp); } else { if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer); ((SFString*)dest)->buffer = url->url ? gf_strdup(url->url) : NULL; } } /*for SFString to MFString cast*/ else if (ori_field_type == GF_SG_VRML_SFSTRING) { if ( ((SFString*)dest)->buffer) gf_free(((SFString*)dest)->buffer); ((SFString*)dest)->buffer = ((SFString*)orig)->buffer ? gf_strdup(((SFString*)orig)->buffer) : NULL; } return; case GF_SG_VRML_SFURL: if (ori_field_type != GF_SG_VRML_SFSTRING) return; url = ((SFURL *)dest); url->OD_ID = 0; if (url->url) gf_free(url->url); if ( ((SFString*)orig)->buffer) url->url = gf_strdup(((SFString*)orig)->buffer); else url->url = NULL; return; case GF_SG_VRML_MFSTRING: case GF_SG_VRML_MFURL: break; default: return; } sf_type_dst = gf_sg_vrml_get_sf_type(dst_field_type); if (gf_sg_vrml_is_sf_field(ori_field_type)) { size = 1; gf_sg_vrml_mf_alloc(dest, dst_field_type, size); gf_sg_vrml_mf_get_item(dest, dst_field_type, &dst_field, 0); VRML_FieldCopyCast(dst_field, sf_type_dst, orig, ori_field_type); return; } size = ((GenMFField *)orig)->count; if (size != ((GenMFField *)dest)->count) gf_sg_vrml_mf_alloc(dest, dst_field_type, size); sf_type_ori = gf_sg_vrml_get_sf_type(ori_field_type); //duplicate all items for (i=0; i<size; i++) { gf_sg_vrml_mf_get_item(dest, dst_field_type, &dst_field, i); gf_sg_vrml_mf_get_item(orig, ori_field_type, &orig_field, i); VRML_FieldCopyCast(dst_field, sf_type_dst, orig_field, sf_type_ori); } return; }
GF_Err BD_DecMFFieldVec(GF_BifsDecoder * codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field, Bool is_mem_com) { GF_Err e; u32 NbBits, nbFields; u32 i; GF_ChildNodeItem *last; u8 qp_local, qp_on, initial_qp; GF_Node *new_node; GF_FieldInfo sffield; memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; initial_qp = qp_local = qp_on = 0; //vector description - alloc the MF size before NbBits = gf_bs_read_int(bs, 5); nbFields = gf_bs_read_int(bs, NbBits); if (codec->ActiveQP) { initial_qp = 1; /*this is for QP 14*/ gf_bifs_dec_qp14_set_length(codec, nbFields); } if (field->fieldType != GF_SG_VRML_MFNODE) { e = gf_sg_vrml_mf_alloc(field->far_ptr, field->fieldType, nbFields); if (e) return e; for (i=0; i<nbFields; i++) { e = gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, & sffield.far_ptr, i); if (e) return e; e = gf_bifs_dec_sf_field(codec, bs, node, &sffield, 0); } } else { last = NULL; for (i=0; i<nbFields; i++) { new_node = gf_bifs_dec_node(codec, bs, field->NDTtype); if (new_node) { e = gf_node_register(new_node, is_mem_com ? NULL : node); if (e) return e; if (node) { /*special case for QP, register as the current QP*/ if (gf_node_get_tag(new_node) == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)new_node)->isLocal; /*we have a QP in the same scope, remove previous NB: we assume this is the right behaviour, the spec doesn't say whether QP is cumulative or not*/ if (qp_on) gf_bifs_dec_qp_remove(codec, 0); e = gf_bifs_dec_qp_set(codec, new_node); if (e) return e; qp_on = 1; if (qp_local) qp_local = 2; if (codec->force_keep_qp) { e = gf_node_list_add_child_last(field->far_ptr, new_node, &last); } else { gf_node_register(new_node, NULL); gf_node_unregister(new_node, node); } } else { e = gf_node_list_add_child_last(field->far_ptr, new_node, &last); } } /*proto coding*/ else if (codec->pCurrentProto) { /*TO DO: what happens if this is a QP node on the interface ?*/ e = gf_node_list_add_child_last( (GF_ChildNodeItem **)field->far_ptr, new_node, &last); } } else { return codec->LastError ? codec->LastError : GF_NON_COMPLIANT_BITSTREAM; } } /*according to the spec, the QP applies to the current node itself, not just children. If IsLocal is TRUE remove the node*/ if (qp_on && qp_local) { if (qp_local == 2) { qp_local = 1; } else { //ask to get rid of QP and reactivate if we had a QP when entering the node gf_bifs_dec_qp_remove(codec, initial_qp); qp_local = 0; } } } /*finally delete the QP if any (local or not) as we get out of this node*/ if (qp_on) gf_bifs_dec_qp_remove(codec, 1); return GF_OK; }
GF_Err gf_bifs_enc_mf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) { GF_ChildNodeItem *list = NULL; GF_Err e; u32 nbBits, qp_local; Bool use_list, qp_on, initial_qp; u32 nbF, i; GF_FieldInfo sffield; nbF = 0; if (field->fieldType != GF_SG_VRML_MFNODE) { nbF = field->far_ptr ? ((GenMFField *)field->far_ptr)->count : 0; if (!nbF && (field->fieldType == GF_SG_VRML_MFSCRIPT)) nbF = 1; } else if (field->far_ptr) { list = *((GF_ChildNodeItem **)field->far_ptr); nbF = gf_node_list_get_count(list); } /*reserved*/ GF_BIFS_WRITE_INT(codec, bs, 0, 1, "reserved", NULL); if (!nbF) { /*is list*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*end flag*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); return GF_OK; } /*do we work in list or vector*/ use_list = GF_FALSE; nbBits = gf_get_bit_size(nbF); if (nbBits + 5 > nbF + 1) use_list = GF_TRUE; GF_BIFS_WRITE_INT(codec, bs, use_list, 1, "isList", NULL); if (!use_list) { GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, nbF, nbBits, "length", NULL); } memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; initial_qp = qp_on = GF_FALSE; qp_local = 0; initial_qp = codec->ActiveQP ? GF_TRUE : GF_FALSE; for (i=0; i<nbF; i++) { if (use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL); if (field->fieldType != GF_SG_VRML_MFNODE) { gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &sffield.far_ptr, i); e = gf_bifs_enc_sf_field(codec, bs, node, &sffield); } else { assert(list); e = gf_bifs_enc_node(codec, list->node, field->NDTtype, bs, node); /*activate QP*/ if (list->node->sgprivate->tag == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)list->node)->isLocal; if (qp_on) gf_bifs_enc_qp_remove(codec, GF_FALSE); e = gf_bifs_enc_qp_set(codec, list->node); if (e) return e; qp_on = GF_TRUE; if (qp_local) qp_local = 2; } list = list->next; } if (e) return e; if (qp_on && qp_local) { if (qp_local == 2) qp_local -= 1; else { gf_bifs_enc_qp_remove(codec, initial_qp); qp_local = qp_on = GF_FALSE; } } } if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); if (qp_on) gf_bifs_enc_qp_remove(codec, initial_qp); /*for QP14*/ gf_bifs_enc_qp14_set_length(codec, nbF); return GF_OK; }
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; }
GF_EXPORT void gf_sg_vrml_field_copy(void *dest, void *orig, u32 field_type) { u32 size, i, sf_type; void *dst_field, *orig_field; if (!dest || !orig) return; switch (field_type) { case GF_SG_VRML_SFBOOL: memcpy(dest, orig, sizeof(SFBool)); break; case GF_SG_VRML_SFCOLOR: memcpy(dest, orig, sizeof(SFColor)); break; case GF_SG_VRML_SFFLOAT: memcpy(dest, orig, sizeof(SFFloat)); break; case GF_SG_VRML_SFINT32: memcpy(dest, orig, sizeof(SFInt32)); break; case GF_SG_VRML_SFROTATION: memcpy(dest, orig, sizeof(SFRotation)); break; case GF_SG_VRML_SFTIME: memcpy(dest, orig, sizeof(SFTime)); break; case GF_SG_VRML_SFVEC2F: memcpy(dest, orig, sizeof(SFVec2f)); break; case GF_SG_VRML_SFVEC3F: memcpy(dest, orig, sizeof(SFVec3f)); break; case GF_SG_VRML_SFSTRING: if ( ((SFString*)dest)->buffer) free(((SFString*)dest)->buffer); if ( ((SFString*)orig)->buffer ) ((SFString*)dest)->buffer = strdup(((SFString*)orig)->buffer); else ((SFString*)dest)->buffer = NULL; break; case GF_SG_VRML_SFURL: if ( ((SFURL *)dest)->url ) free( ((SFURL *)dest)->url ); ((SFURL *)dest)->OD_ID = ((SFURL *)orig)->OD_ID; if (((SFURL *)orig)->url) ((SFURL *)dest)->url = strdup(((SFURL *)orig)->url); else ((SFURL *)dest)->url = NULL; break; case GF_SG_VRML_SFIMAGE: if (((SFImage *)dest)->pixels) free(((SFImage *)dest)->pixels); ((SFImage *)dest)->width = ((SFImage *)orig)->width; ((SFImage *)dest)->height = ((SFImage *)orig)->height; ((SFImage *)dest)->numComponents = ((SFImage *)orig)->numComponents; size = ((SFImage *)dest)->width * ((SFImage *)dest)->height * ((SFImage *)dest)->numComponents; ((SFImage *)dest)->pixels = (u8*)malloc(sizeof(char)*size); memcpy(((SFImage *)dest)->pixels, ((SFImage *)orig)->pixels, sizeof(char)*size); break; case GF_SG_VRML_SFCOMMANDBUFFER: gf_sg_sfcommand_del( *(SFCommandBuffer *)dest); ((SFCommandBuffer *)dest)->commandList = gf_list_new(); ((SFCommandBuffer *)dest)->bufferSize = ((SFCommandBuffer *)orig)->bufferSize; if (((SFCommandBuffer *)dest)->bufferSize) { ((SFCommandBuffer *)dest)->buffer = (u8*)malloc(sizeof(char)*((SFCommandBuffer *)orig)->bufferSize); memcpy(((SFCommandBuffer *)dest)->buffer, ((SFCommandBuffer *)orig)->buffer, sizeof(char)*((SFCommandBuffer *)orig)->bufferSize); } else { ((SFCommandBuffer *)dest)->buffer = NULL; } break; /*simply copy text string*/ case GF_SG_VRML_SFSCRIPT: if (((SFScript*)dest)->script_text) free(((SFScript*)dest)->script_text); ((SFScript*)dest)->script_text = NULL; if ( ((SFScript*)orig)->script_text) ((SFScript *)dest)->script_text = (u8*)strdup( (char*) ((SFScript*)orig)->script_text ); break; //MFFields case GF_SG_VRML_MFBOOL: case GF_SG_VRML_MFFLOAT: case GF_SG_VRML_MFTIME: case GF_SG_VRML_MFINT32: case GF_SG_VRML_MFSTRING: case GF_SG_VRML_MFVEC3F: case GF_SG_VRML_MFVEC2F: case GF_SG_VRML_MFCOLOR: case GF_SG_VRML_MFROTATION: case GF_SG_VRML_MFIMAGE: case GF_SG_VRML_MFURL: case GF_SG_VRML_MFSCRIPT: size = ((GenMFField *)orig)->count; gf_sg_vrml_mf_reset(dest, field_type); gf_sg_vrml_mf_alloc(dest, field_type, size); sf_type = gf_sg_vrml_get_sf_type(field_type); //duplicate all items for (i=0; i<size; i++) { gf_sg_vrml_mf_get_item(dest, field_type, &dst_field, i); gf_sg_vrml_mf_get_item(orig, field_type, &orig_field, i); gf_sg_vrml_field_copy(dst_field, orig_field, sf_type); } break; } }