From f5b2fcf2065fc0ca0ec769e08ae4c3fa0d24db3d Mon Sep 17 00:00:00 2001
From: jdishaw <jim@dishaw.org>
Date: Mon, 2 Mar 2015 01:37:32 -0500
Subject: [PATCH] Revised implementation of plot metafiles

- Disabled (for now) handling of the alternative unicode processing in
src/plbuf.c because it was badly implemented.  Currently only the
cairo driver uses the alternative unicode processing and it handles
its own redraws.

- Changed src/plmetafile.c to handle scaling from the metafile coordinate
system to the device coordinate system.

- Changed src/plmetafile.c, drivers/plmeta.c, and src/plbuf.c to correctly
handle the PLESC_HAS_TEXT function.
  -- Required state information is written/read from the metafiles
  -- The plot buffer will correctly process the state information
---
 drivers/plmeta.c   |  124 ++++++++++++
 include/metadefs.h |    7 +-
 src/plbuf.c        |  255 ++++++++++++-------------
 src/plmetafile.c   |  538 +++++++++++++++++++++++++++-------------------------
 4 files changed, 524 insertions(+), 400 deletions(-)

diff --git a/drivers/plmeta.c b/drivers/plmeta.c
index 489742f..2df848b 100644
--- a/drivers/plmeta.c
+++ b/drivers/plmeta.c
@@ -61,6 +61,7 @@ static void WritePageInfo( PLStream *pls, FPOS_T pp_offset );
 static void UpdateIndex( PLStream *pls, FPOS_T cp_offset );
 static void plm_fill( PLStream *pls );
 static void plm_swin( PLStream *pls );
+static void plm_text( PLStream *pls, EscText *args );
 
 // A little function to help with debugging
 
@@ -121,6 +122,17 @@ plD_init_plm( PLStream *pls )
     pls->dev_fill0 = 1;         // Handle solid fills
     pls->dev_fill1 = 1;         // Driver handles pattern fills
 
+    // NOTE:  This breaks compatibility with the 2005 version of
+    // the plot metafile format
+#define NEW_METAFILE
+#ifdef NEW_METAFILE
+    pls->dev_text    = 1;       // Enable text handling by the driver
+    pls->dev_unicode = 1;       // Enable unicode support
+#else
+    pls->dev_text    = 0;       // Disable text handling by the driver
+    pls->dev_unicode = 0;       // Disable unicode support
+#endif
+
 // Initialize family file info
 
     plFamInit( pls );
@@ -435,6 +447,22 @@ plD_esc_plm( PLStream *pls, PLINT op, void *ptr )
     case PLESC_SWIN:
         plm_swin( pls );
         break;
+
+    // Unicode and non-Unicode text handling
+    case PLESC_HAS_TEXT:
+        plm_text( pls, (EscText *) ptr );
+        break;
+
+    // Alternate unicode text handling
+    case PLESC_BEGIN_TEXT:
+    case PLESC_TEXT_CHAR:
+    case PLESC_CONTROL_CHAR:
+    case PLESC_END_TEXT:
+        // NOP these for now until a decision is made
+        // which method should be implemented for metafiles
+        plwarn("plmeta: Alternate Unicode text handling is not implemented");
+        break;
+
     }
 }
 
@@ -479,6 +507,102 @@ plm_swin( PLStream *pls )
 }
 
 //--------------------------------------------------------------------------
+// plm_text()
+//
+// Stores the text into the metafile.
+//--------------------------------------------------------------------------
+
+static void
+plm_text( PLStream *pls, EscText *args )
+{
+    PLmDev *dev = (PLmDev *) pls->dev;
+
+    /*
+    PLINT base;   // ref point at base(1) or center(0) of text. Currently plplot only use 0
+    PLFLT just;   // continuos justification, 0 left, 0.5 center, 1 right
+    PLFLT *xform; // transformation (rotation) matrix
+    PLINT x;      // raw reference point--after any transformation
+    PLINT y;
+    PLINT refx;   // processed ref. point--after justification, displacement, etc, processing
+    PLINT refy;
+    char  font_face; // font face OPTIONALLY used for rendering hershey codes
+    // The following 3 fields are used by the alternative text handling pathway.
+    // See drivers/cairo.h for details about how this works.
+    PLUNICODE n_fci;          // font storage for unicode font handling
+    PLUNICODE n_char;         // character storage for unicode font handling
+    PLINT     n_ctrl_char;    // control character code storage for unicode font handling
+    PLUNICODE unicode_char;   // an int to hold either a Hershey, ASC-II, or Unicode value for plsym calls
+    PLUNICODE *unicode_array; // a pointer to an array of ints holding either a Hershey, ASC-II, or Unicode value for cached plsym
+    unsigned short unicode_array_len;
+    const char *string;       // text to draw
+    */
+
+    // Write state information needed to render the text
+
+    plm_wr( pdf_wr_ieeef( pls->pdfs, pls->chrht ) );
+    plm_wr( pdf_wr_ieeef( pls->pdfs, pls->diorot ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpxmi ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpxma ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpymi ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, pls->clpyma ) );
+
+    //  Write the text layout information
+
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->base ) );
+    plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->just ) );
+  
+    // Do we have a rotation shear that needs to be saved
+    if( args->xform != NULL ) {
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[0] ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[1] ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[2] ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) args->xform[3] ) );
+    } else {
+        plwarn("plmeta: transformation matrix undefined, using a guess");
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 1.0 ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 0.0 ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 1.0 ) );
+        plm_wr( pdf_wr_ieeef( pls->pdfs, (float) 1.0 ) );
+    }
+
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->x ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->y ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->refx ) );
+    plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->refy ) );
+    plm_wr( pdf_wr_1byte( pls->pdfs, (U_CHAR) args->font_face ) );
+
+    // Are we in Unicode mode?
+    if( pls->dev_unicode ) {
+        PLINT i;
+	PLUNICODE fci;
+  
+	// Get the font characterization integer and write it
+	plgfci( &fci );
+	plm_wr( pdf_wr_4bytes( pls->pdfs, fci ) );
+
+	// Store the text
+	plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) args->unicode_array_len ) );
+
+	// PLplot uses a UTF-32 representation of Unicode characters,
+	// so we need to write 4 bytes for each character
+	for( i = 0; i < args->unicode_array_len; i++ ) {
+	  plm_wr( pdf_wr_4bytes( pls->pdfs, (U_LONG) args->unicode_array[i] ) );
+	}
+    } else {
+        PLINT len;
+
+	len = strlen( args->string );
+        plm_wr( pdf_wr_2bytes( pls->pdfs, (U_SHORT) len ) );
+	if ( len > 0 )
+	    plm_wr( pdf_wr_string( pls->pdfs, args->string ) );
+    }
+
+    // Clear the last known position
+    dev->xold = PL_UNDEFINED;
+    dev->yold = PL_UNDEFINED;
+}
+
+//--------------------------------------------------------------------------
 // Provide a consistent method for handling a failed fsetpos.
 //--------------------------------------------------------------------------
 static void
