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