//-----------------------------------------------------------------------------
// AScript cairo module
//-----------------------------------------------------------------------------
#include "Module_cairo.h"

AScript_BeginModule(cairo)

AScript_DeclarePrivSymbol(type);
AScript_DeclarePrivSymbol(surface);
AScript_DeclarePrivSymbol(stream);
AScript_DeclarePrivSymbol(butt);
AScript_DeclarePrivSymbol(round);
AScript_DeclarePrivSymbol(square);
AScript_DeclarePrivSymbol(miter);
AScript_DeclarePrivSymbol(bevel);
AScript_DeclarePrivSymbol(default_);
AScript_DeclarePrivSymbol(none);
AScript_DeclarePrivSymbol(gray);
AScript_DeclarePrivSymbol(subpixel);
AScript_DeclarePrivSymbol(winding);
AScript_DeclarePrivSymbol(even_odd);
AScript_DeclarePrivSymbol(clear);
AScript_DeclarePrivSymbol(source);
AScript_DeclarePrivSymbol(over);
AScript_DeclarePrivSymbol(in);
AScript_DeclarePrivSymbol(out);
AScript_DeclarePrivSymbol(atop);
AScript_DeclarePrivSymbol(dest);
AScript_DeclarePrivSymbol(dest_over);
AScript_DeclarePrivSymbol(dest_in);
AScript_DeclarePrivSymbol(dest_out);
AScript_DeclarePrivSymbol(dest_atop);
AScript_DeclarePrivSymbol(xor);
AScript_DeclarePrivSymbol(add);
AScript_DeclarePrivSymbol(saturate);
AScript_DeclarePrivSymbol(multiply);
AScript_DeclarePrivSymbol(screen);
AScript_DeclarePrivSymbol(overlay);
AScript_DeclarePrivSymbol(darken);
AScript_DeclarePrivSymbol(lighten);
AScript_DeclarePrivSymbol(color_dodge);
AScript_DeclarePrivSymbol(color_burn);
AScript_DeclarePrivSymbol(hard_light);
AScript_DeclarePrivSymbol(soft_light);
AScript_DeclarePrivSymbol(difference);
AScript_DeclarePrivSymbol(exclusion);
AScript_DeclarePrivSymbol(hsl_hue);
AScript_DeclarePrivSymbol(hsl_saturation);
AScript_DeclarePrivSymbol(hsl_color);
AScript_DeclarePrivSymbol(hsl_luminosity);
AScript_DeclarePrivSymbol(part);
AScript_DeclarePrivSymbol(normal);
AScript_DeclarePrivSymbol(italic);
AScript_DeclarePrivSymbol(oblique);
AScript_DeclarePrivSymbol(bold);
AScript_DeclarePrivSymbol(ascent);
AScript_DeclarePrivSymbol(descent);
AScript_DeclarePrivSymbol(width);
AScript_DeclarePrivSymbol(height);
AScript_DeclarePrivSymbol(max_x_advance);
AScript_DeclarePrivSymbol(max_y_advance);
AScript_DeclarePrivSymbol(x_bearing);
AScript_DeclarePrivSymbol(y_bearing);
AScript_DeclarePrivSymbol(x_advance);
AScript_DeclarePrivSymbol(y_advance);
AScript_DeclarePrivSymbol(repeat);
AScript_DeclarePrivSymbol(reflect);
AScript_DeclarePrivSymbol(pad);
AScript_DeclarePrivSymbol(fast);
AScript_DeclarePrivSymbol(good);
AScript_DeclarePrivSymbol(best);
AScript_DeclarePrivSymbol(nearest);
AScript_DeclarePrivSymbol(bilinear);
AScript_DeclarePrivSymbol(gaussian);
AScript_DeclarePrivSymbol(image);
AScript_DeclarePrivSymbol(pdf);
AScript_DeclarePrivSymbol(ps);
AScript_DeclarePrivSymbol(xlib);
AScript_DeclarePrivSymbol(xcb);
AScript_DeclarePrivSymbol(glitz);
AScript_DeclarePrivSymbol(quartz);
AScript_DeclarePrivSymbol(win32);
AScript_DeclarePrivSymbol(beos);
AScript_DeclarePrivSymbol(directfb);
AScript_DeclarePrivSymbol(svg);
AScript_DeclarePrivSymbol(os2);
AScript_DeclarePrivSymbol(win32_printing);
AScript_DeclarePrivSymbol(quartz_image);
AScript_DeclarePrivSymbol(script);
AScript_DeclarePrivSymbol(qt);
AScript_DeclarePrivSymbol(recording);
AScript_DeclarePrivSymbol(vg);
AScript_DeclarePrivSymbol(gl);
AScript_DeclarePrivSymbol(drm);
AScript_DeclarePrivSymbol(tee);
AScript_DeclarePrivSymbol(xml);
AScript_DeclarePrivSymbol(skia);
AScript_DeclarePrivSymbol(subsurface);
AScript_DeclarePrivSymbol(color);
AScript_DeclarePrivSymbol(alpha);
AScript_DeclarePrivSymbol(color_alpha);

const double NUM_PI = 3.14159265358979323846;

//-----------------------------------------------------------------------------
// Error handling
//-----------------------------------------------------------------------------
bool IsError(Signal sig, cairo_status_t status)
{
	if (status == CAIRO_STATUS_SUCCESS) return false;
	sig.SetError(ERR_RuntimeError, "%s", ::cairo_status_to_string(status));
	return true;
}

bool IsError(Signal sig, cairo_t *cr)
{
	return IsError(sig, ::cairo_status(cr));
}

bool IsError(Signal sig, cairo_pattern_t *pattern)
{
	return IsError(sig, ::cairo_pattern_status(pattern));
}

bool IsError(Signal sig, cairo_region_t *region)
{
	return IsError(sig, ::cairo_region_status(region));
}

bool IsError(Signal sig, cairo_font_face_t *font_face)
{
	return IsError(sig, ::cairo_font_face_status(font_face));
}

bool IsError(Signal sig, cairo_device_t *device)
{
	return IsError(sig, ::cairo_device_status(device));
}

bool IsError(Signal sig, cairo_surface_t *surface)
{
	return IsError(sig, ::cairo_surface_status(surface));
}

//-----------------------------------------------------------------------------
// Symbol converter
//-----------------------------------------------------------------------------
// cairo_antialias_t
cairo_antialias_t SymbolToAntialias(Signal sig, const Symbol *pSymbol)
{
	cairo_antialias_t antialias = static_cast<cairo_antialias_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(default_))) {
		antialias = CAIRO_ANTIALIAS_DEFAULT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(none))) {
		antialias = CAIRO_ANTIALIAS_NONE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(gray))) {
		antialias = CAIRO_ANTIALIAS_GRAY;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(subpixel))) {
		antialias = CAIRO_ANTIALIAS_SUBPIXEL;
	} else {
		sig.SetError(ERR_ValueError, "antialias must be `default, `none, `gray or `subpixel");
	}
	return antialias;
}

const Symbol *AntialiasToSymbol(Signal sig, cairo_antialias_t antialias)
{
	const Symbol *pSymbol = NULL;
	if (antialias == CAIRO_ANTIALIAS_DEFAULT) {
		pSymbol = AScript_PrivSymbol(default_);
	} else if (antialias == CAIRO_ANTIALIAS_NONE) {
		pSymbol = AScript_PrivSymbol(none);
	} else if (antialias == CAIRO_ANTIALIAS_GRAY) {
		pSymbol = AScript_PrivSymbol(gray);
	} else if (antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
		pSymbol = AScript_PrivSymbol(subpixel);
	} else {
		sig.SetError(ERR_ValueError, "invalid antialias value");
	}
	return pSymbol;
}

// cairo_fill_rule_t
cairo_fill_rule_t SymbolToFillRule(Signal sig, const Symbol *pSymbol)
{
	cairo_fill_rule_t fill_rule = static_cast<cairo_fill_rule_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(winding))) {
		fill_rule = CAIRO_FILL_RULE_WINDING;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(even_odd))) {
		fill_rule = CAIRO_FILL_RULE_EVEN_ODD;
	} else {
		sig.SetError(ERR_ValueError, "fill_rule must be `winding or `even_odd");
	}
	return fill_rule;
}

const Symbol *FillRuleToSymbol(Signal sig, cairo_fill_rule_t fill_rule)
{
	const Symbol *pSymbol = NULL;
	if (fill_rule == CAIRO_FILL_RULE_WINDING) {
		pSymbol = AScript_PrivSymbol(winding);
	} else if (fill_rule == CAIRO_FILL_RULE_EVEN_ODD) {
		pSymbol = AScript_PrivSymbol(even_odd);
	} else {
		sig.SetError(ERR_ValueError, "invalid fill_rule value");
	}
	return pSymbol;
}

// cairo_line_cap_t
cairo_line_cap_t SymbolToLineCap(Signal sig, const Symbol *pSymbol)
{
	cairo_line_cap_t line_cap = static_cast<cairo_line_cap_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(butt))) {
		line_cap = CAIRO_LINE_CAP_BUTT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(round))) {
		line_cap = CAIRO_LINE_CAP_ROUND;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(square))) {
		line_cap = CAIRO_LINE_CAP_SQUARE;
	} else {
		sig.SetError(ERR_ValueError, "line_cap must be `butt, `round or `square");
	}
	return line_cap;
}

const Symbol *LineCapToSymbol(Signal sig, cairo_line_cap_t line_cap)
{
	const Symbol *pSymbol = NULL;
	if (line_cap == CAIRO_LINE_CAP_BUTT) {
		pSymbol = AScript_PrivSymbol(butt);
	} else if (line_cap == CAIRO_LINE_CAP_ROUND) {
		pSymbol = AScript_PrivSymbol(round);
	} else if (line_cap == CAIRO_LINE_CAP_SQUARE) {
		pSymbol = AScript_PrivSymbol(square);
	} else {
		sig.SetError(ERR_ValueError, "invalid line_cap value");
	}
	return pSymbol;
}

// cairo_line_join_t
cairo_line_join_t SymbolToLineJoin(Signal sig, const Symbol *pSymbol)
{
	cairo_line_join_t line_join = static_cast<cairo_line_join_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(miter))) {
		line_join = CAIRO_LINE_JOIN_MITER;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(round))) {
		line_join = CAIRO_LINE_JOIN_ROUND;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(bevel))) {
		line_join = CAIRO_LINE_JOIN_BEVEL;
	} else {
		sig.SetError(ERR_ValueError, "line_join must be `miter, `round or `bevel");
	}
	return line_join;
}

const Symbol *LineJoinToSymbol(Signal sig, cairo_line_join_t line_join)
{
	const Symbol *pSymbol = NULL;
	if (line_join == CAIRO_LINE_JOIN_MITER) {
		pSymbol = AScript_PrivSymbol(miter);
	} else if (line_join == CAIRO_LINE_JOIN_ROUND) {
		pSymbol = AScript_PrivSymbol(round);
	} else if (line_join == CAIRO_LINE_JOIN_BEVEL) {
		pSymbol = AScript_PrivSymbol(bevel);
	} else {
		sig.SetError(ERR_ValueError, "invalid line_join value");
	}
	return pSymbol;
}

// cairo_font_slant_t
cairo_font_slant_t SymbolToFontSlant(Signal sig, const Symbol *pSymbol)
{
	cairo_font_slant_t font_slant = static_cast<cairo_font_slant_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(normal))) {
		font_slant = CAIRO_FONT_SLANT_NORMAL;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(italic))) {
		font_slant = CAIRO_FONT_SLANT_ITALIC;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(oblique))) {
		font_slant = CAIRO_FONT_SLANT_OBLIQUE;
	} else {
		sig.SetError(ERR_ValueError, "font_slant must be `normal, `italic or `oblique");
	}
	return font_slant;
}

const Symbol *FontSlantToSymbol(Signal sig, cairo_font_slant_t font_slant)
{
	const Symbol *pSymbol = NULL;
	if (font_slant == CAIRO_FONT_SLANT_NORMAL) {
		pSymbol = AScript_PrivSymbol(normal);
	} else if (font_slant == CAIRO_FONT_SLANT_ITALIC) {
		pSymbol = AScript_PrivSymbol(italic);
	} else if (font_slant == CAIRO_FONT_SLANT_OBLIQUE) {
		pSymbol = AScript_PrivSymbol(oblique);
	} else {
		sig.SetError(ERR_ValueError, "invalid font_slant value");
	}
	return pSymbol;
}

// cairo_font_weight_t
cairo_font_weight_t SymbolToFontWeight(Signal sig, const Symbol *pSymbol)
{
	cairo_font_weight_t font_weight = static_cast<cairo_font_weight_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(normal))) {
		font_weight = CAIRO_FONT_WEIGHT_NORMAL;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(bold))) {
		font_weight = CAIRO_FONT_WEIGHT_BOLD;
	} else {
		sig.SetError(ERR_ValueError, "font_weight must be `normal or `bold");
	}
	return font_weight;
}

const Symbol *FontWeightToSymbol(Signal sig, cairo_font_weight_t font_weight)
{
	const Symbol *pSymbol = NULL;
	if (font_weight == CAIRO_FONT_WEIGHT_NORMAL) {
		pSymbol = AScript_PrivSymbol(normal);
	} else if (font_weight == CAIRO_FONT_WEIGHT_BOLD) {
		pSymbol = AScript_PrivSymbol(bold);
	} else {
		sig.SetError(ERR_ValueError, "invalid font_weight value");
	}
	return pSymbol;
}

