Adds Arc, Chord, GetCharWidth, Pie, PolyPolygon, PolyPolyline, RoundRect,
SetPixel, hatched brushes and a stub for StretchDIBits to the PostScript
driver.

diff --git a/graphics/psdrv/Makefile.in b/graphics/psdrv/Makefile.in
index aa3ddde..764a092 100644
--- a/graphics/psdrv/Makefile.in
+++ b/graphics/psdrv/Makefile.in
@@ -7,6 +7,7 @@
 
 C_SRCS = \
 	afm.c \
+	bitmap.c \
 	brush.c \
 	color.c \
 	driver.c \
diff --git a/graphics/psdrv/bitmap.c b/graphics/psdrv/bitmap.c
new file mode 100644
index 0000000..1a0698b
--- /dev/null
+++ b/graphics/psdrv/bitmap.c
@@ -0,0 +1,30 @@
+/*
+ *	PostScript driver bitmap functions
+ *
+ * Copyright 1998  Huw D M Davies
+ *
+ */
+
+#include "windows.h"
+#include "gdi.h"
+#include "psdrv.h"
+#include "debug.h"
+
+
+/***************************************************************************
+ *
+ *	PSDRV_StretchDIBits
+ */
+INT32 PSDRV_StretchDIBits( DC *dc, INT32 xDst, INT32 yDst, INT32 widthDst,
+			   INT32 heightDst, INT32 xSrc, INT32 ySrc,
+			   INT32 widthSrc, INT32 heightSrc, const void *bits,
+			   const BITMAPINFO *info, UINT32 wUsage, DWORD dwRop )
+{
+    TRACE(psdrv, "(%d,%d %dx%d) -> (%d,%d %dx%d) on %08x. %d colour bits\n",
+	  xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst,
+	  dc->hSelf, info->bmiHeader.biBitCount);
+
+
+    FIXME(psdrv, "stub\n");
+    return FALSE;
+}
diff --git a/graphics/psdrv/brush.c b/graphics/psdrv/brush.c
index 8a82afd..2579e4c 100644
--- a/graphics/psdrv/brush.c
+++ b/graphics/psdrv/brush.c
@@ -9,7 +9,7 @@
 #include "psdrv.h"
 #include "brush.h"
 #include "debug.h"
-
+#include "gdi.h"
 
 /***********************************************************************
  *           PSDRV_BRUSH_SelectObject
@@ -25,16 +25,18 @@
     switch(brush->logbrush.lbStyle) {
 
     case BS_SOLID:
-        physDev->brush.style = BS_SOLID;
         PSDRV_CreateColor(physDev, &physDev->brush.color, 
 			  brush->logbrush.lbColor);
 	break;
 
     case BS_NULL:
-        physDev->brush.style = BS_NULL;
         break;
 
     case BS_HATCHED:
+        PSDRV_CreateColor(physDev, &physDev->brush.color, 
+			  brush->logbrush.lbColor);
+        break;
+
     case BS_PATTERN:
         FIXME(psdrv, "Unsupported brush style %d\n", brush->logbrush.lbStyle);
 	break;
@@ -54,15 +56,25 @@
  *	PSDRV_SetBrush
  *
  */
