static GF_Err lsr_read_add_replace_insert()

in src/laser/lsr_dec.c [4711:5158]


static GF_Err lsr_read_add_replace_insert(GF_LASeRCodec *lsr, GF_List *com_list, u32 com_type)
{
	GF_FieldInfo info;
	GF_Node *n, *operandNode, *new_node;
	GF_Command *com;
	GF_CommandField *field;
	s32 idx, att_type, op_att_type;
	u32 type, idref, op_idref = 0;

	operandNode = NULL;
	att_type = op_att_type = -1;

	att_type = lsr_get_attribute_name(lsr);

	idx = -1;
	if (com_type) {
		GF_LSR_READ_INT(lsr, type, 1, "has_index");
		if (type) idx = lsr_read_vluimsbf5(lsr, "index");
	}
	if (com_type!=3) {
		GF_LSR_READ_INT(lsr, type, 1, "has_operandAttribute");
		if (type) GF_LSR_READ_INT(lsr, op_att_type, 8, "attributeName");
		GF_LSR_READ_INT(lsr, type, 1, "has_operandElementId");
		if (type) {
			op_idref = lsr_read_codec_IDREF_command(lsr, "operandElementId");
			operandNode = gf_sg_find_node(lsr->sg, op_idref);
			if (!operandNode)
				return GF_NON_COMPLIANT_BITSTREAM;
		}
	}
	idref = lsr_read_codec_IDREF_command(lsr, "ref");

	n = gf_sg_find_node(lsr->sg, idref);
	if (!n) {
		if (!com_list) {
			return GF_NON_COMPLIANT_BITSTREAM;
		}
	}

	GF_LSR_READ_INT(lsr, type, 1, "has_value");
	if (type) {
		/*node or node-list replacement*/
		if (att_type==-2) {
			lsr_read_byte_align_string(lsr, NULL, "anyXML");
		}
		else if (att_type<0) {
			GF_Node *new_node;
			if (!com_type)
				return GF_NON_COMPLIANT_BITSTREAM;
			GF_LSR_READ_INT(lsr, type, 1, "isInherit");
			if (type)
				return GF_NON_COMPLIANT_BITSTREAM;
			if (idx==-1) {
				GF_LSR_READ_INT(lsr, type, 1, "escapeFlag");
				if (type)
					return GF_NON_COMPLIANT_BITSTREAM;
			}

			new_node = lsr_read_update_content_model(lsr, (idx==-1) ? NULL : (SVG_Element *)n);
			if (com_list) {
				com = gf_sg_command_new(lsr->sg, (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE);
				gf_list_add(com_list, com);
				if (n) {
					com->node = n;
					gf_node_register(com->node, NULL);
				} else {
					com->RouteID = idref;
					gf_list_add(lsr->unresolved_commands, com);
				}
				field = gf_sg_command_field_new(com);
				field->pos = idx;
				field->new_node = new_node;
				if (new_node) gf_node_register(new_node, NULL);
			} else if (com_type==3) {
				gf_node_list_insert_child(& ((SVG_Element *)n)->children, new_node, idx);
				if (new_node) gf_node_register(new_node, n);
			} else {
				/*child replacement*/
				if (idx!=-1) {
					GF_Node *old = gf_node_list_get_child( ((SVG_Element *)n)->children, idx);
					if (old)
						gf_node_replace(old, new_node, 0);
					else {
						gf_node_list_add_child( & ((SVG_Element *)n)->children, new_node);
						if (new_node) gf_node_register(new_node, n);
					}
				} else {
					/*node replacement*/
					gf_node_replace(n, new_node, 0);
				}
			}
		}
		/*value replace/add*/
		else if (com_list) {
			u32 field_type;
			Bool text_content = 0;
			com = gf_sg_command_new(lsr->sg, (com_type==0) ? GF_SG_LSR_ADD : (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE);
			field = gf_sg_command_field_new(com);
			field->pos = idx;
			field_type = 0;
			switch (att_type) {
			/*text*/
			case LSR_UPDATE_TYPE_TEXT_CONTENT:
				text_content = 1;
				break;
			/*matrix.translation, scale or rotate*/
			case LSR_UPDATE_TYPE_SCALE:
				field->fieldType = field_type = SVG_Transform_Scale_datatype;
				field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
				break;
			case LSR_UPDATE_TYPE_ROTATE:
				field->fieldType = field_type = SVG_Transform_Rotate_datatype;
				field->fieldIndex = TAG_SVG_ATT_transform;
				break;
			case LSR_UPDATE_TYPE_TRANSLATION:
				field->fieldType = field_type = SVG_Transform_Translate_datatype;
				field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
				break;
			case LSR_UPDATE_TYPE_SVG_HEIGHT:
				field->fieldIndex = TAG_SVG_ATT_height;
				field_type = field->fieldType = SVG_Length_datatype;
				break;
			case LSR_UPDATE_TYPE_SVG_WIDTH:
				field->fieldIndex = TAG_SVG_ATT_width;
				field_type = field->fieldType = SVG_Length_datatype;
				break;
			default:
				field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
				if (field->fieldIndex == (u32)-1) {
					lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
					gf_sg_command_del(com);
					return lsr->last_error;
				}
				field_type = field->fieldType = gf_xml_get_attribute_type(field->fieldIndex);
				break;
			}
			gf_list_add(com_list, com);
			if (n) {
				com->node = n;
				gf_node_register(com->node, NULL);
			} else {
				com->RouteID = idref;
				gf_list_add(lsr->unresolved_commands, com);
			}
			if (idx==-1) {
				if (text_content) {
					GF_DOMText *text = gf_dom_new_text_node(n->sgprivate->scenegraph);
					gf_node_register((GF_Node *)text, NULL);
					lsr_read_byte_align_string(lsr, &text->textContent, "val");
					field->new_node = (GF_Node*)text;
				} else {
					field->field_ptr = gf_svg_create_attribute_value(field_type);
					lsr_read_update_value(lsr, NULL, field->fieldIndex, field->fieldType, field->field_ptr, n ? n->sgprivate->tag : 0);
				}
			} else {
				field->field_ptr = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, NULL, idx, com_type==LSR_UPDATE_INSERT, 1);
			}
		} else {
			GF_Point2D matrix_tmp;
			SVG_Point_Angle matrix_tmp_rot;
			u32 fieldIndex = 0;
			u32 field_type = 0;
			Bool text_content = 0;
			Bool is_lsr_transform = 0;
			switch (att_type) {
			/*text*/
			case LSR_UPDATE_TYPE_TEXT_CONTENT:
				text_content = 1;
				break;
			/*matrix.translation, scale or rotate*/
			case LSR_UPDATE_TYPE_SCALE:
				info.far_ptr = (void *)&matrix_tmp;
				field_type = SVG_Transform_Scale_datatype;
				is_lsr_transform = 1;
				break;
			case LSR_UPDATE_TYPE_ROTATE:
				info.far_ptr = (void *)&matrix_tmp_rot;
				field_type = SVG_Transform_Rotate_datatype;
				is_lsr_transform = 1;
				break;
			case LSR_UPDATE_TYPE_TRANSLATION:
				info.far_ptr = (void *)&matrix_tmp;
				field_type = SVG_Transform_Translate_datatype;
				is_lsr_transform = 1;
				break;
			default:
				fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
				gf_node_get_attribute_by_tag(n, fieldIndex, 1, 0, &info);
				field_type = info.fieldType;
				break;
			}
			if (is_lsr_transform) {
				SVG_Transform *dest;
				if (idx==-1) {
					lsr_read_update_value(lsr, NULL, fieldIndex, field_type, info.far_ptr, 0);
				} else {
					assert(0);
				}


				fieldIndex = gf_node_get_attribute_by_tag((GF_Node*)n, TAG_SVG_ATT_transform, 1, 1, &info);
				dest = (SVG_Transform *)info.far_ptr;
				if (com_type) {
					GF_Point2D scale, translate;
					SVG_Point_Angle rotate;
					if (gf_mx2d_decompose(&dest->mat, &scale, &rotate.angle, &translate)) {
						gf_mx2d_init(dest->mat);
						if (att_type==LSR_UPDATE_TYPE_SCALE) scale = matrix_tmp;
						else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) translate = matrix_tmp;
						else if (att_type==LSR_UPDATE_TYPE_ROTATE) rotate = matrix_tmp_rot;

						gf_mx2d_add_scale(&dest->mat, scale.x, scale.y);
						gf_mx2d_add_rotation(&dest->mat, 0, 0, rotate.angle);
						gf_mx2d_add_translation(&dest->mat, translate.x, translate.y);
					}
				}
				else if (att_type==LSR_UPDATE_TYPE_SCALE) gf_mx2d_add_scale(&dest->mat, matrix_tmp.x, matrix_tmp.y);
				else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) gf_mx2d_add_translation(&dest->mat, matrix_tmp.x, matrix_tmp.y);
				else if (att_type==LSR_UPDATE_TYPE_ROTATE) gf_mx2d_add_rotation(&dest->mat, 0, 0, matrix_tmp_rot.angle);

				gf_node_changed((GF_Node*)n, &info);
			}
			else if (com_type) {
				if (text_content) {
					GF_DOMText *t = NULL;
					if (idx>=0) {
						if (com_type==LSR_UPDATE_INSERT) {
							t = gf_dom_new_text_node(n->sgprivate->scenegraph);
							gf_node_register((GF_Node *)t, n);
							gf_node_list_insert_child(&((GF_ParentNode *)n)->children, (GF_Node*)t, idx);
						} else {
							t = (GF_DOMText *) gf_node_list_get_child(((SVG_Element*)n)->children, idx);
							if (t->sgprivate->tag!=TAG_DOMText) t = NULL;
						}
					} else {
						/*this is a replace, reset ALL node content*/
						gf_sg_parent_reset(n);
						t = gf_dom_add_text_node(n, NULL);
					}
					lsr_read_byte_align_string(lsr, t ? &t->textContent : NULL, "textContent");
					gf_node_changed(n, NULL);
				} else if (idx==-1) {
					lsr_read_update_value(lsr, (GF_Node*)n, fieldIndex, field_type, info.far_ptr, n->sgprivate->tag);
				} else {
					SVG_Point *pt;
					Fixed *v1, *v2;
					//SMIL_Time *t;
					void *prev;
					void *tmp = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, info.far_ptr, idx, com_type==LSR_UPDATE_INSERT, 0);
					switch (field_type) {
					/*generic GF_List containers, no type translation needed*/
					case SMIL_KeyTimes_datatype/*ITYPE_keyTime*/:
					case SMIL_KeySplines_datatype/*ITYPE_float*/:
					case SVG_Points_datatype/*ITYPE_point*/:
					case SMIL_Times_datatype/*ITYPE_smil_time*/:
						if (com_type==LSR_UPDATE_INSERT) {
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, tmp, idx);
						} else {
							prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
							gf_free(prev);
							gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, tmp, idx);
						}
						gf_node_changed((GF_Node*)n, NULL);
						break;
					/*list of floats - to check when implementing it...*/
					case SMIL_KeyPoints_datatype/*ITYPE_0to1 - keyPoints*/:
						pt = (SVG_Point*)tmp;
						v1 = (Fixed *) gf_malloc(sizeof(Fixed));
						*v1 = pt->x;
						v2 = (Fixed *) gf_malloc(sizeof(Fixed));
						*v2 = pt->y;
						gf_free(pt);

						if (com_type==LSR_UPDATE_INSERT) {
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx);
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx+1);
						} else {
							prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
							gf_free(prev);
							gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
							prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
							gf_free(prev);
							gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx);
							gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx);
						}
						gf_node_changed((GF_Node*)n, NULL);
						break;
					case SVG_ViewBox_datatype:
						v1 = (Fixed*)tmp;
						switch (idx) {
						case 0:
							((SVG_ViewBox*)info.far_ptr)->x = *v1;
							break;
						case 1:
							((SVG_ViewBox*)info.far_ptr)->y = *v1;
							break;
						case 2:
							((SVG_ViewBox*)info.far_ptr)->width = *v1;
							break;
						case 3:
							((SVG_ViewBox*)info.far_ptr)->height = *v1;
							break;
						}
						gf_free(tmp);
						gf_node_changed((GF_Node*)n, NULL);
						break;
					case SVG_StrokeDashArray_datatype:
						v1 = (Fixed*)tmp;
						if (com_type==LSR_UPDATE_INSERT) {
							SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr;
							/*use MFFloat for insert*/
							if (gf_sg_vrml_mf_insert(&da->array, GF_SG_VRML_MFFLOAT, (void*) &v2, idx)==GF_OK)
								*v2 = *v1;
						} else {
							SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr;
							if (idx<(s32)da->array.count) da->array.vals[idx] = *v1;
						}
						gf_free(tmp);
						gf_node_changed((GF_Node*)n, NULL);
						break;
					default:
						gf_free(tmp);
						break;
					}
				}
			} else {
				GF_FieldInfo tmp;
				tmp = info;
				if (idx==-1) {
					tmp.far_ptr = gf_svg_create_attribute_value(info.fieldType);
					lsr_read_update_value(lsr, n, fieldIndex, field_type, tmp.far_ptr, n->sgprivate->tag);
				} else {
					tmp.far_ptr = lsr_read_update_value_indexed(lsr, n, field_type, NULL, idx, 0, 1);
				}
				gf_svg_attributes_add(&info, &tmp, &info, 0);
				gf_svg_delete_attribute_value(info.fieldType, tmp.far_ptr, gf_node_get_graph(n));
			}
		}
	}
	/*copy from node*/
	else if (operandNode && (op_att_type>=0)) {
		u32 opFieldIndex = gf_lsr_anim_type_to_attribute(op_att_type);
		if (com_list) {
			com = gf_sg_command_new(lsr->sg, com_type ? GF_SG_LSR_REPLACE : GF_SG_LSR_ADD);
			gf_list_add(com_list, com);
			com->node = n;
			gf_node_register(com->node, NULL);
			com->fromNodeID = op_idref;
			com->fromFieldIndex = opFieldIndex;
			field = gf_sg_command_field_new(com);
			field->pos = idx;
			field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
		} else {
			u32 fieldIndex;
			GF_FieldInfo op_info;
			fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
			gf_node_get_field(n, fieldIndex, &info);
			gf_node_get_field(operandNode, opFieldIndex, &op_info);
			if (com_type) {
				gf_svg_attributes_copy(&info, &op_info, 0);
			} else {
				gf_svg_attributes_add(&info, &op_info, &info, 0);
			}
		}
	}

	lsr_read_any_attribute(lsr, NULL, 1);

	/*if not add*/
	if (!com_type) return GF_OK;

	/*list replacement*/
	GF_LSR_READ_INT(lsr, type, 1, "opt_group");
	if (type) {
		if (!com_type /*|| (idx!=-1) */)
			return GF_NON_COMPLIANT_BITSTREAM;

		if (com_list) {
			u32 count;
			GF_ChildNodeItem *last = NULL;

			if (com_type==LSR_UPDATE_INSERT) count = 1;
			else count = lsr_read_vluimsbf5(lsr, "count");

			com = gf_sg_command_new(lsr->sg, (com_type==LSR_UPDATE_REPLACE) ? GF_SG_LSR_REPLACE : GF_SG_LSR_INSERT);
			gf_list_add(com_list, com);
			com->node = n;
			gf_node_register(com->node, NULL);
			field = gf_sg_command_field_new(com);
			field->pos = idx;

			if (!count && (att_type==LSR_UPDATE_TYPE_TEXT_CONTENT)) {
				field->fieldIndex = -1;
			} else if (count==1) {
				field->new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n);
				gf_node_register(field->new_node, NULL);
				if (att_type>=0) field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
			} else {
				field->field_ptr = &field->node_list;
				while (count) {
					GF_Node *new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n);
					gf_node_register(new_node, n);
					gf_node_list_add_child_last(& field->node_list, new_node, &last);
					count--;
				}
			}
		} else {
			SVG_Element*elt = (SVG_Element*)n;
			GF_ChildNodeItem *last = NULL;
			u32 count;
			if (com_type==LSR_UPDATE_INSERT) count = 1;
			else count = lsr_read_vluimsbf5(lsr, "count");

			if (com_type==LSR_UPDATE_REPLACE) {
				if (idx>=0) {
					new_node = gf_node_list_del_child_idx(&elt->children, idx);
					if (new_node) gf_node_unregister(new_node, n);
				} else {
					gf_node_unregister_children(n, elt->children);
					elt->children = NULL;
				}
			}
			if ((com_type==LSR_UPDATE_INSERT) || (gf_lsr_anim_type_to_attribute(att_type) == TAG_LSR_ATT_children)) {
				while (count) {
					new_node = lsr_read_update_content_model(lsr, elt);
					if (new_node) {
						if (idx>=0) {
							gf_node_list_insert_child(&elt->children, new_node, idx);
						} else {
							gf_node_list_add_child_last(&elt->children, new_node, &last);
						}
						gf_node_register(new_node, n);
					}
					count--;
				}
				gf_node_changed(n, NULL);
			}
			/*node replacement*/
			else if ((att_type==-1) && (count==1)) {
				new_node = lsr_read_update_content_model(lsr, elt);
				gf_node_replace((GF_Node*)elt, new_node, 0);
			}
		}
	}
	return GF_OK;
}