// cairo_operator_t
cairo_operator_t SymbolToOperator(Signal sig, const Symbol *pSymbol)
{
	cairo_operator_t operator_ = static_cast<cairo_operator_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(clear))) {
		operator_ = CAIRO_OPERATOR_CLEAR;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(source))) {
		operator_ = CAIRO_OPERATOR_SOURCE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(over))) {
		operator_ = CAIRO_OPERATOR_OVER;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(in))) {
		operator_ = CAIRO_OPERATOR_IN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(out))) {
		operator_ = CAIRO_OPERATOR_OUT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(atop))) {
		operator_ = CAIRO_OPERATOR_ATOP;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(dest))) {
		operator_ = CAIRO_OPERATOR_DEST;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(dest_over))) {
		operator_ = CAIRO_OPERATOR_DEST_OVER;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(dest_in))) {
		operator_ = CAIRO_OPERATOR_DEST_IN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(dest_out))) {
		operator_ = CAIRO_OPERATOR_DEST_OUT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(dest_atop))) {
		operator_ = CAIRO_OPERATOR_DEST_ATOP;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(xor))) {
		operator_ = CAIRO_OPERATOR_XOR;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(add))) {
		operator_ = CAIRO_OPERATOR_ADD;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(saturate))) {
		operator_ = CAIRO_OPERATOR_SATURATE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(multiply))) {
		operator_ = CAIRO_OPERATOR_MULTIPLY;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(screen))) {
		operator_ = CAIRO_OPERATOR_SCREEN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(overlay))) {
		operator_ = CAIRO_OPERATOR_OVERLAY;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(darken))) {
		operator_ = CAIRO_OPERATOR_DARKEN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(lighten))) {
		operator_ = CAIRO_OPERATOR_LIGHTEN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(color_dodge))) {
		operator_ = CAIRO_OPERATOR_COLOR_DODGE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(color_burn))) {
		operator_ = CAIRO_OPERATOR_COLOR_BURN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(hard_light))) {
		operator_ = CAIRO_OPERATOR_HARD_LIGHT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(soft_light))) {
		operator_ = CAIRO_OPERATOR_SOFT_LIGHT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(difference))) {
		operator_ = CAIRO_OPERATOR_DIFFERENCE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(exclusion))) {
		operator_ = CAIRO_OPERATOR_EXCLUSION;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(hsl_hue))) {
		operator_ = CAIRO_OPERATOR_HSL_HUE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(hsl_saturation))) {
		operator_ = CAIRO_OPERATOR_HSL_SATURATION;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(hsl_color))) {
		operator_ = CAIRO_OPERATOR_HSL_COLOR;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(hsl_luminosity))) {
		operator_ = CAIRO_OPERATOR_HSL_LUMINOSITY;
	} else {
		sig.SetError(ERR_ValueError, "invalid operator symbol");
	}
	return operator_;
}

const Symbol *OperatorToSymbol(Signal sig, cairo_operator_t operator_)
{
	const Symbol *pSymbol = NULL;
	if (operator_ == CAIRO_OPERATOR_CLEAR) {
		pSymbol = AScript_PrivSymbol(clear);
	} else if (operator_ == CAIRO_OPERATOR_SOURCE) {
		pSymbol = AScript_PrivSymbol(source);
	} else if (operator_ == CAIRO_OPERATOR_OVER) {
		pSymbol = AScript_PrivSymbol(over);
	} else if (operator_ == CAIRO_OPERATOR_IN) {
		pSymbol = AScript_PrivSymbol(in);
	} else if (operator_ == CAIRO_OPERATOR_OUT) {
		pSymbol = AScript_PrivSymbol(out);
	} else if (operator_ == CAIRO_OPERATOR_ATOP) {
		pSymbol = AScript_PrivSymbol(atop);
	} else if (operator_ == CAIRO_OPERATOR_DEST) {
		pSymbol = AScript_PrivSymbol(dest);
	} else if (operator_ == CAIRO_OPERATOR_DEST_OVER) {
		pSymbol = AScript_PrivSymbol(dest_over);
	} else if (operator_ == CAIRO_OPERATOR_DEST_IN) {
		pSymbol = AScript_PrivSymbol(dest_in);
	} else if (operator_ == CAIRO_OPERATOR_DEST_OUT) {
		pSymbol = AScript_PrivSymbol(dest_out);
	} else if (operator_ == CAIRO_OPERATOR_DEST_ATOP) {
		pSymbol = AScript_PrivSymbol(dest_atop);
	} else if (operator_ == CAIRO_OPERATOR_XOR) {
		pSymbol = AScript_PrivSymbol(xor);
	} else if (operator_ == CAIRO_OPERATOR_ADD) {
		pSymbol = AScript_PrivSymbol(add);
	} else if (operator_ == CAIRO_OPERATOR_SATURATE) {
		pSymbol = AScript_PrivSymbol(saturate);
	} else if (operator_ == CAIRO_OPERATOR_MULTIPLY) {
		pSymbol = AScript_PrivSymbol(multiply);
	} else if (operator_ == CAIRO_OPERATOR_SCREEN) {
		pSymbol = AScript_PrivSymbol(screen);
	} else if (operator_ == CAIRO_OPERATOR_OVERLAY) {
		pSymbol = AScript_PrivSymbol(overlay);
	} else if (operator_ == CAIRO_OPERATOR_DARKEN) {
		pSymbol = AScript_PrivSymbol(darken);
	} else if (operator_ == CAIRO_OPERATOR_LIGHTEN) {
		pSymbol = AScript_PrivSymbol(lighten);
	} else if (operator_ == CAIRO_OPERATOR_COLOR_DODGE) {
		pSymbol = AScript_PrivSymbol(color_dodge);
	} else if (operator_ == CAIRO_OPERATOR_COLOR_BURN) {
		pSymbol = AScript_PrivSymbol(color_burn);
	} else if (operator_ == CAIRO_OPERATOR_HARD_LIGHT) {
		pSymbol = AScript_PrivSymbol(hard_light);
	} else if (operator_ == CAIRO_OPERATOR_SOFT_LIGHT) {
		pSymbol = AScript_PrivSymbol(soft_light);
	} else if (operator_ == CAIRO_OPERATOR_DIFFERENCE) {
		pSymbol = AScript_PrivSymbol(difference);
	} else if (operator_ == CAIRO_OPERATOR_EXCLUSION) {
		pSymbol = AScript_PrivSymbol(exclusion);
	} else if (operator_ == CAIRO_OPERATOR_HSL_HUE) {
		pSymbol = AScript_PrivSymbol(hsl_hue);
	} else if (operator_ == CAIRO_OPERATOR_HSL_SATURATION) {
		pSymbol = AScript_PrivSymbol(hsl_saturation);
	} else if (operator_ == CAIRO_OPERATOR_HSL_COLOR) {
		pSymbol = AScript_PrivSymbol(hsl_color);
	} else if (operator_ == CAIRO_OPERATOR_HSL_LUMINOSITY) {
		pSymbol = AScript_PrivSymbol(hsl_luminosity);
	} else {
		sig.SetError(ERR_ValueError, "invalid operator value");
	}
	return pSymbol;
}

// cairo_region_overlap_t
cairo_region_overlap_t SymbolToRegionOverlap(Signal sig, const Symbol *pSymbol)
{
	cairo_region_overlap_t region_overlap = static_cast<cairo_region_overlap_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(in))) {
		region_overlap = CAIRO_REGION_OVERLAP_IN;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(out))) {
		region_overlap = CAIRO_REGION_OVERLAP_OUT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(part))) {
		region_overlap = CAIRO_REGION_OVERLAP_PART;
	} else {
		sig.SetError(ERR_ValueError, "region_overlap must be `in, `out or `part");
	}
	return region_overlap;
}

const Symbol *RegionOverlapToSymbol(Signal sig, cairo_region_overlap_t region_overlap)
{
	const Symbol *pSymbol = NULL;
	if (region_overlap == CAIRO_REGION_OVERLAP_IN) {
		pSymbol = AScript_PrivSymbol(in);
	} else if (region_overlap == CAIRO_REGION_OVERLAP_OUT) {
		pSymbol = AScript_PrivSymbol(out);
	} else if (region_overlap == CAIRO_REGION_OVERLAP_PART) {
		pSymbol = AScript_PrivSymbol(part);
	} else {
		sig.SetError(ERR_ValueError, "invalid region_overlap value");
	}
	return pSymbol;
}

// cairo_extend_t
cairo_extend_t SymbolToExtend(Signal sig, const Symbol *pSymbol)
{
	cairo_extend_t extend = static_cast<cairo_extend_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(none))) {
		extend = CAIRO_EXTEND_NONE;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(repeat))) {
		extend = CAIRO_EXTEND_REPEAT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(reflect))) {
		extend = CAIRO_EXTEND_REFLECT;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(pad))) {
		extend = CAIRO_EXTEND_PAD;
	} else {
		sig.SetError(ERR_ValueError,
					"extend must be `none, `repeat, `reflect or `pad");
	}
	return extend;
}

const Symbol *ExtendToSymbol(Signal sig, cairo_extend_t extend)
{
	const Symbol *pSymbol = NULL;
	if (extend == CAIRO_EXTEND_NONE) {
		pSymbol = AScript_PrivSymbol(none);
	} else if (extend == CAIRO_EXTEND_REPEAT) {
		pSymbol = AScript_PrivSymbol(repeat);
	} else if (extend == CAIRO_EXTEND_REFLECT) {
		pSymbol = AScript_PrivSymbol(reflect);
	} else if (extend == CAIRO_EXTEND_PAD) {
		pSymbol = AScript_PrivSymbol(pad);
	} else {
		sig.SetError(ERR_ValueError, "invalid extend value");
	}
	return pSymbol;
}

// cairo_filter_t
cairo_filter_t SymbolToFilter(Signal sig, const Symbol *pSymbol)
{
	cairo_filter_t filter = static_cast<cairo_filter_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(fast))) {
		filter = CAIRO_FILTER_FAST;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(good))) {
		filter = CAIRO_FILTER_GOOD;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(best))) {
		filter = CAIRO_FILTER_BEST;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(nearest))) {
		filter = CAIRO_FILTER_NEAREST;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(bilinear))) {
		filter = CAIRO_FILTER_BILINEAR;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(gaussian))) {
		filter = CAIRO_FILTER_GAUSSIAN;
	} else {
		sig.SetError(ERR_ValueError,
			"filter must be `fast, `good, `best, `nearest, `bilinear or `gaussian");
	}
	return filter;
}

const Symbol *FilterToSymbol(Signal sig, cairo_filter_t filter)
{
	const Symbol *pSymbol = NULL;
	if (filter == CAIRO_FILTER_FAST) {
		pSymbol = AScript_PrivSymbol(fast);
	} else if (filter == CAIRO_FILTER_GOOD) {
		pSymbol = AScript_PrivSymbol(good);
	} else if (filter == CAIRO_FILTER_BEST) {
		pSymbol = AScript_PrivSymbol(best);
	} else if (filter == CAIRO_FILTER_NEAREST) {
		pSymbol = AScript_PrivSymbol(nearest);
	} else if (filter == CAIRO_FILTER_BILINEAR) {
		pSymbol = AScript_PrivSymbol(bilinear);
	} else if (filter == CAIRO_FILTER_GAUSSIAN) {
		pSymbol = AScript_PrivSymbol(gaussian);
	} else {
		sig.SetError(ERR_ValueError, "invalid filter value");
	}
	return pSymbol;
}

// cairo_content_t
cairo_content_t SymbolToContent(Signal sig, const Symbol *pSymbol)
{
	cairo_content_t extend = static_cast<cairo_content_t>(0);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(color))) {
		extend = CAIRO_CONTENT_COLOR;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(alpha))) {
		extend = CAIRO_CONTENT_ALPHA;
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(color_alpha))) {
		extend = CAIRO_CONTENT_COLOR_ALPHA;
	} else {
		sig.SetError(ERR_ValueError,
					"extend must be `color, `alpha or `color_alpha");
	}
	return extend;
}

const Symbol *ContentToSymbol(Signal sig, cairo_content_t content)
{
	const Symbol *pSymbol = NULL;
	if (content == CAIRO_CONTENT_COLOR) {
		pSymbol = AScript_PrivSymbol(color);
	} else if (content == CAIRO_CONTENT_ALPHA) {
		pSymbol = AScript_PrivSymbol(alpha);
	} else if (content == CAIRO_CONTENT_COLOR_ALPHA) {
		pSymbol = AScript_PrivSymbol(color_alpha);
	} else {
		sig.SetError(ERR_ValueError, "invalid content value");
	}
	return pSymbol;
}


const Symbol *SurfaceTypeToSymbol(Signal sig, cairo_surface_type_t surface_type)
{
	const Symbol *pSymbol = NULL;
	String str;
	if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) {
		pSymbol = AScript_PrivSymbol(image);
	} else if (surface_type == CAIRO_SURFACE_TYPE_PDF) {
		pSymbol = AScript_PrivSymbol(pdf);
	} else if (surface_type == CAIRO_SURFACE_TYPE_PS) {
		pSymbol = AScript_PrivSymbol(ps);
	} else if (surface_type == CAIRO_SURFACE_TYPE_XLIB) {
		pSymbol = AScript_PrivSymbol(xlib);
	} else if (surface_type == CAIRO_SURFACE_TYPE_XCB) {
		pSymbol = AScript_PrivSymbol(xcb);
	} else if (surface_type == CAIRO_SURFACE_TYPE_GLITZ) {
		pSymbol = AScript_PrivSymbol(glitz);
	} else if (surface_type == CAIRO_SURFACE_TYPE_QUARTZ) {
		pSymbol = AScript_PrivSymbol(quartz);
	} else if (surface_type == CAIRO_SURFACE_TYPE_WIN32) {
		pSymbol = AScript_PrivSymbol(win32);
	} else if (surface_type == CAIRO_SURFACE_TYPE_BEOS) {
		pSymbol = AScript_PrivSymbol(beos);
	} else if (surface_type == CAIRO_SURFACE_TYPE_DIRECTFB) {
		pSymbol = AScript_PrivSymbol(directfb);
	} else if (surface_type == CAIRO_SURFACE_TYPE_SVG) {
		pSymbol = AScript_PrivSymbol(svg);
	} else if (surface_type == CAIRO_SURFACE_TYPE_OS2) {
		pSymbol = AScript_PrivSymbol(os2);
	} else if (surface_type == CAIRO_SURFACE_TYPE_WIN32_PRINTING) {
		pSymbol = AScript_PrivSymbol(win32_printing);
	} else if (surface_type == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
		pSymbol = AScript_PrivSymbol(quartz_image);
	} else if (surface_type == CAIRO_SURFACE_TYPE_SCRIPT) {
		pSymbol = AScript_PrivSymbol(script);
	} else if (surface_type == CAIRO_SURFACE_TYPE_QT) {
		pSymbol = AScript_PrivSymbol(qt);
	} else if (surface_type == CAIRO_SURFACE_TYPE_RECORDING) {
		pSymbol = AScript_PrivSymbol(recording);
	} else if (surface_type == CAIRO_SURFACE_TYPE_VG) {
		pSymbol = AScript_PrivSymbol(vg);
	} else if (surface_type == CAIRO_SURFACE_TYPE_GL) {
		pSymbol = AScript_PrivSymbol(gl);
	} else if (surface_type
	 == CAIRO_SURFACE_TYPE_DRM) {
		pSymbol = AScript_PrivSymbol(drm);
	} else if (surface_type == CAIRO_SURFACE_TYPE_TEE) {
		pSymbol = AScript_PrivSymbol(tee);
	} else if (surface_type == CAIRO_SURFACE_TYPE_XML) {
		pSymbol = AScript_PrivSymbol(xml);
	} else if (surface_type == CAIRO_SURFACE_TYPE_SKIA) {
		pSymbol = AScript_PrivSymbol(skia);
	} else if (surface_type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
		pSymbol = AScript_PrivSymbol(subsurface);
	} else {
		sig.SetError(ERR_ValueError, "invalid surface_type value");
	}
	return pSymbol;
}

