]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/ogl/src/drawn.cpp
OGL fixes for wxMotif; added Set/GetClientData to wxMenu in wxMSW/wxMotif/wxStubs.
[wxWidgets.git] / utils / ogl / src / drawn.cpp
index b9a6cb8102df2f54881f9174214d016a230e67c6..e5ea9c82ce64da79b63bf01fdfb7f5f0e2e3b1ac 100644 (file)
@@ -11,6 +11,7 @@
 
 #ifdef __GNUG__
 #pragma implementation "drawn.h"
+#pragma implementation "drawnp.h"
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
@@ -24,9 +25,7 @@
 #include <wx/wx.h>
 #endif
 
-#ifdef PROLOGIO
 #include <wx/wxexpr.h>
-#endif
 
 #include "basic.h"
 #include "basicp.h"
@@ -38,7 +37,7 @@
 
 static void IntToHex(unsigned int dec, char *buf);
 static unsigned long HexToInt(char *buf);
-extern char *GraphicsBuffer;
+extern char *oglBuffer;
 
 #define gyTYPE_PEN   40
 #define gyTYPE_BRUSH 41
@@ -49,11 +48,12 @@ extern char *GraphicsBuffer;
  *
  */
 
-IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape, wxShape)
+IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape, wxRectangleShape)
 
 wxDrawnShape::wxDrawnShape():wxRectangleShape(100.0, 50.0)
 {
   m_saveToFile = TRUE;
+  m_currentAngle = oglDRAWN_ANGLE_0;
 }
 
 wxDrawnShape::~wxDrawnShape()
@@ -67,22 +67,22 @@ void wxDrawnShape::OnDraw(wxDC& dc)
   if (m_shadowMode != SHADOW_NONE)
   {
     if (m_shadowBrush)
-      m_metafile.m_fillBrush = m_shadowBrush;
-    m_metafile.m_outlinePen = transparent_pen;
-    m_metafile.Draw(dc, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
+      m_metafiles[m_currentAngle].m_fillBrush = m_shadowBrush;
+    m_metafiles[m_currentAngle].m_outlinePen = g_oglTransparentPen;
+    m_metafiles[m_currentAngle].Draw(dc, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
   }
     
-  m_metafile.m_outlinePen = m_pen;
-  m_metafile.m_fillBrush = m_brush;
-  m_metafile.Draw(dc, m_xpos, m_ypos);
+  m_metafiles[m_currentAngle].m_outlinePen = m_pen;
+  m_metafiles[m_currentAngle].m_fillBrush = m_brush;
+  m_metafiles[m_currentAngle].Draw(dc, m_xpos, m_ypos);
 }
 
-void wxDrawnShape::SetSize(float w, float h, bool recursive)
+void wxDrawnShape::SetSize(double w, double h, bool recursive)
 {
   SetAttachmentSize(w, h);
 
-  float scaleX;
-  float scaleY;
+  double scaleX;
+  double scaleY;
   if (GetWidth() == 0.0)
     scaleX = 1.0;
   else scaleX = w/GetWidth();
@@ -90,74 +90,185 @@ void wxDrawnShape::SetSize(float w, float h, bool recursive)
     scaleY = 1.0;
   else scaleY = h/GetHeight();
 
-  m_metafile.Scale(scaleX, scaleY);
+  int i = 0;
+  for (i = 0; i < 4; i++)
+  {
+    if (m_metafiles[i].IsValid())
+        m_metafiles[i].Scale(scaleX, scaleY);
+  }
   m_width = w;
   m_height = h;
   SetDefaultRegionSize();
 }
 
-void wxDrawnShape::Scale(float sx, float sy)
+void wxDrawnShape::Scale(double sx, double sy)
 {
-  m_metafile.Scale(sx, sy);
+    int i;
+    for (i = 0; i < 4; i++)
+    {
+        if (m_metafiles[i].IsValid())
+        {
+            m_metafiles[i].Scale(sx, sy);
+            m_metafiles[i].CalculateSize(this);
+        }
+    }
 }
 
-void wxDrawnShape::Translate(float x, float y)
+void wxDrawnShape::Translate(double x, double y)
 {
-  m_metafile.Translate(x, y);
+    int i;
+    for (i = 0; i < 4; i++)
+    {
+        if (m_metafiles[i].IsValid())
+        {
+            m_metafiles[i].Translate(x, y);
+            m_metafiles[i].CalculateSize(this);
+        }
+    }
 }
 
-void wxDrawnShape::Rotate(float x, float y, float theta)
+// theta is absolute rotation from the zero position
+void wxDrawnShape::Rotate(double x, double y, double theta)
 {
-  if (!m_metafile.GetRotateable())
-    return;
+  m_currentAngle = DetermineMetaFile(theta);
+
+  if (m_currentAngle == 0)
+  {
+    // Rotate metafile
+    if (!m_metafiles[0].GetRotateable())
+      return;
     
-  float actualTheta = theta-m_metafile.m_currentRotation;
+    m_metafiles[0].Rotate(x, y, theta);
+  }
 
-  // Rotate metafile
-  m_metafile.Rotate(x, y, theta);
+  double actualTheta = theta-m_rotation;
 
   // Rotate attachment points
-  float sinTheta = (float)sin(actualTheta);
-  float cosTheta = (float)cos(actualTheta);
+  double sinTheta = (double)sin(actualTheta);
+  double cosTheta = (double)cos(actualTheta);
   wxNode *node = m_attachmentPoints.First();
   while (node)
   {
     wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
-    float x1 = point->m_x;
-    float y1 = point->m_y;
-    point->m_x = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
-    point->m_y = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
+    double x1 = point->m_x;
+    double y1 = point->m_y;
+    point->m_x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+    point->m_y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
     node = node->Next();
   }
   m_rotation = theta;
+
+  m_metafiles[m_currentAngle].CalculateSize(this);
 }
 
-#ifdef PROLOGIO
-// Prolog database stuff
-char *wxDrawnShape::GetFunctor()
+// Which metafile do we use now? Based on current rotation and validity
+// of metafiles.
+
+int wxDrawnShape::DetermineMetaFile(double rotation)
+{
+    double tolerance = 0.0001;
+    const double pi = 3.1415926535897932384626433832795 ;
+    double angle1 = 0.0;
+    double angle2 = pi/2.0;
+    double angle3 = pi;
+    double angle4 = 3.0*pi/2.0;
+
+    int whichMetafile = 0;
+
+    if (oglRoughlyEqual(rotation, angle1, tolerance))
+    {
+        whichMetafile = 0;
+    }
+    else if (oglRoughlyEqual(rotation, angle2, tolerance))
+    {
+        whichMetafile = 1;
+    }
+    else if (oglRoughlyEqual(rotation, angle3, tolerance))
+    {
+        whichMetafile = 2;
+    }
+    else if (oglRoughlyEqual(rotation, angle4, tolerance))
+    {
+        whichMetafile = 3;
+    }
+
+    if ((whichMetafile > 0) && !m_metafiles[whichMetafile].IsValid())
+        whichMetafile = 0;
+
+    return whichMetafile;
+}
+
+void wxDrawnShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
 {
-  return "node_image";
+    if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
+    {
+        wxNode* node = m_metafiles[m_currentAngle].GetOps().Nth(m_metafiles[m_currentAngle].GetOutlineOp());
+        wxASSERT (node != NULL);
+        wxDrawOp* op = (wxDrawOp*) node->Data();
+
+        if (op->OnDrawOutline(dc, x, y, w, h, m_width, m_height))
+            return;
+    }
+
+    // Default... just use a rectangle
+    wxRectangleShape::OnDrawOutline(dc, x, y, w, h);
 }
 
-void wxDrawnShape::WritePrologAttributes(wxExpr *clause)
+// Get the perimeter point using the special outline op, if there is one,
+// otherwise use default wxRectangleShape scheme
+bool wxDrawnShape::GetPerimeterPoint(double x1, double y1,
+                                     double x2, double y2,
+                                     double *x3, double *y3)
 {
-  wxRectangleShape::WritePrologAttributes(clause);
+    if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
+    {
+        wxNode* node = m_metafiles[m_currentAngle].GetOps().Nth(m_metafiles[m_currentAngle].GetOutlineOp());
+        wxASSERT (node != NULL);
+        wxDrawOp* op = (wxDrawOp*) node->Data();
 
+        if (op->GetPerimeterPoint(x1, y1, x2, y2, x3, y3, GetX(), GetY(), GetAttachmentMode()))
+            return TRUE;
+    }
+
+    // Default... just use a rectangle
+    return wxRectangleShape::GetPerimeterPoint(x1, y1, x2, y2, x3, y3);
+}
+
+#ifdef PROLOGIO
+void wxDrawnShape::WriteAttributes(wxExpr *clause)
+{
+  wxRectangleShape::WriteAttributes(clause);
+
+  clause->AddAttributeValue("current_angle", (long)m_currentAngle);
   clause->AddAttributeValue("save_metafile", (long)m_saveToFile);
   if (m_saveToFile)
-    m_metafile.WritePrologAttributes(clause);
+  {
+    int i = 0;
+    for (i = 0; i < 4; i++)
+    {
+        if (m_metafiles[i].IsValid())
+            m_metafiles[i].WriteAttributes(clause, i);
+    }
+  }
 }
 
-void wxDrawnShape::ReadPrologAttributes(wxExpr *clause)
+void wxDrawnShape::ReadAttributes(wxExpr *clause)
 {
-  wxRectangleShape::ReadPrologAttributes(clause);
+  wxRectangleShape::ReadAttributes(clause);
 
   int iVal = (int) m_saveToFile;
-  clause->AssignAttributeValue("save_metafile", &iVal);
+  clause->GetAttributeValue("save_metafile", iVal);
+  clause->GetAttributeValue("current_angle", m_currentAngle);
   m_saveToFile = (iVal != 0);
 
   if (m_saveToFile)
-    m_metafile.ReadPrologAttributes(clause);
+  {
+    int i = 0;
+    for (i = 0; i < 4; i++)
+    {
+      m_metafiles[i].ReadAttributes(clause, i);
+    }
+  }
 }
 #endif
 
@@ -170,15 +281,127 @@ void wxDrawnShape::Copy(wxShape& copy)
 
   wxDrawnShape& drawnCopy = (wxDrawnShape&) copy;
 
-  m_metafile.Copy(drawnCopy.m_metafile);
+  int i = 0;
+  for (i = 0; i < 4; i++)
+  {
+    m_metafiles[i].Copy(drawnCopy.m_metafiles[i]);
+  }
   drawnCopy.m_saveToFile = m_saveToFile;
+  drawnCopy.m_currentAngle = m_currentAngle;
 }
 
 bool wxDrawnShape::LoadFromMetaFile(char *filename)
 {
-  return m_metafile.LoadFromMetaFile(filename, &m_width, &m_height);
+  return m_metafiles[0].LoadFromMetaFile(filename, &m_width, &m_height);
+}
+
+// Set of functions for drawing into a pseudo metafile.
+// They use integers, but doubles are used internally for accuracy
+// when scaling.
+
+void wxDrawnShape::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
+{
+    m_metafiles[m_currentAngle].DrawLine(pt1, pt2);
+}
+
+void wxDrawnShape::DrawRectangle(const wxRect& rect)
+{
+    m_metafiles[m_currentAngle].DrawRectangle(rect);
+}
+
+void wxDrawnShape::DrawRoundedRectangle(const wxRect& rect, double radius)
+{
+    m_metafiles[m_currentAngle].DrawRoundedRectangle(rect, radius);
+}
+
+void wxDrawnShape::DrawEllipse(const wxRect& rect)
+{
+    m_metafiles[m_currentAngle].DrawEllipse(rect);
+}
+
+void wxDrawnShape::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
+{
+    m_metafiles[m_currentAngle].DrawArc(centrePt, startPt, endPt);
+}
+
+void wxDrawnShape::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
+{
+    m_metafiles[m_currentAngle].DrawEllipticArc(rect, startAngle, endAngle);
+}
+
+void wxDrawnShape::DrawPoint(const wxPoint& pt)
+{
+    m_metafiles[m_currentAngle].DrawPoint(pt);
+}
+
+void wxDrawnShape::DrawText(const wxString& text, const wxPoint& pt)
+{
+    m_metafiles[m_currentAngle].DrawText(text, pt);
+}
+
+void wxDrawnShape::DrawLines(int n, wxPoint pts[])
+{
+    m_metafiles[m_currentAngle].DrawLines(n, pts);
+}
+
+void wxDrawnShape::DrawPolygon(int n, wxPoint pts[], int flags)
+{
+    if (flags & oglMETAFLAGS_ATTACHMENTS)
+    {
+        ClearAttachments();
+        int i;
+        for (i = 0; i < n; i++)
+            m_attachmentPoints.Append(new wxAttachmentPoint(i, pts[i].x, pts[i].y));
+    }
+    m_metafiles[m_currentAngle].DrawPolygon(n, pts, flags);
+}
+
+void wxDrawnShape::DrawSpline(int n, wxPoint pts[])
+{
+    m_metafiles[m_currentAngle].DrawSpline(n, pts);
+}
+
+void wxDrawnShape::SetClippingRect(const wxRect& rect)
+{
+    m_metafiles[m_currentAngle].SetClippingRect(rect);
+}
+
+void wxDrawnShape::DestroyClippingRect()
+{
+    m_metafiles[m_currentAngle].DestroyClippingRect();
+}
+
+void wxDrawnShape::SetDrawnPen(wxPen* pen, bool isOutline)
+{
+    m_metafiles[m_currentAngle].SetPen(pen, isOutline);
+}
+
+void wxDrawnShape::SetDrawnBrush(wxBrush* brush, bool isFill)
+{
+    m_metafiles[m_currentAngle].SetBrush(brush, isFill);
+}
+
+void wxDrawnShape::SetDrawnFont(wxFont* font)
+{
+    m_metafiles[m_currentAngle].SetFont(font);
+}
+
+void wxDrawnShape::SetDrawnTextColour(const wxColour& colour)
+{
+    m_metafiles[m_currentAngle].SetTextColour(colour);
+}
+
+void wxDrawnShape::SetDrawnBackgroundColour(const wxColour& colour)
+{
+    m_metafiles[m_currentAngle].SetBackgroundColour(colour);
 }
 
