]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/ogl/drawn.cpp
-1->wxID_ANY, TRUE->true, FALSE->false and tabs replacements. Correct help system...
[wxWidgets.git] / contrib / src / ogl / 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 #pragma implementation "drawnp.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include <wx/wx.h>
26 #endif
27
28 #if wxUSE_PROLOGIO
29 #include <wx/deprecated/wxexpr.h>
30 #endif
31
32 #include "wx/ogl/ogl.h"
33
34
35 #include <math.h>
36
37 static void IntToHex(unsigned int dec, wxChar *buf);
38 static unsigned long HexToInt(wxChar *buf);
39 extern wxChar *oglBuffer;
40
41 #define gyTYPE_PEN 40
42 #define gyTYPE_BRUSH 41
43 #define gyTYPE_FONT 42
44
45 /*
46 * Drawn object
47 *
48 */
49
50 IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape, wxRectangleShape)
51
52 wxDrawnShape::wxDrawnShape():wxRectangleShape(100.0, 50.0)
53 {
54 m_saveToFile = true;
55 m_currentAngle = oglDRAWN_ANGLE_0;
56 }
57
58 wxDrawnShape::~wxDrawnShape()
59 {
60 }
61
62 void wxDrawnShape::OnDraw(wxDC& dc)
63 {
64 // Pass pen and brush in case we have force outline
65 // and fill colours
66 if (m_shadowMode != SHADOW_NONE)
67 {
68 if (m_shadowBrush)
69 m_metafiles[m_currentAngle].m_fillBrush = m_shadowBrush;
70 m_metafiles[m_currentAngle].m_outlinePen = g_oglTransparentPen;
71 m_metafiles[m_currentAngle].Draw(dc, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
72 }
73
74 m_metafiles[m_currentAngle].m_outlinePen = m_pen;
75 m_metafiles[m_currentAngle].m_fillBrush = m_brush;
76 m_metafiles[m_currentAngle].Draw(dc, m_xpos, m_ypos);
77 }
78
79 void wxDrawnShape::SetSize(double w, double h, bool WXUNUSED(recursive))
80 {
81 SetAttachmentSize(w, h);
82
83 double scaleX;
84 double scaleY;
85 if (GetWidth() == 0.0)
86 scaleX = 1.0;
87 else scaleX = w/GetWidth();
88 if (GetHeight() == 0.0)
89 scaleY = 1.0;
90 else scaleY = h/GetHeight();
91
92 for (int i = 0; i < 4; i++)
93 {
94 if (m_metafiles[i].IsValid())
95 m_metafiles[i].Scale(scaleX, scaleY);
96 }
97 m_width = w;
98 m_height = h;
99 SetDefaultRegionSize();
100 }
101
102 void wxDrawnShape::Scale(double sx, double sy)
103 {
104 int i;
105 for (i = 0; i < 4; i++)
106 {
107 if (m_metafiles[i].IsValid())
108 {
109 m_metafiles[i].Scale(sx, sy);
110 m_metafiles[i].CalculateSize(this);
111 }
112 }
113 }
114
115 void wxDrawnShape::Translate(double x, double y)
116 {
117 int i;
118 for (i = 0; i < 4; i++)
119 {
120 if (m_metafiles[i].IsValid())
121 {
122 m_metafiles[i].Translate(x, y);
123 m_metafiles[i].CalculateSize(this);
124 }
125 }
126 }
127
128 // theta is absolute rotation from the zero position
129 void wxDrawnShape::Rotate(double x, double y, double theta)
130 {
131 m_currentAngle = DetermineMetaFile(theta);
132
133 if (m_currentAngle == 0)
134 {
135 // Rotate metafile
136 if (!m_metafiles[0].GetRotateable())
137 return;
138
139 m_metafiles[0].Rotate(x, y, theta);
140 }
141
142 double actualTheta = theta-m_rotation;
143
144 // Rotate attachment points
145 double sinTheta = (double)sin(actualTheta);
146 double cosTheta = (double)cos(actualTheta);
147 wxNode *node = m_attachmentPoints.GetFirst();
148 while (node)
149 {
150 wxAttachmentPoint *point = (wxAttachmentPoint *)node->GetData();
151 double x1 = point->m_x;
152 double y1 = point->m_y;
153 point->m_x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
154 point->m_y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
155 node = node->GetNext();
156 }
157 m_rotation = theta;
158
159 m_metafiles[m_currentAngle].CalculateSize(this);
160 }
161
162 // Which metafile do we use now? Based on current rotation and validity
163 // of metafiles.
164
165 int wxDrawnShape::DetermineMetaFile(double rotation)
166 {
167 double tolerance = 0.0001;
168 const double pi = 3.1415926535897932384626433832795 ;
169 double angle1 = 0.0;
170 double angle2 = pi/2.0;
171 double angle3 = pi;
172 double angle4 = 3.0*pi/2.0;
173
174 int whichMetafile = 0;
175
176 if (oglRoughlyEqual(rotation, angle1, tolerance))
177 {
178 whichMetafile = 0;
179 }
180 else if (oglRoughlyEqual(rotation, angle2, tolerance))
181 {
182 whichMetafile = 1;
183 }
184 else if (oglRoughlyEqual(rotation, angle3, tolerance))
185 {
186 whichMetafile = 2;
187 }
188 else if (oglRoughlyEqual(rotation, angle4, tolerance))
189 {
190 whichMetafile = 3;
191 }
192
193 if ((whichMetafile > 0) && !m_metafiles[whichMetafile].IsValid())
194 whichMetafile = 0;
195
196 return whichMetafile;
197 }
198
199 void wxDrawnShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
200 {
201 if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
202 {
203 wxNode* node = m_metafiles[m_currentAngle].GetOps().Item(m_metafiles[m_currentAngle].GetOutlineOp());
204 wxASSERT (node != NULL);
205 wxDrawOp* op = (wxDrawOp*) node->GetData();
206
207 if (op->OnDrawOutline(dc, x, y, w, h, m_width, m_height))
208 return;
209 }
210
211 // Default... just use a rectangle
212 wxRectangleShape::OnDrawOutline(dc, x, y, w, h);
213 }
214
215 // Get the perimeter point using the special outline op, if there is one,
216 // otherwise use default wxRectangleShape scheme
217 bool wxDrawnShape::GetPerimeterPoint(double x1, double y1,
218 double x2, double y2,
219 double *x3, double *y3)
220 {
221 if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
222 {
223 wxNode* node = m_metafiles[m_currentAngle].GetOps().Item(m_metafiles[m_currentAngle].GetOutlineOp());
224 wxASSERT (node != NULL);
225 wxDrawOp* op = (wxDrawOp*) node->GetData();
226
227 if (op->GetPerimeterPoint(x1, y1, x2, y2, x3, y3, GetX(), GetY(), GetAttachmentMode()))
228 return true;
229 }
230
231 // Default... just use a rectangle
232 return wxRectangleShape::GetPerimeterPoint(x1, y1, x2, y2, x3, y3);
233 }
234
235 #if wxUSE_PROLOGIO
236 void wxDrawnShape::WriteAttributes(wxExpr *clause)
237 {
238 wxRectangleShape::WriteAttributes(clause);
239
240 clause->AddAttributeValue(_T("current_angle"), (long)m_currentAngle);
241 clause->AddAttributeValue(_T("save_metafile"), (long)m_saveToFile);
242 if (m_saveToFile)
243 {
244 for (int i = 0; i < 4; i++)
245 {
246 if (m_metafiles[i].IsValid())
247 m_metafiles[i].WriteAttributes(clause, i);
248 }
249 }
250 }
251
252 void wxDrawnShape::ReadAttributes(wxExpr *clause)
253 {
254 wxRectangleShape::ReadAttributes(clause);
255
256 int iVal = (int) m_saveToFile;
257 clause->GetAttributeValue(_T("save_metafile"), iVal);
258 clause->GetAttributeValue(_T("current_angle"), m_currentAngle);
259 m_saveToFile = (iVal != 0);
260
261 if (m_saveToFile)
262 {
263 for (int i = 0; i < 4; i++)
264 {
265 m_metafiles[i].ReadAttributes(clause, i);
266 }
267 }
268 }
269 #endif
270
271 // Does the copying for this object
272 void wxDrawnShape::Copy(wxShape& copy)
273 {
274 wxRectangleShape::Copy(copy);
275
276 wxASSERT( copy.IsKindOf(CLASSINFO(wxDrawnShape)) ) ;
277
278 wxDrawnShape& drawnCopy = (wxDrawnShape&) copy;
279
280 for (int i = 0; i < 4; i++)
281 {
282 m_metafiles[i].Copy(drawnCopy.m_metafiles[i]);
283 }
284 drawnCopy.m_saveToFile = m_saveToFile;
285 drawnCopy.m_currentAngle = m_currentAngle;
286 }
287
288 bool wxDrawnShape::LoadFromMetaFile(const wxString& filename)
289 {
290 return m_metafiles[0].LoadFromMetaFile(filename, &m_width, &m_height);
291 }
292
293 // Set of functions for drawing into a pseudo metafile.
294 // They use integers, but doubles are used internally for accuracy
295 // when scaling.
296
297 void wxDrawnShape::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
298 {
299 m_metafiles[m_currentAngle].DrawLine(pt1, pt2);
300 }
301
302 void wxDrawnShape::DrawRectangle(const wxRect& rect)
303 {
304 m_metafiles[m_currentAngle].DrawRectangle(rect);
305 }
306
307 void wxDrawnShape::DrawRoundedRectangle(const wxRect& rect, double radius)
308 {
309 m_metafiles[m_currentAngle].DrawRoundedRectangle(rect, radius);
310 }
311
312 void wxDrawnShape::DrawEllipse(const wxRect& rect)
313 {
314 m_metafiles[m_currentAngle].DrawEllipse(rect);
315 }
316
317 void wxDrawnShape::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
318 {
319 m_metafiles[m_currentAngle].DrawArc(centrePt, startPt, endPt);
320 }
321
322 void wxDrawnShape::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
323 {
324 m_metafiles[m_currentAngle].DrawEllipticArc(rect, startAngle, endAngle);
325 }
326
327 void wxDrawnShape::DrawPoint(const wxPoint& pt)
328 {
329 m_metafiles[m_currentAngle].DrawPoint(pt);
330 }
331
332 void wxDrawnShape::DrawText(const wxString& text, const wxPoint& pt)
333 {
334 m_metafiles[m_currentAngle].DrawText(text, pt);
335 }
336
337 void wxDrawnShape::DrawLines(int n, wxPoint pts[])
338 {
339 m_metafiles[m_currentAngle].DrawLines(n, pts);
340 }
341
342 void wxDrawnShape::DrawPolygon(int n, wxPoint pts[], int flags)
343 {
344 if (flags & oglMETAFLAGS_ATTACHMENTS)
345 {
346 ClearAttachments();
347 int i;
348 for (i = 0; i < n; i++)
349 m_attachmentPoints.Append(new wxAttachmentPoint(i, pts[i].x, pts[i].y));
350 }
351 m_metafiles[m_currentAngle].DrawPolygon(n, pts, flags);
352 }
353
354 void wxDrawnShape::DrawSpline(int n, wxPoint pts[])
355 {
356 m_metafiles[m_currentAngle].DrawSpline(n, pts);
357 }
358
359 void wxDrawnShape::SetClippingRect(const wxRect& rect)
360 {
361 m_metafiles[m_currentAngle].SetClippingRect(rect);
362 }
363
364 void wxDrawnShape::DestroyClippingRect()
365 {
366 m_metafiles[m_currentAngle].DestroyClippingRect();
367 }
368
369 void wxDrawnShape::SetDrawnPen(wxPen* pen, bool isOutline)
370 {
371 m_metafiles[m_currentAngle].SetPen(pen, isOutline);
372 }
373
374 void wxDrawnShape::SetDrawnBrush(wxBrush* brush, bool isFill)
375 {
376 m_metafiles[m_currentAngle].SetBrush(brush, isFill);
377 }
378
379 void wxDrawnShape::SetDrawnFont(wxFont* font)
380 {
381 m_metafiles[m_currentAngle].SetFont(font);
382 }
383
384 void wxDrawnShape::SetDrawnTextColour(const wxColour& colour)
385 {
386 m_metafiles[m_currentAngle].SetTextColour(colour);
387 }
388
389 void wxDrawnShape::SetDrawnBackgroundColour(const wxColour& colour)
390 {
391 m_metafiles[m_currentAngle].SetBackgroundColour(colour);
392 }
393
394 void wxDrawnShape::SetDrawnBackgroundMode(int mode)
395 {
396 m_metafiles[m_currentAngle].SetBackgroundMode(mode);
397 }
398
399
400 /*
401 * Individual operations
402 *
403 */
404
405 /*
406 * Set font, brush, text colour
407 *
408 */
409
410 wxOpSetGDI::wxOpSetGDI(int theOp, wxPseudoMetaFile *theImage, int theGdiIndex, int theMode):
411 wxDrawOp(theOp)
412 {
413 m_gdiIndex = theGdiIndex;
414 m_image = theImage;
415 m_mode = theMode;
416 }
417
418 void wxOpSetGDI::Do(wxDC& dc, double WXUNUSED(xoffset), double WXUNUSED(yoffset))
419 {
420 switch (m_op)
421 {
422 case DRAWOP_SET_PEN:
423 {
424 // Check for overriding this operation for outline
425 // colour
426 if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
427 {
428 if (m_image->m_outlinePen)
429 dc.SetPen(* m_image->m_outlinePen);
430 }
431 else
432 {
433 wxNode *node = m_image->m_gdiObjects.Item(m_gdiIndex);
434 if (node)
435 {
436 wxPen *pen = (wxPen *)node->GetData();
437 if (pen)
438 dc.SetPen(* pen);
439 }
440 }
441 break;
442 }
443 case DRAWOP_SET_BRUSH:
444 {
445 // Check for overriding this operation for outline or fill
446 // colour
447 if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
448 {
449 // Need to construct a brush to match the outline pen's colour
450 if (m_image->m_outlinePen)
451 {
452 wxBrush *br = wxTheBrushList->FindOrCreateBrush(m_image->m_outlinePen->GetColour(), wxSOLID);
453 if (br)
454 dc.SetBrush(* br);
455 }
456 }
457 else if (m_image->m_fillColours.Member((wxObject *)m_gdiIndex))
458 {
459 if (m_image->m_fillBrush)
460 {
461 dc.SetBrush(* m_image->m_fillBrush);
462 }
463 }
464 else
465 {
466 wxNode *node = m_image->m_gdiObjects.Item(m_gdiIndex);
467 if (node)
468 {
469 wxBrush *brush = (wxBrush *)node->GetData();
470 if (brush)
471 dc.SetBrush(* brush);
472 }
473 }
474 break;
475 }
476 case DRAWOP_SET_FONT:
477 {
478 wxNode *node = m_image->m_gdiObjects.Item(m_gdiIndex);
479 if (node)
480 {
481 wxFont *font = (wxFont *)node->GetData();
482 if (font)
483 dc.SetFont(* font);
484 }
485 break;
486 }
487 case DRAWOP_SET_TEXT_COLOUR:
488 {
489 wxColour col(m_r,m_g,m_b);
490 dc.SetTextForeground(col);
491 break;
492 }
493 case DRAWOP_SET_BK_COLOUR:
494 {
495 wxColour col(m_r,m_g,m_b);
496 dc.SetTextBackground(col);
497 break;
498 }
499 case DRAWOP_SET_BK_MODE:
500 {
501 dc.SetBackgroundMode(m_mode);
502 break;
503 }
504 default:
505 break;
506 }
507 }
508
509 wxDrawOp *wxOpSetGDI::Copy(wxPseudoMetaFile *newImage)
510 {
511 wxOpSetGDI *newOp = new wxOpSetGDI(m_op, newImage, m_gdiIndex, m_mode);
512 newOp->m_r = m_r;
513 newOp->m_g = m_g;
514 newOp->m_b = m_b;
515 return newOp;
516 }
517
518 #if wxUSE_PROLOGIO
519 wxExpr *wxOpSetGDI::WriteExpr(wxPseudoMetaFile *WXUNUSED(image))
520 {
521 wxExpr *expr = new wxExpr(wxExprList);
522 expr->Append(new wxExpr((long)m_op));
523 switch (m_op)
524 {
525 case DRAWOP_SET_PEN:
526 case DRAWOP_SET_BRUSH:
527 case DRAWOP_SET_FONT:
528 {
529 expr->Append(new wxExpr((long)m_gdiIndex));
530 break;
531 }
532 case DRAWOP_SET_TEXT_COLOUR:
533 case DRAWOP_SET_BK_COLOUR:
534 {
535 expr->Append(new wxExpr((long)m_r));
536 expr->Append(new wxExpr((long)m_g));
537 expr->Append(new wxExpr((long)m_b));
538 break;
539 }
540 case DRAWOP_SET_BK_MODE:
541 {
542 expr->Append(new wxExpr((long)m_mode));
543 break;
544 }
545 default:
546 break;
547 }
548 return expr;
549 }
550
551 void wxOpSetGDI::ReadExpr(wxPseudoMetaFile *WXUNUSED(image), wxExpr *expr)
552 {
553 switch (m_op)
554 {
555 case DRAWOP_SET_PEN:
556 case DRAWOP_SET_BRUSH:
557 case DRAWOP_SET_FONT:
558 {
559 m_gdiIndex = (int)expr->Nth(1)->IntegerValue();
560 break;
561 }
562 case DRAWOP_SET_TEXT_COLOUR:
563 case DRAWOP_SET_BK_COLOUR:
564 {
565 m_r = (unsigned char)expr->Nth(1)->IntegerValue();
566 m_g = (unsigned char)expr->Nth(2)->IntegerValue();
567 m_b = (unsigned char)expr->Nth(3)->IntegerValue();
568 break;
569 }
570 case DRAWOP_SET_BK_MODE:
571 {
572 m_mode = (int)expr->Nth(1)->IntegerValue();
573 break;
574 }
575 default:
576 break;
577 }
578 }
579 #endif
580
581 /*
582 * Set/destroy clipping
583 *
584 */
585
586 wxOpSetClipping::wxOpSetClipping(int theOp, double theX1, double theY1,
587 double theX2, double theY2):wxDrawOp(theOp)
588 {
589 m_x1 = theX1;
590 m_y1 = theY1;
591 m_x2 = theX2;
592 m_y2 = theY2;
593 }
594
595 wxDrawOp *wxOpSetClipping::Copy(wxPseudoMetaFile *WXUNUSED(newImage))
596 {
597 wxOpSetClipping *newOp = new wxOpSetClipping(m_op, m_x1, m_y1, m_x2, m_y2);
598 return newOp;
599 }
600
601 void wxOpSetClipping::Do(wxDC& dc, double xoffset, double yoffset)
602 {
603 switch (m_op)
604 {
605 case DRAWOP_SET_CLIPPING_RECT:
606 {
607 dc.SetClippingRegion((long)(m_x1 + xoffset), (long)(m_y1 + yoffset), (long)(m_x2 + xoffset), (long)(m_y2 + yoffset));
608 break;
609 }
610 case DRAWOP_DESTROY_CLIPPING_RECT:
611 {
612 dc.DestroyClippingRegion();
613 break;
614 }
615 default:
616 break;
617 }
618 }
619
620 void wxOpSetClipping::Scale(double xScale, double yScale)
621 {
622 m_x1 *= xScale;
623 m_y1 *= yScale;
624 m_x2 *= xScale;
625 m_y2 *= yScale;
626 }
627
628 void wxOpSetClipping::Translate(double x, double y)
629 {
630 m_x1 += x;
631 m_y1 += y;
632 }
633
634 #if wxUSE_PROLOGIO
635 wxExpr *wxOpSetClipping::WriteExpr(wxPseudoMetaFile *WXUNUSED(image))
636 {
637 wxExpr *expr = new wxExpr(wxExprList);
638 expr->Append(new wxExpr((long)m_op));
639 switch (m_op)
640 {
641 case DRAWOP_SET_CLIPPING_RECT:
642 {
643 expr->Append(new wxExpr(m_x1));
644 expr->Append(new wxExpr(m_y1));
645 expr->Append(new wxExpr(m_x2));
646 expr->Append(new wxExpr(m_y2));
647 break;
648 }
649 default:
650 break;
651 }
652 return expr;
653 }
654
655 void wxOpSetClipping::ReadExpr(wxPseudoMetaFile *WXUNUSED(image), wxExpr *expr)
656 {
657 switch (m_op)
658 {
659 case DRAWOP_SET_CLIPPING_RECT:
660 {
661 m_x1 = expr->Nth(1)->RealValue();
662 m_y1 = expr->Nth(2)->RealValue();
663 m_x2 = expr->Nth(3)->RealValue();
664 m_y2 = expr->Nth(4)->RealValue();
665 break;
666 }
667 default:
668 break;
669 }
670 }
671 #endif
672
673 /*
674 * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
675 *
676 */
677
678 wxOpDraw::wxOpDraw(int theOp, double theX1, double theY1, double theX2, double theY2,
679 double theRadius, const wxString& s) : wxDrawOp(theOp)
680 {
681 m_x1 = theX1;
682 m_y1 = theY1;
683 m_x2 = theX2;
684 m_y2 = theY2;
685 m_x3 = 0.0;
686 m_y3 = 0.0;
687 m_radius = theRadius;
688 m_textString = s;
689 }
690
691 wxOpDraw::~wxOpDraw()
692 {
693 }
694
695 wxDrawOp *wxOpDraw::Copy(wxPseudoMetaFile *WXUNUSED(newImage))
696 {
697 wxOpDraw *newOp = new wxOpDraw(m_op, m_x1, m_y1, m_x2, m_y2, m_radius, m_textString);
698 newOp->m_x3 = m_x3;
699 newOp->m_y3 = m_y3;
700 return newOp;
701 }
702
703 void wxOpDraw::Do(wxDC& dc, double xoffset, double yoffset)
704 {
705 switch (m_op)
706 {
707 case DRAWOP_DRAW_LINE:
708 {
709 dc.DrawLine(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset));
710 break;
711 }
712 case DRAWOP_DRAW_RECT:
713 {
714 dc.DrawRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
715 break;
716 }
717 case DRAWOP_DRAW_ROUNDED_RECT:
718 {
719 dc.DrawRoundedRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2), m_radius);
720 break;
721 }
722 case DRAWOP_DRAW_ELLIPSE:
723 {
724 dc.DrawEllipse(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
725 break;
726 }
727 case DRAWOP_DRAW_ARC:
728 {
729 dc.DrawArc(WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset),
730 WXROUND(m_x3+xoffset), WXROUND(m_y3+yoffset),
731 WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
732 break;
733 }
734 case DRAWOP_DRAW_ELLIPTIC_ARC:
735 {
736 const double pi = 3.1415926535897932384626433832795 ;
737
738 // Convert back to degrees
739 dc.DrawEllipticArc(
740 WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset),
741 WXROUND(m_x2), WXROUND(m_y2),
742 WXROUND(m_x3*(360.0/(2.0*pi))), WXROUND(m_y3*(360.0/(2.0*pi))));
743 break;
744 }
745 case DRAWOP_DRAW_POINT:
746 {
747 dc.DrawPoint(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
748 break;
749 }
750 case DRAWOP_DRAW_TEXT:
751 {
752 dc.DrawText(m_textString, WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
753 break;
754 }
755 default:
756 break;
757 }
758 }
759
760 void wxOpDraw::Scale(double scaleX, double scaleY)
761 {
762 m_x1 *= scaleX;
763 m_y1 *= scaleY;
764 m_x2 *= scaleX;
765 m_y2 *= scaleY;
766
767 if (m_op != DRAWOP_DRAW_ELLIPTIC_ARC)
768 {
769 m_x3 *= scaleX;
770 m_y3 *= scaleY;
771 }
772
773 m_radius *= scaleX;
774 }
775
776 void wxOpDraw::Translate(double x, double y)
777 {
778 m_x1 += x;
779 m_y1 += y;
780
781 switch (m_op)
782 {
783 case DRAWOP_DRAW_LINE:
784 {
785 m_x2 += x;
786 m_y2 += y;
787 break;
788 }
789 case DRAWOP_DRAW_ARC:
790 {
791 m_x2 += x;
792 m_y2 += y;
793 m_x3 += x;
794 m_y3 += y;
795 break;
796 }
797 case DRAWOP_DRAW_ELLIPTIC_ARC:
798 {
799 break;
800 }
801 default:
802 break;
803 }
804 }
805
806 void wxOpDraw::Rotate(double x, double y, double theta, double sinTheta, double cosTheta)
807 {
808 double newX1 = m_x1*cosTheta - m_y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
809 double newY1 = m_x1*sinTheta + m_y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
810
811 switch (m_op)
812 {
813 case DRAWOP_DRAW_LINE:
814 {
815 double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
816 double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
817
818 m_x1 = newX1;
819 m_y1 = newY1;
820 m_x2 = newX2;
821 m_y2 = newY2;
822 break;
823 }
824 case DRAWOP_DRAW_RECT:
825 case DRAWOP_DRAW_ROUNDED_RECT:
826 case DRAWOP_DRAW_ELLIPTIC_ARC:
827 {
828 // Assume only 0, 90, 180, 270 degree rotations.
829 // oldX1, oldY1 represents the top left corner. Find the
830 // bottom right, and rotate that. Then the width/height is the difference
831 // between x/y values.
832 double oldBottomRightX = m_x1 + m_x2;
833 double oldBottomRightY = m_y1 + m_y2;
834 double newBottomRightX = oldBottomRightX*cosTheta - oldBottomRightY*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
835 double newBottomRightY = oldBottomRightX*sinTheta + oldBottomRightY*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
836
837 // Now find the new top-left, bottom-right coordinates.
838 double minX = wxMin(newX1, newBottomRightX);
839 double minY = wxMin(newY1, newBottomRightY);
840 double maxX = wxMax(newX1, newBottomRightX);
841 double maxY = wxMax(newY1, newBottomRightY);
842
843 m_x1 = minX;
844 m_y1 = minY;
845 m_x2 = maxX - minX; // width
846 m_y2 = maxY - minY; // height
847
848 if (m_op == DRAWOP_DRAW_ELLIPTIC_ARC)
849 {
850 // Add rotation to angles
851 m_x3 += theta;
852 m_y3 += theta;
853 }
854
855 break;
856 }
857 case DRAWOP_DRAW_ARC:
858 {
859 double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
860 double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
861 double newX3 = m_x3*cosTheta - m_y3*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
862 double newY3 = m_x3*sinTheta + m_y3*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
863
864 m_x1 = newX1;
865 m_y1 = newY1;
866 m_x2 = newX2;
867 m_y2 = newY2;
868 m_x3 = newX3;
869 m_y3 = newY3;
870
871 break;
872 }
873 default:
874 break;
875 }
876 }
877
878 #if wxUSE_PROLOGIO
879 wxExpr *wxOpDraw::WriteExpr(wxPseudoMetaFile *WXUNUSED(image))
880 {
881 wxExpr *expr = new wxExpr(wxExprList);
882 expr->Append(new wxExpr((long)m_op));
883 switch (m_op)
884 {
885 case DRAWOP_DRAW_LINE:
886 case DRAWOP_DRAW_RECT:
887 case DRAWOP_DRAW_ELLIPSE:
888 {
889 expr->Append(new wxExpr(m_x1));
890 expr->Append(new wxExpr(m_y1));
891 expr->Append(new wxExpr(m_x2));
892 expr->Append(new wxExpr(m_y2));
893 break;
894 }
895 case DRAWOP_DRAW_ROUNDED_RECT:
896 {
897 expr->Append(new wxExpr(m_x1));
898 expr->Append(new wxExpr(m_y1));
899 expr->Append(new wxExpr(m_x2));
900 expr->Append(new wxExpr(m_y2));
901 expr->Append(new wxExpr(m_radius));
902 break;
903 }
904 case DRAWOP_DRAW_POINT:
905 {
906 expr->Append(new wxExpr(m_x1));
907 expr->Append(new wxExpr(m_y1));
908 break;
909 }
910 case DRAWOP_DRAW_TEXT:
911 {
912 expr->Append(new wxExpr(m_x1));
913 expr->Append(new wxExpr(m_y1));
914 expr->Append(new wxExpr(wxExprString, m_textString));
915 break;
916 }
917 case DRAWOP_DRAW_ARC:
918 case DRAWOP_DRAW_ELLIPTIC_ARC:
919 {
920 expr->Append(new wxExpr(m_x1));
921 expr->Append(new wxExpr(m_y1));
922 expr->Append(new wxExpr(m_x2));
923 expr->Append(new wxExpr(m_y2));
924 expr->Append(new wxExpr(m_x3));
925 expr->Append(new wxExpr(m_y3));
926 break;
927 }
928 default:
929 {
930 break;
931 }
932 }
933 return expr;
934 }
935
936 void wxOpDraw::ReadExpr(wxPseudoMetaFile *WXUNUSED(image), wxExpr *expr)
937 {
938 switch (m_op)
939 {
940 case DRAWOP_DRAW_LINE:
941 case DRAWOP_DRAW_RECT:
942 case DRAWOP_DRAW_ELLIPSE:
943 {
944 m_x1 = expr->Nth(1)->RealValue();
945 m_y1 = expr->Nth(2)->RealValue();
946 m_x2 = expr->Nth(3)->RealValue();
947 m_y2 = expr->Nth(4)->RealValue();
948 break;
949 }
950 case DRAWOP_DRAW_ROUNDED_RECT:
951 {
952 m_x1 = expr->Nth(1)->RealValue();
953 m_y1 = expr->Nth(2)->RealValue();
954 m_x2 = expr->Nth(3)->RealValue();
955 m_y2 = expr->Nth(4)->RealValue();
956 m_radius = expr->Nth(5)->RealValue();
957 break;
958 }
959 case DRAWOP_DRAW_POINT:
960 {
961 m_x1 = expr->Nth(1)->RealValue();
962 m_y1 = expr->Nth(2)->RealValue();
963 break;
964 }
965 case DRAWOP_DRAW_TEXT:
966 {
967 m_x1 = expr->Nth(1)->RealValue();
968 m_y1 = expr->Nth(2)->RealValue();
969 m_textString = wxString(expr->Nth(3)->StringValue());
970 break;
971 }
972 case DRAWOP_DRAW_ARC:
973 case DRAWOP_DRAW_ELLIPTIC_ARC:
974 {
975 m_x1 = expr->Nth(1)->RealValue();
976 m_y1 = expr->Nth(2)->RealValue();
977 m_x2 = expr->Nth(3)->RealValue();
978 m_y2 = expr->Nth(4)->RealValue();
979 m_x3 = expr->Nth(5)->RealValue();
980 m_y3 = expr->Nth(6)->RealValue();
981 break;
982 }
983 default:
984 {
985 break;
986 }
987 }
988 }
989 #endif
990
991 /*
992 * Draw polygon, polyline, spline
993 *
994 */
995
996 wxOpPolyDraw::wxOpPolyDraw(int theOp, int n, wxRealPoint *thePoints):wxDrawOp(theOp)
997 {
998 m_noPoints = n;
999 m_points = thePoints;
1000 }
1001
1002 wxOpPolyDraw::~wxOpPolyDraw()
1003 {
1004 delete[] m_points;
1005 }
1006
1007 wxDrawOp *wxOpPolyDraw::Copy(wxPseudoMetaFile *WXUNUSED(newImage))
1008 {
1009 wxRealPoint *newPoints = new wxRealPoint[m_noPoints];
1010 for (int i = 0; i < m_noPoints; i++)
1011 {
1012 newPoints[i].x = m_points[i].x;
1013 newPoints[i].y = m_points[i].y;
1014 }
1015 wxOpPolyDraw *newOp = new wxOpPolyDraw(m_op, m_noPoints, newPoints);
1016 return newOp;
1017 }
1018
1019 void wxOpPolyDraw::Do(wxDC& dc, double xoffset, double yoffset)
1020 {
1021 switch (m_op)
1022 {
1023 case DRAWOP_DRAW_POLYLINE:
1024 {
1025 wxPoint *actualPoints = new wxPoint[m_noPoints];
1026 int i;
1027 for (i = 0; i < m_noPoints; i++)
1028 {
1029 actualPoints[i].x = WXROUND(m_points[i].x);
1030 actualPoints[i].y = WXROUND(m_points[i].y);
1031 }
1032
1033 dc.DrawLines(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
1034
1035 delete[] actualPoints;
1036 break;
1037 }
1038 case DRAWOP_DRAW_POLYGON:
1039 {
1040 wxPoint *actualPoints = new wxPoint[m_noPoints];
1041 int i;
1042 for (i = 0; i < m_noPoints; i++)
1043 {
1044 actualPoints[i].x = WXROUND(m_points[i].x);
1045 actualPoints[i].y = WXROUND(m_points[i].y);
1046 }
1047
1048 dc.DrawPolygon(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
1049
1050 delete[] actualPoints;
1051 break;
1052 }
1053 case DRAWOP_DRAW_SPLINE:
1054 {
1055 wxPoint *actualPoints = new wxPoint[m_noPoints];
1056 int i;
1057 for (i = 0; i < m_noPoints; i++)
1058 {
1059 actualPoints[i].x = WXROUND(m_points[i].x);
1060 actualPoints[i].y = WXROUND(m_points[i].y);
1061 }
1062
1063 dc.DrawSpline(m_noPoints, actualPoints); // no offsets in DrawSpline // , xoffset, yoffset);
1064
1065 delete[] actualPoints;
1066 break;
1067 }
1068 default:
1069 break;
1070 }
1071 }
1072
1073 void wxOpPolyDraw::Scale(double scaleX, double scaleY)
1074 {
1075 for (int i = 0; i < m_noPoints; i++)
1076 {
1077 m_points[i].x *= scaleX;
1078 m_points[i].y *= scaleY;
1079 }
1080 }
1081
1082 void wxOpPolyDraw::Translate(double x, double y)
1083 {
1084 for (int i = 0; i < m_noPoints; i++)
1085 {
1086 m_points[i].x += x;
1087 m_points[i].y += y;
1088 }
1089 }
1090
1091 void wxOpPolyDraw::Rotate(double x, double y, double WXUNUSED(theta), double sinTheta, double cosTheta)
1092 {
1093 for (int i = 0; i < m_noPoints; i++)
1094 {
1095 double x1 = m_points[i].x;
1096 double y1 = m_points[i].y;
1097 m_points[i].x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
1098 m_points[i].y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
1099 }
1100 }
1101
1102 #if wxUSE_PROLOGIO
1103 wxExpr *wxOpPolyDraw::WriteExpr(wxPseudoMetaFile *WXUNUSED(image))
1104 {
1105 wxExpr *expr = new wxExpr(wxExprList);
1106 expr->Append(new wxExpr((long)m_op));
1107 expr->Append(new wxExpr((long)m_noPoints));
1108
1109 // char buf1[9];
1110 wxChar buf2[5];
1111 wxChar buf3[5];
1112
1113 oglBuffer[0] = 0;
1114
1115 /*
1116 * Store each coordinate pair in a hex string to save space.
1117 * E.g. "1B9080CD". 4 hex digits per coordinate pair.
1118 *
1119 */
1120
1121 for (int i = 0; i < m_noPoints; i++)
1122 {
1123 long signedX = (long)(m_points[i].x*100.0);
1124 long signedY = (long)(m_points[i].y*100.0);
1125
1126 // Scale to 0 -> 64K
1127 long unSignedX = (long)(signedX + 32767.0);
1128 long unSignedY = (long)(signedY + 32767.0);
1129
1130 // IntToHex((unsigned int)signedX, buf2);
1131 // IntToHex((unsigned int)signedY, buf3);
1132 IntToHex((int)unSignedX, buf2);
1133 IntToHex((int)unSignedY, buf3);
1134
1135 // Don't overrun the buffer
1136 if ((i*8) < 3000)
1137 {
1138 wxStrcat(oglBuffer, buf2);
1139 wxStrcat(oglBuffer, buf3);
1140 }
1141 }
1142 expr->Append(new wxExpr(wxExprString, oglBuffer));
1143 return expr;
1144 }
1145
1146 void wxOpPolyDraw::ReadExpr(wxPseudoMetaFile *WXUNUSED(image), wxExpr *expr)
1147 {
1148 m_noPoints = (int)expr->Nth(1)->IntegerValue();
1149
1150 wxChar buf1[5];
1151 wxChar buf2[5];
1152
1153 m_points = new wxRealPoint[m_noPoints];
1154 int i = 0;
1155 int bufPtr = 0;
1156 wxString hexString = expr->Nth(2)->StringValue();
1157 while (i < m_noPoints)
1158 {
1159 buf1[0] = hexString[(size_t)bufPtr];
1160 buf1[1] = hexString[(size_t)(bufPtr + 1)];
1161 buf1[2] = hexString[(size_t)(bufPtr + 2)];
1162 buf1[3] = hexString[(size_t)(bufPtr + 3)];
1163 buf1[4] = 0;
1164
1165 buf2[0] = hexString[(size_t)(bufPtr + 4)];
1166 buf2[1] = hexString[(size_t)(bufPtr + 5)];
1167 buf2[2] = hexString[(size_t)(bufPtr + 6)];
1168 buf2[3] = hexString[(size_t)(bufPtr + 7)];
1169 buf2[4] = 0;
1170
1171 bufPtr += 8;
1172
1173 // int signedX = (signed int)HexToInt(buf1);
1174 // int signedY = (signed int)HexToInt(buf2);
1175 long unSignedX = HexToInt(buf1);
1176 long unSignedY = HexToInt(buf2);
1177 // Scale -32K -> +32K
1178 long signedX = unSignedX - 32767;
1179 long signedY = unSignedY - 32767;
1180 #if defined(__WXMSW__) && 0
1181 int testX = (signed int)unSignedX;
1182 int testY = (signed int)unSignedY;
1183 #endif
1184
1185 m_points[i].x = (double)(signedX / 100.0);
1186 m_points[i].y = (double)(signedY / 100.0);
1187
1188 i ++;
1189 }
1190 }
1191 #endif
1192
1193 // Draw an outline using the current operation.
1194 bool wxOpPolyDraw::OnDrawOutline(wxDC& dc, double x, double y, double w, double h, double oldW, double oldH)
1195 {
1196 dc.SetBrush(* wxTRANSPARENT_BRUSH);
1197
1198 // Multiply all points by proportion of new size to old size
1199 double x_proportion = (double)(fabs(w/oldW));
1200 double y_proportion = (double)(fabs(h/oldH));
1201
1202 int n = m_noPoints;
1203 wxPoint *intPoints = new wxPoint[n];
1204 int i;
1205 for (i = 0; i < n; i++)
1206 {
1207 intPoints[i].x = WXROUND (x_proportion * m_points[i].x);
1208 intPoints[i].y = WXROUND (y_proportion * m_points[i].y);
1209 }
1210 dc.DrawPolygon(n, intPoints, (long) x, (long) y);
1211 delete[] intPoints;
1212 return true;
1213 }
1214
1215 // Assume (x1, y1) is centre of box (most generally, line end at box)
1216 bool wxOpPolyDraw::GetPerimeterPoint(double x1, double y1,
1217 double x2, double y2,
1218 double *x3, double *y3,
1219 double xOffset, double yOffset,
1220 int attachmentMode)
1221 {
1222 int n = m_noPoints;
1223
1224 // First check for situation where the line is vertical,
1225 // and we would want to connect to a point on that vertical --
1226 // oglFindEndForPolyline can't cope with this (the arrow
1227 // gets drawn to the wrong place).
1228 if ((attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2))
1229 {
1230 // Look for the point we'd be connecting to. This is
1231 // a heuristic...
1232 int i;
1233 for (i = 0; i < n; i++)
1234 {
1235 wxRealPoint *point = & (m_points[i]);
1236 if (point->x == 0.0)
1237 {
1238 if ((y2 > y1) && (point->y > 0.0))
1239 {
1240 *x3 = point->x + xOffset;
1241 *y3 = point->y + yOffset;
1242 return true;
1243 }
1244 else if ((y2 < y1) && (point->y < 0.0))
1245 {
1246 *x3 = point->x + xOffset;
1247 *y3 = point->y + yOffset;
1248 return true;
1249 }
1250 }
1251 }
1252 }
1253
1254 double *xpoints = new double[n];
1255 double *ypoints = new double[n];
1256
1257 for (int i = 0; i < n; i++)
1258 {
1259 wxRealPoint *point = & (m_points[i]);
1260 xpoints[i] = point->x + xOffset;
1261 ypoints[i] = point->y + yOffset;
1262 }
1263
1264 oglFindEndForPolyline(n, xpoints, ypoints,
1265 x1, y1, x2, y2, x3, y3);
1266
1267 delete[] xpoints;
1268 delete[] ypoints;
1269
1270 return true;
1271 }
1272
1273
1274 /*
1275 * Utilities
1276 *
1277 */
1278
1279 static char hexArray[] = {
1280 _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'), _T('7'),
1281 _T('8'), _T('9'), _T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F') };
1282
1283 // Convert unsigned 16-bit integer to 4-character hex string
1284 static void IntToHex(unsigned int dec, wxChar *buf)
1285 {
1286 int digit1 = (int)(dec/4096);
1287 int digit2 = (int)((dec - (digit1*4096))/256);
1288 int digit3 = (int)((dec - (digit1*4096) - (digit2*256))/16);
1289 int digit4 = dec - (digit1*4096 + digit2*256 + digit3*16);
1290
1291 buf[0] = hexArray[digit1];
1292 buf[1] = hexArray[digit2];
1293 buf[2] = hexArray[digit3];
1294 buf[3] = hexArray[digit4];
1295 buf[4] = 0;
1296 }
1297
1298 // One hex digit to decimal number
1299 static int HexToInt1(wxChar hex)
1300 {
1301 switch (hex)
1302 {
1303 case _T('0'):
1304 return 0;
1305 case _T('1'):
1306 return 1;
1307 case _T('2'):
1308 return 2;
1309 case _T('3'):
1310 return 3;
1311 case _T('4'):
1312 return 4;
1313 case _T('5'):
1314 return 5;
1315 case _T('6'):
1316 return 6;
1317 case _T('7'):
1318 return 7;
1319 case _T('8'):
1320 return 8;
1321 case _T('9'):
1322 return 9;
1323 case _T('A'):
1324 return 10;
1325 case _T('B'):
1326 return 11;
1327 case _T('C'):
1328 return 12;
1329 case _T('D'):
1330 return 13;
1331 case _T('E'):
1332 return 14;
1333 case _T('F'):
1334 return 15;
1335 #if 0
1336 // handling this default outside switch removes warning under Borland
1337 default:
1338 return 0;
1339 #endif
1340 }
1341
1342 return 0;
1343 }
1344
1345 // 4-digit hex string to unsigned integer
1346 static unsigned long HexToInt(wxChar *buf)
1347 {
1348 long d1 = (long)(HexToInt1(buf[0])*4096.0) ;
1349 long d2 = (long)(HexToInt1(buf[1])*256.0) ;
1350 long d3 = (long)(HexToInt1(buf[2])*16.0) ;
1351 long d4 = (long)(HexToInt1(buf[3])) ;
1352 unsigned long n = (long)(d1 + d2 + d3 + d4) ;
1353 return n;
1354 }
1355
1356 /*
1357 * wxPseudo meta-file
1358 *
1359 */
1360
1361 IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile, wxObject)
1362
1363 wxPseudoMetaFile::wxPseudoMetaFile()
1364 {
1365 m_currentRotation = 0;
1366 m_rotateable = true;
1367 m_width = 0.0;
1368 m_height = 0.0;
1369 m_outlinePen = NULL;
1370 m_fillBrush = NULL;
1371 m_outlineOp = -1;
1372 }
1373
1374 wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile& mf)
1375 {
1376 mf.Copy(*this);
1377 }
1378
1379 wxPseudoMetaFile::~wxPseudoMetaFile()
1380 {
1381 Clear();
1382 }
1383
1384 void wxPseudoMetaFile::Clear()
1385 {
1386 wxNode *node = m_ops.GetFirst();
1387 while (node)
1388 {
1389 wxDrawOp *op = (wxDrawOp *)node->GetData();
1390 delete op;
1391 node = node->GetNext();
1392 }
1393 m_ops.Clear();
1394 m_gdiObjects.Clear();
1395 m_outlineColours.Clear();
1396 m_fillColours.Clear();
1397 m_outlineOp = -1;
1398 }
1399
1400 void wxPseudoMetaFile::Draw(wxDC& dc, double xoffset, double yoffset)
1401 {
1402 wxNode *node = m_ops.GetFirst();
1403 while (node)
1404 {
1405 wxDrawOp *op = (wxDrawOp *)node->GetData();
1406 op->Do(dc, xoffset, yoffset);
1407 node = node->GetNext();
1408 }
1409 }
1410
1411 void wxPseudoMetaFile::Scale(double sx, double sy)
1412 {
1413 wxNode *node = m_ops.GetFirst();
1414 while (node)
1415 {
1416 wxDrawOp *op = (wxDrawOp *)node->GetData();
1417 op->Scale(sx, sy);
1418 node = node->GetNext();
1419 }
1420 m_width *= sx;
1421 m_height *= sy;
1422 }
1423
1424 void wxPseudoMetaFile::Translate(double x, double y)
1425 {
1426 wxNode *node = m_ops.GetFirst();
1427 while (node)
1428 {
1429 wxDrawOp *op = (wxDrawOp *)node->GetData();
1430 op->Translate(x, y);
1431 node = node->GetNext();
1432 }
1433 }
1434
1435 void wxPseudoMetaFile::Rotate(double x, double y, double theta)
1436 {
1437 double theta1 = theta-m_currentRotation;
1438 if (theta1 == 0.0) return;
1439 double cosTheta = (double)cos(theta1);
1440 double sinTheta = (double)sin(theta1);
1441
1442 wxNode *node = m_ops.GetFirst();
1443 while (node)
1444 {
1445 wxDrawOp *op = (wxDrawOp *)node->GetData();
1446 op->Rotate(x, y, theta, sinTheta, cosTheta);
1447 node = node->GetNext();
1448 }
1449 m_currentRotation = theta;
1450 }
1451
1452 #if wxUSE_PROLOGIO
1453 void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
1454 {
1455 wxString widthStr;
1456 widthStr.Printf(wxT("meta_width%d"), whichAngle);
1457
1458 wxString heightStr;
1459 heightStr.Printf(wxT("meta_height%d"), whichAngle);
1460
1461 wxString outlineStr;
1462 outlineStr.Printf(wxT("outline_op%d"), whichAngle);
1463
1464 wxString rotateableStr;
1465 rotateableStr.Printf(wxT("meta_rotateable%d"), whichAngle);
1466
1467 // Write width and height
1468 clause->AddAttributeValue(widthStr, m_width);
1469 clause->AddAttributeValue(heightStr, m_height);
1470 clause->AddAttributeValue(rotateableStr, (long)m_rotateable);
1471 clause->AddAttributeValue(outlineStr, (long)m_outlineOp);
1472
1473 // Write GDI objects
1474 wxChar buf[50];
1475 int i = 1;
1476 wxNode *node = m_gdiObjects.GetFirst();
1477 while (node)
1478 {
1479 wxSprintf(buf, _T("gdi%d_%d"), whichAngle, i);
1480 wxObject *obj = (wxObject *)node->GetData();
1481 wxExpr *expr = NULL;
1482 if (obj)
1483 {
1484 if (obj->IsKindOf(CLASSINFO(wxPen)))
1485 {
1486 wxPen *thePen = (wxPen *)obj;
1487 expr = new wxExpr(wxExprList);
1488 expr->Append(new wxExpr((long)gyTYPE_PEN));
1489 expr->Append(new wxExpr((long)thePen->GetWidth()));
1490 expr->Append(new wxExpr((long)thePen->GetStyle()));
1491 expr->Append(new wxExpr((long)thePen->GetColour().Red()));
1492 expr->Append(new wxExpr((long)thePen->GetColour().Green()));
1493 expr->Append(new wxExpr((long)thePen->GetColour().Blue()));
1494 }
1495 else if (obj->IsKindOf(CLASSINFO(wxBrush)))
1496 {
1497 wxBrush *theBrush = (wxBrush *)obj;
1498 expr = new wxExpr(wxExprList);
1499 expr->Append(new wxExpr((long)gyTYPE_BRUSH));
1500 expr->Append(new wxExpr((long)theBrush->GetStyle()));
1501 expr->Append(new wxExpr((long)theBrush->GetColour().Red()));
1502 expr->Append(new wxExpr((long)theBrush->GetColour().Green()));
1503 expr->Append(new wxExpr((long)theBrush->GetColour().Blue()));
1504 }
1505 else if (obj->IsKindOf(CLASSINFO(wxFont)))
1506 {
1507 wxFont *theFont = (wxFont *)obj;
1508 expr = new wxExpr(wxExprList);
1509 expr->Append(new wxExpr((long)gyTYPE_FONT));
1510 expr->Append(new wxExpr((long)theFont->GetPointSize()));
1511 expr->Append(new wxExpr((long)theFont->GetFamily()));
1512 expr->Append(new wxExpr((long)theFont->GetStyle()));
1513 expr->Append(new wxExpr((long)theFont->GetWeight()));
1514 expr->Append(new wxExpr((long)theFont->GetUnderlined()));
1515 }
1516 }
1517 else
1518 {
1519 // If no recognised GDI object, append a place holder anyway.
1520 expr = new wxExpr(wxExprList);
1521 expr->Append(new wxExpr((long)0));
1522 }
1523
1524 if (expr)
1525 {
1526 clause->AddAttributeValue(buf, expr);
1527 i ++;
1528 }
1529 node = node->GetNext();
1530 }
1531
1532 // Write drawing operations
1533 i = 1;
1534 node = m_ops.GetFirst();
1535 while (node)
1536 {
1537 wxSprintf(buf, _T("op%d_%d"), whichAngle, i);
1538 wxDrawOp *op = (wxDrawOp *)node->GetData();
1539 wxExpr *expr = op->WriteExpr(this);
1540 if (expr)
1541 {
1542 clause->AddAttributeValue(buf, expr);
1543 i ++;
1544 }
1545 node = node->GetNext();
1546 }
1547
1548 // Write outline and fill GDI op lists (if any)
1549 if (m_outlineColours.GetCount() > 0)
1550 {
1551 wxExpr *outlineExpr = new wxExpr(wxExprList);
1552 node = m_outlineColours.GetFirst();
1553 while (node)
1554 {
1555 outlineExpr->Append(new wxExpr((long)node->GetData()));
1556 node = node->GetNext();
1557 }
1558 wxString outlineObjectsStr;
1559 outlineObjectsStr.Printf(wxT("outline_objects%d"), whichAngle);
1560
1561 clause->AddAttributeValue(outlineObjectsStr, outlineExpr);
1562 }
1563 if (m_fillColours.GetCount() > 0)
1564 {
1565 wxExpr *fillExpr = new wxExpr(wxExprList);
1566 node = m_fillColours.GetFirst();
1567 while (node)
1568 {
1569 fillExpr->Append(new wxExpr((long)node->GetData()));
1570 node = node->GetNext();
1571 }
1572 wxString fillObjectsStr;
1573 fillObjectsStr.Printf(wxT("fill_objects%d"), whichAngle);
1574
1575 clause->AddAttributeValue(fillObjectsStr, fillExpr);
1576 }
1577
1578 }
1579
1580 void wxPseudoMetaFile::ReadAttributes(wxExpr *clause, int whichAngle)
1581 {
1582 wxString widthStr;
1583 widthStr.Printf(wxT("meta_width%d"), whichAngle);
1584
1585 wxString heightStr;
1586 heightStr.Printf(wxT("meta_height%d"), whichAngle);
1587
1588 wxString outlineStr;
1589 outlineStr.Printf(wxT("outline_op%d"), whichAngle);
1590
1591 wxString rotateableStr;
1592 rotateableStr.Printf(wxT("meta_rotateable%d"), whichAngle);
1593
1594 clause->GetAttributeValue(widthStr, m_width);
1595 clause->GetAttributeValue(heightStr, m_height);
1596 clause->GetAttributeValue(outlineStr, m_outlineOp);
1597
1598 int iVal = (int) m_rotateable;
1599 clause->GetAttributeValue(rotateableStr, iVal);
1600 m_rotateable = (iVal != 0);
1601
1602 // Read GDI objects
1603 wxChar buf[50];
1604 int i = 1;
1605 bool keepGoing = true;
1606 while (keepGoing)
1607 {
1608 wxSprintf(buf, _T("gdi%d_%d"), whichAngle, i);
1609 wxExpr *expr = NULL;
1610 clause->GetAttributeValue(buf, &expr);
1611 if (!expr)
1612 {
1613 keepGoing = false;
1614 }
1615 else
1616 {
1617 wxExpr *idExpr = expr->Nth(0);
1618 switch (idExpr->IntegerValue())
1619 {
1620 case gyTYPE_PEN:
1621 {
1622 int penWidth = (int)expr->Nth(1)->IntegerValue();
1623 int penStyle = (int)expr->Nth(2)->IntegerValue();
1624 int penRed = (int)expr->Nth(3)->IntegerValue();
1625 int penGreen = (int)expr->Nth(4)->IntegerValue();
1626 int penBlue = (int)expr->Nth(5)->IntegerValue();
1627 wxColour col(penRed, penGreen, penBlue);
1628 wxPen *p = wxThePenList->FindOrCreatePen(col, penWidth, penStyle);
1629 if (!p)
1630 p = wxBLACK_PEN;
1631 m_gdiObjects.Append(p);
1632 break;
1633 }
1634 case gyTYPE_BRUSH:
1635 {
1636 int brushStyle = (int)expr->Nth(1)->IntegerValue();
1637 int brushRed = (int)expr->Nth(2)->IntegerValue();
1638 int brushGreen = (int)expr->Nth(3)->IntegerValue();
1639 int brushBlue = (int)expr->Nth(4)->IntegerValue();
1640 wxColour col(brushRed, brushGreen, brushBlue);
1641 wxBrush *b = wxTheBrushList->FindOrCreateBrush(col, brushStyle);
1642 if (!b)
1643 b = wxWHITE_BRUSH;
1644 m_gdiObjects.Append(b);
1645 break;
1646 }
1647 case gyTYPE_FONT:
1648 {
1649 int fontPointSize = (int)expr->Nth(1)->IntegerValue();
1650 int fontFamily = (int)expr->Nth(2)->IntegerValue();
1651 int fontStyle = (int)expr->Nth(3)->IntegerValue();
1652 int fontWeight = (int)expr->Nth(4)->IntegerValue();
1653 int fontUnderlined = (int)expr->Nth(5)->IntegerValue();
1654 m_gdiObjects.Append(wxTheFontList->FindOrCreateFont(fontPointSize,
1655 fontFamily, fontStyle, fontWeight, (fontUnderlined != 0)));
1656 break;
1657 }
1658 default:
1659 {
1660 // Place holder
1661 m_gdiObjects.Append(NULL);
1662 break;
1663 }
1664 }
1665 i ++;
1666 }
1667 }
1668
1669 // Now read in the operations
1670 keepGoing = true;
1671 i = 1;
1672 while (keepGoing)
1673 {
1674 wxSprintf(buf, _T("op%d_%d"), whichAngle, i);
1675 wxExpr *expr = NULL;
1676 clause->GetAttributeValue(buf, &expr);
1677 if (!expr)
1678 {
1679 keepGoing = false;
1680 }
1681 else
1682 {
1683 wxExpr *idExpr = expr->Nth(0);
1684 int opId = (int)idExpr->IntegerValue();
1685 switch (opId)
1686 {
1687 case DRAWOP_SET_PEN:
1688 case DRAWOP_SET_BRUSH:
1689 case DRAWOP_SET_FONT:
1690 case DRAWOP_SET_TEXT_COLOUR:
1691 case DRAWOP_SET_BK_COLOUR:
1692 case DRAWOP_SET_BK_MODE:
1693 {
1694 wxOpSetGDI *theOp = new wxOpSetGDI(opId, this, 0);
1695 theOp->ReadExpr(this, expr);
1696 m_ops.Append(theOp);
1697 break;
1698 }
1699
1700 case DRAWOP_SET_CLIPPING_RECT:
1701 case DRAWOP_DESTROY_CLIPPING_RECT:
1702 {
1703 wxOpSetClipping *theOp = new wxOpSetClipping(opId, 0.0, 0.0, 0.0, 0.0);
1704 theOp->ReadExpr(this, expr);
1705 m_ops.Append(theOp);
1706 break;
1707 }
1708
1709 case DRAWOP_DRAW_LINE:
1710 case DRAWOP_DRAW_RECT:
1711 case DRAWOP_DRAW_ROUNDED_RECT:
1712 case DRAWOP_DRAW_ELLIPSE:
1713 case DRAWOP_DRAW_POINT:
1714 case DRAWOP_DRAW_ARC:
1715 case DRAWOP_DRAW_TEXT:
1716 {
1717 wxOpDraw *theOp = new wxOpDraw(opId, 0.0, 0.0, 0.0, 0.0);
1718 theOp->ReadExpr(this, expr);
1719 m_ops.Append(theOp);
1720 break;
1721 }
1722 case DRAWOP_DRAW_SPLINE:
1723 case DRAWOP_DRAW_POLYLINE:
1724 case DRAWOP_DRAW_POLYGON:
1725 {
1726 wxOpPolyDraw *theOp = new wxOpPolyDraw(opId, 0, NULL);
1727 theOp->ReadExpr(this, expr);
1728 m_ops.Append(theOp);
1729 break;
1730 }
1731 default:
1732 break;
1733 }
1734 }
1735 i ++;
1736 }
1737
1738 wxString outlineObjectsStr;
1739 outlineObjectsStr.Printf(wxT("outline_objects%d"), whichAngle);
1740
1741 // Now read in the list of outline and fill operations, if any
1742 wxExpr *expr1 = clause->AttributeValue(outlineObjectsStr);
1743 if (expr1)
1744 {
1745 wxExpr *eachExpr = expr1->GetFirst();
1746 while (eachExpr)
1747 {
1748 m_outlineColours.Append((wxObject *)eachExpr->IntegerValue());
1749 eachExpr = eachExpr->GetNext();
1750 }
1751 }
1752
1753 wxString fillObjectsStr;
1754 fillObjectsStr.Printf(wxT("fill_objects%d"), whichAngle);
1755
1756 expr1 = clause->AttributeValue(fillObjectsStr);
1757 if (expr1)
1758 {
1759 wxExpr *eachExpr = expr1->GetFirst();
1760 while (eachExpr)
1761 {
1762 m_fillColours.Append((wxObject *)eachExpr->IntegerValue());
1763 eachExpr = eachExpr->GetNext();
1764 }
1765 }
1766 }
1767 #endif
1768
1769 // Does the copying for this object
1770 void wxPseudoMetaFile::Copy(wxPseudoMetaFile& copy)
1771 {
1772 copy.Clear();
1773
1774 copy.m_currentRotation = m_currentRotation;
1775 copy.m_width = m_width;
1776 copy.m_height = m_height;
1777 copy.m_rotateable = m_rotateable;
1778 copy.m_fillBrush = m_fillBrush;
1779 copy.m_outlinePen = m_outlinePen;
1780 copy.m_outlineOp = m_outlineOp;
1781
1782 // Copy the GDI objects
1783 wxNode *node = m_gdiObjects.GetFirst();
1784 while (node)
1785 {
1786 wxObject *obj = (wxObject *)node->GetData();
1787 copy.m_gdiObjects.Append(obj);
1788 node = node->GetNext();
1789 }
1790
1791 // Copy the operations
1792 node = m_ops.GetFirst();
1793 while (node)
1794 {
1795 wxDrawOp *op = (wxDrawOp *)node->GetData();
1796 copy.m_ops.Append(op->Copy(&copy));
1797 node = node->GetNext();
1798 }
1799
1800 // Copy the outline/fill operations
1801 node = m_outlineColours.GetFirst();
1802 while (node)
1803 {
1804 copy.m_outlineColours.Append((wxObject *)node->GetData());
1805 node = node->GetNext();
1806 }
1807 node = m_fillColours.GetFirst();
1808 while (node)
1809 {
1810 copy.m_fillColours.Append((wxObject *)node->GetData());
1811 node = node->GetNext();
1812 }
1813 }
1814
1815 /*
1816 * Pass size of existing image; scale height to
1817 * fit width and return new width and height.
1818 *
1819 */
1820
1821 bool wxPseudoMetaFile::LoadFromMetaFile(const wxString& filename, double *rwidth, double *rheight)
1822 {
1823 if (!wxFileExists(filename))
1824 return false;
1825
1826 wxXMetaFile *metaFile = new wxXMetaFile;
1827
1828 if (!metaFile->ReadFile(filename))
1829 {
1830 delete metaFile;
1831 return false;
1832 }
1833
1834 double lastX = 0.0;
1835 double lastY = 0.0;
1836
1837 // Convert from metafile records to wxDrawnShape records
1838 wxNode *node = metaFile->metaRecords.GetFirst();
1839 while (node)
1840 {
1841 wxMetaRecord *record = (wxMetaRecord *)node->GetData();
1842 switch (record->metaFunction)
1843 {
1844 case META_SETBKCOLOR:
1845 {
1846 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BK_COLOUR, this, 0);
1847 op->m_r = (unsigned char)record->param1;
1848 op->m_g = (unsigned char)record->param2;
1849 op->m_b = (unsigned char)record->param3;
1850 m_ops.Append(op);
1851 break;
1852 }
1853 case META_SETBKMODE:
1854 {
1855 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BK_MODE, this, 0, (int)record->param1);
1856 m_ops.Append(op);
1857 break;
1858 }
1859 case META_SETMAPMODE:
1860 {
1861 break;
1862 }
1863 // case META_SETROP2:
1864 // case META_SETRELABS:
1865 // case META_SETPOLYFILLMODE:
1866 // case META_SETSTRETCHBLTMODE:
1867 // case META_SETTEXTCHAREXTRA:
1868 case META_SETTEXTCOLOR:
1869 {
1870 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
1871 op->m_r = (unsigned char)record->param1;
1872 op->m_g = (unsigned char)record->param2;
1873 op->m_b = (unsigned char)record->param3;
1874 m_ops.Append(op);
1875 break;
1876 }
1877 // case META_SETTEXTJUSTIFICATION:
1878 // case META_SETWINDOWORG:
1879 // case META_SETWINDOWEXT:
1880 // case META_SETVIEWPORTORG:
1881 // case META_SETVIEWPORTEXT:
1882 // case META_OFFSETWINDOWORG:
1883 // case META_SCALEWINDOWEXT:
1884 // case META_OFFSETVIEWPORTORG:
1885 // case META_SCALEVIEWPORTEXT:
1886 case META_LINETO:
1887 {
1888 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_LINE, (double)lastX, (double)lastY,
1889 (double)record->param1, (double)record->param2);
1890 m_ops.Append(op);
1891 break;
1892 }
1893 case META_MOVETO:
1894 {
1895 lastX = (double)record->param1;
1896 lastY = (double)record->param2;
1897 break;
1898 }
1899 case META_EXCLUDECLIPRECT:
1900 {
1901 /*
1902 wxMetaRecord *rec = new wxMetaRecord(META_EXCLUDECLIPRECT);
1903 rec->param4 = getshort(handle); // m_y2
1904 rec->param3 = getshort(handle); // x2
1905 rec->param2 = getshort(handle); // y1
1906 rec->param1 = getshort(handle); // x1
1907 */
1908 break;
1909 }
1910 case META_INTERSECTCLIPRECT:
1911 {
1912 /*
1913 rec->param4 = getshort(handle); // m_y2
1914 rec->param3 = getshort(handle); // x2
1915 rec->param2 = getshort(handle); // y1
1916 rec->param1 = getshort(handle); // x1
1917 */
1918 break;
1919 }
1920 // case META_ARC: // DO!!!
1921 case META_ELLIPSE:
1922 {
1923 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
1924 (double)record->param1, (double)record->param2,
1925 (double)(record->param3 - record->param1),
1926 (double)(record->param4 - record->param2));
1927 m_ops.Append(op);
1928 break;
1929 }
1930 // case META_FLOODFILL:
1931 // case META_PIE: // DO!!!
1932 case META_RECTANGLE:
1933 {
1934 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_RECT,
1935 (double)record->param1, (double)record->param2,
1936 (double)(record->param3 - record->param1),
1937 (double)(record->param4 - record->param2));
1938 m_ops.Append(op);
1939 break;
1940 }
1941 case META_ROUNDRECT:
1942 {
1943 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
1944 (double)record->param1, (double)record->param2,
1945 (double)(record->param3 - record->param1),
1946 (double)(record->param4 - record->param2), (double)record->param5);
1947 m_ops.Append(op);
1948 break;
1949 }
1950 // case META_PATBLT:
1951 // case META_SAVEDC:
1952 case META_SETPIXEL:
1953 {
1954 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_POINT,
1955 (double)record->param1, (double)record->param2,
1956 0.0, 0.0);
1957
1958 // SHOULD SET THE COLOUR - SET PEN?
1959 // rec->param3 = getint(handle); // COLORREF
1960 m_ops.Append(op);
1961 break;
1962 }
1963 // case META_OFFSETCLIPRGN:
1964 case META_TEXTOUT:
1965 {
1966 wxOpDraw *op = new wxOpDraw(DRAWOP_DRAW_TEXT,
1967 (double)record->param1, (double)record->param2,
1968 0.0, 0.0, 0.0, record->stringParam);
1969 m_ops.Append(op);
1970 break;
1971 }
1972 // case META_BITBLT:
1973 // case META_STRETCHBLT:
1974 case META_POLYGON:
1975 {
1976 int n = (int)record->param1;
1977 wxRealPoint *newPoints = new wxRealPoint[n];
1978 for (int i = 0; i < n; i++)
1979 {
1980 newPoints[i].x = record->points[i].x;
1981 newPoints[i].y = record->points[i].y;
1982 }
1983
1984 wxOpPolyDraw *op = new wxOpPolyDraw(DRAWOP_DRAW_POLYGON, n, newPoints);
1985 m_ops.Append(op);
1986 break;
1987 }
1988 case META_POLYLINE:
1989 {
1990 int n = (int)record->param1;
1991 wxRealPoint *newPoints = new wxRealPoint[n];
1992 for (int i = 0; i < n; i++)
1993 {
1994 newPoints[i].x = record->points[i].x;
1995 newPoints[i].y = record->points[i].y;
1996 }
1997
1998 wxOpPolyDraw *op = new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE, n, newPoints);
1999 m_ops.Append(op);
2000 break;
2001 }
2002 // case META_ESCAPE:
2003 // case META_RESTOREDC:
2004 // case META_FILLREGION:
2005 // case META_FRAMEREGION:
2006 // case META_INVERTREGION:
2007 // case META_PAINTREGION:
2008 // case META_SELECTCLIPREGION: // DO THIS!
2009 case META_SELECTOBJECT:
2010 {
2011 // The pen, brush etc. has already been created when the metafile
2012 // was read in, so we don't create it - we set it.
2013 wxNode *recNode = metaFile->gdiObjects.Item((int)record->param2);
2014 if (recNode)
2015 {
2016 wxMetaRecord *gdiRec = (wxMetaRecord *)recNode->GetData();
2017 if (gdiRec && (gdiRec->param1 != 0))
2018 {
2019 wxObject *obj = (wxObject *)gdiRec->param1;
2020 if (obj->IsKindOf(CLASSINFO(wxPen)))
2021 {
2022 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_PEN, this, (int)record->param2);
2023 m_ops.Append(op);
2024 }
2025 else if (obj->IsKindOf(CLASSINFO(wxBrush)))
2026 {
2027 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_BRUSH, this, (int)record->param2);
2028 m_ops.Append(op);
2029 }
2030 else if (obj->IsKindOf(CLASSINFO(wxFont)))
2031 {
2032 wxOpSetGDI *op = new wxOpSetGDI(DRAWOP_SET_FONT, this, (int)record->param2);
2033 m_ops.Append(op);
2034 }
2035 }
2036 }
2037 break;
2038 }
2039 // case META_SETTEXTALIGN:
2040 // case META_DRAWTEXT:
2041 // case META_CHORD:
2042 // case META_SETMAPPERFLAGS:
2043 // case META_EXTTEXTOUT:
2044 // case META_SETDIBTODEV:
2045 // case META_SELECTPALETTE:
2046 // case META_REALIZEPALETTE:
2047 // case META_ANIMATEPALETTE:
2048 // case META_SETPALENTRIES:
2049 // case META_POLYPOLYGON:
2050 // case META_RESIZEPALETTE:
2051 // case META_DIBBITBLT:
2052 // case META_DIBSTRETCHBLT:
2053 case META_DIBCREATEPATTERNBRUSH:
2054 {
2055 // Place holder
2056 m_gdiObjects.Append(NULL);
2057 break;
2058 }
2059 // case META_STRETCHDIB:
2060 // case META_EXTFLOODFILL:
2061 // case META_RESETDC:
2062 // case META_STARTDOC:
2063 // case META_STARTPAGE:
2064 // case META_ENDPAGE:
2065 // case META_ABORTDOC:
2066 // case META_ENDDOC:
2067 // case META_DELETEOBJECT: // DO!!
2068 case META_CREATEPALETTE:
2069 {
2070 // Place holder
2071 m_gdiObjects.Append(NULL);
2072 break;
2073 }
2074 case META_CREATEBRUSH:
2075 {
2076 // Place holder
2077 m_gdiObjects.Append(NULL);
2078 break;
2079 }
2080 case META_CREATEPATTERNBRUSH:
2081 {
2082 // Place holder
2083 m_gdiObjects.Append(NULL);
2084 break;
2085 }
2086 case META_CREATEPENINDIRECT:
2087 {
2088 // The pen is created when the metafile is read in.
2089 // We keep track of all the GDI objects needed for this
2090 // image so when reading the wxDrawnShape from file,
2091 // we can read in all the GDI objects, then refer
2092 // to them by an index starting from zero thereafter.
2093 m_gdiObjects.Append((wxObject *)record->param1);
2094 break;
2095 }
2096 case META_CREATEFONTINDIRECT:
2097 {
2098 m_gdiObjects.Append((wxObject *)record->param1);
2099 break;
2100 }
2101 case META_CREATEBRUSHINDIRECT:
2102 {
2103 // Don't have to do anything here: the pen is created
2104 // when the metafile is read in.
2105 m_gdiObjects.Append((wxObject *)record->param1);
2106 break;
2107 }
2108 case META_CREATEBITMAPINDIRECT:
2109 {
2110 // Place holder
2111 m_gdiObjects.Append(NULL);
2112 break;
2113 }
2114 case META_CREATEBITMAP:
2115 {
2116 // Place holder
2117 m_gdiObjects.Append(NULL);
2118 break;
2119 }
2120 case META_CREATEREGION:
2121 {
2122 // Place holder
2123 m_gdiObjects.Append(NULL);
2124 break;
2125 }
2126 default:
2127 {
2128 break;
2129 }
2130 }
2131 node = node->GetNext();
2132 }
2133 double actualWidth = (double)fabs(metaFile->right - metaFile->left);
2134 double actualHeight = (double)fabs(metaFile->bottom - metaFile->top);
2135
2136 double initialScaleX = 1.0;
2137 double initialScaleY = 1.0;
2138
2139 double xoffset, yoffset;
2140
2141 // Translate so origin is at centre of rectangle
2142 if (metaFile->bottom > metaFile->top)
2143 yoffset = - (double)((metaFile->bottom - metaFile->top)/2.0);
2144 else
2145 yoffset = - (double)((metaFile->top - metaFile->bottom)/2.0);
2146
2147 if (metaFile->right > metaFile->left)
2148 xoffset = - (double)((metaFile->right - metaFile->left)/2.0);
2149 else
2150 xoffset = - (double)((metaFile->left - metaFile->right)/2.0);
2151
2152 Translate(xoffset, yoffset);
2153
2154 // Scale to a reasonable size (take the width of this wxDrawnShape
2155 // as a guide)
2156 if (actualWidth != 0.0)
2157 {
2158 initialScaleX = (double)((*rwidth) / actualWidth);
2159 initialScaleY = initialScaleX;
2160 (*rheight) = initialScaleY*actualHeight;
2161 }
2162 Scale(initialScaleX, initialScaleY);
2163
2164 m_width = (actualWidth*initialScaleX);
2165 m_height = *rheight;
2166
2167 delete metaFile;
2168 return true;
2169 }
2170
2171 // Scale to fit size
2172 void wxPseudoMetaFile::ScaleTo(double w, double h)
2173 {
2174 double scaleX = (double)(w/m_width);
2175 double scaleY = (double)(h/m_height);
2176
2177 // Do the scaling
2178 Scale(scaleX, scaleY);
2179 }
2180
2181 void wxPseudoMetaFile::GetBounds(double *boundMinX, double *boundMinY, double *boundMaxX, double *boundMaxY)
2182 {
2183 double maxX = (double) -99999.9;
2184 double maxY = (double) -99999.9;
2185 double minX = (double) 99999.9;
2186 double minY = (double) 99999.9;
2187
2188 wxNode *node = m_ops.GetFirst();
2189 while (node)
2190 {
2191 wxDrawOp *op = (wxDrawOp *)node->GetData();
2192 switch (op->GetOp())
2193 {
2194 case DRAWOP_DRAW_LINE:
2195 case DRAWOP_DRAW_RECT:
2196 case DRAWOP_DRAW_ROUNDED_RECT:
2197 case DRAWOP_DRAW_ELLIPSE:
2198 case DRAWOP_DRAW_POINT:
2199 case DRAWOP_DRAW_TEXT:
2200 {
2201 wxOpDraw *opDraw = (wxOpDraw *)op;
2202 if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
2203 if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
2204 if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
2205 if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
2206 if (op->GetOp() == DRAWOP_DRAW_LINE)
2207 {
2208 if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
2209 if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
2210 if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
2211 if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
2212 }
2213 else if (op->GetOp() == DRAWOP_DRAW_RECT ||
2214 op->GetOp() == DRAWOP_DRAW_ROUNDED_RECT ||
2215 op->GetOp() == DRAWOP_DRAW_ELLIPSE)
2216 {
2217 if ((opDraw->m_x1 + opDraw->m_x2) < minX) minX = (opDraw->m_x1 + opDraw->m_x2);
2218 if ((opDraw->m_x1 + opDraw->m_x2) > maxX) maxX = (opDraw->m_x1 + opDraw->m_x2);
2219 if ((opDraw->m_y1 + opDraw->m_y2) < minY) minY = (opDraw->m_y1 + opDraw->m_y2);
2220 if ((opDraw->m_y1 + opDraw->m_y2) > maxY) maxY = (opDraw->m_y1 + opDraw->m_y2);
2221 }
2222 break;
2223 }
2224 case DRAWOP_DRAW_ARC:
2225 {
2226 // TODO: don't yet know how to calculate the bounding box
2227 // for an arc. So pretend it's a line; to get a correct
2228 // bounding box, draw a blank rectangle first, of the correct
2229 // size.
2230 wxOpDraw *opDraw = (wxOpDraw *)op;
2231 if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
2232 if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
2233 if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
2234 if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
2235 if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
2236 if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
2237 if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
2238 if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
2239 break;
2240 }
2241 case DRAWOP_DRAW_POLYLINE:
2242 case DRAWOP_DRAW_POLYGON:
2243 case DRAWOP_DRAW_SPLINE:
2244 {
2245 wxOpPolyDraw *poly = (wxOpPolyDraw *)op;
2246 for (int i = 0; i < poly->m_noPoints; i++)
2247 {
2248 if (poly->m_points[i].x < minX) minX = poly->m_points[i].x;
2249 if (poly->m_points[i].x > maxX) maxX = poly->m_points[i].x;
2250 if (poly->m_points[i].y < minY) minY = poly->m_points[i].y;
2251 if (poly->m_points[i].y > maxY) maxY = poly->m_points[i].y;
2252 }
2253 break;
2254 }
2255 default:
2256 break;
2257 }
2258 node = node->GetNext();
2259 }
2260
2261 *boundMinX = minX;
2262 *boundMinY = minY;
2263 *boundMaxX = maxX;
2264 *boundMaxY = maxY;
2265 /*
2266 *w = (double)fabs(maxX - minX);
2267 *h = (double)fabs(maxY - minY);
2268 */
2269 }
2270
2271 // Calculate size from current operations
2272 void wxPseudoMetaFile::CalculateSize(wxDrawnShape* shape)
2273 {
2274 double boundMinX, boundMinY, boundMaxX, boundMaxY;
2275
2276 GetBounds(& boundMinX, & boundMinY, & boundMaxX, & boundMaxY);
2277
2278 SetSize(boundMaxX - boundMinX, boundMaxY - boundMinY);
2279
2280 if (shape)
2281 {
2282 shape->SetWidth(m_width);
2283 shape->SetHeight(m_height);
2284 }
2285 }
2286
2287 // Set of functions for drawing into a pseudo metafile.
2288 // They use integers, but doubles are used internally for accuracy
2289 // when scaling.
2290
2291 void wxPseudoMetaFile::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
2292 {
2293 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_LINE,
2294 (double) pt1.x, (double) pt1.y, (double) pt2.x, (double) pt2.y);
2295
2296 m_ops.Append(theOp);
2297 }
2298
2299 void wxPseudoMetaFile::DrawRectangle(const wxRect& rect)
2300 {
2301 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_RECT,
2302 (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
2303
2304 m_ops.Append(theOp);
2305 }
2306
2307 void wxPseudoMetaFile::DrawRoundedRectangle(const wxRect& rect, double radius)
2308 {
2309 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
2310 (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
2311
2312 theOp->m_radius = radius;
2313
2314 m_ops.Append(theOp);
2315 }
2316
2317 void wxPseudoMetaFile::DrawEllipse(const wxRect& rect)
2318 {
2319 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
2320 (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
2321
2322 m_ops.Append(theOp);
2323 }
2324
2325 void wxPseudoMetaFile::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
2326 {
2327 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ARC,
2328 (double) centrePt.x, (double) centrePt.y, (double) startPt.x, (double) startPt.y);
2329
2330 theOp->m_x3 = (double) endPt.x;
2331 theOp->m_y3 = (double) endPt.y;
2332
2333 m_ops.Append(theOp);
2334 }
2335
2336 void wxPseudoMetaFile::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
2337 {
2338 const double pi = 3.1415926535897932384626433832795 ;
2339
2340 double startAngleRadians = startAngle* (pi*2.0/360.0);
2341 double endAngleRadians = endAngle* (pi*2.0/360.0);
2342
2343 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPTIC_ARC,
2344 (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
2345
2346 theOp->m_x3 = startAngleRadians;
2347 theOp->m_y3 = endAngleRadians;
2348
2349 m_ops.Append(theOp);
2350 }
2351
2352 void wxPseudoMetaFile::DrawPoint(const wxPoint& pt)
2353 {
2354 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_POINT,
2355 (double) pt.x, (double) pt.y, 0.0, 0.0);
2356
2357 m_ops.Append(theOp);
2358 }
2359
2360 void wxPseudoMetaFile::DrawText(const wxString& text, const wxPoint& pt)
2361 {
2362 wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_TEXT,
2363 (double) pt.x, (double) pt.y, 0.0, 0.0);
2364
2365 theOp->m_textString = text;
2366
2367 m_ops.Append(theOp);
2368 }
2369
2370 void wxPseudoMetaFile::DrawLines(int n, wxPoint pts[])
2371 {
2372 wxRealPoint* realPoints = new wxRealPoint[n];
2373 int i;
2374 for (i = 0; i < n; i++)
2375 {
2376 realPoints[i].x = pts[i].x;
2377 realPoints[i].y = pts[i].y;
2378 }
2379 wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE, n, realPoints);
2380 m_ops.Append(theOp);
2381 }
2382
2383 void wxPseudoMetaFile::DrawPolygon(int n, wxPoint pts[], int flags)
2384 {
2385 wxRealPoint* realPoints = new wxRealPoint[n];
2386 int i;
2387 for (i = 0; i < n; i++)
2388 {
2389 realPoints[i].x = pts[i].x;
2390 realPoints[i].y = pts[i].y;
2391 }
2392 wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYGON, n, realPoints);
2393 m_ops.Append(theOp);
2394
2395 if (flags & oglMETAFLAGS_OUTLINE)
2396 m_outlineOp = (m_ops.GetCount() - 1);
2397 }
2398
2399 void wxPseudoMetaFile::DrawSpline(int n, wxPoint pts[])
2400 {
2401 wxRealPoint* realPoints = new wxRealPoint[n];
2402 int i;
2403 for (i = 0; i < n; i++)
2404 {
2405 realPoints[i].x = pts[i].x;
2406 realPoints[i].y = pts[i].y;
2407 }
2408 wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_SPLINE, n, realPoints);
2409 m_ops.Append(theOp);
2410 }
2411
2412 void wxPseudoMetaFile::SetClippingRect(const wxRect& rect)
2413 {
2414 /* wxOpSetClipping* theOp = */ new wxOpSetClipping(DRAWOP_SET_CLIPPING_RECT,
2415 (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
2416 }
2417
2418 void wxPseudoMetaFile::DestroyClippingRect()
2419 {
2420 wxOpSetClipping* theOp = new wxOpSetClipping(DRAWOP_DESTROY_CLIPPING_RECT,
2421 0.0, 0.0, 0.0, 0.0);
2422
2423 m_ops.Append(theOp);
2424 }
2425
2426 void wxPseudoMetaFile::SetPen(wxPen* pen, bool isOutline)
2427 {
2428 m_gdiObjects.Append(pen);
2429 int n = m_gdiObjects.GetCount();
2430
2431 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_PEN, this, n - 1);
2432
2433 m_ops.Append(theOp);
2434
2435 if (isOutline)
2436 {
2437 m_outlineColours.Append((wxObject*) (n - 1));
2438 }
2439 }
2440
2441 void wxPseudoMetaFile::SetBrush(wxBrush* brush, bool isFill)
2442 {
2443 m_gdiObjects.Append(brush);
2444 int n = m_gdiObjects.GetCount();
2445
2446 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BRUSH, this, n - 1);
2447
2448 m_ops.Append(theOp);
2449
2450 if (isFill)
2451 {
2452 m_fillColours.Append((wxObject*) (n - 1));
2453 }
2454 }
2455
2456 void wxPseudoMetaFile::SetFont(wxFont* font)
2457 {
2458 m_gdiObjects.Append(font);
2459 int n = m_gdiObjects.GetCount();
2460
2461 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_FONT, this, n - 1);
2462
2463 m_ops.Append(theOp);
2464 }
2465
2466 void wxPseudoMetaFile::SetTextColour(const wxColour& colour)
2467 {
2468 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
2469 theOp->m_r = colour.Red();
2470 theOp->m_g = colour.Green();
2471 theOp->m_b = colour.Blue();
2472
2473 m_ops.Append(theOp);
2474 }
2475
2476 void wxPseudoMetaFile::SetBackgroundColour(const wxColour& colour)
2477 {
2478 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_COLOUR, this, 0);
2479 theOp->m_r = colour.Red();
2480 theOp->m_g = colour.Green();
2481 theOp->m_b = colour.Blue();
2482
2483 m_ops.Append(theOp);
2484 }
2485
2486 void wxPseudoMetaFile::SetBackgroundMode(int mode)
2487 {
2488 wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_MODE, this, 0, mode);
2489
2490 m_ops.Append(theOp);
2491 }
2492