//-----------------------------------------------------------------------------
// Value converter
//-----------------------------------------------------------------------------
Value RectangleToValue(Environment &env, const cairo_rectangle_t &rectangle)
{
	Value value;
	ValueList &valList = value.InitAsList(env);
	valList.reserve(4);
	valList.push_back(Value(rectangle.x));
	valList.push_back(Value(rectangle.y));
	valList.push_back(Value(rectangle.width));
	valList.push_back(Value(rectangle.height));
	valList.push_back(value);
	return value;
}

bool ValueListToRectangle(Signal sig, cairo_rectangle_t &rectangle, const ValueList &valList)
{
	if (valList.size() != 4) {
		sig.SetError(ERR_ValueError, "list must have four elements");
		return false;
	}
	rectangle.x = valList[0].GetDouble();
	rectangle.y = valList[1].GetDouble();
	rectangle.width = valList[2].GetDouble();
	rectangle.height = valList[3].GetDouble();
	return true;
}

bool ValueListToRectangle(Signal sig, cairo_rectangle_int_t &rectangle, const ValueList &valList)
{
	if (valList.size() != 4) {
		sig.SetError(ERR_ValueError, "list must have four elements");
		return false;
	}
	rectangle.x = valList[0].GetInt();
	rectangle.y = valList[1].GetInt();
	rectangle.width = valList[2].GetInt();
	rectangle.height = valList[3].GetInt();
	return true;
}

Object_Matrix *CairoToMatrix(Environment &env, cairo_matrix_t &matrix)
{
	Object_Matrix *pObjMatrix = new Object_Matrix(env, 3, 3);
	pObjMatrix->SetElement(0, 0, Value(matrix.xx));
	pObjMatrix->SetElement(0, 1, Value(matrix.xy));
	pObjMatrix->SetElement(1, 0, Value(matrix.yx));
	pObjMatrix->SetElement(1, 1, Value(matrix.yy));
	pObjMatrix->SetElement(0, 2, Value(matrix.x0));
	pObjMatrix->SetElement(1, 2, Value(matrix.y0));
	pObjMatrix->SetElement(2, 2, Value(1.));
	return pObjMatrix;
}

bool MatrixToCairo(Signal sig, cairo_matrix_t &matrix, Object_Matrix *pObjMatrix)
{
	if (pObjMatrix->RowSize() != 3 || pObjMatrix->ColSize() != 3) {
		sig.SetError(ERR_ValueError, "matrix size must be 3x3");
		return false;
	}
	matrix.xx = pObjMatrix->GetElement(0, 0).GetDouble();
	matrix.xy = pObjMatrix->GetElement(0, 1).GetDouble();
	matrix.yx = pObjMatrix->GetElement(1, 0).GetDouble();
	matrix.yy = pObjMatrix->GetElement(1, 1).GetDouble();
	matrix.x0 = pObjMatrix->GetElement(0, 2).GetDouble();
	matrix.y0 = pObjMatrix->GetElement(1, 2).GetDouble();
	return true;
}

Value CreateValueList(Environment &env, double x1, double x2)
{
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(2);
	valList.push_back(Value(x1));
	valList.push_back(Value(x2));
	return result;
}

Value CreateValueList(Environment &env, double x1, double x2, double x3)
{
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(3);
	valList.push_back(Value(x1));
	valList.push_back(Value(x2));
	valList.push_back(Value(x3));
	return result;
}

Value CreateValueList(Environment &env, double x1, double x2, double x3, double x4)
{
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(4);
	valList.push_back(Value(x1));
	valList.push_back(Value(x2));
	valList.push_back(Value(x3));
	valList.push_back(Value(x4));
	return result;
}

Value CreateValueList(Environment &env,
				double x1, double x2, double x3, double x4, double x5)
{
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(5);
	valList.push_back(Value(x1));
	valList.push_back(Value(x2));
	valList.push_back(Value(x3));
	valList.push_back(Value(x4));
	valList.push_back(Value(x5));
	return result;
}

Value CreateValueList(Environment &env,
				double x1, double x2, double x3, double x4, double x5, double x6)
{
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(6);
	valList.push_back(Value(x1));
	valList.push_back(Value(x2));
	valList.push_back(Value(x3));
	valList.push_back(Value(x4));
	valList.push_back(Value(x5));
	valList.push_back(Value(x6));
	return result;
}

cairo_surface_t *CreateSurfaceFromImage(Signal sig, Object_Image *pObjImage)
{
	if (!pObjImage->CheckValid(sig)) return NULL;
	if (pObjImage->GetFormat() != Object_Image::FORMAT_RGBA) {
		sig.SetError(ERR_FormatError, "cairo can be applied to image in `rgba format");
		return NULL;
	}
	size_t width = pObjImage->GetWidth();
	size_t height = pObjImage->GetHeight();
	cairo_surface_t *surface = ::cairo_image_surface_create_for_data(
				pObjImage->GetBuffer(), CAIRO_FORMAT_ARGB32,
				static_cast<int>(width), static_cast<int>(height),
				static_cast<int>(pObjImage->GetBytesPerLine()));
	return surface;
}

//-----------------------------------------------------------------------------
// Writer implementation
//-----------------------------------------------------------------------------
Writer::~Writer()
{
	//_pStream->Close();
	Stream::Delete(_pStream);
}

cairo_status_t Writer::WriteFunc(const unsigned char *data, unsigned int length)
{
	_pStream->Write(_sig, data, length);
	if (_sig.IsSignalled()) return CAIRO_STATUS_WRITE_ERROR;
	return CAIRO_STATUS_SUCCESS;
}

cairo_status_t Writer::write_func(void *closure,
						const unsigned char *data, unsigned int length)
{
	Writer *pWriter = reinterpret_cast<Writer *>(closure);
	return pWriter->WriteFunc(data, length);
}

//-----------------------------------------------------------------------------
// Object_FontExtents implementation
//-----------------------------------------------------------------------------
Object_FontExtents::~Object_FontExtents()
{
}

Object *Object_FontExtents::Clone() const
{
	return NULL;
}

Value Object_FontExtents::DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag)
{
	evaluatedFlag = true;
	if (pSymbol->IsIdentical(AScript_PrivSymbol(ascent))) {
		return Value(_font_extents.ascent);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(descent))) {
		return Value(_font_extents.descent);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(height))) {
		return Value(_font_extents.height);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(max_x_advance))) {
		return Value(_font_extents.max_x_advance);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(max_y_advance))) {
		return Value(_font_extents.max_y_advance);
	}
	evaluatedFlag = false;
	return Value::Null;
}

String Object_FontExtents::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.font_extents>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_FontExtents
//-----------------------------------------------------------------------------
// implementation of class FontExtents
AScript_ImplementPrivClass(FontExtents)
{
}

//-----------------------------------------------------------------------------
// Object_TextExtents implementation
//-----------------------------------------------------------------------------
Object_TextExtents::~Object_TextExtents()
{
}

Object *Object_TextExtents::Clone() const
{
	return NULL;
}

Value Object_TextExtents::DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag)
{
	evaluatedFlag = true;
	if (pSymbol->IsIdentical(AScript_PrivSymbol(x_bearing))) {
		return Value(_text_extents.x_bearing);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(y_bearing))) {
		return Value(_text_extents.y_bearing);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(width))) {
		return Value(_text_extents.width);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(height))) {
		return Value(_text_extents.height);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(x_advance))) {
		return Value(_text_extents.x_advance);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(y_advance))) {
		return Value(_text_extents.y_advance);
	}
	evaluatedFlag = false;
	return Value::Null;
}

String Object_TextExtents::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.text_extents>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_TextExtents
//-----------------------------------------------------------------------------
// implementation of class TextExtents
AScript_ImplementPrivClass(TextExtents)
{
}

//-----------------------------------------------------------------------------
// Object_Rectangle implementation
//-----------------------------------------------------------------------------
Object_Rectangle::~Object_Rectangle()
{
}

Object *Object_Rectangle::Clone() const
{
	return NULL;
}

String Object_Rectangle::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.rectangle>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Rectangle
//-----------------------------------------------------------------------------
// implementation of class Rectangle
AScript_ImplementPrivClass(Rectangle)
{
}

//-----------------------------------------------------------------------------
// Object_RectangleInt implementation
//-----------------------------------------------------------------------------
Object_RectangleInt::~Object_RectangleInt()
{
}

Object *Object_RectangleInt::Clone() const
{
	return NULL;
}

String Object_RectangleInt::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.rectangle_int>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_RectangleInt
//-----------------------------------------------------------------------------
// implementation of class RectangleInt
AScript_ImplementPrivClass(RectangleInt)
{
}

//-----------------------------------------------------------------------------
// Object_Region implementation
//-----------------------------------------------------------------------------
Object_Region::~Object_Region()
{
	::cairo_region_destroy(_region);
}

Object *Object_Region::Clone() const
{
	return NULL;
}

String Object_Region::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.region>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Region
//-----------------------------------------------------------------------------
// cairo.region#is_empty()
AScript_DeclareMethod(Region, is_empty)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Region, is_empty)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	bool rtn = ::cairo_region_is_empty(region)? true : false;
	if (IsError(sig, region)) return Value::Null;
	return Value(rtn);
}

// cairo.region#contains_point(x:number, y:number)
AScript_DeclareMethod(Region, contains_point)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}


AScript_ImplementMethod(Region, contains_point)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	bool rtn = ::cairo_region_contains_point(region, args.GetInt(0), args.GetInt(1))? true : false;
	if (IsError(sig, region)) return Value::Null;
	return Value(rtn);
}

// cairo.region#contains_rectangle(rectangle:cairo.rectangle_int)
AScript_DeclareMethod(Region, contains_rectangle)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "rectangle", AScript_PrivVTYPE(RectangleInt));
}

AScript_ImplementMethod(Region, contains_rectangle)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_rectangle_int_t &rectangle =
					Object_RectangleInt::GetObject(args, 0)->GetRectangle();
	cairo_region_overlap_t region_overlap =
					::cairo_region_contains_rectangle(region, &rectangle);
	if (IsError(sig, region)) return Value::Null;
	const Symbol *pSymbol = RegionOverlapToSymbol(sig, region_overlap);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.region#equal(region:cairo.region)
AScript_DeclareMethod(Region, equal)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "region", AScript_PrivVTYPE(Region));
}

AScript_ImplementMethod(Region, equal)
{
	cairo_region_t *a = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *b = Object_Region::GetObject(args, 0)->GetRegion();
	bool rtn = ::cairo_region_equal(a, b)? true : false;
	if (IsError(sig, a)) return Value::Null;
	return Value(rtn);
}

// cairo.region#translate(dx:number, dy:number)
AScript_DeclareMethod(Region, translate)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "dx", VTYPE_Number);
	DeclareArg(env, "dy", VTYPE_Number);
}

AScript_ImplementMethod(Region, translate)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	::cairo_region_translate(region, args.GetInt(0), args.GetInt(1));
	if (IsError(sig, region)) return Value::Null;
	return Value::Null;
}

// cairo.region#intersect(other:cairo.region)
AScript_DeclareMethod(Region, intersect)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "other", AScript_PrivVTYPE(Region));
}

AScript_ImplementMethod(Region, intersect)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_region_t *other = Object_Region::GetObject(args, 0)->GetRegion();
	cairo_status_t status = ::cairo_region_intersect(dst, other);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#intersect_rectangle(rectangle:cairo.rectangle_int)
AScript_DeclareMethod(Region, intersect_rectangle)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "rectangle", AScript_PrivVTYPE(RectangleInt));
}

AScript_ImplementMethod(Region, intersect_rectangle)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_rectangle_int_t &rectangle =
					Object_RectangleInt::GetObject(args, 0)->GetRectangle();
	cairo_status_t status = ::cairo_region_intersect_rectangle(dst, &rectangle);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#subtract(other:cairo.region)
AScript_DeclareMethod(Region, subtract)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "other", AScript_PrivVTYPE(Region));
}

AScript_ImplementMethod(Region, subtract)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_region_t *other = Object_Region::GetObject(args, 0)->GetRegion();
	cairo_status_t status = ::cairo_region_subtract(dst, other);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#subtract_rectangle(rectangle:cairo.rectangle_int)
AScript_DeclareMethod(Region, subtract_rectangle)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "rectangle", AScript_PrivVTYPE(RectangleInt));
}

AScript_ImplementMethod(Region, subtract_rectangle)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_rectangle_int_t &rectangle =
					Object_RectangleInt::GetObject(args, 0)->GetRectangle();
	cairo_status_t status = ::cairo_region_subtract_rectangle(dst, &rectangle);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#union(other:cairo.region)
AScript_DeclareMethod(Region, union_)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "other", AScript_PrivVTYPE(Region));
}

AScript_ImplementMethod(Region, union_)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_region_t *other = Object_Region::GetObject(args, 0)->GetRegion();
	cairo_status_t status = ::cairo_region_union(dst, other);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#union_rectangle(rectangle:cairo.rectangle_int)
AScript_DeclareMethod(Region, union_rectangle)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "rectangle", AScript_PrivVTYPE(RectangleInt));
}

AScript_ImplementMethod(Region, union_rectangle)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_rectangle_int_t &rectangle =
					Object_RectangleInt::GetObject(args, 0)->GetRectangle();
	cairo_status_t status = ::cairo_region_union_rectangle(dst, &rectangle);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#xor(other:cairo.region)
AScript_DeclareMethodAlias(Region, xor_, "xor")
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "other", AScript_PrivVTYPE(Region));
}

AScript_ImplementMethod(Region, xor_)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_region_t *other = Object_Region::GetObject(args, 0)->GetRegion();
	cairo_status_t status = ::cairo_region_xor(dst, other);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// cairo.region#xor_rectangle(rectangle:cairo.rectangle_int)
AScript_DeclareMethod(Region, xor_rectangle)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "rectangle", AScript_PrivVTYPE(RectangleInt));
}