+void wxDrawnShape::SetDrawnBackgroundMode(int mode)
+{
+    m_metafiles[m_currentAngle].SetBackgroundMode(mode);
+}
+
+
 /*
  * Individual operations
  *
@@ -192,27 +415,27 @@ bool wxDrawnShape::LoadFromMetaFile(char *filename)
 wxOpSetGDI::wxOpSetGDI(int theOp, wxPseudoMetaFile *theImage, int theGdiIndex, int theMode):
   wxDrawOp(theOp)
 {
-  gdiIndex = theGdiIndex;
-  image = theImage;
-  mode = theMode;
+  m_gdiIndex = theGdiIndex;
+  m_image = theImage;
+  m_mode = theMode;
 }
 
-void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
+void wxOpSetGDI::Do(wxDC& dc, double xoffset, double yoffset)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_SET_PEN:
     {
       // Check for overriding this operation for outline
       // colour
-      if (image->m_outlineColours.Member((wxObject *)gdiIndex))
+      if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
       {
-        if (image->m_outlinePen)
-          dc.SetPen(image->m_outlinePen);
+        if (m_image->m_outlinePen)
+          dc.SetPen(m_image->m_outlinePen);
       }
       else
       {
-        wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
+        wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
         if (node)
         {
           wxPen *pen = (wxPen *)node->Data();
@@ -226,26 +449,26 @@ void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
     {
       // Check for overriding this operation for outline or fill
       // colour
-      if (image->m_outlineColours.Member((wxObject *)gdiIndex))
+      if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
       {
         // Need to construct a brush to match the outline pen's colour
-        if (image->m_outlinePen)
+        if (m_image->m_outlinePen)
         {
-          wxBrush *br = wxTheBrushList->FindOrCreateBrush(image->m_outlinePen->GetColour(), wxSOLID);
+          wxBrush *br = wxTheBrushList->FindOrCreateBrush(m_image->m_outlinePen->GetColour(), wxSOLID);
           if (br)
             dc.SetBrush(br);
         }
       }
-      else if (image->m_fillColours.Member((wxObject *)gdiIndex))
+      else if (m_image->m_fillColours.Member((wxObject *)m_gdiIndex))
       {
-        if (image->m_fillBrush)
+        if (m_image->m_fillBrush)
         {
-          dc.SetBrush(image->m_fillBrush);
+          dc.SetBrush(m_image->m_fillBrush);
         }
       }
       else
       {
-        wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
+        wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
         if (node)
         {
           wxBrush *brush = (wxBrush *)node->Data();
@@ -257,7 +480,7 @@ void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
     }
     case DRAWOP_SET_FONT:
     {
-      wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
+      wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
       if (node)
       {
         wxFont *font = (wxFont *)node->Data();
@@ -268,19 +491,19 @@ void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
     }
     case DRAWOP_SET_TEXT_COLOUR:
     {
-      wxColour col(r,g,b);
+      wxColour col(m_r,m_g,m_b);
       dc.SetTextForeground(col);
       break;
     }
     case DRAWOP_SET_BK_COLOUR:
     {
-      wxColour col(r,g,b);
+      wxColour col(m_r,m_g,m_b);
       dc.SetTextBackground(col);
       break;
     }
     case DRAWOP_SET_BK_MODE:
     {
-      dc.SetBackgroundMode(mode);
+      dc.SetBackgroundMode(m_mode);
       break;
     }
     default:
@@ -290,37 +513,37 @@ void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
 
 wxDrawOp *wxOpSetGDI::Copy(wxPseudoMetaFile *newImage)
 {
-  wxOpSetGDI *newOp = new wxOpSetGDI(op, newImage, gdiIndex, mode);
-  newOp->r = r;
-  newOp->g = g;
-  newOp->b = b;
+  wxOpSetGDI *newOp = new wxOpSetGDI(m_op, newImage, m_gdiIndex, m_mode);
+  newOp->m_r = m_r;
+  newOp->m_g = m_g;
+  newOp->m_b = m_b;
   return newOp;
 }
 
-wxExpr *wxOpSetGDI::WritewxExpr(wxPseudoMetaFile *image)
+wxExpr *wxOpSetGDI::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
-  expr->Append(new wxExpr((long)op));
-  switch (op)
+  wxExpr *expr = new wxExpr(wxExprList);
+  expr->Append(new wxExpr((long)m_op));
+  switch (m_op)
   {
     case DRAWOP_SET_PEN:
     case DRAWOP_SET_BRUSH:
     case DRAWOP_SET_FONT:
     {
-      expr->Append(new wxExpr((long)gdiIndex));
+      expr->Append(new wxExpr((long)m_gdiIndex));
       break;
     }
     case DRAWOP_SET_TEXT_COLOUR:
     case DRAWOP_SET_BK_COLOUR:
     {
-      expr->Append(new wxExpr((long)r));
-      expr->Append(new wxExpr((long)g));
-      expr->Append(new wxExpr((long)b));
+      expr->Append(new wxExpr((long)m_r));
+      expr->Append(new wxExpr((long)m_g));
+      expr->Append(new wxExpr((long)m_b));
       break;
     }
     case DRAWOP_SET_BK_MODE:
     {
-      expr->Append(new wxExpr((long)mode));
+      expr->Append(new wxExpr((long)m_mode));
       break;
     }
     default:
@@ -329,28 +552,28 @@ wxExpr *wxOpSetGDI::WritewxExpr(wxPseudoMetaFile *image)
   return expr;
 }
 
-void wxOpSetGDI::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
+void wxOpSetGDI::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_SET_PEN:
     case DRAWOP_SET_BRUSH:
     case DRAWOP_SET_FONT:
     {
-      gdiIndex = (int)expr->Nth(1)->IntegerValue();
+      m_gdiIndex = (int)expr->Nth(1)->IntegerValue();
       break;
     }
     case DRAWOP_SET_TEXT_COLOUR:
     case DRAWOP_SET_BK_COLOUR:
     {
-      r = (unsigned char)expr->Nth(1)->IntegerValue();
-      g = (unsigned char)expr->Nth(2)->IntegerValue();
-      b = (unsigned char)expr->Nth(3)->IntegerValue();
+      m_r = (unsigned char)expr->Nth(1)->IntegerValue();
+      m_g = (unsigned char)expr->Nth(2)->IntegerValue();
+      m_b = (unsigned char)expr->Nth(3)->IntegerValue();
       break;
     }
     case DRAWOP_SET_BK_MODE:
     {
-      mode = (int)expr->Nth(1)->IntegerValue();
+      m_mode = (int)expr->Nth(1)->IntegerValue();
       break;
     }
     default:
@@ -363,28 +586,28 @@ void wxOpSetGDI::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
  *
  */
  
