/**********************************************************************
 
	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 	"machine/v_x11.h"
#include	"long_char.h"
#include	"change_endian.h"

extern LC_FONT_ENGINE_TYPE X_font_engine_type;

void
get_strbuf(char ** bufp,XChar2b ** buf16p,int * lenp,LCF_SET * str,int len,
	L_CHAR mask)
{
int i;
char * buf;
XChar2b * buf16;
int dst;
	buf16 = d_alloc(sizeof(XChar2b)*len);
	buf = d_alloc(len);
	dst = 0;

		for ( i = 0 ; i < len ; i ++ ) {
			buf16[dst].byte2 = str[i].ch&0xff;
			buf16[dst].byte1 = (str[i].ch>>8)&0xff;
			if ( mask == LCZM_7b_TYPE )
				buf[dst++] = str[i].ch&0x7f;
			else	buf[dst++] = str[i].ch;
		}
	*bufp = buf;
	*buf16p = buf16;
	*lenp = dst;
}

void
_text_minrect(VRECT * r,int * width,char * str,XChar2b * str2,
	int len,XFontStruct * fs)
{
int dir,ascent,descent;
XCharStruct cs;

	if ( fs->min_byte1 == 0 && fs->max_byte1 == 0 ) {
		XTextExtents(fs,str,len,
			&dir,
			&ascent,
			&descent,
			&cs);
		*width = XTextWidth(fs,str,len);
	}
	else {
		XTextExtents16(fs,str2,len,
			&dir,
			&ascent,
			&descent,
			&cs);
		*width = XTextWidth16(fs,str2,len);
	}
	switch ( dir ) {
	case FontRightToLeft:
		r->br.x = -cs.lbearing;
		r->tl.x = -cs.rbearing;
		break;
	case FontLeftToRight:
		r->tl.x = cs.lbearing;
		r->br.x = cs.rbearing;
		break;
	}
	r->tl.y = -ascent;
	r->br.y = descent;
}


typedef struct _v_gsp {
  	LC_STRING_PIC * p;
	VDISPLAY * disp;
	LCF_SET * str;
	int	len;
	int	size;
	int 	dir;
	XFontStruct *	fs;
	L_CHAR mask;
} _V_GSP;

int
_v_get_string_pic(
	_V_GSP	* v)
{
LC_STRING_PIC * p;
VDISPLAY * disp;
LCF_SET * str;
int	size;
int 	dir;
char * buf;
XChar2b * buf16;
int len;
int x,y;
int w,h;
Pixmap pm;
GC gc;
int st_x,st_y;
XImage * xi;
int width;
int index,um,dm;
XFontStruct * fs;

	p = v->p;
	disp = v->disp;
	str = v->str;
	size = v->size;
	dir = v->dir;
	fs = v->fs;

	get_strbuf(&buf,&buf16,&len,str,v->len,v->mask);
	_text_minrect(&p->r,&width,buf,buf16,len,
		fs);
	p->width = width;
	w = p->r.br.x - p->r.tl.x;
	h = p->r.br.y - p->r.tl.y;
	if ( h == 0 ) {
		p->pic = 0;
		goto err;
	}
	if ( w == 0 ) {
		p->pic = d_alloc(h*h);
		for ( x = 0 ; x < h*h ; x ++ )
			p->pic[x] = 0;
		goto err;
	}
	pm = XCreatePixmap(disp->d,disp->for_string_pic->w,w,h,1);
	gc = XCreateGC(disp->d,pm,0,0);
	XSetForeground(
		disp->d,
		gc,
		1); /* color */
	XFillRectangle(disp->d,pm,gc,0,0,w,h); 
    	XSetFont(disp->d,
		gc,
		fs->fid);
	XSetForeground(
		disp->d,
		gc,
		0); /* color */
	st_x = - p->r.tl.x;
	st_y = - p->r.tl.y;
	if ( fs->min_byte1 == 0 && fs->max_byte1 == 0 ) {
		XDrawString(
			disp->d,
			pm,
			gc,
			st_x,
			st_y,
			buf,
			len);
	}
	else {
		XDrawString16(
			disp->d,
			pm,
			gc,
			st_x,
			st_y,
			buf16,
			len);
	}

	d_f_ree(buf);
	d_f_ree(buf16);

	xi = XGetImage(disp->d,pm,0,0,w,h,1,ZPixmap);
	if ( xi == 0 )
		er_panic("xi\n");