diff --git a/include/metadefs.h b/include/metadefs.h
index 427b581..a8f1603 100644
--- a/include/metadefs.h
+++ b/include/metadefs.h
@@ -95,7 +95,8 @@ typedef struct
     PLINT   version;    // Metafile version number
     U_SHORT page;       // Current page
 
-    // Viewport configuration. Used to render a metafile
-    PLFLT   vpxmin, vpymin;
-    PLFLT   vpxmax, vpymax;
+    // Metafile coordinates to physical (virtual pixels) coordinates 
+    // transformation
+    PLFLT   mfpcxa, mfpcxb;    // x = mfpcxa * x + mfpcxb
+    PLFLT   mfpcya, mfpcyb;    // y = mfpcya * y + mfpcyb
 } PLmDev;
diff --git a/src/plbuf.c b/src/plbuf.c
index 31c2d1f..4c48d06 100644
--- a/src/plbuf.c
+++ b/src/plbuf.c
@@ -320,37 +320,51 @@ plbuf_image( PLStream *pls, IMG_DT *img_dt )
 static void
 plbuf_text( PLStream *pls, EscText *text )
 {
-    PLUNICODE fci;
-
     dbug_enter( "plbuf_text" );
 
-    // Retrieve the font characterization integer
-    plgfci( &fci );
-
-    // Write the text information
-
-    wr_data( pls, &fci, sizeof ( PLUNICODE ) );
-
-    wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
-
-    wr_data( pls, &text->base, sizeof ( PLINT ) );
-    wr_data( pls, &text->just, sizeof ( PLFLT ) );
-    wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
-    wr_data( pls, &text->x, sizeof ( PLINT ) );
-    wr_data( pls, &text->y, sizeof ( PLINT ) );
-    wr_data( pls, &text->refx, sizeof ( PLINT ) );
-    wr_data( pls, &text->refy, sizeof ( PLINT ) );
-
-    wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
-    if ( text->unicode_array_len )
-        wr_data( pls,
-            text->unicode_array,
-            sizeof ( PLUNICODE ) * text->unicode_array_len );
+    // Store the state information needed to render the text
+
+    wr_data( pls, &pls->chrht, sizeof ( pls->chrht ) );
+    wr_data( pls, &pls->diorot, sizeof ( pls->diorot ) );
+    wr_data( pls, &pls->clpxmi, sizeof ( pls->clpxmi ) );
+    wr_data( pls, &pls->clpxma, sizeof ( pls->clpxma ) );
+    wr_data( pls, &pls->clpymi, sizeof ( pls->clpymi ) );
+    wr_data( pls, &pls->clpyma, sizeof ( pls->clpyma ) );
+
+    // Store the text layout information
+    
+    wr_data( pls, &text->base, sizeof ( text->base ) );
+    wr_data( pls, &text->just, sizeof ( text->just ) );
+    wr_data( pls, text->xform, sizeof ( text->xform[0] ) * 4 );
+    wr_data( pls, &text->x, sizeof ( text->x ) );
+    wr_data( pls, &text->y, sizeof ( text->y ) );
+    wr_data( pls, &text->refx, sizeof ( text->refx ) );
+    wr_data( pls, &text->refy, sizeof ( text->refy ) );
+    wr_data( pls, &text->font_face, sizeof ( text->font_face ) );
+
+    // Store the text
+
+    if( pls->dev_unicode ) {
+        PLUNICODE fci;
+  
+        // Retrieve and store the font characterization integer
+	plgfci( &fci );
+
+	wr_data( pls, &fci, sizeof ( fci ) );
+
+	wr_data( pls, &text->unicode_array_len, sizeof ( U_SHORT ) );
+	if ( text->unicode_array_len )
+	    wr_data( pls,
+		     text->unicode_array,
+		     sizeof ( PLUNICODE ) * text->unicode_array_len );
+    } else {
+        U_SHORT len;
+  
+	len = strlen( text->string );
+	wr_data( pls, &len, sizeof ( len ) );
+	if( len > 0 )
+	  wr_data( pls, (void *) text->string, sizeof( char ) * len );
+    }
 }
 
 //--------------------------------------------------------------------------
