#ifndef _VECIMAGE_H_
#define _VECIMAGE_H_

#include "stringa.h"
#include "raster.h"


#define PSS_LineColor 1
#define PSS_LineStyle 2
#define PSS_LineWidth 4
#define PSS_FillColor 8

#define mm2PSu(x)   ( (float)(x)*71/25.4 )

void Font2PS(string & Text, const float FontSize, const char *FontName="Times-Roman");
void Color2PS(string & Text, const RGB_Record & TextColor);


class CpTranslator;


typedef struct
{
	float FontSize, FontSizeW;	///< Size of font in [mm].
	WORD FontWeight;
	SWORD FontOrientation10;	///< Text rotation request.
        CpTranslator *ConvertCpg;
        
	char FontItallic;
	char dirty;
	char FillPattern;
	BYTE LineStyle;
        BYTE PolyFillMode;		///< 0-standard; 1-alternating

	float LineWidth;
	RGB_Record FillColor;
        BYTE FillTransparency;
        RGB_Record FillBackground;

	RGB_Record LineColor;
	RGB_Record TextColor;

        bool FirstTimeFix;
} PS_StateC;


class PS_State: public PS_StateC
{
public:
	PS_State(void);
	RGB_Record PaperBackground;

	string FontName;
};


void PS_Attr(string & PSData, PS_State *PSS);
void FillObjectPS(float MinPolyX, float MaxPolyX, float MinPolyY, float MaxPolyY, string & PSData, PS_State *PSS);


class AbstractTransformXY
{
public:
  virtual void ApplyTransform(float &x, float &y) const = 0;
};


/** This functor class is used for resizing image data. */
class vecResizeXY: public AbstractTransformXY
{
public:
  vecResizeXY(const float iniScale) {Scale=iniScale;}

  virtual void ApplyTransform(float &x, float &y) const {x*=Scale; y*=Scale;}

  float Scale;
};



///////////////////////////////////////////////////////////

class VectorAttribute
{
public:
  virtual ~VectorAttribute() {}
  virtual void prepExport(PS_State *PSS) const = 0;
};

class vecPen: public VectorAttribute
{
public:
  RGB_Record LineColor;
  unsigned char LineStyle;
  float PenWidth;

  vecPen(void);
  vecPen(const PS_State &PSS) {AttribFromPSS(PSS);}

  virtual void prepExport(PS_State *PSS) const;
  void AttribFromPSS(const PS_State &PSS);
};


class vecBrush: public VectorAttribute
{
public:
  RGB_Record FillColor;
  unsigned char BrushStyle;

  vecBrush() {BrushStyle=1;}
  vecBrush(const PS_State &PSS);

  virtual void prepExport(PS_State *PSS) const;
  virtual void FeaturesEPS(unsigned & Feature) const;
  void AttribFromPSS(const PS_State &PSS);
};


class vecFont: public VectorAttribute
{
public:
  vecFont();
  vecFont(const PS_State &PSS);
  virtual void prepExport(PS_State *PSS) const;

  CpTranslator *ConvertCpg;
  RGB_Record TextColor;
  float FontSize, FontSizeW;
  WORD Weight;
  SWORD FontOrientation10;
  char Italic;
};


class vecTransform
{
public:
  float CenterX, CenterY;
  float RotAngle;
  float TranslateX, TranslateY;
  float ScaleX, ScaleY;
 
  vecTransform(void);
  bool ApplyTransform(string &s);
};


///////////////////////////////////////////////////////////

class VectorList;


/** Base Vector object. */
class VectorObject
{
public:
  virtual temp_string Export2EPS(PS_State *PSS=NULL) const {return temp_string();}
  virtual void Transform(const AbstractTransformXY &Tx) {}
  virtual void FeaturesEPS(unsigned & Feature) const {return;}
  virtual unsigned isInside(float xp, float yp) const {return 0;}

  virtual ~VectorObject() {NextObject=NULL;UpperCont=NULL;}
  VectorObject() {NextObject=NULL;UpperCont=NULL;}

  VectorObject *NextObject;
  VectorList *UpperCont;
};


class PsBlob: public VectorObject
{
public:
  char *Blob;

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const {return temp_string(Blob);}
  //virtual void Transform(const AbstractTransformXY &Tx) {}
  virtual void FeaturesEPS(unsigned & Feature) const;
  virtual ~PsBlob() {NextObject=NULL; if(Blob) {free(Blob);Blob=NULL;}}
  PsBlob(char *IniBlob) {Blob=IniBlob;}
};


/** List of plain Vector objects. */
class VectorList: public VectorObject
{
public:
  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  void Export2EPS(FILE *F, PS_State *PSS=NULL) const;
  virtual void FeaturesEPS(unsigned & Feature) const;
  VectorList(void);
  virtual ~VectorList();

