1/////////////////////////////////////////////////////////////////////////////
2// Name:        mfutils.cpp
3// Purpose:     Metafile utillities
4// Author:      Julian Smart
5// Modified by:
6// Created:     12/07/98
7// RCS-ID:      $Id: mfutils.cpp 35812 2005-10-06 18:17:23Z ABX $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
23#include "wx/metafile.h"
24#include "wx/utils.h"
25
26#include "wx/ogl/ogl.h"
27
28#include <stdio.h>
29
30static char _buf[1024]; // a temp buffer to use inplace of wxBuffer, which is deprecated.
31
32// 16-bit unsigned integer
33static unsigned int getshort(FILE *fp)
34{
35  int c, c1;
36  c = getc(fp);  c1 = getc(fp);
37  unsigned int res = ((unsigned int) c) + (((unsigned int) c1) << 8);
38  return res;
39}
40
41// 16-bit signed integer
42static int getsignedshort(FILE *fp)
43{
44  int c, c1;
45  c = getc(fp);  c1 = getc(fp);
46#if 0
47   // this is not used value, no need to execute it
48  int testRes = ((unsigned int) c) + (((unsigned int) c1) << 8);
49#endif
50  unsigned long res1 = ((unsigned int) c) + (((unsigned int) c1) << 8);
51  int res;
52  if (res1 > 32767)
53    res = (int)(res1 - 65536);
54  else
55    res = (int)(res1);
56  return res;
57}
58
59// 32-bit integer
60static long getint(FILE *fp)
61{
62  int c, c1, c2, c3;
63  c = getc(fp);  c1 = getc(fp);  c2 = getc(fp);  c3 = getc(fp);
64  long res = (long)((long) c) +
65         (((long) c1) << 8) +
66         (((long) c2) << 16) +
67         (((long) c3) << 24);
68  return res;
69}
70
71
72/* Placeable metafile header
73struct mfPLACEABLEHEADER {
74    DWORD  key;         // 32-bit
75    HANDLE hmf;         // 16-bit
76    RECT   bbox;        // 4x16 bit
77    WORD   inch;        // 16-bit
78    DWORD  reserved;    // 32-bit
79    WORD   checksum;    // 16-bit
80};
81*/
82
83wxMetaRecord::~wxMetaRecord(void)
84{
85  if (points) delete[] points;
86  if (stringParam) delete[] stringParam;
87}
88
89wxXMetaFile::wxXMetaFile(const wxChar *file)
90{
91  ok = false;
92  top = 0.0;
93  bottom = 0.0;
94  left = 0.0;
95  right = 0.0;
96
97  if (file)
98    ok = ReadFile(file);
99}
100
101/*
102  Handle table       gdiObjects
103  ------------       ----------
104  [0]                  wxPen
105  [1]----param2---     wxBrush
106  [2]             |    wxFont
107  [3]             | -> wxPen
108
109 The handle table works as follows.
110 When a GDI object is created while reading in the
111 metafile, the (e.g.) createpen record is added to the
112 first free entry in the handle table. The createpen
113 record's param1 is a pointer to the actual wxPen, and
114 its param2 is the index into the gdiObjects list, which only
115 grows and never shrinks (unlike the handle table.)
116
117 When SelectObject(index) is found, the index in the file
118 refers to the position in the handle table. BUT we then
119 set param2 to be the position of the wxPen in gdiObjects,
120 i.e. to param2 of the CreatePen record, itself found in
121 the handle table.
122
123 When an object is deleted, the entry in the handletable is
124 NULLed but the gdiObjects entry is not removed (no point, and
125 allows us to create all GDI objects in advance of playing the
126 metafile).
127*/
128
129
130static wxMetaRecord *HandleTable[100];
131static int HandleTableSize = 0;
132
133void DeleteMetaRecordHandle(int index)
134{
135  HandleTable[index] = NULL;
136}
137
138int AddMetaRecordHandle(wxMetaRecord *record)
139{
140  for (int i = 0; i < HandleTableSize; i++)
141    if (!HandleTable[i])
142    {
143      HandleTable[i] = record;
144      return i;
145    }
146  // No free spaces in table, so append.
147
148  HandleTable[HandleTableSize] = record;
149  HandleTableSize ++;
150  return (HandleTableSize - 1);
151}
152
153bool wxXMetaFile::ReadFile(const wxChar *file)
154{
155  HandleTableSize = 0;
156
157  FILE *handle = wxFopen(file, wxT("rb"));
158  if (!handle) return false;
159
160  // Read placeable metafile header, if any
161  long key = getint(handle);
162
163  if (key == (long) 0x9AC6CDD7)
164  {
165    /* long hmf = */ getshort(handle);
166    int iLeft, iTop, iRight, iBottom;
167    iLeft = getsignedshort(handle);
168    iTop = getsignedshort(handle);
169    iRight = getsignedshort(handle);
170    iBottom = getsignedshort(handle);
171
172    left = (double)iLeft;
173    top = (double)iTop;
174    right = (double)iRight;
175    bottom = (double)iBottom;
176
177    /* int inch = */ getshort(handle);
178    /* long reserved = */ getint(handle);
179    /* int checksum = */ getshort(handle);
180/*
181      double widthInUnits = (double)right - left;
182      double heightInUnits = (double)bottom - top;
183      *width = (int)((widthInUnits*1440.0)/inch);
184      *height = (int)((heightInUnits*1440.0)/inch);
185*/
186  }
187  else rewind(handle);
188
189  // Read METAHEADER
190  int mtType = getshort(handle);
191
192  if (mtType != 1 && mtType != 2)
193  {
194    fclose(handle);
195    return false;
196  }
197
198  /* int mtHeaderSize = */ getshort(handle);
199  int mtVersion = getshort(handle);
200
201  if (mtVersion != 0x0300 && mtVersion != 0x0100)
202  {
203    fclose(handle);
204    return false;
205  }
206
207  /* long mtSize = */ getint(handle);
208  /* int mtNoObjects = */ getshort(handle);
209  /* long mtMaxRecord = */ getint(handle);
210  /* int mtNoParameters = */ getshort(handle);
211
212  while (!feof(handle))
213  {
214    long rdSize = getint(handle);      // 4 bytes
215    int rdFunction = getshort(handle); // 2 bytes
216    if (feof(handle))
217      break;
218
219    switch (rdFunction)
220    {
221      case META_SETBKCOLOR:
222      {
223        wxMetaRecord *rec = new wxMetaRecord(META_SETBKCOLOR);
224        long colorref = getint(handle); // COLORREF
225        rec->param1 = GetRValue(colorref);
226        rec->param2 = GetGValue(colorref);
227        rec->param3 = GetBValue(colorref);
228        metaRecords.Append(rec);
229        break;
230      }
231      case META_SETBKMODE:
232      {
233        wxMetaRecord *rec = new wxMetaRecord(META_SETBKMODE);
234        rec->param1 = getshort(handle); // Background mode
235        if (rec->param1 == OPAQUE) rec->param1 = wxSOLID;
236        else rec->param1 = wxTRANSPARENT;
237        metaRecords.Append(rec);
238        break;
239      }
240      case META_SETMAPMODE:
241      {
242        wxMetaRecord *rec = new wxMetaRecord(META_SETMAPMODE);
243        rec->param1 = getshort(handle);
244        metaRecords.Append(rec);
245        break;
246      }
247//      case META_SETROP2:
248//      case META_SETRELABS:
249//      case META_SETPOLYFILLMODE:
250//      case META_SETSTRETCHBLTMODE:
251//      case META_SETTEXTCHAREXTRA:
252      case META_SETTEXTCOLOR:
253      {
254        wxMetaRecord *rec = new wxMetaRecord(META_SETTEXTCOLOR);
255        long colorref = getint(handle); // COLORREF
256        rec->param1 = GetRValue(colorref);
257        rec->param2 = GetGValue(colorref);
258        rec->param3 = GetBValue(colorref);
259        metaRecords.Append(rec);
260        break;
261      }
262//      case META_SETTEXTJUSTIFICATION:
263      case META_SETWINDOWORG:
264      {
265        wxMetaRecord *rec = new wxMetaRecord(META_SETWINDOWORG);
266        rec->param2 = getshort(handle);
267        rec->param1 = getshort(handle);
268        metaRecords.Append(rec);
269        break;
270      }
271      case META_SETWINDOWEXT:
272      {
273        wxMetaRecord *rec = new wxMetaRecord(META_SETWINDOWEXT);
274        rec->param2 = getshort(handle);
275        rec->param1 = getshort(handle);
276        metaRecords.Append(rec);
277        break;
278      }
279//      case META_SETVIEWPORTORG:
280//      case META_SETVIEWPORTEXT:
281//      case META_OFFSETWINDOWORG:
282//      case META_SCALEWINDOWEXT:
283//      case META_OFFSETVIEWPORTORG:
284//      case META_SCALEVIEWPORTEXT:
285      case META_LINETO:
286      {
287        wxMetaRecord *rec = new wxMetaRecord(META_LINETO);
288        rec->param1 = getshort(handle); // x1
289        rec->param2 = getshort(handle); // y1
290        metaRecords.Append(rec);
291        break;
292      }
293      case META_MOVETO:
294      {
295        wxMetaRecord *rec = new wxMetaRecord(META_MOVETO);
296        rec->param1 = getshort(handle); // x1
297        rec->param2 = getshort(handle); // y1
298        metaRecords.Append(rec);
299        break;
300      }
301      case META_EXCLUDECLIPRECT:
302      {
303        wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
304        rec->param4 = getshort(handle); // y2
305        rec->param3 = getshort(handle); // x2
306        rec->param2 = getshort(handle); // y1
307        rec->param1 = getshort(handle); // x1
308        metaRecords.Append(rec);
309        break;
310      }
311      case META_INTERSECTCLIPRECT:
312      {
313        wxMetaRecord *rec = new wxMetaRecord(META_INTERSECTCLIPRECT);
314        rec->param4 = getshort(handle); // y2
315        rec->param3 = getshort(handle); // x2
316        rec->param2 = getshort(handle); // y1
317        rec->param1 = getshort(handle); // x1
318        metaRecords.Append(rec);
319        break;
320      }
321//      case META_ARC: // DO!!!
322      case META_ELLIPSE:
323      {
324        wxMetaRecord *rec = new wxMetaRecord(META_ELLIPSE);
325        rec->param4 = getshort(handle); // y2
326        rec->param3 = getshort(handle); // x2
327        rec->param2 = getshort(handle); // y1
328        rec->param1 = getshort(handle); // x1
329        metaRecords.Append(rec);
330        break;
331      }
332//      case META_FLOODFILL:
333//      case META_PIE: // DO!!!
334      case META_RECTANGLE:
335      {
336        wxMetaRecord *rec = new wxMetaRecord(META_RECTANGLE);
337        rec->param4 = getshort(handle); // y2
338        rec->param3 = getshort(handle); // x2
339        rec->param2 = getshort(handle); // y1
340        rec->param1 = getshort(handle); // x1
341        metaRecords.Append(rec);
342        break;
343      }
344      case META_ROUNDRECT:
345      {
346        wxMetaRecord *rec = new wxMetaRecord(META_ROUNDRECT);
347        rec->param6 = getshort(handle); // width
348        rec->param5 = getshort(handle); // height
349        rec->param4 = getshort(handle); // y2
350        rec->param3 = getshort(handle); // x2
351        rec->param2 = getshort(handle); // y1
352        rec->param1 = getshort(handle); // x1
353        metaRecords.Append(rec);
354        break;
355      }
356//      case META_PATBLT:
357//      case META_SAVEDC:
358      case META_SETPIXEL:
359      {
360        wxMetaRecord *rec = new wxMetaRecord(META_SETPIXEL);
361        rec->param1 = getshort(handle); // x1
362        rec->param2 = getshort(handle); // y1
363        rec->param3 = getint(handle);   // COLORREF
364        metaRecords.Append(rec);
365        break;
366      }
367//      case META_OFFSETCLIPRGN:
368      case META_TEXTOUT:
369      {
370        wxMetaRecord *rec = new wxMetaRecord(META_TEXTOUT);
371        int count = getshort(handle);
372        rec->stringParam = new wxChar[count+1];
373        fread((void *)rec->stringParam, sizeof(wxChar), count, handle);
374        rec->stringParam[count] = 0;
375        rec->param2 = getshort(handle); // Y
376        rec->param1 = getshort(handle); // X
377        metaRecords.Append(rec);
378        break;
379      }
380/*
381      case META_EXTTEXTOUT:
382      {
383        wxMetaRecord *rec = new wxMetaRecord(META_EXTTEXTOUT);
384        int cellSpacing = getshort(handle);
385        int count = getshort(handle);
386        rec->stringParam = new char[count+1];
387        fread((void *)rec->stringParam, sizeof(char), count, handle);
388        rec->stringParam[count] = 0;
389        // Rectangle
390        int rectY2 = getshort(handle);
391        int rectX2 = getshort(handle);
392        int rectY1 = getshort(handle);
393        int rectX1 = getshort(handle);
394        int rectType = getshort(handle);
395        rec->param2 = getshort(handle); // Y
396        rec->param1 = getshort(handle); // X
397        metaRecords.Append(rec);
398        break;
399      }
400*/
401//      case META_BITBLT:
402//      case META_STRETCHBLT:
403      case META_POLYGON:
404      {
405        wxMetaRecord *rec = new wxMetaRecord(META_POLYGON);
406        rec->param1 = getshort(handle);
407        rec->points = new wxRealPoint[(int)rec->param1];
408        for (int i = 0; i < rec->param1; i++)
409        {
410          rec->points[i].x = getshort(handle);
411          rec->points[i].y = getshort(handle);
412        }
413
414        metaRecords.Append(rec);
415        break;
416      }
417      case META_POLYLINE:
418      {
419        wxMetaRecord *rec = new wxMetaRecord(META_POLYLINE);
420        rec->param1 = (long)getshort(handle);
421        rec->points = new wxRealPoint[(int)rec->param1];
422        for (int i = 0; i < rec->param1; i++)
423        {
424          rec->points[i].x = getshort(handle);
425          rec->points[i].y = getshort(handle);
426        }
427
428        metaRecords.Append(rec);
429        break;
430      }
431//      case META_ESCAPE:
432//      case META_RESTOREDC:
433//      case META_FILLREGION:
434//      case META_FRAMEREGION:
435//      case META_INVERTREGION:
436//      case META_PAINTREGION:
437//      case META_SELECTCLIPREGION: // DO THIS!
438      case META_SELECTOBJECT:
439      {
440        wxMetaRecord *rec = new wxMetaRecord(META_SELECTOBJECT);
441        rec->param1 = (long)getshort(handle); // Position of object in gdiObjects list
442        metaRecords.Append(rec);
443        // param2 gives the index into gdiObjects, which is different from
444        // the index into the handle table.
445        rec->param2 = HandleTable[(int)rec->param1]->param2;
446        break;
447      }
448//      case META_SETTEXTALIGN:
449//      case META_DRAWTEXT:
450//      case META_CHORD:
451//      case META_SETMAPPERFLAGS:
452//      case META_EXTTEXTOUT:
453//      case META_SETDIBTODEV:
454//      case META_SELECTPALETTE:
455//      case META_REALIZEPALETTE:
456//      case META_ANIMATEPALETTE:
457//      case META_SETPALENTRIES:
458//      case META_POLYPOLYGON:
459//      case META_RESIZEPALETTE:
460//      case META_DIBBITBLT:
461//      case META_DIBSTRETCHBLT:
462      case META_DIBCREATEPATTERNBRUSH:
463      {
464        wxMetaRecord *rec = new wxMetaRecord(META_DIBCREATEPATTERNBRUSH);
465        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
466
467        metaRecords.Append(rec);
468        gdiObjects.Append(rec);
469        AddMetaRecordHandle(rec);
470        rec->param2 = (long)(gdiObjects.GetCount() - 1);
471        break;
472      }
473//      case META_STRETCHDIB:
474//      case META_EXTFLOODFILL:
475//      case META_RESETDC:
476//      case META_STARTDOC:
477//      case META_STARTPAGE:
478//      case META_ENDPAGE:
479//      case META_ABORTDOC:
480//      case META_ENDDOC:
481      case META_DELETEOBJECT:
482      {
483        int index = getshort(handle);
484        DeleteMetaRecordHandle(index);
485        break;
486      }
487      case META_CREATEPALETTE:
488      {
489        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPALETTE);
490        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
491
492        metaRecords.Append(rec);
493        gdiObjects.Append(rec);
494        AddMetaRecordHandle(rec);
495        rec->param2 = (long)(gdiObjects.GetCount() - 1);
496        break;
497      }
498      case META_CREATEBRUSH:
499      {
500        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBRUSH);
501        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
502        metaRecords.Append(rec);
503        gdiObjects.Append(rec);
504        AddMetaRecordHandle(rec);
505        rec->param2 = (long)(gdiObjects.GetCount() - 1);
506        break;
507      }
508      case META_CREATEPATTERNBRUSH:
509      {
510        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPATTERNBRUSH);
511        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
512        metaRecords.Append(rec);
513        gdiObjects.Append(rec);
514        AddMetaRecordHandle(rec);
515        rec->param2 = (long)(gdiObjects.GetCount() - 1);
516        break;
517      }
518      case META_CREATEPENINDIRECT:
519      {
520        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPENINDIRECT);
521        int msStyle = getshort(handle); // Style: 2 bytes
522        int x = getshort(handle); // X:     2 bytes
523        /* int y = */ getshort(handle); // Y:     2 bytes
524        long colorref = getint(handle); // COLORREF 4 bytes
525
526        int style;
527        if (msStyle == PS_DOT)
528          style = wxDOT;
529        else if (msStyle == PS_DASH)
530          style = wxSHORT_DASH;
531        else if (msStyle == PS_NULL)
532          style = wxTRANSPARENT;
533        else style = wxSOLID;
534
535        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
536        rec->param1 = (long)wxThePenList->FindOrCreatePen(colour, x, style);
537        metaRecords.Append(rec);
538        gdiObjects.Append(rec);
539
540        AddMetaRecordHandle(rec);
541        rec->param2 = (long)(gdiObjects.GetCount() - 1);
542
543        // For some reason, the size of this record is sometimes 9 words!!!
544        // instead of the usual 8. So read 2 characters extra.
545        if (rdSize == 9)
546        {
547          (void) getshort(handle);
548        }
549        break;
550      }
551      case META_CREATEFONTINDIRECT:
552      {
553        wxMetaRecord *rec = new wxMetaRecord(META_CREATEFONTINDIRECT);
554        int lfHeight = getshort(handle);    // 2 bytes
555        /* int lfWidth = */ getshort(handle);     // 2 bytes
556        /* int lfEsc = */ getshort(handle);       // 2 bytes
557        /* int lfOrient = */ getshort(handle);    // 2 bytes
558        int lfWeight = getshort(handle);    // 2 bytes
559        char lfItalic = (char)getc(handle);       // 1 byte
560        char lfUnderline = (char)getc(handle);    // 1 byte
561        /* char lfStrikeout = */ getc(handle);    // 1 byte
562        /* char lfCharSet = */ getc(handle);      // 1 byte
563        /* char lfOutPrecision = */ getc(handle); // 1 byte
564        /* char lfClipPrecision = */ getc(handle); // 1 byte
565        /* char lfQuality = */ getc(handle);      // 1 byte
566        char lfPitchAndFamily = (char)getc(handle);   // 1 byte (18th)
567        char lfFacename[32];
568        // Read the rest of the record, which is total record size
569        // minus the number of bytes already read (18 record, 6 metarecord
570        // header)
571        fread((void *)lfFacename, sizeof(char), (int)((2*rdSize) - 18 - 6), handle);
572
573        int family;
574        if (lfPitchAndFamily & FF_MODERN)
575          family = wxMODERN;
576        else if (lfPitchAndFamily & FF_MODERN)
577          family = wxMODERN;
578        else if (lfPitchAndFamily & FF_ROMAN)
579          family = wxROMAN;
580        else if (lfPitchAndFamily & FF_SWISS)
581          family = wxSWISS;
582        else if (lfPitchAndFamily & FF_DECORATIVE)
583          family = wxDECORATIVE;
584        else
585          family = wxDEFAULT;
586
587        int weight;
588        if (lfWeight == 300)
589          weight = wxLIGHT;
590        else if (lfWeight == 400)
591          weight = wxNORMAL;
592        else if (lfWeight == 900)
593          weight = wxBOLD;
594        else weight = wxNORMAL;
595
596        int style;
597        if (lfItalic != 0)
598          style = wxITALIC;
599        else
600          style = wxNORMAL;
601
602        // About how many pixels per inch???
603        int logPixelsY = 100;
604        int pointSize = (int)(lfHeight*72.0/logPixelsY);
605
606        wxFont *theFont =
607          wxTheFontList->FindOrCreateFont(pointSize, family, style, weight, (lfUnderline != 0));
608
609        rec->param1 = (long) theFont;
610        metaRecords.Append(rec);
611        gdiObjects.Append(rec);
612        AddMetaRecordHandle(rec);
613        rec->param2 = (long)(gdiObjects.GetCount() - 1);
614        break;
615      }
616      case META_CREATEBRUSHINDIRECT:
617      {
618        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBRUSHINDIRECT);
619        int msStyle = getshort(handle); // Style: 2 bytes
620        long colorref = getint(handle);   // COLORREF: 4 bytes
621        int hatchStyle = getshort(handle); // Hatch style 2 bytes
622
623        int style;
624        switch (msStyle)
625        {
626          case BS_HATCHED:
627          {
628            switch (hatchStyle)
629            {
630              case HS_BDIAGONAL:
631                style = wxBDIAGONAL_HATCH;
632                break;
633              case HS_DIAGCROSS:
634                style = wxCROSSDIAG_HATCH;
635                break;
636              case HS_FDIAGONAL:
637                style = wxFDIAGONAL_HATCH;
638                break;
639              case HS_HORIZONTAL:
640                style = wxHORIZONTAL_HATCH;
641                break;
642              case HS_VERTICAL:
643                style = wxVERTICAL_HATCH;
644                break;
645              default:
646              case HS_CROSS:
647                style = wxCROSS_HATCH;
648                break;
649            }
650            break;
651          }
652#if PS_DOT != BS_HATCHED
653          /* ABX 30.12.2003                                   */
654          /* in microsoft/include/wingdi.h  both are the same */
655          /* in fact I'm not sure  why pen related PS_XXX and */
656          /* BS_XXX constants are all mixed into single style */
657          case PS_DOT:
658            style = wxDOT;
659            break;
660#endif
661          case PS_DASH:
662            style = wxSHORT_DASH;
663            break;
664          case PS_NULL:
665            style = wxTRANSPARENT;
666            break;
667          case BS_SOLID:
668          default:
669            style = wxSOLID;
670            break;
671        }
672
673        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
674        rec->param1 = (long)wxTheBrushList->FindOrCreateBrush(colour, style);
675        metaRecords.Append(rec);
676        gdiObjects.Append(rec);
677        AddMetaRecordHandle(rec);
678        rec->param2 = (long)(gdiObjects.GetCount() - 1);
679        break;
680      }
681      case META_CREATEBITMAPINDIRECT:
682      {
683        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBITMAPINDIRECT);
684        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
685
686        metaRecords.Append(rec);
687        gdiObjects.Append(rec);
688        AddMetaRecordHandle(rec);
689        rec->param2 = (long)(gdiObjects.GetCount() - 1);
690        break;
691      }
692      case META_CREATEBITMAP:
693      {
694        wxMetaRecord *rec = new wxMetaRecord(META_CREATEBITMAP);
695        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
696
697        metaRecords.Append(rec);
698        gdiObjects.Append(rec);
699        AddMetaRecordHandle(rec);
700        rec->param2 = (long)(gdiObjects.GetCount() - 1);
701        break;
702      }
703      case META_CREATEREGION:
704      {
705        wxMetaRecord *rec = new wxMetaRecord(META_CREATEREGION);
706        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
707
708        metaRecords.Append(rec);
709        gdiObjects.Append(rec);
710        AddMetaRecordHandle(rec);
711        rec->param2 = (long)(gdiObjects.GetCount() - 1);
712        break;
713      }
714      default:
715      {
716        fread((void *)_buf, sizeof(char), (int)((2*rdSize) - 6), handle);
717        break;
718      }
719    }
720  }
721  fclose(handle);
722  return true;
723}
724
725wxXMetaFile::~wxXMetaFile(void)
726{
727  wxObjectList::compatibility_iterator node = metaRecords.GetFirst();
728  while (node)
729  {
730    wxMetaRecord *rec = (wxMetaRecord *)node->GetData();
731    delete rec;
732    wxObjectList::compatibility_iterator next = node->GetNext();
733    metaRecords.Erase(node);
734    node = next;
735  }
736}
737
738bool wxXMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height))
739{
740  return false;
741}
742
743bool wxXMetaFile::Play(wxDC *dc)
744{
745  wxObjectList::compatibility_iterator node = metaRecords.GetFirst();
746  while (node)
747  {
748    wxMetaRecord *rec = (wxMetaRecord *)node->GetData();
749    int rdFunction = rec->metaFunction;
750
751    switch (rdFunction)
752    {
753      case META_SETBKCOLOR:
754      {
755        break;
756      }
757      case META_SETBKMODE:
758      {
759        break;
760      }
761      case META_SETMAPMODE:
762      {
763        break;
764      }
765//      case META_SETROP2:
766//      case META_SETRELABS:
767//      case META_SETPOLYFILLMODE:
768//      case META_SETSTRETCHBLTMODE:
769//      case META_SETTEXTCHAREXTRA:
770      case META_SETTEXTCOLOR:
771      {
772        break;
773      }
774//      case META_SETTEXTJUSTIFICATION:
775      case META_SETWINDOWORG:
776      {
777        break;
778      }
779      case META_SETWINDOWEXT:
780      {
781        break;
782      }
783//      case META_SETVIEWPORTORG:
784//      case META_SETVIEWPORTEXT:
785//      case META_OFFSETWINDOWORG:
786//      case META_SCALEWINDOWEXT:
787//      case META_OFFSETVIEWPORTORG:
788//      case META_SCALEVIEWPORTEXT:
789      case META_LINETO:
790      {
791        long x1 = rec->param1;
792        long y1 = rec->param2;
793        dc->DrawLine((long) lastX, (long) lastY, x1, y1);
794        break;
795      }
796      case META_MOVETO:
797      {
798        lastX = (double)rec->param1;
799        lastY = (double)rec->param2;
800        break;
801      }
802      case META_EXCLUDECLIPRECT:
803      {
804        break;
805      }
806      case META_INTERSECTCLIPRECT:
807      {
808        break;
809      }
810//      case META_ARC: // DO!!!
811      case META_ELLIPSE:
812      {
813        break;
814      }
815//      case META_FLOODFILL:
816//      case META_PIE: // DO!!!
817      case META_RECTANGLE:
818      {
819        dc->DrawRectangle((long)rec->param1, (long)rec->param2,
820                          (long)rec->param3 - rec->param1,
821                          (long)rec->param4 - rec->param2);
822        break;
823      }
824      case META_ROUNDRECT:
825      {
826        dc->DrawRoundedRectangle((long)rec->param1, (long)rec->param2,
827                          (long)rec->param3 - rec->param1,
828                          (long)rec->param4 - rec->param2,
829                          (long)rec->param5);
830        break;
831      }
832//      case META_PATBLT:
833//      case META_SAVEDC:
834      case META_SETPIXEL:
835      {
836//        rec->param1 = getshort(handle); // x1
837//        rec->param2 = getshort(handle); // y1
838//        rec->param3 = getint(handle);   // COLORREF
839        break;
840      }
841//      case META_OFFSETCLIPRGN:
842      case META_TEXTOUT:
843      {
844/*
845        int count = getshort(handle);
846        rec->stringParam = new char[count+1];
847        fread((void *)rec->stringParam, sizeof(char), count, handle);
848        rec->stringParam[count] = 0;
849        rec->param2 = getshort(handle); // Y
850        rec->param1 = getshort(handle); // X
851*/
852        break;
853      }
854//      case META_BITBLT:
855//      case META_STRETCHBLT:
856      case META_POLYGON:
857      {
858/*
859        rec->param1 = getshort(handle);
860        rec->points = new wxRealPoint[(int)rec->param1];
861        for (int i = 0; i < rec->param1; i++)
862        {
863          rec->points[i].x = getshort(handle);
864          rec->points[i].y = getshort(handle);
865        }
866*/
867        break;
868      }
869      case META_POLYLINE:
870      {
871/*
872        wxMetaRecord *rec = new wxMetaRecord(META_POLYLINE);
873        rec->param1 = (long)getshort(handle);
874        rec->points = new wxRealPoint[(int)rec->param1];
875        for (int i = 0; i < rec->param1; i++)
876        {
877          rec->points[i].x = getshort(handle);
878          rec->points[i].y = getshort(handle);
879        }
880*/
881        break;
882      }
883//      case META_ESCAPE:
884//      case META_RESTOREDC:
885//      case META_FILLREGION:
886//      case META_FRAMEREGION:
887//      case META_INVERTREGION:
888//      case META_PAINTREGION:
889//      case META_SELECTCLIPREGION: // DO THIS!
890      case META_SELECTOBJECT:
891      {
892/*
893        wxMetaRecord *rec = new wxMetaRecord(META_SELECTOBJECT);
894        rec->param1 = (long)getshort(handle); // Position of object in gdiObjects list
895*/
896        break;
897      }
898//      case META_SETTEXTALIGN:
899//      case META_DRAWTEXT:
900//      case META_CHORD:
901//      case META_SETMAPPERFLAGS:
902//      case META_EXTTEXTOUT:
903//      case META_SETDIBTODEV:
904//      case META_SELECTPALETTE:
905//      case META_REALIZEPALETTE:
906//      case META_ANIMATEPALETTE:
907//      case META_SETPALENTRIES:
908//      case META_POLYPOLYGON:
909//      case META_RESIZEPALETTE:
910//      case META_DIBBITBLT:
911//      case META_DIBSTRETCHBLT:
912      case META_DIBCREATEPATTERNBRUSH:
913      {
914/*
915        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
916*/
917        break;
918      }
919//      case META_STRETCHDIB:
920//      case META_EXTFLOODFILL:
921//      case META_RESETDC:
922//      case META_STARTDOC:
923//      case META_STARTPAGE:
924//      case META_ENDPAGE:
925//      case META_ABORTDOC:
926//      case META_ENDDOC:
927//      case META_DELETEOBJECT: // DO!!
928      case META_CREATEPALETTE:
929      {
930/*
931        wxMetaRecord *rec = new wxMetaRecord(META_CREATEPALETTE);
932        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
933*/
934        break;
935      }
936      case META_CREATEBRUSH:
937      {
938/*
939        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
940*/
941        break;
942      }
943      case META_CREATEPATTERNBRUSH:
944      {
945/*
946        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
947*/
948        break;
949      }
950      case META_CREATEPENINDIRECT:
951      {
952/*
953        int msStyle = getshort(handle); // Style: 2 bytes
954        int x = getshort(handle); // X:     2 bytes
955        int y = getshort(handle); // Y:     2 bytes
956        int colorref = getint(handle); // COLORREF 4 bytes
957
958        int style;
959        if (msStyle == PS_DOT)
960          style = wxDOT;
961        else if (msStyle == PS_DASH)
962          style = wxSHORT_DASH;
963        else if (msStyle == PS_NULL)
964          style = wxTRANSPARENT;
965        else style = wxSOLID;
966
967        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
968        rec->param1 = (long)wxThePenList->FindOrCreatePen(&colour, x, style);
969*/
970        break;
971      }
972      case META_CREATEFONTINDIRECT:
973      {
974/*
975        int lfHeight = getshort(handle);
976        int lfWidth = getshort(handle);
977        int lfEsc = getshort(handle);
978        int lfOrient = getshort(handle);
979        int lfWeight = getshort(handle);
980        char lfItalic = getc(handle);
981        char lfUnderline = getc(handle);
982        char lfStrikeout = getc(handle);
983        char lfCharSet = getc(handle);
984        char lfOutPrecision = getc(handle);
985        char lfClipPrecision = getc(handle);
986        char lfQuality = getc(handle);
987        char lfPitchAndFamily = getc(handle);
988        char lfFacename[32];
989        fread((void *)lfFacename, sizeof(char), 32, handle);
990
991        int family;
992        if (lfPitchAndFamily & FF_MODERN)
993          family = wxMODERN;
994        else if (lfPitchAndFamily & FF_MODERN)
995          family = wxMODERN;
996        else if (lfPitchAndFamily & FF_ROMAN)
997          family = wxROMAN;
998        else if (lfPitchAndFamily & FF_SWISS)
999          family = wxSWISS;
1000        else if (lfPitchAndFamily & FF_DECORATIVE)
1001          family = wxDECORATIVE;
1002        else
1003          family = wxDEFAULT;
1004
1005        int weight;
1006        if (lfWeight == 300)
1007          weight = wxLIGHT;
1008        else if (lfWeight == 400)
1009          weight = wxNORMAL;
1010        else if (lfWeight == 900)
1011          weight = wxBOLD;
1012        else weight = wxNORMAL;
1013
1014        int style;
1015        if ((bool)lfItalic)
1016          style = wxITALIC;
1017        else
1018          style = wxNORMAL;
1019
1020        // About how many pixels per inch???
1021        int logPixelsY = 100;
1022        int pointSize = (int)(lfHeight*72.0/logPixelsY);
1023
1024        wxFont *theFont =
1025          wxTheFontList->FindOrCreateFont(pointSize, family, style, weight, (bool)lfUnderline);
1026
1027        rec->param1 = (long)theFont;
1028*/
1029        break;
1030      }
1031      case META_CREATEBRUSHINDIRECT:
1032      {
1033/*
1034        int msStyle = getshort(handle); // Style: 2 bytes
1035        int colorref = getint(handle);   // COLORREF: 4 bytes
1036        int hatchStyle = getshort(handle); // Hatch style 2 bytes
1037
1038        int style;
1039        if (msStyle == PS_DOT)
1040          style = wxDOT;
1041        else if (msStyle == PS_DASH)
1042          style = wxSHORT_DASH;
1043        else if (msStyle == PS_NULL)
1044          style = wxTRANSPARENT;
1045        else style = wxSOLID;
1046
1047        wxColour colour(GetRValue(colorref), GetGValue(colorref), GetBValue(colorref));
1048        rec->param1 = (long)wxTheBrushList->FindOrCreateBrush(&colour, wxSOLID);
1049*/
1050        break;
1051      }
1052      case META_CREATEBITMAPINDIRECT:
1053      {
1054/*
1055        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
1056*/
1057        break;
1058      }
1059      case META_CREATEBITMAP:
1060      {
1061/*
1062        fread((void *)wxBuffer, sizeof(char), (int)(rdSize - 3), handle);
1063*/
1064        break;
1065      }
1066      case META_CREATEREGION:
1067      {
1068        dc->DestroyClippingRegion();
1069/*
1070        rec->param1 = getshort(handle); // Style: 2 bytes
1071*/
1072        break;
1073      }
1074      default:
1075      {
1076        break;
1077      }
1078    }
1079    node = node->GetNext();
1080  }
1081  return true;
1082}
1083
1084