@@ -364,35 +378,7 @@ plbuf_text_unicode( PLStream *pls, EscText *text )
 {
     PLUNICODE fci;
 
-    dbug_enter( "plbuf_text" );
-
-    // Retrieve the font characterization integer
-    plgfci( &fci );
-
-    // Write the text information
-
-    wr_data( pls, &fci, sizeof ( PLUNICODE ) );
-
-    wr_data( pls, &pls->chrht, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->diorot, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
-    wr_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
-
-    wr_data( pls, &text->base, sizeof ( PLINT ) );
-    wr_data( pls, &text->just, sizeof ( PLFLT ) );
-    wr_data( pls, text->xform, sizeof ( PLFLT ) * 4 );
-    wr_data( pls, &text->x, sizeof ( PLINT ) );
-    wr_data( pls, &text->y, sizeof ( PLINT ) );
-    wr_data( pls, &text->refx, sizeof ( PLINT ) );
-    wr_data( pls, &text->refy, sizeof ( PLINT ) );
-
-    wr_data( pls, &text->n_fci, sizeof ( PLUNICODE ) );
-    wr_data( pls, &text->n_char, sizeof ( PLUNICODE ) );
-    wr_data( pls, &text->n_ctrl_char, sizeof ( PLINT ) );
-
-    wr_data( pls, &text->unicode_array_len, sizeof ( PLINT ) );
+    dbug_enter( "plbuf_text_unicode" );
 }
 
 
@@ -427,22 +413,33 @@ plbuf_esc( PLStream *pls, PLINT op, void *ptr )
     case PLESC_FILL:
         plbuf_fill( pls );
         break;
+
     case PLESC_SWIN:
         plbuf_swin( pls, (PLWindow *) ptr );
         break;
+
     case PLESC_IMAGE:
         plbuf_image( pls, (IMG_DT *) ptr );
         break;
+
+    // Unicode and non-Unicode text handling
     case PLESC_HAS_TEXT:
         if ( ptr != NULL ) // Check required by GCW driver, please don't remove
             plbuf_text( pls, (EscText *) ptr );
         break;
+
+    // Alternate Unicode text handling
     case PLESC_BEGIN_TEXT:
     case PLESC_TEXT_CHAR:
     case PLESC_CONTROL_CHAR:
     case PLESC_END_TEXT:
-        plbuf_text_unicode( pls, (EscText *) ptr );
+        // The alternative unicode processing is not correctly implemented
+        // and is currently only used by Cairo, which handles its own
+        // redraws.  Skip further processing for now
+
+        //plbuf_text_unicode( pls, (EscText *) ptr );
         break;
+
     case PLESC_IMPORT_BUFFER:
         buffer = (plbuffer *) ptr;
         if ( buffer->size > pls->plbuf_buffer_size )
@@ -822,7 +819,10 @@ rdbuf_esc( PLStream *pls )
     case PLESC_TEXT_CHAR:
     case PLESC_CONTROL_CHAR:
     case PLESC_END_TEXT:
-        rdbuf_text_unicode( op, pls );
+        // Disable for now because alternative unicode processing is
+        // not correctly implemented
+
+        //rdbuf_text_unicode( op, pls );
         break;
     case PLESC_IMPORT_BUFFER:
         // Place holder until an appropriate action is determined.
@@ -954,61 +954,82 @@ rdbuf_swin( PLStream *pls )
 //--------------------------------------------------------------------------
 // rdbuf_text()
 //
-// Draw PostScript text.
+// Render text through the driver.
 //--------------------------------------------------------------------------
 
 static void
 rdbuf_text( PLStream *pls )
 {
-    PLUNICODE( fci );
     EscText  text;
     PLFLT    xform[4];
-    PLUNICODE* unicode;
 
     dbug_enter( "rdbuf_text" );
 
     text.xform = xform;
 
-    // Read in the data
-    rd_data( pls, &fci, sizeof ( PLUNICODE ) );
-
-    rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
-
-    rd_data( pls, &text.base, sizeof ( PLINT ) );
-    rd_data( pls, &text.just, sizeof ( PLFLT ) );
-    rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
-    rd_data( pls, &text.x, sizeof ( PLINT ) );
-    rd_data( pls, &text.y, sizeof ( PLINT ) );
-    rd_data( pls, &text.refx, sizeof ( PLINT ) );
-    rd_data( pls, &text.refy, sizeof ( PLINT ) );
-
-    rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
-
-    // Initialize to NULL so we don't accidentally try to free the memory
-    text.unicode_array = NULL;
-    if ( text.unicode_array_len )
-    {
-        if ( ( unicode = (PLUNICODE *) malloc( text.unicode_array_len * sizeof ( PLUNICODE ) ) )
-             == NULL )
-            plexit( "rdbuf_text: Insufficient memory" );
+    // Read the state information
 
-        rd_data( pls, unicode, sizeof ( PLUNICODE ) * text.unicode_array_len );
-        text.unicode_array = unicode;
-    }
-    else
-        text.unicode_array = NULL;
+    rd_data( pls, &pls->chrht, sizeof ( pls->chrht ) );
+    rd_data( pls, &pls->diorot, sizeof ( pls->diorot ) );
+    rd_data( pls, &pls->clpxmi, sizeof ( pls->clpxmi ) );
+    rd_data( pls, &pls->clpxma, sizeof ( pls->clpxma ) );
+    rd_data( pls, &pls->clpymi, sizeof ( pls->clpymi ) );
+    rd_data( pls, &pls->clpyma, sizeof ( pls->clpyma ) );
 
-    // Make the call for unicode devices
-    if ( pls->dev_unicode )
-    {
+    // Read the text layout information
+
+    rd_data( pls, &text.base, sizeof ( text.base ) );
+    rd_data( pls, &text.just, sizeof ( text.just ) );
+    rd_data( pls, text.xform, sizeof ( text.xform[0] ) * 4 );
+    rd_data( pls, &text.x, sizeof ( text.x ) );
+    rd_data( pls, &text.y, sizeof ( text.y ) );
+    rd_data( pls, &text.refx, sizeof ( text.refx ) );
+    rd_data( pls, &text.refy, sizeof ( text.refy ) );
+    rd_data( pls, &text.font_face, sizeof ( text.font_face ) );
+
+    // Read in the text
+    if( pls->dev_unicode ) {
+	PLUNICODE  fci ;
+
+	rd_data( pls, &fci, sizeof ( fci ) );
         plsfci( fci );
-        plP_esc( PLESC_HAS_TEXT, &text );
+
+	rd_data( pls, &text.unicode_array_len, sizeof ( U_SHORT ) );
+	if ( text.unicode_array_len )
+	{
+	    // Set the pointer to the unicode data in the buffer.  This avoids
+            // allocating and freeing memory
+	    rd_data_no_copy( 
+		pls,
+	        (void **) ( &text.unicode_array ), 
+		sizeof ( PLUNICODE ) * text.unicode_array_len );
+	}
+	else
+	{
+	    text.unicode_array = NULL;
+	}
     }
+    else 
+    {
+        U_SHORT len;
+	
+	rd_data( pls, &len, sizeof ( len ) );
+	if( len > 0 )
+	{
+	    // Set the pointer to the string data in the buffer.  This avoids
+            // allocating and freeing memory
+	    rd_data_no_copy( 
+		pls,
+	        (void **) ( &text.string ), 
+		sizeof ( char ) * len );
+	}
+	else
+	{
+	    text.string = NULL;
+	}
+    }
+
+    plP_esc( PLESC_HAS_TEXT, &text );
 }
 
 //--------------------------------------------------------------------------
@@ -1020,44 +1041,8 @@ rdbuf_text( PLStream *pls )
 static void
 rdbuf_text_unicode( PLINT op, PLStream *pls )
 {
-    PLUNICODE( fci );
-    EscText text;
-    PLFLT   xform[4];
-
     dbug_enter( "rdbuf_text_unicode" );
 
-    text.xform = xform;
-
-    // Read in the data
-
-    rd_data( pls, &fci, sizeof ( PLUNICODE ) );
-
-    rd_data( pls, &pls->chrht, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->diorot, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpxmi, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpxma, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpymi, sizeof ( PLFLT ) );
-    rd_data( pls, &pls->clpyma, sizeof ( PLFLT ) );
-
-    rd_data( pls, &text.base, sizeof ( PLINT ) );
-    rd_data( pls, &text.just, sizeof ( PLFLT ) );
-    rd_data( pls, text.xform, sizeof ( PLFLT ) * 4 );
-    rd_data( pls, &text.x, sizeof ( PLINT ) );
-    rd_data( pls, &text.y, sizeof ( PLINT ) );
-    rd_data( pls, &text.refx, sizeof ( PLINT ) );
-    rd_data( pls, &text.refy, sizeof ( PLINT ) );
-
-    rd_data( pls, &text.n_fci, sizeof ( PLUNICODE ) );
-    rd_data( pls, &text.n_char, sizeof ( PLUNICODE ) );
-    rd_data( pls, &text.n_ctrl_char, sizeof ( PLINT ) );
-
-    rd_data( pls, &text.unicode_array_len, sizeof ( PLINT ) );
-
-    if ( pls->dev_unicode )
-    {
-        plsfci( fci );
-        plP_esc( op, &text );
-    }
 }
 
 //--------------------------------------------------------------------------
diff --git a/src/plmetafile.c b/src/plmetafile.c
index dc2afe7..81e46f1 100644
--- a/src/plmetafile.c
+++ b/src/plmetafile.c
@@ -32,6 +32,9 @@
 
 #define MAX_BUFFER    256 // Character buffer size for reading records
 
+// Placeholder until decision into which header file this goes into
+void plbuf_write( PLStream *pls, void *data, size_t bytes );
+
 // Status codes
 enum _plm_status
 {
@@ -63,7 +66,8 @@ enum _plp_types
     PLP_USHORT,
     PLP_SHORT,
     PLP_PLINT,
-    PLP_PLFLT
+    PLP_PLFLT,
+    PLP_ULONG,
 };
 
 // Data format entry structure
@@ -153,6 +157,9 @@ enum _plm_status set_ubyte_plp_value( uint8_t x,
     case PLP_PLFLT:
         *(PLFLT *) dest = x;
         break;
+    case PLP_ULONG:
+        *(U_LONG *) dest = x;
+	break;
     default:
         plwarn( "Unhandled datatype conversion in set_plp_value." );
         rc = PLM_UNKNOWN_DATATYPE;
@@ -190,6 +197,9 @@ enum _plm_status set_ushort_plp_value( U_SHORT x,
     case PLP_PLFLT:
         *(PLFLT *) dest = x;
         break;
+    case PLP_ULONG:
+        *(U_LONG *) dest = x;
+	break;
     default:
         plwarn( "Unhandled datatype conversion in set_plp_value." );
         rc = PLM_UNKNOWN_DATATYPE;
@@ -227,6 +237,9 @@ enum _plm_status set_ulong_plp_value( unsigned long x,
     case PLP_PLFLT:
         *(PLFLT *) dest = x;
         break;
+    case PLP_ULONG:
+        *(U_LONG *) dest = x;
+	break;
     default:
         plwarn( "Unhandled datatype conversion in set_plp_value." );
         rc = PLM_UNKNOWN_DATATYPE;
@@ -264,6 +277,9 @@ enum _plm_status set_ieeef_plp_value( float x,
     case PLP_PLFLT:
         *(PLFLT *) dest = x;
         break;
+    case PLP_ULONG:
+        *(U_LONG *) dest = x;
+	break;
     default:
         plwarn( "Unhandled datatype conversion in set_plp_value." );
         rc = PLM_UNKNOWN_DATATYPE;
@@ -407,30 +423,38 @@ enum _plm_status read_header( PDFstrm *plm,
 static
 enum _plm_status read_line( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
-    PLFLT            x_list[2], y_list[2];
+    PLFLT            x1, y1, x2, y2;
+    short            xy_list[4];
     enum _plm_status rc;
 
     // Read the start and end points
     // The metafile stores the points as x,y pairs
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[0] );  // x1
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x1 );
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[0] );  // y1
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y1 );
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[1] );  // x2
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x2 );
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[1] );  // y2
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y2 );
     if ( rc != PLM_SUCCESS )
         return rc;
 
