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