]> git.saurik.com Git - wxWidgets.git/blobdiff - src/ogl/mfutils.cpp
Moved OGL to new locations.
[wxWidgets.git] / src / ogl / mfutils.cpp
diff --git a/src/ogl/mfutils.cpp b/src/ogl/mfutils.cpp
new file mode 100644 (file)
index 0000000..b268483
--- /dev/null
@@ -0,0 +1,1085 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mfutils.cpp
+// Purpose:     Metafile utillities
+// Author:      Julian Smart
+// Modified by:
+// Created:     12/07/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart
+// Licence:    wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "mfutils.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/metafile.h>
+#include <wx/utils.h>
+
+#include <wx/ogl/mfutils.h>
+#include <stdio.h>
+
+static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
+  'C', 'D', 'E', 'F' };
+
+static void DecToHex(int dec, char *buf)
+{
+  int firstDigit = (int)(dec/16.0);
+  int secondDigit = (int)(dec - (firstDigit*16.0));
+  buf[0] = hexArray[firstDigit];
+  buf[1] = hexArray[secondDigit];
+  buf[2] = 0;
+}
+// 16-bit unsigned integer
+static unsigned int getshort(FILE *fp)
+{
+  int c, c1;
+  c = getc(fp);  c1 = getc(fp);
+  unsigned int res = ((unsigned int) c) + (((unsigned int) c1) << 8);
+  return res;
+}
+
+// 16-bit signed integer
+static int getsignedshort(FILE *fp)
+{
+  int c, c1;
+  c = getc(fp);  c1 = getc(fp);
+  int testRes = ((unsigned int) c) + (((unsigned int) c1) << 8);
+  unsigned long res1 = ((unsigned int) c) + (((unsigned int) c1) << 8);
+  int res = 0;
+  if (res1 > 32767)
+    res = (int)(res1 - 65536);
+  else
+    res = (int)(res1);
+  return res;
+}
+
+// 32-bit integer
+static long getint(FILE *fp)
+{
+  int c, c1, c2, c3;
+  c = getc(fp);  c1 = getc(fp);  c2 = getc(fp);  c3 = getc(fp);
+  long res = (long)((long) c) +
+         (((long) c1) << 8) + 
+        (((long) c2) << 16) +
+        (((long) c3) << 24);
+  return res;
+}
+
+
+/* Placeable metafile header
+struct mfPLACEABLEHEADER {
+       DWORD   key;         // 32-bit
+       HANDLE  hmf;         // 16-bit
+       RECT    bbox;        // 4x16 bit
+       WORD    inch;        // 16-bit
+       DWORD   reserved;    // 32-bit
+       WORD    checksum;    // 16-bit
+};
+*/
+
+wxMetaRecord::~wxMetaRecord(void)
+{
+  if (points) delete[] points;
+  if (stringParam) delete[] stringParam;
+}
+
+wxXMetaFile::wxXMetaFile(char *file)
+{
+  ok = FALSE;
+  top = 0.0;
+  bottom = 0.0;
+  left = 0.0;
+  right = 0.0;
+  
+  if (file)
+    ok = ReadFile(file);
+}
+
+/*
+  Handle table       gdiObjects
+  ------------       ----------
+  [0]                  wxPen
+  [1]----param2---     wxBrush
+  [2]             |    wxFont
+  [3]             | -> wxPen
+  
+ The handle table works as follows.
+ When a GDI object is created whilst reading in the
+ metafile, the (e.g.) createpen record is added to the
+ first free entry in the handle table. The createpen
+ record's param1 is a pointer to the actual wxPen, and
+ its param2 is the index into the gdiObjects list, which only
+ grows and never shrinks (unlike the handle table.)
+ When SelectObject(index) is found, the index in the file
+ refers to the position in the handle table. BUT we then
+ set param2 to be the position of the wxPen in gdiObjects,
+ i.e. to param2 of the CreatePen record, itself found in
+ the handle table.
+
+ When an object is deleted, the entry in the handletable is
+ NULLed but the gdiObjects entry is not removed (no point, and
+ allows us to create all GDI objects in advance of playing the
+ metafile).
+*/
+
+static wxMetaRecord *HandleTable[100];
+static int HandleTableSize = 0;
+
+void DeleteMetaRecordHandle(int index)
+{
+  HandleTable[index] = NULL;
+}
+
+int AddMetaRecordHandle(wxMetaRecord *record)
+{
+  for (int i = 0; i < HandleTableSize; i++)
+    if (!HandleTable[i])
+    {
+      HandleTable[i] = record;
+      return i;
+    }
+  // No free spaces in table, so append.
+  
+  HandleTable[HandleTableSize] = record;
+  HandleTableSize ++;
+  return (HandleTableSize - 1);
+}
+
+bool wxXMetaFile::ReadFile(char *file)
+{
+  HandleTableSize = 0;
+  
+  FILE *handle = fopen(file, "rb");
+  if (!handle) return FALSE;
+
+  // Read placeable metafile header, if any
+  long key = getint(handle);
+    
+  if (key == (long) 0x9AC6CDD7)
+  {
+    long hmf = getshort(handle);
+    int iLeft, iTop, iRight, iBottom;
+    iLeft = getsignedshort(handle);
+    iTop = getsignedshort(handle);
+    iRight = getsignedshort(handle);
+    iBottom = getsignedshort(handle);
+
+    left = (double)iLeft;
+    top = (double)iTop;
+    right = (double)iRight;
+    bottom = (double)iBottom;
+
+    int inch = getshort(handle);
+    long reserved = getint(handle);
+    int checksum = getshort(handle);
+/*
+      double widthInUnits = (double)right - left;
+      double heightInUnits = (double)bottom - top;
+      *width = (int)((widthInUnits*1440.0)/inch);
+      *height = (int)((heightInUnits*1440.0)/inch);
+*/
+  }
+  else rewind(handle);
+
+  // Read METAHEADER
+  int mtType = getshort(handle);
+
+  if (mtType != 1 && mtType != 2)
+  {
+    fclose(handle);
+    return FALSE;
+  }
+
+  int mtHeaderSize = getshort(handle);
+  int mtVersion = getshort(handle);
+
+  if (mtVersion != 0x0300 && mtVersion != 0x0100)
+  {
+    fclose(handle);
+    return FALSE;
+  }
+  
+  long mtSize = getint(handle);
+  int mtNoObjects = getshort(handle);
+  long mtMaxRecord = getint(handle);
+  int mtNoParameters = getshort(handle);
+
+  while (!feof(handle))
+  {
+    long rdSize = getint(handle);      // 4 bytes
+    int rdFunction = getshort(handle); // 2 bytes
+    if (feof(handle))
+      break;
+
+    switch (rdFunction)
+    {
+      case META_SETBKCOLOR:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETBKCOLOR);
+        long colorref = getint(handle); // COLORREF
+        rec->param1 = GetRValue(colorref);
+        rec->param2 = GetGValue(colorref);
+        rec->param3 = GetBValue(colorref);
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_SETBKMODE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETBKMODE);
+        rec->param1 = getshort(handle); // Background mode
+        if (rec->param1 == OPAQUE) rec->param1 = wxSOLID;
+        else rec->param1 = wxTRANSPARENT;
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_SETMAPMODE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETMAPMODE);
+        rec->param1 = getshort(handle);
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_SETROP2:
+//      case META_SETRELABS:
+//      case META_SETPOLYFILLMODE:
+//      case META_SETSTRETCHBLTMODE:
+//      case META_SETTEXTCHAREXTRA:
+      case META_SETTEXTCOLOR:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETTEXTCOLOR);
+        long colorref = getint(handle); // COLORREF
+        rec->param1 = GetRValue(colorref);
+        rec->param2 = GetGValue(colorref);
+        rec->param3 = GetBValue(colorref);
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_SETTEXTJUSTIFICATION:
+      case META_SETWINDOWORG:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETWINDOWORG);
+        rec->param2 = getshort(handle);
+        rec->param1 = getshort(handle);
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_SETWINDOWEXT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETWINDOWEXT);
+        rec->param2 = getshort(handle);
+        rec->param1 = getshort(handle);
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_SETVIEWPORTORG:
+//      case META_SETVIEWPORTEXT:
+//      case META_OFFSETWINDOWORG:
+//      case META_SCALEWINDOWEXT:
+//      case META_OFFSETVIEWPORTORG:
+//      case META_SCALEVIEWPORTEXT:
+      case META_LINETO:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_LINETO);
+        rec->param1 = getshort(handle); // x1
+        rec->param2 = getshort(handle); // y1
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_MOVETO:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_MOVETO);
+        rec->param1 = getshort(handle); // x1
+        rec->param2 = getshort(handle); // y1
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_EXCLUDECLIPRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
+        rec->param4 = getshort(handle); // y2
+        rec->param3 = getshort(handle); // x2
+        rec->param2 = getshort(handle); // y1
+        rec->param1 = getshort(handle); // x1
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_INTERSECTCLIPRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_INTERSECTCLIPRECT);
+        rec->param4 = getshort(handle); // y2
+        rec->param3 = getshort(handle); // x2
+        rec->param2 = getshort(handle); // y1
+        rec->param1 = getshort(handle); // x1
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_ARC: // DO!!!
+      case META_ELLIPSE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_ELLIPSE);
+        rec->param4 = getshort(handle); // y2
+        rec->param3 = getshort(handle); // x2
+        rec->param2 = getshort(handle); // y1
+        rec->param1 = getshort(handle); // x1
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_FLOODFILL:
+//      case META_PIE: // DO!!!
+      case META_RECTANGLE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_RECTANGLE);
+        rec->param4 = getshort(handle); // y2
+        rec->param3 = getshort(handle); // x2
+        rec->param2 = getshort(handle); // y1
+        rec->param1 = getshort(handle); // x1
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_ROUNDRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_ROUNDRECT);
+        rec->param6 = getshort(handle); // width
+        rec->param5 = getshort(handle); // height
+        rec->param4 = getshort(handle); // y2
+        rec->param3 = getshort(handle); // x2
+        rec->param2 = getshort(handle); // y1
+        rec->param1 = getshort(handle); // x1
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_PATBLT:
+//      case META_SAVEDC:
+      case META_SETPIXEL:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SETPIXEL);
+        rec->param1 = getshort(handle); // x1
+        rec->param2 = getshort(handle); // y1
+        rec->param3 = getint(handle);   // COLORREF
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_OFFSETCLIPRGN:
+      case META_TEXTOUT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_TEXTOUT);
+        int count = getshort(handle);
+        rec->stringParam = new char[count+1];
+        fread((void *)rec->stringParam, sizeof(char), count, handle);
+        rec->stringParam[count] = 0;
+        rec->param2 = getshort(handle); // Y
+        rec->param1 = getshort(handle); // X
+        metaRecords.Append(rec);
+        break;
+      }
+/*
+      case META_EXTTEXTOUT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_EXTTEXTOUT);
+        int cellSpacing = getshort(handle);
+        int count = getshort(handle);
+        rec->stringParam = new char[count+1];
+        fread((void *)rec->stringParam, sizeof(char), count, handle);
+        rec->stringParam[count] = 0;
+        // Rectangle
+        int rectY2 = getshort(handle);
+        int rectX2 = getshort(handle);
+        int rectY1 = getshort(handle);
+        int rectX1 = getshort(handle);
+        int rectType = getshort(handle);
+        rec->param2 = getshort(handle); // Y
+        rec->param1 = getshort(handle); // X
+        metaRecords.Append(rec);
+        break;
+      }
+*/
+//      case META_BITBLT:
+//      case META_STRETCHBLT:
+      case META_POLYGON:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_POLYGON);
+        rec->param1 = getshort(handle);
+        rec->points = new wxRealPoint[(int)rec->param1];
+        for (int i = 0; i < rec->param1; i++)
+        {
+          rec->points[i].x = getshort(handle);
+          rec->points[i].y = getshort(handle);
+        }
+        
+        metaRecords.Append(rec);
+        break;
+      }
+      case META_POLYLINE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_POLYLINE);
+        rec->param1 = (long)getshort(handle);
+        rec->points = new wxRealPoint[(int)rec->param1];
+        for (int i = 0; i < rec->param1; i++)
+        {
+          rec->points[i].x = getshort(handle);
+          rec->points[i].y = getshort(handle);
+        }
+        
+        metaRecords.Append(rec);
+        break;
+      }
+//      case META_ESCAPE:
+//      case META_RESTOREDC:
+//      case META_FILLREGION:
+//      case META_FRAMEREGION:
+//      case META_INVERTREGION:
+//      case META_PAINTREGION:
+//      case META_SELECTCLIPREGION: // DO THIS!
+      case META_SELECTOBJECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_SELECTOBJECT);
+        rec->param1 = (long)getshort(handle); // Position of object in gdiObjects list
+        metaRecords.Append(rec);
+        // param2 gives the index into gdiObjects, which is different from
+        // the index into the handle table.
+        rec->param2 = HandleTable[(int)rec->param1]->param2;
+        break;
+      }
+//      case META_SETTEXTALIGN:
+//      case META_DRAWTEXT:
+//      case META_CHORD:
+//      case META_SETMAPPERFLAGS:
+//      case META_EXTTEXTOUT:
+//      case META_SETDIBTODEV:
+//      case META_SELECTPALETTE:
+//      case META_REALIZEPALETTE:
+//      case META_ANIMATEPALETTE:
+//      case META_SETPALENTRIES:
+//      case META_POLYPOLYGON:
+//      case META_RESIZEPALETTE:
+//      case META_DIBBITBLT:
+//      case META_DIBSTRETCHBLT:
+      case META_DIBCREATEPATTERNBRUSH:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_DIBCREATEPATTERNBRUSH);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+//      case META_STRETCHDIB:
+//      case META_EXTFLOODFILL:
+//      case META_RESETDC:
+//      case META_STARTDOC:
+//      case META_STARTPAGE:
+//      case META_ENDPAGE:
+//      case META_ABORTDOC:
+//      case META_ENDDOC:
+      case META_DELETEOBJECT:
+      {
+        int index = getshort(handle);
+        DeleteMetaRecordHandle(index);
+        break;
+      }
+      case META_CREATEPALETTE:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPALETTE);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEBRUSH:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBRUSH);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEPATTERNBRUSH:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPATTERNBRUSH);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEPENINDIRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPENINDIRECT);
+        int msStyle = getshort(handle); // Style: 2 bytes
+        int x = getshort(handle); // X:     2 bytes
+        int y = getshort(handle); // Y:     2 bytes
+        long colorref = getint(handle); // COLORREF 4 bytes
+
+        int style;
+        if (msStyle == PS_DOT)
+          style = wxDOT;
+        else if (msStyle == PS_DASH)
+          style = wxSHORT_DASH;
+        else if (msStyle == PS_NULL)
+          style = wxTRANSPARENT;
+        else style = wxSOLID;
+
+        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
+        rec->param1 = (long)wxThePenList->FindOrCreatePen(colour, x, style);
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        
+        // For some reason, the size of this record is sometimes 9 words!!!
+        // instead of the usual 8. So read 2 characters extra.
+        if (rdSize == 9)
+        {
+          (void) getshort(handle);
+        }
+        break;
+      }
+      case META_CREATEFONTINDIRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEFONTINDIRECT);
+        int lfHeight = getshort(handle);    // 2 bytes
+        int lfWidth = getshort(handle);     // 2 bytes
+        int lfEsc = getshort(handle);       // 2 bytes
+        int lfOrient = getshort(handle);    // 2 bytes
+        int lfWeight = getshort(handle);    // 2 bytes
+        char lfItalic = getc(handle);       // 1 byte
+        char lfUnderline = getc(handle);    // 1 byte
+        char lfStrikeout = getc(handle);    // 1 byte
+        char lfCharSet = getc(handle);      // 1 byte
+        char lfOutPrecision = getc(handle); // 1 byte
+        char lfClipPrecision = getc(handle); // 1 byte
+        char lfQuality = getc(handle);      // 1 byte
+        char lfPitchAndFamily = getc(handle);   // 1 byte (18th)
+        char lfFacename[32];
+        // Read the rest of the record, which is total record size
+        // minus the number of bytes already read (18 record, 6 metarecord
+        // header)
+        fread((void *)lfFacename, sizeof(char), (int)((2*rdSize) - 18 - 6), handle);
+
+        int family;
+        if (lfPitchAndFamily & FF_MODERN)
+          family = wxMODERN;
+        else if (lfPitchAndFamily & FF_MODERN)
+          family = wxMODERN;
+        else if (lfPitchAndFamily & FF_ROMAN)
+          family = wxROMAN;
+        else if (lfPitchAndFamily & FF_SWISS)
+          family = wxSWISS;
+        else if (lfPitchAndFamily & FF_DECORATIVE)
+          family = wxDECORATIVE;
+        else
+          family = wxDEFAULT;
+
+        int weight;
+        if (lfWeight == 300)
+          weight = wxLIGHT;
+        else if (lfWeight == 400)
+          weight = wxNORMAL;
+        else if (lfWeight == 900)
+          weight = wxBOLD;
+        else weight = wxNORMAL;
+
+        int style;
+        if (lfItalic != 0)
+          style = wxITALIC;
+        else
+          style = wxNORMAL;
+
+        // About how many pixels per inch???
+        int logPixelsY = 100;
+        int pointSize = (int)(lfHeight*72.0/logPixelsY);
+
+        wxFont *theFont =
+          wxTheFontList->FindOrCreateFont(pointSize, family, style, weight, (lfUnderline != 0));
+
+        rec->param1 = (long) theFont;
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEBRUSHINDIRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBRUSHINDIRECT);
+        int msStyle = getshort(handle); // Style: 2 bytes
+        long colorref = getint(handle);   // COLORREF: 4 bytes
+        int hatchStyle = getshort(handle); // Hatch style 2 bytes
+
+        int style;
+        switch (msStyle)
+        {
+          case BS_HATCHED:
+          {
+            switch (hatchStyle)
+            {
+              case HS_BDIAGONAL:
+                style = wxBDIAGONAL_HATCH;
+                break;
+              case HS_DIAGCROSS:
+                style = wxCROSSDIAG_HATCH;
+                break;
+              case HS_FDIAGONAL:
+                style = wxFDIAGONAL_HATCH;
+                break;
+              case HS_HORIZONTAL:
+                style = wxHORIZONTAL_HATCH;
+                break;
+              case HS_VERTICAL:
+                style = wxVERTICAL_HATCH;
+                break;
+              default:
+              case HS_CROSS:
+                style = wxCROSS_HATCH;
+                break;
+            }
+            break;
+          }
+          case BS_SOLID:
+          default:
+            style = wxSOLID;
+            break;
+        }
+        if (msStyle == PS_DOT)
+          style = wxDOT;
+        else if (msStyle == PS_DASH)
+          style = wxSHORT_DASH;
+        else if (msStyle == PS_NULL)
+          style = wxTRANSPARENT;
+        else style = wxSOLID;
+
+        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
+        rec->param1 = (long)wxTheBrushList->FindOrCreateBrush(colour, style);
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEBITMAPINDIRECT:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBITMAPINDIRECT);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEBITMAP:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBITMAP);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      case META_CREATEREGION:
+      {
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEREGION);
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+
+        metaRecords.Append(rec);
+        gdiObjects.Append(rec);
+        AddMetaRecordHandle(rec);
+        rec->param2 = (long)(gdiObjects.Number() - 1);
+        break;
+      }
+      default:
+      {
+        fread((void *)wxBuffer, sizeof(char), (int)((2*rdSize) - 6), handle);
+        break;
+      }
+    }
+  }
+  fclose(handle);
+  return TRUE;
+}
+
+wxXMetaFile::~wxXMetaFile(void)
+{
+  wxNode *node = metaRecords.First();
+  while (node)
+  {
+    wxMetaRecord *rec = (wxMetaRecord *)node->Data();
+    delete rec;
+    wxNode *next = node->Next();
+    delete node;
+    node = next;
+  }
+}
+
+bool wxXMetaFile::SetClipboard(int width, int height)
+{
+  return FALSE;
+}
+
+bool wxXMetaFile::Play(wxDC *dc)
+{
+  wxNode *node = metaRecords.First();
+  while (node)
+  {
+    wxMetaRecord *rec = (wxMetaRecord *)node->Data();
+    int rdFunction = rec->metaFunction;
+
+    switch (rdFunction)
+    {
+      case META_SETBKCOLOR:
+      {
+        break;
+      }
+      case META_SETBKMODE:
+      {
+        break;
+      }
+      case META_SETMAPMODE:
+      {
+        break;
+      }
+//      case META_SETROP2:
+//      case META_SETRELABS:
+//      case META_SETPOLYFILLMODE:
+//      case META_SETSTRETCHBLTMODE:
+//      case META_SETTEXTCHAREXTRA:
+      case META_SETTEXTCOLOR:
+      {
+        break;
+      }
+//      case META_SETTEXTJUSTIFICATION:
+      case META_SETWINDOWORG:
+      {
+        break;
+      }
+      case META_SETWINDOWEXT:
+      {
+        break;
+      }
+//      case META_SETVIEWPORTORG:
+//      case META_SETVIEWPORTEXT:
+//      case META_OFFSETWINDOWORG:
+//      case META_SCALEWINDOWEXT:
+//      case META_OFFSETVIEWPORTORG:
+//      case META_SCALEVIEWPORTEXT:
+      case META_LINETO:
+      {
+        long x1 = rec->param1;
+        long y1 = rec->param2;
+        dc->DrawLine((long) lastX, (long) lastY, x1, y1);
+        break;
+      }
+      case META_MOVETO:
+      {
+        lastX = (double)rec->param1;
+        lastY = (double)rec->param2;
+        break;
+      }
+      case META_EXCLUDECLIPRECT:
+      {
+        break;
+      }
+      case META_INTERSECTCLIPRECT:
+      {
+        break;
+      }
+//      case META_ARC: // DO!!!
+      case META_ELLIPSE:
+      {
+        break;
+      }
+//      case META_FLOODFILL:
+//      case META_PIE: // DO!!!
+      case META_RECTANGLE:
+      {
+        dc->DrawRectangle((long)rec->param1, (long)rec->param2,
+                          (long)rec->param3 - rec->param1,
+                          (long)rec->param4 - rec->param2);
+        break;
+      }
+      case META_ROUNDRECT:
+      {
+        dc->DrawRoundedRectangle((long)rec->param1, (long)rec->param2,
+                          (long)rec->param3 - rec->param1,
+                          (long)rec->param4 - rec->param2,
+                          (long)rec->param5);
+        break;
+      }
+//      case META_PATBLT:
+//      case META_SAVEDC:
+      case META_SETPIXEL:
+      {
+//        rec->param1 = getshort(handle); // x1
+//        rec->param2 = getshort(handle); // y1
+//        rec->param3 = getint(handle);   // COLORREF
+        break;
+      }
+//      case META_OFFSETCLIPRGN:
+      case META_TEXTOUT:
+      {
+/*
+        int count = getshort(handle);
+        rec->stringParam = new char[count+1];
+        fread((void *)rec->stringParam, sizeof(char), count, handle);
+        rec->stringParam[count] = 0;
+        rec->param2 = getshort(handle); // Y
+        rec->param1 = getshort(handle); // X
+*/
+        break;
+      }
+//      case META_BITBLT:
+//      case META_STRETCHBLT:
+      case META_POLYGON:
+      {
+/*
+        rec->param1 = getshort(handle);
+        rec->points = new wxRealPoint[(int)rec->param1];
+        for (int i = 0; i < rec->param1; i++)
+        {
+          rec->points[i].x = getshort(handle);
+          rec->points[i].y = getshort(handle);
+        }
+*/        
+        break;
+      }
+      case META_POLYLINE:
+      {
+/*
+        wxMetaRecord *rec = new wxMetaRecord(META_POLYLINE);
+        rec->param1 = (long)getshort(handle);
+        rec->points = new wxRealPoint[(int)rec->param1];
+        for (int i = 0; i < rec->param1; i++)
+        {
+          rec->points[i].x = getshort(handle);
+          rec->points[i].y = getshort(handle);
+        }
+*/        
+        break;
+      }
+//      case META_ESCAPE:
+//      case META_RESTOREDC:
+//      case META_FILLREGION:
+//      case META_FRAMEREGION:
+//      case META_INVERTREGION:
+//      case META_PAINTREGION:
+//      case META_SELECTCLIPREGION: // DO THIS!
+      case META_SELECTOBJECT:
+      {
+/*
+        wxMetaRecord *rec = new wxMetaRecord(META_SELECTOBJECT);
+        rec->param1 = (long)getshort(handle); // Position of object in gdiObjects list
+*/
+        break;
+      }
+//      case META_SETTEXTALIGN:
+//      case META_DRAWTEXT:
+//      case META_CHORD:
+//      case META_SETMAPPERFLAGS:
+//      case META_EXTTEXTOUT:
+//      case META_SETDIBTODEV:
+//      case META_SELECTPALETTE:
+//      case META_REALIZEPALETTE:
+//      case META_ANIMATEPALETTE:
+//      case META_SETPALENTRIES:
+//      case META_POLYPOLYGON:
+//      case META_RESIZEPALETTE:
+//      case META_DIBBITBLT:
+//      case META_DIBSTRETCHBLT:
+      case META_DIBCREATEPATTERNBRUSH:
+      {
+/*
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/        
+        break;
+      }
+//      case META_STRETCHDIB:
+//      case META_EXTFLOODFILL:
+//      case META_RESETDC:
+//      case META_STARTDOC:
+//      case META_STARTPAGE:
+//      case META_ENDPAGE:
+//      case META_ABORTDOC:
+//      case META_ENDDOC:
+//      case META_DELETEOBJECT: // DO!!
+      case META_CREATEPALETTE:
+      {
+/*
+        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPALETTE);
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/
+        break;
+      }
+      case META_CREATEBRUSH:
+      {
+/*
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/
+        break;
+      }
+      case META_CREATEPATTERNBRUSH:
+      {
+/*
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/
+        break;
+      }
+      case META_CREATEPENINDIRECT:
+      {
+/*
+        int msStyle = getshort(handle); // Style: 2 bytes
+        int x = getshort(handle); // X:     2 bytes
+        int y = getshort(handle); // Y:     2 bytes
+        int colorref = getint(handle); // COLORREF 4 bytes
+
+        int style;
+        if (msStyle == PS_DOT)
+          style = wxDOT;
+        else if (msStyle == PS_DASH)
+          style = wxSHORT_DASH;
+        else if (msStyle == PS_NULL)
+          style = wxTRANSPARENT;
+        else style = wxSOLID;
+
+        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
+        rec->param1 = (long)wxThePenList->FindOrCreatePen(&colour, x, style);
+*/
+        break;
+      }
+      case META_CREATEFONTINDIRECT:
+      {
+/*
+        int lfHeight = getshort(handle);
+        int lfWidth = getshort(handle);
+        int lfEsc = getshort(handle);
+        int lfOrient = getshort(handle);
+        int lfWeight = getshort(handle);
+        char lfItalic = getc(handle);
+        char lfUnderline = getc(handle);
+        char lfStrikeout = getc(handle);
+        char lfCharSet = getc(handle);
+        char lfOutPrecision = getc(handle);
+        char lfClipPrecision = getc(handle);
+        char lfQuality = getc(handle);
+        char lfPitchAndFamily = getc(handle);
+        char lfFacename[32];
+        fread((void *)lfFacename, sizeof(char), 32, handle);
+
+        int family;
+        if (lfPitchAndFamily & FF_MODERN)
+          family = wxMODERN;
+        else if (lfPitchAndFamily & FF_MODERN)
+          family = wxMODERN;
+        else if (lfPitchAndFamily & FF_ROMAN)
+          family = wxROMAN;
+        else if (lfPitchAndFamily & FF_SWISS)
+          family = wxSWISS;
+        else if (lfPitchAndFamily & FF_DECORATIVE)
+          family = wxDECORATIVE;
+        else
+          family = wxDEFAULT;
+
+        int weight;
+        if (lfWeight == 300)
+          weight = wxLIGHT;
+        else if (lfWeight == 400)
+          weight = wxNORMAL;
+        else if (lfWeight == 900)
+          weight = wxBOLD;
+        else weight = wxNORMAL;
+
+        int style;
+        if ((bool)lfItalic)
+          style = wxITALIC;
+        else
+          style = wxNORMAL;
+
+        // About how many pixels per inch???
+        int logPixelsY = 100;
+        int pointSize = (int)(lfHeight*72.0/logPixelsY);
+
+        wxFont *theFont =
+          wxTheFontList->FindOrCreateFont(pointSize, family, style, weight, (bool)lfUnderline);
+
+        rec->param1 = (long)theFont;
+*/
+        break;
+      }
+      case META_CREATEBRUSHINDIRECT:
+      {
+/*
+        int msStyle = getshort(handle); // Style: 2 bytes
+        int colorref = getint(handle);   // COLORREF: 4 bytes
+        int hatchStyle = getshort(handle); // Hatch style 2 bytes
+
+        int style;
+        if (msStyle == PS_DOT)
+          style = wxDOT;
+        else if (msStyle == PS_DASH)
+          style = wxSHORT_DASH;
+        else if (msStyle == PS_NULL)
+          style = wxTRANSPARENT;
+        else style = wxSOLID;
+
+        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
+        rec->param1 = (long)wxTheBrushList->FindOrCreateBrush(&colour, wxSOLID);
+*/
+        break;
+      }
+      case META_CREATEBITMAPINDIRECT:
+      {
+/*
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/        
+        break;
+      }
+      case META_CREATEBITMAP:
+      {
+/*
+        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
+*/        
+        break;
+      }
+      case META_CREATEREGION:
+      {
+        dc->DestroyClippingRegion();
+/*
+        rec->param1 = getshort(handle); // Style: 2 bytes
+*/
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+    node = node->Next();
+  }
+  return TRUE;
+}
+