Blame synfig-core/src/modules/lyr_std/julia.cpp

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file julia.cpp
Carlos Lopez a09598
**	\brief Implementation of the "Julia Set" layer
Carlos Lopez a09598
**
Carlos Lopez a09598
**	$Id$
Carlos Lopez a09598
**
Carlos Lopez a09598
**	\legal
Carlos Lopez a09598
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Carlos Lopez a09598
**	Copyright (c) 2007 Chris Moore
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is free software; you can redistribute it and/or
Carlos Lopez a09598
**	modify it under the terms of the GNU General Public License as
Carlos Lopez a09598
**	published by the Free Software Foundation; either version 2 of
Carlos Lopez a09598
**	the License, or (at your option) any later version.
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is distributed in the hope that it will be useful,
Carlos Lopez a09598
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Carlos Lopez a09598
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Carlos Lopez a09598
**	General Public License for more details.
Carlos Lopez a09598
**	\endlegal
Carlos Lopez a09598
**
Carlos Lopez a09598
** === N O T E S ===========================================================
Carlos Lopez a09598
**
Carlos Lopez a09598
** ========================================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === H E A D E R S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef USING_PCH
Carlos Lopez a09598
#	include "pch.h"
Carlos Lopez a09598
#else
Carlos Lopez a09598
#ifdef HAVE_CONFIG_H
Carlos Lopez a09598
#	include <config.h></config.h>
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
#include "julia.h"
Carlos Lopez a09598
bw 94d8a6
#include <synfig localization.h=""></synfig>
bw 94d8a6
#include <synfig general.h=""></synfig>
bw 94d8a6
Carlos Lopez a09598
#include <synfig string.h=""></synfig>
Carlos Lopez a09598
#include <synfig time.h=""></synfig>
Carlos Lopez a09598
#include <synfig context.h=""></synfig>
Carlos Lopez a09598
#include <synfig paramdesc.h=""></synfig>
Carlos Lopez a09598
#include <synfig renddesc.h=""></synfig>
Carlos Lopez a09598
#include <synfig surface.h=""></synfig>
Carlos Lopez a09598
#include <synfig value.h=""></synfig>
Carlos Lopez a09598
#include <synfig valuenode.h=""></synfig>
Carlos Lopez a09598
Carlos Lopez a09598
#endif
Carlos Lopez a09598
9f3c68
using namespace std;
9f3c68
using namespace etl;
9f3c68
using namespace synfig;
144d3f
using namespace modules;
9f3c68
using namespace lyr_std;
9f3c68
Carlos Lopez a09598
/* === M A C R O S ========================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#define LOG_OF_2		0.69314718055994528623
Carlos Lopez a09598
Carlos Lopez a09598
/* === G L O B A L S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
SYNFIG_LAYER_INIT(Julia);
Carlos Lopez a09598
SYNFIG_LAYER_SET_NAME(Julia,"julia");
Carlos Lopez a09598
SYNFIG_LAYER_SET_LOCAL_NAME(Julia,N_("Julia Set"));
Carlos Lopez a09598
SYNFIG_LAYER_SET_CATEGORY(Julia,N_("Fractals"));
Carlos Lopez a09598
SYNFIG_LAYER_SET_VERSION(Julia,"0.1");
Carlos Lopez a09598
SYNFIG_LAYER_SET_CVS_ID(Julia,"$Id$");
Carlos Lopez a09598
Carlos Lopez a09598
/* === P R O C E D U R E S ================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
inline void
Carlos Lopez a09598
color_neg_flip(Color &color)
Carlos Lopez a09598
{
Carlos Lopez a09598
	if(color.get_a()==0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		color=Color::alpha();
Carlos Lopez a09598
		return;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	if(color.get_a()<0)
Carlos Lopez a09598
		color=-color;
Carlos Lopez a09598
Carlos Lopez a09598
	if(color.get_r()<0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		color.set_g(color.get_g()-color.get_r());
Carlos Lopez a09598
		color.set_b(color.get_b()-color.get_r());
Carlos Lopez a09598
		color.set_r(0);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	if(color.get_g()<0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		color.set_r(color.get_r()-color.get_g());
Carlos Lopez a09598
		color.set_b(color.get_b()-color.get_g());
Carlos Lopez a09598
		color.set_g(0);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	if(color.get_b()<0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		color.set_r(color.get_r()-color.get_b());
Carlos Lopez a09598
		color.set_g(color.get_g()-color.get_b());
Carlos Lopez a09598
		color.set_b(0);
Carlos Lopez a09598
	}
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* === M E T H O D S ======================================================= */
Carlos Lopez a09598
Carlos Lopez 63ff26
Julia::Julia():
Carlos Lopez 63ff26
param_color_shift(ValueBase(Angle::deg(0)))
Carlos Lopez a09598
{
Carlos Lopez 63ff26
	param_icolor=ValueBase(Color::black());
Carlos Lopez 63ff26
	param_ocolor=ValueBase(Color::black());
Carlos Lopez 63ff26
	param_iterations=ValueBase(int(32));
Carlos Lopez 63ff26
	param_color_shift=ValueBase(Angle::deg(0));
Carlos Lopez 63ff26
	
Carlos Lopez 63ff26
	param_distort_inside=ValueBase(true);
Carlos Lopez 63ff26
	param_distort_outside=ValueBase(true);
Carlos Lopez 63ff26
	param_shade_inside=ValueBase(true);
Carlos Lopez 63ff26
	param_shade_outside=ValueBase(true);
Carlos Lopez 63ff26
	param_solid_inside=ValueBase(false);
Carlos Lopez 63ff26
	param_solid_outside=ValueBase(false);
Carlos Lopez 63ff26
	param_invert_inside=ValueBase(false);
Carlos Lopez 63ff26
	param_invert_outside=ValueBase(false);
Carlos Lopez 63ff26
	param_color_inside=ValueBase(true);
Carlos Lopez 63ff26
	param_color_outside=ValueBase(false);
Carlos Lopez 63ff26
	param_color_cycle=ValueBase(false);
Carlos Lopez 63ff26
	param_smooth_outside=ValueBase(true);
Carlos Lopez 63ff26
	param_broken=ValueBase(false);
Carlos Lopez 63ff26
	param_seed=ValueBase(Point(0,0));
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	param_bailout=ValueBase(Real(4));
Carlos Lopez 63ff26
	lp=log(log(param_bailout.get(Real())));
Carlos Lopez 63ff26
Carlos Lopez b3fcc2
	SET_INTERPOLATION_DEFAULTS();
Carlos Lopez b3fcc2
	SET_STATIC_DEFAULTS();
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
Julia::set_param(const String & param, const ValueBase &value)
Carlos Lopez a09598
{
Carlos Lopez a09598
Carlos Lopez 63ff26
	IMPORT_VALUE(param_icolor);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_ocolor);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_color_shift);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_seed);
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	IMPORT_VALUE(param_distort_inside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_distort_outside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_shade_inside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_shade_outside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_solid_inside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_solid_outside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_invert_inside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_invert_outside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_color_inside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_color_outside);
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	IMPORT_VALUE(param_color_cycle);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_smooth_outside);
Carlos Lopez 63ff26
	IMPORT_VALUE(param_broken);
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	IMPORT_VALUE_PLUS(param_iterations,
Carlos Lopez a09598
	{
Carlos Lopez 63ff26
		int iterations=param_iterations.get(int());
Carlos Lopez a09598
		iterations=value.get(iterations);
Carlos Lopez a09598
		if(iterations<0)
Carlos Lopez a09598
			iterations=0;
Carlos Lopez a09598
		if(iterations>500000)
Carlos Lopez a09598
			iterations=500000;
Carlos Lopez 63ff26
		param_iterations.set(iterations);
Carlos Lopez a09598
		return true;
Carlos Lopez a09598
	}
Carlos Lopez 63ff26
	);
