#include <stdlib.h>
#include <stdio.h>
#include <gd.h>
#include <string.h>
#include <stdint.h>
#include <wchar.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <locale.h>
//#include <utf8.h>
#include <iconv.h>
//#include <glib-2.0/glib.h>
/* to determine codepoint categories */
#include <unicode/uchar.h>
/* to output UTF-32 codepoints in proper encoding for terminal */
#include <unicode/ustdio.h>

#include <sys/types.h>
#include <limits.h>

#define SEMICOLON 59

/*
#ifndef uint48_t
typedef struct bitfield48 {
  uint64_t value : 48;
} uint48_t;
#endif
*/



#define __INT48_TYPE__

#ifdef __INT48_TYPE__
typedef signed __INT48_TYPE__ int48_t;
typedef unsigned __INT48_TYPE__ uint48_t;
typedef int48_t int_least48_t;
typedef uint48_t uint_least48_t;
typedef int48_t int_fast48_t;
typedef uint48_t uint_fast48_t;
# define __int_least32_t int48_t
# define __uint_least32_t uint48_t
# define __int_least16_t int48_t
# define __uint_least16_t uint48_t
# define __int_least8_t int48_t
# define __uint_least8_t uint48_t
#endif /* __INT48_TYPE__ */

#ifdef __INT48_TYPE__
# ifdef __INT48_C_SUFFIX__
#  define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__)
#  define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__)
#  define __int32_c_suffix __INT48_C_SUFFIX__
#  define __int16_c_suffix __INT48_C_SUFFIX__
#  define __int8_c_suffix  __INT48_C_SUFFIX__
# else
#  define INT48_C(v) v
#  define UINT48_C(v) v ## U
#  undef __int32_c_suffix
#  undef __int16_c_suffix
#  undef  __int8_c_suffix
# endif /* __INT48_C_SUFFIX__ */
#endif /* __INT48_TYPE__ */

#ifdef __INT48_TYPE__
# define INT48_MAX           INT48_C(140737488355327)
# define INT48_MIN         (-INT48_C(140737488355327)-1)
# define UINT48_MAX         UINT48_C(281474976710655)
# define INT_LEAST48_MIN     INT48_MIN
# define INT_LEAST48_MAX     INT48_MAX
# define UINT_LEAST48_MAX   UINT48_MAX
# define INT_FAST48_MIN      INT48_MIN
# define INT_FAST48_MAX      INT48_MAX
# define UINT_FAST48_MAX    UINT48_MAX
# define __INT_LEAST32_MIN   INT48_MIN
# define __INT_LEAST32_MAX   INT48_MAX
# define __UINT_LEAST32_MAX UINT48_MAX
# define __INT_LEAST16_MIN   INT48_MIN
# define __INT_LEAST16_MAX   INT48_MAX
# define __UINT_LEAST16_MAX UINT48_MAX
# define __INT_LEAST8_MIN    INT48_MIN
# define __INT_LEAST8_MAX    INT48_MAX
# define __UINT_LEAST8_MAX  UINT48_MAX
#endif /* __INT48_TYPE__ */

struct BoundBox {
	int x;
	int y;
	int w;
	int h;
};

