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