/*
 *	Fractal Engine by tos.
 */

//#include <math.h>
//#include <complex.h>
//#include <system.hpp>
//#include <list.h>

#include <complex.h>
#include <vcl.h>

#include "TFLib.h"

extern	int	TFMultiThreadNum;

/* Primitive Class ***********************************************************/

enum
{
	TF_NOCHECK = 0,
	TF_NOMODIFY,
	TF_MODIFY,
	TF_UPDATED
};


class   TFObject
{
protected:
	AnsiString	FName;
	int		FModify;

	virtual AnsiString __fastcall OutputSourceMember(AnsiString indent) =0;
	virtual bool __fastcall InputSourceMember(AnsiString *src) = 0;

	__property int Modify = { read = FModify, write = FModify };

public:
	TFObject(void)
	{
		FName = "";
		FModify = TF_NOCHECK;
	}

	__property AnsiString Name = {read = FName, write = FName};

	bool __fastcall Update(void)
	{
		if (Modify == TF_NOCHECK) Modify = TF_NOMODIFY;
		if (Modify == TF_MODIFY)  Modify = TF_UPDATED;
		return (Modify);
	}

	virtual void __fastcall CompleteUpdate(void) 
	{ Modify = TF_NOCHECK; }

	AnsiString __fastcall OutputSource (AnsiString indent)
	{
		AnsiString      output;
		output += Name + "\n";
		output += indent + "{\n";
		output += OutputSourceMember(indent + "\t");
		output += indent + "}\n";
		output += "\n";
		return (output);
	}

	bool __fastcall InputSource (AnsiString *src)
	{
		bool		rc;

		/* クラスの名前を取得 */
		FName = TFLib::GetWord(src);

		/* 空白をスキップする */
		TFLib::SkipSpaceCR (src);

		/* '{' をスキップする */
		if (TFLib::SkipChar(src, '{')) return (TFFAILD);
		TFLib::SkipSpaceCR (src);

		rc = InputSourceMember(src);
		if (rc) return (TFFAILD);

		/* '}' をスキップする */
		if (TFLib::SkipChar(src, '}')) return (TFFAILD);
		TFLib::SkipSpaceCR (src);

		return (TFSUCCESS);
	}
};

struct TFPointData
{
	complex<double>	z;
	int		count;
};

union	TFRGB
{
	TColor		color;
	struct
	{
		unsigned char	r;
		unsigned char	g;
		unsigned char	b;
		unsigned char	_reserve;
	};
};


/* Primitive Method **********************************************************/

class	TFMethod: public TFObject
{
protected:
	unsigned int  	FParamNum;
	AnsiString	*FParamName;
	complex<double>	*FParam;


	AnsiString __fastcall GetParamName(unsigned int index)
	{
		if (index < FParamNum)
			return (FParamName[index]);
		else
			return ("");
	}

	void __fastcall SetParam (unsigned int index, complex<double> param)
	{
		if (index < FParamNum)
		{
			FParam[index] = param;
			Modify = TF_MODIFY;
		}
	}

	complex<double> __fastcall GetParam (unsigned int index)
	{
		if (index < FParamNum)
			return (FParam[index]);
		else
			return (0);
	}

	AnsiString __fastcall OutputSourceMember (AnsiString indent)
	{
		AnsiString      output;
		unsigned int    i;

		for (i = 0 ; i < ParamNum ; i++)
			output += indent + "Parameter: " + TFLib::ToAnsiString(Param[i]) + "\n";
		return (output);
	}

	bool __fastcall InputSourceMember (AnsiString *src)
	{
		AnsiString	word;
		complex<double>	z;
		unsigned int    i;

		for (i = 0 ; i < ParamNum ; i++)
		{
			if (TFLib::SkipWord(src, "Parameter:"))
				return (TFFAILD);
			if (TFLib::GetComplex(src, &z))
				return (TFFAILD);
			Param[i] = z;
			TFLib::SkipSpaceCR (src);
		}
		return (TFSUCCESS);
	}


public:
	__property unsigned int ParamNum = {read = FParamNum};
	__property AnsiString ParamName[unsigned int index] = {read = GetParamName};
	__property complex<double> Param[unsigned int index] = {read = GetParam, write=SetParam};

	TFMethod(AnsiString name, unsigned int param_num, TFMethod *m)
	{
		FName      = name;
		FParamNum  = param_num;
		FParam     = new complex<double>[param_num];
		FParamName = new AnsiString[param_num];
		if (m != NULL)
		{
			for (unsigned int i = 0 ; i < param_num ; i++)
			{
				FParamName[i] = m->ParamName[i];
				FParam[i] = m->Param[i];
			}
		}
	}

	~TFMethod()
	{
		delete [] FParam;
		delete [] FParamName;
	}

};

/* Fractal Method ************************************************************/

class	TFFractalMethod: public TFMethod
{
public:
	static TFFractalMethod	*List[];
	static int		MethodNum;

	TFFractalMethod (AnsiString name, unsigned int param_num, TFMethod *m)
	 : TFMethod (name, param_num, m) {}
	virtual complex<double> __fastcall FractalFunction (complex<double> z, complex<double> c) = 0;
	virtual TFFractalMethod * __fastcall New(void) = 0;

	static TFFractalMethod * __fastcall SearchMethod(AnsiString name)
	{
		int		i;

		for (i = 0 ; i < MethodNum ; i++)
			if (List[i]->Name == name) return (List[i]);
		return (NULL);
	}
};


#define	DEFINE_TF_FRACTAL_METHOD(class_name, name, param_num, param_data, func) \
class	class_name : public TFFractalMethod \
{ \
public: \
	class_name (class_name *m = NULL): TFFractalMethod (name, param_num, m) \
	{ if (m == NULL) { param_data; } } \
 \
	class_name * __fastcall New(void) \
	{ return (new class_name(this)); } \
 \
	complex<double> __fastcall FractalFunction (complex<double> z, complex<double> c) \
	{ return (func); } \
}

DEFINE_TF_FRACTAL_METHOD (TFFractalMethod_Z3, "z^3+C", 0, 0, z*z*z+c);

class	TFFractalMethod_Z2: public TFFractalMethod
{
public:
	TFFractalMethod_Z2 (TFFractalMethod_Z2 *m = NULL)
	  : TFFractalMethod ("z^2+C", 0, m)
	{}

	TFFractalMethod_Z2 * __fastcall New(void)
	{ return (new TFFractalMethod_Z2(this)); }

	complex<double> __fastcall FractalFunction (complex<double> z, complex<double> c)
	{ return (z*z + c); }
};

/* Divergence Method *********************************************************/

class	TFDivergenceMethod: public TFMethod
{
public:
	static TFDivergenceMethod	*List[];
	static int			MethodNum;

	TFDivergenceMethod (AnsiString name, unsigned int param_num, TFMethod *m)
	 : TFMethod (name, param_num, m) {}
	virtual bool __fastcall DivergenceFunction (complex<double> z, int count) = 0;
	virtual TFDivergenceMethod * __fastcall New(void) = 0;

	static TFDivergenceMethod * __fastcall SearchMethod(AnsiString name)
	{
		int		i;

		for (i = 0 ; i < MethodNum ; i++)
			if (List[i]->Name == name) return (List[i]);
		return (NULL);
	}
};

#define	DEFINE_TF_DIVERGENCE_METHOD(class_name, name, param_num, param_data, func) \
class	class_name : public TFDivergenceMethod \
{ \
public: \
	class_name (class_name *m = NULL) \
	  : TFDivergenceMethod (name, param_num, m) \
	{ if (m == NULL) { param_data; } } \
 \
	class_name * __fastcall New(void) \
	{ return (new class_name(this)); } \
 \
	bool __fastcall DivergenceFunction (complex<double> z, int count) \
	{ return (func); } \
}

DEFINE_TF_DIVERGENCE_METHOD(
	TFDivergenceMethod_Stalks, "エプシロンクロス", 2,
	(FParamName[0] = "幅",   FParam[0] = complex<double>(0.01, 0.01),
	 FParamName[1] = "回数", FParam[1] = 0 ),
	(
		 count > real(Param[1])
		 && (fabs(real(z)) < real(Param[0]) || fabs(imag(z)) < imag(Param[0])
	)
	 ? 1 : 0)
	);

