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 
30 static char _buf[1024]; // a temp buffer to use inplace of wxBuffer, which is deprecated.
31 
32 // 16-bit unsigned integer
getshort(FILE * fp)33 static 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
getsignedshort(FILE * fp)42 static 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
getint(FILE * fp)60 static 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
73 struct 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 
~wxMetaRecord(void)83 wxMetaRecord::~wxMetaRecord(void)
84 {
85   if (points) delete[] points;
86   if (stringParam) delete[] stringParam;
87 }
88 
wxXMetaFile(const wxChar * file)89 wxXMetaFile::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 
130 static wxMetaRecord *HandleTable[100];
131 static int HandleTableSize = 0;
132 
DeleteMetaRecordHandle(int index)133 void DeleteMetaRecordHandle(int index)
134 {
135   HandleTable[index] = NULL;
136 }
137 
AddMetaRecordHandle(wxMetaRecord * record)138 int 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 
ReadFile(const wxChar * file)153 bool 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 
~wxXMetaFile(void)725 wxXMetaFile::~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 
SetClipboard(int WXUNUSED (width),int WXUNUSED (height))738 bool wxXMetaFile::SetClipboard(int WXUNUSED(width), int WXUNUSED(height))
739 {
740   return false;
741 }
742 
Play(wxDC * dc)743 bool 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