-BOOL32 PSDRV_SetBrush(DC *dc)
+static BOOL32 PSDRV_SetBrush(DC *dc)
 {
     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
+    BRUSHOBJ *brush = (BRUSHOBJ *)GDI_GetObjPtr( dc->w.hBrush, BRUSH_MAGIC );
 
-    switch (physDev->brush.style) {
+    if(!brush) {
+        ERR(psdrv, "Can't get BRUSHOBJ\n");
+	return FALSE;
+    }
+    
+    switch (brush->logbrush.lbStyle) {
     case BS_SOLID:
+    case BS_HATCHED:
         PSDRV_WriteSetColor(dc, &physDev->brush.color);
 	break;
 
+    case BS_NULL:
+        break;
+
     default:
         return FALSE;
         break;
@@ -71,3 +83,120 @@
     physDev->brush.set = TRUE;
     return TRUE;
 }
+
+
+/**********************************************************************
+ *
+ *	PSDRV_Fill
+ *
+ */
+static BOOL32 PSDRV_Fill(DC *dc, BOOL32 EO)
+{
+    if(!EO)
+        return PSDRV_WriteFill(dc);
+    else
+      return PSDRV_WriteEOFill(dc);
+}
+
+
+/**********************************************************************
+ *
+ *	PSDRV_Clip
+ *
+ */
+static BOOL32 PSDRV_Clip(DC *dc, BOOL32 EO)
+{
+    if(!EO)
+        return PSDRV_WriteClip(dc);
+    else
+        return PSDRV_WriteEOClip(dc);
+}
+
+/**********************************************************************
+ *
+ *	PSDRV_Brush
+ *
+ */
+BOOL32 PSDRV_Brush(DC *dc, BOOL32 EO)
+{
+    BRUSHOBJ *brush = (BRUSHOBJ *)GDI_GetObjPtr( dc->w.hBrush, BRUSH_MAGIC );
+
+    if(!brush) {
+        ERR(psdrv, "Can't get BRUSHOBJ\n");
+	return FALSE;
+    }
+
+    switch (brush->logbrush.lbStyle) {
+    case BS_SOLID:
+        PSDRV_SetBrush(dc);
+	PSDRV_WriteGSave(dc);
+        PSDRV_Fill(dc, EO);
+	PSDRV_WriteGRestore(dc);
+	return TRUE;
+	break;
+
+    case BS_HATCHED:
+        PSDRV_SetBrush(dc);
+
+	switch(brush->logbrush.lbHatch) {
+	case HS_VERTICAL:
+	case HS_CROSS:
+	    PSDRV_WriteGSave(dc);
+	    PSDRV_Clip(dc, EO);
+	    PSDRV_WriteHatch(dc);
+	    PSDRV_WriteStroke(dc);
+	    PSDRV_WriteGRestore(dc);
+	    if(brush->logbrush.lbHatch == HS_VERTICAL)
+	        break;
+	    /* else fallthrough for HS_CROSS */
+
+	case HS_HORIZONTAL:
+	    PSDRV_WriteGSave(dc);
+	    PSDRV_Clip(dc, EO);
+	    PSDRV_WriteRotate(dc, 90.0);
+	    PSDRV_WriteHatch(dc);
+	    PSDRV_WriteStroke(dc);
+	    PSDRV_WriteGRestore(dc);
+	    break;
+
+	case HS_FDIAGONAL:
+	case HS_DIAGCROSS:
+	    PSDRV_WriteGSave(dc);
+	    PSDRV_Clip(dc, EO);
+	    PSDRV_WriteRotate(dc, -45.0);
+	    PSDRV_WriteHatch(dc);
+	    PSDRV_WriteStroke(dc);
+	    PSDRV_WriteGRestore(dc);
+	    if(brush->logbrush.lbHatch == HS_FDIAGONAL)
+	        break;
+	    /* else fallthrough for HS_DIAGCROSS */
+	    
+	case HS_BDIAGONAL:
+	    PSDRV_WriteGSave(dc);
+	    PSDRV_Clip(dc, EO);
+	    PSDRV_WriteRotate(dc, 45.0);
+	    PSDRV_WriteHatch(dc);
+	    PSDRV_WriteStroke(dc);
+	    PSDRV_WriteGRestore(dc);
+	    break;
+
+	default:
+	    ERR(psdrv, "Unknown hatch style\n");
+	    return FALSE;
+	}
+	return TRUE;
+	break;
+
+    case BS_NULL:
+        return TRUE;
+	break;
+
+    default:
+        return FALSE;
+	break;
+    }
+}
+
+
+
+
diff --git a/graphics/psdrv/font.c b/graphics/psdrv/font.c
index 6a05880..ba73a42 100644
--- a/graphics/psdrv/font.c
+++ b/graphics/psdrv/font.c
@@ -179,6 +179,24 @@
 
 
 /***********************************************************************
+ *           PSDRV_GetCharWidth
+ */
+BOOL32 PSDRV_GetCharWidth( DC *dc, UINT32 firstChar, UINT32 lastChar,
+			   LPINT32 buffer )
+{
+    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
+    UINT32 i;
+
+    TRACE(psdrv, "first = %d last = %d\n", firstChar, lastChar);
+
+    for( i = firstChar; i <= lastChar; i++ )
+        *buffer++ = physDev->font.afm->CharWidths[i] * physDev->font.scale;
+
+    return TRUE;
+}
+
+    
+/***********************************************************************
  *           PSDRV_SetFont
  */
 BOOL32 PSDRV_SetFont( DC *dc )
diff --git a/graphics/psdrv/graphics.c b/graphics/psdrv/graphics.c
index 70a84ce..6d2cceb 100644
--- a/graphics/psdrv/graphics.c
+++ b/graphics/psdrv/graphics.c
@@ -5,10 +5,14 @@
  *
  */
 #include <string.h>
+#include <math.h>
 #include "windows.h"
 #include "psdrv.h"
 #include "debug.h"
 #include "print.h"
+#ifndef PI
+#define PI M_PI
+#endif
 
 /**********************************************************************
  *	     PSDRV_MoveToEx
@@ -27,6 +31,7 @@
     return TRUE;
 }
 
+
 /***********************************************************************
  *           PSDRV_LineTo
  */
@@ -45,11 +50,12 @@
     return TRUE;
 }
 
+
 /***********************************************************************
  *           PSDRV_Rectangle
  */
-BOOL32 PSDRV_Rectangle(DC *dc, INT32 left, INT32 top, INT32 right,
-		       INT32 bottom)
+BOOL32 PSDRV_Rectangle( DC *dc, INT32 left, INT32 top, INT32 right,
+		       INT32 bottom )
 {
     INT32 width = XLSTODS(dc, right - left);
     INT32 height = YLSTODS(dc, bottom - top);
@@ -60,10 +66,7 @@
     PSDRV_WriteRectangle(dc, XLPTODP(dc, left), YLPTODP(dc, top),
 			     width, height);
 
-    PSDRV_SetBrush(dc);
-    PSDRV_Writegsave(dc);
-    PSDRV_WriteFill(dc);
-    PSDRV_Writegrestore(dc);
+    PSDRV_Brush(dc,0);
     PSDRV_SetPen(dc);
     PSDRV_WriteStroke(dc);
     return TRUE;
@@ -71,25 +74,140 @@
 
 
 /***********************************************************************
+ *           PSDRV_RoundRect
+ */
+BOOL32 PSDRV_RoundRect( DC *dc, INT32 left, INT32 top, INT32 right,
+			INT32 bottom, INT32 ell_width, INT32 ell_height )
+{
+    left = XLPTODP( dc, left );
+    right = XLPTODP( dc, right );
+    top = YLPTODP( dc, top );
+    bottom = YLPTODP( dc, bottom );
+    ell_width = XLSTODS( dc, ell_width );
+    ell_height = YLSTODS( dc, ell_height );
+
+    if( left > right ) { INT32 tmp = left; left = right; right = tmp; }
+    if( top > bottom ) { INT32 tmp = top; top = bottom; bottom = tmp; }
+
+    if(ell_width > right - left) ell_width = right - left;
+    if(ell_height > bottom - top) ell_height = bottom - top;
+
+    PSDRV_WriteMoveTo( dc, left, top + ell_height/2 );
+    PSDRV_WriteArc( dc, left + ell_width/2, top + ell_height/2, ell_width,
+		    ell_height, 90.0, 180.0);
+    PSDRV_WriteLineTo( dc, right - ell_width/2, top );
+    PSDRV_WriteArc( dc, right - ell_width/2, top + ell_height/2, ell_width,
+		    ell_height, 0.0, 90.0);
+    PSDRV_WriteLineTo( dc, right, bottom - ell_height/2 );
+    PSDRV_WriteArc( dc, right - ell_width/2, bottom - ell_height/2, ell_width,
+		    ell_height, -90.0, 0.0);
+    PSDRV_WriteLineTo( dc, right - ell_width/2, bottom);
+    PSDRV_WriteArc( dc, left + ell_width/2, bottom - ell_height/2, ell_width,
+		    ell_height, 180.0, -90.0);
+    PSDRV_WriteClosePath( dc );
+
+    PSDRV_Brush(dc,0);
+    PSDRV_SetPen(dc);
+    PSDRV_WriteStroke(dc);
+    return TRUE;
+}
+
+/***********************************************************************
+ *           PSDRV_DrawArc
+ *
+ * Does the work of Arc, Chord and Pie. lines is 0, 1 or 2 respectively.
+ */
+static BOOL32 PSDRV_DrawArc( DC *dc, INT32 left, INT32 top, 
+			     INT32 right, INT32 bottom,
+			     INT32 xstart, INT32 ystart,
+			     INT32 xend, INT32 yend,
+			     int lines )
+{
+    INT32 x, y, h, w;
+    double start_angle, end_angle, ratio;
+
+    x = XLPTODP(dc, (left + right)/2);
+    y = YLPTODP(dc, (top + bottom)/2);
+
+    w = XLSTODS(dc, (right - left));
+    h = YLSTODS(dc, (bottom - top));
+
+    if(w < 0) w = -w;
+    if(h < 0) h = -h;
+    ratio = ((double)w)/h;
+
+    /* angle is the angle after the rectangle is transformed to a square and is
+       measured anticlockwise from the +ve x-axis */
+
+    start_angle = atan2((double)(y - ystart) * ratio, (double)(xstart - x));
+    end_angle = atan2((double)(y - yend) * ratio, (double)(xend - x));
+
+    start_angle *= 180.0 / PI;
+    end_angle *= 180.0 / PI;
+
+    if(lines == 2) /* pie */
+        PSDRV_WriteMoveTo(dc, x, y);
+    PSDRV_WriteArc(dc, x, y, w, h, start_angle, end_angle);
+    if(lines == 1 || lines == 2) { /* chord or pie */
+        PSDRV_WriteClosePath(dc);
+	PSDRV_Brush(dc,0);
+    }
+    PSDRV_SetPen(dc);
+    PSDRV_WriteStroke(dc);
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PSDRV_Arc
+ */
+BOOL32 PSDRV_Arc( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+		  INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return PSDRV_DrawArc( dc, left, top, right, bottom, xstart, ystart,
+			 xend, yend, 0 );
+}
+
+/***********************************************************************
+ *           PSDRV_Chord
+ */
+BOOL32 PSDRV_Chord( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+		  INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return PSDRV_DrawArc( dc, left, top, right, bottom, xstart, ystart,
+			 xend, yend, 1 );
+}
+
+
+/***********************************************************************
+ *           PSDRV_Pie
+ */
+BOOL32 PSDRV_Pie( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+		  INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return PSDRV_DrawArc( dc, left, top, right, bottom, xstart, ystart,
+			 xend, yend, 2 );
+}
+
+
+/***********************************************************************
  *           PSDRV_Ellipse
  */
 BOOL32 PSDRV_Ellipse( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom)
 {
-    INT32 x, y, a, b;
+    INT32 x, y, w, h;
 
     TRACE(psdrv, "%d %d - %d %d\n", left, top, right, bottom);
 
     x = XLPTODP(dc, (left + right)/2);
     y = YLPTODP(dc, (top + bottom)/2);
 
-    a = XLSTODS(dc, (right - left)/2);
-    b = YLSTODS(dc, (bottom - top)/2);
+    w = XLSTODS(dc, (right - left));
+    h = YLSTODS(dc, (bottom - top));
 
-    PSDRV_WriteEllispe(dc, x, y, a, b);
-    PSDRV_SetBrush(dc);
-    PSDRV_Writegsave(dc);
-    PSDRV_WriteFill(dc);
-    PSDRV_Writegrestore(dc);
+    PSDRV_WriteArc(dc, x, y, w, h, 0.0, 360.0);
+    PSDRV_WriteClosePath(dc);
+    PSDRV_Brush(dc,0);
     PSDRV_SetPen(dc);
     PSDRV_WriteStroke(dc);
     return TRUE;
@@ -97,40 +215,92 @@
 
 
 /***********************************************************************
+ *           PSDRV_PolyPolyline
+ */
+BOOL32 PSDRV_PolyPolyline( DC *dc, LPPOINT32 pts, LPDWORD counts,
+			   DWORD polylines )
+{
+    DWORD polyline, line;
+    LPPOINT32 pt;
+    TRACE(psdrv, "\n");
+
+    pt = pts;
+    for(polyline = 0; polyline < polylines; polyline++) {
+        PSDRV_WriteMoveTo(dc, XLPTODP(dc, pt->x), YLPTODP(dc, pt->y));
+	pt++;
+	for(line = 1; line < counts[polyline]; line++) {
+	    PSDRV_WriteLineTo(dc, XLPTODP(dc, pt->x), YLPTODP(dc, pt->y));
+	    pt++;
+	}
+    }
+    PSDRV_SetPen(dc);
+    PSDRV_WriteStroke(dc);
+    return TRUE;
+}   
+
+
+/***********************************************************************
  *           PSDRV_Polyline
  */
 BOOL32 PSDRV_Polyline( DC *dc, const LPPOINT32 pt, INT32 count )
 {
-    INT32 i;
-    TRACE(psdrv, "count = %d\n", count);
-    
+    return PSDRV_PolyPolyline( dc, pt, (LPDWORD) &count, 1 );
+}
+
+
+/***********************************************************************
+ *           PSDRV_PolyPolygon
+ */
+BOOL32 PSDRV_PolyPolygon( DC *dc, LPPOINT32 pts, LPINT32 counts,
+			  UINT32 polygons )
+{
+    DWORD polygon, line;
+    LPPOINT32 pt;
+    TRACE(psdrv, "\n");
+
+    pt = pts;
+    for(polygon = 0; polygon < polygons; polygon++) {
+        PSDRV_WriteMoveTo(dc, XLPTODP(dc, pt->x), YLPTODP(dc, pt->y));
+	pt++;
+	for(line = 1; line < counts[polygon]; line++) {
+	    PSDRV_WriteLineTo(dc, XLPTODP(dc, pt->x), YLPTODP(dc, pt->y));
+	    pt++;
+	}
+	PSDRV_WriteClosePath(dc);
+    }
+
+    if(dc->w.polyFillMode == ALTERNATE)
+        PSDRV_Brush(dc, 1);
+    else /* WINDING */
+        PSDRV_Brush(dc, 0);
     PSDRV_SetPen(dc);
-    PSDRV_WriteMoveTo(dc, XLPTODP(dc, pt[0].x), YLPTODP(dc, pt[0].y));
-    for(i = 1; i < count; i++)
-        PSDRV_WriteLineTo(dc, XLPTODP(dc, pt[i].x), YLPTODP(dc, pt[i].y));
     PSDRV_WriteStroke(dc);
     return TRUE;
 }
 
-
 /***********************************************************************
  *           PSDRV_Polygon
  */
 BOOL32 PSDRV_Polygon( DC *dc, LPPOINT32 pt, INT32 count )
 {
-    INT32 i;
-    TRACE(psdrv, "count = %d\n", count);
-    FIXME(psdrv, "Hack!\n");
-    
-    PSDRV_SetPen(dc);
-    PSDRV_WriteMoveTo(dc, XLPTODP(dc, pt[0].x), YLPTODP(dc, pt[0].y));
-    for(i = 1; i < count; i++)
-        PSDRV_WriteLineTo(dc, XLPTODP(dc, pt[i].x), YLPTODP(dc, pt[i].y));
-
-    if(pt[0].x != pt[count-1].x || pt[0].y != pt[count-1].y)
-        PSDRV_WriteLineTo(dc, XLPTODP(dc, pt[0].x), YLPTODP(dc, pt[0].y));
-
-    PSDRV_WriteStroke(dc);
-    return TRUE;
+     return PSDRV_PolyPolygon( dc, pt, &count, 1 );
 }
 
+
+/***********************************************************************
+ *           PSDRV_SetPixel
+ */
+COLORREF PSDRV_SetPixel( DC *dc, INT32 x, INT32 y, COLORREF color )
+{
+    PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
+    PSCOLOR pscolor;
+
+    x = XLPTODP(dc, x);
+    y = YLPTODP(dc, y);
+
+    PSDRV_WriteRectangle( dc, x, y, 0, 0 );
+    PSDRV_CreateColor( physDev, &pscolor, color );
+    PSDRV_WriteSetColor( dc, &pscolor );
+    PSDRV_WriteFill( dc );
+    return color;
+}
diff --git a/graphics/psdrv/init.c b/graphics/psdrv/init.c
index cc43a6d..55d4d81 100644
--- a/graphics/psdrv/init.c
+++ b/graphics/psdrv/init.c
@@ -20,9 +20,9 @@
 
 static const DC_FUNCTIONS PSDRV_Funcs =
 {
-    NULL,                            /* pArc */
+    PSDRV_Arc,                       /* pArc */
     NULL,                            /* pBitBlt */
-    NULL,                            /* pChord */
+    PSDRV_Chord,                     /* pChord */
     PSDRV_CreateDC,                  /* pCreateDC */
     PSDRV_DeleteDC,                  /* pDeleteDC */
     NULL,                            /* pDeleteObject */
@@ -33,7 +33,7 @@
     NULL,                            /* pExcludeVisRect */
     NULL,                            /* pExtFloodFill */
     PSDRV_ExtTextOut,                /* pExtTextOut */
-    NULL,                            /* pGetCharWidth */
+    PSDRV_GetCharWidth,              /* pGetCharWidth */
     NULL,                            /* pGetPixel */
     PSDRV_GetTextExtentPoint,        /* pGetTextExtentPoint */
     PSDRV_GetTextMetrics,            /* pGetTextMetrics */
@@ -46,16 +46,16 @@
     NULL,                            /* pOffsetWindowOrg (optional) */
     NULL,                            /* pPaintRgn */
     NULL,                            /* pPatBlt */
-    NULL,                            /* pPie */
-    NULL,                            /* pPolyPolygon */
-    NULL,                            /* pPolyPolyline */
+    PSDRV_Pie,                       /* pPie */
+    PSDRV_PolyPolygon,               /* pPolyPolygon */
+    PSDRV_PolyPolyline,              /* pPolyPolyline */
     PSDRV_Polygon,                   /* pPolygon */
     PSDRV_Polyline,                  /* pPolyline */
     NULL,                            /* pPolyBezier */		     
     NULL,                            /* pRealizePalette */
     PSDRV_Rectangle,                 /* pRectangle */
     NULL,                            /* pRestoreDC */
-    NULL,                            /* pRoundRect */
+    PSDRV_RoundRect,                 /* pRoundRect */
     NULL,                            /* pSaveDC */
     NULL,                            /* pScaleViewportExt (optional) */
     NULL,                            /* pScaleWindowExt (optional) */
@@ -68,7 +68,7 @@
     NULL,                            /* pSetDIBitsToDevice */
     NULL,                            /* pSetMapMode (optional) */
     NULL,                            /* pSetMapperFlags */
-    NULL,                            /* pSetPixel */
+    PSDRV_SetPixel,                  /* pSetPixel */
     NULL,                            /* pSetPolyFillMode */
     NULL,                            /* pSetROP2 */
     NULL,                            /* pSetRelAbs */
@@ -82,7 +82,7 @@
     NULL,                            /* pSetWindowExt (optional) */
     NULL,                            /* pSetWindowOrg (optional) */
     NULL,                            /* pStretchBlt */
-    NULL                             /* pStretchDIBits */
+    PSDRV_StretchDIBits              /* pStretchDIBits */
 };
 
 
diff --git a/graphics/psdrv/ps.c b/graphics/psdrv/ps.c
index d301c36..b972d68 100644
--- a/graphics/psdrv/ps.c
+++ b/graphics/psdrv/ps.c
@@ -35,15 +35,24 @@
 
 static char psprolog[] = /* output ANSIEncoding vector first */
 "/reencodefont {\n"
-"findfont\n"
-"dup length dict begin\n"
-"{1 index /FID ne {def} {pop pop} ifelse} forall\n"
-"/Encoding ANSIEncoding def\n"
-"currentdict\n"
-"end\n"
-"definefont pop\n"
+"  findfont\n"
+"  dup length dict begin\n"
+"  {1 index /FID ne {def} {pop pop} ifelse} forall\n"
+"  /Encoding ANSIEncoding def\n"
+"  currentdict\n"
+"  end\n"
+"  definefont pop\n"
 "} bind def\n"
-"/tmpmtrx matrix def\n";
+"/tmpmtrx matrix def\n"
+"/hatch {\n"
+"  pathbbox\n"
+"  /b exch def /r exch def /t exch def /l exch def /gap 32 def\n"
+"  l cvi gap idiv gap mul\n"
+"  gap\n"
+"  r cvi gap idiv gap mul\n"
+"  {t moveto 0 b t sub rlineto}\n"
+"  for\n"
+"} bind def\n";
 
 static char psbeginsetup[] =
 "%%BeginSetup\n";
@@ -116,11 +125,11 @@
 static char pssetrgbcolor[] = /* r, g, b */
 "%.2f %.2f %.2f setrgbcolor\n";
 
-static char psellipse[] = /* x, y, a, b */
+static char psarc[] = /* x, y, w, h, ang1, ang2 */
 "tmpmtrx currentmatrix pop\n"
 "%d %d translate\n"
 "%d %d scale\n"
-"0 0 1 0 360 arc\n"
+"0 0 0.5 %.1f %.1f arc\n"
 "tmpmtrx setmatrix\n";
 
 static char psgsave[] =
@@ -132,6 +141,24 @@
 static char psfill[] =
 "fill\n";
 
+static char pseofill[] =
+"eofill\n";
+
+static char psclosepath[] =
+"closepath\n";
+
+static char psclip[] =
+"clip\n";
+
+static char pseoclip[] =
+"eoclip\n";
+
+static char pshatch[] =
+"hatch\n";
+
+static char psrotate[] = /* ang */
+"%.1f rotate\n";
+
 char *PSDRV_ANSIVector[256] = {
 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
@@ -454,11 +481,14 @@
     return PSDRV_WriteSpool(dc, buf, strlen(buf));
 }
 
-BOOL32 PSDRV_WriteEllispe(DC *dc, INT32 x, INT32 y, INT32 a, INT32 b)
+BOOL32 PSDRV_WriteArc(DC *dc, INT32 x, INT32 y, INT32 w, INT32 h, double ang1,
+		      double ang2)
 {
     char buf[256];
 
-    sprintf(buf, psellipse, x, y, a, b);
+    /* Make angles -ve and swap order because we're working with an upside
+       down y-axis */
+    sprintf(buf, psarc, x, y, w, h, -ang2, -ang1);
     return PSDRV_WriteSpool(dc, buf, strlen(buf));
 }
 
@@ -618,17 +648,47 @@
     return PSDRV_WriteSpool(dc, psfill, sizeof(psfill)-1);
 }
 
-BOOL32 PSDRV_Writegsave(DC *dc)
+BOOL32 PSDRV_WriteEOFill(DC *dc)
+{
+    return PSDRV_WriteSpool(dc, pseofill, sizeof(pseofill)-1);
+}
+
+BOOL32 PSDRV_WriteGSave(DC *dc)
 {
     return PSDRV_WriteSpool(dc, psgsave, sizeof(psgsave)-1);
 }
 
-BOOL32 PSDRV_Writegrestore(DC *dc)
+BOOL32 PSDRV_WriteGRestore(DC *dc)
 {
     return PSDRV_WriteSpool(dc, psgrestore, sizeof(psgrestore)-1);
 }
 
+BOOL32 PSDRV_WriteClosePath(DC *dc)
+{
+    return PSDRV_WriteSpool(dc, psclosepath, sizeof(psclosepath)-1);
+}
 
+BOOL32 PSDRV_WriteClip(DC *dc)
+{
+    return PSDRV_WriteSpool(dc, psclip, sizeof(psclip)-1);
+}
 
+BOOL32 PSDRV_WriteEOClip(DC *dc)
+{
+    return PSDRV_WriteSpool(dc, pseoclip, sizeof(pseoclip)-1);
+}
+
+BOOL32 PSDRV_WriteHatch(DC *dc)
+{
+    return PSDRV_WriteSpool(dc, pshatch, sizeof(pshatch)-1);
+}
+
+BOOL32 PSDRV_WriteRotate(DC *dc, float ang)
+{
+    char buf[256];
+
+    sprintf(buf, psrotate, ang);
+    return PSDRV_WriteSpool(dc, buf, strlen(buf));
+}