/*
printf("(%i %i)\n",w,h);
printf("f (%i %i) %i %i %i %i %i\n",
xi->byte_order,LSBFirst,
xi->bitmap_unit,
xi->bitmap_bit_order,
xi->bitmap_pad,
xi->depth,
xi->bytes_per_line);
*/

	p->pic = d_alloc(w*h);
	if ( (xi->byte_order == MSBFirst && endian_flag == 0) ||
		(xi->byte_order == LSBFirst && endian_flag == 1) ||
			xi->bitmap_unit == 8 ) {
		if ( xi->bitmap_bit_order == LSBFirst ) {
			for ( y = 0 ; y < h ; y ++ )
				for ( x = 0 ; x < w ; x ++ ) {
					if ( xi->data
					   [y*xi->bytes_per_line + x/8] &
							(1<<(x%8)) )
						p->pic[x + y*w] = 255;
					else	p->pic[x + y*w] = 0;
				}
		}
		else {
			for ( y = 0 ; y < h ; y ++ )
				for ( x = 0 ; x < w ; x ++ ) {
					if ( xi->data
					   [y*xi->bytes_per_line + x/8] &
							(1<<(7- (x%8))) )
						p->pic[x + y*w] = 255;
					else	p->pic[x + y*w] = 0;
				}
		}
	}
	else {
		switch ( xi->bitmap_unit ) {
		case 16:
			um = 0xfffffffe;
			dm = 0x00000001;
			break;
		case 32:
			um = 0xfffffffc;
			dm = 0x00000003;
			break;
		default:
			er_panic("v_get_string_pic(1)");
		}
		if ( xi->bitmap_bit_order == LSBFirst ) {
			for ( y = 0 ; y < h ; y ++ )
				for ( x = 0 ; x < w ; x ++ ) {
					index = y*xi->bytes_per_line + x/8;
					index = (um&index) +
						dm - (dm&index);
					if ( xi->data[index] & (1<<(x%8)) )
						p->pic[x + y*w] = 255;
					else	p->pic[x + y*w] = 0;
				}
		}
		else {
			for ( y = 0 ; y < h ; y ++ )
				for ( x = 0 ; x < w ; x ++ ) {
					index = y*xi->bytes_per_line + x/8;
					index = (um&index) +
						dm - (dm&index);
					if ( xi->data[index]&(1<<(7- (x%8))) )
						p->pic[x + y*w] = 255;
					else	p->pic[x + y*w] = 0;
				}
		}
	}
	p->dir = VSD_V_L2R;
	XDestroyImage(xi);
	XFreeGC(disp->d,gc);
	XFreePixmap(disp->d,pm);
err:
	return 0;
}


void
v_get_string_pic(
	LC_STRING_PIC * p,
	int 		dir,
	LCF_SET *	str,
	int len)
{
_V_GSP	v;
int i,vlen;
VFONT * vf;
LC_FONT * f;
int size;

	f = str->font;
	size = str->size;
	if ( f->fw_list[0].fe->type != &X_font_engine_type ) {
		memset(p,0,sizeof(*p));
		return;
	}
	v.disp = (VDISPLAY*)f->fw_list[0].fe->work;
	vf = (VFONT*)f->fw_list[0].work;
	vlen = vf->vlist_len;
	for ( i = 0 ; i < vlen ; i ++ )
		if ( vf->vlist[i].size == size )
			break;
	if ( i == vlen ) {
		memset(p,0,sizeof(*p));
		return;
	}
	v.fs = vf->vlist[i].fs;

	v.p = p;
	v.str = str;
	v.len = len;
	v.size = size;
	v.dir = dir;
	v.mask = get_lc_mask(str[0].ch);
	ms_do((int (*)(void*))_v_get_string_pic,&v,1,"v_get_string_pic");
}


