#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <locale.h>
#include <libps/pslib.h>
#ifdef MEMORY_DEBUGGING
#include <libps/pslib-mp.h>
#endif

void errorhandler(PSDoc *p, int error, const char *str, void *data) {
	fprintf(stderr, "PSLib: %s\n", str);
}

size_t writeproc(PSDoc *p, void *data, size_t size) {
	return fwrite(data, 1, size, stdout);
}

#define LEFT_BORDER 50
#define EXAMPLE_BOX_HEIGHT 120
#define EXAMPLE_BOX_WIDTH  100
#define EXAMPLE_BOX_TITLE_HEIGHT  20

void begin_example_box(PSDoc *p, float llx, float lly, char *title, int font) {
	PS_save(p);
	PS_translate(p, llx, lly);
	PS_setcolor(p, "fill", "gray", 0.5, 0.0, 0.0, 0.0);
	PS_rect(p, 0, EXAMPLE_BOX_HEIGHT-EXAMPLE_BOX_TITLE_HEIGHT,
	           EXAMPLE_BOX_WIDTH, EXAMPLE_BOX_TITLE_HEIGHT);
	PS_fill(p);
	PS_setcolor(p, "stroke", "gray", 1.0, 0.0, 0.0, 0.0);
	PS_setfont(p, font, 12.0);
	PS_show_xy(p, title, 10, EXAMPLE_BOX_HEIGHT-EXAMPLE_BOX_TITLE_HEIGHT+5);
	PS_setlinewidth(p, 1.0);
	PS_setcolor(p, "stroke", "gray", 0.0, 0.0, 0.0, 0.0);
	PS_rect(p, 0, 0, EXAMPLE_BOX_WIDTH, EXAMPLE_BOX_HEIGHT);
	PS_stroke(p);
	PS_moveto(p, 0, EXAMPLE_BOX_HEIGHT-EXAMPLE_BOX_TITLE_HEIGHT);
	PS_lineto(p, EXAMPLE_BOX_WIDTH, EXAMPLE_BOX_HEIGHT-EXAMPLE_BOX_TITLE_HEIGHT);
	PS_stroke(p);
}

void end_example_box(PSDoc *p) {
	PS_restore(p);
}

void footer(PSDoc *p, const char *text) {
	int psfont;
	char buffer[100];
	psfont = PS_findfont(p, "Helvetica", "", 0);
	PS_setfont(p, psfont, 8.0);
	sprintf(buffer, "This file has been created with pslib %s", PS_get_parameter(p, "dottedversion", 0.0));
	PS_show_xy(p, buffer, LEFT_BORDER, 25);
}
 
