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