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