AScript_ImplementMethod(Region, xor_rectangle)
{
	cairo_region_t *region = Object_Region::GetSelfObj(args)->GetRegion();
	cairo_region_t *dst = ::cairo_region_copy(region);
	if (IsError(sig, dst)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	cairo_rectangle_int_t &rectangle =
					Object_RectangleInt::GetObject(args, 0)->GetRectangle();
	cairo_status_t status = ::cairo_region_xor_rectangle(dst, &rectangle);
	if (IsError(sig, status)) {
		::cairo_region_destroy(dst);
		return Value::Null;
	}
	Object_Region *pObjRegion = new Object_Region(dst);
	return Value(pObjRegion);
}

// implementation of class Region
AScript_ImplementPrivClass(Region)
{
	AScript_AssignMethod(Region, is_empty);
	AScript_AssignMethod(Region, contains_point);
	AScript_AssignMethod(Region, contains_rectangle);
	AScript_AssignMethod(Region, equal);
	AScript_AssignMethod(Region, translate);
	AScript_AssignMethod(Region, intersect);
	AScript_AssignMethod(Region, intersect_rectangle);
	AScript_AssignMethod(Region, subtract);
	AScript_AssignMethod(Region, subtract_rectangle);
	AScript_AssignMethodEx(Region, union_, "union");
	AScript_AssignMethod(Region, union_rectangle);
	AScript_AssignMethod(Region, xor_);
	AScript_AssignMethod(Region, xor_rectangle);
}

//-----------------------------------------------------------------------------
// Object_FontOptions implementation
//-----------------------------------------------------------------------------
Object_FontOptions::~Object_FontOptions()
{
	::cairo_font_options_destroy(_options);
}

Object *Object_FontOptions::Clone() const
{
	return NULL;
}

String Object_FontOptions::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.font_options>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_FontOptions
//-----------------------------------------------------------------------------
// implementation of class FontOptions
AScript_ImplementPrivClass(FontOptions)
{
}

//-----------------------------------------------------------------------------
// Object_Device implementation
//-----------------------------------------------------------------------------
Object_Device::~Object_Device()
{
	::cairo_device_destroy(_device);
}

Object *Object_Device::Clone() const
{
	return NULL;
}

String Object_Device::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.device>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Device
//-----------------------------------------------------------------------------
// implementation of class Device
AScript_ImplementPrivClass(Device)
{
}

//-----------------------------------------------------------------------------
// Object_Surface implementation
//-----------------------------------------------------------------------------
Object_Surface::~Object_Surface()
{
	::cairo_surface_destroy(_surface);
	Object::Delete(_pObjImage);
	delete _pWriter;
}

Object *Object_Surface::Clone() const
{
	return NULL;
}

Value Object_Surface::DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag)
{
	Environment &env = *this;
	evaluatedFlag = true;
	cairo_surface_type_t type = ::cairo_surface_get_type(_surface);
	if (pSymbol->IsIdentical(AScript_PrivSymbol(type))) {
		cairo_surface_type_t surface_type = ::cairo_surface_get_type(_surface);
		const Symbol *pSymbol = SurfaceTypeToSymbol(sig, surface_type);
		if (sig.IsSignalled()) return Value::Null;
		return Value(pSymbol);
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(width))) {
		if (!HasSize()) return Value::Null;
		return Value(GetWidth());
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(height))) {
		if (!HasSize()) return Value::Null;
		return Value(GetHeight());
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(image))) {
		if (_pObjImage == NULL) {
			return Value::Null;
		} else {
			return Value(Object_Image::Reference(_pObjImage));
		}
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(stream))) {
		if (_pWriter == NULL) {
			return Value::Null;
		} else {
			Stream *pStream = _pWriter->GetStream();
			Object_Stream *pObjStream = new Object_Stream(env, Stream::Reference(pStream));
			return Value(pObjStream);
		}
	}
	evaluatedFlag = false;
	return Value::Null;
}

String Object_Surface::ToString(Signal sig, bool exprFlag)
{
	String str;
	str += "<cairo.surface:";
	cairo_surface_type_t surface_type = ::cairo_surface_get_type(_surface);
	const Symbol *pSymbol = SurfaceTypeToSymbol(sig, surface_type);
	if (sig.IsSignalled()) return str;
	str += pSymbol->GetName();
	if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) {
		str += ":";
		str += NumberToString(::cairo_image_surface_get_width(_surface));
		str += "x";
		str += NumberToString(::cairo_image_surface_get_height(_surface));
	}
	str += ">";
	return str;
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Surface
//-----------------------------------------------------------------------------
// cairo.surface#finish():reduce
AScript_DeclareMethod(Surface, finish)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, finish)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_finish(surface);
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#flush():reduce
AScript_DeclareMethod(Surface, flush)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, flush)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_flush(surface);
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#get_device()
AScript_DeclareMethod(Surface, get_device)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_device)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	cairo_device_t *device = ::cairo_surface_get_device(surface);
	if (IsError(sig, surface) || device == NULL) return Value::Null;
	Object_Device *pObjDevice = new Object_Device(::cairo_device_reference(device));
	return Value(pObjDevice);
}

// cairo.surface#get_font_options()
AScript_DeclareMethod(Surface, get_font_options)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_font_options)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	cairo_font_options_t *options = ::cairo_font_options_create();
	::cairo_surface_get_font_options(surface, options);
	if (IsError(sig, surface)) {
		::cairo_font_options_destroy(options);
		return Value::Null;
	}
	Object_FontOptions *pObjFontOptions = new Object_FontOptions(options);
	return Value(pObjFontOptions);
}

// cairo.surface#get_content()
AScript_DeclareMethod(Surface, get_content)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_content)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	cairo_content_t content = ::cairo_surface_get_content(surface);
	if (IsError(sig, surface)) return Value::Null;
	const Symbol *pSymbol = ContentToSymbol(sig, content);
	if (sig.IsSignalled()) return Value::Null;
	return Value(pSymbol);
}

// cairo.surface#mark_dirty():reduce
AScript_DeclareMethod(Surface, mark_dirty)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, mark_dirty)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_mark_dirty(surface);
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#mark_dirty_rectangle(x:number, y:number, width:number, height:number):reduce
AScript_DeclareMethod(Surface, mark_dirty_rectangle)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
	DeclareArg(env, "width", VTYPE_Number);
	DeclareArg(env, "height", VTYPE_Number);
}

AScript_ImplementMethod(Surface, mark_dirty_rectangle)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_mark_dirty_rectangle(surface,
			args.GetInt(0), args.GetInt(1), args.GetInt(2), args.GetInt(3));
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#set_device_offset(x_offset:number, y_offset:number):reduce
AScript_DeclareMethod(Surface, set_device_offset)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "x_offset", VTYPE_Number);
	DeclareArg(env, "y_offset", VTYPE_Number);
}

AScript_ImplementMethod(Surface, set_device_offset)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_set_device_offset(surface, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#get_device_offset()
AScript_DeclareMethod(Surface, get_device_offset)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_device_offset)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	double x_offset, y_offset;
	::cairo_surface_get_device_offset(surface, &x_offset, &y_offset);
	if (IsError(sig, surface)) return Value::Null;
	return CreateValueList(env, x_offset, y_offset);
}

// cairo.surface#set_fallback_resolution(x_pixels_per_inch:number, y_pixels_per_inch:number):reduce
AScript_DeclareMethod(Surface, set_fallback_resolution)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "x_pixels_per_inch", VTYPE_Number);
	DeclareArg(env, "y_pixels_per_inch", VTYPE_Number);
}

AScript_ImplementMethod(Surface, set_fallback_resolution)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_set_fallback_resolution(surface, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#get_fallback_resolution()
AScript_DeclareMethod(Surface, get_fallback_resolution)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_fallback_resolution)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	double x_pixels_per_inch, y_pixels_per_inch;
	::cairo_surface_get_fallback_resolution(surface, &x_pixels_per_inch, &y_pixels_per_inch);
	if (IsError(sig, surface)) return Value::Null;
	return CreateValueList(env, x_pixels_per_inch, y_pixels_per_inch);
}

// cairo.surface#copy_page():reduce
AScript_DeclareMethod(Surface, copy_page)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, copy_page)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_copy_page(surface);
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#show_page():reduce
AScript_DeclareMethod(Surface, show_page)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, show_page)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	::cairo_surface_show_page(surface);
	if (IsError(sig, surface)) return Value::Null;
	return args.GetSelf();
}

// cairo.surface#has_show_text_glyphs()
AScript_DeclareMethod(Surface, has_show_text_glyphs)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, has_show_text_glyphs)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	bool rtn = ::cairo_surface_has_show_text_glyphs(surface)? true : false;
	if (IsError(sig, surface)) return Value::Null;
	return Value(rtn);
}

// cairo.surface#set_mime_data():reduce
AScript_DeclareMethod(Surface, set_mime_data)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, set_mime_data)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.surface#get_mime_data()
AScript_DeclareMethod(Surface, get_mime_data)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Surface, get_mime_data)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

#if 0
// cairo.surface#XXX():reduce
AScript_DeclareMethod(Surface, XXX)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Surface, XXX)
{
	cairo_surface_t *surface = Object_Surface::GetSelfObj(args)->GetSurface();
	return args.GetSelf();
}
#endif

// implementation of class Surface
AScript_ImplementPrivClassWithCast(Surface)
{
	AScript_AssignMethod(Surface, finish);
	AScript_AssignMethod(Surface, flush);
	AScript_AssignMethod(Surface, get_device);
	AScript_AssignMethod(Surface, get_font_options);
	AScript_AssignMethod(Surface, get_content);
	AScript_AssignMethod(Surface, mark_dirty);
	AScript_AssignMethod(Surface, mark_dirty_rectangle);
	AScript_AssignMethod(Surface, set_device_offset);
	AScript_AssignMethod(Surface, get_device_offset);
	AScript_AssignMethod(Surface, set_fallback_resolution);
	AScript_AssignMethod(Surface, get_fallback_resolution);
	AScript_AssignMethod(Surface, copy_page);
	AScript_AssignMethod(Surface, show_page);
	AScript_AssignMethod(Surface, has_show_text_glyphs);
	AScript_AssignMethod(Surface, set_mime_data);
	AScript_AssignMethod(Surface, get_mime_data);
}

AScript_ImplementCastFrom(Surface)
{
	if (value.IsImage()) {
		Object_Image *pObjImage = Object_Image::Reference(value.GetImageObj());
		cairo_surface_t *surface = CreateSurfaceFromImage(sig, pObjImage);
		if (sig.IsSignalled()) {
			Object_Image::Delete(pObjImage);
			return false;
		}
		value = Value(new Object_Surface(surface, pObjImage));
		return true;
	}
	return false;
}

AScript_ImplementCastTo(Surface)
{
	return false;
}

//-----------------------------------------------------------------------------
// Object_Pattern implementation
//-----------------------------------------------------------------------------
Object_Pattern::~Object_Pattern()
{
	::cairo_pattern_destroy(_pattern);
}

Object *Object_Pattern::Clone() const
{
	return NULL;
}

String Object_Pattern::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.pattern>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Pattern
//-----------------------------------------------------------------------------
// cairo.pattern#add_color_stop_rgb(offset:number, red:number, green:number, blue:number):reduce
AScript_DeclareMethod(Pattern, add_color_stop_rgb)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "offset", VTYPE_Number);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
}

AScript_ImplementMethod(Pattern, add_color_stop_rgb)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	::cairo_pattern_add_color_stop_rgb(pattern, args.GetDouble(0),
		args.GetDouble(1), args.GetDouble(2), args.GetDouble(3));
	if (IsError(sig, pattern)) return Value::Null;
	return args.GetSelf();
}

// cairo.pattern#add_color_stop_rgba(offset:number, red:number, green:number, blue:number, alpha:number):reduce
AScript_DeclareMethod(Pattern, add_color_stop_rgba)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "offset", VTYPE_Number);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
	DeclareArg(env, "alpha", VTYPE_Number);
}

AScript_ImplementMethod(Pattern, add_color_stop_rgba)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	::cairo_pattern_add_color_stop_rgba(pattern, args.GetDouble(0),
		args.GetDouble(1), args.GetDouble(2), args.GetDouble(3), args.GetDouble(4));
	if (IsError(sig, pattern)) return Value::Null;
	return args.GetSelf();
}

// cairo.pattern#get_color_stop_count()
AScript_DeclareMethod(Pattern, get_color_stop_count)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_color_stop_count)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	int count;
	cairo_status_t status = ::cairo_pattern_get_color_stop_count(pattern, &count);
	if (IsError(sig, status)) return Value::Null;
	return Value(count);
}

// cairo.pattern#get_color_stop_rgba(index:number)
AScript_DeclareMethod(Pattern, get_color_stop_rgba)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "index", VTYPE_Number);
}

AScript_ImplementMethod(Pattern, get_color_stop_rgba)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	double offset, red, green, blue, alpha;
	cairo_status_t status = ::cairo_pattern_get_color_stop_rgba(pattern, args.GetInt(0),
										&offset, &red, &green, &blue, &alpha);
	if (IsError(sig, status)) return Value::Null;
	return CreateValueList(env, offset, red, green, blue, alpha);
}

// cairo.pattern#get_rgba()
AScript_DeclareMethod(Pattern, get_rgba)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_rgba)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	double red, green, blue, alpha;
	cairo_status_t status = ::cairo_pattern_get_rgba(pattern,
										&red, &green, &blue, &alpha);
	if (IsError(sig, status)) return Value::Null;
	return CreateValueList(env, red, green, blue, alpha);
}

// cairo.pattern#get_surface()
AScript_DeclareMethod(Pattern, get_surface)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_surface)
{
	Object_Pattern *pSelf = Object_Pattern::GetSelfObj(args);
	cairo_pattern_t *pattern = pSelf->GetPattern();
	cairo_surface_t *surface = NULL;
	cairo_status_t status = ::cairo_pattern_get_surface(pattern, &surface);
	if (IsError(sig, status)) return Value::Null;
	Object_Surface *pObjSurface =
			new Object_Surface(::cairo_surface_reference(surface));
	return Value(pObjSurface);
}

// cairo.pattern#get_linear_points()
AScript_DeclareMethod(Pattern, get_linear_points)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_linear_points)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	double x0, y0, x1, y1;
	cairo_status_t status =
			::cairo_pattern_get_linear_points(pattern, &x0, &y0, &x1, &y1);
	if (IsError(sig, status)) return Value::Null;
	return CreateValueList(env, x0, y0, x1, y1);
}