-    // Draw the line
-    plline( 2, x_list, y_list );
+    // Transform the coordinates from the meta device to the current
+    // device coordinate system
+    xy_list[0] = (short)lround( dev->mfpcxa * x1 + dev->mfpcxb );
+    xy_list[2] = (short)lround( dev->mfpcya * y1 + dev->mfpcyb );
+    xy_list[1] = (short)lround( dev->mfpcxa * x2 + dev->mfpcxb );
+    xy_list[3] = (short)lround( dev->mfpcya * y2 + dev->mfpcyb );
+    
+    // Put the coordinates into the plot buffer
+    plbuf_write( pls, xy_list, sizeof(xy_list) );
 
     // Preserve the last XY coords for the LINETO command
-    dev->xold = (short) x_list[1];
-    dev->yold = (short) y_list[1];
+    dev->xold = (short) xy_list[1];
+    dev->yold = (short) xy_list[3];
 
     return PLM_SUCCESS;
 }
@@ -443,34 +467,40 @@ enum _plm_status read_line( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 static
 enum _plm_status read_lineto( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
-    PLFLT            x_list[2], y_list[2];
+    PLFLT            x2, y2;
+    short            xy_list[4];
     int              i;
     enum _plm_status rc;
 
     // Set the start to the last known position
-    x_list[0] = (PLFLT) dev->xold;
-    y_list[0] = (PLFLT) dev->yold;
+    xy_list[0] = (PLFLT) dev->xold;
+    xy_list[2] = (PLFLT) dev->yold;
 
     // Read the end point
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x_list[1] );
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x2 );
     if ( rc != PLM_SUCCESS )
         return rc;
-    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y_list[1] );
+    rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y2 );
     if ( rc != PLM_SUCCESS )
         return rc;
 
-    // Draw the line
-    plline( 2, x_list, y_list );
+    // Transform the coordinates from the meta device to the current
+    // device coordinate system
+    xy_list[1] = (short)lround( dev->mfpcxa * x2 + dev->mfpcxb );
+    xy_list[3] = (short)lround( dev->mfpcya * y2 + dev->mfpcyb );
+    
+    // Put the coordinates into the plot buffer
+    plbuf_write( pls, xy_list, sizeof(xy_list) );
 
     // Preserve the last XY coords for the LINETO command