int main() {
	PSDoc *ps;
	int psfont, dicefont, corkfont, builtinfont;
	int psimage;
	int pspattern1, pspattern2, pstemplate;
	float polydash[4] = {5.0, 3.0, 1.0, 4.0};
	int x, y, i;
	float width, dimension[3];
	char str[80];
	double texty;
	double boxheight;

	PS_boot();
	setlocale(LC_NUMERIC, "");
#ifdef MEMORY_DEBUGGING
	PS_mp_init();
#endif

#ifdef MEMORY_DEBUGGING
	ps = PS_new2(errorhandler, PS_mp_malloc, PS_mp_realloc, PS_mp_free, NULL);
#else
	ps = PS_new();
#endif

	if (0 > PS_open_file(ps, "draw.ps")) {
//	if (0 > PS_open_mem(ps, writeproc)) {
		printf("Cannot open PostScript file\n");
		exit(1);
	}

	PS_set_parameter(ps, "warning", "true");

	PS_set_info(ps, "Creator", __FILE__);
	PS_set_info(ps, "Author", "Uwe Steinmann");
	PS_set_info(ps, "Title", "Drawing Examples");
	PS_set_info(ps, "Keywords", "LineTo, MoveTo, Arc, Rect, Polygon");
//	PS_set_info(ps, "BoundingBox", "0 0 596 842");

	pstemplate = PS_begin_template(ps, 30.0, 30.0);
	PS_moveto(ps, 0, 0);
	PS_lineto(ps, 30, 30);
	PS_moveto(ps, 0, 30);
	PS_lineto(ps, 30, 0);
	PS_stroke(ps);
	PS_end_template(ps);

	pspattern1 = PS_begin_pattern(ps, 10.0, 10.0, 10.0, 10.0, 1);
	PS_setlinewidth(ps, 0.2);
	PS_setcolor(ps, "stroke", "rgb", 0.0, 0.0, 1.0, 0.0);
	PS_moveto(ps, 0, 0);
	PS_lineto(ps, 7, 7);
	PS_stroke(ps);
	PS_moveto(ps, 0, 7);
	PS_lineto(ps, 7, 0);
	PS_stroke(ps);
	PS_end_pattern(ps);

	pspattern2 = PS_begin_pattern(ps, 10.0, 10.0, 10.0, 10.0, 2);
//	PS_setcolor(ps, "stroke", "rgb", 0.0, 0.0, 1.0, 0.0);
	PS_moveto(ps, 0, 0);
	PS_lineto(ps, 5, 5);
	PS_stroke(ps);
	PS_end_pattern(ps);

	PS_begin_page(ps, 596, 842);
	footer(ps, "");

	PS_set_parameter(ps, "transition", "wipe");
	PS_set_value(ps, "duration", 0.5);
		
	psfont = PS_findfont(ps, "Helvetica", "", 0);

	x = 0;
	y = 675;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Lines", psfont);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);

	PS_setdash(ps, 5.0, 5.0);
	PS_moveto(ps, 10, 15);
	PS_lineto(ps, 90, 30);
	PS_stroke(ps);

	PS_setdash(ps, 0.0, 0.0);
	PS_setlinewidth(ps, 2.0);
	PS_moveto(ps, 10, 20);
	PS_lineto(ps, 90, 50);
	PS_stroke(ps);

	PS_setlinewidth(ps, 1.0);
	PS_setcolor(ps, "stroke", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_moveto(ps, 10, 25);
	PS_lineto(ps, 90, 70);
	PS_stroke(ps);

	PS_setcolor(ps, "stroke", "gray", 0.0, 0.0, 0.0, 0.0);
	PS_setpolydash(ps, polydash, 4);
	PS_moveto(ps, 10, 30);
	PS_lineto(ps, 90, 90);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Rectangles", psfont);
	PS_rect(ps, 10, 10, 35, 35);
	PS_stroke(ps);
	PS_setcolor(ps, "stroke", "rgb", 0.0, 1.0, 0.0, 0.0);
	PS_rect(ps, 50, 10, 35, 35);
	PS_stroke(ps);
	PS_setcolor(ps, "fill", "rgb", 1.0, 1.0, 0.0, 0.0);
	PS_rect(ps, 10, 50, 35, 35);
	PS_fill(ps);
	PS_setlinewidth(ps, 3.0);
	PS_setcolor(ps, "stroke", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_setdash(ps, 5.0, 5.0);
	PS_rect(ps, 50, 50, 35, 35);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Circles, Arcs", psfont);
	PS_circle(ps, 30, 30, 20);
	PS_stroke(ps);
	PS_circle(ps, 70, 30, 20);
	PS_fill(ps);
	PS_arc(ps, 30, 70, 20, 0, 270);
	PS_fill(ps);
	PS_setlinewidth(ps, 3.0);
	PS_setcolor(ps, "both", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_setdash(ps, 5.0, 5.0);
	PS_arc(ps, 70, 70, 20, 0, 270);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Clipping", psfont);
	PS_rect(ps, 30, 30, 40, 40);
	PS_clip(ps);
	PS_circle(ps, 30, 30, 20);
	PS_stroke(ps);
	PS_circle(ps, 70, 30, 20);
	PS_fill(ps);
	PS_arc(ps, 30, 70, 20, 0, 270);
	PS_fill(ps);
	PS_setlinewidth(ps, 3.0);
	PS_setcolor(ps, "both", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_setdash(ps, 5.0, 5.0);
	PS_arc(ps, 70, 70, 20, 0, 270);
	PS_stroke(ps);
	end_example_box(ps);

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Line joins", psfont);
	PS_setlinewidth(ps, 5.0);
	PS_setlinejoin(ps, 0);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 25, 40);
	PS_lineto(ps, 40, 10);
	PS_stroke(ps);
	PS_setlinejoin(ps, 1);
	PS_moveto(ps, 60, 10);
	PS_lineto(ps, 75, 40);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);
	PS_setlinejoin(ps, 2);
	PS_moveto(ps, 10, 60);
	PS_lineto(ps, 25, 90);
	PS_lineto(ps, 40, 60);
	PS_stroke(ps);

	PS_setlinewidth(ps, 0.5);
	PS_setcolor(ps, "both", "gray", 1.0, 0.0, 0.0, 0.0);
	PS_setlinejoin(ps, 0);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 25, 40);
	PS_lineto(ps, 40, 10);
	PS_stroke(ps);
	PS_moveto(ps, 60, 10);
	PS_lineto(ps, 75, 40);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);
	PS_moveto(ps, 10, 60);
	PS_lineto(ps, 25, 90);
	PS_lineto(ps, 40, 60);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Line caps", psfont);
	PS_setlinewidth(ps, 5.0);
	PS_setlinecap(ps, 0);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 25, 40);
	PS_lineto(ps, 40, 10);
	PS_stroke(ps);
	PS_setlinecap(ps, 1);
	PS_moveto(ps, 60, 10);
	PS_lineto(ps, 75, 40);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);
	PS_setlinecap(ps, 2);
	PS_moveto(ps, 10, 60);
	PS_lineto(ps, 25, 90);
	PS_lineto(ps, 40, 60);
	PS_stroke(ps);

	PS_setlinewidth(ps, 0.5);
	PS_setcolor(ps, "both", "gray", 1.0, 0.0, 0.0, 0.0);
	PS_setlinejoin(ps, 0);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 25, 40);
	PS_lineto(ps, 40, 10);
	PS_stroke(ps);
	PS_moveto(ps, 60, 10);
	PS_lineto(ps, 75, 40);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);
	PS_moveto(ps, 10, 60);
	PS_lineto(ps, 25, 90);
	PS_lineto(ps, 40, 60);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Miter limit", psfont);
	PS_show_xy(ps, "10", 13, 10);
	PS_setmiterlimit(ps, 10);
	PS_moveto(ps, 11, 10);
	PS_lineto(ps, 20, 90);
	PS_lineto(ps, 29, 10);
	PS_stroke(ps);
	PS_show_xy(ps, "5", 47, 10);
	PS_setmiterlimit(ps, 5);
	PS_moveto(ps, 41, 10);
	PS_lineto(ps, 50, 90);
	PS_lineto(ps, 59, 10);
	PS_stroke(ps);
	PS_show_xy(ps, "1", 77, 10);
	PS_setmiterlimit(ps, 1);
	PS_moveto(ps, 71, 10);
	PS_lineto(ps, 80, 90);
	PS_lineto(ps, 89, 10);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Curves", psfont);
	PS_moveto(ps, 10, 10);
	PS_curveto(ps, 10, 40, 40, 20, 50, 20);
	PS_curveto(ps, 50, 20, 80, 90, 20, 70);
	PS_curveto(ps, 20, 70, 80, 20, 10, 10);
	PS_stroke(ps);
	PS_setcolor(ps, "both", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_moveto(ps, 50, 10);
	PS_curveto(ps, 50, 10, 110, 40, 90, 90);
	PS_curveto(ps, 90, 90, 30, 90, 80, 70);
	PS_curveto(ps, 80, 70, 100, 10, 50, 10);
	PS_fill(ps);
	end_example_box(ps);

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "PNG-Image", psfont);
	psimage = PS_open_image_file(ps, "png", "debian.png", NULL, 0);
	PS_place_image(ps, psimage, 10, 10, 0.5);
	PS_place_image(ps, psimage, 40, 40, 0.8);
	PS_close_image(ps, psimage);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "EPS-Image", psfont);
	psimage = PS_open_image_file(ps, "eps", "picture.eps", NULL, 0);
	PS_place_image(ps, psimage, 10, 10, 0.3);
	PS_close_image(ps, psimage);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Path (1)", psfont);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 50, 50);
	PS_moveto(ps, 20, 10);
	PS_lineto(ps, 60, 50);
	PS_circle(ps, 60, 60, 20);
	PS_lineto(ps, 90, 70);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Path (2)", psfont);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 20, 20);
	PS_rect(ps, 30, 30, 10, 20);
	PS_lineto(ps, 50, 10);
	PS_stroke(ps);
	PS_moveto(ps, 70, 10);
	PS_lineto(ps, 70, 50);
	PS_arc(ps, 70, 60, 20, 60, 210);
	PS_stroke(ps);
	end_example_box(ps);

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text", psfont);
	PS_setfont(ps, psfont, 8.0);
	PS_show_xy(ps, "This is text in 8.0", 10, 10);
	PS_setfont(ps, psfont, 12.0);
	PS_show_xy(ps, "and in 12.0", 10, 23);
	PS_setfont(ps, psfont, 18.0);
	PS_show_xy(ps, "in 18.0", 10, 40);
	PS_setfont(ps, psfont, 36.0);
	PS_show_xy(ps, "huge", 10, 65);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text outlined", psfont);
	PS_setfont(ps, psfont, 36.0);
	PS_set_value(ps, "textrendering", 1);
	PS_show_xy(ps, "huge", 10, 15);
	PS_setlinewidth(ps, 0.5);
	PS_show_xy(ps, "huge", 10, 55);
	PS_set_value(ps, "textrendering", -1);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text clipping", psfont);
	PS_setfont(ps, psfont, 70.0);
	PS_set_value(ps, "textrendering", 5);
	PS_show_xy(ps, "82", 10, 15);
	psimage = PS_open_image_file(ps, "png", "debian.png", NULL, 0);
	PS_place_image(ps, psimage, 10, 1, 1.5);
	PS_close_image(ps, psimage);
	PS_set_value(ps, "textrendering", 6);
	PS_setfont(ps, psfont, 20.0);
	PS_set_parameter(ps, "kerning", "false");
	PS_setcolor(ps, "stroke", "gray", 0.5, 0.0, 0.0, 0.0);
	PS_show_xy(ps, "Stripes", 10, 80);
	PS_set_parameter(ps, "kerning", "true");
	PS_setcolor(ps, "stroke", "gray", 0.0, 0.0, 0.0, 0.0);
	for(i=75; i<97; i=i+2) {
		PS_moveto(ps, 10, i);
		PS_lineto(ps, 80, i);
		PS_stroke(ps);
	}
	PS_set_value(ps, "textrendering", -1);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "invisible Text", psfont);
	PS_setfont(ps, psfont, 10.0);
	PS_show_xy(ps, "This is ", 5, 15);
	PS_set_value(ps, "textrendering", 3);
	PS_show(ps, "invisible");
	PS_set_value(ps, "textrendering", -1);
	PS_show(ps, " text.");
	PS_show_xy(ps, "This is ", 5, 35);
	PS_show(ps, "invisible");
	PS_show(ps, " text.");
	end_example_box(ps);

	{
	char *str1 = {"Text can be put into a box of any size. This one is 80x80 pixels and its lower left corner ist at (10, 10). The text is left justified. The font size is 8.0."};
	x = 0;
	y -= 150;
	PS_set_parameter(ps, "hyphenation", "true");
	PS_set_parameter(ps, "hyphendict", "hyph_en.dic");
	PS_set_value(ps, "hyphenminchars", 2);
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text in a box (1)", psfont);
	PS_setfont(ps, psfont, 8.0);
	PS_set_value(ps, "leading", 11);
	PS_show_boxed(ps, str1, 10, 10, 80, 80, "left", NULL);
	end_example_box(ps);
	}

	{
	char *str2 = {"Text can be put into a box of any size. This one is 80x80 pixels and its lower left corner ist at (10, 10). The text is left and right justified. The font size is 8.0."};
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text in a box (2)", psfont);
	PS_setfont(ps, psfont, 8.0);
	PS_set_value(ps, "leading", 11);
	PS_show_boxed(ps, str2, 10, 10, 80, 80, "justify", NULL);
	end_example_box(ps);
	}

	{
	char *str3 = {"Text can be put into a box of any size. This one is 80x80 pixels and its lower left corner ist at (10, 10). The text is right justified. The font size is 8.0."};
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text in a box (3)", psfont);
	PS_setfont(ps, psfont, 8.0);
	PS_set_value(ps, "leading", 11);
	PS_show_boxed(ps, str3, 10, 10, 80, 80, "right", NULL);
	end_example_box(ps);
	}

	{
	char *str5 = {"If the parameter linebreak is turned on,¶\neach line will be ended with a carriage return.¶\nCR are marked with a '¶' in this paragraph.¶\n"};
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text with CR", psfont);
	PS_setfont(ps, psfont, 8.0);
	PS_set_value(ps, "leading", 11);
	PS_set_parameter(ps, "linebreak", "true");
	PS_show_boxed(ps, str5, 10, 10, 80, 80, "center", NULL);
	PS_set_parameter(ps, "linebreak", "false");
	end_example_box(ps);
	}

	PS_end_page(ps);

	PS_begin_page(ps, 596, 842);

	PS_set_parameter(ps, "transition", "wipe");
	PS_set_value(ps, "duration", 0.5);
		
	if(0 == (psfont = PS_findfont(ps, "Helvetica", "", 0))) {
		fprintf(stderr, "Could not load font 'Helvetica'.\n");
		exit(1);
	}

	x = 0;
	y = 675;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text", psfont);
	PS_setfont(ps, psfont, 10.0);
	PS_show_xy(ps, "No lines at all", 5, 75);
	PS_set_parameter(ps, "underline", "true");
	PS_show_xy(ps, "Text is underlined", 5, 60);
	PS_set_parameter(ps, "underline", "false");
	PS_set_parameter(ps, "overline", "true");
	PS_show_xy(ps, "Text is overlined", 5, 45);
	PS_set_parameter(ps, "overline", "false");
	PS_set_parameter(ps, "strikeout", "true");
	PS_show_xy(ps, "Text is striked out", 5, 30);
	PS_set_parameter(ps, "underline", "true");
	PS_set_parameter(ps, "overline", "true");
	PS_show_xy(ps, "Everything at once", 5, 15);
	PS_set_parameter(ps, "overline", "false");
	PS_set_parameter(ps, "underline", "false");
	PS_set_parameter(ps, "strikeout", "false");
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text width", psfont);
	PS_setfont(ps, psfont, 14.0);
	PS_show_xy(ps, "Geometry", 10, 50);
	width = PS_stringwidth2(ps, "Geometry", -1, psfont, 14);
	PS_moveto(ps, 10, 45);
	PS_lineto(ps, 10+width, 45);
	PS_stroke(ps);
	PS_setfont(ps, psfont, 6.0);
	sprintf(str, "Text is %.2f pixel wide.", width);
	PS_show_xy(ps, str, 10, 35);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text geometry", psfont);
	PS_setfont(ps, psfont, 14.0);
	PS_show_xy(ps, "Geometry", 10, 50);
	width = PS_string_geometry(ps, "Geometry", -1, psfont, 14, dimension);
	PS_setlinewidth(ps, 0.4);
	PS_moveto(ps, 10, 50);
	PS_lineto(ps, 10+dimension[0], 50);
	PS_stroke(ps);
	PS_moveto(ps, 10, 50+dimension[1]);
	PS_lineto(ps, 10+dimension[0], 50+dimension[1]);
	PS_stroke(ps);
	PS_moveto(ps, 10, 50+dimension[2]);
	PS_lineto(ps, 10+dimension[0], 50+dimension[2]);
	PS_stroke(ps);
	PS_setfont(ps, psfont, 6.0);
	sprintf(str, "Text is %.2f pixel wide.", dimension[0]);
	PS_show_xy(ps, str, 10, 35);
	sprintf(str, "Ascender is %.2f pixel.", dimension[2]);
	PS_show_xy(ps, str, 10, 27);
	sprintf(str, "Descender is %.2f pixel.", dimension[1]);
	PS_show_xy(ps, str, 10, 19);
	end_example_box(ps);

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text kerning", psfont);
	PS_setfont(ps, psfont, 14.0);
	PS_set_parameter(ps, "kerning", "true");
	PS_show_xy(ps, "Tea VA life", 10, 70);
	width = PS_stringwidth2(ps, "Tea VA life", -1, psfont, 14);
	PS_moveto(ps, 10, 65);
	PS_lineto(ps, 10+width, 65);
	PS_stroke(ps);
	PS_setfont(ps, psfont, 6.0);
	sprintf(str, "Text is %.2f pixel wide.", width);
	PS_show_xy(ps, str, 10, 55);

	PS_setfont(ps, psfont, 14.0);
	PS_set_parameter(ps, "kerning", "false");
	PS_show_xy(ps, "Tea VA life", 10, 30);
	width = PS_stringwidth2(ps, "Tea VA life", -1, psfont, 14);
	PS_moveto(ps, 10, 25);
	PS_lineto(ps, 10+width, 25);
	PS_stroke(ps);
	PS_setfont(ps, psfont, 6.0);
	sprintf(str, "Text is %.2f pixel wide.", width);
	PS_show_xy(ps, str, 10, 15);

	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Embedded font", psfont);
	dicefont = PS_findfont(ps, "dice", "", 1);
	PS_setfont(ps, dicefont, 10.0);
	PS_show_xy(ps, "123456", 10, 70);
	PS_setfont(ps, dicefont, 14.0);
	PS_show_xy(ps, "123456", 10, 50);
	PS_setfont(ps, dicefont, 18.0);
	PS_show_xy(ps, "123456", 10, 24);
	end_example_box(ps);

	{
	char *str4 = {"If text is output in a box left and right justified then the margins can appear bumby due to punction and hyphens. To prevent this, one can allow certain glyphs to exceed the margin. Finding the right values can be a painful task. Look for the hyphen and the exaggerated 'e' in this text."};
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Protusion", psfont);
	PS_set_parameter(ps, "hyphenation", "true");
	PS_set_parameter(ps, "protusion", "true");
	PS_set_parameter(ps, "hyphendict", "hyph_en.dic");
	PS_set_value(ps, "hyphenminchars", 2);
	PS_setfont(ps, psfont, 6.0);
	PS_set_value(ps, "leading", 8);
	PS_show_boxed(ps, str4, 10, 10, 80, 80, "justify", NULL);
	PS_set_parameter(ps, "protusion", "false");
	PS_setlinewidth(ps, 0.2);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 10, 90);
	PS_stroke(ps);
	PS_moveto(ps, 90, 10);
	PS_lineto(ps, 90, 90);
	PS_stroke(ps);
	end_example_box(ps);
	}

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Encoding", psfont);
	corkfont = PS_findfont(ps, "Helvetica", "", 0);
	builtinfont = PS_findfont(ps, "Helvetica", "builtin", 0);
	PS_setfont(ps, corkfont, 9.0);
	PS_show_xy(ps, "cork encoding äüöß", 10, 10);
	PS_setfont(ps, builtinfont, 9.0);
	PS_show_xy(ps, "builtin encoding äüöß", 10, 30);
	end_example_box(ps);

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Text rise", psfont);
	PS_set_value(ps, "textx", 13);
	PS_set_value(ps, "texty", 60);
	PS_setfont(ps, psfont, 18.0);
	PS_show(ps, "a");
	PS_setfont(ps, psfont, 12.0);
	PS_set_value(ps, "textrise", 6);
	PS_show(ps, "2");
	PS_setfont(ps, psfont, 18.0);
	PS_set_value(ps, "textrise", 0);
	PS_show(ps, "+b");
	PS_setfont(ps, psfont, 12.0);
	PS_set_value(ps, "textrise", 6);
	PS_show(ps, "2");
	PS_setfont(ps, psfont, 18.0);
	PS_set_value(ps, "textrise", 0);
	PS_show(ps, "=c");
	PS_setfont(ps, psfont, 12.0);
	PS_set_value(ps, "textrise", 6);
	PS_show(ps, "2");
	PS_set_value(ps, "textrise", 0);

	PS_set_value(ps, "textx", 13);
	PS_set_value(ps, "texty", 30);
	PS_setfont(ps, psfont, 14.0);
	PS_show(ps, "some");
	PS_setfont(ps, psfont, 9.0);
	PS_set_value(ps, "textrise", 6);
	PS_show(ps, "1)");
	PS_set_value(ps, "textrise", 0);
	PS_setfont(ps, psfont, 14.0);
	PS_show(ps, " Text");
	PS_setfont(ps, psfont, 9.0);
	PS_show_xy(ps, "1) and a footnote", 14, 10);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Strange Text", psfont);
	PS_set_value(ps, "textx", 10);
	PS_set_value(ps, "texty", 70);
	PS_setfont(ps, psfont, 14.0);
	PS_show(ps, "ÅÊÜß¹²³Æ½");
	PS_set_value(ps, "textx", 10);
	PS_set_value(ps, "texty", 53);
	PS_show(ps, "¢¡¶§×Ç");
	end_example_box(ps);

	{
	char *str6 = {"Text can be put into a box of any size. This one has a height of 0 pixels, which makes it height as needed to contain all text."};
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Var. box length", psfont);
	PS_setfont(ps, psfont, 5.0);
	PS_set_value(ps, "leading", 7);
	PS_show_boxed(ps, str6, 10, 90, 80, 0.0, "left", NULL);
	texty = PS_get_value(ps, "texty", 0.0);
	boxheight = PS_get_value(ps, "boxheight", 0.0);
	fprintf(stderr, "texty = %f\n", texty);
	fprintf(stderr, "boxheight = %f\n", boxheight);
	PS_save(ps);
	PS_setlinewidth(ps, 0.2);
	PS_moveto(ps, 10, texty);
	PS_lineto(ps, 90, texty);
	PS_stroke(ps);
	PS_restore(ps);
	PS_show_boxed(ps, str6, 10, 90-boxheight, 80, 0.0, "left", NULL);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Blind box", psfont);
	PS_setfont(ps, psfont, 5.0);
	PS_set_value(ps, "leading", 7);
	PS_show_boxed(ps, str6, 10, 90, 80, 0.0, "left", "blind");
	texty = PS_get_value(ps, "texty", 0.0);
	boxheight = PS_get_value(ps, "boxheight", 0.0);
	fprintf(stderr, "texty = %f\n", texty);
	fprintf(stderr, "boxheight = %f\n", boxheight);
	PS_save(ps);
	PS_setlinewidth(ps, 0.2);
	PS_rect(ps, 10, 90-boxheight, 80, boxheight);
	PS_stroke(ps);
	PS_restore(ps);
	PS_show_boxed(ps, str6, 10, 90-boxheight, 80, 0.0, "left", NULL);
	end_example_box(ps);
	}

	x = 0;
	y -= 150;
	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Templates", psfont);
	PS_place_image(ps, pstemplate, 20.0, 20.0, 1.0);
	PS_place_image(ps, pstemplate, 50.0, 30.0, 0.5);
	PS_place_image(ps, pstemplate, 70.0, 70.0, 0.6);
	PS_place_image(ps, pstemplate, 30.0, 50.0, 1.3);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Patterns", psfont);
	PS_setcolor(ps, "both", "pattern", (float) pspattern1, 0.0, 0.0, 0.0);
	PS_rect(ps, 10, 10, 35, 35);
	PS_fill(ps);
	PS_setlinewidth(ps, 10);
	PS_setcolor(ps, "stroke", "gray", 0.5, 0.0, 0.0, 0.0);
	PS_moveto(ps, 15, 55);
	PS_lineto(ps, 40, 90);
	PS_stroke(ps);
	PS_setcolor(ps, "stroke", "pattern", (float) pspattern1, 0.0, 0.0, 0.0);
	PS_moveto(ps, 15, 55);
	PS_lineto(ps, 40, 90);
	PS_stroke(ps);
	PS_setcolor(ps, "both", "pattern", (float) pspattern1, 0.0, 0.0, 0.0);
	PS_setfont(ps, psfont, 65.0);
	PS_show_xy(ps, "A", 50, 10);
	PS_setcolor(ps, "both", "rgb", 1.0, 0.0, 0.0, 0.0);
	/* FIXME: pspattern2 doesn't work because PaintType 2 doesn't work in some
	 * version of ghostscript */
	PS_setcolor(ps, "fill", "pattern", (float) pspattern2, 0.0, 0.0, 0.0);
	PS_rect(ps, 50, 50, 35, 35);
	PS_fill(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "Graphic States", psfont);
	PS_setcolor(ps, "stroke", "rgb", 1.0, 0.0, 0.0, 0.0);
	PS_moveto(ps, 10, 10);
	PS_lineto(ps, 90, 10);
	PS_stroke(ps);
	PS_save(ps);
	PS_setcolor(ps, "stroke", "rgb", 0.0, 1.0, 0.0, 0.0);
	PS_moveto(ps, 10, 20);
	PS_lineto(ps, 90, 20);
	PS_stroke(ps);
	PS_save(ps);
	PS_setlinewidth(ps, 3);
	PS_moveto(ps, 10, 30);
	PS_lineto(ps, 90, 30);
	PS_stroke(ps);
	PS_restore(ps);
	PS_moveto(ps, 10, 40);
	PS_lineto(ps, 90, 40);
	PS_stroke(ps);
	PS_restore(ps);
	PS_moveto(ps, 10, 50);
	PS_lineto(ps, 90, 50);
	PS_stroke(ps);
	end_example_box(ps);

	begin_example_box(ps, LEFT_BORDER+(EXAMPLE_BOX_WIDTH+30)*(x++), y, "JPG-Image", psfont);
	psimage = PS_open_image_file(ps, "jpeg", "exiftest.jpg", NULL, 0);
	PS_place_image(ps, psimage, 10, 10, 0.2);
	PS_close_image(ps, psimage);
	end_example_box(ps);

	PS_end_page(ps);

	PS_close(ps);
	PS_delete(ps);

#ifdef MEMORY_DEBUGGING 
	PS_mp_list_unfreed();
#endif  

	PS_shutdown();
	exit(0);
}