void Convert_Brect(int *brect, struct BoundBox *bb){
	//int i=0;
	int h_x=INT_MIN;
	int l_x=INT_MAX;
	int h_y=INT_MIN;
	int l_y=INT_MAX;
	//find highest x
	//for(i=0; i<
	//h_x = brect[0]>brect[2] ? brect[0] : brect[2];
	//i = brect[4]>brect[6] ? brect[4] : brect[6];
	//if(i>h_x)
	//	h_x = i;

	if(brect[0]>h_x)
		h_x = brect[0];
	if(brect[2]>h_x)
		h_x = brect[2];
	if(brect[4]>h_x)
		h_x = brect[4];
	if(brect[6]>h_x)
		h_x = brect[6];

	if(brect[0]<l_x)
		l_x = brect[0];
	if(brect[2]<l_x)
		l_x = brect[2];
	if(brect[4]<l_x)
		l_x = brect[4];
	if(brect[6]<l_x)
		l_x = brect[6];

	if(brect[1]>h_y)
		h_y = brect[1];
	if(brect[3]>h_y)
		h_y = brect[3];
	if(brect[5]>h_y)
		h_y = brect[5];
	if(brect[7]>h_y)
		h_y = brect[7];

	if(brect[1]<l_y)
		l_y = brect[1];
	if(brect[3]<l_y)
		l_y = brect[3];
	if(brect[5]<l_y)
		l_y = brect[5];
	if(brect[7]<l_y)
		l_y = brect[7];

//y is off by 4 x might be off too
//	bb->x = brect[6];
//	bb->y = brect[7]-4;
//width/height can't be zero
	bb->w = (h_x - l_x);
	bb->h = (h_y - l_y);

        bb->x = brect[6];
        bb->y = brect[7]-bb->h;


//bb->x = brect[6];
//bb->y = brect[1]+bb->h;

//if(bb->w < 0)
//printf("negative width\n");
//if(bb->h < 0)
//printf("negative height\n");

	return;
}


/*
#define UTF8_BUFERR_SIZE  256

static wchar_t *utf8towchar(char* utf8) {
  wchar_t *text=malloc (UTF8_BUFERR_SIZE * sizeof(wchar_t));
  char *output = (char *) text;

  gchar *input = g_strdup(utf8);                // get length of utf-8 string
  gchar *def_copy = input;

  iconv_t foo = iconv_open("WCHAR_T", "UTF-8"); // Convert UTF-8 to WCHAR_T
  size_t ibl = strlen(input);                   // Input length
  size_t obl = UTF8_BUFERR_SIZE;                // Max output length
  iconv(foo, &input, &ibl, &output, &obl);
  iconv_close(foo);

  g_free(def_copy);

  return text;
}
*/


/*
int u8_wc_toutf8(char *dest, u_int32_t ch)
{
    if (ch < 0x80) {
        dest[0] = (char)ch;
        return 1;
    }
    if (ch < 0x800) {
        dest[0] = (ch>>6) | 0xC0;
        dest[1] = (ch & 0x3F) | 0x80;
        return 2;
    }
    if (ch < 0x10000) {
        dest[0] = (ch>>12) | 0xE0;
        dest[1] = ((ch>>6) & 0x3F) | 0x80;
        dest[2] = (ch & 0x3F) | 0x80;
        return 3;
    }
    if (ch < 0x110000) {
        dest[0] = (ch>>18) | 0xF0;
        dest[1] = ((ch>>12) & 0x3F) | 0x80;
        dest[2] = ((ch>>6) & 0x3F) | 0x80;
        dest[3] = (ch & 0x3F) | 0x80;
        return 4;
    }
    return 0;
}
*/



/*
wchar_t utf8_to_wchar(char *in){
	wchar_t out;
	uint32_t codepoint;
	uint32_t x = 0;
	while(in[x] != '\0'){
		if(in[x] <= 0x7F)
			codepoint = in[x];
		else if(in[x] <= 0xBF)
			codepoint = (codepoint << 6) | (in[x] & 0x3F);
		else if(in[x] <= 0xDF)
			codepoint = 
		else if(in[x] <= 0xEF)

		else if(in[x] <= 0x)

		else
			
		x++;
	}

}

if (byte < 0xC0) {
*chPtr = (Tcl_UniChar) byte;
} else if (byte < 0xE0) {
if ((str[1] & 0xC0) == 0x80) {
*chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F));

*chPtr = (Tcl_UniChar) byte;

*chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
*chPtr = (Tcl_UniChar) (  ((byte & 0x07) << 18) | ((str[1] & 0x3F) << 12) | ((str[2] & 0x3F) << 6) | (str[3] & 0x3F));

*/