-    dev->xold = (short) x_list[1];
-    dev->yold = (short) y_list[1];
+    dev->xold = (short) xy_list[1];
+    dev->yold = (short) xy_list[1];
 
     return PLM_SUCCESS;
 }
 
 //--------------------------------------------------------------------------
-// read_lineto()
+// read_polyline()
 //
 // Process a POLYLINE command from the metafile
 //--------------------------------------------------------------------------
@@ -478,49 +508,49 @@ static
 enum _plm_status read_polyline( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 {
     PLINT            i, npts;
-    PLFLT            *x_list, *y_list;
+    PLFLT            x, y;
+    short            xd, yd;
     enum _plm_status rc;
 
-    // Read the number of control points
+    // Read the number of control points and put into the plot buffer
     rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &npts );
     if ( rc != PLM_SUCCESS )
         return rc;
 
-    // Not optimal to alloc/dealloc memory, but it works for now
-    if ( ( x_list = malloc( npts * sizeof ( PLFLT ) ) ) == NULL )
-    {
-        plexit( "read_polyline: Unable to allocate memory\n" );
-    }
-    if ( ( y_list = malloc( npts * sizeof ( PLFLT ) ) ) == NULL )
-    {
-        plexit( "read_polyline: Unable to allocate memory\n" );
-    }
+    plbuf_write( pls, &npts, sizeof(npts) );
 
     // Read the points and insert into the plot buffer
     // The x values
     for ( i = 0; i < npts; i++ )
     {
-        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, x_list + i );
+        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x );
         if ( rc != PLM_SUCCESS )
             return rc;
+
+	// Transform the coordinates from the meta device to the current
+	// device coordinate system
+	xd = (short)lround( dev->mfpcxa * x + dev->mfpcxb );
+
+	plbuf_write( pls, &xd, sizeof(xd) );
     }
+    // Preserve the last X value for the LINETO command
+    dev->xold = xd;
+
     // The y values
     for ( i = 0; i < npts; i++ )
     {
-        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, y_list + i );
+        rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y );
         if ( rc != PLM_SUCCESS )
             return rc;
-    }
 
-    // Draw the line
-    plline( npts, x_list, y_list );
+	// Transform the coordinates from the meta device to the current
+	// device coordinate system
+	yd = (short)lround( dev->mfpcya * y + dev->mfpcyb );
 
-    // Preserve the last X coord for the LINETO command
-    dev->xold = (short) x_list[npts - 1];
-    dev->yold = (short) y_list[npts - 1];
-
-    free( x_list );
-    free( y_list );
+	plbuf_write( pls, &yd, sizeof(yd) );
+    }
+    // Preserve the last Y value for the LINETO command
+    dev->yold = yd;
 
     return PLM_SUCCESS;
 }
@@ -540,43 +570,42 @@ enum _plm_status read_escape( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     if ( pdf_rd_1byte( plm, &op ) != 0 )
         return PLM_FORMAT_ERROR;
 
+    // Put this operation into the plot buffer
+    plbuf_write( pls, &op, sizeof(op) );
+
     switch ( op )
     {
     case PLESC_FILL:
     {
         PLINT i, npts;
-        PLFLT *x_list, *y_list;
+	PLFLT x, y;
+	short xy[2];
 
         // Get the number of control points for the fill
         rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &npts );
         if ( rc != PLM_SUCCESS )
             return rc;
 
-        // Not optimal to alloc/dealloc memory, but it works for now
-        if ( ( x_list = malloc( npts * sizeof ( PLFLT ) ) ) == NULL )
-        {
-            plexit( "read_escape: Unable to allocate memory\n" );
-        }
-        if ( ( y_list = malloc( npts * sizeof ( PLFLT ) ) ) == NULL )
-        {
-            plexit( "read_escape: Unable to allocate memory\n" );
-        }
+	// Write the number of control points into the plot buffer
+	plbuf_write( pls, &npts, sizeof(npts) );
 
         for ( i = 0; i < npts; i++ )
         {
-            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, x_list + i );
+            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x );
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, y_list + i );
+            rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y );
             if ( rc != PLM_SUCCESS )
                 return rc;
-        }
 
-        plfill( npts, x_list, y_list );
+	    // Transform the coordinates from the meta device to the current
+	    // device coordinate system
+	    xy[0] = (short)lround( dev->mfpcxa * x + dev->mfpcxb );
+	    xy[1] = (short)lround( dev->mfpcya * y + dev->mfpcyb );
 
-        free( x_list );
-        free( y_list );
+	    plbuf_write( pls, xy, sizeof(xy) );
+        }
     }
     break;
 
@@ -584,6 +613,101 @@ enum _plm_status read_escape( PDFstrm *plm, PLmDev *dev, PLStream *pls )
         rc = PLM_SUCCESS;
         break;
 