Carlos Lopez 63ff26
	IMPORT_VALUE_PLUS(param_bailout,
Carlos Lopez a09598
	{
Carlos Lopez 63ff26
		Real bailout=param_bailout.get(Real());
Carlos Lopez a09598
		bailout=value.get(bailout);
Carlos Lopez a09598
		bailout*=bailout;
Carlos Lopez a09598
		lp=log(log(bailout));
Carlos Lopez 63ff26
		param_bailout.set(bailout);
Carlos Lopez a09598
		return true;
Carlos Lopez a09598
	}
Carlos Lopez 63ff26
	);
Carlos Lopez a09598
Carlos Lopez a09598
	return false;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
ValueBase
Carlos Lopez a09598
Julia::get_param(const String & param)const
Carlos Lopez a09598
{
Carlos Lopez 63ff26
	EXPORT_VALUE(param_icolor);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_ocolor);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_color_shift);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_iterations);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_seed);
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	EXPORT_VALUE(param_distort_inside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_distort_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_shade_inside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_shade_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_solid_inside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_solid_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_invert_inside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_invert_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_color_inside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_color_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_color_cycle);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_smooth_outside);
Carlos Lopez 63ff26
	EXPORT_VALUE(param_broken);
Carlos Lopez a09598
Carlos Lopez a09598
	if(param=="bailout")