class	TFDivergenceMethod_Norm: public TFDivergenceMethod
{
public:
	TFDivergenceMethod_Norm (TFDivergenceMethod_Norm *m = NULL)
	  : TFDivergenceMethod ("終点ノルム", 1, m)
	{
		if (m == NULL)
		{
			FParamName[0] = "範囲"; FParam[0] = 4.0;
		}
	}

	TFDivergenceMethod_Norm * __fastcall New(void)
	{ return (new TFDivergenceMethod_Norm(this)); }

	bool __fastcall DivergenceFunction (complex<double> z, int count)
	{ return (norm(z) > norm(Param[0]) ? 1 : 0); }
};

/* Output Method *************************************************************/

class	TFOutputMethod: public TFMethod
{
protected:
	TFPointData		point0;

public:
	static TFOutputMethod	*List[];
	static int		MethodNum;

	TFOutputMethod (AnsiString name, unsigned int param_num, TFMethod *m)
	 : TFMethod (name, param_num, m) {}
	virtual void __fastcall Init(void) {};
	virtual void __fastcall SetOutput (complex<double> z, int count) = 0;
	void __fastcall GetOutput (TFPointData *p)
	{ *p = point0; }
	virtual TFOutputMethod * __fastcall New(void) = 0;

	static TFOutputMethod * __fastcall SearchMethod(AnsiString name)
	{
		int		i;

		for (i = 0 ; i < MethodNum ; i++)
			if (List[i]->Name == name) return (List[i]);
		return (NULL);
	}
};

#define	DEFINE_TF_OUTPUT_METHOD(class_name, name, param_num, param_data, def_var, init_var, set_output) \
class	class_name : public TFOutputMethod \
{ \
private: \
	def_var; \
 \
public: \
	class_name (class_name *m = NULL) \
	  : TFOutputMethod (name, param_num, m) \
	{ if (m == NULL) { param_data; } } \
 \
	class_name * __fastcall New(void) \
	{ return (new class_name(this)); } \
 \
	void __fastcall Init(void) \
	{ init_var; }; \
 \
	void __fastcall SetOutput (complex<double> z, int count) \
	{ set_output; } \
}

DEFINE_TF_OUTPUT_METHOD(TFOutputMethod_Ball, "球", 2,
	( FParamName[0] = "位置", FParam[0] = 0,
	  FParamName[1] = "開始回数", FParam[1] = 1 ) ,
	double dist_min ,
	dist_min = 1e100;
	point0.z = 0;
	point0.count = 1; ,
	double	dist;
	if (count >= real(Param[1]))
	{
		dist = abs(z - Param[0]);
		if (dist < dist_min)
		{
			point0.z = z - Param[0];
			point0.count = count;
			dist_min = dist;
		}
	}
	);

class	TFOutputMethod_EndPoint: public TFOutputMethod
{
public:
	TFOutputMethod_EndPoint (TFOutputMethod_EndPoint *m = NULL)
	  : TFOutputMethod ("終点", 0, m)
	{}

	TFOutputMethod_EndPoint * __fastcall New(void)
	{ return (new TFOutputMethod_EndPoint(this)); }

	void __fastcall SetOutput (complex<double> z, int count)
	{ point0.z = z; point0.count = count; }
};

/* Rendering Method **********************************************************/

class	TFRenderingMethod: public TFMethod
{
public:
	static TFRenderingMethod	*List[];
	static int			MethodNum;

	TFRenderingMethod (AnsiString name, unsigned int param_num, TFMethod *m)
	 : TFMethod (name, param_num, m) {}
	virtual double __fastcall RenderingFunction (complex<double> z, int count) = 0;
	virtual TFRenderingMethod * __fastcall New(void) = 0;

	static TFRenderingMethod * __fastcall SearchMethod(AnsiString name)
	{
		int		i;

		for (i = 0 ; i < MethodNum ; i++)
			if (List[i]->Name == name) return (List[i]);
		return (NULL);
	}
};

#define	DEFINE_TF_RENDERING_METHOD(class_name, name, param_num, param_data, func) \
class	class_name: public TFRenderingMethod \
{ \
public: \
	class_name (class_name *m = NULL) \
	  : TFRenderingMethod (name, param_num, m) \
	{ if (m == NULL) { param_data; } } \
 \
	class_name * __fastcall New(void) \
	{ return (new class_name(this)); } \
 \
	double __fastcall RenderingFunction (complex<double> z, int count) \
	{ return ( func ); } \
}


class	TFRenderingMethod_Count: public TFRenderingMethod
{
public:
	TFRenderingMethod_Count (TFRenderingMethod_Count *m = NULL)
	  : TFRenderingMethod ("回数", 1, m)
	{
		if (m == NULL)
		{
			FParamName[0] = "定数"; FParam[0] = 100.0;
		}
	}

	TFRenderingMethod_Count * __fastcall New(void)
	{ return (new TFRenderingMethod_Count(this)); }

	double __fastcall RenderingFunction (complex<double> z, int count)
	{ return ( (double)count/(count + real(Param[0])) ); }
};

DEFINE_TF_RENDERING_METHOD(TFRenderingMethod_Count0, "回数0", 0, 0, count);
DEFINE_TF_RENDERING_METHOD(TFRenderingMethod_REAL, "実部", 0, 0, real(z));
DEFINE_TF_RENDERING_METHOD(TFRenderingMethod_IMAG, "虚部", 0, 0, imag(z));
DEFINE_TF_RENDERING_METHOD(TFRenderingMethod_ABS, "大きさ", 1, (FParamName[0] = "中心点", FParam[0] = 0), abs(z - Param[0]));
DEFINE_TF_RENDERING_METHOD(TFRenderingMethod_ARG, "角度", 1, (FParamName[0] = "中心点", FParam[0] = 0), arg(z - Param[0])*180/M_PI);



/* Primitive Field ***********************************************************/

class TFField
{
private:
	int	FWidth;
	int	FHeight;
	int	FOneSize;
	void	*Field;

public:
	__fastcall TFField (int size)
	{
		FOneSize = size;
		FWidth = FHeight = 0;
		Field = NULL;
	}

	__fastcall ~TFField(void)
	{
		if (Field != NULL) delete Field;
	}

	__property int Width = { read = FWidth};
	__property int Height = { read = FHeight};
	__property int OneSize = { read = FOneSize};

	void __fastcall SetSize (int w, int h)
	{
		if (Width == w && Height == h) return;
		if (Width != 0 && Height != 0)
		{
		        delete[] Field;
			Field = NULL;
		}

		FWidth = w;
		FHeight = h;

		if (w == 0 || h == 0) return;

	       	Field  = new char[Width*Height*OneSize];

	}

	void * __fastcall Get(int x, int y)
	{
		return ((char *)Field + OneSize*x + OneSize*Width*y);
	}

	void __fastcall Set(int x, int y, void *d)
	{
		memcpy (Get(x, y), d, OneSize);
	}
};

class TFFractalField: public TFField
{
public:
	__fastcall TFFractalField(void): TFField(sizeof(TFPointData))
	{};

	TFPointData * __fastcall Get(int x, int y)
	{ return ((TFPointData*) TFField::Get(x, y)); }

};

class TFRGBField: public TFField
{
public:
	__fastcall TFRGBField(void): TFField(sizeof(TFRGB))
	{};

	TFRGB * __fastcall Get(int x, int y)
	{ return ((TFRGB*) TFField::Get(x, y)); }

};


/* Parameter *****************************************************************/

enum
{
	TF_FRACTAL_TYPE_MANDELBROT = 0,
	TF_FRACTAL_TYPE_JULIA,

	TF_FRACTAL_TYPE_NUM
};

class TFParameter: public TFObject
{
private:
	AnsiString	*FFractalTypeList;

	int		FFractalType;
	TFFractalMethod	*FFractalMethod;
	complex<double> FFractalParameter;
	complex<double> FViewpoint;
	double		FScale;
	int		FWidth;
	int		FHeight;

	AnsiString __fastcall GetFractalTypeList(int n)
	{ return (FFractalTypeList[n]); }

        void __fastcall SetFractalType (int type)
        {
                FFractalType = type;
                Modify = TF_MODIFY;
        }