// cairo.pattern#get_radial_circles():reduce
AScript_DeclareMethod(Pattern, get_radial_circles)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_radial_circles)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	double x0, y0, r0, x1, y1, r1;
	cairo_status_t status =
		::cairo_pattern_get_radial_circles(pattern, &x0, &y0, &r0, &x1, &y1, &r1);
	if (IsError(sig, status)) return Value::Null;
	return CreateValueList(env, x0, y0, r0, x1, y1, r1);
}

// cairo.pattern#set_extend(extend:symbol):reduce
AScript_DeclareMethod(Pattern, set_extend)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "extend", VTYPE_Symbol);
}

AScript_ImplementMethod(Pattern, set_extend)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	cairo_extend_t extend = SymbolToExtend(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_pattern_set_extend(pattern, extend);
	if (IsError(sig, pattern)) return Value::Null;
	return args.GetSelf();
}

// cairo.pattern#get_extend()
AScript_DeclareMethod(Pattern, get_extend)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_extend)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	cairo_extend_t extend = ::cairo_pattern_get_extend(pattern);
	if (IsError(sig, pattern)) return Value::Null;
	const Symbol *pSymbol = ExtendToSymbol(sig, extend);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.pattern#set_filter(filter:symbol):reduce
AScript_DeclareMethod(Pattern, set_filter)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "filter", VTYPE_Symbol);
}

AScript_ImplementMethod(Pattern, set_filter)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	cairo_filter_t filter = SymbolToFilter(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_pattern_set_filter(pattern, filter);
	if (IsError(sig, pattern)) return Value::Null;
	return args.GetSelf();
}

// cairo.pattern#get_filter()
AScript_DeclareMethod(Pattern, get_filter)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_filter)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	cairo_filter_t filter = ::cairo_pattern_get_filter(pattern);
	if (IsError(sig, pattern)) return Value::Null;
	const Symbol *pSymbol = FilterToSymbol(sig, filter);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.pattern#set_matrix(matrix:matrix):reduce
AScript_DeclareMethod(Pattern, set_matrix)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "matrix", VTYPE_Matrix);
}

AScript_ImplementMethod(Pattern, set_matrix)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	Object_Matrix *pObjMatrix = args.GetMatrixObj(0);
	cairo_matrix_t matrix;
	if (!MatrixToCairo(sig, matrix, pObjMatrix)) return Value::Null;
	::cairo_pattern_set_matrix(pattern, &matrix);
	if (IsError(sig, pattern)) return Value::Null;
	return args.GetSelf();
}

// cairo.pattern#get_matrix()
AScript_DeclareMethod(Pattern, get_matrix)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Pattern, get_matrix)
{
	cairo_pattern_t *pattern = Object_Pattern::GetSelfObj(args)->GetPattern();
	cairo_matrix_t matrix;
	::cairo_pattern_get_matrix(pattern, &matrix);
	if (IsError(sig, pattern)) return Value::Null;
	Object_Matrix *pObjMatrix = CairoToMatrix(env, matrix);
	return Value(pObjMatrix);
}

// implementation of class Pattern
AScript_ImplementPrivClass(Pattern)
{
	AScript_AssignMethod(Pattern, add_color_stop_rgb);
	AScript_AssignMethod(Pattern, add_color_stop_rgba);
	AScript_AssignMethod(Pattern, get_color_stop_count);
	AScript_AssignMethod(Pattern, get_color_stop_rgba);
	AScript_AssignMethod(Pattern, get_rgba);
	AScript_AssignMethod(Pattern, get_surface);
	AScript_AssignMethod(Pattern, get_linear_points);
	AScript_AssignMethod(Pattern, get_radial_circles);
	AScript_AssignMethod(Pattern, set_extend);
	AScript_AssignMethod(Pattern, get_extend);
	AScript_AssignMethod(Pattern, set_filter);
	AScript_AssignMethod(Pattern, get_filter);
	AScript_AssignMethod(Pattern, set_matrix);
	AScript_AssignMethod(Pattern, get_matrix);
}

//-----------------------------------------------------------------------------
// Object_Path implementation
//-----------------------------------------------------------------------------
Object_Path::~Object_Path()
{
	::cairo_path_destroy(_path);
}

Object *Object_Path::Clone() const
{
	return NULL;
}

String Object_Path::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.path>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Path
//-----------------------------------------------------------------------------
// implementation of class Path
AScript_ImplementPrivClass(Path)
{
}

//-----------------------------------------------------------------------------
// Object_Glyph implementation
//-----------------------------------------------------------------------------
Object_Glyph::~Object_Glyph()
{
}

Object *Object_Glyph::Clone() const
{
	return NULL;
}

String Object_Glyph::ToString(Signal sig, bool exprFlag)
{
	return String("<cairo.path>");
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Glyph
//-----------------------------------------------------------------------------
// implementation of class Glyph
AScript_ImplementPrivClass(Glyph)
{
}

//-----------------------------------------------------------------------------
// Object_Context implementation
//-----------------------------------------------------------------------------
Object_Context::~Object_Context()
{
	::cairo_destroy(_cr);
	Object::Delete(_pObjSurface);
}

Object *Object_Context::Clone() const
{
	return NULL;
}

Value Object_Context::DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag)
{
	evaluatedFlag = true;
	if (pSymbol->IsIdentical(AScript_PrivSymbol(surface))) {
		return Value(Object_Surface::Reference(_pObjSurface));
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(width))) {
		if (!_pObjSurface->HasSize()) return Value::Null;
		return Value(_pObjSurface->GetWidth());
	} else if (pSymbol->IsIdentical(AScript_PrivSymbol(height))) {
		if (!_pObjSurface->HasSize()) return Value::Null;
		return Value(_pObjSurface->GetHeight());
	}
	evaluatedFlag = false;
	return Value::Null;
}

String Object_Context::ToString(Signal sig, bool exprFlag)
{
	String str;
	str += "<cairo.context:";
	cairo_surface_t *surface = ::cairo_get_target(_cr);
	cairo_surface_type_t surface_type = ::cairo_surface_get_type(surface);
	const Symbol *pSymbol = SurfaceTypeToSymbol(sig, surface_type);
	if (sig.IsSignalled()) return str;
	str += pSymbol->GetName();
	if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) {
		str += ":";
		str += NumberToString(::cairo_image_surface_get_width(surface));
		str += "x";
		str += NumberToString(::cairo_image_surface_get_height(surface));
	}
	str += ">";
	return str;
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Context
// Context operations
//-----------------------------------------------------------------------------
// cairo.context#save():reduce {block?}
AScript_DeclareMethod(Context, save)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementMethod(Context, save)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_save(cr);
	if (IsError(sig, cr)) return Value::Null;
	if (args.IsBlockSpecified()) {
		const Expr_Block *pExprBlock = args.GetBlock(env, sig);
		if (sig.IsSignalled()) return Value::Null;
		pExprBlock->Exec(env, sig);
		::cairo_restore(cr);
		if (IsError(sig, cr)) return Value::Null;
	}
	return args.GetSelf();
}

// cairo.context#restore():reduce
AScript_DeclareMethod(Context, restore)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, restore)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_restore(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_target()
AScript_DeclareMethod(Context, get_target)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_target)
{
	Object_Context *pSelf = Object_Context::GetSelfObj(args);
	cairo_t *cr = pSelf->GetContext();
	cairo_surface_t *surface = ::cairo_get_target(cr);
	if (IsError(sig, cr)) return Value::Null;
	return Value(Object_Surface::Reference(pSelf->GetSurfaceObj()));
}

// cairo.context#push_group():reduce
AScript_DeclareMethod(Context, push_group)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, push_group)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_push_group(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#push_group_with_content(content:symbol):reduce
AScript_DeclareMethod(Context, push_group_with_content)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "content", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, push_group_with_content)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_content_t content = SymbolToContent(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_push_group_with_content(cr, content);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#pop_group()
AScript_DeclareMethod(Context, pop_group)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, pop_group)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_pattern_t *pattern = ::cairo_pop_group(cr);
	if (IsError(sig, cr)) return Value::Null;
	Object_Pattern *pObjPattern = new Object_Pattern(pattern);
	return Value(pObjPattern);
}

// cairo.context#pop_group_to_source():reduce
AScript_DeclareMethod(Context, pop_group_to_source)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, pop_group_to_source)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_pop_group_to_source(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_group_target()
AScript_DeclareMethod(Context, get_group_target)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_group_target)
{
	Object_Context *pSelf = Object_Context::GetSelfObj(args);
	cairo_t *cr = pSelf->GetContext();
	cairo_surface_t *surface = ::cairo_get_group_target(cr);
	if (IsError(sig, cr)) return Value::Null;
	Object_Surface *pObjSurface =
			new Object_Surface(::cairo_surface_reference(surface));
	return Value(pObjSurface);
}

// cairo.context#set_source_rgb(red:number, green:number, blue:number):reduce
AScript_DeclareMethod(Context, set_source_rgb)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_source_rgb)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_source_rgb(cr, args.GetDouble(0), args.GetDouble(1), args.GetDouble(2));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_source_rgba(red:number, green:number, blue:number, alpha:number):reduce
AScript_DeclareMethod(Context, set_source_rgba)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
	DeclareArg(env, "alpha", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_source_rgba)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_source_rgba(cr, args.GetDouble(0), args.GetDouble(1),
									args.GetDouble(2), args.GetDouble(3));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_source_color(color:color, alpha?:number):reduce
AScript_DeclareMethod(Context, set_source_color)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "color", VTYPE_Color);
	DeclareArg(env, "alpha", VTYPE_Number, OCCUR_ZeroOrOnce);
}

AScript_ImplementMethod(Context, set_source_color)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	const Color &color = args.GetColorObj(0)->GetColor();
	double red = static_cast<double>(color.GetRed()) / 255;
	double green = static_cast<double>(color.GetGreen()) / 255;
	double blue = static_cast<double>(color.GetBlue()) / 255;
	if (args.IsNumber(1)) {
		double alpha = args.GetDouble(1);
		::cairo_set_source_rgba(cr, red, green, blue, alpha);
	} else {
		::cairo_set_source_rgb(cr, red, green, blue);
	}
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_source(source:cairo.pattern):reduce
AScript_DeclareMethod(Context, set_source)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "source", AScript_PrivVTYPE(Pattern));
}

AScript_ImplementMethod(Context, set_source)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_pattern_t *source = Object_Pattern::GetObject(args, 0)->GetPattern();
	::cairo_set_source(cr, source);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_source_surface(surface:cairo.surface, x:number, y:number):reduce
AScript_DeclareMethod(Context, set_source_surface)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "surface", AScript_PrivVTYPE(Surface));
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_source_surface)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_surface_t *surface = Object_Surface::GetObject(args, 0)->GetSurface();
	double x = args.GetDouble(1);
	double y = args.GetDouble(2);
	::cairo_set_source_surface(cr, surface, x, y);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_source()
AScript_DeclareMethod(Context, get_source)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_source)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_pattern_t *pattern = ::cairo_get_source(cr);
	if (IsError(sig, cr)) return Value::Null;
	Object_Pattern *pObjPattern =
				new Object_Pattern(::cairo_pattern_reference(pattern));
	return Value(pObjPattern);
}

// cairo.context#set_antialias(antialias:symbol):reduce
AScript_DeclareMethod(Context, set_antialias)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "antialias", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, set_antialias)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_antialias_t antialias = SymbolToAntialias(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_set_antialias(cr, antialias);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_antialias()
AScript_DeclareMethod(Context, get_antialias)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_antialias)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_antialias_t antialias = ::cairo_get_antialias(cr);
	if (IsError(sig, cr)) return Value::Null;
	const Symbol *pSymbol = AntialiasToSymbol(sig, antialias);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.context#set_dash(dashes[]:number, offset:number):reduce
AScript_DeclareMethod(Context, set_dash)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "dashes", VTYPE_Number, OCCUR_Once, true);
	DeclareArg(env, "offset", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_dash)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	int num_dashes = static_cast<int>(args.GetList(0).size());
	double *dashes = new double [num_dashes];
	int i = 0;
	foreach_const (ValueList, pValue, args.GetList(0)) {
		dashes[i++] = pValue->GetDouble();
	}
	double offset = args.GetDouble(1);
	::cairo_set_dash(cr, dashes, num_dashes, offset);
	delete[] dashes;
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_dash()
AScript_DeclareMethod(Context, get_dash)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_dash)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
#if 0
	//int num_dashes = ::cairo_get_dash_count(cr);
	double *dashes = new double [num_dashes];
	double offset = 0;
	::cairo_get_dash(cr, dashes, &offset);
	if (IsError(sig, cr)) return Value::Null;
#endif
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#set_fill_rule(fill_rule:symbol):reduce
AScript_DeclareMethod(Context, set_fill_rule)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "fill_rule", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, set_fill_rule)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_fill_rule_t fill_rule = SymbolToFillRule(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_set_fill_rule(cr, fill_rule);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_fill_rule()
AScript_DeclareMethod(Context, get_fill_rule)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_fill_rule)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_fill_rule_t fill_rule = ::cairo_get_fill_rule(cr);
	if (IsError(sig, cr)) return Value::Null;
	const Symbol *pSymbol = FillRuleToSymbol(sig, fill_rule);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.context#set_line_cap(line_cap:symbol):reduce
AScript_DeclareMethod(Context, set_line_cap)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "line_cap", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, set_line_cap)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_line_cap_t line_cap = SymbolToLineCap(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_set_line_cap(cr, line_cap);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_line_cap()
AScript_DeclareMethod(Context, get_line_cap)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_line_cap)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_line_cap_t line_cap = ::cairo_get_line_cap(cr);
	if (IsError(sig, cr)) return Value::Null;
	const Symbol *pSymbol = LineCapToSymbol(sig, line_cap);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.context#set_line_join(line_join:symbol):reduce
AScript_DeclareMethod(Context, set_line_join)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "line_join", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, set_line_join)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_line_join_t line_join = SymbolToLineJoin(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_set_line_join(cr, line_join);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_line_join()
AScript_DeclareMethod(Context, get_line_join)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_line_join)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_line_join_t line_join = ::cairo_get_line_join(cr);
	if (IsError(sig, cr)) return Value::Null;
	const Symbol *pSymbol = LineJoinToSymbol(sig, line_join);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.context#set_line_width(width:number):reduce
AScript_DeclareMethod(Context, set_line_width)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "width", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_line_width)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_line_width(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_line_width()
AScript_DeclareMethod(Context, get_line_width)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_line_width)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double width = ::cairo_get_line_width(cr);
	if (IsError(sig, cr)) return Value::Null;
	return Value(width);
}