Carlos Lopez 5b3df3
	{
Carlos Lopez 63ff26
		// This line is needed to copy the static and interpolation options
Carlos Lopez 63ff26
		ValueBase ret(param_bailout);
Carlos Lopez 63ff26
		ret.set(sqrt(param_bailout.get(Real())));
Carlos Lopez 5b3df3
		return ret;
Carlos Lopez 5b3df3
	}
Carlos Lopez a09598
Carlos Lopez a09598
	EXPORT_NAME();
Carlos Lopez a09598
	EXPORT_VERSION();
Carlos Lopez a09598
Carlos Lopez a09598
	return ValueBase();
Carlos Lopez a09598
}
Carlos Lopez a09598
06c9ce
RendDesc
06c9ce
Julia::get_sub_renddesc_vfunc(const RendDesc &renddesc) const
06c9ce
{
06c9ce
	RendDesc desc(renddesc);
06c9ce
	desc.set_wh(512, 512);
06c9ce
	desc.set_tl(Vector(-5.0, -5.0));
06c9ce
	desc.set_br(Vector( 5.0,  5.0));
06c9ce
	return desc;
06c9ce
}
06c9ce
Carlos Lopez a09598
Color
Carlos Lopez a09598
Julia::get_color(Context context, const Point &pos)const
Carlos Lopez a09598
{
9f3c68
	Color icolor=param_icolor.get(Color());
9f3c68
	Color ocolor=param_ocolor.get(Color());
9f3c68
	Angle color_shift=param_color_shift.get(Angle());
Carlos Lopez 63ff26
	int iterations=param_iterations.get(int());
9f3c68
	Point seed=param_seed.get(Point());
Carlos Lopez 63ff26
	bool distort_inside=param_distort_inside.get(bool());
Carlos Lopez 63ff26
	bool shade_inside=param_shade_inside.get(bool());
Carlos Lopez 63ff26
	bool solid_inside=param_solid_inside.get(bool());
Carlos Lopez 63ff26
	bool invert_inside=param_invert_inside.get(bool());
Carlos Lopez 63ff26
	bool color_inside=param_color_inside.get(bool());
Carlos Lopez 63ff26
	bool distort_outside=param_distort_outside.get(bool());
Carlos Lopez 63ff26
	bool shade_outside=param_shade_outside.get(bool());
Carlos Lopez 63ff26
	bool solid_outside=param_solid_outside.get(bool());
Carlos Lopez 63ff26
	bool invert_outside=param_invert_outside.get(bool());
Carlos Lopez 63ff26
	bool color_outside=param_color_outside.get(bool());
Carlos Lopez 63ff26
Carlos Lopez 63ff26
	bool color_cycle=param_color_cycle.get(bool());
Carlos Lopez 63ff26
	bool smooth_outside=param_smooth_outside.get(bool());
Carlos Lopez 63ff26
	bool broken=param_broken.get(bool());
Carlos Lopez 63ff26
Carlos Lopez a09598
	Real
Carlos Lopez a09598
		cr, ci,
Carlos Lopez a09598
		zr, zi,
Carlos Lopez a09598
		zr_hold;
Carlos Lopez a09598
Carlos Lopez a09598
	ColorReal
Carlos Lopez a09598
		depth, mag(0);
Carlos Lopez a09598
Carlos Lopez a09598
	Color
Carlos Lopez a09598
		ret;
Carlos Lopez a09598
Carlos Lopez a09598
	cr=seed[0];
Carlos Lopez a09598
	ci=seed[1];
Carlos Lopez a09598
	zr=pos[0];
Carlos Lopez a09598
	zi=pos[1];
Carlos Lopez a09598
Carlos Lopez a09598
	for(int i=0;i
Carlos Lopez a09598
	{
Carlos Lopez a09598
		// Perform complex multiplication
Carlos Lopez a09598
		zr_hold=zr;
Carlos Lopez a09598
		zr=zr*zr-zi*zi + cr;
Carlos Lopez a09598
		zi=zr_hold*zi*2 + ci;
Carlos Lopez a09598
Carlos Lopez a09598
		// Use "broken" algorithm, if requested (looks weird)
Carlos Lopez a09598
		if(broken)zr+=zi;
Carlos Lopez a09598
Carlos Lopez a09598
		// Calculate Magnitude
Carlos Lopez a09598
		mag=zr*zr+zi*zi;
Carlos Lopez a09598
Carlos Lopez a09598
		if(mag>4)
Carlos Lopez a09598
		{
Carlos Lopez a09598
			if(smooth_outside)
Carlos Lopez a09598
			{
Carlos Lopez a09598
				// Darco's original mandelbrot smoothing algo
Carlos Lopez a09598
				// depth=((Point::value_type)i+(2.0-sqrt(mag))/PI);
Carlos Lopez a09598
Carlos Lopez a09598
				// Linas Vepstas algo (Better than darco's)
Carlos Lopez a09598
				// See (http://linas.org/art-gallery/escape/smooth.html)
Carlos Lopez a09598
				depth= (ColorReal)i - log(log(sqrt(mag))) / LOG_OF_2;
Carlos Lopez a09598
Carlos Lopez a09598
				// Clamp
Carlos Lopez a09598
				if(depth<0) depth=0;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			else
Carlos Lopez a09598
				depth=static_cast<colorreal>(i);</colorreal>
Carlos Lopez a09598
Carlos Lopez a09598
			if(solid_outside)
Carlos Lopez a09598
				ret=ocolor;
Carlos Lopez a09598
			else
Carlos Lopez a09598
				if(distort_outside)
Carlos Lopez a09598
					ret=context.get_color(Point(zr,zi));
Carlos Lopez a09598
				else
Carlos Lopez a09598
					ret=context.get_color(pos);
Carlos Lopez a09598
Carlos Lopez a09598
			if(invert_outside)
Carlos Lopez a09598
				ret=~ret;
Carlos Lopez a09598
Carlos Lopez a09598
			if(color_outside)
Carlos Lopez a09598
				ret=ret.set_uv(zr,zi).clamped_negative();
Carlos Lopez a09598
Carlos Lopez a09598
			if(color_cycle)
Carlos Lopez a09598
				ret=ret.rotate_uv(color_shift.operator*(depth)).clamped_negative();
Carlos Lopez a09598
Carlos Lopez a09598
			if(shade_outside)
Carlos Lopez a09598
			{
Carlos Lopez a09598
				ColorReal alpha=depth/static_cast<colorreal>(iterations);</colorreal>
Carlos Lopez a09598
				ret=(ocolor-ret)*alpha+ret;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			return ret;
Carlos Lopez a09598
		}
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	if(solid_inside)
Carlos Lopez a09598
		ret=icolor;
Carlos Lopez a09598
	else
Carlos Lopez a09598
		if(distort_inside)
Carlos Lopez a09598
			ret=context.get_color(Point(zr,zi));
Carlos Lopez a09598
		else
Carlos Lopez a09598
			ret=context.get_color(pos);
Carlos Lopez a09598
Carlos Lopez a09598
	if(invert_inside)
Carlos Lopez a09598
		ret=~ret;
Carlos Lopez a09598
Carlos Lopez a09598
	if(color_inside)
Carlos Lopez a09598
		ret=ret.set_uv(zr,zi).clamped_negative();
Carlos Lopez a09598
Carlos Lopez a09598
	if(shade_inside)
Carlos Lopez a09598
		ret=(icolor-ret)*mag+ret;
Carlos Lopez a09598
Carlos Lopez a09598
	return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Layer::Vocab
Carlos Lopez a09598
Julia::get_param_vocab()const
Carlos Lopez a09598
{
Carlos Lopez a09598
	Layer::Vocab ret;
Carlos Lopez a09598
Carlos Lopez a09598
	ret.push_back(ParamDesc("icolor")
Carlos Lopez a09598
		.set_local_name(_("Inside Color"))
Carlos Lopez a09598
		.set_description(_("Color of the Set"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("ocolor")
Carlos Lopez a09598
		.set_local_name(_("Outside Color"))
Carlos Lopez a09598
		.set_description(_("Color outside the Set"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("color_shift")
Carlos Lopez a09598
		.set_local_name(_("Color Shift"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("iterations")
Carlos Lopez a09598
		.set_local_name(_("Iterations"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("seed")
Carlos Lopez a09598
		.set_local_name(_("Seed Point"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("bailout")
Carlos Lopez a09598
		.set_local_name(_("Bailout ValueBase"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
Carlos Lopez a09598
	ret.push_back(ParamDesc("distort_inside")
Carlos Lopez a09598
		.set_local_name(_("Distort Inside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("shade_inside")
Carlos Lopez a09598
		.set_local_name(_("Shade Inside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("solid_inside")
Carlos Lopez a09598
		.set_local_name(_("Solid Inside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("invert_inside")
Carlos Lopez a09598
		.set_local_name(_("Invert Inside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("color_inside")
Carlos Lopez a09598
		.set_local_name(_("Color Inside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("distort_outside")
Carlos Lopez a09598
		.set_local_name(_("Distort Outside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("shade_outside")
Carlos Lopez a09598
		.set_local_name(_("Shade Outside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("solid_outside")
Carlos Lopez a09598
		.set_local_name(_("Solid Outside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("invert_outside")
Carlos Lopez a09598
		.set_local_name(_("Invert Outside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("color_outside")
Carlos Lopez a09598
		.set_local_name(_("Color Outside"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
Carlos Lopez a09598
	ret.push_back(ParamDesc("color_cycle")
Carlos Lopez a09598
		.set_local_name(_("Color Cycle"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("smooth_outside")
Carlos Lopez a09598
		.set_local_name(_("Smooth Outside"))
Carlos Lopez a09598
		.set_description(_("Smooth the coloration outside the set"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("broken")
Carlos Lopez a09598
		.set_local_name(_("Break Set"))
Carlos Lopez a09598
		.set_description(_("Modify equation to achieve interesting results"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
	return ret;
Carlos Lopez a09598
}