/**********************************************************************
 
	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 <stdio.h>
#include "long_char.h"
#include "gbf.h"
#include "v.h"
#include "memory_debug.h"

extern int fontsize;

unsigned int
gbf_get_len(GBF_OFS * ofs)
{
	int w = ofs->end_x - ofs->st_x;
	int h = ofs->end_y - ofs->st_y;
	if ( ofs->type == FT_BITMAP )
		return (w*h+7)>>3;
	else if ( ofs->type == FT_GRAY )
		return w*h;
	else 
		return 0;
}

void
gbf_get_string_pic_call(
	V_STRING_PIC * p,
	VDISPLAY * disp,
	L_CHAR * str,
	int len,
	VFONT * vf,
	int	size,
	int 	dir,
	L_CHAR mask)
{
GBF_DATA * fdat;
GBF_OFS * ofs;
FILE * file;
L_CHAR c;
int w, h, ws, hs;
int x0, x_st, y1, y2;
int i, x, y, bit, pmlen;
unsigned char * pixmap, *src, *dst;

	fdat = gbf_search(vf->id);
	if ( fdat == 0 ) {
		p->pic = 0;
		return;
	}

	file = fopen(fdat->path, "r");
	if ( file == 0 ) {
		fprintf(stderr,"load font : %s",fdat->path);
		perror("");
		p->pic = 0;
		return;
	}
	
	if ( fdat->ofs == 0 ) {
		fseek(file, sizeof(GBF_HEADER), SEEK_SET);
		fdat->ofs = d_alloc(sizeof(GBF_OFS) * fdat->nos, 1934);
		if ( fread(fdat->ofs, sizeof(GBF_OFS), fdat->nos, file) != fdat->nos ) {
			fprintf(stderr,"load font : %s",fdat->path);
			perror("");
			p->pic = 0;
			fclose(file);
			return;
		}
	}
	
	ofs = d_alloc(sizeof(GBF_OFS) * len, 239);
	y1 = y2 = 0;
	w = h = 0;
	for ( i = 0 ; i < len ; i++ ) {
		c = str[i] & (~mask);
		if ( c < fdat->st_no || c >= fdat->end_no ) {
			ofs[i].st_x = 0;
			ofs[i].st_y = 0;
			ofs[i].end_x = 0;
			ofs[i].end_y = 0;
			ofs[i].w = fontsize;
			ofs[i].type = 0;
			ofs[i].ofs = 0;
			w += fontsize;
		}
		else {
			ofs[i] = fdat->ofs[c-fdat->st_no];
			w += ofs[i].w;
			if ( y1 > ofs[i].st_y )
				y1 = ofs[i].st_y;
			if ( y2 < ofs[i].end_y )
				y2 = ofs[i].end_y;
		}
	}
	x0 = 0;
	if ( ofs[0].st_x < 0 ) {
		w -= ofs[0].st_x;
		x0 = - ofs[0].st_x;
	}
	if ( ofs[len-1].end_x > ofs[len-1].w )
		w += ofs[len-1].end_x - ofs[len-1].w;
	h = y2-y1;
	if ( h == 0 ) {
		y1--;
		h++;
	}
	
	p->r.tl.x = 0;
	p->r.br.x = w;
	p->r.tl.y = y1;
	p->r.br.y = y2;
	p->width = w;

	if ( w )
		p->pic = d_alloc(w*h, 230);
	else
		p->pic = 0;
	for ( i = 0 ; i < w*h ; i++ )
		p->pic[i] = 255;
	
	for ( i = 0 ; i < len ; i++ ) {
		if ( ofs[i].ofs != 0 ) {
			pmlen = gbf_get_len(&ofs[i]);
			src = pixmap = d_alloc(pmlen,235);
			fseek(file, ofs[i].ofs, SEEK_SET);
			fread(pixmap, pmlen, 1, file);
		}
		else
			pixmap = 0;
		
		ws = ofs[i].end_x - ofs[i].st_x;
		hs = ofs[i].end_y - ofs[i].st_y;
		x_st = ofs[i].st_x;
		switch( ofs[i].type ) {
		case FT_GRAY :
			for ( y = 0 ; y < hs ; y++ ) {
				dst = &p->pic[x0+x_st + y*w];
				for ( x = 0 ; x < ws ; x++ ) {
					*dst = (((int)*dst+1)*((int)*src+1)>>8)-1;
					src++;
					dst++;
				}
			}
			break;
		case FT_BITMAP :
			bit = 7;
			for ( y = 0 ; y < hs ; y++ ) {
				dst = &p->pic[x0+x_st + y*w];
				for ( x = 0 ; x < ws ; x++ ) {
					if ( ( *src & (1 << bit) ) == 0 )
						*dst = 0;
					if ( --bit < 0 ) {
						src++;
						bit = 7;
					}
					dst++;
				}
			}
			break;
		case FT_SPACE :
			break;
		}
		x0 += ofs[i].w;
		if ( pixmap )
			d_f_ree(pixmap);
	}
	fclose(file);
	return;
}


void
gbf_compose_pic(V_STRING_PIC * p,V_STRING_PIC * pp)
{
V_STRING_PIC ppp;
int w,h,ww,hh;
int x,y,i;
int y_ofs,x_ofs;
	ppp.width = p->width + pp->width;
	ppp.dir = p->dir;
	ppp.r.tl.x = p->r.tl.x;
	if ( p->r.tl.y < pp->r.tl.y )
		ppp.r.tl.y = p->r.tl.y;
	else	ppp.r.tl.y = pp->r.tl.y;
	ppp.r.br.x = p->width + pp->r.br.x;
	if ( p->r.br.y < pp->r.br.y )
		ppp.r.br.y = pp->r.br.y;
	else	ppp.r.br.y = p->r.br.y;
	w = ppp.r.br.x - ppp.r.tl.x;
	h = ppp.r.br.y - ppp.r.tl.y;
	ppp.pic = d_alloc(w*h,230);
	for ( i = 0 ; i < w*h ; i ++ )
		ppp.pic[i] = 255;
	ww = p->r.br.x - p->r.tl.x;
	hh = p->r.br.y - p->r.tl.y;
	y_ofs = p->r.tl.y - ppp.r.tl.y;
	i = 0;
	for ( y = y_ofs ; y < hh+y_ofs ; y ++ )
		for ( x = 0 ; x < ww ; x ++ )
			ppp.pic[x + y*w] = p->pic[i++];
	x_ofs = -ppp.r.tl.x+p->width+pp->r.tl.x;
	y_ofs = pp->r.tl.y - ppp.r.tl.y;
	ww = pp->r.br.x - pp->r.tl.x;
	hh = pp->r.br.y - pp->r.tl.y;
	i = 0;
	for ( y = y_ofs ; y < hh+y_ofs ; y ++ )
		for ( x = x_ofs ; x < ww+x_ofs ; x ++ ){
			if ( pp->pic[i] != 255 )
				ppp.pic[x + y*w] = pp->pic[i];
			i ++;
		}
	d_f_ree(p->pic);
	d_f_ree(pp->pic);
	*p = ppp;
}


void
gbf_get_string_pic(
	V_STRING_PIC * p,
	VDISPLAY * disp,
	L_CHAR * str,
	int	size,
	int 	dir)
{
int len;
int i,j;
V_STRING_PIC pp;
L_CHAR unknown;
int f;
WRITABLE_CODE_TABLE * t;
	len = l_strlen(str);
	unknown = '?';
	f = 0;
	for ( i = 0 ; i < len ; ) {
		t = get_wct(disp->font_work,str[i]);
		if ( t ) {
			for ( j = i ; j < len &&
				(str[j]&t->mask) == t->lcz ; j ++ );
			gbf_get_string_pic_call(
				&pp,
				disp,
				&str[i],
				j-i,
				t->work,
				size,
				dir,
				t->mask);
			i = j;
			if ( pp.pic == 0 ) {
				gbf_get_string_pic_call(
					&pp,
					disp,
					&unknown,
					1,
					&disp->iso8859_1,
					size,
					dir,
					LCZM_1B_TYPE);
			}
		}
		else {
			gbf_get_string_pic_call(
				&pp,
				disp,
				&unknown,
				1,
				&disp->iso8859_1,
				size,
				dir,
				LCZM_1B_TYPE);
			i ++;
		}
		if ( pp.pic == 0 ) {
			fprintf(stderr,"gbf_get_string_pic : cannot draw font\n");
			exit(0);
		}
		if ( f == 0 ) {
			*p = pp;
			f = 1;
		}
		else {
			gbf_compose_pic(p,&pp);
		}
	}
}