// cairo.context#set_miter_limit(limit:number):reduce
AScript_DeclareMethod(Context, set_miter_limit)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "limit", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_miter_limit)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_miter_limit(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_miter_limit()
AScript_DeclareMethod(Context, get_miter_limit)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_miter_limit)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double limit = ::cairo_get_miter_limit(cr);
	if (IsError(sig, cr)) return Value::Null;
	return Value(limit);
}

// cairo.context#set_operator(op:symbol):reduce
AScript_DeclareMethod(Context, set_operator)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "op", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, set_operator)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_operator_t operator_ = SymbolToOperator(sig, args.GetSymbol(0));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_set_operator(cr, operator_);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_operator()
AScript_DeclareMethod(Context, get_operator)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_operator)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_operator_t operator_ = ::cairo_get_operator(cr);
	if (IsError(sig, cr)) return Value::Null;
	const Symbol *pSymbol = OperatorToSymbol(sig, operator_);
	if (pSymbol == NULL) return Value::Null;
	return Value(pSymbol);
}

// cairo.context#set_tolerance(tolerance:number):reduce
AScript_DeclareMethod(Context, set_tolerance)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "tolerance", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_tolerance)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_tolerance(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_tolerance()
AScript_DeclareMethod(Context, get_tolerance)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_tolerance)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double tolerance = ::cairo_get_tolerance(cr);
	if (IsError(sig, cr)) return Value::Null;
	return Value(tolerance);
}

// cairo.context#clip():reduce
AScript_DeclareMethod(Context, clip)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, clip)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_clip(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#clip_preserve():reduce
AScript_DeclareMethod(Context, clip_preserve)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, clip_preserve)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_clip_preserve(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#clip_extents()
AScript_DeclareMethod(Context, clip_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, clip_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x1, y1, x2, y2;
	::cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x1, y1, x2, y2);
}

// cairo.context#in_clip(x:number, y:number)
AScript_DeclareMethod(Context, in_clip)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, in_clip)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	bool rtn = ::cairo_in_clip(cr, args.GetDouble(0), args.GetDouble(1))? true : false;
	if (IsError(sig, cr)) return Value::Null;
	return Value(rtn);
}

// cairo.context#reset_clip():reduce
AScript_DeclareMethod(Context, reset_clip)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, reset_clip)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_reset_clip(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#copy_clip_rectangle_list()
AScript_DeclareMethod(Context, copy_clip_rectangle_list)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, copy_clip_rectangle_list)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_rectangle_list_t *rectangle_list = ::cairo_copy_clip_rectangle_list(cr);
	if (IsError(sig, cr)) {
		::cairo_rectangle_list_destroy(rectangle_list);
		return Value::Null;
	}
	Value result;
	ValueList &valList = result.InitAsList(env);
	valList.reserve(rectangle_list->num_rectangles);
	for (int i = 0; i < rectangle_list->num_rectangles; i++) {
		cairo_rectangle_t &rectangle = rectangle_list->rectangles[i];
		valList.push_back(RectangleToValue(env, rectangle));
	}
	::cairo_rectangle_list_destroy(rectangle_list);
	return result;
}

// cairo.context#fill():reduce
AScript_DeclareMethod(Context, fill)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, fill)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_fill(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#fill_preserve():reduce
AScript_DeclareMethod(Context, fill_preserve)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, fill_preserve)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_fill_preserve(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#fill_extents():reduce
AScript_DeclareMethod(Context, fill_extents)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, fill_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x1, y1, x2, y2;
	::cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x1, y1, x2, y2);
}

// cairo.context#in_fill(x:number, y:number)
AScript_DeclareMethod(Context, in_fill)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, in_fill)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	bool rtn = ::cairo_in_fill(cr, args.GetDouble(0), args.GetDouble(1))? true : false;
	if (IsError(sig, cr)) return Value::Null;
	return Value(rtn);
}

// cairo.context#mask(pattern:cairo.pattern):reduce
AScript_DeclareMethod(Context, mask)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "pattern", AScript_PrivVTYPE(Pattern));
}

AScript_ImplementMethod(Context, mask)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_pattern_t *pattern = Object_Pattern::GetObject(args, 0)->GetPattern();
	::cairo_mask(cr, pattern);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#mask_surface(surface:cairo.surface, surface_x:number, surface_y:number):reduce
AScript_DeclareMethod(Context, mask_surface)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "surface", AScript_PrivVTYPE(Surface));
	DeclareArg(env, "surface_x", VTYPE_Number);
	DeclareArg(env, "surface_y", VTYPE_Number);
}

AScript_ImplementMethod(Context, mask_surface)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_surface_t *surface = Object_Surface::GetObject(args, 0)->GetSurface();
	double surface_x = args.GetDouble(1);
	double surface_y = args.GetDouble(2);
	::cairo_mask_surface(cr, surface, surface_x, surface_y);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#paint():reduce
AScript_DeclareMethod(Context, paint)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, paint)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_paint(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#paint_with_alpha(alpha:number):reduce
AScript_DeclareMethod(Context, paint_with_alpha)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "alpha", VTYPE_Number);
}

AScript_ImplementMethod(Context, paint_with_alpha)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_paint_with_alpha(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#stroke():reduce
AScript_DeclareMethod(Context, stroke)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, stroke)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_stroke(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#stroke_preserve():reduce
AScript_DeclareMethod(Context, stroke_preserve)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, stroke_preserve)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_stroke_preserve(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#stroke_extents()
AScript_DeclareMethod(Context, stroke_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, stroke_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x1, y1, x2, y2;
	::cairo_stroke_extents(cr, &x1, &y1, &x2, &y2);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x1, y1, x2, y2);
}

// cairo.context#in_stroke(x:number, y:number)
AScript_DeclareMethod(Context, in_stroke)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, in_stroke)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	bool rtn = ::cairo_in_stroke(cr, args.GetDouble(0), args.GetDouble(1))? true : false;
	if (IsError(sig, cr)) return Value::Null;
	return Value(rtn);
}

// cairo.context#copy_page():reduce
AScript_DeclareMethod(Context, copy_page)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, copy_page)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_copy_page(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#show_page():reduce
AScript_DeclareMethod(Context, show_page)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, show_page)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_show_page(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Context
// Paths - Creating paths and manipulating path data
//-----------------------------------------------------------------------------
// cairo.context#copy_path()
AScript_DeclareMethod(Context, copy_path)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, copy_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_path_t *path = ::cairo_copy_path(cr);
	if (IsError(sig, cr)) return Value::Null;
	Value result(new Object_Path(path));
	return result;
}

// cairo.context#copy_path_flat()
AScript_DeclareMethod(Context, copy_path_flat)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, copy_path_flat)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_path_t *path = ::cairo_copy_path_flat(cr);
	if (IsError(sig, cr)) return Value::Null;
	Value result(new Object_Path(path));
	return result;
}

// cairo.context#has_current_point()
AScript_DeclareMethod(Context, has_current_point)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, has_current_point)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	bool rtn = ::cairo_has_current_point(cr)? true : false;
	if (IsError(sig, cr)) return Value::Null;
	return Value(rtn);
}

// cairo.context#get_current_point()
AScript_DeclareMethod(Context, get_current_point)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_current_point)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x, y;
	::cairo_get_current_point(cr, &x, &y);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x, y);
}

// cairo.context#new_path():reduce
AScript_DeclareMethod(Context, new_path)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, new_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_new_path(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#new_sub_path():reduce
AScript_DeclareMethod(Context, new_sub_path)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, new_sub_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_new_sub_path(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#close_path():reduce
AScript_DeclareMethod(Context, close_path)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, close_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_close_path(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#arc(xc:number, yc:number, radius:number,
//                   angle1?:number, angle2?:number):map:reduce
AScript_DeclareMethod(Context, arc)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "xc", VTYPE_Number);
	DeclareArg(env, "yc", VTYPE_Number);
	DeclareArg(env, "radius", VTYPE_Number);
	DeclareArg(env, "angle1", VTYPE_Number, OCCUR_ZeroOrOnce);
	DeclareArg(env, "angle2", VTYPE_Number, OCCUR_ZeroOrOnce);
}

AScript_ImplementMethod(Context, arc)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double angle1 = args.IsNumber(3)? args.GetDouble(3) : 0;
	double angle2 = args.IsNumber(4)? args.GetDouble(4) : 2 * NUM_PI;
	::cairo_arc(cr, args.GetDouble(0), args.GetDouble(1),
										args.GetDouble(2), angle1, angle2);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#arc_negative(xc:number, yc:number, radius:number,
//                            angle1?:number, angle2?:number):map:reduce
AScript_DeclareMethod(Context, arc_negative)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "xc", VTYPE_Number);
	DeclareArg(env, "yc", VTYPE_Number);
	DeclareArg(env, "radius", VTYPE_Number);
	DeclareArg(env, "angle1", VTYPE_Number, OCCUR_ZeroOrOnce);
	DeclareArg(env, "angle2", VTYPE_Number, OCCUR_ZeroOrOnce);
}

AScript_ImplementMethod(Context, arc_negative)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double angle1 = args.IsNumber(3)? args.GetDouble(3) : 0;
	double angle2 = args.IsNumber(4)? args.GetDouble(4) : 2 * NUM_PI;
	::cairo_arc_negative(cr, args.GetDouble(0), args.GetDouble(1),
										args.GetDouble(2), angle1, angle2);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#curve_to(x1:number, y1:number, x2:number, y2:number, x3:number, y3:number):map:reduce
AScript_DeclareMethod(Context, curve_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "x1", VTYPE_Number);
	DeclareArg(env, "y1", VTYPE_Number);
	DeclareArg(env, "x2", VTYPE_Number);
	DeclareArg(env, "y2", VTYPE_Number);
	DeclareArg(env, "x3", VTYPE_Number);
	DeclareArg(env, "y3", VTYPE_Number);
}

AScript_ImplementMethod(Context, curve_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_curve_to(cr,
			args.GetDouble(0), args.GetDouble(1),
			args.GetDouble(2), args.GetDouble(3),
			args.GetDouble(4), args.GetDouble(5));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#line_to(x:number, y:number):map:reduce
AScript_DeclareMethod(Context, line_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, line_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_line_to(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#move_to(x:number, y:number):map:reduce
AScript_DeclareMethod(Context, move_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, move_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_move_to(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#rectangle(x:number, y:number, width:number, height:number):map:reduce
AScript_DeclareMethod(Context, rectangle)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
	DeclareArg(env, "width", VTYPE_Number);
	DeclareArg(env, "height", VTYPE_Number);
}

AScript_ImplementMethod(Context, rectangle)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_rectangle(cr,
			args.GetDouble(0), args.GetDouble(1),
			args.GetDouble(2), args.GetDouble(3));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#glyph_path(glyph[]:cairo.glyph):reduce
AScript_DeclareMethod(Context, glyph_path)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "glyph", AScript_PrivVTYPE(Glyph));
}

AScript_ImplementMethod(Context, glyph_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	//::cairo_text_path(cr, args.GetString(0));
	if (IsError(sig, cr)) return Value::Null;
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#text_path(text:string):map:reduce
AScript_DeclareMethod(Context, text_path)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "text", VTYPE_String);
}

AScript_ImplementMethod(Context, text_path)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_text_path(cr, args.GetString(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#rel_curve_to(dx1:number, dy1:number, dx2:number, dy2:number, dx3:number, dy3:number):map:reduce
AScript_DeclareMethod(Context, rel_curve_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "dx1", VTYPE_Number);
	DeclareArg(env, "dy1", VTYPE_Number);
	DeclareArg(env, "dx2", VTYPE_Number);
	DeclareArg(env, "dy2", VTYPE_Number);
	DeclareArg(env, "dx3", VTYPE_Number);
	DeclareArg(env, "dy3", VTYPE_Number);
}

AScript_ImplementMethod(Context, rel_curve_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_rel_curve_to(cr,
			args.GetDouble(0), args.GetDouble(1),
			args.GetDouble(2), args.GetDouble(3),
			args.GetDouble(4), args.GetDouble(5));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#rel_line_to(dx:number, dy:number):map:reduce
AScript_DeclareMethod(Context, rel_line_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "dx", VTYPE_Number);
	DeclareArg(env, "dy", VTYPE_Number);
}

AScript_ImplementMethod(Context, rel_line_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_rel_line_to(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#rel_move_to(dx:number, dy:number):map:reduce
AScript_DeclareMethod(Context, rel_move_to)
{
	SetMode(RSLTMODE_Reduce, FLAG_Map);
	DeclareArg(env, "dx", VTYPE_Number);
	DeclareArg(env, "dy", VTYPE_Number);
}

AScript_ImplementMethod(Context, rel_move_to)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_rel_move_to(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#path_extents()
AScript_DeclareMethod(Context, path_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, path_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x1, y1, x2, y2;
	::cairo_path_extents(cr, &x1, &y1, &x2, &y2);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x1, y1, x2, y2);
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Context
// Transformations - Manipulating the current transformation matrix
//-----------------------------------------------------------------------------
// cairo.context#translate(tx:number, ty:number):reduce
AScript_DeclareMethod(Context, translate)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "tx", VTYPE_Number);
	DeclareArg(env, "ty", VTYPE_Number);
}

AScript_ImplementMethod(Context, translate)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_translate(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#scale(sx:number, sy:number):reduce
AScript_DeclareMethod(Context, scale)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "sx", VTYPE_Number);
	DeclareArg(env, "sy", VTYPE_Number);
}

AScript_ImplementMethod(Context, scale)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_scale(cr, args.GetDouble(0), args.GetDouble(1));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#rotate(angle:number):reduce
AScript_DeclareMethod(Context, rotate)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "angle", VTYPE_Number);
}

AScript_ImplementMethod(Context, rotate)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_rotate(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#transform(matrix:matrix):reduce
AScript_DeclareMethod(Context, transform)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "matrix", VTYPE_Matrix);
}

AScript_ImplementMethod(Context, transform)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	Object_Matrix *pObjMatrix = args.GetMatrixObj(0);
	cairo_matrix_t matrix;
	if (!MatrixToCairo(sig, matrix, pObjMatrix)) return Value::Null;
	::cairo_transform(cr, &matrix);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_matrix(matrix:matrix):reduce
AScript_DeclareMethod(Context, set_matrix)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "matrix", VTYPE_Matrix);
}