int utf8_encode(char *out, uint48_t utf)
{
  if (utf <= 0x7F) {
    // Plain ASCII
    out[0] = (char) utf;
    out[1] = '\0';
    return 1;
  } else if (utf <= 0x07FF) {
    // 2-byte unicode
    out[0] = (char) (((utf >> 6) & 0x1F) | 0xC0);
    out[1] = (char) (((utf >> 0) & 0x3F) | 0x80);
    out[2] = '\0';
    return 2;
  } else if (utf <= 0xFFFF) {
    // 3-byte unicode
    out[0] = (char) (((utf >> 12) & 0x0F) | 0xE0);
    out[1] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[2] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[3] = '\0';
    return 3;
  } else if (utf <= 0x001FFFFF) {
//  } else if (utf <= 0x10FFFF) {
    // 4-byte unicode
    out[0] = (char) (((utf >> 18) & 0x07) | 0xF0);
    out[1] = (char) (((utf >> 12) & 0x3F) | 0x80);
    out[2] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[4] = '\0';
    return 4;
  } else if (utf <= 0x03FFFFFF) {
    // 5-byte unicode
    out[0] = (char) (((utf >> 24) & 0x03) | 0xF8);
    out[1] = (char) (((utf >> 18) & 0x3F) | 0x80);
    out[2] = (char) (((utf >> 12) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[4] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[5] = 0;
    return 5;
  } else if (utf <= 0x7FFFFFFF) {
    // 6-byte unicode
    out[0] = (char) (((utf >> 30) & 0x01) | 0xFC);
    out[1] = (char) (((utf >> 24) & 0x3F) | 0x80);
    out[2] = (char) (((utf >> 18) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  12) & 0x3F) | 0x80);
    out[4] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[5] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[6] = 0;
    return 6;
  }  else {
    // error - use replacement character
    out[0] = (char) 0xEF;  
    out[1] = (char) 0xBF;
    out[2] = (char) 0xBD;
    out[3] = 0;
    return 0;
  }


}






int main(int argc, char **argv){
	FILE *image_out;
	FILE *font_fnt_out;
	FILE *input_hex;
FILE *testout;

	gdImagePtr im;
	int black;
	int white;

	int brect[8];
	int x, y;
	char *err;
	int no_fontconfig;
	int row_cur = 0;
	int row_spacing_pixels = 20;
	int col_spacing_pixels = 20;
	int bounding_box_width_max = 0;
	int bounding_box_height_max = 0;
	int bounding_box_width_cur = 0;
	int bounding_box_height_cur = 0;
	int row_width_max = 0;
	int row_width_cur = 0;
	int columns = 50;
	int column_cur = 0;
	//int row_width_cur = 0;
	int row_width_widest = 0;

	wchar_t space = ' ';
	wchar_t tab = '\t';
	wchar_t newline = '\n';
	wchar_t null = '\0';

	int image_width = 0;
	int image_height = 0;
	wint_t c;
	uint64_t total_chars_to_print = 0;
	uint32_t total_rows = 0;
	uint32_t total_cols = 0;
	char linestring[1024];
char *s;
//wchar_t test[5];

char test[8];
uint48_t hexchar;
iconv_t cd;
char *pIn;
char *pOut;
size_t inbytesleft = 4;
size_t outbytesleft = 4;
char *inbuf;
char *outbuf;
int num1;


int tallest_char = 0;
int widest_char = 0;


//wchar_t bla[2]; //= {L"\u1d400", '\0'};


char *locale = setlocale(LC_ALL, "en_US.UTF-8");
//wint_t bla;
wchar_t *bla;
//wchar_t BLA = 0x0001FBB2;
//bla = &BLA;
// = L"\U0023";

//wchar_t *bla ='A';

//Convert_Brect(int *brect, struct BoundBox *bb)
struct BoundBox bb;


//if (fwide(stdout, 0) == 0) /* 0 queries the current mode */
//{ /* stdout has no specific char mode yet, attempt to set to wide */
//if (fwide(stdout, 1) <= 0) /* a value greater than zero switches to wide character mode */
//printf("could not switch to wide char mode!n");
//else
//wprintf(L"switched to wide char mode.n");
//}
//bla[0] = L"\U1FBB2";
//bla[0] = L"\U0023";
//bla[1] = '\0';

//char *locale = setlocale(LC_ALL, "en_US.UTF-8");


//strtoul("FA", NULL, 16);

	double pixel_pt_size = 4.5;
	char *input_ttf = "/mnt/sdb1/pub/test/gdfont/iosevka-fixed-slab-extended.ttf";
	int aa_disable;

//        int input_hex;
//        struct stat buffer;
        int status;
//uint32_t file_bytes;
//wchar_t *mem_file;


/*
input_hex = open("hex.txt", O_RDONLY);
        if(input_hex == -1){
                fprintf( stderr, "Error opening input.txt\n");
                exit( 1 );
        }

	status = fstat(input_hex, &buffer);
        file_bytes=buffer.st_size;
        if(file_bytes < 1){
                printf("Error: file is too small!\n");
                exit(1);
        }
printf("input: input.txt\n");
*/

	gdFTStringExtra Strex = {0,0,0,0,0,NULL,NULL};
	gdFTStringExtraPtr strex = &Strex;


strex->flags |= gdFTEX_LINESPACE;
strex->flags |= gdFTEX_CHARMAP;
strex->flags |= gdFTEX_RESOLUTION;
strex->flags |= gdFTEX_DISABLE_KERNING;
//strex->flags |= gdFTEX_XSHOW;
strex->flags |= gdFTEX_RETURNFONTPATHNAME;
//strex->flags |= gdFTEX_FONTPATHNAME;
//strex->flags |= gdFTEX_FONTCONFIG;
//strex->flags |= gdFTEX_FONTPATHNAME;


strex->linespacing = 1.00;
strex->charmap = gdFTEX_Unicode;
//FT_ENCODING_UNICODE
//strex->charmap = gdFTEX_Big5;
//strex->charmap = gdFTEX_Shift_JIS;
//strex->charmap = gdFTEX_Adobe_Custom;

//strex->hdpi=1350;
//strex->vdpi=1950;

strex->hdpi=187;
strex->vdpi=187;




        if( ( input_hex = fopen("hex.txt", "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "hex.txt" );
               	return 1;
        }

        if( ( font_fnt_out = fopen("font.fnt", "w" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "font.fnt" );
                return 1;
        }


	memset ((void*) linestring, '\0', sizeof (linestring));


fprintf(font_fnt_out, "%c image file\n", SEMICOLON);
fprintf(font_fnt_out, "image=font.png\n");
fprintf(font_fnt_out, "%c \"character\"=x,y,width,height\n", SEMICOLON);


	x = row_spacing_pixels+row_spacing_pixels;
	y = col_spacing_pixels+col_spacing_pixels;

	while( fgets(linestring, sizeof(linestring), input_hex) != NULL){
		//printf("%s", linestring);
		//replace newline with null
		for(num1=0; num1<sizeof(linestring); num1++){
			if(linestring[num1] == '\n'){
				linestring[num1] = '\0';
				break;
			}
		}
		//populate brect to get font box width/height

memset ((void*)test, '\0', sizeof(test));
hexchar = (uint48_t)strtoul((const char *)linestring, NULL, 16);

if(hexchar > 0xFFFF)
	break;

(void)utf8_encode(test, hexchar);

//1d400

//pInt = &hexchar;
/*
memset ((void*)test, '\0', sizeof(test));
inbytesleft = 4;
outbytesleft = 4;
inbuf=(char *)&hexchar;
outbuf=(char *)test;
//cd = iconv_open ("UTF-8", "UCS−4−INTERNAL");
cd = iconv_open ("UTF-8","UCS−4−INTERNAL");
iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
iconv_close(cd);
//test[4] = '\0';
*/

//size_t iconv (iconv_t cd,
//const char* * inbuf, size_t * inbytesleft,
//char* * outbuf, size_t * outbytesleft);


//(void)u8_toutf8(test, 8, &hexchar, 1);

//test[1] = '\0';
//test[0] = 'Ā';

//test[0] = linestring[0];
//test[1] = linestring[1];
//test[2] = linestring[2];
//test[3] = linestring[3];
//test[4] = linestring[4];
//test[5] = '\0';

//utf8_encode(test, hexchar)





brect[0]=0;
brect[1]=0;
brect[2]=0;
brect[3]=0;
brect[4]=0;
brect[5]=0;
brect[6]=0;
brect[7]=0;
//s = (char *)test;
err = gdImageStringFTEx(NULL,brect,0,input_ttf,pixel_pt_size,0.0,x,y,(const char *)test,strex);
//		err = gdImageStringFTEx(NULL,&brect[0],0,input_ttf,pixel_pt_size,0.0,x,y,(const char *)test,strex);
		if (err) {fprintf(stderr,err); return 1;}

		bounding_box_width_cur = brect[4]-brect[0];
		bounding_box_height_cur = brect[3]-brect[7];


//struct BoundBox bb;
//memset ((void*)bb, '\0', sizeof(struct BoundBox));


bb.x=0;
bb.y=0;
bb.w=0;
bb.h=0;

Convert_Brect(brect, &bb);

/*
if(bb.x < 0)
printf("negative x\n");
if(bb.y < 0)
printf("negative y\n");
if(bb.w < 0)
printf("negative w\n");
if(bb.h < 0)
printf("negative h\n");

printf("brect: %d %d %d %d %d %d %d %d\n", brect[0],brect[1],brect[2],brect[3],brect[4],brect[5],brect[6],brect[7]);





fprintf(font_fnt_out, "\"%s\"=%d,%d,%d,%d\n", test, bb.x, bb.y, bb.w, bb.h);
*/
//bounding_box_width_cur = bb.w;
//bounding_box_height_cur = bb.h;


		//save font location/size to font.fnt
		//fprintf(font_fnt_out, "\"0x%s\"=%d,%d,%d,%d\n", linestring, x, y-bounding_box_height_cur, bounding_box_width_cur, bounding_box_height_cur );
//s=&hexchar;
//bla=hexchar;
//s=&bla;
//bla=(wchar_t)hexchar;
//bla=utf8towchar(test);

//fprintf(font_fnt_out, "\"%s\"", test);
//fwprintf(font_fnt_out, L"\"%lc\"", test);
//fwprintf(font_fnt_out, "\"%c\"", bla);
//fprintf(font_fnt_out, L"\"%ls\"", test);


//fwprintf(font_fnt_out, L"%c", bla);


fprintf(font_fnt_out, "\"%s\"=%d,%d,%d,%d\n", test, brect[6], brect[7], bounding_box_width_cur, bounding_box_height_cur );

//fprintf(font_fnt_out, "\"%s\"=%d,%d,%d,%d,%d,%d\n", test, x, y-bounding_box_height_cur, bounding_box_width_cur, bounding_box_height_cur,x,y );
//printf("brect: %d %d %d %d %d %d %d %d\n", brect[0],brect[1],brect[2],brect[3],brect[4],brect[5],brect[6],brect[7]);
//printf("bb: %d %d %d %d %d %d\n", bb.x, bb.y, bb.w, bb.h,x,y);
		//add up width for current row
		row_width_cur += col_spacing_pixels + bounding_box_width_cur;
		//find tallest box in current row to know for next row's offset
		if(bounding_box_height_cur > bounding_box_height_max)
			bounding_box_height_max = bounding_box_height_cur;
//free(bla);

if(tallest_char < bounding_box_height_cur)
	tallest_char = bounding_box_height_cur;

if(widest_char < bounding_box_width_cur)
	widest_char = bounding_box_width_cur;

		x += col_spacing_pixels + bounding_box_width_cur;
		//continue with current row
		if(column_cur < columns-1){
			column_cur++;
		}else{ //max columns reached
			y += row_spacing_pixels + bounding_box_height_max;
			//add border space
			row_width_cur += col_spacing_pixels;
			//this row is widest yet, adjust image width
			if(row_width_cur > image_width)
				image_width = row_width_cur;
			row_width_cur = 0;
			//add to height for image
			image_height += row_spacing_pixels + bounding_box_height_max;
			bounding_box_height_max = 0;
			//reset to first col for new row
			column_cur = 0;
			row_cur++;
			x = row_spacing_pixels;
		}
	}

printf("tallest char: %d\n", tallest_char);
printf("widest char: %d\n", widest_char);

//fclose(font_fnt_out);
fclose(input_hex);
//free(bla);
//x += col_spacing_pixels;
//y += row_spacing_pixels;

strex->flags |= gdFTEX_LINESPACE;
strex->flags |= gdFTEX_CHARMAP;
strex->flags |= gdFTEX_RESOLUTION;
strex->flags |= gdFTEX_DISABLE_KERNING;
//strex->flags |= gdFTEX_XSHOW;
strex->flags |= gdFTEX_RETURNFONTPATHNAME;
//strex->flags |= gdFTEX_FONTPATHNAME;
//strex->flags |= gdFTEX_FONTCONFIG;
//strex->flags |= gdFTEX_FONTPATHNAME;


strex->linespacing = 1.00;
strex->charmap = gdFTEX_Unicode;
//strex->charmap = gdFTEX_Big5;
//strex->charmap = gdFTEX_Adobe_Custom;

//strex->hdpi=1350;
//strex->vdpi=1950;

strex->hdpi=187;
strex->vdpi=187;

        if( ( input_hex = fopen("hex.txt", "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "hex.txt" );
                return 1;
        }

	if( ( testout = fopen("testout.txt", "w" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "testout.txt" );
                return 1;
        }


	image_height += row_spacing_pixels+row_spacing_pixels+row_spacing_pixels;
	image_width  += col_spacing_pixels;

	//create image
	im = gdImageCreateTrueColor(image_width, image_height);
	//aa_disable = gdImageColorAllocate(im, -1, -1, -1);
	white = gdImageColorResolve(im, 0, 0, 0);
	black = gdImageColorResolve(im, 0, 255, 0);

	x = row_spacing_pixels+row_spacing_pixels;
	y = col_spacing_pixels+col_spacing_pixels;
	row_width_cur = 0;
	row_cur = 0;
	bounding_box_height_max = 0;
	column_cur = 0;

        while( fgets(linestring, sizeof(linestring), input_hex) != NULL){
                //printf("%s", linestring);
                //replace newline with null
                for(num1=0; num1<sizeof(linestring); num1++){
                        if(linestring[num1] == '\n'){
                                linestring[num1] = '\0';
                                break;
                        }
                }
               	//
//test[0] = strtoul((const char *)linestring, NULL, 16);
//test[1] = '\0';
//test[0] = 'Ā';
//test[0] = 'B';
//fprintf(testout, "     %c\t", test[0]);
//test[0] = 'Ā';
//s = (char *)test;
//test[0] = linestring[0];
//test[1] = linestring[1];
//test[2] = linestring[2];
//test[3] = linestring[3];
//test[4] = linestring[4];
//test[5] = '\0';


memset ((void*)test, '\0', sizeof(test));
hexchar = (uint48_t)strtoul((const char *)linestring, NULL, 16);
if(hexchar > 0xFFFF)
        break;
(void)utf8_encode(test, hexchar);

//cd = iconv_open ("UTF-8", "UCS−4−INTERNAL");
//iconv(cd, &hexchar, 4, test, 8);
//iconv_close(cd);
/*
memset ((void*)test, '\0', sizeof(test));
inbytesleft = 4;
outbytesleft = 4;
inbuf=(char *)&hexchar;
outbuf=(char *)test;
//cd = iconv_open ("UTF-8", "UCS−4−INTERNAL");
cd = iconv_open ("UTF-8","UCS−4−INTERNAL");
iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
iconv_close(cd);
//test[4] = '\0';
*/
//(void)u8_toutf8(test, 8, &hexchar, 1);

err = gdImageStringFTEx(im,brect,black,input_ttf,pixel_pt_size,0.0,x,y,(const char *)test,strex);
//                err = gdImageStringFTEx(im,&brect[0],black,input_ttf,pixel_pt_size,0.0,x,y,(const char *)test,strex);
                if (err) {fprintf(stderr,err); return 1;}
                bounding_box_width_cur = brect[4]-brect[0];
                bounding_box_height_cur = brect[3]-brect[7];
                //save font location/size to font.fnt
//                fprintf(font_fnt_out, "\"0x%s\"=%d,%d,%d,%d\n", linestring, x, y, bounding_box_width_cur, bounding_box_height_cur );
                //add up width for current row
 //               row_width_cur += col_spacing_pixels + bounding_box_width_cur;
                //find tallest box in current row to know for next row's offset
                if(bounding_box_height_cur > bounding_box_height_max)
                        bounding_box_height_max = bounding_box_height_cur;

                x += col_spacing_pixels + bounding_box_width_cur;
                //continue with current row
                if(column_cur < columns-1){
                        column_cur++;
                }else{ //max columns reached
fprintf(testout, "\n");
                        y += row_spacing_pixels + bounding_box_height_max;
                        //add border space
                        row_width_cur += col_spacing_pixels;
                        //this row is widest yet, adjust image width
//                        if(row_width_cur > image_width)
//                                image_width = row_width_cur;
//                        row_width_cur = 0;
                        //add to height for image
//                        image_height += row_spacing_pixels + bounding_box_height_max;
                        bounding_box_height_max = 0;
                        //reset to first col for new row
                        column_cur = 0;
                        row_cur++;
			x = row_spacing_pixels;
                }
        }

fclose(font_fnt_out);
fclose(input_hex);
fclose(testout);

//0 to 10FFFF
//Determine size of single character string box


	/* obtain brect so that we can size the image */
//	err = gdImageStringFT(NULL,&brect[0],0,f,sz,0.,0,0,s);
//	err = gdImageStringFTEx(NULL,&brect[0],0,f,sz,0.,0,0,s,strex);
//char *gdImageStringFT(gdImagePtr im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *string)
//char *gdImageStringFTEx(gdImagePtr im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *string, gdFTStringExtraPtr strex)
//	if (err) {fprintf(stderr,err); return 1;}

//printf("here 1\n");
//printf("%s\n", strex.fontpath);
//gdFree((void *)strex->xshow);
//gdFree((void *)strex->fontpath);
	/* create an image big enough for the string plus a little whitespace */
//	x = brect[2]-brect[6] + 9;
//	y = brect[3]-brect[7] + 19;

//printf("character width: %d height: %d\n", brect[2]-brect[6], brect[3]-brect[7]);
/*
x = 4000;
y = 4000;

//



printf("here 2\n");





//create image
	im = gdImageCreate(x,y);
//aa_disable = gdImageColorAllocate(im, -1, -1, -1);
	white = gdImageColorResolve(im, 0, 0, 0);
	black = gdImageColorResolve(im, 0, 255, 0);

	//x = 0;
	//y = 0;

x=20;
y=20;

test[1] = '\0';
for(test[0]=0; test[0]<16000; test[0]++){

//if(test[0] == tab || test[0] == newline)
//	continue;



s = test;
//	x = 0 - brect[6];
//	y = 0 - brect[7];


//	err = gdImageStringFT(im,&brect[0],black,f,sz,0.0,x,y,s);
	err = gdImageStringFTEx(im,&brect[0],black,input_ttf,pixel_pt_size,0.0,x,y,s,strex);
//char *gdImageStringFTEx(gdImagePtr im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *string, gdFTStringExtraPtr strex)
	if (err) {fprintf(stderr,err); return 1;}
//printf("%s\n", (const char *)strex->xshow);
//printf("%s\n", (const char *)strex->fontpath);
gdFree((void *)strex->xshow);
gdFree((void *)strex->fontpath);
x+=20;
if(test[0] % 164 == 0){
	y+=40;
	x=20;
}

}

printf("here 3\n");

	//gdImagePng(im, stdout);

*/

        image_out = fopen("test01.png", "w");
        gdImageInterlace(im, 1);
        gdImagePng(im, image_out);


        fclose(image_out);
        gdImageDestroy(im);

 //      if(munmap(mem_file, file_bytes) == -1) {
 //               perror("Error un-mmapping the file");
 //       }



//fclose(input_hex);

	/* Destroy it */
	//gdImageDestroy(im);

	return 0;
}
