#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <libps/pslib-mp.h>

void * my_malloc(PSDoc *p, size_t size, const char *caller) {
	void *a;
	a = (void *) malloc(size);
	return(a);
}   

void * my_realloc(PSDoc *p, void *mem, size_t size, const char *caller) {
	return((void *) realloc(mem, size));
} 
  
void my_free(PSDoc *p, void *mem) {
	free(mem);
}

void usage() {
	fprintf(stderr, "Usage: fontsample <list of fontnames>\n\n");
}


int main(int argc, char *argv[]) {
	PSDoc *psdoc;
	int psfont, samplefont;
	float bottommargin, colwidth, rowheight, leftmargin;
	float textwidth, fontsize, fontsamplesize;
	int i, j, k;
	char *text;

	colwidth = 25;
	rowheight = 25;
	leftmargin = 100;
	bottommargin = 270;
	fontsize = 10.0;
	fontsamplesize = 12.0;

	if(argc < 2) {
		usage();
		exit(1);
	}

	PS_mp_init();
	PS_boot();
	psdoc = PS_new2(NULL, PS_mp_malloc, PS_mp_realloc, PS_mp_free, NULL);
	PS_open_file(psdoc, "fontsample.ps");
	PS_set_info(psdoc, "Creator", __FILE__);
	PS_set_info(psdoc, "Author", "Uwe Steinmann");
	PS_set_info(psdoc, "Title", "Font sample");
	PS_set_info(psdoc, "Keywords", "font, sample");
	PS_set_info(psdoc, "BoundingBox", "0 0 596 842");

	PS_set_parameter(psdoc, "hyphenation", "true");
	PS_set_parameter(psdoc, "hyphendict", "hyph_en.dic");

	psfont = PS_findfont(psdoc, "Helvetica", NULL, 1);
	fprintf(stdout, "Creating %d pages\n", argc-1);
	for(k=1; k<argc; k++) {
		fprintf(stdout, "Creating page for %s\n", argv[k]);
		text = malloc(100);

		PS_begin_page(psdoc, 596, 842);
		samplefont = PS_findfont(psdoc, argv[k], "builtin", 1);

		PS_setfont(psdoc, psfont, 15.0);
		sprintf(text, "Fontsample for '%s'", PS_get_parameter(psdoc, "fontname", (float) samplefont));
		PS_show_xy(psdoc, text, leftmargin, bottommargin+20*rowheight);
		PS_setfont(psdoc, psfont, 10.0);
		PS_show_xy(psdoc, "Font encoding: ", leftmargin, bottommargin+19.0*rowheight);
		PS_show(psdoc, PS_get_parameter(psdoc, "fontencoding", (float) samplefont));
		PS_show_xy(psdoc, "capheight: ", leftmargin, bottommargin+18.5*rowheight);
		sprintf(text, "%.2f", PS_get_value(psdoc, "capheight", (float) samplefont));
		PS_show(psdoc, text);
		PS_show_xy(psdoc, "ascender: ", leftmargin, bottommargin+18.0*rowheight);
		sprintf(text, "%.2f", PS_get_value(psdoc, "ascender", (float) samplefont));
		PS_show(psdoc, text);
		PS_show_xy(psdoc, "descender: ", leftmargin, bottommargin+17.5*rowheight);
		sprintf(text, "%.2f", PS_get_value(psdoc, "descender", (float) samplefont));
		PS_show(psdoc, text);

		for(i=0; i<=16; i++) {
			PS_moveto(psdoc, leftmargin+i*colwidth, bottommargin);
			PS_lineto(psdoc, leftmargin+i*colwidth, bottommargin+16*rowheight);
			PS_stroke(psdoc);
		}
		for(j=0; j<=16; j++) {
			PS_moveto(psdoc, leftmargin, bottommargin+j*rowheight);
			PS_lineto(psdoc, leftmargin+16*colwidth, bottommargin+j*rowheight);
			PS_stroke(psdoc);
		}

		PS_setfont(psdoc, psfont, fontsize);
		for(i=0; i<16; i++) {
			sprintf(text, "x%X", i);
			textwidth = PS_stringwidth2(psdoc, text,  -1, psfont, fontsize);
			PS_show_xy(psdoc, text, leftmargin+i*colwidth+colwidth/2-textwidth/2, bottommargin+16*rowheight+fontsize/2);
		}
		for(j=0; j<16; j++) {
			sprintf(text, "%Xx", j);
			PS_show_xy(psdoc, text, leftmargin-1.7*fontsize, bottommargin+(15-j)*rowheight+rowheight/2-fontsize/2);
		}

		/* The symbol itself */
		PS_setfont(psdoc, samplefont, fontsamplesize);
		PS_setlinewidth(psdoc, 0.4);
		for(j=0; j<16; j++) {
			for(i=0; i<16; i++) {
				textwidth = PS_symbol_width(psdoc, j*16+i, 0, fontsamplesize);
				PS_set_value(psdoc, "textx", leftmargin+i*colwidth+colwidth/2-textwidth/2);
				PS_set_value(psdoc, "texty", bottommargin+(15-j)*rowheight+rowheight/2+3-fontsize/2);
				//PS_show_xy(psdoc, text, leftmargin+i*colwidth+colwidth/2-textwidth/2, bottommargin+(15-j)*rowheight+rowheight/2-fontsize/2);
	//			PS_show(psdoc, text);
				PS_symbol(psdoc, j*16+i);
				PS_moveto(psdoc, leftmargin+i*colwidth+colwidth/2-textwidth/2, bottommargin+(15-j)*rowheight+rowheight/2+3-fontsize/2);
				PS_lineto(psdoc, leftmargin+i*colwidth+colwidth/2+textwidth/2, bottommargin+(15-j)*rowheight+rowheight/2+3-fontsize/2);
				PS_stroke(psdoc);
			}
		}

		/* The name of the symbol */
		PS_setfont(psdoc, psfont, 3);
		for(j=0; j<16; j++) {
			for(i=0; i<16; i++) {
				PS_symbol_name(psdoc, j*16+i, samplefont, text, 100);
				PS_set_value(psdoc, "textx", leftmargin+i*colwidth+2);
				PS_set_value(psdoc, "texty", bottommargin+(15-j)*rowheight+2);
				PS_show(psdoc, text);
				sprintf(text, " (%d)", j*16+i);
				PS_show(psdoc, text);
			}
		}
		free(text);

		text = "This fontsample matrix is created with the PS_symbol() function. It prints a glyph by its decimal value in the font encoding vector. pslib can use the TeXBase1 encoding (default) or the encoding shipped with the font itself, which is usually AdobeStandardEncoding. The above matrix uses the encoding of the font which is used when the parameter 'encoding' of PS_findfont() is set to 'builtin'. This usually results in a subset of all available glyphs of the font.\n\nQuite a lot of glyphs cannot be reached without the PS_symbol() function. The reason is simple: If text is output with PS_show(), then each character will be first mapped to a glyph by applying the ISO-8859-1 input encoding on it. Since ISO-8859-1 has less characters then a font usually provides glyphs, there will be some glyphs not reachable with regular text.";
		PS_setfont(psdoc, psfont, 8);
		PS_set_value(psdoc, "leading", 12.0);
		PS_set_value(psdoc, "parindent", 12.0);
		PS_show_boxed(psdoc, text, leftmargin, bottommargin-250, colwidth*7.5, 230, "fulljustify", NULL);

		PS_setfont(psdoc, samplefont, 8);
		PS_set_value(psdoc, "leading", 12.0);
		PS_set_value(psdoc, "parindent", 12.0);
		PS_show_boxed(psdoc, text, leftmargin+colwidth*8.5, bottommargin-250, colwidth*7.5, 230, "fulljustify", NULL);

		PS_deletefont(psdoc, samplefont);
		PS_end_page(psdoc);
	}
	PS_deletefont(psdoc, psfont);
	PS_close(psdoc);
	PS_delete(psdoc);
	PS_mp_list_unfreed();
	PS_shutdown();
	exit(0);
}
