#ifndef __MODULE_CAIRO_H__
#define __MODULE_CAIRO_H__

#include <ascript.h>
#include <cairo.h>
#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <cairo-svg.h>

AScript_BeginModule(cairo)

//-----------------------------------------------------------------------------
// Writer declaration
//-----------------------------------------------------------------------------
class Writer {
private:
	Signal _sig;
	Stream *_pStream;
	double _width, _height;
public:
	inline Writer(Signal sig, Stream *pStream, double width, double height) :
				_sig(sig), _pStream(pStream), _width(width), _height(height) {}
	~Writer();
	cairo_status_t WriteFunc(const unsigned char *data, unsigned int length);
	static cairo_status_t write_func(void *closure,
						const unsigned char *data, unsigned int length);
	inline Stream *GetStream() { return _pStream; }
	inline double GetWidth() const { return _width; }
	inline double GetHeight() const { return _height; }
};

//-----------------------------------------------------------------------------
// Object_FontExtents declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(FontExtents);

class Object_FontExtents : public Object {
private:
	cairo_font_extents_t _font_extents;
public:
	AScript_DeclareObjectAccessor(FontExtents)
public:
	inline Object_FontExtents(const cairo_font_extents_t &font_extents) :
			Object(AScript_PrivClass(FontExtents)), _font_extents(font_extents) {}
	virtual ~Object_FontExtents();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_font_extents_t &GetFontExtents() { return _font_extents; }
};

//-----------------------------------------------------------------------------
// Object_TextExtents declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(TextExtents);

class Object_TextExtents : public Object {
private:
	cairo_text_extents_t _text_extents;
public:
	AScript_DeclareObjectAccessor(TextExtents)
public:
	inline Object_TextExtents(const cairo_text_extents_t &text_extents) :
			Object(AScript_PrivClass(TextExtents)), _text_extents(text_extents) {}
	virtual ~Object_TextExtents();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_text_extents_t &GetTextExtents() { return _text_extents; }
};

//-----------------------------------------------------------------------------
// Object_Rectangle declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Rectangle);

class Object_Rectangle : public Object {
private:
	cairo_rectangle_t _rectangle;
public:
	AScript_DeclareObjectAccessor(Rectangle)
public:
	inline Object_Rectangle(const cairo_rectangle_t &rectangle) :
					Object(AScript_PrivClass(Rectangle)), _rectangle(rectangle) {}
	virtual ~Object_Rectangle();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_rectangle_t &GetRectangle() { return _rectangle; }
};

//-----------------------------------------------------------------------------
// Object_RectangleInt declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(RectangleInt);

class Object_RectangleInt : public Object {
private:
	cairo_rectangle_int_t _rectangle;
public:
	AScript_DeclareObjectAccessor(RectangleInt)
public:
	inline Object_RectangleInt(const cairo_rectangle_int_t &rectangle) :
					Object(AScript_PrivClass(RectangleInt)), _rectangle(rectangle) {}
	virtual ~Object_RectangleInt();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_rectangle_int_t &GetRectangle() { return _rectangle; }
};

//-----------------------------------------------------------------------------
// Object_Region declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Region);

class Object_Region : public Object {
private:
	cairo_region_t *_region;
public:
	AScript_DeclareObjectAccessor(Region)
public:
	inline Object_Region(cairo_region_t *region) :
						Object(AScript_PrivClass(Region)), _region(region) {}
	virtual ~Object_Region();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_region_t *GetRegion() { return _region; }
};

//-----------------------------------------------------------------------------
// Object_FontOptions declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(FontOptions);

class Object_FontOptions : public Object {
private:
	cairo_font_options_t *_options;
public:
	AScript_DeclareObjectAccessor(FontOptions)
public:
	inline Object_FontOptions(cairo_font_options_t *options) :
					Object(AScript_PrivClass(FontOptions)), _options(options) {}
	virtual ~Object_FontOptions();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_font_options_t *GetFontOptions() { return _options; }
};

//-----------------------------------------------------------------------------
// Object_Device declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Device);