        void __fastcall SetFractalMethod (TFFractalMethod *method)
        {
		if (FFractalMethod) delete FFractalMethod;
                FFractalMethod = method;
                Modify = TF_MODIFY;
        }

        void __fastcall SetFractalParameter (complex<double> p)
        {
                FFractalParameter = p;
                Modify = TF_MODIFY;
        }

        void __fastcall SetViewpoint (complex<double> p)
        {
                FViewpoint = p;
                Modify = TF_MODIFY;
        }

        void __fastcall SetScale (double scale)
        {
                FScale = scale;
                Modify = TF_MODIFY;
        }

        void __fastcall SetWidth (int width)
        {
                FWidth = width;
                Modify = TF_MODIFY;
        }

        void __fastcall SetHeight (int height)
        {
                FHeight = height;
                Modify = TF_MODIFY;
	}

	AnsiString __fastcall GetFractalTypeName(void)
	{
		return (FractalTypeList[FractalType]);
	}

	AnsiString __fastcall OutputSourceMember (AnsiString indent)
	{
		AnsiString      output;
		unsigned int    i;

		output += indent + "FractalType: " + FractalTypeList[FractalType] + "\n";
		output += indent + "FractalMethod: " + FractalMethod->OutputSource(indent);
		output += indent + "FractalParameter: " + TFLib::ToAnsiString(FFractalParameter) + "\n";
		output += indent + "Viewpoint: " + TFLib::ToAnsiString(FViewpoint) + "\n";
		output += indent + "Scale: " + Scale + "\n";
		output += indent + "Width: " + Width + "\n";
		output += indent + "Height: " + Height + "\n";

		return (output);
	}

	bool __fastcall InputSourceMember (AnsiString *src)
	{
		AnsiString	word;
		double		x;
		complex<double>	z;
		unsigned int    i;
		TFFractalMethod	*fm;

		if (TFLib::SkipWord(src, "FractalType:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		for (i = 0 ; i < TF_FRACTAL_TYPE_NUM ; i++)
		{
			if (FractalTypeList[i] == word)
			{
				FractalType = i;
				break;
			}
		}
		if (i >= TF_FRACTAL_TYPE_NUM) return (TFFAILD);
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "FractalMethod:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		fm = TFFractalMethod::SearchMethod(word);
		if (fm == NULL) return (TFFAILD);
		FractalMethod = fm->New();
		*src = word + "\n" + *src;
		if (FractalMethod->InputSource(src)) return (TFFAILD);

		if (TFLib::SkipWord(src, "FractalParameter:")) return (TFFAILD);
		if (TFLib::GetComplex(src, &z)) return (TFFAILD);

		FractalParameter = z;
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "Viewpoint:")) return (TFFAILD);
		if (TFLib::GetComplex(src, &z)) return (TFFAILD);
		Viewpoint = z;
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "Scale:")) return (TFFAILD);
		if (TFLib::GetNumber(src, &x)) return (TFFAILD);
		Scale = x;
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "Width:")) return (TFFAILD);
		if (TFLib::GetNumber(src, &x)) return (TFFAILD);
		Width = x;
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "Height:")) return (TFFAILD);
		if (TFLib::GetNumber(src, &x)) return (TFFAILD);
		Height = x;
		TFLib::SkipSpaceCR (src);

		return (TFSUCCESS);
	}

public:
	__fastcall TFParameter(void)
	{
		extern TFFractalMethod_Z2	FractalMethod_Z2;
		int		i;
		static char	*ft_list[] = 
		{
			"マンデルブロ",
			"ジュリア"
		};

		FFractalTypeList = new AnsiString[TF_FRACTAL_TYPE_NUM];
		for (i = 0 ; i < TF_FRACTAL_TYPE_NUM ; i++)
			FFractalTypeList[i] = ft_list[i];

		FractalType = TF_FRACTAL_TYPE_MANDELBROT;
		FFractalMethod = FractalMethod_Z2.New();
		FractalParameter = 0;
		Viewpoint = 0;
		Scale = 4;
		Width = 320;
		Height = 320;
	}

	__fastcall ~TFParameter(void)
	{
		delete[] FFractalTypeList;
	}

	__property AnsiString FractalTypeList[int n] = { read = GetFractalTypeList };
	__property int FractalType = { read = FFractalType, write = SetFractalType };
	__property AnsiString FractalTypeName = {read = GetFractalTypeName };
	__property TFFractalMethod * FractalMethod = { read = FFractalMethod, write = SetFractalMethod };
	__property complex<double> FractalParameter = { read = FFractalParameter, write = SetFractalParameter };
	__property complex<double> Viewpoint = { read = FViewpoint, write = SetViewpoint };
	__property double Scale = { read = FScale, write = SetScale };
	__property int Width = { read = FWidth, write = SetWidth };
	__property int Height = { read = FHeight, write = SetHeight };

	bool __fastcall Update(void)
	{
		int	modify;

		if (Modify == TF_NOMODIFY || Modify == TF_UPDATED)
			return (Modify);

		modify = FractalMethod->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;

		if (Modify == TF_MODIFY)
			Modify = TF_UPDATED;
		else
			Modify = TF_NOMODIFY;

		return (Modify);
	}

	void __fastcall CompleteUpdate(void)
	{
		FractalMethod->CompleteUpdate();
		Modify = TF_NOCHECK;
	}

};

/* Generator *****************************************************************/

class	TFGenerator;

class	TFThreadGenerator: public TThread
{
private:
	TFGenerator	*Generator;
	int		Offset;

public:
	__fastcall TFThreadGenerator (TFGenerator *g, int offset)
		 : TThread(false)
	{
		Generator = g;
		Offset = offset;
	}

	void __fastcall Execute(void);
};


class	TFGenerator: public TFObject
{
public:
	static TList		*List;

private:
	static int		ID;

	TFParameter		*FParameter;
	TFDivergenceMethod	*FDivergenceMethod;
	TFOutputMethod		*FOutputMethod;
	int			FDepth;
	double			FRange;
	TFFractalField		FFractalField;

	void __fastcall	SetParameter (TFParameter *p)
	{
                FParameter = p;
                Modify = TF_MODIFY;
        }

	void __fastcall SetDivergenceMethod (TFDivergenceMethod *dm)
	{
		if (FDivergenceMethod) delete FDivergenceMethod;
                FDivergenceMethod = dm;
                Modify = TF_MODIFY;
        }

	void __fastcall SetOutputMethod (TFOutputMethod *om)
	{
		if (FOutputMethod) delete FOutputMethod;
		FOutputMethod = om;
		Modify = TF_MODIFY;
	}

	void __fastcall SetDepth (int depth)
	{
                FDepth = depth;
                Modify = TF_MODIFY;
        }

	void __fastcall SetRange (double range)
	{
                FRange = range;
                Modify = TF_MODIFY;
        }

	TFFractalField * __fastcall GetFractalField(void)
	{ return (&FFractalField); }


        AnsiString __fastcall OutputSourceMember (AnsiString indent)
        {
                AnsiString      output;

                output += indent + "DivergenceMethod: " + DivergenceMethod->OutputSource (indent);
                output += indent + "OutputMethod: " + OutputMethod->OutputSource (indent);
                output += indent + "Depth: " + Depth + "\n";
                return (output);
        }