-wxOpSetClipping::wxOpSetClipping(int theOp, float theX1, float theY1,
-    float theX2, float theY2):wxDrawOp(theOp)
+wxOpSetClipping::wxOpSetClipping(int theOp, double theX1, double theY1,
+    double theX2, double theY2):wxDrawOp(theOp)
 {
-  x1 = theX1;
-  y1 = theY1;
-  x2 = theX2;
-  y2 = theY2;
+  m_x1 = theX1;
+  m_y1 = theY1;
+  m_x2 = theX2;
+  m_y2 = theY2;
 }
 
 wxDrawOp *wxOpSetClipping::Copy(wxPseudoMetaFile *newImage)
 {
-  wxOpSetClipping *newOp = new wxOpSetClipping(op, x1, y1, x2, y2);
+  wxOpSetClipping *newOp = new wxOpSetClipping(m_op, m_x1, m_y1, m_x2, m_y2);
   return newOp;
 }
     
-void wxOpSetClipping::Do(wxDC& dc, float xoffset, float yoffset)
+void wxOpSetClipping::Do(wxDC& dc, double xoffset, double yoffset)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_SET_CLIPPING_RECT:
     {
-      dc.SetClippingRegion(x1 + xoffset, y1 + yoffset, x2 + xoffset, y2 + yoffset);
+      dc.SetClippingRegion(m_x1 + xoffset, m_y1 + yoffset, m_x2 + xoffset, m_y2 + yoffset);
       break;
     }
     case DRAWOP_DESTROY_CLIPPING_RECT:
@@ -397,32 +620,32 @@ void wxOpSetClipping::Do(wxDC& dc, float xoffset, float yoffset)
   }
 }
 
-void wxOpSetClipping::Scale(float xScale, float yScale)
+void wxOpSetClipping::Scale(double xScale, double yScale)
 {
-  x1 *= xScale;
-  y1 *= yScale;
-  x2 *= xScale;
-  y2 *= yScale;
+  m_x1 *= xScale;
+  m_y1 *= yScale;
+  m_x2 *= xScale;
+  m_y2 *= yScale;
 }
 
-void wxOpSetClipping::Translate(float x, float y)
+void wxOpSetClipping::Translate(double x, double y)
 {
-  x1 += x;
-  y1 += y;
+  m_x1 += x;
+  m_y1 += y;
 }
 
-wxExpr *wxOpSetClipping::WritewxExpr(wxPseudoMetaFile *image)
+wxExpr *wxOpSetClipping::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
-  expr->Append(new wxExpr((long)op));
-  switch (op)
+  wxExpr *expr = new wxExpr(wxExprList);
+  expr->Append(new wxExpr((long)m_op));
+  switch (m_op)
   {
     case DRAWOP_SET_CLIPPING_RECT:
     {
-      expr->Append(new wxExpr(x1));
-      expr->Append(new wxExpr(y1));
-      expr->Append(new wxExpr(x2));
-      expr->Append(new wxExpr(y2));
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
+      expr->Append(new wxExpr(m_x2));
+      expr->Append(new wxExpr(m_y2));
       break;
     }
     default:
@@ -431,16 +654,16 @@ wxExpr *wxOpSetClipping::WritewxExpr(wxPseudoMetaFile *image)
   return expr;
 }
 
-void wxOpSetClipping::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
+void wxOpSetClipping::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_SET_CLIPPING_RECT:
     {
-      x1 = expr->Nth(1)->RealValue();
-      y1 = expr->Nth(2)->RealValue();
-      x2 = expr->Nth(3)->RealValue();
-      y2 = expr->Nth(4)->RealValue();
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
+      m_x2 = expr->Nth(3)->RealValue();
+      m_y2 = expr->Nth(4)->RealValue();
       break;
     }
     default:
@@ -453,61 +676,83 @@ void wxOpSetClipping::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
  *
  */
  
-wxOpDraw::wxOpDraw(int theOp, float theX1, float theY1, float theX2, float theY2,
-         float theRadius, char *s):wxDrawOp(theOp)
+wxOpDraw::wxOpDraw(int theOp, double theX1, double theY1, double theX2, double theY2,
+         double theRadius, char *s):wxDrawOp(theOp)
 {
-  x1 = theX1;
-  y1 = theY1;
-  x2 = theX2;
-  y2 = theY2;
-  radius = theRadius;
-  if (s) textString = copystring(s);
-  else textString = NULL;
+  m_x1 = theX1;
+  m_y1 = theY1;
+  m_x2 = theX2;
+  m_y2 = theY2;
+  m_x3 = 0.0;
+  m_y3 = 0.0;
+  m_radius = theRadius;
+  if (s) m_textString = copystring(s);
+  else m_textString = NULL;
 }
 
 wxOpDraw::~wxOpDraw()
 {
-  if (textString) delete[] textString;
+  if (m_textString) delete[] m_textString;
 }
 
 wxDrawOp *wxOpDraw::Copy(wxPseudoMetaFile *newImage)
 {
-  wxOpDraw *newOp = new wxOpDraw(op, x1, y1, x2, y2, radius, textString);
+  wxOpDraw *newOp = new wxOpDraw(m_op, m_x1, m_y1, m_x2, m_y2, m_radius, m_textString);
+  newOp->m_x3 = m_x3;
+  newOp->m_y3 = m_y3;
   return newOp;
 }
 