+
+    // Unicode and non-Unicode text handling
+    case PLESC_HAS_TEXT:
+    {
+        EscText   text;
+	PLFLT     xform[4];
+        PLUNICODE fci, ch;
+	PLINT     i;
+	PLFLT     xmin, xmax, ymin, ymax;
+	PLFLT     x, y, refx, refy;
+
+	// Setup storage for the transformation matrix
+	text.xform = xform;
+
+	// Read the information from the metafile
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &pls->chrht );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &pls->diorot );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &xmin );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &xmax );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &ymin );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &ymax );
+
+	rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &text.base );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &text.just );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &text.xform[0] );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &text.xform[1] );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &text.xform[2] );
+	rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &text.xform[3] );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &x );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &y );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &refx );
+	rc = read_entry( plm, PDF_USHORT, PLP_PLFLT, &refy );
+	rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &text.font_face );
+
+	// Translate coordinates to the device coordinate system
+
+	pls->clpxmi = (short)lround( dev->mfpcxa * xmin + dev->mfpcxb );
+	pls->clpxma = (short)lround( dev->mfpcxa * xmax + dev->mfpcxb );
+	pls->clpymi = (short)lround( dev->mfpcxa * ymin + dev->mfpcxb );
+	pls->clpyma = (short)lround( dev->mfpcxa * ymax + dev->mfpcxb );
+
+	text.x = (short)lround( dev->mfpcxa * x + dev->mfpcxb );
+	text.y = (short)lround( dev->mfpcya * y + dev->mfpcyb );
+	text.refx = (short)lround( dev->mfpcxa * refx + dev->mfpcxb );
+	text.refy = (short)lround( dev->mfpcya * refy + dev->mfpcyb );
+
+	// Copy the information that the buffer expects
+
+	plbuf_write( pls, &pls->chrht, sizeof ( pls->chrht ) );
+	plbuf_write( pls, &pls->diorot, sizeof ( pls->diorot) );
+	plbuf_write( pls, &pls->clpxmi, sizeof ( pls->clpxmi ) );
+	plbuf_write( pls, &pls->clpxma, sizeof ( pls->clpxma ) );
+	plbuf_write( pls, &pls->clpymi, sizeof ( pls->clpymi ) );
+	plbuf_write( pls, &pls->clpyma, sizeof ( pls->clpyma ) );
+	
+	plbuf_write( pls, &text.base, sizeof ( text.base ) );
+	plbuf_write( pls, &text.just, sizeof ( text.just ) );
+	plbuf_write( pls, text.xform, sizeof ( text.xform[0] ) * 4 );
+	plbuf_write( pls, &text.x, sizeof ( text.x ) );
+	plbuf_write( pls, &text.y, sizeof ( text.y ) );
+	plbuf_write( pls, &text.refx, sizeof ( text.refx ) );
+	plbuf_write( pls, &text.refy, sizeof ( text.refy ) );
+	plbuf_write( pls, &text.font_face, sizeof( text.font_face ) );
+
+	// Metafiles use Unicode strings, so store the data needed to
+	// handle Unicode strings
+
+        // Retrieve the font characterization integer
+	rc = read_entry( plm, PDF_ULONG, PLP_ULONG, &fci );
+	plbuf_write( pls, &fci, sizeof ( fci ) );
+
+	// Retrieve the text
+	rc = read_entry( plm, PDF_USHORT, PLP_USHORT, &text.unicode_array_len );
+	plbuf_write( pls, &text.unicode_array_len, sizeof ( U_SHORT ) );
+
+	for(i = 0; i < text.unicode_array_len; i++) {
+	    rc = read_entry( plm, PDF_ULONG, PLP_ULONG, &ch );
+	    plbuf_write( pls, &ch, sizeof ( PLUNICODE ));
+	}
+	
+    }
+    rc = PLM_SUCCESS;
+    break;
+
+    // Alternate unicode text handling
+    case PLESC_BEGIN_TEXT:
+    case PLESC_TEXT_CHAR:
+    case PLESC_CONTROL_CHAR:
+    case PLESC_END_TEXT:
+        // NOP these for now until a decision is made
+        // which method should be implemented for metafiles
+        plwarn("plmetafile: Alternate Unicode text handling is not implemented");
+	rc = PLM_INVALID_CMD;
+        break;
+
     default:
         break;
     }
@@ -606,6 +730,9 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
     if ( pdf_rd_1byte( plm, &op ) != 0 )
         return PLM_FORMAT_ERROR;
 
+    // Write the operation to the plot buffer
+    plbuf_write( pls, &op, sizeof(op) );
+
     switch ( op )
     {
     case PLSTATE_WIDTH:
@@ -618,12 +745,13 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            plwidth( width );
+	    plbuf_write( pls, &width, sizeof(width) );
         }
         break;
 
     case PLSTATE_COLOR0:
-        pldebug( "state: COLOR0" );
+    case PLSTATE_COLOR1:
+        pldebug( "state: COLOR0/COLOR1" );
 
         {
             PLINT icol;
@@ -633,9 +761,13 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            if ( icol == PL_RGB_COLOR )
+	    // Write the color index value to the plot buffer
+	    plbuf_write( pls, &icol, sizeof(icol) );
+
+	    // Was pen 0 set to an RGB value rather than color index?
+            if ( op == PLSTATE_COLOR0 && icol == PL_RGB_COLOR )
             {
-                // Set pen 0 to the specified RGB value
+                // Get the RGB value and copy to the plot buffer
                 PLColor color;
 
                 rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.r );
@@ -653,94 +785,29 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
                 color.a    = 1.0;
                 color.name = NULL;
 
-                plscol0( icol, color.r, color.g, color.b );
-            }
-            else
-            {
-                // Set color for pen 0
-                plcol0( icol );
+		plbuf_write( pls, &color, sizeof(color) );
             }
         }
         break;
 
-    case PLSTATE_COLOR1:
-        pldebug( "state: COLOR1" );
-
-        {
-            PLINT icol;
-
-            // Read the color index number
-            rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &icol );
-            if ( rc != PLM_SUCCESS )
-                return rc;
-
-            plcol1( icol );
-        }
-        break;
-
     case PLSTATE_FILL:
         pldebug( "state: FILL" );
 
         {
             U_CHAR pattern;
 
-            // Read the color index number
+            // Read the pattern and put into the plot buffer
             rc = read_entry( plm, PDF_USHORT, PLP_UCHAR, &pattern );
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            plpsty( pattern );
+	    plbuf_write( pls, &pattern, sizeof(pattern) );
         }
         break;
 
     case PLSTATE_CMAP0:
-        pldebug( "state: CMAP0" );
-
-        {
-            PLINT   i, ncol;
-            PLColor color;
-
-            // Read the number of colors
-            rc = read_entry( plm, PDF_USHORT, PLP_PLINT, &ncol );
-            if ( rc != PLM_SUCCESS )
-                return rc;
-
-            // Set the number of colors in the colormap
-            plscmap0n( ncol );
-
-            // Read the colormap
-            for ( i = 0; i < ncol; i++ )
-            {
-                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.r );
-                if ( rc != PLM_SUCCESS )
-                    return rc;
-
-                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.g );
-                if ( rc != PLM_SUCCESS )
-                    return rc;
-
-                rc = read_entry( plm, PDF_UBYTE, PLP_UCHAR, &color.b );
-                if ( rc != PLM_SUCCESS )
-                    return rc;
-
-                color.a    = 1.0;
-                color.name = NULL;
-
-                // Save the color for this entry
-                plsc->cmap0[i].r    = color.r;
-                plsc->cmap0[i].g    = color.g;
-                plsc->cmap0[i].b    = color.b;
-                plsc->cmap0[i].a    = color.a;
-                plsc->cmap0[i].name = color.name;
-            }
-
-            if ( plsc->level > 0 )
-                plP_state( PLSTATE_CMAP0 );
-        }
-        break;
-
     case PLSTATE_CMAP1:
-        pldebug( "state: CMAP0" );
+        pldebug( "state: CMAP0/CMAP1" );
 
         {
             PLINT   i, ncol;
@@ -751,8 +818,8 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             if ( rc != PLM_SUCCESS )
                 return rc;
 
-            // Set the number of colors in the colormap
-            plscmap1n( ncol );
+	    // Put the number of colors into the plot buffer
+	    plbuf_write( pls, &ncol, sizeof(ncol) );
 
             // Read the colormap
             for ( i = 0; i < ncol; i++ )
@@ -772,27 +839,16 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
                 color.a    = 1.0;
                 color.name = NULL;
 
-                // Save the color for this entry
-                plsc->cmap1[i].r    = color.r;
-                plsc->cmap1[i].g    = color.g;
-                plsc->cmap1[i].b    = color.b;
-                plsc->cmap1[i].a    = color.a;
-                plsc->cmap1[i].name = color.name;
+		plbuf_write( pls, &color, sizeof(color) );
             }
-
-            if ( plsc->level > 0 )
-                plP_state( PLSTATE_CMAP1 );
         }
         break;
 
     case PLSTATE_CHR:
         pldebug( "state: CHR" );
 
-        // Note: The operation is not put into the buffer because
-        // this operation is not supported in the 2005 format.
-        // This code is a placeholder until a new version is made
-        // Put the command into the plot buffer
-
+	// The 2005 version and earlier do not support this
+	// operation, so put in the current value
         if ( 0 )
         {
             PLFLT chrdef;
@@ -805,17 +861,22 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &chrht );
             if ( rc != PLM_SUCCESS )
                 return rc;
+
+	    plbuf_write( pls, &chrdef, sizeof(chrdef) );
+	    plbuf_write( pls, &chrht, sizeof(chrht) );
         }
+	else 
+	{
+	    plbuf_write( pls, &pls->chrdef, sizeof(pls->chrdef) );
+	    plbuf_write( pls, &pls->chrht, sizeof(pls->chrht) );
+	}
         break;
 
     case PLSTATE_SYM:
         pldebug( "state: SYM" );
 
-        // Note: The operation is not put into the buffer because
-        // this operation is not supported in the 2005 format.
-        // This code is a placeholder until a new version is made
-        // Put the command into the plot buffer
-
+	// The 2005 version and earlier do not support this
+	// operation, so put in the current value
         if ( 0 )
         {
             PLFLT symdef;
@@ -828,7 +889,15 @@ enum _plm_status read_state( PDFstrm *plm, PLmDev *dev, PLStream *pls )
             rc = read_entry( plm, PDF_IEEEF, PLP_PLFLT, &symht );
             if ( rc != PLM_SUCCESS )
                 return rc;
+
+	    plbuf_write( pls, &symdef, sizeof(symdef) );
+	    plbuf_write( pls, &symht, sizeof(symht) );
         }
+	else 
+	{
+	    plbuf_write( pls, &pls->symdef, sizeof(pls->symdef) );
+	    plbuf_write( pls, &pls->symht, sizeof(pls->symht) );
+	}
         break;
 
     default:
@@ -861,7 +930,10 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
         {
         case INITIALIZE:
             pldebug( "cmd: INITIALIZE" );
-            // No action needed
+
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             break;
 
         case CLOSE:
@@ -871,13 +943,20 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 
         case EOP:
             pldebug( "cmd: EOP" );
-            // No action needed
+
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             break;
 
         case BOP:
         case BOP0:                   // First BOP in a file
             pldebug( "cmd: BOP/BOP0" );
 
+	    // Put the command into the plot buffer
+	    cmd = BOP;
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             // Read the metadata for this page
             rc = read_entry( plm,
                 page_2005_header[0].pdf_type,
@@ -901,46 +980,56 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
                 break;
 
 
-            // Setup the subwindows
-            //plP_ssub( pls->nsubx, pls->nsuby, pls->cursub );
-            plP_setsub();
-
-            plvpor(
-                dev->vpxmin, dev->vpxmax,
-                dev->vpymin, dev->vpymax );
-            plwind(
-                (PLFLT) dev->xmin, (PLFLT) dev->xmax,
-                (PLFLT) dev->ymin, (PLFLT) dev->ymax );
+	    // Push state information into the plot buffer
+	    plbuf_write( pls, &(pls->icol0), sizeof(pls->icol0) );
+	    plbuf_write( pls, &(pls->icol1), sizeof(pls->icol1) );
+	    plbuf_write( pls, &(pls->curcolor), sizeof(pls->curcolor) );
 
             break;
 
         case LINE:
             pldebug( "cmd: LINE" );
 
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+	    
             rc = read_line( plm, dev, pls );
             break;
 
         case LINETO:
             pldebug( "cmd: LINETO" );
 
+	    // Put the command into the plot buffer
+	    cmd = LINE;
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             rc = read_lineto( plm, dev, pls );
             break;
 
         case ESCAPE:
             pldebug( "cmd: ESCAPE" );
 
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             rc = read_escape( plm, dev, pls );
             break;
 
         case POLYLINE:
             pldebug( "cmd: POLYLINE" );
 
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             rc = read_polyline( plm, dev, pls );
             break;
 
         case CHANGE_STATE:
             pldebug( "cmd: CHANGE_STATE" );
 
+	    // Put the command into the plot buffer
+	    plbuf_write( pls, &cmd, sizeof(cmd) );
+
             rc = read_state( plm, dev, pls );
             break;
 
@@ -974,86 +1063,16 @@ enum _plm_status read_plot_commands( PDFstrm *plm, PLmDev *dev, PLStream *pls )
 }
 
 static
-void setup_page( PLmDev *dev )
+void setup_page( PLmDev *mf_dev, PLStream *pls )
 {
-    PLFLT aspect;
-    PLINT dev_xmin, dev_ymin;
-    PLINT dev_xmax, dev_ymax;
-    PLINT dev_xlen, dev_ylen;
-    PLFLT dev_xpmm, dev_ypmm;
-    PLFLT dev_aspect;
-    PLFLT ratio;
-    PLFLT vpxlen, vpylen;
-    PLINT nsubx, nsuby, cursub;
-
-    // Determine the current subpage
-    plP_gsub( &nsubx, &nsuby, &cursub );
-
-    // Are we on a valid subpage?
-    if ( cursub == 0 || cursub > nsubx * nsuby )
-    {
-        // No, it appears that the current subpage is unintialized or the
-        // subpage is not valid for the current supbage configuration
-        cursub = 1;
-
-        // Set the subpage information
-        plP_ssub( nsubx, nsuby, cursub );
-        plP_setsub();
-    }
-
-    // Set aspect ratio to the natural ratio of the metafile coordinate system.
-
-    // For older versions of plplot, the length is not set.  Do it here
-    // just in case.
-    dev->xlen = dev->xmax - dev->xmin;
-    dev->ylen = dev->ymax - dev->ymin;
-
-    // Aspect ration of the plot metafile
-    aspect = ( ( (PLFLT) dev->ylen ) / dev->pxly )
-             / ( ( (PLFLT) dev->xlen ) / dev->pxlx );
-
-    // Aspect ratio of the current output device
-    plP_gphy( &dev_xmin, &dev_xmax, &dev_ymin, &dev_ymax );
-    plP_gpixmm( &dev_xpmm, &dev_ypmm );
-
-    dev_xlen = dev_xmax - dev_xmin;
-    dev_ylen = dev_ymax - dev_ymin;
-
-    dev_aspect = ( ( (PLFLT) dev_ylen ) / dev_ypmm )
-                 / ( ( (PLFLT) dev_xlen ) / dev_xpmm );
-
-    if ( dev_aspect <= 0. )
-        fprintf( stderr, "Aspect ratio error: dev_aspect = %f\n", dev_aspect );
-
-    ratio = aspect / dev_aspect;
-
-    // Default relative coordinate space
-    vpxlen      = 1.0;
-    vpylen      = 1.0;
-    dev->vpxmin = 0.5 - vpxlen / 2.;
-    dev->vpymin = 0.5 - vpylen / 2.;
-    dev->vpxmax = dev->vpxmin + vpxlen;
-    dev->vpymax = dev->vpymin + vpylen;
-
-    //
-    // Construct viewport that preserves the aspect ratio of the original
-    // device (plmeta output file).  Thus you automatically get all physical
-    // coordinate plots to come out correctly.  Note: this could also be done
-    // using the driver interface function plsdimap.
-    //
-
-    if ( ratio <= 0 )
-        fprintf( stderr, "Aspect ratio error: ratio = %f\n", ratio );
-    else if ( ratio < 1 )
-        vpylen = ratio;
-    else
-        vpxlen = 1. / ratio;
-
-    dev->vpxmin = ( 1. - vpxlen ) / 2.;
-    dev->vpxmax = dev->vpxmin + vpxlen;
-
-    dev->vpymin = ( 1. - vpylen ) / 2.;
-    dev->vpymax = dev->vpymin + vpylen;
+    PLmDev *dev = pls->dev;
+
+    mf_dev->mfpcxa = (PLFLT) dev->xlen 
+        / (PLFLT)( mf_dev->xmax - mf_dev->xmin );
+    mf_dev->mfpcxb = (PLFLT) dev->xmin;
+    mf_dev->mfpcya = (PLFLT) dev->ylen 
+        / (PLFLT)( mf_dev->ymax - mf_dev->ymin );
+    mf_dev->mfpcyb = (PLFLT) dev->ymin;
 }
 
 //--------------------------------------------------------------------------
@@ -1076,7 +1095,7 @@ void plreadmetafile( char *infile )
 {
     PDFstrm          *plm;
     PLStream         mf_pls;
-    PLmDev           dev;
+    PLmDev           mf_dev;
     PLmIndex         index;
     enum _plm_status rc;
 
@@ -1098,7 +1117,7 @@ void plreadmetafile( char *infile )
     }
 
     // Read the file header
-    if ( ( rc = read_metafile_header( plm, &dev ) ) != PLM_SUCCESS )
+    if ( ( rc = read_metafile_header( plm, &mf_dev ) ) != PLM_SUCCESS )
     {
         pdf_close( plm );
         plwarn( "Failed to parse PLplot metafile, ignoring file." );
@@ -1107,7 +1126,7 @@ void plreadmetafile( char *infile )
 
     // Read the index header
     rc = read_header( plm,
-        metafile_format[dev.version].index_header,
+        metafile_format[mf_dev.version].index_header,
         (U_CHAR *) &index );
     if ( rc != PLM_SUCCESS )
     {
@@ -1118,8 +1137,8 @@ void plreadmetafile( char *infile )
 
     // Read the device header
     rc = read_header( plm,
-        metafile_format[dev.version].device_header,
-        (U_CHAR *) &dev );
+        metafile_format[mf_dev.version].device_header,
+        (U_CHAR *) &mf_dev );
     if ( rc != PLM_SUCCESS )
     {
         pdf_close( plm );
@@ -1133,7 +1152,7 @@ void plreadmetafile( char *infile )
     // (e.g. xlength = 0).  The plspage() call should be smart enough
     // to setup the page correctly.
     rc = read_header( plm,
-        metafile_format[dev.version].plot_header,
+        metafile_format[mf_dev.version].plot_header,
         (U_CHAR *) &mf_pls );
     if ( rc != PLM_SUCCESS )
     {
@@ -1142,23 +1161,16 @@ void plreadmetafile( char *infile )
         return;
     }
 
-    // Set the physical characterisics of the output device if the current
-    // stream has not been initialized
-    if ( plsc->level == 0 )
-    {
-        plspage( mf_pls.xdpi, mf_pls.ydpi,
-            mf_pls.xlength, mf_pls.ylength,
-            mf_pls.xoffset, mf_pls.yoffset );
-
+    // Is the plot stream initialized?
+    if( plsc->level == 0 ) {
+        // No, we must intialize it in order to get the
+        // device configuation set
         plinit();
     }
-
-    // Configure the plot match the configuration used when the plot
-    // was created
-    setup_page( &dev );
+    setup_page( &mf_dev, plsc);
 
     // At this point we should be in the plot commands
-    rc = read_plot_commands( plm, &dev, plsc );
+    rc = read_plot_commands( plm, &mf_dev, plsc );
     if ( rc != PLM_SUCCESS )
     {
         pdf_close( plm );
@@ -1167,4 +1179,6 @@ void plreadmetafile( char *infile )
     }
 
     pdf_close( plm );
+
+    plreplot();
 }
-- 
1.7.10.4

