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