-void wxOpDraw::Do(wxDC& dc, float xoffset, float yoffset)
+void wxOpDraw::Do(wxDC& dc, double xoffset, double yoffset)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_DRAW_LINE:
     {
-      dc.DrawLine(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
+      dc.DrawLine(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset));
       break;
     }
     case DRAWOP_DRAW_RECT:
     {
-      dc.DrawRectangle(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
+      dc.DrawRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
       break;
     }
     case DRAWOP_DRAW_ROUNDED_RECT:
     {
-      dc.DrawRoundedRectangle(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset, radius);
+      dc.DrawRoundedRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2), m_radius);
       break;
     }
     case DRAWOP_DRAW_ELLIPSE:
     {
-      dc.DrawEllipse(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
+      dc.DrawEllipse(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
+      break;
+    }
+    case DRAWOP_DRAW_ARC:
+    {
+      dc.DrawArc(WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset),
+                 WXROUND(m_x3+xoffset), WXROUND(m_y3+yoffset),
+                 WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
+      break;
+    }
+    case DRAWOP_DRAW_ELLIPTIC_ARC:
+    {
+      const double pi = 3.1415926535897932384626433832795 ;
+
+      // Convert back to degrees
+      dc.DrawEllipticArc(
+                 WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset),
+                 WXROUND(m_x2), WXROUND(m_y2),
+                 WXROUND(m_x3*(360.0/(2.0*pi))), WXROUND(m_y3*(360.0/(2.0*pi))));
       break;
     }
     case DRAWOP_DRAW_POINT:
     {
-      dc.DrawPoint(x1+xoffset, y1+yoffset);
+      dc.DrawPoint(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
       break;
     }
     case DRAWOP_DRAW_TEXT:
     {
-      dc.DrawText(textString, x1+xoffset, y1+yoffset);
+      dc.DrawText(m_textString, WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
       break;
     }
     default:
@@ -515,32 +760,117 @@ void wxOpDraw::Do(wxDC& dc, float xoffset, float yoffset)
   }
 }
 
-void wxOpDraw::Scale(float scaleX, float scaleY)
+void wxOpDraw::Scale(double scaleX, double scaleY)
 {
-  x1 *= scaleX;
-  y1 *= scaleY;
-  x2 *= scaleX;
-  y2 *= scaleY;
-  radius *= scaleX;
+  m_x1 *= scaleX;
+  m_y1 *= scaleY;
+  m_x2 *= scaleX;
+  m_y2 *= scaleY;
+
+  if (m_op != DRAWOP_DRAW_ELLIPTIC_ARC)
+  {
+    m_x3 *= scaleX;
+    m_y3 *= scaleY;
+  }
+
+  m_radius *= scaleX;
 }
 
-void wxOpDraw::Translate(float x, float y)
+void wxOpDraw::Translate(double x, double y)
 {
-  x1 += x;
-  y1 += y;
+  m_x1 += x;
+  m_y1 += y;
+
+  switch (m_op)
+  {
+    case DRAWOP_DRAW_LINE:
+    {
+      m_x2 += x;
+      m_y2 += y;
+      break;
+    }
+    case DRAWOP_DRAW_ARC:
+    {
+      m_x2 += x;
+      m_y2 += y;
+      m_x3 += x;
+      m_y3 += y;
+      break;
+    }
+    case DRAWOP_DRAW_ELLIPTIC_ARC:
+    {
+      break;
+    }
+    default:
+      break;
+  }
 }
 
-void wxOpDraw::Rotate(float x, float y, float sinTheta, float cosTheta)
+void wxOpDraw::Rotate(double x, double y, double theta, double sinTheta, double cosTheta)
 {
-  x1 = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
-  y1 = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
-  
-  switch (op)
+  double newX1 = m_x1*cosTheta - m_y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+  double newY1 = m_x1*sinTheta + m_y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+
+  switch (m_op)
   {
     case DRAWOP_DRAW_LINE:
     {
-      x2 = x2*cosTheta - y2*sinTheta + x*(1 - cosTheta) + y*sinTheta;
-      y2 = x2*sinTheta + y2*cosTheta + y*(1 - cosTheta) + x*sinTheta;
+      double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+      double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+
+         m_x1 = newX1;
+         m_y1 = newY1;
+         m_x2 = newX2;
+         m_y2 = newY2;
+      break;
+    }
+    case DRAWOP_DRAW_RECT:
+    case DRAWOP_DRAW_ROUNDED_RECT:
+    case DRAWOP_DRAW_ELLIPTIC_ARC:
+    {
+      // Assume only 0, 90, 180, 270 degree rotations.
+      // oldX1, oldY1 represents the top left corner. Find the
+      // bottom right, and rotate that. Then the width/height is the difference
+      // between x/y values.
+      double oldBottomRightX = m_x1 + m_x2;
+      double oldBottomRightY = m_y1 + m_y2;
+      double newBottomRightX = oldBottomRightX*cosTheta - oldBottomRightY*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+      double newBottomRightY = oldBottomRightX*sinTheta + oldBottomRightY*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+
+      // Now find the new top-left, bottom-right coordinates.
+      double minX = wxMin(newX1, newBottomRightX);
+      double minY = wxMin(newY1, newBottomRightY);
+      double maxX = wxMax(newX1, newBottomRightX);
+      double maxY = wxMax(newY1, newBottomRightY);
+
+      m_x1 = minX;
+      m_y1 = minY;
+      m_x2 = maxX - minX; // width
+      m_y2 = maxY - minY; // height
+
+      if (m_op == DRAWOP_DRAW_ELLIPTIC_ARC)
+      {
+        // Add rotation to angles
+        m_x3 += theta;
+        m_y3 += theta;
+      }
+
+      break;
+    }
+    case DRAWOP_DRAW_ARC:
+    {
+      double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+      double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+      double newX3 = m_x3*cosTheta - m_y3*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+      double newY3 = m_x3*sinTheta + m_y3*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
+
+         m_x1 = newX1;
+         m_y1 = newY1;
+         m_x2 = newX2;
+         m_y2 = newY2;
+         m_x3 = newX3;
+         m_y3 = newY3;
+
       break;
     }
     default:
@@ -548,45 +878,55 @@ void wxOpDraw::Rotate(float x, float y, float sinTheta, float cosTheta)
   }
 }
 
-wxExpr *wxOpDraw::WritewxExpr(wxPseudoMetaFile *image)
+wxExpr *wxOpDraw::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
-  expr->Append(new wxExpr((long)op));
-  switch (op)
+  wxExpr *expr = new wxExpr(wxExprList);
+  expr->Append(new wxExpr((long)m_op));
+  switch (m_op)
   {
     case DRAWOP_DRAW_LINE:
     case DRAWOP_DRAW_RECT:
     case DRAWOP_DRAW_ELLIPSE:
     {
-      expr->Append(new wxExpr(x1));
-      expr->Append(new wxExpr(y1));
-      expr->Append(new wxExpr(x2));
-      expr->Append(new wxExpr(y2));
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
+      expr->Append(new wxExpr(m_x2));
+      expr->Append(new wxExpr(m_y2));
       break;
     }
     case DRAWOP_DRAW_ROUNDED_RECT:
     {
-      expr->Append(new wxExpr(x1));
-      expr->Append(new wxExpr(y1));
-      expr->Append(new wxExpr(x2));
-      expr->Append(new wxExpr(y2));
-      expr->Append(new wxExpr(radius));
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
+      expr->Append(new wxExpr(m_x2));
+      expr->Append(new wxExpr(m_y2));
+      expr->Append(new wxExpr(m_radius));
       break;
     }
     case DRAWOP_DRAW_POINT:
     {
-      expr->Append(new wxExpr(x1));
-      expr->Append(new wxExpr(y1));
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
       break;
     }
     case DRAWOP_DRAW_TEXT:
     {
-      expr->Append(new wxExpr(x1));
-      expr->Append(new wxExpr(y1));
-      expr->Append(new wxExpr(PrologString, textString));
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
+      expr->Append(new wxExpr(wxExprString, m_textString));
       break;
     }
     case DRAWOP_DRAW_ARC:
+    case DRAWOP_DRAW_ELLIPTIC_ARC:
+    {
+      expr->Append(new wxExpr(m_x1));
+      expr->Append(new wxExpr(m_y1));
+      expr->Append(new wxExpr(m_x2));
+      expr->Append(new wxExpr(m_y2));
+      expr->Append(new wxExpr(m_x3));
+      expr->Append(new wxExpr(m_y3));
+      break;
+    }
     default:
     {
       break;
@@ -595,43 +935,54 @@ wxExpr *wxOpDraw::WritewxExpr(wxPseudoMetaFile *image)
   return expr;
 }
 
-void wxOpDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
+void wxOpDraw::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_DRAW_LINE:
     case DRAWOP_DRAW_RECT:
     case DRAWOP_DRAW_ELLIPSE:
     {
-      x1 = expr->Nth(1)->RealValue();
-      y1 = expr->Nth(2)->RealValue();
-      x2 = expr->Nth(3)->RealValue();
-      y2 = expr->Nth(4)->RealValue();
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
+      m_x2 = expr->Nth(3)->RealValue();
+      m_y2 = expr->Nth(4)->RealValue();
       break;
     }
     case DRAWOP_DRAW_ROUNDED_RECT:
     {
-      x1 = expr->Nth(1)->RealValue();
-      y1 = expr->Nth(2)->RealValue();
-      x2 = expr->Nth(3)->RealValue();
-      y2 = expr->Nth(4)->RealValue();
-      radius = expr->Nth(5)->RealValue();
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
+      m_x2 = expr->Nth(3)->RealValue();
+      m_y2 = expr->Nth(4)->RealValue();
+      m_radius = expr->Nth(5)->RealValue();
       break;
     }
     case DRAWOP_DRAW_POINT:
     {
-      x1 = expr->Nth(1)->RealValue();
-      y1 = expr->Nth(2)->RealValue();
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
       break;
     }
     case DRAWOP_DRAW_TEXT:
     {
-      x1 = expr->Nth(1)->RealValue();
-      y1 = expr->Nth(2)->RealValue();
-      textString = copystring(expr->Nth(3)->StringValue());
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
+      wxString str(expr->Nth(3)->StringValue());
+      m_textString = copystring((const char*) str);
       break;
     }
     case DRAWOP_DRAW_ARC:
+    case DRAWOP_DRAW_ELLIPTIC_ARC:
+    {
+      m_x1 = expr->Nth(1)->RealValue();
+      m_y1 = expr->Nth(2)->RealValue();
+      m_x2 = expr->Nth(3)->RealValue();
+      m_y2 = expr->Nth(4)->RealValue();
+      m_x3 = expr->Nth(5)->RealValue();
+      m_y3 = expr->Nth(6)->RealValue();
+      break;
+    }
     default:
     {
       break;
@@ -646,64 +997,75 @@ void wxOpDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
 
 wxOpPolyDraw::wxOpPolyDraw(int theOp, int n, wxRealPoint *thePoints):wxDrawOp(theOp)
 {
-  noPoints = n;
-  points = thePoints;
+  m_noPoints = n;
+  m_points = thePoints;
 }
 
 wxOpPolyDraw::~wxOpPolyDraw()
 {
-  delete[] points;
+  delete[] m_points;
 }
 
 wxDrawOp *wxOpPolyDraw::Copy(wxPseudoMetaFile *newImage)
 {
-  wxRealPoint *newPoints = new wxRealPoint[noPoints];
-  for (int i = 0; i < noPoints; i++)
+  wxRealPoint *newPoints = new wxRealPoint[m_noPoints];
+  for (int i = 0; i < m_noPoints; i++)
   {
-    newPoints[i].x = points[i].x;
-    newPoints[i].y = points[i].y;
+    newPoints[i].x = m_points[i].x;
+    newPoints[i].y = m_points[i].y;
   }
-  wxOpPolyDraw *newOp = new wxOpPolyDraw(op, noPoints, newPoints);
+  wxOpPolyDraw *newOp = new wxOpPolyDraw(m_op, m_noPoints, newPoints);
   return newOp;
 }
 
-void wxOpPolyDraw::Do(wxDC& dc, float xoffset, float yoffset)
+void wxOpPolyDraw::Do(wxDC& dc, double xoffset, double yoffset)
 {
-  switch (op)
+  switch (m_op)
   {
     case DRAWOP_DRAW_POLYLINE:
     {
-        wxPoint *actualPoints = new wxPoint[noPoints];
+        wxPoint *actualPoints = new wxPoint[m_noPoints];
         int i;
-        for (i = 0; i < noPoints; i++)
+        for (i = 0; i < m_noPoints; i++)
         {
-            actualPoints[i].x = (long) points[i].x;
-            actualPoints[i].y = (long) points[i].y;
+            actualPoints[i].x = WXROUND(m_points[i].x);
+            actualPoints[i].y = WXROUND(m_points[i].y);
         }
 
-        dc.DrawLines(noPoints, actualPoints, xoffset, yoffset);
+        dc.DrawLines(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
 
         delete[] actualPoints;
         break;
     }
     case DRAWOP_DRAW_POLYGON:
     {
-        wxPoint *actualPoints = new wxPoint[noPoints];
+        wxPoint *actualPoints = new wxPoint[m_noPoints];
         int i;
-        for (i = 0; i < noPoints; i++)
+        for (i = 0; i < m_noPoints; i++)
         {
-            actualPoints[i].x = (long) points[i].x;
-            actualPoints[i].y = (long) points[i].y;
+            actualPoints[i].x = WXROUND(m_points[i].x);
+            actualPoints[i].y = WXROUND(m_points[i].y);
         }
 
-        dc.DrawPolygon(noPoints, actualPoints, xoffset, yoffset);
+        dc.DrawPolygon(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
 
         delete[] actualPoints;
         break;
     }
     case DRAWOP_DRAW_SPLINE:
     {
-//      dc.DrawSpline(noPoints, points, xoffset, yoffset);
+        wxPoint *actualPoints = new wxPoint[m_noPoints];
+        int i;
+        for (i = 0; i < m_noPoints; i++)
+        {
+            actualPoints[i].x = WXROUND(m_points[i].x);
+            actualPoints[i].y = WXROUND(m_points[i].y);
+        }
+
+        dc.DrawSpline(m_noPoints, actualPoints); // no offsets in DrawSpline // , xoffset, yoffset);
+
+        delete[] actualPoints;
+        break;
       break;
     }
     default:
@@ -711,57 +1073,57 @@ void wxOpPolyDraw::Do(wxDC& dc, float xoffset, float yoffset)
   }
 }
 
-void wxOpPolyDraw::Scale(float scaleX, float scaleY)
+void wxOpPolyDraw::Scale(double scaleX, double scaleY)
 {
-  for (int i = 0; i < noPoints; i++)
+  for (int i = 0; i < m_noPoints; i++)
   {
-    points[i].x *= scaleX;
-    points[i].y *= scaleY;
+    m_points[i].x *= scaleX;
+    m_points[i].y *= scaleY;
   }
 }
 
-void wxOpPolyDraw::Translate(float x, float y)
+void wxOpPolyDraw::Translate(double x, double y)
 {
-  for (int i = 0; i < noPoints; i++)
+  for (int i = 0; i < m_noPoints; i++)
   {
-    points[i].x += x;
-    points[i].y += y;
+    m_points[i].x += x;
+    m_points[i].y += y;
   }
 }
 
-void wxOpPolyDraw::Rotate(float x, float y, float sinTheta, float cosTheta)
+void wxOpPolyDraw::Rotate(double x, double y, double theta, double sinTheta, double cosTheta)
 {
-  for (int i = 0; i < noPoints; i++)
+  for (int i = 0; i < m_noPoints; i++)
   {
-    float x1 = points[i].x;
-    float y1 = points[i].y;
-    points[i].x = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
-    points[i].y = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
+    double x1 = m_points[i].x;
+    double y1 = m_points[i].y;
+    m_points[i].x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
+    m_points[i].y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
   }
 }
 
-wxExpr *wxOpPolyDraw::WritewxExpr(wxPseudoMetaFile *image)
+wxExpr *wxOpPolyDraw::WriteExpr(wxPseudoMetaFile *image)
 {
-  wxExpr *expr = new wxExpr(PrologList);
-  expr->Append(new wxExpr((long)op));
-  expr->Append(new wxExpr((long)noPoints));
+  wxExpr *expr = new wxExpr(wxExprList);
+  expr->Append(new wxExpr((long)m_op));
+  expr->Append(new wxExpr((long)m_noPoints));
 
 //  char buf1[9];
   char buf2[5];
   char buf3[5];
 
-  GraphicsBuffer[0] = 0;
-  
+  oglBuffer[0] = 0;
+
   /*
    * Store each coordinate pair in a hex string to save space.
    * E.g. "1B9080CD". 4 hex digits per coordinate pair.
    *
    */
    
-  for (int i = 0; i < noPoints; i++)
+  for (int i = 0; i < m_noPoints; i++)
   {
-    long signedX = (long)(points[i].x*100.0);
-    long signedY = (long)(points[i].y*100.0);
+    long signedX = (long)(m_points[i].x*100.0);
+    long signedY = (long)(m_points[i].y*100.0);
 
     // Scale to 0 -> 64K
     long unSignedX = (long)(signedX + 32767.0);
@@ -775,26 +1137,26 @@ wxExpr *wxOpPolyDraw::WritewxExpr(wxPseudoMetaFile *image)
     // Don't overrun the buffer
     if ((i*8) < 3000)
     {
-      strcat(GraphicsBuffer, buf2);
-      strcat(GraphicsBuffer, buf3);
+      strcat(oglBuffer, buf2);
+      strcat(oglBuffer, buf3);
     }
   }
-  expr->Append(new wxExpr(PrologString, GraphicsBuffer));
+  expr->Append(new wxExpr(wxExprString, oglBuffer));
   return expr;
 }
 
-void wxOpPolyDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
+void wxOpPolyDraw::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
 {
-  noPoints = (int)expr->Nth(1)->IntegerValue();
+  m_noPoints = (int)expr->Nth(1)->IntegerValue();
 
   char buf1[5];
   char buf2[5];
 
-  points = new wxRealPoint[noPoints];
+  m_points = new wxRealPoint[m_noPoints];
   int i = 0;
   int bufPtr = 0;
   wxString hexString = expr->Nth(2)->StringValue();
-  while (i < noPoints)
+  while (i < m_noPoints)
   {
     buf1[0] = hexString[bufPtr];
     buf1[1] = hexString[bufPtr + 1];
@@ -822,13 +1184,94 @@ void wxOpPolyDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
     int testY = (signed int)unSignedY;
 #endif
 
-    points[i].x = (float)(signedX / 100.0);
-    points[i].y = (float)(signedY / 100.0);
+    m_points[i].x = (double)(signedX / 100.0);
+    m_points[i].y = (double)(signedY / 100.0);
 
     i ++;
   }
 }
 
+// Draw an outline using the current operation.
+bool wxOpPolyDraw::OnDrawOutline(wxDC& dc, double x, double y, double w, double h, double oldW, double oldH)
+{
+    dc.SetBrush(wxTRANSPARENT_BRUSH);
+
+    // Multiply all points by proportion of new size to old size
+    double x_proportion = (double)(fabs(w/oldW));
+    double y_proportion = (double)(fabs(h/oldH));
+
+    int n = m_noPoints;
+    wxPoint *intPoints = new wxPoint[n];
+    int i;
+    for (i = 0; i < n; i++)
+    {
+        intPoints[i].x = WXROUND (x_proportion * m_points[i].x);
+        intPoints[i].y = WXROUND (y_proportion * m_points[i].y);
+    }
+    dc.DrawPolygon(n, intPoints, x, y);
+    delete[] intPoints;
+    return TRUE;
+}
+
+// Assume (x1, y1) is centre of box (most generally, line end at box)
+bool wxOpPolyDraw::GetPerimeterPoint(double x1, double y1,
+                                     double x2, double y2,
+                                     double *x3, double *y3,
+                                     double xOffset, double yOffset,
+                                     int attachmentMode)
+{
+  int n = m_noPoints;
+
+  // First check for situation where the line is vertical,
+  // and we would want to connect to a point on that vertical --
+  // oglFindEndForPolyline can't cope with this (the arrow
+  // gets drawn to the wrong place).
+  if ((attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2))
+  {
+    // Look for the point we'd be connecting to. This is
+    // a heuristic...
+    int i;
+    for (i = 0; i < n; i++)
+    {
+      wxRealPoint *point = & (m_points[i]);
+      if (point->x == 0.0)
+      {
+        if ((y2 > y1) && (point->y > 0.0))
+        {
+          *x3 = point->x + xOffset;
+          *y3 = point->y + yOffset;
+          return TRUE;
+        }
+        else if ((y2 < y1) && (point->y < 0.0))
+        {
+          *x3 = point->x + xOffset;
+          *y3 = point->y + yOffset;
+          return TRUE;
+        }
+      }
+    }
+  }
+  
+  double *xpoints = new double[n];
+  double *ypoints = new double[n];
+
+  int i = 0;
+  for (i = 0; i < n; i++)
+  {
+    wxRealPoint *point = & (m_points[i]);
+    xpoints[i] = point->x + xOffset;
+    ypoints[i] = point->y + yOffset;
+  }
+
+  oglFindEndForPolyline(n, xpoints, ypoints, 
+                        x1, y1, x2, y2, x3, y3);
+
+  delete[] xpoints;
+  delete[] ypoints;
+
+  return TRUE;
+}
+
 
 /*
  * Utilities
@@ -920,6 +1363,9 @@ wxPseudoMetaFile::wxPseudoMetaFile()
   m_rotateable = TRUE;
   m_width = 0.0;
   m_height = 0.0;
+  m_outlinePen = NULL;
+  m_fillBrush = NULL;
+  m_outlineOp = -1;
 }
 
 wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile& mf)
@@ -943,9 +1389,12 @@ void wxPseudoMetaFile::Clear()
   }
   m_ops.Clear();
   m_gdiObjects.Clear();
+  m_outlineColours.Clear();
+  m_fillColours.Clear();
+  m_outlineOp = -1;
 }
 
-void wxPseudoMetaFile::Draw(wxDC& dc, float xoffset, float yoffset)
+void wxPseudoMetaFile::Draw(wxDC& dc, double xoffset, double yoffset)
 {
   wxNode *node = m_ops.First();
   while (node)
@@ -956,7 +1405,7 @@ void wxPseudoMetaFile::Draw(wxDC& dc, float xoffset, float yoffset)
   }
 }
 
-void wxPseudoMetaFile::Scale(float sx, float sy)
+void wxPseudoMetaFile::Scale(double sx, double sy)
 {
   wxNode *node = m_ops.First();
   while (node)
@@ -969,7 +1418,7 @@ void wxPseudoMetaFile::Scale(float sx, float sy)
   m_height *= sy;
 }
 
-void wxPseudoMetaFile::Translate(float x, float y)
+void wxPseudoMetaFile::Translate(double x, double y)
 {
   wxNode *node = m_ops.First();
   while (node)
@@ -980,30 +1429,43 @@ void wxPseudoMetaFile::Translate(float x, float y)
   }
 }
 
-void wxPseudoMetaFile::Rotate(float x, float y, float theta)
+void wxPseudoMetaFile::Rotate(double x, double y, double theta)
 {
-  float theta1 = theta-m_currentRotation;
+  double theta1 = theta-m_currentRotation;
   if (theta1 == 0.0) return;
-  float cosTheta = (float)cos(theta1);
-  float sinTheta = (float)sin(theta1);
+  double cosTheta = (double)cos(theta1);
+  double sinTheta = (double)sin(theta1);
 
   wxNode *node = m_ops.First();
   while (node)
   {
     wxDrawOp *op = (wxDrawOp *)node->Data();
-    op->Rotate(x, y, sinTheta, cosTheta);
+    op->Rotate(x, y, theta, sinTheta, cosTheta);
     node = node->Next();
   }
   m_currentRotation = theta;
 }
 
 #ifdef PROLOGIO
-void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
+void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
 {
+  wxString widthStr;
+  widthStr.Printf("meta_width%d", whichAngle);
+
+  wxString heightStr;
+  heightStr.Printf("meta_height%d", whichAngle);
+
+  wxString outlineStr;
+  outlineStr.Printf("outline_op%d", whichAngle);
+
+  wxString rotateableStr;
+  rotateableStr.Printf("meta_rotateable%d", whichAngle);
+
   // Write width and height
-  clause->AddAttributeValue("meta_width", m_width);
-  clause->AddAttributeValue("meta_height", m_height);
-  clause->AddAttributeValue("meta_rotateable", (long)m_rotateable);
+  clause->AddAttributeValue(widthStr, m_width);
+  clause->AddAttributeValue(heightStr, m_height);
+  clause->AddAttributeValue(rotateableStr, (long)m_rotateable);
+  clause->AddAttributeValue(outlineStr, (long)m_outlineOp);
 
   // Write GDI objects
   char buf[50];
@@ -1011,7 +1473,7 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
   wxNode *node = m_gdiObjects.First();
   while (node)
   {
-    sprintf(buf, "gdi%d", i);
+    sprintf(buf, "gdi%d_%d", whichAngle, i);
     wxObject *obj = (wxObject *)node->Data();
     wxExpr *expr = NULL;
     if (obj)
@@ -1019,7 +1481,7 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
       if (obj->IsKindOf(CLASSINFO(wxPen)))
       {
         wxPen *thePen = (wxPen *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_PEN));
         expr->Append(new wxExpr((long)thePen->GetWidth()));
         expr->Append(new wxExpr((long)thePen->GetStyle()));
@@ -1030,7 +1492,7 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
       else if (obj->IsKindOf(CLASSINFO(wxBrush)))
       {
         wxBrush *theBrush = (wxBrush *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_BRUSH));
         expr->Append(new wxExpr((long)theBrush->GetStyle()));
         expr->Append(new wxExpr((long)theBrush->GetColour().Red()));
@@ -1040,7 +1502,7 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
       else if (obj->IsKindOf(CLASSINFO(wxFont)))
       {
         wxFont *theFont = (wxFont *)obj;
-        expr = new wxExpr(PrologList);
+        expr = new wxExpr(wxExprList);
         expr->Append(new wxExpr((long)gyTYPE_FONT));
         expr->Append(new wxExpr((long)theFont->GetPointSize()));
         expr->Append(new wxExpr((long)theFont->GetFamily()));
@@ -1052,7 +1514,7 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
     else
     {
       // If no recognised GDI object, append a place holder anyway.
-      expr = new wxExpr(PrologList);
+      expr = new wxExpr(wxExprList);
       expr->Append(new wxExpr((long)0));
     }
 
@@ -1069,9 +1531,9 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
   node = m_ops.First();
   while (node)
   {
-    sprintf(buf, "op%d", i);
+    sprintf(buf, "op%d_%d", whichAngle, i);
     wxDrawOp *op = (wxDrawOp *)node->Data();
-    wxExpr *expr = op->WritewxExpr(this);
+    wxExpr *expr = op->WriteExpr(this);
     if (expr)
     {
       clause->AddAttributeValue(buf, expr);
@@ -1083,36 +1545,55 @@ void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
   // Write outline and fill GDI op lists (if any)
   if (m_outlineColours.Number() > 0)
   {
-    wxExpr *outlineExpr = new wxExpr(PrologList);
+    wxExpr *outlineExpr = new wxExpr(wxExprList);
     node = m_outlineColours.First();
     while (node)
     {
       outlineExpr->Append(new wxExpr((long)node->Data()));
       node = node->Next();
     }
-    clause->AddAttributeValue("outline_objects", outlineExpr);
+    wxString outlineObjectsStr;
+    outlineObjectsStr.Printf("outline_objects%d", whichAngle);
+
+    clause->AddAttributeValue(outlineObjectsStr, outlineExpr);
   }
   if (m_fillColours.Number() > 0)
   {
-    wxExpr *fillExpr = new wxExpr(PrologList);
+    wxExpr *fillExpr = new wxExpr(wxExprList);
     node = m_fillColours.First();
     while (node)
     {
       fillExpr->Append(new wxExpr((long)node->Data()));
       node = node->Next();
     }
-    clause->AddAttributeValue("fill_objects", fillExpr);
+    wxString fillObjectsStr;
+    fillObjectsStr.Printf("fill_objects%d", whichAngle);
+
+    clause->AddAttributeValue(fillObjectsStr, fillExpr);
   }
     
 }
 
-void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
+void wxPseudoMetaFile::ReadAttributes(wxExpr *clause, int whichAngle)
 {
-  clause->AssignAttributeValue("meta_width", &m_width);
-  clause->AssignAttributeValue("meta_height", &m_height);
+  wxString widthStr;
+  widthStr.Printf("meta_width%d", whichAngle);
+
+  wxString heightStr;
+  heightStr.Printf("meta_height%d", whichAngle);
+
+  wxString outlineStr;
+  outlineStr.Printf("outline_op%d", whichAngle);
+
+  wxString rotateableStr;
+  rotateableStr.Printf("meta_rotateable%d", whichAngle);
+
+  clause->GetAttributeValue(widthStr, m_width);
+  clause->GetAttributeValue(heightStr, m_height);
+  clause->GetAttributeValue(outlineStr, m_outlineOp);
 
   int iVal = (int) m_rotateable;
-  clause->AssignAttributeValue("meta_rotateable", &iVal);
+  clause->GetAttributeValue(rotateableStr, iVal);
   m_rotateable = (iVal != 0);
 
   // Read GDI objects
@@ -1121,9 +1602,9 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
   bool keepGoing = TRUE;
   while (keepGoing)
   {
-    sprintf(buf, "gdi%d", i);
+    sprintf(buf, "gdi%d_%d", whichAngle, i);
     wxExpr *expr = NULL;
-    clause->AssignAttributeValue(buf, &expr);
+    clause->GetAttributeValue(buf, &expr);
     if (!expr)
     {
       keepGoing = FALSE;
@@ -1187,9 +1668,9 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
   i = 1;
   while (keepGoing)
   {
-    sprintf(buf, "op%d", i);
+    sprintf(buf, "op%d_%d", whichAngle, i);
     wxExpr *expr = NULL;
-    clause->AssignAttributeValue(buf, &expr);
+    clause->GetAttributeValue(buf, &expr);
     if (!expr)
     {
       keepGoing = FALSE;
@@ -1208,7 +1689,7 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
         case DRAWOP_SET_BK_MODE:
         {
           wxOpSetGDI *theOp = new wxOpSetGDI(opId, this, 0);
-          theOp->ReadwxExpr(this, expr);
+          theOp->ReadExpr(this, expr);
           m_ops.Append(theOp);
           break;
         }
@@ -1217,7 +1698,7 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
         case DRAWOP_DESTROY_CLIPPING_RECT:
         {
           wxOpSetClipping *theOp = new wxOpSetClipping(opId, 0.0, 0.0, 0.0, 0.0);
-          theOp->ReadwxExpr(this, expr);
+          theOp->ReadExpr(this, expr);
           m_ops.Append(theOp);
           break;
         }
@@ -1231,7 +1712,7 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
         case DRAWOP_DRAW_TEXT:
         {
           wxOpDraw *theOp = new wxOpDraw(opId, 0.0, 0.0, 0.0, 0.0);
-          theOp->ReadwxExpr(this, expr);
+          theOp->ReadExpr(this, expr);
           m_ops.Append(theOp);
           break;
         }
@@ -1240,7 +1721,7 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
         case DRAWOP_DRAW_POLYGON:
         {
           wxOpPolyDraw *theOp = new wxOpPolyDraw(opId, 0, NULL);
-          theOp->ReadwxExpr(this, expr);
+          theOp->ReadExpr(this, expr);
           m_ops.Append(theOp);
           break;
         }
@@ -1251,8 +1732,11 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
     i ++;
   }
 
+  wxString outlineObjectsStr;
+  outlineObjectsStr.Printf("outline_objects%d", whichAngle);
+
   // Now read in the list of outline and fill operations, if any
-  wxExpr *expr1 = clause->AttributeValue("outline_objects");
+  wxExpr *expr1 = clause->AttributeValue(outlineObjectsStr);
   if (expr1)
   {
     wxExpr *eachExpr = expr1->GetFirst();
@@ -1262,7 +1746,11 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
       eachExpr = eachExpr->GetNext();
     }
   }
-  expr1 = clause->AttributeValue("fill_objects");
+
+  wxString fillObjectsStr;
+  fillObjectsStr.Printf("fill_objects%d", whichAngle);
+
+  expr1 = clause->AttributeValue(fillObjectsStr);
   if (expr1)
   {
     wxExpr *eachExpr = expr1->GetFirst();
@@ -1278,10 +1766,15 @@ void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
 // Does the copying for this object
 void wxPseudoMetaFile::Copy(wxPseudoMetaFile& copy)
 {
+  copy.Clear();
+
   copy.m_currentRotation = m_currentRotation;
   copy.m_width = m_width;
   copy.m_height = m_height;
   copy.m_rotateable = m_rotateable;
+  copy.m_fillBrush = m_fillBrush;
+  copy.m_outlinePen = m_outlinePen;
+  copy.m_outlineOp = m_outlineOp;
 
   // Copy the GDI objects
   wxNode *node = m_gdiObjects.First();
@@ -1302,14 +1795,12 @@ void wxPseudoMetaFile::Copy(wxPseudoMetaFile& copy)
   }
 
   // Copy the outline/fill operations
-  copy.m_outlineColours.Clear();
   node = m_outlineColours.First();
   while (node)
   {
     copy.m_outlineColours.Append((wxObject *)node->Data());
     node = node->Next();
   }
-  copy.m_fillColours.Clear();
   node = m_fillColours.First();
   while (node)
   {
@@ -1324,7 +1815,7 @@ void wxPseudoMetaFile::Copy(wxPseudoMetaFile& copy)
  *
  */
  
-bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rheight)
+bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, double *rwidth, double *rheight)
 {
   if (!FileExists(filename))
     return NULL;
@@ -1337,8 +1828,8 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
     return FALSE;
   }
 
-  float lastX = 0.0;
-  float lastY = 0.0;
+  double lastX = 0.0;
+  double lastY = 0.0;
 
   // Convert from metafile records to wxDrawnShape records
   wxNode *node = metaFile->metaRecords.First();
@@ -1350,9 +1841,9 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_SETBKCOLOR:
       {
         wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BK_COLOUR, this, 0);
-        op->r = (unsigned char)record->param1;
-        op->g = (unsigned char)record->param2;
-        op->b = (unsigned char)record->param3;
+        op->m_r = (unsigned char)record->param1;
+        op->m_g = (unsigned char)record->param2;
+        op->m_b = (unsigned char)record->param3;
         m_ops.Append(op);
         break;
       }
@@ -1374,9 +1865,9 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_SETTEXTCOLOR:
       {
         wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
-        op->r = (unsigned char)record->param1;
-        op->g = (unsigned char)record->param2;
-        op->b = (unsigned char)record->param3;
+        op->m_r = (unsigned char)record->param1;
+        op->m_g = (unsigned char)record->param2;
+        op->m_b = (unsigned char)record->param3;
         m_ops.Append(op);
         break;
       }
@@ -1391,22 +1882,22 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
 //      case META_SCALEVIEWPORTEXT:
       case META_LINETO:
       {
-        wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_LINE, (float)lastX, (float)lastY,
-                               (float)record->param1, (float)record->param2);
+        wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_LINE, (double)lastX, (double)lastY,
+                               (double)record->param1, (double)record->param2);
         m_ops.Append(op);
         break;
       }
       case META_MOVETO:
       {
-        lastX = (float)record->param1;
-        lastY = (float)record->param2;
+        lastX = (double)record->param1;
+        lastY = (double)record->param2;
         break;
       }
       case META_EXCLUDECLIPRECT:
       {
 /*
         wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
-        rec->param4 = getshort(handle); // y2
+        rec->param4 = getshort(handle); // m_y2
         rec->param3 = getshort(handle); // x2
         rec->param2 = getshort(handle); // y1
         rec->param1 = getshort(handle); // x1
@@ -1416,7 +1907,7 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_INTERSECTCLIPRECT:
       {
 /*
-        rec->param4 = getshort(handle); // y2
+        rec->param4 = getshort(handle); // m_y2
         rec->param3 = getshort(handle); // x2
         rec->param2 = getshort(handle); // y1
         rec->param1 = getshort(handle); // x1
@@ -1427,9 +1918,9 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_ELLIPSE:
       {
         wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
-                               (float)record->param1, (float)record->param2,
-                               (float)(record->param3 - record->param1),
-                               (float)(record->param4 - record->param2));
+                               (double)record->param1, (double)record->param2,
+                               (double)(record->param3 - record->param1),
+                               (double)(record->param4 - record->param2));
         m_ops.Append(op);
         break;
       }
@@ -1438,18 +1929,18 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_RECTANGLE:
       {
         wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_RECT,
-                               (float)record->param1, (float)record->param2,
-                               (float)(record->param3 - record->param1),
-                               (float)(record->param4 - record->param2));
+                               (double)record->param1, (double)record->param2,
+                               (double)(record->param3 - record->param1),
+                               (double)(record->param4 - record->param2));
         m_ops.Append(op);
         break;
       }
       case META_ROUNDRECT:
       {
         wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
-              (float)record->param1, (float)record->param2,
-              (float)(record->param3 - record->param1),
-              (float)(record->param4 - record->param2), (float)record->param5);
+              (double)record->param1, (double)record->param2,
+              (double)(record->param3 - record->param1),
+              (double)(record->param4 - record->param2), (double)record->param5);
         m_ops.Append(op);
         break;
       }
@@ -1458,7 +1949,7 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_SETPIXEL:
       {
         wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_POINT,
-              (float)record->param1, (float)record->param2,
+              (double)record->param1, (double)record->param2,
               0.0, 0.0);
 
 //        SHOULD SET THE COLOUR - SET PEN?
@@ -1470,7 +1961,7 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
       case META_TEXTOUT:
       {
         wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_TEXT,
-              (float)record->param1, (float)record->param2,
+              (double)record->param1, (double)record->param2,
               0.0, 0.0, 0.0, record->stringParam);
         m_ops.Append(op);
         break;
@@ -1636,24 +2127,24 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
     }
     node = node->Next();
   }
-  float actualWidth = (float)fabs(metaFile->right - metaFile->left);
-  float actualHeight = (float)fabs(metaFile->bottom - metaFile->top);
-  
-  float initialScaleX = 1.0;
-  float initialScaleY = 1.0;
+  double actualWidth = (double)fabs(metaFile->right - metaFile->left);
+  double actualHeight = (double)fabs(metaFile->bottom - metaFile->top);
+
+  double initialScaleX = 1.0;
+  double initialScaleY = 1.0;
 
-  float xoffset, yoffset;
+  double xoffset, yoffset;
 
   // Translate so origin is at centre of rectangle
   if (metaFile->bottom > metaFile->top)
-    yoffset = - (float)((metaFile->bottom - metaFile->top)/2.0);
+    yoffset = - (double)((metaFile->bottom - metaFile->top)/2.0);
   else
-    yoffset = - (float)((metaFile->top - metaFile->bottom)/2.0);
+    yoffset = - (double)((metaFile->top - metaFile->bottom)/2.0);
 
   if (metaFile->right > metaFile->left)
-    xoffset = - (float)((metaFile->right - metaFile->left)/2.0);
+    xoffset = - (double)((metaFile->right - metaFile->left)/2.0);
   else
-    xoffset = - (float)((metaFile->left - metaFile->right)/2.0);
+    xoffset = - (double)((metaFile->left - metaFile->right)/2.0);
 
   Translate(xoffset, yoffset);
 
@@ -1661,7 +2152,7 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
   // as a guide)
   if (actualWidth != 0.0)
   {
-    initialScaleX = (float)((*rwidth) / actualWidth);
+    initialScaleX = (double)((*rwidth) / actualWidth);
     initialScaleY = initialScaleX;
     (*rheight) = initialScaleY*actualHeight;
   }
@@ -1675,70 +2166,86 @@ bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rh
 }
 
 // Scale to fit size
-void wxPseudoMetaFile::ScaleTo(float w, float h)
+void wxPseudoMetaFile::ScaleTo(double w, double h)
 {
-  float scaleX = (float)(w/m_width);
-  float scaleY = (float)(h/m_height);
+  double scaleX = (double)(w/m_width);
+  double scaleY = (double)(h/m_height);
 
   // Do the scaling
   Scale(scaleX, scaleY);
 }
 
-void wxPseudoMetaFile::GetBounds(float *boundMinX, float *boundMinY, float *boundMaxX, float *boundMaxY)
+void wxPseudoMetaFile::GetBounds(double *boundMinX, double *boundMinY, double *boundMaxX, double *boundMaxY)
 {
-  float maxX = (float) -99999.9;
-  float maxY = (float) -99999.9;
-  float minX = (float) 99999.9;
-  float minY = (float) 99999.9;
+  double maxX = (double) -99999.9;
+  double maxY = (double) -99999.9;
+  double minX = (double) 99999.9;
+  double minY = (double) 99999.9;
 
   wxNode *node = m_ops.First();
   while (node)
   {
     wxDrawOp *op = (wxDrawOp *)node->Data();
-    switch (op->op)
+    switch (op->GetOp())
     {
       case DRAWOP_DRAW_LINE:
       case DRAWOP_DRAW_RECT:
       case DRAWOP_DRAW_ROUNDED_RECT:
       case DRAWOP_DRAW_ELLIPSE:
       case DRAWOP_DRAW_POINT:
-      case DRAWOP_DRAW_ARC:
       case DRAWOP_DRAW_TEXT:
       {
         wxOpDraw *opDraw = (wxOpDraw *)op;
-        if (opDraw->x1 < minX) minX = opDraw->x1;
-        if (opDraw->x1 > maxX) maxX = opDraw->x1;
-        if (opDraw->y1 < minY) minY = opDraw->y1;
-        if (opDraw->y1 > maxY) maxY = opDraw->y1;
-        if (op->op == DRAWOP_DRAW_LINE)
+        if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
+        if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
+        if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
+        if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
+        if (op->GetOp() == DRAWOP_DRAW_LINE)
         {
-          if (opDraw->x2 < minX) minX = opDraw->x2;
-          if (opDraw->x2 > maxX) maxX = opDraw->x2;
-          if (opDraw->y2 < minY) minY = opDraw->y2;
-          if (opDraw->y2 > maxY) maxY = opDraw->y2;
+          if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
+          if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
+          if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
+          if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
         }
-        else if (op->op == DRAWOP_DRAW_RECT ||
-                 op->op == DRAWOP_DRAW_ROUNDED_RECT ||
-                 op->op == DRAWOP_DRAW_ELLIPSE)
+        else if (op->GetOp() == DRAWOP_DRAW_RECT ||
+                 op->GetOp() == DRAWOP_DRAW_ROUNDED_RECT ||
+                 op->GetOp() == DRAWOP_DRAW_ELLIPSE)
         {
-          if ((opDraw->x1 + opDraw->x2) < minX) minX = (opDraw->x1 + opDraw->x2);
-          if ((opDraw->x1 + opDraw->x2) > maxX) maxX = (opDraw->x1 + opDraw->x2);
-          if ((opDraw->y1 + opDraw->y2) < minY) minY = (opDraw->y1 + opDraw->y2);
-          if ((opDraw->y1 + opDraw->y2) > maxY) maxY = (opDraw->y1 + opDraw->y2);
+          if ((opDraw->m_x1 + opDraw->m_x2) < minX) minX = (opDraw->m_x1 + opDraw->m_x2);
+          if ((opDraw->m_x1 + opDraw->m_x2) > maxX) maxX = (opDraw->m_x1 + opDraw->m_x2);
+          if ((opDraw->m_y1 + opDraw->m_y2) < minY) minY = (opDraw->m_y1 + opDraw->m_y2);
+          if ((opDraw->m_y1 + opDraw->m_y2) > maxY) maxY = (opDraw->m_y1 + opDraw->m_y2);
         }
         break;
       }
+      case DRAWOP_DRAW_ARC:
+      {
+        // TODO: don't yet know how to calculate the bounding box
+        // for an arc. So pretend it's a line; to get a correct
+        // bounding box, draw a blank rectangle first, of the correct
+        // size.
+        wxOpDraw *opDraw = (wxOpDraw *)op;
+        if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
+        if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
+        if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
+        if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
+        if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
+        if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
+        if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
+        if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
+        break;
+      }
       case DRAWOP_DRAW_POLYLINE:
       case DRAWOP_DRAW_POLYGON:
       case DRAWOP_DRAW_SPLINE:
       {
         wxOpPolyDraw *poly = (wxOpPolyDraw *)op;
-        for (int i = 0; i < poly->noPoints; i++)
+        for (int i = 0; i < poly->m_noPoints; i++)
         {
-          if (poly->points[i].x < minX) minX = poly->points[i].x;
-          if (poly->points[i].x > maxX) maxX = poly->points[i].x;
-          if (poly->points[i].y < minY) minY = poly->points[i].y;
-          if (poly->points[i].y > maxY) maxY = poly->points[i].y;
+          if (poly->m_points[i].x < minX) minX = poly->m_points[i].x;
+          if (poly->m_points[i].x > maxX) maxX = poly->m_points[i].x;
+          if (poly->m_points[i].y < minY) minY = poly->m_points[i].y;
+          if (poly->m_points[i].y > maxY) maxY = poly->m_points[i].y;
         }
         break;
       }
@@ -1753,9 +2260,230 @@ void wxPseudoMetaFile::GetBounds(float *boundMinX, float *boundMinY, float *boun
   *boundMaxX = maxX;
   *boundMaxY = maxY;
 /*
-  *w = (float)fabs(maxX - minX);
-  *h = (float)fabs(maxY - minY);
+  *w = (double)fabs(maxX - minX);
+  *h = (double)fabs(maxY - minY);
 */
 }
 