class Object_Device : public Object {
private:
	cairo_device_t *_device;
public:
	AScript_DeclareObjectAccessor(Device)
public:
	inline Object_Device(cairo_device_t *device) :
					Object(AScript_PrivClass(Device)), _device(device) {}
	virtual ~Object_Device();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_device_t *GetDevice() { return _device; }
};

//-----------------------------------------------------------------------------
// Object_Surface declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Surface);

class Object_Surface : public Object {
private:
	cairo_surface_t *_surface;
	Object_Image *_pObjImage;		// valid when initialized as image
	Writer *_pWriter;				// valid when initialized as pdf, ps
public:
	AScript_DeclareObjectAccessor(Surface)
public:
	inline Object_Surface(cairo_surface_t *surface) :
				Object(AScript_PrivClass(Surface)),
				_surface(surface), _pObjImage(NULL), _pWriter(NULL) {}
	inline Object_Surface(cairo_surface_t *surface, Object_Image *pObjImage) :
				Object(AScript_PrivClass(Surface)),
				_surface(surface), _pObjImage(pObjImage), _pWriter(NULL) {}
	inline Object_Surface(cairo_surface_t *surface, Writer *pWriter) :
				Object(AScript_PrivClass(Surface)),
				_surface(surface), _pObjImage(NULL), _pWriter(pWriter) {}
	virtual ~Object_Surface();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_surface_t *GetSurface() { return _surface; }
	inline Object_Image *GetImageObj() { return _pObjImage; }
	inline bool HasSize() const {
		return _pObjImage != NULL || _pWriter != NULL;
	}
	inline double GetWidth() const {
		return (_pObjImage != NULL)? _pObjImage->GetWidth() :
			(_pWriter != NULL)? _pWriter->GetWidth() : 0.;
	}
	inline double GetHeight() const {
		return (_pObjImage != NULL)? _pObjImage->GetHeight() :
			(_pWriter != NULL)? _pWriter->GetHeight() : 0.;
	}
};

//-----------------------------------------------------------------------------
// Object_Pattern declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Pattern);

class Object_Pattern : public Object {
private:
	cairo_pattern_t *_pattern;
public:
	AScript_DeclareObjectAccessor(Pattern)
public:
	inline Object_Pattern(cairo_pattern_t *pattern) :
						Object(AScript_PrivClass(Pattern)), _pattern(pattern) {}
	virtual ~Object_Pattern();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_pattern_t *GetPattern() { return _pattern; }
};

//-----------------------------------------------------------------------------
// Object_Path declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Path);

class Object_Path : public Object {
private:
	cairo_path_t *_path;
public:
	AScript_DeclareObjectAccessor(Path)
public:
	inline Object_Path(cairo_path_t *path) :
						Object(AScript_PrivClass(Path)), _path(path) {}
	virtual ~Object_Path();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_path_t *GetPath() { return _path; }
};

//-----------------------------------------------------------------------------
// Object_Glyph declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Glyph);

class Object_Glyph : public Object {
private:
	cairo_glyph_t _glyph;
public:
	AScript_DeclareObjectAccessor(Glyph)
public:
	inline Object_Glyph(const cairo_glyph_t &glyph) :
						Object(AScript_PrivClass(Glyph)), _glyph(glyph) {}
	virtual ~Object_Glyph();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_glyph_t &GetGlyph() { return _glyph; }
	inline const cairo_glyph_t &GetGlyph() const { return _glyph; }
};

//-----------------------------------------------------------------------------
// Object_Context declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Context);

class Object_Context : public Object {
private:
	cairo_t *_cr;
	Object_Surface *_pObjSurface;
public:
	AScript_DeclareObjectAccessor(Context)
public:
	inline Object_Context(cairo_t *cr, Object_Surface *pObjSurface) :
		Object(AScript_PrivClass(Context)), _cr(cr), _pObjSurface(pObjSurface) {}
	virtual ~Object_Context();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline cairo_t *GetContext() { return _cr; }
	inline Object_Surface *GetSurfaceObj() { return _pObjSurface; }
};


}}

#endif