AScript_ImplementMethod(Context, set_matrix)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	Object_Matrix *pObjMatrix = args.GetMatrixObj(0);
	cairo_matrix_t matrix;
	if (!MatrixToCairo(sig, matrix, pObjMatrix)) return Value::Null;
	::cairo_set_matrix(cr, &matrix);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_matrix()
AScript_DeclareMethod(Context, get_matrix)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_matrix)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_matrix_t matrix;
	::cairo_get_matrix(cr, &matrix);
	if (IsError(sig, cr)) return Value::Null;
	Object_Matrix *pObjMatrix = CairoToMatrix(env, matrix);
	return Value(pObjMatrix);
}

// cairo.context#identity_matrix():reduce
AScript_DeclareMethod(Context, identity_matrix)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, identity_matrix)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_identity_matrix(cr);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#user_to_device(x:number, y:number)
AScript_DeclareMethod(Context, user_to_device)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, user_to_device)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x = args.GetDouble(0);
	double y = args.GetDouble(1);
	::cairo_user_to_device(cr, &x, &y);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x, y);
}

// cairo.context#user_to_device_distance(dx:number, dy:number)
AScript_DeclareMethod(Context, user_to_device_distance)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "dx", VTYPE_Number);
	DeclareArg(env, "dy", VTYPE_Number);
}

AScript_ImplementMethod(Context, user_to_device_distance)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double dx = args.GetDouble(0);
	double dy = args.GetDouble(1);
	::cairo_user_to_device_distance(cr, &dx, &dy);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, dx, dy);
}

// cairo.context#device_to_user(x:number, y:number)
AScript_DeclareMethod(Context, device_to_user)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x", VTYPE_Number);
	DeclareArg(env, "y", VTYPE_Number);
}

AScript_ImplementMethod(Context, device_to_user)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double x = args.GetDouble(0);
	double y = args.GetDouble(1);
	::cairo_device_to_user(cr, &x, &y);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, x, y);
}

// cairo.context#device_to_user_distance(dx:number, dy:number)
AScript_DeclareMethod(Context, device_to_user_distance)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "dx", VTYPE_Number);
	DeclareArg(env, "dy", VTYPE_Number);
}

AScript_ImplementMethod(Context, device_to_user_distance)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	double dx = args.GetDouble(0);
	double dy = args.GetDouble(1);
	::cairo_device_to_user_distance(cr, &dx, &dy);
	if (IsError(sig, cr)) return Value::Null;
	return CreateValueList(env, dx, dy);
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Context
// text - Rendering text and glyphs
//-----------------------------------------------------------------------------
// cairo.context#select_font_face(family:string, slant:symbol, weight:symbol):reduce
AScript_DeclareMethod(Context, select_font_face)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "family", VTYPE_String);
	DeclareArg(env, "slant", VTYPE_Symbol);
	DeclareArg(env, "weight", VTYPE_Symbol);
}

AScript_ImplementMethod(Context, select_font_face)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	const char *family = args.GetString(0);
	cairo_font_slant_t slant = SymbolToFontSlant(sig, args.GetSymbol(1));
	if (sig.IsSignalled()) return Value::Null;
	cairo_font_weight_t weight = SymbolToFontWeight(sig, args.GetSymbol(2));
	if (sig.IsSignalled()) return Value::Null;
	::cairo_select_font_face(cr, family, slant, weight);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_font_size(size:number):reduce
AScript_DeclareMethod(Context, set_font_size)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "size", VTYPE_Number);
}

AScript_ImplementMethod(Context, set_font_size)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_font_size(cr, args.GetDouble(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#set_font_matrix(matrix:matrix):reduce
AScript_DeclareMethod(Context, set_font_matrix)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "matrix", VTYPE_Matrix);
}

AScript_ImplementMethod(Context, set_font_matrix)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	Object_Matrix *pObjMatrix = Object_Matrix::GetObject(args, 0);
	cairo_matrix_t matrix;
	if (!MatrixToCairo(sig, matrix, pObjMatrix)) return Value::Null;
	::cairo_set_font_matrix(cr, &matrix);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_font_matrix()
AScript_DeclareMethod(Context, get_font_matrix)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_font_matrix)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_matrix_t matrix;
	::cairo_get_font_matrix(cr, &matrix);
	if (IsError(sig, cr)) return Value::Null;
	Object_Matrix *pObjMatrix = CairoToMatrix(env, matrix);
	return Value(pObjMatrix);
}

// cairo.context#set_font_options(options:cairo.font_options):reduce
AScript_DeclareMethod(Context, set_font_options)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "options", AScript_PrivVTYPE(FontOptions));
}

AScript_ImplementMethod(Context, set_font_options)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_set_font_options(cr,
				Object_FontOptions::GetObject(args, 0)->GetFontOptions());
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#get_font_options()
AScript_DeclareMethod(Context, get_font_options)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_font_options)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_font_options_t *options = ::cairo_font_options_create();
	::cairo_get_font_options(cr, options);
	if (IsError(sig, cr)) {
		::cairo_font_options_destroy(options);
		return Value::Null;
	}
	Object_FontOptions *pObjFontOptions = new Object_FontOptions(options);
	return Value(pObjFontOptions);
}

// cairo.context#set_font_face():reduce
AScript_DeclareMethod(Context, set_font_face)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, set_font_face)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#get_font_face()
AScript_DeclareMethod(Context, get_font_face)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_font_face)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#set_scaled_font():reduce
AScript_DeclareMethod(Context, set_scaled_font)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, set_scaled_font)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#get_scaled_font()
AScript_DeclareMethod(Context, get_scaled_font)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, get_scaled_font)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#show_text(text:string):reduce
AScript_DeclareMethod(Context, show_text)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "text", VTYPE_String);
}

AScript_ImplementMethod(Context, show_text)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	::cairo_show_text(cr, args.GetString(0));
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#show_glyphs(glyphs[]:cairo.glyph):reduce
AScript_DeclareMethod(Context, show_glyphs)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
	DeclareArg(env, "glyphs", AScript_PrivVTYPE(Glyph), OCCUR_Once, true);
}

AScript_ImplementMethod(Context, show_glyphs)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	int num_glyphs = static_cast<int>(args.GetList(0).size());
	cairo_glyph_t *glyphs = ::cairo_glyph_allocate(num_glyphs);
	int i = 0;
	foreach_const (ValueList, pValue, args.GetList(0)) {
		glyphs[i++] = Object_Glyph::GetObject(*pValue)->GetGlyph();
	}
	::cairo_show_glyphs(cr, glyphs, num_glyphs);
	::cairo_glyph_free(glyphs);
	if (IsError(sig, cr)) return Value::Null;
	return args.GetSelf();
}

// cairo.context#show_text_glyphs():reduce
AScript_DeclareMethod(Context, show_text_glyphs)
{
	SetMode(RSLTMODE_Reduce, FLAG_None);
}

AScript_ImplementMethod(Context, show_text_glyphs)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	
	sig.SetError(ERR_SystemError, "not implemented yet");
	
	return args.GetSelf();
}

// cairo.context#font_extents()
AScript_DeclareMethod(Context, font_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, font_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_font_extents_t extents;
	::cairo_font_extents(cr, &extents);
	if (IsError(sig, cr)) return Value::Null;
	Object_FontExtents *pObjFontExtents = new Object_FontExtents(extents);
	return Value(pObjFontExtents);
}

// cairo.context#text_extents(text:string)
AScript_DeclareMethod(Context, text_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "text", VTYPE_String);
}

AScript_ImplementMethod(Context, text_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	cairo_text_extents_t extents;
	::cairo_text_extents(cr, args.GetString(0), &extents);
	if (IsError(sig, cr)) return Value::Null;
	Object_TextExtents *pObjTextExtents = new Object_TextExtents(extents);
	return Value(pObjTextExtents);
}

// cairo.context#glyph_extents(glyphs[]:cairo.glyph)
AScript_DeclareMethod(Context, glyph_extents)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
}

AScript_ImplementMethod(Context, glyph_extents)
{
	cairo_t *cr = Object_Context::GetSelfObj(args)->GetContext();
	int num_glyphs = static_cast<int>(args.GetList(0).size());
	cairo_glyph_t *glyphs = ::cairo_glyph_allocate(num_glyphs);
	int i = 0;
	foreach_const (ValueList, pValue, args.GetList(0)) {
		glyphs[i++] = Object_Glyph::GetObject(*pValue)->GetGlyph();
	}
	cairo_text_extents_t extents;
	::cairo_glyph_extents(cr, glyphs, num_glyphs, &extents);
	::cairo_glyph_free(glyphs);
	if (IsError(sig, cr)) return Value::Null;
	Object_TextExtents *pObjTextExtents = new Object_TextExtents(extents);
	return Value(pObjTextExtents);
}

// implementation of class Context
AScript_ImplementPrivClass(Context)
{
	// Context operations
	AScript_AssignMethod(Context, save);
	AScript_AssignMethod(Context, restore);
	AScript_AssignMethod(Context, get_target);
	AScript_AssignMethod(Context, push_group);
	AScript_AssignMethod(Context, push_group_with_content);
	AScript_AssignMethod(Context, pop_group);
	AScript_AssignMethod(Context, pop_group_to_source);
	AScript_AssignMethod(Context, get_group_target);
	AScript_AssignMethod(Context, set_source_rgb);
	AScript_AssignMethod(Context, set_source_rgba);
	AScript_AssignMethod(Context, set_source_color);
	AScript_AssignMethod(Context, set_source);
	AScript_AssignMethod(Context, set_source_surface);
	AScript_AssignMethod(Context, get_source);
	AScript_AssignMethod(Context, set_antialias);
	AScript_AssignMethod(Context, get_antialias);
	AScript_AssignMethod(Context, set_dash);
	AScript_AssignMethod(Context, get_dash);
	AScript_AssignMethod(Context, set_fill_rule);
	AScript_AssignMethod(Context, get_fill_rule);
	AScript_AssignMethod(Context, set_line_cap);
	AScript_AssignMethod(Context, get_line_cap);
	AScript_AssignMethod(Context, set_line_join);
	AScript_AssignMethod(Context, get_line_join);
	AScript_AssignMethod(Context, set_line_width);
	AScript_AssignMethod(Context, get_line_width);
	AScript_AssignMethod(Context, set_miter_limit);
	AScript_AssignMethod(Context, get_miter_limit);
	AScript_AssignMethod(Context, set_operator);
	AScript_AssignMethod(Context, get_operator);
	AScript_AssignMethod(Context, set_tolerance);
	AScript_AssignMethod(Context, get_tolerance);
	AScript_AssignMethod(Context, clip);
	AScript_AssignMethod(Context, clip_preserve);
	AScript_AssignMethod(Context, clip_extents);
	AScript_AssignMethod(Context, in_clip);
	AScript_AssignMethod(Context, reset_clip);
	AScript_AssignMethod(Context, copy_clip_rectangle_list);
	AScript_AssignMethod(Context, fill);
	AScript_AssignMethod(Context, fill_preserve);
	AScript_AssignMethod(Context, fill_extents);
	AScript_AssignMethod(Context, in_fill);
	AScript_AssignMethod(Context, mask);
	AScript_AssignMethod(Context, mask_surface);
	AScript_AssignMethod(Context, paint);
	AScript_AssignMethod(Context, paint_with_alpha);
	AScript_AssignMethod(Context, stroke);
	AScript_AssignMethod(Context, stroke_preserve);
	AScript_AssignMethod(Context, stroke_extents);
	AScript_AssignMethod(Context, in_stroke);
	AScript_AssignMethod(Context, copy_page);
	AScript_AssignMethod(Context, show_page);
	// Paths - Creating paths and manipulating path data
	AScript_AssignMethod(Context, copy_path);
	AScript_AssignMethod(Context, copy_path_flat);
	AScript_AssignMethod(Context, has_current_point);
	AScript_AssignMethod(Context, get_current_point);
	AScript_AssignMethod(Context, new_path);
	AScript_AssignMethod(Context, new_sub_path);
	AScript_AssignMethod(Context, close_path);
	AScript_AssignMethod(Context, arc);
	AScript_AssignMethod(Context, arc_negative);
	AScript_AssignMethod(Context, curve_to);
	AScript_AssignMethod(Context, line_to);
	AScript_AssignMethod(Context, move_to);
	AScript_AssignMethod(Context, rectangle);
	AScript_AssignMethod(Context, text_path);
	AScript_AssignMethod(Context, rel_curve_to);
	AScript_AssignMethod(Context, rel_line_to);
	AScript_AssignMethod(Context, rel_move_to);
	AScript_AssignMethod(Context, path_extents);
	// Transformations - Manipulating the current transformation matrix
	AScript_AssignMethod(Context, translate);
	AScript_AssignMethod(Context, scale);
	AScript_AssignMethod(Context, rotate);
	AScript_AssignMethod(Context, transform);
	AScript_AssignMethod(Context, set_matrix);
	AScript_AssignMethod(Context, get_matrix);
	AScript_AssignMethod(Context, identity_matrix);
	AScript_AssignMethod(Context, user_to_device);
	AScript_AssignMethod(Context, user_to_device_distance);
	AScript_AssignMethod(Context, device_to_user);
	AScript_AssignMethod(Context, device_to_user_distance);
	// text - Rendering text and glyphs
	AScript_AssignMethod(Context, select_font_face);
	AScript_AssignMethod(Context, set_font_size);
	AScript_AssignMethod(Context, set_font_matrix);
	AScript_AssignMethod(Context, get_font_matrix);
	AScript_AssignMethod(Context, set_font_options);
	AScript_AssignMethod(Context, get_font_options);
	AScript_AssignMethod(Context, set_font_face);
	AScript_AssignMethod(Context, get_font_face);
	AScript_AssignMethod(Context, set_scaled_font);
	AScript_AssignMethod(Context, get_scaled_font);
	AScript_AssignMethod(Context, show_text);
	AScript_AssignMethod(Context, show_glyphs);
	AScript_AssignMethod(Context, show_text_glyphs);
	AScript_AssignMethod(Context, font_extents);
	AScript_AssignMethod(Context, text_extents);
	AScript_AssignMethod(Context, glyph_extents);
}

//-----------------------------------------------------------------------------
// AScript interfaces for Object_Image
// These method are available after importing opengl module.
//-----------------------------------------------------------------------------
// image#cairo() {block?}
AScript_DeclareMethod(Image, cairo)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementMethod(Image, cairo)
{
	Object_Image *pSelf = Object_Image::GetSelfObj(args);
	Object_Image *pObjImage = Object_Image::Reference(pSelf);
	cairo_surface_t *surface = CreateSurfaceFromImage(sig, pObjImage);
	if (sig.IsSignalled()) {
		Object_Image::Delete(pObjImage);
		return Value::Null;
	}
	Object_Surface *pObjSurface = new Object_Surface(surface, pObjImage);
	cairo_t *cr = ::cairo_create(surface);
	Value result(new Object_Context(cr, pObjSurface));
	return ReturnValue(env, sig, args, result);
}

