/**********************************************************************
 
	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 <stdlib.h>
#include "xl.h"
#include "avt.h"
#include "long_char.h"
#include "svg2gb.h"
#include "svg2gb.h"
#include "xl2pdb_p.h"
#include "memory_debug.h"


PDB_POLYGON2D * pdb_p_list;
int pdb_p_list_nos;
GB_RECT minrect;
int point_nos;
L_CHAR * unitname;
char * data_encoding;
CODE_METHOD * data_encoding_cm;

SVG2GB_CONTEXT *g_svg2gb_context=0;

/**********************************************/
/*          utility                           */
/**********************************************/
static void insert_rect(GB_RECT * r,GB_POINT p)
{
	if ( r->tl.x > r->br.x ) {
		r->tl = r->br = p;
		return;
	}
	if ( r->tl.x > p.x )
		r->tl.x = p.x;
	if ( r->tl.y > p.y )
		r->tl.y = p.y;
	if ( r->br.x < p.x )
		r->br.x = p.x;
	if ( r->br.y < p.y )
		r->br.y = p.y;
	return;
}

static void svg_color2gb_color(GB_COLOR *gb, const SVG_COLOR *svg){
	gb->r = ((float)(svg->r))/255;
	gb->g = ((float)(svg->g))/255;
	gb->b = ((float)(svg->b))/255;
	gb->t = ((float)(svg->a))/255;
}

static L_CHAR *make_polygon_name(){
	char name[256];
	static int n=-1;
	sprintf(name, "noname:%ld", ++n);
	return l_string(std_cm, name);
}
/**********************************************/



void svg2gb_init()
{
	unitname = nl_copy_str(std_cm,"m");
	data_encoding = copy_str("EUC-JP");
	data_encoding_cm = search_cm(data_encoding);
	if ( data_encoding_cm == 0 )
		er_panic("svg2gb_init");
	svg2gb_make_context();
	minrect.tl.x = minrect.tl.y = 0;
	minrect.br.x = minrect.br.y = -1;
}

void svg2gb_clean()
{
	svg2gb_free_context();
}
	
void regist_polygon_to_pdb_avt(
	L_CHAR *name,
	int type,
	GB_COLOR *pclLineColor, 
	GB_COLOR *pclPaddingColor,
	GB_POINT *Points,
	SVG_POINT_LIST * svg_pl,
	int nPointCount)
{
PDB_POLYGON2D *new_p2d;
PDB_POLYGON2D *p2;
int point_no;
PDB_PD_POINT *new_pdb_point, * tail;

		
	if ( search_pdb_avt(name, l_string(std_cm, "")) ){
		fprintf(stderr, "duplicated polygon polyname:%s", n_string(std_cm, name));
		return;
	}
	
	new_p2d = (PDB_POLYGON2D *)d_alloc(sizeof(PDB_POLYGON2D), 351); 
	if(!new_p2d){
		fprintf(stderr, "err memory alloc : at regist_polygon_to_pdb_avt");
		return;
	}

	/* initialize new polygon */
	memset(new_p2d, 0, sizeof(PDB_POLYGON2D));
	new_p2d->minrect.br.x = -1;
	new_p2d->minrect.br.y = -1;
	new_p2d->subname = ll_copy_str(l_string(std_cm,"0"),123);
	
	/* set name */
	new_p2d->name = ll_copy_str(name,123);
/*
fflush(stdout);
ss_printf("> %ls\n",new_p2d->name);
*/
	/* set type */
	new_p2d->type = type;
	
	/* set padding color */
	memcpy(&(new_p2d->padding),pclPaddingColor,sizeof(GB_COLOR));
	
	/* set line color */
	memcpy(&(new_p2d->line),pclLineColor,sizeof(GB_COLOR));
	
	/* set points */
	tail = 0;
	for(point_no=0; point_no<nPointCount; ++point_no){
		/* create pdb point */
		new_pdb_point = (PDB_PD_POINT *)d_alloc(sizeof(PDB_PD_POINT), 352);
		memset(new_pdb_point,0,sizeof(PDB_PD_POINT));
		new_pdb_point->reso = -1;
		new_pdb_point->no = point_no|
			(svg_pl[point_no].flags&PP_LFLAGS);
		new_pdb_point->lod_max = 0;
		new_pdb_point->lod_min = 0;
		new_pdb_point->p.x = Points[point_no].x;
		new_pdb_point->p.y = Points[point_no].y;

		/* append new_point to polygon */
		new_pdb_point->next = 0;
		if ( tail == 0 )
			tail = new_p2d->point = new_pdb_point;
		else {
			tail->next = new_pdb_point;
			tail = new_pdb_point;
		}
		
		/* calc minimum rect */
		insert_rect(&(new_p2d->minrect), Points[point_no]);
		insert_rect(&minrect, Points[point_no]);
		
		/* increment grobal 'point_nos' */
		point_nos++;

	}

	/* append polygon to pdblist */
	lock_mem();
	new_p2d->seq = pdb_p_list_nos;
	new_p2d->next = pdb_p_list;
	pdb_p_list = new_p2d;
	pdb_p_list_nos ++;
	unlock_mem();

	/* insert polygon to avt_tree */
	insert_pdb_avt(new_p2d);
	
	p2 = search_sn_avt(new_p2d->name);
	if ( p2 == 0 ) {
		new_p2d->samename = 0;
		insert_sn_avt(new_p2d);
	}
	else {
		new_p2d->samename = p2->samename;
		p2->samename = new_p2d;
	}
}