+// Calculate size from current operations
+void wxPseudoMetaFile::CalculateSize(wxDrawnShape* shape)
+{
+  double boundMinX, boundMinY, boundMaxX, boundMaxY;
+
+  GetBounds(& boundMinX, & boundMinY, & boundMaxX, & boundMaxY);
+
+  SetSize(boundMaxX - boundMinX, boundMaxY - boundMinY);
+
+  if (shape)
+  {
+    shape->SetWidth(m_width);
+    shape->SetHeight(m_height);
+  }
+}
+
+// Set of functions for drawing into a pseudo metafile.
+// They use integers, but doubles are used internally for accuracy
+// when scaling.
+
+void wxPseudoMetaFile::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_LINE,
+          (double) pt1.x, (double) pt1.y, (double) pt2.x, (double) pt2.y);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawRectangle(const wxRect& rect)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_RECT,
+          (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawRoundedRectangle(const wxRect& rect, double radius)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
+          (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+
+    theOp->m_radius = radius;
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawEllipse(const wxRect& rect)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
+          (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ARC,
+          (double) centrePt.x, (double) centrePt.y, (double) startPt.x, (double) startPt.y);
+
+    theOp->m_x3 = (double) endPt.x;
+    theOp->m_y3 = (double) endPt.y;
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
+{
+    const double pi = 3.1415926535897932384626433832795 ;
+
+    double startAngleRadians = startAngle* (pi*2.0/360.0);
+    double endAngleRadians = endAngle* (pi*2.0/360.0);
+
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPTIC_ARC,
+          (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+
+    theOp->m_x3 = startAngleRadians;
+    theOp->m_y3 = endAngleRadians;
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawPoint(const wxPoint& pt)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_POINT,
+          (double) pt.x, (double) pt.y, 0.0, 0.0);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawText(const wxString& text, const wxPoint& pt)
+{
+    wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_TEXT,
+          (double) pt.x, (double) pt.y, 0.0, 0.0);
+
+    theOp->m_textString = copystring(text);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawLines(int n, wxPoint pts[])
+{
+    wxRealPoint* realPoints = new wxRealPoint[n];
+    int i;
+    for (i = 0; i < n; i++)
+    {
+        realPoints[i].x = pts[i].x;
+        realPoints[i].y = pts[i].y;
+    }
+    wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE, n, realPoints);
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::DrawPolygon(int n, wxPoint pts[], int flags)
+{
+    wxRealPoint* realPoints = new wxRealPoint[n];
+    int i;
+    for (i = 0; i < n; i++)
+    {
+        realPoints[i].x = pts[i].x;
+        realPoints[i].y = pts[i].y;
+    }
+    wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYGON, n, realPoints);
+    m_ops.Append(theOp);
+
+    if (flags & oglMETAFLAGS_OUTLINE)
+        m_outlineOp = (m_ops.Number() - 1);
+}
+
+void wxPseudoMetaFile::DrawSpline(int n, wxPoint pts[])
+{
+    wxRealPoint* realPoints = new wxRealPoint[n];
+    int i;
+    for (i = 0; i < n; i++)
+    {
+        realPoints[i].x = pts[i].x;
+        realPoints[i].y = pts[i].y;
+    }
+    wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_SPLINE, n, realPoints);
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::SetClippingRect(const wxRect& rect)
+{
+    wxOpSetClipping* theOp = new wxOpSetClipping(DRAWOP_SET_CLIPPING_RECT,
+        (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
+}
+
+void wxPseudoMetaFile::DestroyClippingRect()
+{
+    wxOpSetClipping* theOp = new wxOpSetClipping(DRAWOP_DESTROY_CLIPPING_RECT,
+        0.0, 0.0, 0.0, 0.0);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::SetPen(wxPen* pen, bool isOutline)
+{
+    m_gdiObjects.Append(pen);
+    int n = m_gdiObjects.Number();
+
+    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_PEN, this, n - 1);
+
+    m_ops.Append(theOp);
+
+    if (isOutline)
+    {
+        m_outlineColours.Append((wxObject*) (n - 1));
+    }
+}
+
+void wxPseudoMetaFile::SetBrush(wxBrush* brush, bool isFill)
+{
+    m_gdiObjects.Append(brush);
+    int n = m_gdiObjects.Number();
+
+    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BRUSH, this, n - 1);
+
+    m_ops.Append(theOp);
+
+    if (isFill)
+    {
+        m_fillColours.Append((wxObject*) (n - 1));
+    }
+}
+
+void wxPseudoMetaFile::SetFont(wxFont* font)
+{
+    m_gdiObjects.Append(font);
+    int n = m_gdiObjects.Number();
+
+    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_FONT, this, n - 1);
+
+    m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::SetTextColour(const wxColour& colour)
+{
+   wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
+   theOp->m_r = colour.Red();
+   theOp->m_g = colour.Green();
+   theOp->m_b = colour.Blue();
+
+   m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::SetBackgroundColour(const wxColour& colour)
+{
+   wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_COLOUR, this, 0);
+   theOp->m_r = colour.Red();
+   theOp->m_g = colour.Green();
+   theOp->m_b = colour.Blue();
+
+   m_ops.Append(theOp);
+}
+
+void wxPseudoMetaFile::SetBackgroundMode(int mode)
+{
+   wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_MODE, this, 0, mode);
+
+   m_ops.Append(theOp);
+}