//-----------------------------------------------------------------------------
// AScript module functions: cairo
//-----------------------------------------------------------------------------
// cairo.image_create(width:number, height:number, color?:color) {block?}
AScript_DeclareFunction(image_create)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "width", VTYPE_Number);
	DeclareArg(env, "height", VTYPE_Number);
	DeclareArg(env, "color", VTYPE_Color, OCCUR_ZeroOrOnce);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementFunction(image_create)
{
	Object_Image *pObjImage = new Object_Image(env, Object_Image::FORMAT_RGBA);
	size_t width = args.GetSizeT(0);
	size_t height = args.GetSizeT(1);
	if (!pObjImage->AllocBuffer(sig, width, height, 0xff)) return Value::Null;
	if (args.IsColor(2)) {
		pObjImage->Fill(args.GetColorObj(2));
	}
	cairo_surface_t *surface = ::cairo_image_surface_create_for_data(
				pObjImage->GetBuffer(), CAIRO_FORMAT_ARGB32,
				static_cast<int>(width), static_cast<int>(height),
				static_cast<int>(pObjImage->GetBytesPerLine()));
	Object_Surface *pObjSurface = new Object_Surface(surface, pObjImage);
	cairo_t *cr = ::cairo_create(surface);
	Value result(new Object_Context(cr, pObjSurface));
	return ReturnValue(env, sig, args, result);
}

// cairo.pdf_create(stream:stream, width_in_points:number, height_in_points:number) {block?}
AScript_DeclareFunction(pdf_create)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "stream", VTYPE_Stream);
	DeclareArg(env, "width_in_points", VTYPE_Number);
	DeclareArg(env, "height_in_points", VTYPE_Number);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementFunction(pdf_create)
{
	double width = args.GetDouble(1), height = args.GetDouble(2);
	Writer *pWriter = new Writer(sig,
					Stream::Reference(&args.GetStream(0)), width, height);
	cairo_surface_t *surface = ::cairo_pdf_surface_create_for_stream(
					Writer::write_func, pWriter, width, height);
	Object_Surface *pObjSurface = new Object_Surface(surface, pWriter);
	cairo_t *cr = ::cairo_create(surface);
	Value result(new Object_Context(cr, pObjSurface));
	return ReturnValue(env, sig, args, result);
}

// cairo.ps_create(stream:stream, width_in_points:number, height_in_points:number) {block?}
AScript_DeclareFunction(ps_create)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "stream", VTYPE_Stream);
	DeclareArg(env, "width_in_points", VTYPE_Number);
	DeclareArg(env, "height_in_points", VTYPE_Number);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementFunction(ps_create)
{
	double width = args.GetDouble(1), height = args.GetDouble(2);
	Writer *pWriter = new Writer(sig,
					Stream::Reference(&args.GetStream(0)), width, height);
	cairo_surface_t *surface = ::cairo_ps_surface_create_for_stream(
					Writer::write_func, pWriter, width, height);
	Object_Surface *pObjSurface = new Object_Surface(surface, pWriter);
	cairo_t *cr = ::cairo_create(surface);
	Value result(new Object_Context(cr, pObjSurface));
	return ReturnValue(env, sig, args, result);
}

// cairo.svg_create(stream:stream, width_in_points:number, height_in_points:number) {block?}
AScript_DeclareFunction(svg_create)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "stream", VTYPE_Stream);
	DeclareArg(env, "width_in_points", VTYPE_Number);
	DeclareArg(env, "height_in_points", VTYPE_Number);
	DeclareBlock(OCCUR_ZeroOrOnce);
}

AScript_ImplementFunction(svg_create)
{
	double width = args.GetDouble(1), height = args.GetDouble(2);
	Writer *pWriter = new Writer(sig,
					Stream::Reference(&args.GetStream(0)), width, height);
	cairo_surface_t *surface = ::cairo_svg_surface_create_for_stream(
					Writer::write_func, pWriter, width, height);
	Object_Surface *pObjSurface = new Object_Surface(surface, pWriter);
	cairo_t *cr = ::cairo_create(surface);
	Value result(new Object_Context(cr, pObjSurface));
	return ReturnValue(env, sig, args, result);
}

// cairo.pattern_create_rgb(red:number, green:number, blue:number)
AScript_DeclareFunction(pattern_create_rgb)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
}

AScript_ImplementFunction(pattern_create_rgb)
{
	cairo_pattern_t *pattern = ::cairo_pattern_create_rgb(
			args.GetDouble(0), args.GetDouble(1), args.GetDouble(2));
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// cairo.pattern_create_rgba(red:number, green:number, blue:number, alpha:number)
AScript_DeclareFunction(pattern_create_rgba)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "red", VTYPE_Number);
	DeclareArg(env, "green", VTYPE_Number);
	DeclareArg(env, "blue", VTYPE_Number);
	DeclareArg(env, "alpha", VTYPE_Number);
}

AScript_ImplementFunction(pattern_create_rgba)
{
	cairo_pattern_t *pattern = ::cairo_pattern_create_rgba(
			args.GetDouble(0), args.GetDouble(1), args.GetDouble(2), args.GetDouble(3));
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// cairo.pattern_create_color(color:color, alpha?:number)
AScript_DeclareFunction(pattern_create_color)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "color", VTYPE_Color);
	DeclareArg(env, "alpha", VTYPE_Number, OCCUR_ZeroOrOnce);
}

AScript_ImplementFunction(pattern_create_color)
{
	const Color &color = Object_Color::GetObject(args, 0)->GetColor();
	double red = static_cast<double>(color.GetRed()) / 255;
	double green = static_cast<double>(color.GetGreen()) / 255;
	double blue = static_cast<double>(color.GetBlue()) / 255;
	cairo_pattern_t *pattern;
	if (args.IsNumber(1)) {
		double alpha = args.GetDouble(1);
		pattern = ::cairo_pattern_create_rgba(red, green, blue, alpha);
	} else {
		pattern = ::cairo_pattern_create_rgb(red, green, blue);
	}
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// cairo.pattern_create_for_surface(surface:cairo.surface)
AScript_DeclareFunction(pattern_create_for_surface)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "surface", AScript_PrivVTYPE(Surface));
}

AScript_ImplementFunction(pattern_create_for_surface)
{
	cairo_surface_t *surface = Object_Surface::GetObject(args, 0)->GetSurface();
	cairo_pattern_t *pattern = ::cairo_pattern_create_for_surface(surface);
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// cairo.pattern_create_linear(x0:number, y0:number, x1:number, y1:number)
AScript_DeclareFunction(pattern_create_linear)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "x0", VTYPE_Number);
	DeclareArg(env, "y0", VTYPE_Number);
	DeclareArg(env, "x1", VTYPE_Number);
	DeclareArg(env, "y1", VTYPE_Number);
}

AScript_ImplementFunction(pattern_create_linear)
{
	cairo_pattern_t *pattern = ::cairo_pattern_create_linear(
			args.GetDouble(0), args.GetDouble(1), args.GetDouble(2), args.GetDouble(3));
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// cairo.pattern_create_radial(cx0:number, cy0:number, radius0:number, cx1:number, cy1:number, radius1:number)
AScript_DeclareFunction(pattern_create_radial)
{
	SetMode(RSLTMODE_Normal, FLAG_None);
	DeclareArg(env, "cx0", VTYPE_Number);
	DeclareArg(env, "cy0", VTYPE_Number);
	DeclareArg(env, "radius0", VTYPE_Number);
	DeclareArg(env, "cx1", VTYPE_Number);
	DeclareArg(env, "cy1", VTYPE_Number);
	DeclareArg(env, "radius1", VTYPE_Number);
}

AScript_ImplementFunction(pattern_create_radial)
{
	cairo_pattern_t *pattern = ::cairo_pattern_create_radial(
			args.GetDouble(0), args.GetDouble(1), args.GetDouble(2),
			args.GetDouble(3), args.GetDouble(4), args.GetDouble(5));
	if (IsError(sig, pattern)) {
		::cairo_pattern_destroy(pattern);
		return Value::Null;
	}
	return Value(new Object_Pattern(pattern));
}

// Module entry
AScript_ModuleEntry()
{
	// symbol realization
	AScript_RealizePrivSymbol(type);
	AScript_RealizePrivSymbol(surface);
	AScript_RealizePrivSymbol(stream);
	AScript_RealizePrivSymbol(butt);
	AScript_RealizePrivSymbol(round);
	AScript_RealizePrivSymbol(square);
	AScript_RealizePrivSymbol(miter);
	AScript_RealizePrivSymbol(bevel);
	AScript_RealizePrivSymbolEx(default_, "default");
	AScript_RealizePrivSymbol(none);
	AScript_RealizePrivSymbol(gray);
	AScript_RealizePrivSymbol(subpixel);
	AScript_RealizePrivSymbol(winding);
	AScript_RealizePrivSymbol(even_odd);
	AScript_RealizePrivSymbol(clear);
	AScript_RealizePrivSymbol(source);
	AScript_RealizePrivSymbol(over);
	AScript_RealizePrivSymbol(in);
	AScript_RealizePrivSymbol(out);
	AScript_RealizePrivSymbol(atop);
	AScript_RealizePrivSymbol(dest);
	AScript_RealizePrivSymbol(dest_over);
	AScript_RealizePrivSymbol(dest_in);
	AScript_RealizePrivSymbol(dest_out);
	AScript_RealizePrivSymbol(dest_atop);
	AScript_RealizePrivSymbol(xor);
	AScript_RealizePrivSymbol(add);
	AScript_RealizePrivSymbol(saturate);
	AScript_RealizePrivSymbol(multiply);
	AScript_RealizePrivSymbol(screen);
	AScript_RealizePrivSymbol(overlay);
	AScript_RealizePrivSymbol(darken);
	AScript_RealizePrivSymbol(lighten);
	AScript_RealizePrivSymbol(color_dodge);
	AScript_RealizePrivSymbol(color_burn);
	AScript_RealizePrivSymbol(hard_light);
	AScript_RealizePrivSymbol(soft_light);
	AScript_RealizePrivSymbol(difference);
	AScript_RealizePrivSymbol(exclusion);
	AScript_RealizePrivSymbol(hsl_hue);
	AScript_RealizePrivSymbol(hsl_saturation);
	AScript_RealizePrivSymbol(hsl_color);
	AScript_RealizePrivSymbol(hsl_luminosity);
	AScript_RealizePrivSymbol(part);
	AScript_RealizePrivSymbol(normal);
	AScript_RealizePrivSymbol(italic);
	AScript_RealizePrivSymbol(oblique);
	AScript_RealizePrivSymbol(bold);
	AScript_RealizePrivSymbol(ascent);
	AScript_RealizePrivSymbol(descent);
	AScript_RealizePrivSymbol(width);
	AScript_RealizePrivSymbol(height);
	AScript_RealizePrivSymbol(max_x_advance);
	AScript_RealizePrivSymbol(max_y_advance);
	AScript_RealizePrivSymbol(x_bearing);
	AScript_RealizePrivSymbol(y_bearing);
	AScript_RealizePrivSymbol(x_advance);
	AScript_RealizePrivSymbol(y_advance);
	AScript_RealizePrivSymbol(repeat);
	AScript_RealizePrivSymbol(reflect);
	AScript_RealizePrivSymbol(pad);
	AScript_RealizePrivSymbol(fast);
	AScript_RealizePrivSymbol(good);
	AScript_RealizePrivSymbol(best);
	AScript_RealizePrivSymbol(nearest);
	AScript_RealizePrivSymbol(bilinear);
	AScript_RealizePrivSymbol(gaussian);
	AScript_RealizePrivSymbol(image);
	AScript_RealizePrivSymbol(pdf);
	AScript_RealizePrivSymbol(ps);
	AScript_RealizePrivSymbol(xlib);
	AScript_RealizePrivSymbol(xcb);
	AScript_RealizePrivSymbol(glitz);
	AScript_RealizePrivSymbol(quartz);
	AScript_RealizePrivSymbol(win32);
	AScript_RealizePrivSymbol(beos);
	AScript_RealizePrivSymbol(directfb);
	AScript_RealizePrivSymbol(svg);
	AScript_RealizePrivSymbol(os2);
	AScript_RealizePrivSymbol(win32_printing);
	AScript_RealizePrivSymbol(quartz_image);
	AScript_RealizePrivSymbol(script);
	AScript_RealizePrivSymbol(qt);
	AScript_RealizePrivSymbol(recording);
	AScript_RealizePrivSymbol(vg);
	AScript_RealizePrivSymbol(gl);
	AScript_RealizePrivSymbol(drm);
	AScript_RealizePrivSymbol(tee);
	AScript_RealizePrivSymbol(xml);
	AScript_RealizePrivSymbol(skia);
	AScript_RealizePrivSymbol(subsurface);
	AScript_RealizePrivSymbol(color);
	AScript_RealizePrivSymbol(alpha);
	AScript_RealizePrivSymbol(color_alpha);
	// class realization
	AScript_RealizePrivClass(FontExtents, "font_extents", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(TextExtents, "text_extents", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Rectangle, "rectangle", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(RectangleInt, "rectangle_int", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(FontOptions, "font_options", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Device, "device", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Surface, "surface", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Pattern, "pattern", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Region, "region", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Path, "path", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Glyph, "glyph", env.LookupClass(VTYPE_Object));
	AScript_RealizePrivClass(Context, "context", env.LookupClass(VTYPE_Object));
	// method assignment to image type
	AScript_AssignMethodTo(VTYPE_Image, Image, cairo);
	// function assignment
	AScript_AssignFunction(image_create);
	AScript_AssignFunction(pdf_create);
	AScript_AssignFunction(ps_create);
	AScript_AssignFunction(svg_create);
	AScript_AssignFunction(pattern_create_rgb);
	AScript_AssignFunction(pattern_create_rgba);
	AScript_AssignFunction(pattern_create_color);
	AScript_AssignFunction(pattern_create_for_surface);
	AScript_AssignFunction(pattern_create_linear);
	AScript_AssignFunction(pattern_create_radial);
}

AScript_ModuleTerminate()
{
}

AScript_EndModule(cairo, cairo)

AScript_RegisterModule(cairo)
