/**********************************************************************
 
	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 LC_FONT_ENGINE gbf_font_engine;


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(
	LC_STRING_PIC * p,
	int dir,
	LCF_SET * str,
	int	len)

{
GBF_DATA * fdat;
GBF_FONT * gf;
LC_FONT * lcf;
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;
LC_FONT_WORK * fw;

int size;

	lcf = str->font;
	size = str->size;
	fw = get_font_work(lcf,&gbf_font_engine);
	if ( fw == 0 ) {
		p->pic = 0;
		return;
	}
	gf = (GBF_FONT*)fw->work;
	fdat = 0;
	for ( i = 0 ; i < gf->len ; i ++ ) {
		fdat = gf->dat[i];
		if ( fdat->size == size )
			break;
	}
	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);
		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);
	y1 = y2 = 0;
	w = h = 0;
	for ( i = 0 ; i < len ; i++ ) {
		c = str[i].ch & (~get_lc_mask(str[i].ch));
		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 = size;
			ofs[i].type = 0;
			ofs[i].ofs = 0;
			w += size/10;
		}
		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);
	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);
			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;
}