	bool __fastcall InputSourceMember (AnsiString *src)
	{
		double		x;
		AnsiString	word;
		unsigned int    i;
		TFDivergenceMethod *dm;
		TFOutputMethod	*om;

		if (TFLib::SkipWord(src, "DivergenceMethod:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		dm = TFDivergenceMethod::SearchMethod(word);
		if (dm == NULL) return (TFFAILD);
		DivergenceMethod = dm->New();
		*src = word + "\n" + *src;
		if (DivergenceMethod->InputSource(src)) return (TFFAILD);

		if (TFLib::SkipWord(src, "OutputMethod:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		om = TFOutputMethod::SearchMethod(word);
		if (om == NULL) return (TFFAILD);
		OutputMethod = om->New();
		*src = word + "\n" + *src;
		if (OutputMethod->InputSource(src)) return (TFFAILD);

		if (TFLib::SkipWord(src, "Depth:")) return (TFFAILD);
		if (TFLib::GetNumber(src, &x)) return (TFFAILD);
		Depth = x;
		TFLib::SkipSpaceCR (src);

		return (TFSUCCESS);
	}

public:
#if 0
	__fastcall TFGenerator(TFParameter *p)
	{
		extern TFDivergenceMethod_Norm	DivergenceMethod_Norm;
		extern TFOutputMethod_EndPoint	OutputMethod_EndPoint;
		Parameter = p;
		FDivergenceMethod = DivergenceMethod_Norm.New();
		FOutputMethod = OutputMethod_EndPoint.New();
		Depth = 100;

		Name = "Generator" + (AnsiString)++ID;
	}
#endif

        __fastcall TFGenerator (TFGenerator *generator = NULL)
        {
		extern TFDivergenceMethod_Norm	DivergenceMethod_Norm;
		extern TFOutputMethod_EndPoint	OutputMethod_EndPoint;

		if (generator == NULL)
		{
			FDivergenceMethod = DivergenceMethod_Norm.New();
			FOutputMethod = OutputMethod_EndPoint.New();
			Depth = 100;
			Range = 4.0;
		}
		else
		{
			Parameter = generator->Parameter;
			FDivergenceMethod = generator->DivergenceMethod->New();
			FOutputMethod = generator->OutputMethod->New();
			Depth = generator->Depth;
		}

		Name = "Generator" + (AnsiString)++ID;
		Modify = TF_MODIFY;
		List->Add(this);
        }

	__fastcall ~TFGenerator(void)
	{
		if (FDivergenceMethod) delete FDivergenceMethod;
		if (FOutputMethod) delete FOutputMethod;
		List->Delete(List->IndexOf(this));
	}

        __property TFParameter * Parameter = { read = FParameter, write = SetParameter };
        __property TFDivergenceMethod * DivergenceMethod = { read = FDivergenceMethod, write = SetDivergenceMethod };
        __property TFOutputMethod * OutputMethod = { read = FOutputMethod, write = SetOutputMethod };
        __property int Depth = { read = FDepth, write = SetDepth };
        __property double Range = { read = FRange, write = SetRange };
	__property TFFractalField * FractalField = { read = GetFractalField };


	static TFGenerator * __fastcall SearchGenerator (AnsiString name)
	{
		int		i;
		TFGenerator	*g;

		for (i = 0 ; i < List->Count ; i++)
		{

			g = (TFGenerator *)List->Items[i];
			if (g->Name == name) return (g);
		}
		return (NULL);
	}

	bool __fastcall Update(void)
	{
		int	modify;

		if (Modify == TF_NOMODIFY || Modify == TF_UPDATED)
			return (Modify);

		modify = Parameter->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;
		modify = DivergenceMethod->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;
		modify = OutputMethod->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;
		modify = Modify;
		if (modify == TF_UPDATED) Modify = TF_MODIFY;

		if (Modify == TF_MODIFY)
		{
			Generate();
			Modify = TF_UPDATED;
		}
		else
			Modify = TF_NOMODIFY;

		return (Modify);
	}

	void __fastcall CompleteUpdate(void)
	{
		Parameter->CompleteUpdate();
		DivergenceMethod->CompleteUpdate();
		OutputMethod->CompleteUpdate();
		Modify = false;
	}

	void __fastcall	Generate(void)
	{
		TFThreadGenerator	**g;
		int			i;

	        FractalField->SetSize (Parameter->Width, Parameter->Height);

		g = new TFThreadGenerator*[TFMultiThreadNum];

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			g[i] = new TFThreadGenerator(this, i);

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			g[i]->WaitFor();

		delete	g;
	}

	void __fastcall	Generate0(int offset)
	{
		complex<double> z;
		complex<double> z0;
		complex<double> c;
		int		ix;
		int		iy;
		int		n;
		double		x, y;
		double		x0, y0;
		double		width, height;
	        double          Scale;
	        int             Width, Height;
		TFPointData	pd;
//		TFDivergenceMethod	*divergence_method;
		TFOutputMethod		*output_method;

	        Scale = Parameter->Scale;
	        Width = Parameter->Width;
	        Height = Parameter->Height;

//	        FractalField->SetSize (Width, Height);

//		divergence_method = DivergenceMethod->New();
		output_method = OutputMethod->New();

		width  = Scale;
		height = Scale*Height/Width;

		for (iy = offset ; iy < Height ; iy += TFMultiThreadNum)
		{
			y = height*(Height/2 - iy)/Height;

			for (ix = 0 ; ix < Width ; ix++)
			{
	        		x = width*(ix - Width/2)/Width;

	                        if (Parameter->FractalType == TF_FRACTAL_TYPE_MANDELBROT)
	                        {
				        c = Parameter->Viewpoint + complex<double>(x, y);
	                                z = Parameter->FractalParameter;
	                        }
	                        else
	                        {
	                        	c = Parameter->FractalParameter;
				        z = Parameter->Viewpoint + complex<double>(x, y);
	                        }

				output_method->Init();
				for (n = 1 ; n <= Depth ; n++)
				{
					z0 = z;
					z = Parameter->FractalMethod->FractalFunction(z, c);
					output_method->SetOutput (z, n);
					if (norm(z) > Range
					 || DivergenceMethod->DivergenceFunction(z, n))
						break;
				}

				output_method->GetOutput (&pd);
				FractalField->Set (ix, iy, &pd);
			}
		}

		delete output_method;
	}

};

/* Effector ******************************************************************/

struct	TFConvertData
{
	double		X;
	TColor		Y;
};

class	TFEffector;

class	TFThreadEffector: public TThread
{
private:
	TFEffector	*Effector;
	int		Offset;

public:
	__fastcall TFThreadEffector (TFEffector *e, int offset)
		 : TThread(false)
	{
		Effector = e;
		Offset = offset;
	}

	void __fastcall Execute(void);
};

class   TFEffector: public TFObject
{
public:
	static TList		*List;

private:
	static int		ID;

	TFGenerator		*FGenerator;
	TFRenderingMethod	*FRenderingMethod;
	int			FDifferential;
	TList			*ConvertData;	// TFConvertData*
	TFRGBField		FRGBField;

	void __fastcall SetGenerator (TFGenerator *g)
	{
		FGenerator = g;
		Modify = TF_MODIFY;
	}

	void __fastcall SetRenderingMethod (TFRenderingMethod *rm)
	{
		if (FRenderingMethod) delete FRenderingMethod;
		FRenderingMethod = rm;
		Modify = TF_MODIFY;
	}

	void __fastcall SetDifferential (int flag)
	{
		FDifferential = flag;
		Modify = TF_MODIFY;
	}

	double __fastcall GetX(int index)
	{
		TFConvertData	*p;

		p = (TFConvertData *)ConvertData->Items[index];
		return (p->X);
        }

	TColor __fastcall GetY(int index)
	{
		TFConvertData	*p;

		p = (TFConvertData *)ConvertData->Items[index];
		return (p->Y);
        }

	void __fastcall SetX(int index, double x)
	{
		TFConvertData    *p;

		p = (TFConvertData *)ConvertData->Items[index];
		p->X = x;
		Modify = TF_MODIFY;
	}

	void __fastcall SetY(int index, TColor y)
	{
		TFConvertData    *p;

		p = (TFConvertData *)ConvertData->Items[index];
		p->Y = y;
		Modify = TF_MODIFY;
	}

	int __fastcall GetCount(void)
	{ return (ConvertData->Count); }

	TFRGBField * __fastcall GetRGBField(void)
	{ return (&FRGBField); };


	AnsiString __fastcall OutputSourceMember (AnsiString indent)
	{
		AnsiString      output;
		int		r, g, b;
		int             i;

		output += indent + "Generator: " + Generator->Name + "\n";
		output += indent + "RenderingMethod: " + RenderingMethod->OutputSource(indent);
		output += indent + "Differential: " + (Differential ? "on" : "off") + "\n";
		for (i = 0 ; i < ConvertData->Count ; i++)
		{
			TFLib::ToRGB(Y[i], &r, &g, &b);
			output += indent + "ConvertData: " + X[i] + " " + r + " " + g + " " + b + "\n";
		}
		return (output);
	}


	bool __fastcall InputSourceMember (AnsiString *src)
	{
		AnsiString	word;
		double		x, y;
		int		r, g, b;
		int		i;
		TFRenderingMethod *rm;

		if (TFLib::SkipWord(src, "Generator:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		Generator = TFGenerator::SearchGenerator(word);
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "RenderingMethod:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		rm = TFRenderingMethod::SearchMethod(word);
		if (rm == NULL) return (TFFAILD);
		RenderingMethod = rm->New();
		*src = word + "\n" + *src;
		if (RenderingMethod->InputSource(src)) return (TFFAILD);

		if (TFLib::SkipWord(src, "Differential:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		if (word == "on")
			Differential = true;
		else if (word == "off")
			Differential = false;
		else
			return (TFFAILD);
		TFLib::SkipSpaceCR (src);

                for (i = 0 ;  ConvertData->Count > 0 ; i++)
		{
                        delete ConvertData->Items[0];
			ConvertData->Delete (0);
		}

		while (1)
		{
			if (TFLib::SkipWord(src, "ConvertData:")) break;
			if (TFLib::GetNumber(src, &x)) return (TFFAILD);
			if (TFLib::GetNumber(src, &y)) return (TFFAILD);
			r = y;
			if (TFLib::GetNumber(src, &y)) return (TFFAILD);
			g = y;
			if (TFLib::GetNumber(src, &y)) return (TFFAILD);
			b = y;
			AddEntry (x, TFLib::ToColor(r, g, b));
			TFLib::SkipSpaceCR (src);
		}

		return (TFSUCCESS);
	}


public:
#if 0
	__fastcall TFEffector(TFGenerator *g)
	{
		extern TFRenderingMethod_Count	RenderingMethod_Count;

		FGenerator = g;
		RenderingMethod = RenderingMethod_Count.New();

		TFConvertData	*cd;

		ConvertData = new TList;

		cd = new TFConvertData;
		cd->X = 0;
		cd->Y = TFLib::ToColor(0, 0, 0);
		ConvertData->Add(cd);

		cd = new TFConvertData;
		cd->X = 1;
		cd->Y = TFLib::ToColor(255, 255, 255);
		ConvertData->Add(cd);

		Name = "Effector" + (AnsiString)++ID;
	}
#endif

	__fastcall TFEffector (TFEffector *effector = NULL)
	{
		extern TFRenderingMethod_Count	RenderingMethod_Count;

		if (effector == NULL)
		{
			FRenderingMethod = RenderingMethod_Count.New();

			TFConvertData	*cd;

			ConvertData = new TList;

			cd = new TFConvertData;
			cd->X = 0;
			cd->Y = TFLib::ToColor(0, 0, 0);
			ConvertData->Add(cd);

			cd = new TFConvertData;
			cd->X = 1;
			cd->Y = TFLib::ToColor(255, 255, 255);
			ConvertData->Add(cd);
		}
		else
		{
			FGenerator = effector->Generator;
			RenderingMethod = effector->RenderingMethod->New();
        	        ConvertData = new TList;

	                TFConvertData	*convertdata;
        	        for (int i = 0 ; i < effector->ConvertData->Count ; i++)
                	{
                        	convertdata = new TFConvertData;
				*convertdata = *(TFConvertData *)effector->ConvertData->Items[i];
                        	ConvertData->Add (convertdata);
	                }
		}

		Name = "Effector" + (AnsiString)++ID;
		Modify = TF_MODIFY;
		List->Add(this);
	}

	__fastcall ~TFEffector(void)
	{
                int             i;

		delete RenderingMethod;

                for (i = 0 ; i < ConvertData->Count ; i++)
                        delete ConvertData->Items[i];

                delete ConvertData;
		List->Delete(List->IndexOf(this));
	}


	__property TFGenerator * Generator = { read = FGenerator, write = SetGenerator };
	__property TFRenderingMethod * RenderingMethod = { read = FRenderingMethod, write = SetRenderingMethod };
	__property int Differential = { read = FDifferential, write = SetDifferential };
	__property double X[int n] = {read = GetX, write = SetX };
	__property TColor Y[int n] = {read = GetY, write = SetY };
	__property int Count = { read = GetCount };
	__property TFRGBField * RGBField = { read = GetRGBField };


	static TFEffector * __fastcall SearchEffector(AnsiString name)
	{
		int		i;
		TFEffector	*e = NULL;

		for (i = 0 ; i < List->Count ; i++)
		{
			e = (TFEffector *)List->Items[i];
			if (e->Name == name) return (e);
		}
		return (NULL);
	}


	int __fastcall IndexOf(double x)
	{
		int		i;
		TFConvertData	*p;

		for (i = 0 ; i < ConvertData->Count ; i++)
		{
			p = (TFConvertData *)ConvertData->Items[i];
			if (p->X == x) return (i);
		}

		return (-1);
	}


	void __fastcall AddEntry(double x, TColor y)
	{
		TFConvertData	*p;
		int             i;

		for (i = 0 ; i < ConvertData->Count ; i++)
		{
			p = (TFConvertData *)ConvertData->Items[i];
			if (p->X >= x) break;
		}

		if (i < ConvertData->Count && p->X == x)
		{
			p->Y = y;
			Modify = TF_MODIFY;
			return;
		}

		p = new TFConvertData;
		p->X = x;
		p->Y = y;
		ConvertData->Insert (i, p);
		Modify = TF_MODIFY;
	}


	void __fastcall DelEntry(int index)
	{
		TFConvertData	*p;

		p = (TFConvertData *)ConvertData->Items[index];
		delete p;
		ConvertData->Delete (index);
		Modify = TF_MODIFY;
	}


	double __fastcall Convert(double x)
	{
		TFConvertData	*p, *p0;
		int		i;
		double		lx, hx;
		TColor		lv, hv;
		TColor		value;


		p = NULL;

		for (i = 0 ; i < ConvertData->Count ; i++)
		{
			p = (TFConvertData *)ConvertData->Items[i];
			if (p->X >= x) break;
		}

		if (i >= ConvertData->Count) p0 = p, p = NULL;

		if (i > 0)
			p0 = (TFConvertData *)ConvertData->Items[i - 1];
		else
			p0 = NULL;

		value = TColor(0, 0, 0);
		lx = hx = x;
		lv = hv = TColor(0, 0, 0);

		if (p == NULL && p0 == NULL) return (value);

		if (p0 == NULL)
			lv = p->Y;
		else
		{
			lx = p0->X;
			lv = p0->Y;
		}

		if (p == NULL)
			hv = p0->Y;
		else
		{
			hx = p->X;
			hv = p->Y;
                }

		if (lx == hx)
			value = lv;
		else
		{
			int	lr, lg, lb, hr, hg, hb;
			int	r, g, b;

			TFLib::ToRGB (lv, &lr, &lg, &lb);
			TFLib::ToRGB (hv, &hr, &hg, &hb);
			r = (lr*(hx - x) + hr*(x - lx))/(hx - lx);
			g = (lg*(hx - x) + hg*(x - lx))/(hx - lx);
			b = (lb*(hx - x) + hb*(x - lx))/(hx - lx);
			value = TFLib::ToColor(r, g, b);
		}

		return (value);
	}


	bool __fastcall Update(void)
	{
		int	modify;


		if (Modify == TF_NOMODIFY || Modify == TF_UPDATED)
			return (Modify);

		modify = Generator->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;
		modify = RenderingMethod->Update();
		if (modify == TF_UPDATED) Modify = TF_MODIFY;

		if (Modify == TF_MODIFY)
		{
			Effect();
			Modify = TF_UPDATED;
		}
		else
			Modify = TF_NOMODIFY;

		return (Modify);
	}

	void __fastcall CompleteUpdate(void)
	{
		Generator->CompleteUpdate();
		RenderingMethod->CompleteUpdate();
		Modify = TF_NOCHECK;
	}


	void __fastcall Effect(void)
	{
		TFThreadEffector	**e;
		int			width, height;
		int			i;

		width  = Generator->FractalField->Width;
		height = Generator->FractalField->Height;

		if (width != RGBField->Width || height != RGBField->Height)
			RGBField->SetSize (width, height);

		e = new TFThreadEffector*[TFMultiThreadNum];

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			e[i] = new TFThreadEffector(this, i);

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			e[i]->WaitFor();

		delete	e;
	}

	void __fastcall Effect0(int offset)
	{
		int		width, height;
		int		x, y;
		int		count, count0;
		complex<double>	z, v;
		TFPointData	pd, pd0;
		TFRGB		rgb;
		double		xx;

		width  = Generator->FractalField->Width;
		height = Generator->FractalField->Height;

//		if (width != RGBField->Width || height != RGBField->Height)
//			RGBField->SetSize (width, height);

		for (y = offset ; y < height ; y += TFMultiThreadNum)
		{
			for (x = 0 ; x < width ; x++)
			{
				pd = *Generator->FractalField->Get (x, y);

				if (Differential)
				{
					if (x == 0 || y == 0)
						pd0 = pd;
					else
						pd0 = *Generator->FractalField->Get (x - 1, y - 1);
					pd.z     -= pd0.z;
					pd.count -= pd0.count;
				}

				xx = RenderingMethod->RenderingFunction(pd.z, pd.count);
				rgb.color = (TColor)Convert(xx);
				RGBField->Set (x, y, &rgb);
			}
		}

		Modify = false;
	}

};


/* Mixer *********************************************************************/

enum
{
        TF_TRANSPARENT_TYPE_ADD = 0,
        TF_TRANSPARENT_TYPE_MIX,
        TF_TRANSPARENT_TYPE_FADE,

        TF_TRANSPARENT_TYPE_NUM,
};


class	TFMixer;

class	TFThreadMixer: public TThread
{
private:
	TFMixer		*Mixer;
	int		Offset;

public:
	__fastcall TFThreadMixer (TFMixer *m, int offset)
		 : TThread(false)
	{
		Mixer = m;
		Offset = offset;
	}

	void __fastcall Execute(void);
};


class TFMixer: public TFObject
{
public:
	static TList	*List;

private:
	static int	ID;
	AnsiString	*TransparenceTypeList;

	TFMixer		*FPrevLayer;
	TList		*SourceList;
	TList		*MaskList;
	TList		*TransparenceList;
	TList		*TransparenceMaskList;
	int		FTransparenceType;
	int		FMaskSW;
	TFRGBField	FRGBField;

	void __fastcall SetPrevLayer (TFMixer *pl)
	{
		FPrevLayer = pl;
		Modify = TF_MODIFY;
	}

	void __fastcall SetTransparenceType (int tt)
	{
		FTransparenceType = tt;
		Modify = TF_MODIFY;
	}

	void __fastcall SetMaskSW (int sw)
	{
		FMaskSW = sw;
	}

	TFRGBField * __fastcall GetRGBField(void)
	{ return (&FRGBField); };

	AnsiString __fastcall GetTransparenceTypeName(void)
	{ return (TransparenceTypeList[TransparenceType]); }


	AnsiString __fastcall OutputSourceMember (AnsiString indent)
	{
		AnsiString      output;
		TFEffector	*e;
		int		i;

		for (i = 0 ; i < SourceList->Count ; i++)
		{
			e = (TFEffector *)SourceList->Items[i];
			output += indent + "SourceList: " + e->Name + "\n";
		}

		for (i = 0 ; i < MaskList->Count ; i++)
		{
			e = (TFEffector *)MaskList->Items[i];
			output += indent + "MaskList: " + e->Name + "\n";
		}

		for (i = 0 ; i < TransparenceList->Count ; i++)
		{
			e = (TFEffector *)TransparenceList->Items[i];
			output += indent + "TransparenceList: " + e->Name + "\n";
		}

		for (i = 0 ; i < TransparenceMaskList->Count ; i++)
		{
			e = (TFEffector *)TransparenceMaskList->Items[i];
			output += indent + "TransparenceMaskList: " + e->Name + "\n";
		}

		output += indent + "TransparenceType: " + TransparenceTypeName + "\n";
		output += indent + "MaskSW: " + (MaskSW ? "on" : "off") + "\n";
		return (output);
	}


	bool __fastcall InputSourceMember (AnsiString *src)
	{
		AnsiString	word;
		double		x, y;
		int		i;


		while (1)
		{
			if (TFLib::SkipWord(src, "SourceList:")) break;
			word = TFLib::GetWord(src);
			SourceList->Add(TFEffector::SearchEffector(word));
			TFLib::SkipSpaceCR (src);
		}

		while (1)
		{
			if (TFLib::SkipWord(src, "MaskList:")) break;
			word = TFLib::GetWord(src);
			MaskList->Add(TFEffector::SearchEffector(word));
			TFLib::SkipSpaceCR (src);
		}

		while (1)
		{
			if (TFLib::SkipWord(src, "TransparenceList:")) break;
			word = TFLib::GetWord(src);
			TransparenceList->Add(TFEffector::SearchEffector(word));
			TFLib::SkipSpaceCR (src);
		}

		while (1)
		{
			if (TFLib::SkipWord(src, "TransparenceMaskList:")) break;
			word = TFLib::GetWord(src);
			TransparenceMaskList->Add(TFEffector::SearchEffector(word));
			TFLib::SkipSpaceCR (src);
		}

		if (TFLib::SkipWord(src, "TransparenceType:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		for (i = 0 ; i < TF_TRANSPARENT_TYPE_NUM ; i++)
		{
			if (TransparenceTypeList[i] == word)
			{
				TransparenceType = i;
				break;
			}
		}
		if (i >= TF_TRANSPARENT_TYPE_NUM) return (TFFAILD);
		TFLib::SkipSpaceCR (src);

		if (TFLib::SkipWord(src, "MaskSW:")) return (TFFAILD);
		word = TFLib::GetWord(src);
		if (word == "on")
			MaskSW = true;
		else if (word == "off")
			MaskSW = false;
		else
			return (TFFAILD);
		TFLib::SkipSpaceCR (src);

		return (TFSUCCESS);
	}


public:
	__fastcall TFMixer(void)
	{
		int			i;
		static char	*tt_list[] =
		{
			"和合成",
			"透明合成１",
			"透明合成２"
		};

		TransparenceTypeList = new AnsiString[TF_TRANSPARENT_TYPE_NUM];
		for (i = 0 ; i < TF_TRANSPARENT_TYPE_NUM ; i++)
			TransparenceTypeList[i] = tt_list[i];
		PrevLayer = (List->Count == 0) ? NULL : (TFMixer *)List->Last();
		SourceList = new TList;
		MaskList = new TList;
		TransparenceList = new TList;
		TransparenceMaskList = new TList;
		MaskSW = 0;

		Name = "Mixer" + (AnsiString)++ID;
		List->Add(this);
	}

	__fastcall ~TFMixer(void)
	{
		delete[] TransparenceTypeList;
		delete SourceList;
		delete MaskList;
		delete TransparenceList;
		delete TransparenceMaskList;
		List->Delete(List->IndexOf(this));
	}

	__property TFMixer * PrevLayer = { read = FPrevLayer, write = SetPrevLayer };
	__property int TransparenceType = { read = FTransparenceType, write = SetTransparenceType };
	__property AnsiString TransparenceTypeName = { read = GetTransparenceTypeName };
	__property int MaskSW = { read = FMaskSW, write = SetMaskSW };
	__property TFRGBField * RGBField = { read = GetRGBField };


	void __fastcall AddSource (TFEffector *e)
	{
		SourceList->Add(e);
		Modify = TF_MODIFY;
	}

	void __fastcall DelSource (TFEffector *e)
	{
		SourceList->Delete (SourceList->IndexOf(e));
		Modify = TF_MODIFY;
	}

	void __fastcall AddMask (TFEffector *e)
	{
		MaskList->Add(e);
		Modify = TF_MODIFY;
	}

	void __fastcall DelMask (TFEffector *e)
	{
		MaskList->Delete (MaskList->IndexOf(e));
		Modify = TF_MODIFY;
	}

	void __fastcall AddTransparence (TFEffector *e)
	{
		TransparenceList->Add(e);
		Modify = TF_MODIFY;
	}

	void __fastcall DelTransparence (TFEffector *e)
	{
		TransparenceList->Delete (TransparenceList->IndexOf(e));
		Modify = TF_MODIFY;
	}

	void __fastcall AddTransparenceMask (TFEffector *e)
	{
		TransparenceMaskList->Add(e);
		Modify = TF_MODIFY;
	}

	void __fastcall DelTransparenceMask (TFEffector *e)
	{
		TransparenceMaskList->Delete (TransparenceMaskList->IndexOf(e));
		Modify = TF_MODIFY;
	}

	bool __fastcall Update(void)
	{
		int		modify;
		TFEffector	*e;
		int		i;


		if (Modify == TF_NOMODIFY || Modify == TF_UPDATED)
			return (Modify);

		if (PrevLayer)
		{
			modify = PrevLayer->Update();
			if (modify == TF_UPDATED) Modify = TF_MODIFY;
		}

		if (MaskSW)
		{
			if (Modify == TF_MODIFY)
			{
				Pass();
				Modify = TF_UPDATED;
			}
			else
				Modify = TF_NOMODIFY;

			return (Modify);
		}

		for (i = 0 ; i < SourceList->Count ; i++)
		{
			e = (TFEffector *)SourceList->Items[i];
			modify = e->Update();
			if (modify == TF_UPDATED) Modify = TF_MODIFY;
		}

		for (i = 0 ; i < MaskList->Count ; i++)
		{
			e = (TFEffector *)MaskList->Items[i];
			modify = e->Update();
			if (modify == TF_UPDATED) Modify = TF_MODIFY;
		}

		for (i = 0 ; i < TransparenceList->Count ; i++)
		{
			e = (TFEffector *)TransparenceList->Items[i];
			modify = e->Update();
			if (modify == TF_UPDATED) Modify = TF_MODIFY;
		}

		for (i = 0 ; i < TransparenceMaskList->Count ; i++)
		{
			e = (TFEffector *)TransparenceMaskList->Items[i];
			modify = e->Update();
			if (modify == TF_UPDATED) Modify = TF_MODIFY;
		}

		if (Modify == TF_MODIFY)
		{
			Mix();
			Modify = TF_UPDATED;
		}
		else
			Modify = TF_NOMODIFY;

		return (Modify);
	}

	void __fastcall CompleteUpdate(void)
	{
		TFEffector	*e;
		int		i;

		if (PrevLayer) PrevLayer->CompleteUpdate();

		if (MaskSW) return;

		for (i = 0 ; i < SourceList->Count ; i++)
		{
			e = (TFEffector *)SourceList->Items[i];
			e->CompleteUpdate();
		}

		for (i = 0 ; i < MaskList->Count ; i++)
		{
			e = (TFEffector *)MaskList->Items[i];
			e->CompleteUpdate();
		}

		for (i = 0 ; i < TransparenceList->Count ; i++)
		{
			e = (TFEffector *)TransparenceList->Items[i];
			e->CompleteUpdate();
		}

		for (i = 0 ; i < TransparenceMaskList->Count ; i++)
		{
			e = (TFEffector *)TransparenceMaskList->Items[i];
			e->CompleteUpdate();
		}

		Modify = TF_NOCHECK;
	}

	void _fastcall Pass(void)
	{
		int		width, height;
		int		x, y;
		TFRGB		rgb;

		if (PrevLayer)
		{
			width  = PrevLayer->RGBField->Width;
			height = PrevLayer->RGBField->Height;
		}
		else
		{
			TFEffector	*src;

			src = (TFEffector *)SourceList->First();
			width  = src->RGBField->Width;
			height = src->RGBField->Height;
		}

        	RGBField->SetSize (width, height);

		for (y = 0 ; y < height ; y ++)
		{
			for (x = 0 ; x < width ; x++)
			{
				if (PrevLayer)
					rgb = *PrevLayer->RGBField->Get(x, y);
				else
					rgb.color = (TColor)0;

                                RGBField->Set (x, y, &rgb);
                        }
                }
	}

	void __fastcall Mix(void)
	{
		TFThreadMixer		**m;
		int			width, height;
		int			i;

		if (PrevLayer
		 && PrevLayer->RGBField->Width > 0
		 && PrevLayer->RGBField->Height > 0)
		{
			width  = PrevLayer->RGBField->Width;
			height = PrevLayer->RGBField->Height;
		}
		else
		{
			TFEffector	*src;

			src = (TFEffector *)SourceList->First();
			width  = src->RGBField->Width;
			height = src->RGBField->Height;
		}

        	RGBField->SetSize (width, height);

		m = new TFThreadMixer*[TFMultiThreadNum];

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			m[i] = new TFThreadMixer(this, i);

		for (i = 0 ; i < TFMultiThreadNum ; i++)
			m[i]->WaitFor();

		delete	m;
	}

	void __fastcall Mix0(int offset)
	{
		int		width, height;
		int		x, y;
		TFRGB		rgb;
		int		i;
		int		br, bg, bb;
		int		sr, sg, sb;
		int		mr, mg, mb;
		int		tr, tg, tb;
		int		tmr, tmg, tmb;
		TFEffector	*e;


		if (PrevLayer
		 && PrevLayer->RGBField->Width > 0
		 && PrevLayer->RGBField->Height > 0)
		{
			width  = PrevLayer->RGBField->Width;
			height = PrevLayer->RGBField->Height;
		}
		else
		{
			TFEffector	*src;

			src = (TFEffector *)SourceList->First();
			width  = src->RGBField->Width;
			height = src->RGBField->Height;
		}

//        	RGBField->SetSize (width, height);

		for (y = offset ; y < height ; y += TFMultiThreadNum)
		{
			for (x = 0 ; x < width ; x++)
			{
				if (PrevLayer
				 && PrevLayer->RGBField->Width != 0
				 && PrevLayer->RGBField->Height != 0)
				{
					rgb = *PrevLayer->RGBField->Get(x, y);
					br = rgb.r;
					bg = rgb.g;
					bb = rgb.b;
				}
				else
				{
					br = bg = bb = 0;
				}

				sr = sg = sb = 0;
				for (i = 0 ; i < SourceList->Count ; i++)
				{
					e = (TFEffector *)SourceList->Items[i];
					rgb = *e->RGBField->Get (x, y);
					sr += rgb.r;
					sg += rgb.g;
					sb += rgb.b;
				}
#if 0
				sr /= SourceList->Count;
				sg /= SourceList->Count;
				sb /= SourceList->Count;
#endif

				mr = mg = mb = 0;
				for (i = 0 ; i < MaskList->Count ; i++)
				{
					e = (TFEffector *)MaskList->Items[i];
					rgb = *e->RGBField->Get(x, y);
					mr += rgb.r;
					mg += rgb.g;
					mb += rgb.b;
				}
				if (MaskList->Count == 0)
				{
					mr = 255;
					mg = 255;
					mb = 255;
				}
				else
				{
#if 0
					mr /= MaskList->Count;
					mg /= MaskList->Count;
					mb /= MaskList->Count;
#endif
				}

				tr = tg = tb = 0;
				for (i = 0 ; i < TransparenceList->Count ; i++)
				{
					e = (TFEffector *)TransparenceList->Items[i];
					rgb = *e->RGBField->Get(x, y);
					tr += rgb.r;
					tg += rgb.g;
					tb += rgb.b;
				}
				if (TransparenceList->Count == 0)
				{
					tr = 255;
					tg = 255;
					tb = 255;
				}
				else
				{
#if 0
					tr /= TransparenceList->Count;
					tg /= TransparenceList->Count;
					tb /= TransparenceList->Count;
#endif
				}

				tmr = tmg = tmb = 0;
				for (i = 0 ; i < TransparenceMaskList->Count ; i++)
				{
					e = (TFEffector *)TransparenceMaskList->Items[i];
					rgb = *e->RGBField->Get(x, y);
					tmr += rgb.r;
					tmg += rgb.g;
					tmb += rgb.b;
				}
				if (TransparenceMaskList->Count == 0)
				{
					tmr = 255;
					tmg = 255;
					tmb = 255;
				}
				else
				{
#if 0
					tmr /= TransparenceMaskList->Count;
					tmg /= TransparenceMaskList->Count;
					tmb /= TransparenceMaskList->Count;
#endif
				}

				sr = sr*mr/255;
				sg = sg*mg/255;
				sb = sb*mb/255;

				tr = tr*tmr/255;
				tg = tg*tmg/255;
				tb = tb*tmb/255;
				TFLib::RegularRGB(&tr, &tg, &tb);

				switch (TransparenceType)
				{
				case TF_TRANSPARENT_TYPE_ADD:
					break;

				case TF_TRANSPARENT_TYPE_MIX:
					br = br*tr/255;
					bg = bg*tg/255;
					bb = bb*tb/255;
					break;

				case TF_TRANSPARENT_TYPE_FADE:
					br = br*tr/255;
					bg = bg*tg/255;
					bb = bb*tb/255;
					sr = sr*(255 - tr)/255;
					sg = sg*(255 - tg)/255;
					sb = sb*(255 - tb)/255;
					break;

				default:
					break;
				}

				sr += br;
				sg += bg;
				sb += bb;
				TFLib::RegularRGB(&sr, &sg, &sb);

#if 0
				if (sr > 255 || sg > 255 || sb > 255)
				{
					int	max_bright;

					max_bright = sr;
					if (max_bright < sg) max_bright = sg;
					if (max_bright < sb) max_bright = sb;
					sr = sr*255/max_bright;
					sg = sg*255/max_bright;
					sb = sb*255/max_bright;
				}
#endif

				rgb.r = sr;
				rgb.g = sg;
				rgb.b = sb;

                                RGBField->Set (x, y, &rgb);
                        }
                }
	}


	void __fastcall Draw (TCanvas *canvas)
	{
		int		x, y;

		for (y = 0 ; y < RGBField->Height ; y ++)
			for (x = 0 ; x < RGBField->Width ; x++)
			{
				TColor	c;
				c = RGBField->Get(x, y)->color;
				canvas->Pixels[x][y] = c;
			}
        }


};


/* T-Fract Main **************************************************************/

class	TFMain;

class	TFThreadMain: public TThread
{
private:
	TFMain		*Main;
	TCanvas		*Canvas;

public:
	__fastcall TFThreadMain(TFMain *main, TCanvas *canvas) : TThread(false)
	{
		Main = main;
		Canvas = canvas;
	}

	void __fastcall Execute(void);
	void __fastcall DrawCanvas(void);
};

class	TFMain
{
private:
	TFParameter	FParameter;
//	TList		*GeneratorList;
//	TList		*EffectorList;
//	TList		*MixerList;

	TFParameter * __fastcall GetParameter(void)
	{ return (&FParameter); }

	TFGenerator * __fastcall GetGenerator(int n)
	{ return ( (TFGenerator *)TFGenerator::List->Items[n] ); }

	TFEffector * __fastcall GetEffector(int n)
	{ return ( (TFEffector *)TFEffector::List->Items[n] ); }

	TFMixer * __fastcall GetMixer(int n)
	{ return ( (TFMixer *)TFMixer::List->Items[n] ); }

public:
	__fastcall TFMain(void)
	{
		TFGenerator	*g;
		TFEffector	*e;
		TFMixer		*m;
#if 0
		GeneratorList = new TList;
		EffectorList = new TList;
		MixerList = new TList;
#endif
		g = new TFGenerator();
		g->Parameter = Parameter;
//		GeneratorList->Add (g);

		e = new TFEffector();
		e->Generator = g;
//		EffectorList->Add (e);

		m = new TFMixer;
		m->AddSource (e);
//		MixerList->Add (m);
	}

	__fastcall ~TFMain(void)
	{

		while (TFGenerator::List->Count > 0)
			delete (TFGenerator *)TFGenerator::List->Items[0];

		while (TFEffector::List->Count > 0)
			delete (TFEffector *)TFEffector::List->Items[0];

		while (TFMixer::List->Count > 0)
			delete (TFMixer *)TFMixer::List->Items[0];

#if 0
		delete GeneratorList;
		delete EffectorList;
		delete MixerList;
#endif
	}

	__property TFParameter * Parameter = { read = GetParameter };
	__property TFGenerator * Generator[int n] = { read = GetGenerator };
	__property TFEffector * Effector[int n] = { read = GetEffector };
	__property TFMixer * Mixer[int n] = { read = GetMixer };

#if 0
	TFGenerator * __fastcall AddGenerator(void)
	{
		TFGenerator	*g;

		g = new TFGenerator();
		g->Parameter = Parameter;
		GeneratorList->Add (g);
		return (g);
	}

	void __fastcall DelGenerator (TFGenerator *g)
	{
		GeneratorList->Delete (GeneratorList->IndexOf(g));
		delete g;
	}

	TFEffector * __fastcall AddEffector (TFGenerator *g)
	{
		TFEffector	*e;

		e = new TFEffector();
		e->Generator = g;
		EffectorList->Add (e);
		return (e);
	}

	void __fastcall DelEffector (TFEffector *e)
	{
		EffectorList->Delete (EffectorList->IndexOf(e));
		delete e;
	}

	TFMixer * __fastcall AddMixer(void)
	{
		TFMixer		*m;

		m = new TFMixer();
		MixerList->Add (m);
		return (m);
	}

	TFMixer * __fastcall InsertMixer (TFMixer *m, TFMixer *pm)
	{
		int	index, pindex;

		if (m == NULL) m = new TFMixer();
		if (m == pm) return (m);

		index = MixerList->IndexOf(m);
		if (index >= 0) MixerList->Delete (index);

		pindex = MixerList->IndexOf(pm);
		MixerList->Insert (pindex + 1, m);
		return (m);
	}

	void __fastcall DelMixer (TFMixer *m)
	{
		MixerList->Delete (MixerList->IndexOf(m));
		delete m;
	}
#endif

	void __fastcall Draw(TCanvas *canvas)
	{
		TFThreadMain	*main = new TFThreadMain(this, canvas);
	}

	void __fastcall Draw0(TCanvas *canvas)
	{
		TFMixer		*output_mixer;

		output_mixer = (TFMixer *)TFMixer::List->Last();
		output_mixer->Update();
		output_mixer->CompleteUpdate();
	}

	AnsiString __fastcall OutputSource(void)
	{
		AnsiString	output;
		int		i;
		TFGenerator	*g;
		TFEffector	*e;
		TFMixer		*m;

		output = "";
		output += "Parameter: " + Parameter->OutputSource ("");

		for (i = 0 ; i < TFGenerator::List->Count ; i++)
		{
			g = (TFGenerator *)TFGenerator::List->Items[i];
			output += "Generator: " + g->OutputSource ("");
		}

		for (i = 0 ; i < TFEffector::List->Count ; i++)
		{
			e = (TFEffector *)TFEffector::List->Items[i];
			output += "Effector: " + e->OutputSource ("");
		}

		for (i = 0 ; i < TFMixer::List->Count ; i++)
		{
			m = (TFMixer *)TFMixer::List->Items[i];
			output += "Mixer: " + m->OutputSource ("");
		}

		return (output);
	}

	bool __fastcall InputSource (AnsiString *source)
	{
		int	i;

		while (TFGenerator::List->Count > 0)
			delete (TFGenerator *)TFGenerator::List->Items[0];

		while (TFEffector::List->Count > 0)
			delete (TFEffector *)TFEffector::List->Items[0];

		while (TFMixer::List->Count > 0)
			delete (TFMixer *)TFMixer::List->Items[0];


		TFLib::SkipSpaceCR (source);
		if (TFLib::SkipWord(source, "Parameter:")) return (TFFAILD);
		if (Parameter->InputSource(source)) return (TFFAILD);

		while (1)
		{
			TFGenerator	*g;

			if (TFLib::SkipWord(source, "Generator:")) break;
			g = new TFGenerator();
			g->Parameter = Parameter;
			if (g->InputSource(source)) return (TFFAILD);
		}

		while (1)
		{
			TFEffector	*e;

			if (TFLib::SkipWord(source, "Effector:")) break;
			e = new TFEffector();
			if (e->InputSource(source)) return (TFFAILD);
		}

		while (1)
		{
			TFMixer		*m;

			if (TFLib::SkipWord(source, "Mixer:")) break;
			m = new TFMixer();
			if (m->InputSource(source)) return (TFFAILD);
		}

		return (TFSUCCESS);
	}


	static	void __fastcall Main(void)
	{

	}

};

/* Prototype *****************************************************************/




/* Extern ********************************************************************/




/* End of Program ************************************************************/

