home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / contrib / src / ogl / drawn.cpp < prev    next >
C/C++ Source or Header  |  2002-12-18  |  67KB  |  2,500 lines

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