/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	"memory_debug.h"
#include	"xlerror.h"
#include	"gbview.h"

extern int lock_pdb_lock_p;

typedef struct svg_d {
	char		cmd;
	GB_POINT	p;
} SVG_D;

char *
skip_space(char * p)
{
	for ( ; ; p ++ ) {
		switch ( *p ) {
		case 0:
			return p;
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			break;
		default:
			return p;
		}
	}
}

char *
skip_char(char * p)
{
	for ( ; ; p ++ ) {
		switch ( *p ) {
		case 0:
			return p;
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			return p;
		default:
			break;
		}
	}
}

char * 
skip_element(char * p)
{
	p = skip_char(p);
	p = skip_space(p);
	p = skip_char(p);
	p = skip_space(p);
	p = skip_char(p);
	p = skip_space(p);
	return p;
}

SVG_D *
get_svg_d(int * lenp,L_CHAR * d)
{
char * dd;
char * p;
SVG_D * ret;
int len;
	dd = ln_copy_str(std_cm,d);
	ret = d_alloc(1);
	len = 0;
	p = dd;
	p = skip_space(p);
	for ( ; *p ; ) {
		ret = d_re_alloc(ret,(len+1)*sizeof(*ret));
		sscanf(p,"%s %f %f",
			&ret[len].cmd,
			&ret[len].p.x,
			&ret[len].p.y);
		len ++;
		p = skip_element(p);
	}
	d_f_ree(dd);
	*lenp = len;
	return ret;
}

XL_SEXP *
svg_path(XLISP_ENV * e,XL_SEXP * s,
	XLISP_ENV * a,
	XL_SYM_FIELD * sf)
{
RESOURCE * r;
XLISP_ENV * ee;
L_CHAR * id;
unsigned int _id;
OBJ * obj;
XL_SEXP * ret;
int i;
L_CHAR * d;
SVG_D * svgd;
int len;
int start;
int num;


	r = get_resource_ptr(&ret,e,s->h.file,s->h.line);
	if ( r == 0 )
		return ret;
	if ( r->h.type != RT_DRAW_GB )
		er_panic("dgb_polygon2d(2)");
	id = get_sf_attribute(sf,l_string(std_cm,"id"));
	if ( id == 0 )
		goto id_is_required;
	sscanf(n_string(std_cm,id),"%i",&_id);
	d = get_sf_attribute(sf,l_string(std_cm,"d"));
	if ( d == 0 )
		goto d_is_required;
	svgd = get_svg_d(&len,d);

	lock_pdb_lock(r,0);
	obj = 0;
	start = -1;
	for ( i = 0 ; i < len ; i ++ ) {
		switch ( svgd[i].cmd ) {
		case 'M':
			if ( obj )
				insert_rect_tree(
					&r->draw_gb.obj_rect_tree,
					obj);
			obj = search_obj(r,_id);
			if ( obj == 0 ) {
				obj = new_object(r,OT_POLYGON2D,_id);
				INIT_RING(&obj->polygon2d.point_list);
			}
			_id ++;
			obj->polygon2d.type = PT_CLOSE;
			start = i;
			num = 0;
			insert_point(r,obj,&obj->polygon2d.point_list,
				num,svgd[i].p.x,svgd[i].p.y,0,0,0,0,
				obj->h.code);
			insert_rect(&obj->h.minrect,svgd[i].p);
			num ++;
			break;
		case 'L':
			if ( obj == 0 )
				break;
			if ( i < len - 1 ) {
				if ( svgd[i+1].cmd == 'M' &&
					svgd[i].p.x == svgd[start].p.x &&
					svgd[i].p.y == svgd[start].p.y ) {

					obj->polygon2d.type = PT_CLOSE;
				}
				else {
					obj->polygon2d.type = PT_OPEN;
					insert_point(
						r,
						obj,
						&obj->polygon2d.point_list,
						num,svgd[i].p.x,
						svgd[i].p.y,0,0,0,0,
						obj->h.code);
					insert_rect(&obj->h.minrect,svgd[i].p);
					num ++;
				}
			}
			else {
				insert_point(r,obj,&obj->polygon2d.point_list,
					num,svgd[i].p.x,svgd[i].p.y,
					0,0,0,0,
					obj->h.code);
				insert_rect(&obj->h.minrect,svgd[i].p);
				num ++;
			}
			break;
		default:
			er_panic("svg_path(1)");
		}
	}
	if ( obj )
		insert_rect_tree(
			&r->draw_gb.obj_rect_tree,
			obj);
	r->draw_gb.flags |= DGF_POLY;
	unlock_pdb_lock(r);

	return 0;
type_missmatch:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_SEMANTICS_TYPE_MISSMATCH,
		l_string(std_cm,"polygon2d"),
		List(n_get_string("type missmatch"),-1));
id_is_required:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_UNDEF_NAME,
		l_string(std_cm,"svg/path"),
		List(n_get_string("id is required"),-1));
d_is_required:
	return get_error(
		s->h.file,
		s->h.line,
		XLE_PROTO_UNDEF_NAME,
		l_string(std_cm,"svg/path"),
		List(n_get_string("d is required"),-1));
}