void svg2gb_make_context()
{
	g_svg2gb_context = (SVG2GB_CONTEXT *)calloc(sizeof(SVG2GB_CONTEXT),1);
}

void svg2gb_free_context()
{
	SVG_LAYER *layer;
	if(!g_svg2gb_context)
		return ;
	layer = g_svg2gb_context->root_layer;
	if(layer)
		svg_free_layer(layer);
	if(g_svg2gb_context->point_buff){
		free(g_svg2gb_context->point_buff);
	}
	free(g_svg2gb_context);
	g_svg2gb_context = NULL;
}



SVG2GB_CONTEXT *svg2gb_get_context()
{
SVG2GB_CONTEXT * ret;
	if(!g_svg2gb_context){
		svg2gb_make_context();
	}
	ret = g_svg2gb_context;
	ret->digit = 0x7fffffff;
	return ret;
}

SVG_LAYER *svg2gb_get_current_layer(SVG2GB_CONTEXT *ctx)
{
	if(!ctx->current_layer)
		er_panic("svg2gb_get_current_layer");
	return ctx->current_layer;
}

void svg2gb_on_convert_polygon(SVG2GB_CONTEXT *ctx, int closeFlag)
{
	GB_COLOR fill;
	GB_COLOR line;
	int type;
	char *info=NULL;
	GB_POINT *points=NULL;
	int point_count;

	point_count = ctx->point_count;
	
	/* convert from svgtype to gbstype */
	svg_color2gb_color(&fill, &ctx->current_fill_color);
	svg_color2gb_color(&line, &ctx->current_stroke_color);
	type = (closeFlag==1) ? PDT_CLOSE : PDT_OPEN;

	if(point_count){
		int i;
		points = malloc (sizeof(GB_POINT) * point_count);
		for(i=0;i<point_count;++i){
			points[i].x = ctx->point_buff[i].p.x;
			points[i].y = ctx->point_buff[i].p.y;
		}
		if ( points[0].x == points[point_count-1].x   &&
				points[0].y == points[point_count-1].y ) {
					type = PDT_CLOSE;
					point_count --;
		}
		else
			type = PDT_OPEN;
	}
	else{
		type = PDT_OPEN;
	}


	
	gc_push(0,0,"regist_polygon_to_pdb_avt");
	/* regist polygon to pdb_avt */ 

	regist_polygon_to_pdb_avt(
		ctx->current_id ? ctx->current_id : make_polygon_name(),
		type,
		&line,
		&fill,
		points,
		ctx->point_buff,
		point_count);
	gc_pop(0,0);
	
	if(points)
		free(points);

}