  void AddObject(VectorObject *NewObj);
  virtual void Transform(const AbstractTransformXY &Tx);

  VectorObject *FirstObject;
  VectorObject *LastObject;
  int VectorObjects;
};


class VectorEllipse: public VectorObject, public vecPen, public vecBrush
{
public:
  VectorEllipse(float iniBottomRect, float iniTopRect, float iniRightRect, float iniLeftRect);
  virtual ~VectorEllipse();

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);
  virtual void FeaturesEPS(unsigned & Feature) const  {Feature|=EPS_DrawElipse; vecBrush::FeaturesEPS(Feature);}
  void AttribFromPSS(const PS_State &PSS) {vecPen::AttribFromPSS(PSS);vecBrush::AttribFromPSS(PSS);}

  vecTransform *Tx;
  int bAngle, eAngle;
  float	BottomRect, TopRect, RightRect, LeftRect;
};


class VectorLine: public VectorObject, public vecPen
{
public:
  VectorLine(int iniPointCount);
  VectorLine(float *iniBottomRect, int iniPointCount);
  virtual ~VectorLine();

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);

  int CountPoints;
  float *Points;  	///< x, y coordinate list of the line.
  bool Close;
};


class VectorCurve: public VectorLine, public vecBrush
{
public:
  VectorCurve(int iniPointCount): VectorLine(iniPointCount) {Filled=false;};
  VectorCurve(float *iniBottomRect, int iniPointCount): VectorLine(iniBottomRect,iniPointCount) {Filled=false;};

  void AttribFromPSS(const PS_State &PSS) {vecPen::AttribFromPSS(PSS);vecBrush::AttribFromPSS(PSS);}
  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;

  bool Filled;
};


class VectorPolygon: public VectorObject, public vecPen, public vecBrush
{
public:
  VectorPolygon(float *iniBottomRect, int iniPointCount);
  virtual ~VectorPolygon();

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);
  virtual unsigned isInside(float xp, float yp) const;
  void AttribFromPSS(const PS_State &PSS) {vecPen::AttribFromPSS(PSS);vecBrush::AttribFromPSS(PSS);}
  virtual void FeaturesEPS(unsigned & Feature) const  {vecBrush::FeaturesEPS(Feature);}

  //unsigned isInsideX(float xp, float yp) const;
  //unsigned isInsideY(float xp, float yp) const;

  int CountPoints;
  float *Points;  
  bool Close;
  bool Outline;  
};


class VectorRectangle: public VectorObject, public vecPen, public vecBrush
{
public:
  VectorRectangle(float iniBottomRect, float iniTopRect, float iniLeftRect, float iniRightRect);
  ~VectorRectangle();

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);
  virtual unsigned isInside(float xp, float yp) const;
  void AttribFromPSS(const PS_State &PSS) {vecPen::AttribFromPSS(PSS);vecBrush::AttribFromPSS(PSS);}

  vecTransform *Tx;
  float	BottomRect, TopRect, RightRect, LeftRect;
};


class VectorRectangleArc: public VectorRectangle
{
public:
  VectorRectangleArc(float iniBottomRect, float iniTopRect, float iniRightRect, float iniLeftRect, 
                     float iniHradius, float iniVradius);

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);

  float	Hradius, Vradius;
};


/** Container for text, must be included into ::TextContainer. */
class TextObject
{
public:
  string TargetFont;
  string contents;
  //WORD Weight;
  //char Itallic;
  float size;			///< Size of font in [mm].
  RGB_Record TextColor;
};


class TextContainer: public VectorObject
{
public:
  float PosX, PosY;		///< Tex start point.
  float FontOrientation;	///< Font rotation [deg]
  float RotCenterX, RotCenterY;

  TextContainer();
  virtual ~TextContainer();  

  virtual temp_string Export2EPS(PS_State *PSS=NULL) const;
  virtual void Transform(const AbstractTransformXY &Tx);
  virtual void FeaturesEPS(unsigned & Feature) const;
  
  void AddText(temp_string contents, const PS_State &PSS);
  void AddText(temp_string contents, const char *font, const PS_State &PSS);

  bool isEmpty(void) const;

  TextObject **Text;
  int TextObjects;
};



/// Vector image wrapper.
class VectorImage: public VectorList
{
public:
  mutable short UsageCount;
  PS_State PSS;

  VectorImage(void);
  VectorImage(VectorList &VecList, const PS_State & NewPSS);

  void Export2EPS(FILE *F) {VectorList::Export2EPS(F,&PSS);}
};


#endif
