]> git.saurik.com Git - wxWidgets.git/blame - utils/ogl/src/drawn.cpp
Added revamped Object Graphics Library (for node/arc diagrams).
[wxWidgets.git] / utils / ogl / src / drawn.cpp
CommitLineData
0fc1a713
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: drawn.cpp
3// Purpose: wxDrawnShape
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "drawn.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include <wx/wxprec.h>
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <wx/wx.h>
25#endif
26
27#ifdef PROLOGIO
28#include <wx/wxexpr.h>
29#endif
30
31#include "basic.h"
32#include "basicp.h"
33#include "canvas.h"
34#include "mfutils.h"
35#include "drawn.h"
36#include "drawnp.h"
37#include "misc.h"
38
39static void IntToHex(unsigned int dec, char *buf);
40static unsigned long HexToInt(char *buf);
41extern char *GraphicsBuffer;
42
43#define gyTYPE_PEN 40
44#define gyTYPE_BRUSH 41
45#define gyTYPE_FONT 42
46
47/*
48 * Drawn object
49 *
50 */
51
52IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape, wxShape)
53
54wxDrawnShape::wxDrawnShape():wxRectangleShape(100.0, 50.0)
55{
56 m_saveToFile = TRUE;
57}
58
59wxDrawnShape::~wxDrawnShape()
60{
61}
62
63void wxDrawnShape::OnDraw(wxDC& dc)
64{
65 // Pass pen and brush in case we have force outline
66 // and fill colours
67 if (m_shadowMode != SHADOW_NONE)
68 {
69 if (m_shadowBrush)
70 m_metafile.m_fillBrush = m_shadowBrush;
71 m_metafile.m_outlinePen = transparent_pen;
72 m_metafile.Draw(dc, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
73 }
74
75 m_metafile.m_outlinePen = m_pen;
76 m_metafile.m_fillBrush = m_brush;
77 m_metafile.Draw(dc, m_xpos, m_ypos);
78}
79
80void wxDrawnShape::SetSize(float w, float h, bool recursive)
81{
82 SetAttachmentSize(w, h);
83
84 float scaleX;
85 float scaleY;
86 if (GetWidth() == 0.0)
87 scaleX = 1.0;
88 else scaleX = w/GetWidth();
89 if (GetHeight() == 0.0)
90 scaleY = 1.0;
91 else scaleY = h/GetHeight();
92
93 m_metafile.Scale(scaleX, scaleY);
94 m_width = w;
95 m_height = h;
96 SetDefaultRegionSize();
97}
98
99void wxDrawnShape::Scale(float sx, float sy)
100{
101 m_metafile.Scale(sx, sy);
102}
103
104void wxDrawnShape::Translate(float x, float y)
105{
106 m_metafile.Translate(x, y);
107}
108
109void wxDrawnShape::Rotate(float x, float y, float theta)
110{
111 if (!m_metafile.GetRotateable())
112 return;
113
114 float actualTheta = theta-m_metafile.m_currentRotation;
115
116 // Rotate metafile
117 m_metafile.Rotate(x, y, theta);
118
119 // Rotate attachment points
120 float sinTheta = (float)sin(actualTheta);
121 float cosTheta = (float)cos(actualTheta);
122 wxNode *node = m_attachmentPoints.First();
123 while (node)
124 {
125 wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
126 float x1 = point->m_x;
127 float y1 = point->m_y;
128 point->m_x = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
129 point->m_y = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
130 node = node->Next();
131 }
132 m_rotation = theta;
133}
134
135#ifdef PROLOGIO
136// Prolog database stuff
137char *wxDrawnShape::GetFunctor()
138{
139 return "node_image";
140}
141
142void wxDrawnShape::WritePrologAttributes(wxExpr *clause)
143{
144 wxRectangleShape::WritePrologAttributes(clause);
145
146 clause->AddAttributeValue("save_metafile", (long)m_saveToFile);
147 if (m_saveToFile)
148 m_metafile.WritePrologAttributes(clause);
149}
150
151void wxDrawnShape::ReadPrologAttributes(wxExpr *clause)
152{
153 wxRectangleShape::ReadPrologAttributes(clause);
154
155 int iVal = (int) m_saveToFile;
156 clause->AssignAttributeValue("save_metafile", &iVal);
157 m_saveToFile = (iVal != 0);
158
159 if (m_saveToFile)
160 m_metafile.ReadPrologAttributes(clause);
161}
162#endif
163
164// Does the copying for this object
165void wxDrawnShape::Copy(wxDrawnShape& copy)
166{
167 wxRectangleShape::Copy(copy);
168 m_metafile.Copy(copy.m_metafile);
169 copy.m_saveToFile = m_saveToFile;
170}
171
172// Returns a new instance, and does the copy for this class. Define for each class.
173wxShape *wxDrawnShape::PrivateCopy()
174{
175 wxDrawnShape *obj = new wxDrawnShape;
176 Copy(*obj);
177 return obj;
178}
179
180bool wxDrawnShape::LoadFromMetaFile(char *filename)
181{
182 return m_metafile.LoadFromMetaFile(filename, &m_width, &m_height);
183}
184
185/*
186 * Individual operations
187 *
188 */
189
190/*
191 * Set font, brush, text colour
192 *
193 */
194
195wxOpSetGDI::wxOpSetGDI(int theOp, wxPseudoMetaFile *theImage, int theGdiIndex, int theMode):
196 wxDrawOp(theOp)
197{
198 gdiIndex = theGdiIndex;
199 image = theImage;
200 mode = theMode;
201}
202
203void wxOpSetGDI::Do(wxDC& dc, float xoffset, float yoffset)
204{
205 switch (op)
206 {
207 case DRAWOP_SET_PEN:
208 {
209 // Check for overriding this operation for outline
210 // colour
211 if (image->m_outlineColours.Member((wxObject *)gdiIndex))
212 {
213 if (image->m_outlinePen)
214 dc.SetPen(image->m_outlinePen);
215 }
216 else
217 {
218 wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
219 if (node)
220 {
221 wxPen *pen = (wxPen *)node->Data();
222 if (pen)
223 dc.SetPen(pen);
224 }
225 }
226 break;
227 }
228 case DRAWOP_SET_BRUSH:
229 {
230 // Check for overriding this operation for outline or fill
231 // colour
232 if (image->m_outlineColours.Member((wxObject *)gdiIndex))
233 {
234 // Need to construct a brush to match the outline pen's colour
235 if (image->m_outlinePen)
236 {
237 wxBrush *br = wxTheBrushList->FindOrCreateBrush(image->m_outlinePen->GetColour(), wxSOLID);
238 if (br)
239 dc.SetBrush(br);
240 }
241 }
242 else if (image->m_fillColours.Member((wxObject *)gdiIndex))
243 {
244 if (image->m_fillBrush)
245 {
246 dc.SetBrush(image->m_fillBrush);
247 }
248 }
249 else
250 {
251 wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
252 if (node)
253 {
254 wxBrush *brush = (wxBrush *)node->Data();
255 if (brush)
256 dc.SetBrush(brush);
257 }
258 }
259 break;
260 }
261 case DRAWOP_SET_FONT:
262 {
263 wxNode *node = image->m_gdiObjects.Nth(gdiIndex);
264 if (node)
265 {
266 wxFont *font = (wxFont *)node->Data();
267 if (font)
268 dc.SetFont(font);
269 }
270 break;
271 }
272 case DRAWOP_SET_TEXT_COLOUR:
273 {
274 wxColour col(r,g,b);
275 dc.SetTextForeground(col);
276 break;
277 }
278 case DRAWOP_SET_BK_COLOUR:
279 {
280 wxColour col(r,g,b);
281 dc.SetTextBackground(col);
282 break;
283 }
284 case DRAWOP_SET_BK_MODE:
285 {
286 dc.SetBackgroundMode(mode);
287 break;
288 }
289 default:
290 break;
291 }
292}
293
294wxDrawOp *wxOpSetGDI::Copy(wxPseudoMetaFile *newImage)
295{
296 wxOpSetGDI *newOp = new wxOpSetGDI(op, newImage, gdiIndex, mode);
297 newOp->r = r;
298 newOp->g = g;
299 newOp->b = b;
300 return newOp;
301}
302
303wxExpr *wxOpSetGDI::WritewxExpr(wxPseudoMetaFile *image)
304{
305 wxExpr *expr = new wxExpr(PrologList);
306 expr->Append(new wxExpr((long)op));
307 switch (op)
308 {
309 case DRAWOP_SET_PEN:
310 case DRAWOP_SET_BRUSH:
311 case DRAWOP_SET_FONT:
312 {
313 expr->Append(new wxExpr((long)gdiIndex));
314 break;
315 }
316 case DRAWOP_SET_TEXT_COLOUR:
317 case DRAWOP_SET_BK_COLOUR:
318 {
319 expr->Append(new wxExpr((long)r));
320 expr->Append(new wxExpr((long)g));
321 expr->Append(new wxExpr((long)b));
322 break;
323 }
324 case DRAWOP_SET_BK_MODE:
325 {
326 expr->Append(new wxExpr((long)mode));
327 break;
328 }
329 default:
330 break;
331 }
332 return expr;
333}
334
335void wxOpSetGDI::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
336{
337 switch (op)
338 {
339 case DRAWOP_SET_PEN:
340 case DRAWOP_SET_BRUSH:
341 case DRAWOP_SET_FONT:
342 {
343 gdiIndex = (int)expr->Nth(1)->IntegerValue();
344 break;
345 }
346 case DRAWOP_SET_TEXT_COLOUR:
347 case DRAWOP_SET_BK_COLOUR:
348 {
349 r = (unsigned char)expr->Nth(1)->IntegerValue();
350 g = (unsigned char)expr->Nth(2)->IntegerValue();
351 b = (unsigned char)expr->Nth(3)->IntegerValue();
352 break;
353 }
354 case DRAWOP_SET_BK_MODE:
355 {
356 mode = (int)expr->Nth(1)->IntegerValue();
357 break;
358 }
359 default:
360 break;
361 }
362}
363
364/*
365 * Set/destroy clipping
366 *
367 */
368
369wxOpSetClipping::wxOpSetClipping(int theOp, float theX1, float theY1,
370 float theX2, float theY2):wxDrawOp(theOp)
371{
372 x1 = theX1;
373 y1 = theY1;
374 x2 = theX2;
375 y2 = theY2;
376}
377
378wxDrawOp *wxOpSetClipping::Copy(wxPseudoMetaFile *newImage)
379{
380 wxOpSetClipping *newOp = new wxOpSetClipping(op, x1, y1, x2, y2);
381 return newOp;
382}
383
384void wxOpSetClipping::Do(wxDC& dc, float xoffset, float yoffset)
385{
386 switch (op)
387 {
388 case DRAWOP_SET_CLIPPING_RECT:
389 {
390 dc.SetClippingRegion(x1 + xoffset, y1 + yoffset, x2 + xoffset, y2 + yoffset);
391 break;
392 }
393 case DRAWOP_DESTROY_CLIPPING_RECT:
394 {
395 dc.DestroyClippingRegion();
396 break;
397 }
398 default:
399 break;
400 }
401}
402
403void wxOpSetClipping::Scale(float xScale, float yScale)
404{
405 x1 *= xScale;
406 y1 *= yScale;
407 x2 *= xScale;
408 y2 *= yScale;
409}
410
411void wxOpSetClipping::Translate(float x, float y)
412{
413 x1 += x;
414 y1 += y;
415}
416
417wxExpr *wxOpSetClipping::WritewxExpr(wxPseudoMetaFile *image)
418{
419 wxExpr *expr = new wxExpr(PrologList);
420 expr->Append(new wxExpr((long)op));
421 switch (op)
422 {
423 case DRAWOP_SET_CLIPPING_RECT:
424 {
425 expr->Append(new wxExpr(x1));
426 expr->Append(new wxExpr(y1));
427 expr->Append(new wxExpr(x2));
428 expr->Append(new wxExpr(y2));
429 break;
430 }
431 default:
432 break;
433 }
434 return expr;
435}
436
437void wxOpSetClipping::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
438{
439 switch (op)
440 {
441 case DRAWOP_SET_CLIPPING_RECT:
442 {
443 x1 = expr->Nth(1)->RealValue();
444 y1 = expr->Nth(2)->RealValue();
445 x2 = expr->Nth(3)->RealValue();
446 y2 = expr->Nth(4)->RealValue();
447 break;
448 }
449 default:
450 break;
451 }
452}
453
454/*
455 * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
456 *
457 */
458
459wxOpDraw::wxOpDraw(int theOp, float theX1, float theY1, float theX2, float theY2,
460 float theRadius, char *s):wxDrawOp(theOp)
461{
462 x1 = theX1;
463 y1 = theY1;
464 x2 = theX2;
465 y2 = theY2;
466 radius = theRadius;
467 if (s) textString = copystring(s);
468 else textString = NULL;
469}
470
471wxOpDraw::~wxOpDraw()
472{
473 if (textString) delete[] textString;
474}
475
476wxDrawOp *wxOpDraw::Copy(wxPseudoMetaFile *newImage)
477{
478 wxOpDraw *newOp = new wxOpDraw(op, x1, y1, x2, y2, radius, textString);
479 return newOp;
480}
481
482void wxOpDraw::Do(wxDC& dc, float xoffset, float yoffset)
483{
484 switch (op)
485 {
486 case DRAWOP_DRAW_LINE:
487 {
488 dc.DrawLine(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
489 break;
490 }
491 case DRAWOP_DRAW_RECT:
492 {
493 dc.DrawRectangle(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
494 break;
495 }
496 case DRAWOP_DRAW_ROUNDED_RECT:
497 {
498 dc.DrawRoundedRectangle(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset, radius);
499 break;
500 }
501 case DRAWOP_DRAW_ELLIPSE:
502 {
503 dc.DrawEllipse(x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset);
504 break;
505 }
506 case DRAWOP_DRAW_POINT:
507 {
508 dc.DrawPoint(x1+xoffset, y1+yoffset);
509 break;
510 }
511 case DRAWOP_DRAW_TEXT:
512 {
513 dc.DrawText(textString, x1+xoffset, y1+yoffset);
514 break;
515 }
516 default:
517 break;
518 }
519}
520
521void wxOpDraw::Scale(float scaleX, float scaleY)
522{
523 x1 *= scaleX;
524 y1 *= scaleY;
525 x2 *= scaleX;
526 y2 *= scaleY;
527 radius *= scaleX;
528}
529
530void wxOpDraw::Translate(float x, float y)
531{
532 x1 += x;
533 y1 += y;
534}
535
536void wxOpDraw::Rotate(float x, float y, float sinTheta, float cosTheta)
537{
538 x1 = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
539 y1 = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
540
541 switch (op)
542 {
543 case DRAWOP_DRAW_LINE:
544 {
545 x2 = x2*cosTheta - y2*sinTheta + x*(1 - cosTheta) + y*sinTheta;
546 y2 = x2*sinTheta + y2*cosTheta + y*(1 - cosTheta) + x*sinTheta;
547 break;
548 }
549 default:
550 break;
551 }
552}
553
554wxExpr *wxOpDraw::WritewxExpr(wxPseudoMetaFile *image)
555{
556 wxExpr *expr = new wxExpr(PrologList);
557 expr->Append(new wxExpr((long)op));
558 switch (op)
559 {
560 case DRAWOP_DRAW_LINE:
561 case DRAWOP_DRAW_RECT:
562 case DRAWOP_DRAW_ELLIPSE:
563 {
564 expr->Append(new wxExpr(x1));
565 expr->Append(new wxExpr(y1));
566 expr->Append(new wxExpr(x2));
567 expr->Append(new wxExpr(y2));
568 break;
569 }
570 case DRAWOP_DRAW_ROUNDED_RECT:
571 {
572 expr->Append(new wxExpr(x1));
573 expr->Append(new wxExpr(y1));
574 expr->Append(new wxExpr(x2));
575 expr->Append(new wxExpr(y2));
576 expr->Append(new wxExpr(radius));
577 break;
578 }
579 case DRAWOP_DRAW_POINT:
580 {
581 expr->Append(new wxExpr(x1));
582 expr->Append(new wxExpr(y1));
583 break;
584 }
585 case DRAWOP_DRAW_TEXT:
586 {
587 expr->Append(new wxExpr(x1));
588 expr->Append(new wxExpr(y1));
589 expr->Append(new wxExpr(PrologString, textString));
590 break;
591 }
592 case DRAWOP_DRAW_ARC:
593 default:
594 {
595 break;
596 }
597 }
598 return expr;
599}
600
601void wxOpDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
602{
603 switch (op)
604 {
605 case DRAWOP_DRAW_LINE:
606 case DRAWOP_DRAW_RECT:
607 case DRAWOP_DRAW_ELLIPSE:
608 {
609 x1 = expr->Nth(1)->RealValue();
610 y1 = expr->Nth(2)->RealValue();
611 x2 = expr->Nth(3)->RealValue();
612 y2 = expr->Nth(4)->RealValue();
613 break;
614 }
615 case DRAWOP_DRAW_ROUNDED_RECT:
616 {
617 x1 = expr->Nth(1)->RealValue();
618 y1 = expr->Nth(2)->RealValue();
619 x2 = expr->Nth(3)->RealValue();
620 y2 = expr->Nth(4)->RealValue();
621 radius = expr->Nth(5)->RealValue();
622 break;
623 }
624 case DRAWOP_DRAW_POINT:
625 {
626 x1 = expr->Nth(1)->RealValue();
627 y1 = expr->Nth(2)->RealValue();
628 break;
629 }
630 case DRAWOP_DRAW_TEXT:
631 {
632 x1 = expr->Nth(1)->RealValue();
633 y1 = expr->Nth(2)->RealValue();
634 textString = copystring(expr->Nth(3)->StringValue());
635 break;
636 }
637 case DRAWOP_DRAW_ARC:
638 default:
639 {
640 break;
641 }
642 }
643}
644
645/*
646 * Draw polygon, polyline, spline
647 *
648 */
649
650wxOpPolyDraw::wxOpPolyDraw(int theOp, int n, wxRealPoint *thePoints):wxDrawOp(theOp)
651{
652 noPoints = n;
653 points = thePoints;
654}
655
656wxOpPolyDraw::~wxOpPolyDraw()
657{
658 delete[] points;
659}
660
661wxDrawOp *wxOpPolyDraw::Copy(wxPseudoMetaFile *newImage)
662{
663 wxRealPoint *newPoints = new wxRealPoint[noPoints];
664 for (int i = 0; i < noPoints; i++)
665 {
666 newPoints[i].x = points[i].x;
667 newPoints[i].y = points[i].y;
668 }
669 wxOpPolyDraw *newOp = new wxOpPolyDraw(op, noPoints, newPoints);
670 return newOp;
671}
672
673void wxOpPolyDraw::Do(wxDC& dc, float xoffset, float yoffset)
674{
675 switch (op)
676 {
677 case DRAWOP_DRAW_POLYLINE:
678 {
679 wxPoint *actualPoints = new wxPoint[noPoints];
680 int i;
681 for (i = 0; i < noPoints; i++)
682 {
683 actualPoints[i].x = (long) points[i].x;
684 actualPoints[i].y = (long) points[i].y;
685 }
686
687 dc.DrawLines(noPoints, actualPoints, xoffset, yoffset);
688
689 delete[] actualPoints;
690 break;
691 }
692 case DRAWOP_DRAW_POLYGON:
693 {
694 wxPoint *actualPoints = new wxPoint[noPoints];
695 int i;
696 for (i = 0; i < noPoints; i++)
697 {
698 actualPoints[i].x = (long) points[i].x;
699 actualPoints[i].y = (long) points[i].y;
700 }
701
702 dc.DrawPolygon(noPoints, actualPoints, xoffset, yoffset);
703
704 delete[] actualPoints;
705 break;
706 }
707 case DRAWOP_DRAW_SPLINE:
708 {
709// dc.DrawSpline(noPoints, points, xoffset, yoffset);
710 break;
711 }
712 default:
713 break;
714 }
715}
716
717void wxOpPolyDraw::Scale(float scaleX, float scaleY)
718{
719 for (int i = 0; i < noPoints; i++)
720 {
721 points[i].x *= scaleX;
722 points[i].y *= scaleY;
723 }
724}
725
726void wxOpPolyDraw::Translate(float x, float y)
727{
728 for (int i = 0; i < noPoints; i++)
729 {
730 points[i].x += x;
731 points[i].y += y;
732 }
733}
734
735void wxOpPolyDraw::Rotate(float x, float y, float sinTheta, float cosTheta)
736{
737 for (int i = 0; i < noPoints; i++)
738 {
739 float x1 = points[i].x;
740 float y1 = points[i].y;
741 points[i].x = x1*cosTheta - y1*sinTheta + x*(1 - cosTheta) + y*sinTheta;
742 points[i].y = x1*sinTheta + y1*cosTheta + y*(1 - cosTheta) + x*sinTheta;
743 }
744}
745
746wxExpr *wxOpPolyDraw::WritewxExpr(wxPseudoMetaFile *image)
747{
748 wxExpr *expr = new wxExpr(PrologList);
749 expr->Append(new wxExpr((long)op));
750 expr->Append(new wxExpr((long)noPoints));
751
752// char buf1[9];
753 char buf2[5];
754 char buf3[5];
755
756 GraphicsBuffer[0] = 0;
757
758 /*
759 * Store each coordinate pair in a hex string to save space.
760 * E.g. "1B9080CD". 4 hex digits per coordinate pair.
761 *
762 */
763
764 for (int i = 0; i < noPoints; i++)
765 {
766 long signedX = (long)(points[i].x*100.0);
767 long signedY = (long)(points[i].y*100.0);
768
769 // Scale to 0 -> 64K
770 long unSignedX = (long)(signedX + 32767.0);
771 long unSignedY = (long)(signedY + 32767.0);
772
773// IntToHex((unsigned int)signedX, buf2);
774// IntToHex((unsigned int)signedY, buf3);
775 IntToHex((int)unSignedX, buf2);
776 IntToHex((int)unSignedY, buf3);
777
778 // Don't overrun the buffer
779 if ((i*8) < 3000)
780 {
781 strcat(GraphicsBuffer, buf2);
782 strcat(GraphicsBuffer, buf3);
783 }
784 }
785 expr->Append(new wxExpr(PrologString, GraphicsBuffer));
786 return expr;
787}
788
789void wxOpPolyDraw::ReadwxExpr(wxPseudoMetaFile *image, wxExpr *expr)
790{
791 noPoints = (int)expr->Nth(1)->IntegerValue();
792
793 char buf1[5];
794 char buf2[5];
795
796 points = new wxRealPoint[noPoints];
797 int i = 0;
798 int bufPtr = 0;
799 wxString hexString = expr->Nth(2)->StringValue();
800 while (i < noPoints)
801 {
802 buf1[0] = hexString[bufPtr];
803 buf1[1] = hexString[bufPtr + 1];
804 buf1[2] = hexString[bufPtr + 2];
805 buf1[3] = hexString[bufPtr + 3];
806 buf1[4] = 0;
807
808 buf2[0] = hexString[bufPtr + 4];
809 buf2[1] = hexString[bufPtr + 5];
810 buf2[2] = hexString[bufPtr + 6];
811 buf2[3] = hexString[bufPtr + 7];
812 buf2[4] = 0;
813
814 bufPtr += 8;
815
816// int signedX = (signed int)HexToInt(buf1);
817// int signedY = (signed int)HexToInt(buf2);
818 long unSignedX = HexToInt(buf1);
819 long unSignedY = HexToInt(buf2);
820 // Scale -32K -> +32K
821 long signedX = unSignedX - 32767;
822 long signedY = unSignedY - 32767;
823#ifdef __WXMSW__
824 int testX = (signed int)unSignedX;
825 int testY = (signed int)unSignedY;
826#endif
827
828 points[i].x = (float)(signedX / 100.0);
829 points[i].y = (float)(signedY / 100.0);
830
831 i ++;
832 }
833}
834
835
836/*
837 * Utilities
838 *
839 */
840
841static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
842 'C', 'D', 'E', 'F' };
843
844// Convert unsigned 16-bit integer to 4-character hex string
845static void IntToHex(unsigned int dec, char *buf)
846{
847 int digit1 = (int)(dec/4096);
848 int digit2 = (int)((dec - (digit1*4096))/256);
849 int digit3 = (int)((dec - (digit1*4096) - (digit2*256))/16);
850 int digit4 = dec - (digit1*4096 + digit2*256 + digit3*16);
851
852 buf[0] = hexArray[digit1];
853 buf[1] = hexArray[digit2];
854 buf[2] = hexArray[digit3];
855 buf[3] = hexArray[digit4];
856 buf[4] = 0;
857}
858
859// One hex digit to decimal number
860static int HexToInt1(char hex)
861{
862 switch (hex)
863 {
864 case '0':
865 return 0;
866 case '1':
867 return 1;
868 case '2':
869 return 2;
870 case '3':
871 return 3;
872 case '4':
873 return 4;
874 case '5':
875 return 5;
876 case '6':
877 return 6;
878 case '7':
879 return 7;
880 case '8':
881 return 8;
882 case '9':
883 return 9;
884 case 'A':
885 return 10;
886 case 'B':
887 return 11;
888 case 'C':
889 return 12;
890 case 'D':
891 return 13;
892 case 'E':
893 return 14;
894 case 'F':
895 return 15;
896 default:
897 return 0;
898 }
899 return 0;
900}
901
902// 4-digit hex string to unsigned integer
903static unsigned long HexToInt(char *buf)
904{
905 long d1 = (long)(HexToInt1(buf[0])*4096.0) ;
906 long d2 = (long)(HexToInt1(buf[1])*256.0) ;
907 long d3 = (long)(HexToInt1(buf[2])*16.0) ;
908 long d4 = (long)(HexToInt1(buf[3])) ;
909 unsigned long n = (long)(d1 + d2 + d3 + d4) ;
910 return n;
911}
912
913/*
914 * wxPseudo meta-file
915 *
916 */
917
918IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile, wxObject)
919
920wxPseudoMetaFile::wxPseudoMetaFile()
921{
922 m_currentRotation = 0;
923 m_rotateable = TRUE;
924 m_width = 0.0;
925 m_height = 0.0;
926}
927
928wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile& mf)
929{
930 mf.Copy(*this);
931}
932
933wxPseudoMetaFile::~wxPseudoMetaFile()
934{
935 Clear();
936}
937
938void wxPseudoMetaFile::Clear()
939{
940 wxNode *node = m_ops.First();
941 while (node)
942 {
943 wxDrawOp *op = (wxDrawOp *)node->Data();
944 delete op;
945 node = node->Next();
946 }
947 m_ops.Clear();
948 m_gdiObjects.Clear();
949}
950
951void wxPseudoMetaFile::Draw(wxDC& dc, float xoffset, float yoffset)
952{
953 wxNode *node = m_ops.First();
954 while (node)
955 {
956 wxDrawOp *op = (wxDrawOp *)node->Data();
957 op->Do(dc, xoffset, yoffset);
958 node = node->Next();
959 }
960}
961
962void wxPseudoMetaFile::Scale(float sx, float sy)
963{
964 wxNode *node = m_ops.First();
965 while (node)
966 {
967 wxDrawOp *op = (wxDrawOp *)node->Data();
968 op->Scale(sx, sy);
969 node = node->Next();
970 }
971 m_width *= sx;
972 m_height *= sy;
973}
974
975void wxPseudoMetaFile::Translate(float x, float y)
976{
977 wxNode *node = m_ops.First();
978 while (node)
979 {
980 wxDrawOp *op = (wxDrawOp *)node->Data();
981 op->Translate(x, y);
982 node = node->Next();
983 }
984}
985
986void wxPseudoMetaFile::Rotate(float x, float y, float theta)
987{
988 float theta1 = theta-m_currentRotation;
989 if (theta1 == 0.0) return;
990 float cosTheta = (float)cos(theta1);
991 float sinTheta = (float)sin(theta1);
992
993 wxNode *node = m_ops.First();
994 while (node)
995 {
996 wxDrawOp *op = (wxDrawOp *)node->Data();
997 op->Rotate(x, y, sinTheta, cosTheta);
998 node = node->Next();
999 }
1000 m_currentRotation = theta;
1001}
1002
1003#ifdef PROLOGIO
1004void wxPseudoMetaFile::WritePrologAttributes(wxExpr *clause)
1005{
1006 // Write width and height
1007 clause->AddAttributeValue("meta_width", m_width);
1008 clause->AddAttributeValue("meta_height", m_height);
1009 clause->AddAttributeValue("meta_rotateable", (long)m_rotateable);
1010
1011 // Write GDI objects
1012 char buf[50];
1013 int i = 1;
1014 wxNode *node = m_gdiObjects.First();
1015 while (node)
1016 {
1017 sprintf(buf, "gdi%d", i);
1018 wxObject *obj = (wxObject *)node->Data();
1019 wxExpr *expr = NULL;
1020 if (obj)
1021 {
1022 if (obj->IsKindOf(CLASSINFO(wxPen)))
1023 {
1024 wxPen *thePen = (wxPen *)obj;
1025 expr = new wxExpr(PrologList);
1026 expr->Append(new wxExpr((long)gyTYPE_PEN));
1027 expr->Append(new wxExpr((long)thePen->GetWidth()));
1028 expr->Append(new wxExpr((long)thePen->GetStyle()));
1029 expr->Append(new wxExpr((long)thePen->GetColour().Red()));
1030 expr->Append(new wxExpr((long)thePen->GetColour().Green()));
1031 expr->Append(new wxExpr((long)thePen->GetColour().Blue()));
1032 }
1033 else if (obj->IsKindOf(CLASSINFO(wxBrush)))
1034 {
1035 wxBrush *theBrush = (wxBrush *)obj;
1036 expr = new wxExpr(PrologList);
1037 expr->Append(new wxExpr((long)gyTYPE_BRUSH));
1038 expr->Append(new wxExpr((long)theBrush->GetStyle()));
1039 expr->Append(new wxExpr((long)theBrush->GetColour().Red()));
1040 expr->Append(new wxExpr((long)theBrush->GetColour().Green()));
1041 expr->Append(new wxExpr((long)theBrush->GetColour().Blue()));
1042 }
1043 else if (obj->IsKindOf(CLASSINFO(wxFont)))
1044 {
1045 wxFont *theFont = (wxFont *)obj;
1046 expr = new wxExpr(PrologList);
1047 expr->Append(new wxExpr((long)gyTYPE_FONT));
1048 expr->Append(new wxExpr((long)theFont->GetPointSize()));
1049 expr->Append(new wxExpr((long)theFont->GetFamily()));
1050 expr->Append(new wxExpr((long)theFont->GetStyle()));
1051 expr->Append(new wxExpr((long)theFont->GetWeight()));
1052 expr->Append(new wxExpr((long)theFont->GetUnderlined()));
1053 }
1054 }
1055 else
1056 {
1057 // If no recognised GDI object, append a place holder anyway.
1058 expr = new wxExpr(PrologList);
1059 expr->Append(new wxExpr((long)0));
1060 }
1061
1062 if (expr)
1063 {
1064 clause->AddAttributeValue(buf, expr);
1065 i ++;
1066 }
1067 node = node->Next();
1068 }
1069
1070 // Write drawing operations
1071 i = 1;
1072 node = m_ops.First();
1073 while (node)
1074 {
1075 sprintf(buf, "op%d", i);
1076 wxDrawOp *op = (wxDrawOp *)node->Data();
1077 wxExpr *expr = op->WritewxExpr(this);
1078 if (expr)
1079 {
1080 clause->AddAttributeValue(buf, expr);
1081 i ++;
1082 }
1083 node = node->Next();
1084 }
1085
1086 // Write outline and fill GDI op lists (if any)
1087 if (m_outlineColours.Number() > 0)
1088 {
1089 wxExpr *outlineExpr = new wxExpr(PrologList);
1090 node = m_outlineColours.First();
1091 while (node)
1092 {
1093 outlineExpr->Append(new wxExpr((long)node->Data()));
1094 node = node->Next();
1095 }
1096 clause->AddAttributeValue("outline_objects", outlineExpr);
1097 }
1098 if (m_fillColours.Number() > 0)
1099 {
1100 wxExpr *fillExpr = new wxExpr(PrologList);
1101 node = m_fillColours.First();
1102 while (node)
1103 {
1104 fillExpr->Append(new wxExpr((long)node->Data()));
1105 node = node->Next();
1106 }
1107 clause->AddAttributeValue("fill_objects", fillExpr);
1108 }
1109
1110}
1111
1112void wxPseudoMetaFile::ReadPrologAttributes(wxExpr *clause)
1113{
1114 clause->AssignAttributeValue("meta_width", &m_width);
1115 clause->AssignAttributeValue("meta_height", &m_height);
1116
1117 int iVal = (int) m_rotateable;
1118 clause->AssignAttributeValue("meta_rotateable", &iVal);
1119 m_rotateable = (iVal != 0);
1120
1121 // Read GDI objects
1122 char buf[50];
1123 int i = 1;
1124 bool keepGoing = TRUE;
1125 while (keepGoing)
1126 {
1127 sprintf(buf, "gdi%d", i);
1128 wxExpr *expr = NULL;
1129 clause->AssignAttributeValue(buf, &expr);
1130 if (!expr)
1131 {
1132 keepGoing = FALSE;
1133 }
1134 else
1135 {
1136 wxExpr *idExpr = expr->Nth(0);
1137 switch (idExpr->IntegerValue())
1138 {
1139 case gyTYPE_PEN:
1140 {
1141 int penWidth = (int)expr->Nth(1)->IntegerValue();
1142 int penStyle = (int)expr->Nth(2)->IntegerValue();
1143 int penRed = (int)expr->Nth(3)->IntegerValue();
1144 int penGreen = (int)expr->Nth(4)->IntegerValue();
1145 int penBlue = (int)expr->Nth(5)->IntegerValue();
1146 wxColour col(penRed, penGreen, penBlue);
1147 wxPen *p = wxThePenList->FindOrCreatePen(col, penWidth, penStyle);
1148 if (!p)
1149 p = wxBLACK_PEN;
1150 m_gdiObjects.Append(p);
1151 break;
1152 }
1153 case gyTYPE_BRUSH:
1154 {
1155 int brushStyle = (int)expr->Nth(1)->IntegerValue();
1156 int brushRed = (int)expr->Nth(2)->IntegerValue();
1157 int brushGreen = (int)expr->Nth(3)->IntegerValue();
1158 int brushBlue = (int)expr->Nth(4)->IntegerValue();
1159 wxColour col(brushRed, brushGreen, brushBlue);
1160 wxBrush *b = wxTheBrushList->FindOrCreateBrush(col, brushStyle);
1161 if (!b)
1162 b = wxWHITE_BRUSH;
1163 m_gdiObjects.Append(b);
1164 break;
1165 }
1166 case gyTYPE_FONT:
1167 {
1168 int fontPointSize = (int)expr->Nth(1)->IntegerValue();
1169 int fontFamily = (int)expr->Nth(2)->IntegerValue();
1170 int fontStyle = (int)expr->Nth(3)->IntegerValue();
1171 int fontWeight = (int)expr->Nth(4)->IntegerValue();
1172 int fontUnderlined = (int)expr->Nth(5)->IntegerValue();
1173 m_gdiObjects.Append(wxTheFontList->FindOrCreateFont(fontPointSize,
1174 fontFamily, fontStyle, fontWeight, (fontUnderlined != 0)));
1175 break;
1176 }
1177 default:
1178 {
1179 // Place holder
1180 m_gdiObjects.Append(NULL);
1181 break;
1182 }
1183 }
1184 i ++;
1185 }
1186 }
1187
1188 // Now read in the operations
1189 keepGoing = TRUE;
1190 i = 1;
1191 while (keepGoing)
1192 {
1193 sprintf(buf, "op%d", i);
1194 wxExpr *expr = NULL;
1195 clause->AssignAttributeValue(buf, &expr);
1196 if (!expr)
1197 {
1198 keepGoing = FALSE;
1199 }
1200 else
1201 {
1202 wxExpr *idExpr = expr->Nth(0);
1203 int opId = (int)idExpr->IntegerValue();
1204 switch (opId)
1205 {
1206 case DRAWOP_SET_PEN:
1207 case DRAWOP_SET_BRUSH:
1208 case DRAWOP_SET_FONT:
1209 case DRAWOP_SET_TEXT_COLOUR:
1210 case DRAWOP_SET_BK_COLOUR:
1211 case DRAWOP_SET_BK_MODE:
1212 {
1213 wxOpSetGDI *theOp = new wxOpSetGDI(opId, this, 0);
1214 theOp->ReadwxExpr(this, expr);
1215 m_ops.Append(theOp);
1216 break;
1217 }
1218
1219 case DRAWOP_SET_CLIPPING_RECT:
1220 case DRAWOP_DESTROY_CLIPPING_RECT:
1221 {
1222 wxOpSetClipping *theOp = new wxOpSetClipping(opId, 0.0, 0.0, 0.0, 0.0);
1223 theOp->ReadwxExpr(this, expr);
1224 m_ops.Append(theOp);
1225 break;
1226 }
1227
1228 case DRAWOP_DRAW_LINE:
1229 case DRAWOP_DRAW_RECT:
1230 case DRAWOP_DRAW_ROUNDED_RECT:
1231 case DRAWOP_DRAW_ELLIPSE:
1232 case DRAWOP_DRAW_POINT:
1233 case DRAWOP_DRAW_ARC:
1234 case DRAWOP_DRAW_TEXT:
1235 {
1236 wxOpDraw *theOp = new wxOpDraw(opId, 0.0, 0.0, 0.0, 0.0);
1237 theOp->ReadwxExpr(this, expr);
1238 m_ops.Append(theOp);
1239 break;
1240 }
1241 case DRAWOP_DRAW_SPLINE:
1242 case DRAWOP_DRAW_POLYLINE:
1243 case DRAWOP_DRAW_POLYGON:
1244 {
1245 wxOpPolyDraw *theOp = new wxOpPolyDraw(opId, 0, NULL);
1246 theOp->ReadwxExpr(this, expr);
1247 m_ops.Append(theOp);
1248 break;
1249 }
1250 default:
1251 break;
1252 }
1253 }
1254 i ++;
1255 }
1256
1257 // Now read in the list of outline and fill operations, if any
1258 wxExpr *expr1 = clause->AttributeValue("outline_objects");
1259 if (expr1)
1260 {
1261 wxExpr *eachExpr = expr1->GetFirst();
1262 while (eachExpr)
1263 {
1264 m_outlineColours.Append((wxObject *)eachExpr->IntegerValue());
1265 eachExpr = eachExpr->GetNext();
1266 }
1267 }
1268 expr1 = clause->AttributeValue("fill_objects");
1269 if (expr1)
1270 {
1271 wxExpr *eachExpr = expr1->GetFirst();
1272 while (eachExpr)
1273 {
1274 m_fillColours.Append((wxObject *)eachExpr->IntegerValue());
1275 eachExpr = eachExpr->GetNext();
1276 }
1277 }
1278}
1279#endif
1280
1281// Does the copying for this object
1282void wxPseudoMetaFile::Copy(wxPseudoMetaFile& copy)
1283{
1284 copy.m_currentRotation = m_currentRotation;
1285 copy.m_width = m_width;
1286 copy.m_height = m_height;
1287 copy.m_rotateable = m_rotateable;
1288
1289 // Copy the GDI objects
1290 wxNode *node = m_gdiObjects.First();
1291 while (node)
1292 {
1293 wxObject *obj = (wxObject *)node->Data();
1294 copy.m_gdiObjects.Append(obj);
1295 node = node->Next();
1296 }
1297
1298 // Copy the operations
1299 node = m_ops.First();
1300 while (node)
1301 {
1302 wxDrawOp *op = (wxDrawOp *)node->Data();
1303 copy.m_ops.Append(op->Copy(&copy));
1304 node = node->Next();
1305 }
1306
1307 // Copy the outline/fill operations
1308 copy.m_outlineColours.Clear();
1309 node = m_outlineColours.First();
1310 while (node)
1311 {
1312 copy.m_outlineColours.Append((wxObject *)node->Data());
1313 node = node->Next();
1314 }
1315 copy.m_fillColours.Clear();
1316 node = m_fillColours.First();
1317 while (node)
1318 {
1319 copy.m_fillColours.Append((wxObject *)node->Data());
1320 node = node->Next();
1321 }
1322}
1323
1324/*
1325 * Pass size of existing image; scale height to
1326 * fit width and return new width and height.
1327 *
1328 */
1329
1330bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, float *rwidth, float *rheight)
1331{
1332 if (!FileExists(filename))
1333 return NULL;
1334
1335 wxXMetaFile *metaFile = new wxXMetaFile;
1336
1337 if (!metaFile->ReadFile(filename))
1338 {
1339 delete metaFile;
1340 return FALSE;
1341 }
1342
1343 float lastX = 0.0;
1344 float lastY = 0.0;
1345
1346 // Convert from metafile records to wxDrawnShape records
1347 wxNode *node = metaFile->metaRecords.First();
1348 while (node)
1349 {
1350 wxMetaRecord *record = (wxMetaRecord *)node->Data();
1351 switch (record->metaFunction)
1352 {
1353 case META_SETBKCOLOR:
1354 {
1355 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BK_COLOUR, this, 0);
1356 op->r = (unsigned char)record->param1;
1357 op->g = (unsigned char)record->param2;
1358 op->b = (unsigned char)record->param3;
1359 m_ops.Append(op);
1360 break;
1361 }
1362 case META_SETBKMODE:
1363 {
1364 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BK_MODE, this, 0, (int)record->param1);
1365 m_ops.Append(op);
1366 break;
1367 }
1368 case META_SETMAPMODE:
1369 {
1370 break;
1371 }
1372// case META_SETROP2:
1373// case META_SETRELABS:
1374// case META_SETPOLYFILLMODE:
1375// case META_SETSTRETCHBLTMODE:
1376// case META_SETTEXTCHAREXTRA:
1377 case META_SETTEXTCOLOR:
1378 {
1379 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
1380 op->r = (unsigned char)record->param1;
1381 op->g = (unsigned char)record->param2;
1382 op->b = (unsigned char)record->param3;
1383 m_ops.Append(op);
1384 break;
1385 }
1386// case META_SETTEXTJUSTIFICATION:
1387// case META_SETWINDOWORG:
1388// case META_SETWINDOWEXT:
1389// case META_SETVIEWPORTORG:
1390// case META_SETVIEWPORTEXT:
1391// case META_OFFSETWINDOWORG:
1392// case META_SCALEWINDOWEXT:
1393// case META_OFFSETVIEWPORTORG:
1394// case META_SCALEVIEWPORTEXT:
1395 case META_LINETO:
1396 {
1397 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_LINE, (float)lastX, (float)lastY,
1398 (float)record->param1, (float)record->param2);
1399 m_ops.Append(op);
1400 break;
1401 }
1402 case META_MOVETO:
1403 {
1404 lastX = (float)record->param1;
1405 lastY = (float)record->param2;
1406 break;
1407 }
1408 case META_EXCLUDECLIPRECT:
1409 {
1410/*
1411 wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
1412 rec->param4 = getshort(handle); // y2
1413 rec->param3 = getshort(handle); // x2
1414 rec->param2 = getshort(handle); // y1
1415 rec->param1 = getshort(handle); // x1
1416*/
1417 break;
1418 }
1419 case META_INTERSECTCLIPRECT:
1420 {
1421/*
1422 rec->param4 = getshort(handle); // y2
1423 rec->param3 = getshort(handle); // x2
1424 rec->param2 = getshort(handle); // y1
1425 rec->param1 = getshort(handle); // x1
1426*/
1427 break;
1428 }
1429// case META_ARC: // DO!!!
1430 case META_ELLIPSE:
1431 {
1432 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
1433 (float)record->param1, (float)record->param2,
1434 (float)(record->param3 - record->param1),
1435 (float)(record->param4 - record->param2));
1436 m_ops.Append(op);
1437 break;
1438 }
1439// case META_FLOODFILL:
1440// case META_PIE: // DO!!!
1441 case META_RECTANGLE:
1442 {
1443 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_RECT,
1444 (float)record->param1, (float)record->param2,
1445 (float)(record->param3 - record->param1),
1446 (float)(record->param4 - record->param2));
1447 m_ops.Append(op);
1448 break;
1449 }
1450 case META_ROUNDRECT:
1451 {
1452 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
1453 (float)record->param1, (float)record->param2,
1454 (float)(record->param3 - record->param1),
1455 (float)(record->param4 - record->param2), (float)record->param5);
1456 m_ops.Append(op);
1457 break;
1458 }
1459// case META_PATBLT:
1460// case META_SAVEDC:
1461 case META_SETPIXEL:
1462 {
1463 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_POINT,
1464 (float)record->param1, (float)record->param2,
1465 0.0, 0.0);
1466
1467// SHOULD SET THE COLOUR - SET PEN?
1468// rec->param3 = getint(handle); // COLORREF
1469 m_ops.Append(op);
1470 break;
1471 }
1472// case META_OFFSETCLIPRGN:
1473 case META_TEXTOUT:
1474 {
1475 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_TEXT,
1476 (float)record->param1, (float)record->param2,
1477 0.0, 0.0, 0.0, record->stringParam);
1478 m_ops.Append(op);
1479 break;
1480 }
1481// case META_BITBLT:
1482// case META_STRETCHBLT:
1483 case META_POLYGON:
1484 {
1485 int n = (int)record->param1;
1486 wxRealPoint *newPoints = new wxRealPoint[n];
1487 for (int i = 0; i < n; i++)
1488 {
1489 newPoints[i].x = record->points[i].x;
1490 newPoints[i].y = record->points[i].y;
1491 }
1492
1493 wxOpPolyDraw *op = new wxOpPolyDraw(DRAWOP_DRAW_POLYGON, n, newPoints);
1494 m_ops.Append(op);
1495 break;
1496 }
1497 case META_POLYLINE:
1498 {
1499 int n = (int)record->param1;
1500 wxRealPoint *newPoints = new wxRealPoint[n];
1501 for (int i = 0; i < n; i++)
1502 {
1503 newPoints[i].x = record->points[i].x;
1504 newPoints[i].y = record->points[i].y;
1505 }
1506
1507 wxOpPolyDraw *op = new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE, n, newPoints);
1508 m_ops.Append(op);
1509 break;
1510 }
1511// case META_ESCAPE:
1512// case META_RESTOREDC:
1513// case META_FILLREGION:
1514// case META_FRAMEREGION:
1515// case META_INVERTREGION:
1516// case META_PAINTREGION:
1517// case META_SELECTCLIPREGION: // DO THIS!
1518 case META_SELECTOBJECT:
1519 {
1520 // The pen, brush etc. has already been created when the metafile
1521 // was read in, so we don't create it - we set it.
1522 wxNode *recNode = metaFile->gdiObjects.Nth((int)record->param2);
1523 if (recNode)
1524 {
1525 wxMetaRecord *gdiRec = (wxMetaRecord *)recNode->Data();
1526 if (gdiRec && (gdiRec->param1 != 0))
1527 {
1528 wxObject *obj = (wxObject *)gdiRec->param1;
1529 if (obj->IsKindOf(CLASSINFO(wxPen)))
1530 {
1531 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_PEN, this, (int)record->param2);
1532 m_ops.Append(op);
1533 }
1534 else if (obj->IsKindOf(CLASSINFO(wxBrush)))
1535 {
1536 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BRUSH, this, (int)record->param2);
1537 m_ops.Append(op);
1538 }
1539 else if (obj->IsKindOf(CLASSINFO(wxFont)))
1540 {
1541 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_FONT, this, (int)record->param2);
1542 m_ops.Append(op);
1543 }
1544 }
1545 }
1546 break;
1547 }
1548// case META_SETTEXTALIGN:
1549// case META_DRAWTEXT:
1550// case META_CHORD:
1551// case META_SETMAPPERFLAGS:
1552// case META_EXTTEXTOUT:
1553// case META_SETDIBTODEV:
1554// case META_SELECTPALETTE:
1555// case META_REALIZEPALETTE:
1556// case META_ANIMATEPALETTE:
1557// case META_SETPALENTRIES:
1558// case META_POLYPOLYGON:
1559// case META_RESIZEPALETTE:
1560// case META_DIBBITBLT:
1561// case META_DIBSTRETCHBLT:
1562 case META_DIBCREATEPATTERNBRUSH:
1563 {
1564 // Place holder
1565 m_gdiObjects.Append(NULL);
1566 break;
1567 }
1568// case META_STRETCHDIB:
1569// case META_EXTFLOODFILL:
1570// case META_RESETDC:
1571// case META_STARTDOC:
1572// case META_STARTPAGE:
1573// case META_ENDPAGE:
1574// case META_ABORTDOC:
1575// case META_ENDDOC:
1576// case META_DELETEOBJECT: // DO!!
1577 case META_CREATEPALETTE:
1578 {
1579 // Place holder
1580 m_gdiObjects.Append(NULL);
1581 break;
1582 }
1583 case META_CREATEBRUSH:
1584 {
1585 // Place holder
1586 m_gdiObjects.Append(NULL);
1587 break;
1588 }
1589 case META_CREATEPATTERNBRUSH:
1590 {
1591 // Place holder
1592 m_gdiObjects.Append(NULL);
1593 break;
1594 }
1595 case META_CREATEPENINDIRECT:
1596 {
1597 // The pen is created when the metafile is read in.
1598 // We keep track of all the GDI objects needed for this
1599 // image so when reading the wxDrawnShape from file,
1600 // we can read in all the GDI objects, then refer
1601 // to them by an index starting from zero thereafter.
1602 m_gdiObjects.Append((wxObject *)record->param1);
1603 break;
1604 }
1605 case META_CREATEFONTINDIRECT:
1606 {
1607 m_gdiObjects.Append((wxObject *)record->param1);
1608 break;
1609 }
1610 case META_CREATEBRUSHINDIRECT:
1611 {
1612 // Don't have to do anything here: the pen is created
1613 // when the metafile is read in.
1614 m_gdiObjects.Append((wxObject *)record->param1);
1615 break;
1616 }
1617 case META_CREATEBITMAPINDIRECT:
1618 {
1619 // Place holder
1620 m_gdiObjects.Append(NULL);
1621 break;
1622 }
1623 case META_CREATEBITMAP:
1624 {
1625 // Place holder
1626 m_gdiObjects.Append(NULL);
1627 break;
1628 }
1629 case META_CREATEREGION:
1630 {
1631 // Place holder
1632 m_gdiObjects.Append(NULL);
1633 break;
1634 }
1635 default:
1636 {
1637 break;
1638 }
1639 }
1640 node = node->Next();
1641 }
1642 float actualWidth = (float)fabs(metaFile->right - metaFile->left);
1643 float actualHeight = (float)fabs(metaFile->bottom - metaFile->top);
1644
1645 float initialScaleX = 1.0;
1646 float initialScaleY = 1.0;
1647
1648 float xoffset, yoffset;
1649
1650 // Translate so origin is at centre of rectangle
1651 if (metaFile->bottom > metaFile->top)
1652 yoffset = - (float)((metaFile->bottom - metaFile->top)/2.0);
1653 else
1654 yoffset = - (float)((metaFile->top - metaFile->bottom)/2.0);
1655
1656 if (metaFile->right > metaFile->left)
1657 xoffset = - (float)((metaFile->right - metaFile->left)/2.0);
1658 else
1659 xoffset = - (float)((metaFile->left - metaFile->right)/2.0);
1660
1661 Translate(xoffset, yoffset);
1662
1663 // Scale to a reasonable size (take the width of this wxDrawnShape
1664 // as a guide)
1665 if (actualWidth != 0.0)
1666 {
1667 initialScaleX = (float)((*rwidth) / actualWidth);
1668 initialScaleY = initialScaleX;
1669 (*rheight) = initialScaleY*actualHeight;
1670 }
1671 Scale(initialScaleX, initialScaleY);
1672
1673 m_width = (actualWidth*initialScaleX);
1674 m_height = *rheight;
1675
1676 delete metaFile;
1677 return TRUE;
1678}
1679
1680// Scale to fit size
1681void wxPseudoMetaFile::ScaleTo(float w, float h)
1682{
1683 float scaleX = (float)(w/m_width);
1684 float scaleY = (float)(h/m_height);
1685
1686 // Do the scaling
1687 Scale(scaleX, scaleY);
1688}
1689
1690void wxPseudoMetaFile::GetBounds(float *boundMinX, float *boundMinY, float *boundMaxX, float *boundMaxY)
1691{
1692 float maxX = (float) -99999.9;
1693 float maxY = (float) -99999.9;
1694 float minX = (float) 99999.9;
1695 float minY = (float) 99999.9;
1696
1697 wxNode *node = m_ops.First();
1698 while (node)
1699 {
1700 wxDrawOp *op = (wxDrawOp *)node->Data();
1701 switch (op->op)
1702 {
1703 case DRAWOP_DRAW_LINE:
1704 case DRAWOP_DRAW_RECT:
1705 case DRAWOP_DRAW_ROUNDED_RECT:
1706 case DRAWOP_DRAW_ELLIPSE:
1707 case DRAWOP_DRAW_POINT:
1708 case DRAWOP_DRAW_ARC:
1709 case DRAWOP_DRAW_TEXT:
1710 {
1711 wxOpDraw *opDraw = (wxOpDraw *)op;
1712 if (opDraw->x1 < minX) minX = opDraw->x1;
1713 if (opDraw->x1 > maxX) maxX = opDraw->x1;
1714 if (opDraw->y1 < minY) minY = opDraw->y1;
1715 if (opDraw->y1 > maxY) maxY = opDraw->y1;
1716 if (op->op == DRAWOP_DRAW_LINE)
1717 {
1718 if (opDraw->x2 < minX) minX = opDraw->x2;
1719 if (opDraw->x2 > maxX) maxX = opDraw->x2;
1720 if (opDraw->y2 < minY) minY = opDraw->y2;
1721 if (opDraw->y2 > maxY) maxY = opDraw->y2;
1722 }
1723 else if (op->op == DRAWOP_DRAW_RECT ||
1724 op->op == DRAWOP_DRAW_ROUNDED_RECT ||
1725 op->op == DRAWOP_DRAW_ELLIPSE)
1726 {
1727 if ((opDraw->x1 + opDraw->x2) < minX) minX = (opDraw->x1 + opDraw->x2);
1728 if ((opDraw->x1 + opDraw->x2) > maxX) maxX = (opDraw->x1 + opDraw->x2);
1729 if ((opDraw->y1 + opDraw->y2) < minY) minY = (opDraw->y1 + opDraw->y2);
1730 if ((opDraw->y1 + opDraw->y2) > maxY) maxY = (opDraw->y1 + opDraw->y2);
1731 }
1732 break;
1733 }
1734 case DRAWOP_DRAW_POLYLINE:
1735 case DRAWOP_DRAW_POLYGON:
1736 case DRAWOP_DRAW_SPLINE:
1737 {
1738 wxOpPolyDraw *poly = (wxOpPolyDraw *)op;
1739 for (int i = 0; i < poly->noPoints; i++)
1740 {
1741 if (poly->points[i].x < minX) minX = poly->points[i].x;
1742 if (poly->points[i].x > maxX) maxX = poly->points[i].x;
1743 if (poly->points[i].y < minY) minY = poly->points[i].y;
1744 if (poly->points[i].y > maxY) maxY = poly->points[i].y;
1745 }
1746 break;
1747 }
1748 default:
1749 break;
1750 }
1751 node = node->Next();
1752 }
1753
1754 *boundMinX = minX;
1755 *boundMinY = minY;
1756 *boundMaxX = maxX;
1757 *boundMaxY = maxY;
1758/*
1759 *w = (float)fabs(maxX - minX);
1760 *h = (float)fabs(maxY - minY);
1761*/
1762}
1763
1764