home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / src / ogl / drawn.cpp < prev    next >
C/C++ Source or Header  |  2002-03-16  |  67KB  |  2,490 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 2002/03/15 20:50:39 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. static void IntToHex(unsigned int dec, char *buf);
  39. static unsigned long HexToInt(char *buf);
  40. extern char *oglBuffer;
  41.  
  42. #define gyTYPE_PEN   40
  43. #define gyTYPE_BRUSH 41
  44. #define gyTYPE_FONT  42
  45.  
  46. /*
  47.  * Drawn object
  48.  *
  49.  */
  50.  
  51. IMPLEMENT_DYNAMIC_CLASS(wxDrawnShape, wxRectangleShape)
  52.  
  53. wxDrawnShape::wxDrawnShape():wxRectangleShape(100.0, 50.0)
  54. {
  55.   m_saveToFile = TRUE;
  56.   m_currentAngle = oglDRAWN_ANGLE_0;
  57. }
  58.  
  59. wxDrawnShape::~wxDrawnShape()
  60. {
  61. }
  62.  
  63. void wxDrawnShape::OnDraw(wxDC& dc)
  64. {
  65.   // Pass pen and brush in case we have force outline
  66.   // and fill colours
  67.   if (m_shadowMode != SHADOW_NONE)
  68.   {
  69.     if (m_shadowBrush)
  70.       m_metafiles[m_currentAngle].m_fillBrush = m_shadowBrush;
  71.     m_metafiles[m_currentAngle].m_outlinePen = g_oglTransparentPen;
  72.     m_metafiles[m_currentAngle].Draw(dc, m_xpos + m_shadowOffsetX, m_ypos + m_shadowOffsetY);
  73.   }
  74.  
  75.   m_metafiles[m_currentAngle].m_outlinePen = m_pen;
  76.   m_metafiles[m_currentAngle].m_fillBrush = m_brush;
  77.   m_metafiles[m_currentAngle].Draw(dc, m_xpos, m_ypos);
  78. }
  79.  
  80. void wxDrawnShape::SetSize(double w, double h, bool recursive)
  81. {
  82.   SetAttachmentSize(w, h);
  83.  
  84.   double scaleX;
  85.   double scaleY;
  86.   if (GetWidth() == 0.0)
  87.     scaleX = 1.0;
  88.   else scaleX = w/GetWidth();
  89.   if (GetHeight() == 0.0)
  90.     scaleY = 1.0;
  91.   else scaleY = h/GetHeight();
  92.  
  93.   int i = 0;
  94.   for (i = 0; i < 4; i++)
  95.   {
  96.     if (m_metafiles[i].IsValid())
  97.         m_metafiles[i].Scale(scaleX, scaleY);
  98.   }
  99.   m_width = w;
  100.   m_height = h;
  101.   SetDefaultRegionSize();
  102. }
  103.  
  104. void wxDrawnShape::Scale(double sx, double sy)
  105. {
  106.     int i;
  107.     for (i = 0; i < 4; i++)
  108.     {
  109.         if (m_metafiles[i].IsValid())
  110.         {
  111.             m_metafiles[i].Scale(sx, sy);
  112.             m_metafiles[i].CalculateSize(this);
  113.         }
  114.     }
  115. }
  116.  
  117. void wxDrawnShape::Translate(double x, double y)
  118. {
  119.     int i;
  120.     for (i = 0; i < 4; i++)
  121.     {
  122.         if (m_metafiles[i].IsValid())
  123.         {
  124.             m_metafiles[i].Translate(x, y);
  125.             m_metafiles[i].CalculateSize(this);
  126.         }
  127.     }
  128. }
  129.  
  130. // theta is absolute rotation from the zero position
  131. void wxDrawnShape::Rotate(double x, double y, double theta)
  132. {
  133.   m_currentAngle = DetermineMetaFile(theta);
  134.  
  135.   if (m_currentAngle == 0)
  136.   {
  137.     // Rotate metafile
  138.     if (!m_metafiles[0].GetRotateable())
  139.       return;
  140.  
  141.     m_metafiles[0].Rotate(x, y, theta);
  142.   }
  143.  
  144.   double actualTheta = theta-m_rotation;
  145.  
  146.   // Rotate attachment points
  147.   double sinTheta = (double)sin(actualTheta);
  148.   double cosTheta = (double)cos(actualTheta);
  149.   wxNode *node = m_attachmentPoints.First();
  150.   while (node)
  151.   {
  152.     wxAttachmentPoint *point = (wxAttachmentPoint *)node->Data();
  153.     double x1 = point->m_x;
  154.     double y1 = point->m_y;
  155.     point->m_x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  156.     point->m_y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  157.     node = node->Next();
  158.   }
  159.   m_rotation = theta;
  160.  
  161.   m_metafiles[m_currentAngle].CalculateSize(this);
  162. }
  163.  
  164. // Which metafile do we use now? Based on current rotation and validity
  165. // of metafiles.
  166.  
  167. int wxDrawnShape::DetermineMetaFile(double rotation)
  168. {
  169.     double tolerance = 0.0001;
  170.     const double pi = 3.1415926535897932384626433832795 ;
  171.     double angle1 = 0.0;
  172.     double angle2 = pi/2.0;
  173.     double angle3 = pi;
  174.     double angle4 = 3.0*pi/2.0;
  175.  
  176.     int whichMetafile = 0;
  177.  
  178.     if (oglRoughlyEqual(rotation, angle1, tolerance))
  179.     {
  180.         whichMetafile = 0;
  181.     }
  182.     else if (oglRoughlyEqual(rotation, angle2, tolerance))
  183.     {
  184.         whichMetafile = 1;
  185.     }
  186.     else if (oglRoughlyEqual(rotation, angle3, tolerance))
  187.     {
  188.         whichMetafile = 2;
  189.     }
  190.     else if (oglRoughlyEqual(rotation, angle4, tolerance))
  191.     {
  192.         whichMetafile = 3;
  193.     }
  194.  
  195.     if ((whichMetafile > 0) && !m_metafiles[whichMetafile].IsValid())
  196.         whichMetafile = 0;
  197.  
  198.     return whichMetafile;
  199. }
  200.  
  201. void wxDrawnShape::OnDrawOutline(wxDC& dc, double x, double y, double w, double h)
  202. {
  203.     if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
  204.     {
  205.         wxNode* node = m_metafiles[m_currentAngle].GetOps().Nth(m_metafiles[m_currentAngle].GetOutlineOp());
  206.         wxASSERT (node != NULL);
  207.         wxDrawOp* op = (wxDrawOp*) node->Data();
  208.  
  209.         if (op->OnDrawOutline(dc, x, y, w, h, m_width, m_height))
  210.             return;
  211.     }
  212.  
  213.     // Default... just use a rectangle
  214.     wxRectangleShape::OnDrawOutline(dc, x, y, w, h);
  215. }
  216.  
  217. // Get the perimeter point using the special outline op, if there is one,
  218. // otherwise use default wxRectangleShape scheme
  219. bool wxDrawnShape::GetPerimeterPoint(double x1, double y1,
  220.                                      double x2, double y2,
  221.                                      double *x3, double *y3)
  222. {
  223.     if (m_metafiles[m_currentAngle].GetOutlineOp() != -1)
  224.     {
  225.         wxNode* node = m_metafiles[m_currentAngle].GetOps().Nth(m_metafiles[m_currentAngle].GetOutlineOp());
  226.         wxASSERT (node != NULL);
  227.         wxDrawOp* op = (wxDrawOp*) node->Data();
  228.  
  229.         if (op->GetPerimeterPoint(x1, y1, x2, y2, x3, y3, GetX(), GetY(), GetAttachmentMode()))
  230.             return TRUE;
  231.     }
  232.  
  233.     // Default... just use a rectangle
  234.     return wxRectangleShape::GetPerimeterPoint(x1, y1, x2, y2, x3, y3);
  235. }
  236.  
  237. #ifdef PROLOGIO
  238. void wxDrawnShape::WriteAttributes(wxExpr *clause)
  239. {
  240.   wxRectangleShape::WriteAttributes(clause);
  241.  
  242.   clause->AddAttributeValue("current_angle", (long)m_currentAngle);
  243.   clause->AddAttributeValue("save_metafile", (long)m_saveToFile);
  244.   if (m_saveToFile)
  245.   {
  246.     int i = 0;
  247.     for (i = 0; i < 4; i++)
  248.     {
  249.         if (m_metafiles[i].IsValid())
  250.             m_metafiles[i].WriteAttributes(clause, i);
  251.     }
  252.   }
  253. }
  254.  
  255. void wxDrawnShape::ReadAttributes(wxExpr *clause)
  256. {
  257.   wxRectangleShape::ReadAttributes(clause);
  258.  
  259.   int iVal = (int) m_saveToFile;
  260.   clause->GetAttributeValue("save_metafile", iVal);
  261.   clause->GetAttributeValue("current_angle", m_currentAngle);
  262.   m_saveToFile = (iVal != 0);
  263.  
  264.   if (m_saveToFile)
  265.   {
  266.     int i = 0;
  267.     for (i = 0; i < 4; i++)
  268.     {
  269.       m_metafiles[i].ReadAttributes(clause, i);
  270.     }
  271.   }
  272. }
  273. #endif
  274.  
  275. // Does the copying for this object
  276. void wxDrawnShape::Copy(wxShape& copy)
  277. {
  278.   wxRectangleShape::Copy(copy);
  279.  
  280.   wxASSERT( copy.IsKindOf(CLASSINFO(wxDrawnShape)) ) ;
  281.  
  282.   wxDrawnShape& drawnCopy = (wxDrawnShape&) copy;
  283.  
  284.   int i = 0;
  285.   for (i = 0; i < 4; i++)
  286.   {
  287.     m_metafiles[i].Copy(drawnCopy.m_metafiles[i]);
  288.   }
  289.   drawnCopy.m_saveToFile = m_saveToFile;
  290.   drawnCopy.m_currentAngle = m_currentAngle;
  291. }
  292.  
  293. bool wxDrawnShape::LoadFromMetaFile(char *filename)
  294. {
  295.   return m_metafiles[0].LoadFromMetaFile(filename, &m_width, &m_height);
  296. }
  297.  
  298. // Set of functions for drawing into a pseudo metafile.
  299. // They use integers, but doubles are used internally for accuracy
  300. // when scaling.
  301.  
  302. void wxDrawnShape::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
  303. {
  304.     m_metafiles[m_currentAngle].DrawLine(pt1, pt2);
  305. }
  306.  
  307. void wxDrawnShape::DrawRectangle(const wxRect& rect)
  308. {
  309.     m_metafiles[m_currentAngle].DrawRectangle(rect);
  310. }
  311.  
  312. void wxDrawnShape::DrawRoundedRectangle(const wxRect& rect, double radius)
  313. {
  314.     m_metafiles[m_currentAngle].DrawRoundedRectangle(rect, radius);
  315. }
  316.  
  317. void wxDrawnShape::DrawEllipse(const wxRect& rect)
  318. {
  319.     m_metafiles[m_currentAngle].DrawEllipse(rect);
  320. }
  321.  
  322. void wxDrawnShape::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
  323. {
  324.     m_metafiles[m_currentAngle].DrawArc(centrePt, startPt, endPt);
  325. }
  326.  
  327. void wxDrawnShape::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
  328. {
  329.     m_metafiles[m_currentAngle].DrawEllipticArc(rect, startAngle, endAngle);
  330. }
  331.  
  332. void wxDrawnShape::DrawPoint(const wxPoint& pt)
  333. {
  334.     m_metafiles[m_currentAngle].DrawPoint(pt);
  335. }
  336.  
  337. void wxDrawnShape::DrawText(const wxString& text, const wxPoint& pt)
  338. {
  339.     m_metafiles[m_currentAngle].DrawText(text, pt);
  340. }
  341.  
  342. void wxDrawnShape::DrawLines(int n, wxPoint pts[])
  343. {
  344.     m_metafiles[m_currentAngle].DrawLines(n, pts);
  345. }
  346.  
  347. void wxDrawnShape::DrawPolygon(int n, wxPoint pts[], int flags)
  348. {
  349.     if (flags & oglMETAFLAGS_ATTACHMENTS)
  350.     {
  351.         ClearAttachments();
  352.         int i;
  353.         for (i = 0; i < n; i++)
  354.             m_attachmentPoints.Append(new wxAttachmentPoint(i, pts[i].x, pts[i].y));
  355.     }
  356.     m_metafiles[m_currentAngle].DrawPolygon(n, pts, flags);
  357. }
  358.  
  359. void wxDrawnShape::DrawSpline(int n, wxPoint pts[])
  360. {
  361.     m_metafiles[m_currentAngle].DrawSpline(n, pts);
  362. }
  363.  
  364. void wxDrawnShape::SetClippingRect(const wxRect& rect)
  365. {
  366.     m_metafiles[m_currentAngle].SetClippingRect(rect);
  367. }
  368.  
  369. void wxDrawnShape::DestroyClippingRect()
  370. {
  371.     m_metafiles[m_currentAngle].DestroyClippingRect();
  372. }
  373.  
  374. void wxDrawnShape::SetDrawnPen(wxPen* pen, bool isOutline)
  375. {
  376.     m_metafiles[m_currentAngle].SetPen(pen, isOutline);
  377. }
  378.  
  379. void wxDrawnShape::SetDrawnBrush(wxBrush* brush, bool isFill)
  380. {
  381.     m_metafiles[m_currentAngle].SetBrush(brush, isFill);
  382. }
  383.  
  384. void wxDrawnShape::SetDrawnFont(wxFont* font)
  385. {
  386.     m_metafiles[m_currentAngle].SetFont(font);
  387. }
  388.  
  389. void wxDrawnShape::SetDrawnTextColour(const wxColour& colour)
  390. {
  391.     m_metafiles[m_currentAngle].SetTextColour(colour);
  392. }
  393.  
  394. void wxDrawnShape::SetDrawnBackgroundColour(const wxColour& colour)
  395. {
  396.     m_metafiles[m_currentAngle].SetBackgroundColour(colour);
  397. }
  398.  
  399. void wxDrawnShape::SetDrawnBackgroundMode(int mode)
  400. {
  401.     m_metafiles[m_currentAngle].SetBackgroundMode(mode);
  402. }
  403.  
  404.  
  405. /*
  406.  * Individual operations
  407.  *
  408.  */
  409.  
  410. /*
  411.  * Set font, brush, text colour
  412.  *
  413.  */
  414.  
  415. wxOpSetGDI::wxOpSetGDI(int theOp, wxPseudoMetaFile *theImage, int theGdiIndex, int theMode):
  416.   wxDrawOp(theOp)
  417. {
  418.   m_gdiIndex = theGdiIndex;
  419.   m_image = theImage;
  420.   m_mode = theMode;
  421. }
  422.  
  423. void wxOpSetGDI::Do(wxDC& dc, double xoffset, double yoffset)
  424. {
  425.   switch (m_op)
  426.   {
  427.     case DRAWOP_SET_PEN:
  428.     {
  429.       // Check for overriding this operation for outline
  430.       // colour
  431.       if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
  432.       {
  433.         if (m_image->m_outlinePen)
  434.           dc.SetPen(* m_image->m_outlinePen);
  435.       }
  436.       else
  437.       {
  438.         wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
  439.         if (node)
  440.         {
  441.           wxPen *pen = (wxPen *)node->Data();
  442.           if (pen)
  443.             dc.SetPen(* pen);
  444.         }
  445.       }
  446.       break;
  447.     }
  448.     case DRAWOP_SET_BRUSH:
  449.     {
  450.       // Check for overriding this operation for outline or fill
  451.       // colour
  452.       if (m_image->m_outlineColours.Member((wxObject *)m_gdiIndex))
  453.       {
  454.         // Need to construct a brush to match the outline pen's colour
  455.         if (m_image->m_outlinePen)
  456.         {
  457.           wxBrush *br = wxTheBrushList->FindOrCreateBrush(m_image->m_outlinePen->GetColour(), wxSOLID);
  458.           if (br)
  459.             dc.SetBrush(* br);
  460.         }
  461.       }
  462.       else if (m_image->m_fillColours.Member((wxObject *)m_gdiIndex))
  463.       {
  464.         if (m_image->m_fillBrush)
  465.         {
  466.           dc.SetBrush(* m_image->m_fillBrush);
  467.         }
  468.       }
  469.       else
  470.       {
  471.         wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
  472.         if (node)
  473.         {
  474.           wxBrush *brush = (wxBrush *)node->Data();
  475.           if (brush)
  476.             dc.SetBrush(* brush);
  477.         }
  478.       }
  479.       break;
  480.     }
  481.     case DRAWOP_SET_FONT:
  482.     {
  483.       wxNode *node = m_image->m_gdiObjects.Nth(m_gdiIndex);
  484.       if (node)
  485.       {
  486.         wxFont *font = (wxFont *)node->Data();
  487.         if (font)
  488.           dc.SetFont(* font);
  489.       }
  490.       break;
  491.     }
  492.     case DRAWOP_SET_TEXT_COLOUR:
  493.     {
  494.       wxColour col(m_r,m_g,m_b);
  495.       dc.SetTextForeground(col);
  496.       break;
  497.     }
  498.     case DRAWOP_SET_BK_COLOUR:
  499.     {
  500.       wxColour col(m_r,m_g,m_b);
  501.       dc.SetTextBackground(col);
  502.       break;
  503.     }
  504.     case DRAWOP_SET_BK_MODE:
  505.     {
  506.       dc.SetBackgroundMode(m_mode);
  507.       break;
  508.     }
  509.     default:
  510.       break;
  511.   }
  512. }
  513.  
  514. wxDrawOp *wxOpSetGDI::Copy(wxPseudoMetaFile *newImage)
  515. {
  516.   wxOpSetGDI *newOp = new wxOpSetGDI(m_op, newImage, m_gdiIndex, m_mode);
  517.   newOp->m_r = m_r;
  518.   newOp->m_g = m_g;
  519.   newOp->m_b = m_b;
  520.   return newOp;
  521. }
  522.  
  523. wxExpr *wxOpSetGDI::WriteExpr(wxPseudoMetaFile *image)
  524. {
  525.   wxExpr *expr = new wxExpr(wxExprList);
  526.   expr->Append(new wxExpr((long)m_op));
  527.   switch (m_op)
  528.   {
  529.     case DRAWOP_SET_PEN:
  530.     case DRAWOP_SET_BRUSH:
  531.     case DRAWOP_SET_FONT:
  532.     {
  533.       expr->Append(new wxExpr((long)m_gdiIndex));
  534.       break;
  535.     }
  536.     case DRAWOP_SET_TEXT_COLOUR:
  537.     case DRAWOP_SET_BK_COLOUR:
  538.     {
  539.       expr->Append(new wxExpr((long)m_r));
  540.       expr->Append(new wxExpr((long)m_g));
  541.       expr->Append(new wxExpr((long)m_b));
  542.       break;
  543.     }
  544.     case DRAWOP_SET_BK_MODE:
  545.     {
  546.       expr->Append(new wxExpr((long)m_mode));
  547.       break;
  548.     }
  549.     default:
  550.       break;
  551.   }
  552.   return expr;
  553. }
  554.  
  555. void wxOpSetGDI::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
  556. {
  557.   switch (m_op)
  558.   {
  559.     case DRAWOP_SET_PEN:
  560.     case DRAWOP_SET_BRUSH:
  561.     case DRAWOP_SET_FONT:
  562.     {
  563.       m_gdiIndex = (int)expr->Nth(1)->IntegerValue();
  564.       break;
  565.     }
  566.     case DRAWOP_SET_TEXT_COLOUR:
  567.     case DRAWOP_SET_BK_COLOUR:
  568.     {
  569.       m_r = (unsigned char)expr->Nth(1)->IntegerValue();
  570.       m_g = (unsigned char)expr->Nth(2)->IntegerValue();
  571.       m_b = (unsigned char)expr->Nth(3)->IntegerValue();
  572.       break;
  573.     }
  574.     case DRAWOP_SET_BK_MODE:
  575.     {
  576.       m_mode = (int)expr->Nth(1)->IntegerValue();
  577.       break;
  578.     }
  579.     default:
  580.       break;
  581.   }
  582. }
  583.  
  584. /*
  585.  * Set/destroy clipping
  586.  *
  587.  */
  588.  
  589. wxOpSetClipping::wxOpSetClipping(int theOp, double theX1, double theY1,
  590.     double theX2, double theY2):wxDrawOp(theOp)
  591. {
  592.   m_x1 = theX1;
  593.   m_y1 = theY1;
  594.   m_x2 = theX2;
  595.   m_y2 = theY2;
  596. }
  597.  
  598. wxDrawOp *wxOpSetClipping::Copy(wxPseudoMetaFile *newImage)
  599. {
  600.   wxOpSetClipping *newOp = new wxOpSetClipping(m_op, m_x1, m_y1, m_x2, m_y2);
  601.   return newOp;
  602. }
  603.  
  604. void wxOpSetClipping::Do(wxDC& dc, double xoffset, double yoffset)
  605. {
  606.   switch (m_op)
  607.   {
  608.     case DRAWOP_SET_CLIPPING_RECT:
  609.     {
  610.       dc.SetClippingRegion((long)(m_x1 + xoffset), (long)(m_y1 + yoffset), (long)(m_x2 + xoffset), (long)(m_y2 + yoffset));
  611.       break;
  612.     }
  613.     case DRAWOP_DESTROY_CLIPPING_RECT:
  614.     {
  615.       dc.DestroyClippingRegion();
  616.       break;
  617.     }
  618.     default:
  619.       break;
  620.   }
  621. }
  622.  
  623. void wxOpSetClipping::Scale(double xScale, double yScale)
  624. {
  625.   m_x1 *= xScale;
  626.   m_y1 *= yScale;
  627.   m_x2 *= xScale;
  628.   m_y2 *= yScale;
  629. }
  630.  
  631. void wxOpSetClipping::Translate(double x, double y)
  632. {
  633.   m_x1 += x;
  634.   m_y1 += y;
  635. }
  636.  
  637. wxExpr *wxOpSetClipping::WriteExpr(wxPseudoMetaFile *image)
  638. {
  639.   wxExpr *expr = new wxExpr(wxExprList);
  640.   expr->Append(new wxExpr((long)m_op));
  641.   switch (m_op)
  642.   {
  643.     case DRAWOP_SET_CLIPPING_RECT:
  644.     {
  645.       expr->Append(new wxExpr(m_x1));
  646.       expr->Append(new wxExpr(m_y1));
  647.       expr->Append(new wxExpr(m_x2));
  648.       expr->Append(new wxExpr(m_y2));
  649.       break;
  650.     }
  651.     default:
  652.       break;
  653.   }
  654.   return expr;
  655. }
  656.  
  657. void wxOpSetClipping::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
  658. {
  659.   switch (m_op)
  660.   {
  661.     case DRAWOP_SET_CLIPPING_RECT:
  662.     {
  663.       m_x1 = expr->Nth(1)->RealValue();
  664.       m_y1 = expr->Nth(2)->RealValue();
  665.       m_x2 = expr->Nth(3)->RealValue();
  666.       m_y2 = expr->Nth(4)->RealValue();
  667.       break;
  668.     }
  669.     default:
  670.       break;
  671.   }
  672. }
  673.  
  674. /*
  675.  * Draw line, rectangle, rounded rectangle, ellipse, point, arc, text
  676.  *
  677.  */
  678.  
  679. wxOpDraw::wxOpDraw(int theOp, double theX1, double theY1, double theX2, double theY2,
  680.          double theRadius, wxChar *s) : wxDrawOp(theOp)
  681. {
  682.   m_x1 = theX1;
  683.   m_y1 = theY1;
  684.   m_x2 = theX2;
  685.   m_y2 = theY2;
  686.   m_x3 = 0.0;
  687.   m_y3 = 0.0;
  688.   m_radius = theRadius;
  689.   if (s) m_textString = copystring(s);
  690.   else m_textString = NULL;
  691. }
  692.  
  693. wxOpDraw::~wxOpDraw()
  694. {
  695.   if (m_textString) delete[] m_textString;
  696. }
  697.  
  698. wxDrawOp *wxOpDraw::Copy(wxPseudoMetaFile *newImage)
  699. {
  700.   wxOpDraw *newOp = new wxOpDraw(m_op, m_x1, m_y1, m_x2, m_y2, m_radius, m_textString);
  701.   newOp->m_x3 = m_x3;
  702.   newOp->m_y3 = m_y3;
  703.   return newOp;
  704. }
  705.  
  706. void wxOpDraw::Do(wxDC& dc, double xoffset, double yoffset)
  707. {
  708.   switch (m_op)
  709.   {
  710.     case DRAWOP_DRAW_LINE:
  711.     {
  712.       dc.DrawLine(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset));
  713.       break;
  714.     }
  715.     case DRAWOP_DRAW_RECT:
  716.     {
  717.       dc.DrawRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
  718.       break;
  719.     }
  720.     case DRAWOP_DRAW_ROUNDED_RECT:
  721.     {
  722.       dc.DrawRoundedRectangle(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2), m_radius);
  723.       break;
  724.     }
  725.     case DRAWOP_DRAW_ELLIPSE:
  726.     {
  727.       dc.DrawEllipse(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset), WXROUND(m_x2), WXROUND(m_y2));
  728.       break;
  729.     }
  730.     case DRAWOP_DRAW_ARC:
  731.     {
  732.       dc.DrawArc(WXROUND(m_x2+xoffset), WXROUND(m_y2+yoffset),
  733.                  WXROUND(m_x3+xoffset), WXROUND(m_y3+yoffset),
  734.                  WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
  735.       break;
  736.     }
  737.     case DRAWOP_DRAW_ELLIPTIC_ARC:
  738.     {
  739.       const double pi = 3.1415926535897932384626433832795 ;
  740.  
  741.       // Convert back to degrees
  742.       dc.DrawEllipticArc(
  743.                  WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset),
  744.                  WXROUND(m_x2), WXROUND(m_y2),
  745.                  WXROUND(m_x3*(360.0/(2.0*pi))), WXROUND(m_y3*(360.0/(2.0*pi))));
  746.       break;
  747.     }
  748.     case DRAWOP_DRAW_POINT:
  749.     {
  750.       dc.DrawPoint(WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
  751.       break;
  752.     }
  753.     case DRAWOP_DRAW_TEXT:
  754.     {
  755.       dc.DrawText(m_textString, WXROUND(m_x1+xoffset), WXROUND(m_y1+yoffset));
  756.       break;
  757.     }
  758.     default:
  759.       break;
  760.   }
  761. }
  762.  
  763. void wxOpDraw::Scale(double scaleX, double scaleY)
  764. {
  765.   m_x1 *= scaleX;
  766.   m_y1 *= scaleY;
  767.   m_x2 *= scaleX;
  768.   m_y2 *= scaleY;
  769.  
  770.   if (m_op != DRAWOP_DRAW_ELLIPTIC_ARC)
  771.   {
  772.     m_x3 *= scaleX;
  773.     m_y3 *= scaleY;
  774.   }
  775.  
  776.   m_radius *= scaleX;
  777. }
  778.  
  779. void wxOpDraw::Translate(double x, double y)
  780. {
  781.   m_x1 += x;
  782.   m_y1 += y;
  783.  
  784.   switch (m_op)
  785.   {
  786.     case DRAWOP_DRAW_LINE:
  787.     {
  788.       m_x2 += x;
  789.       m_y2 += y;
  790.       break;
  791.     }
  792.     case DRAWOP_DRAW_ARC:
  793.     {
  794.       m_x2 += x;
  795.       m_y2 += y;
  796.       m_x3 += x;
  797.       m_y3 += y;
  798.       break;
  799.     }
  800.     case DRAWOP_DRAW_ELLIPTIC_ARC:
  801.     {
  802.       break;
  803.     }
  804.     default:
  805.       break;
  806.   }
  807. }
  808.  
  809. void wxOpDraw::Rotate(double x, double y, double theta, double sinTheta, double cosTheta)
  810. {
  811.   double newX1 = m_x1*cosTheta - m_y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  812.   double newY1 = m_x1*sinTheta + m_y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  813.  
  814.   switch (m_op)
  815.   {
  816.     case DRAWOP_DRAW_LINE:
  817.     {
  818.       double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  819.       double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  820.  
  821.       m_x1 = newX1;
  822.       m_y1 = newY1;
  823.       m_x2 = newX2;
  824.       m_y2 = newY2;
  825.       break;
  826.     }
  827.     case DRAWOP_DRAW_RECT:
  828.     case DRAWOP_DRAW_ROUNDED_RECT:
  829.     case DRAWOP_DRAW_ELLIPTIC_ARC:
  830.     {
  831.       // Assume only 0, 90, 180, 270 degree rotations.
  832.       // oldX1, oldY1 represents the top left corner. Find the
  833.       // bottom right, and rotate that. Then the width/height is the difference
  834.       // between x/y values.
  835.       double oldBottomRightX = m_x1 + m_x2;
  836.       double oldBottomRightY = m_y1 + m_y2;
  837.       double newBottomRightX = oldBottomRightX*cosTheta - oldBottomRightY*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  838.       double newBottomRightY = oldBottomRightX*sinTheta + oldBottomRightY*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  839.  
  840.       // Now find the new top-left, bottom-right coordinates.
  841.       double minX = wxMin(newX1, newBottomRightX);
  842.       double minY = wxMin(newY1, newBottomRightY);
  843.       double maxX = wxMax(newX1, newBottomRightX);
  844.       double maxY = wxMax(newY1, newBottomRightY);
  845.  
  846.       m_x1 = minX;
  847.       m_y1 = minY;
  848.       m_x2 = maxX - minX; // width
  849.       m_y2 = maxY - minY; // height
  850.  
  851.       if (m_op == DRAWOP_DRAW_ELLIPTIC_ARC)
  852.       {
  853.         // Add rotation to angles
  854.         m_x3 += theta;
  855.         m_y3 += theta;
  856.       }
  857.  
  858.       break;
  859.     }
  860.     case DRAWOP_DRAW_ARC:
  861.     {
  862.       double newX2 = m_x2*cosTheta - m_y2*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  863.       double newY2 = m_x2*sinTheta + m_y2*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  864.       double newX3 = m_x3*cosTheta - m_y3*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  865.       double newY3 = m_x3*sinTheta + m_y3*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  866.  
  867.       m_x1 = newX1;
  868.       m_y1 = newY1;
  869.       m_x2 = newX2;
  870.       m_y2 = newY2;
  871.       m_x3 = newX3;
  872.       m_y3 = newY3;
  873.  
  874.       break;
  875.     }
  876.     default:
  877.       break;
  878.   }
  879. }
  880.  
  881. wxExpr *wxOpDraw::WriteExpr(wxPseudoMetaFile *image)
  882. {
  883.   wxExpr *expr = new wxExpr(wxExprList);
  884.   expr->Append(new wxExpr((long)m_op));
  885.   switch (m_op)
  886.   {
  887.     case DRAWOP_DRAW_LINE:
  888.     case DRAWOP_DRAW_RECT:
  889.     case DRAWOP_DRAW_ELLIPSE:
  890.     {
  891.       expr->Append(new wxExpr(m_x1));
  892.       expr->Append(new wxExpr(m_y1));
  893.       expr->Append(new wxExpr(m_x2));
  894.       expr->Append(new wxExpr(m_y2));
  895.       break;
  896.     }
  897.     case DRAWOP_DRAW_ROUNDED_RECT:
  898.     {
  899.       expr->Append(new wxExpr(m_x1));
  900.       expr->Append(new wxExpr(m_y1));
  901.       expr->Append(new wxExpr(m_x2));
  902.       expr->Append(new wxExpr(m_y2));
  903.       expr->Append(new wxExpr(m_radius));
  904.       break;
  905.     }
  906.     case DRAWOP_DRAW_POINT:
  907.     {
  908.       expr->Append(new wxExpr(m_x1));
  909.       expr->Append(new wxExpr(m_y1));
  910.       break;
  911.     }
  912.     case DRAWOP_DRAW_TEXT:
  913.     {
  914.       expr->Append(new wxExpr(m_x1));
  915.       expr->Append(new wxExpr(m_y1));
  916.       expr->Append(new wxExpr(wxExprString, m_textString));
  917.       break;
  918.     }
  919.     case DRAWOP_DRAW_ARC:
  920.     case DRAWOP_DRAW_ELLIPTIC_ARC:
  921.     {
  922.       expr->Append(new wxExpr(m_x1));
  923.       expr->Append(new wxExpr(m_y1));
  924.       expr->Append(new wxExpr(m_x2));
  925.       expr->Append(new wxExpr(m_y2));
  926.       expr->Append(new wxExpr(m_x3));
  927.       expr->Append(new wxExpr(m_y3));
  928.       break;
  929.     }
  930.     default:
  931.     {
  932.       break;
  933.     }
  934.   }
  935.   return expr;
  936. }
  937.  
  938. void wxOpDraw::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
  939. {
  940.   switch (m_op)
  941.   {
  942.     case DRAWOP_DRAW_LINE:
  943.     case DRAWOP_DRAW_RECT:
  944.     case DRAWOP_DRAW_ELLIPSE:
  945.     {
  946.       m_x1 = expr->Nth(1)->RealValue();
  947.       m_y1 = expr->Nth(2)->RealValue();
  948.       m_x2 = expr->Nth(3)->RealValue();
  949.       m_y2 = expr->Nth(4)->RealValue();
  950.       break;
  951.     }
  952.     case DRAWOP_DRAW_ROUNDED_RECT:
  953.     {
  954.       m_x1 = expr->Nth(1)->RealValue();
  955.       m_y1 = expr->Nth(2)->RealValue();
  956.       m_x2 = expr->Nth(3)->RealValue();
  957.       m_y2 = expr->Nth(4)->RealValue();
  958.       m_radius = expr->Nth(5)->RealValue();
  959.       break;
  960.     }
  961.     case DRAWOP_DRAW_POINT:
  962.     {
  963.       m_x1 = expr->Nth(1)->RealValue();
  964.       m_y1 = expr->Nth(2)->RealValue();
  965.       break;
  966.     }
  967.     case DRAWOP_DRAW_TEXT:
  968.     {
  969.       m_x1 = expr->Nth(1)->RealValue();
  970.       m_y1 = expr->Nth(2)->RealValue();
  971.       wxString str(expr->Nth(3)->StringValue());
  972.       m_textString = copystring(str);
  973.       break;
  974.     }
  975.     case DRAWOP_DRAW_ARC:
  976.     case DRAWOP_DRAW_ELLIPTIC_ARC:
  977.     {
  978.       m_x1 = expr->Nth(1)->RealValue();
  979.       m_y1 = expr->Nth(2)->RealValue();
  980.       m_x2 = expr->Nth(3)->RealValue();
  981.       m_y2 = expr->Nth(4)->RealValue();
  982.       m_x3 = expr->Nth(5)->RealValue();
  983.       m_y3 = expr->Nth(6)->RealValue();
  984.       break;
  985.     }
  986.     default:
  987.     {
  988.       break;
  989.     }
  990.   }
  991. }
  992.  
  993. /*
  994.  * Draw polygon, polyline, spline
  995.  *
  996.  */
  997.  
  998. wxOpPolyDraw::wxOpPolyDraw(int theOp, int n, wxRealPoint *thePoints):wxDrawOp(theOp)
  999. {
  1000.   m_noPoints = n;
  1001.   m_points = thePoints;
  1002. }
  1003.  
  1004. wxOpPolyDraw::~wxOpPolyDraw()
  1005. {
  1006.   delete[] m_points;
  1007. }
  1008.  
  1009. wxDrawOp *wxOpPolyDraw::Copy(wxPseudoMetaFile *newImage)
  1010. {
  1011.   wxRealPoint *newPoints = new wxRealPoint[m_noPoints];
  1012.   for (int i = 0; i < m_noPoints; i++)
  1013.   {
  1014.     newPoints[i].x = m_points[i].x;
  1015.     newPoints[i].y = m_points[i].y;
  1016.   }
  1017.   wxOpPolyDraw *newOp = new wxOpPolyDraw(m_op, m_noPoints, newPoints);
  1018.   return newOp;
  1019. }
  1020.  
  1021. void wxOpPolyDraw::Do(wxDC& dc, double xoffset, double yoffset)
  1022. {
  1023.   switch (m_op)
  1024.   {
  1025.     case DRAWOP_DRAW_POLYLINE:
  1026.     {
  1027.         wxPoint *actualPoints = new wxPoint[m_noPoints];
  1028.         int i;
  1029.         for (i = 0; i < m_noPoints; i++)
  1030.         {
  1031.             actualPoints[i].x = WXROUND(m_points[i].x);
  1032.             actualPoints[i].y = WXROUND(m_points[i].y);
  1033.         }
  1034.  
  1035.         dc.DrawLines(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
  1036.  
  1037.         delete[] actualPoints;
  1038.         break;
  1039.     }
  1040.     case DRAWOP_DRAW_POLYGON:
  1041.     {
  1042.         wxPoint *actualPoints = new wxPoint[m_noPoints];
  1043.         int i;
  1044.         for (i = 0; i < m_noPoints; i++)
  1045.         {
  1046.             actualPoints[i].x = WXROUND(m_points[i].x);
  1047.             actualPoints[i].y = WXROUND(m_points[i].y);
  1048.         }
  1049.  
  1050.         dc.DrawPolygon(m_noPoints, actualPoints, WXROUND(xoffset), WXROUND(yoffset));
  1051.  
  1052.         delete[] actualPoints;
  1053.         break;
  1054.     }
  1055.     case DRAWOP_DRAW_SPLINE:
  1056.     {
  1057.         wxPoint *actualPoints = new wxPoint[m_noPoints];
  1058.         int i;
  1059.         for (i = 0; i < m_noPoints; i++)
  1060.         {
  1061.             actualPoints[i].x = WXROUND(m_points[i].x);
  1062.             actualPoints[i].y = WXROUND(m_points[i].y);
  1063.         }
  1064.  
  1065.         dc.DrawSpline(m_noPoints, actualPoints); // no offsets in DrawSpline // , xoffset, yoffset);
  1066.  
  1067.         delete[] actualPoints;
  1068.         break;
  1069.       break;
  1070.     }
  1071.     default:
  1072.       break;
  1073.   }
  1074. }
  1075.  
  1076. void wxOpPolyDraw::Scale(double scaleX, double scaleY)
  1077. {
  1078.   for (int i = 0; i < m_noPoints; i++)
  1079.   {
  1080.     m_points[i].x *= scaleX;
  1081.     m_points[i].y *= scaleY;
  1082.   }
  1083. }
  1084.  
  1085. void wxOpPolyDraw::Translate(double x, double y)
  1086. {
  1087.   for (int i = 0; i < m_noPoints; i++)
  1088.   {
  1089.     m_points[i].x += x;
  1090.     m_points[i].y += y;
  1091.   }
  1092. }
  1093.  
  1094. void wxOpPolyDraw::Rotate(double x, double y, double theta, double sinTheta, double cosTheta)
  1095. {
  1096.   for (int i = 0; i < m_noPoints; i++)
  1097.   {
  1098.     double x1 = m_points[i].x;
  1099.     double y1 = m_points[i].y;
  1100.     m_points[i].x = x1*cosTheta - y1*sinTheta + x*(1.0 - cosTheta) + y*sinTheta;
  1101.     m_points[i].y = x1*sinTheta + y1*cosTheta + y*(1.0 - cosTheta) + x*sinTheta;
  1102.   }
  1103. }
  1104.  
  1105. wxExpr *wxOpPolyDraw::WriteExpr(wxPseudoMetaFile *image)
  1106. {
  1107.   wxExpr *expr = new wxExpr(wxExprList);
  1108.   expr->Append(new wxExpr((long)m_op));
  1109.   expr->Append(new wxExpr((long)m_noPoints));
  1110.  
  1111. //  char buf1[9];
  1112.   char buf2[5];
  1113.   char buf3[5];
  1114.  
  1115.   oglBuffer[0] = 0;
  1116.  
  1117.   /*
  1118.    * Store each coordinate pair in a hex string to save space.
  1119.    * E.g. "1B9080CD". 4 hex digits per coordinate pair.
  1120.    *
  1121.    */
  1122.  
  1123.   for (int i = 0; i < m_noPoints; i++)
  1124.   {
  1125.     long signedX = (long)(m_points[i].x*100.0);
  1126.     long signedY = (long)(m_points[i].y*100.0);
  1127.  
  1128.     // Scale to 0 -> 64K
  1129.     long unSignedX = (long)(signedX + 32767.0);
  1130.     long unSignedY = (long)(signedY + 32767.0);
  1131.  
  1132. //    IntToHex((unsigned int)signedX, buf2);
  1133. //    IntToHex((unsigned int)signedY, buf3);
  1134.     IntToHex((int)unSignedX, buf2);
  1135.     IntToHex((int)unSignedY, buf3);
  1136.  
  1137.     // Don't overrun the buffer
  1138.     if ((i*8) < 3000)
  1139.     {
  1140.       strcat(oglBuffer, buf2);
  1141.       strcat(oglBuffer, buf3);
  1142.     }
  1143.   }
  1144.   expr->Append(new wxExpr(wxExprString, oglBuffer));
  1145.   return expr;
  1146. }
  1147.  
  1148. void wxOpPolyDraw::ReadExpr(wxPseudoMetaFile *image, wxExpr *expr)
  1149. {
  1150.   m_noPoints = (int)expr->Nth(1)->IntegerValue();
  1151.  
  1152.   char buf1[5];
  1153.   char buf2[5];
  1154.  
  1155.   m_points = new wxRealPoint[m_noPoints];
  1156.   int i = 0;
  1157.   int bufPtr = 0;
  1158.   wxString hexString = expr->Nth(2)->StringValue();
  1159.   while (i < m_noPoints)
  1160.   {
  1161.     buf1[0] = hexString[(size_t)bufPtr];
  1162.     buf1[1] = hexString[(size_t)(bufPtr + 1)];
  1163.     buf1[2] = hexString[(size_t)(bufPtr + 2)];
  1164.     buf1[3] = hexString[(size_t)(bufPtr + 3)];
  1165.     buf1[4] = 0;
  1166.  
  1167.     buf2[0] = hexString[(size_t)(bufPtr + 4)];
  1168.     buf2[1] = hexString[(size_t)(bufPtr + 5)];
  1169.     buf2[2] = hexString[(size_t)(bufPtr + 6)];
  1170.     buf2[3] = hexString[(size_t)(bufPtr + 7)];
  1171.     buf2[4] = 0;
  1172.  
  1173.     bufPtr += 8;
  1174.  
  1175. //    int signedX = (signed int)HexToInt(buf1);
  1176. //    int signedY = (signed int)HexToInt(buf2);
  1177.     long unSignedX = HexToInt(buf1);
  1178.     long unSignedY = HexToInt(buf2);
  1179.     // Scale -32K -> +32K
  1180.     long signedX = unSignedX - 32767;
  1181.     long signedY = unSignedY - 32767;
  1182. #ifdef __WXMSW__
  1183.     int testX = (signed int)unSignedX;
  1184.     int testY = (signed int)unSignedY;
  1185. #endif
  1186.  
  1187.     m_points[i].x = (double)(signedX / 100.0);
  1188.     m_points[i].y = (double)(signedY / 100.0);
  1189.  
  1190.     i ++;
  1191.   }
  1192. }
  1193.  
  1194. // Draw an outline using the current operation.
  1195. bool wxOpPolyDraw::OnDrawOutline(wxDC& dc, double x, double y, double w, double h, double oldW, double oldH)
  1196. {
  1197.     dc.SetBrush(* wxTRANSPARENT_BRUSH);
  1198.  
  1199.     // Multiply all points by proportion of new size to old size
  1200.     double x_proportion = (double)(fabs(w/oldW));
  1201.     double y_proportion = (double)(fabs(h/oldH));
  1202.  
  1203.     int n = m_noPoints;
  1204.     wxPoint *intPoints = new wxPoint[n];
  1205.     int i;
  1206.     for (i = 0; i < n; i++)
  1207.     {
  1208.         intPoints[i].x = WXROUND (x_proportion * m_points[i].x);
  1209.         intPoints[i].y = WXROUND (y_proportion * m_points[i].y);
  1210.     }
  1211.     dc.DrawPolygon(n, intPoints, (long) x, (long) y);
  1212.     delete[] intPoints;
  1213.     return TRUE;
  1214. }
  1215.  
  1216. // Assume (x1, y1) is centre of box (most generally, line end at box)
  1217. bool wxOpPolyDraw::GetPerimeterPoint(double x1, double y1,
  1218.                                      double x2, double y2,
  1219.                                      double *x3, double *y3,
  1220.                                      double xOffset, double yOffset,
  1221.                                      int attachmentMode)
  1222. {
  1223.   int n = m_noPoints;
  1224.  
  1225.   // First check for situation where the line is vertical,
  1226.   // and we would want to connect to a point on that vertical --
  1227.   // oglFindEndForPolyline can't cope with this (the arrow
  1228.   // gets drawn to the wrong place).
  1229.   if ((attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2))
  1230.   {
  1231.     // Look for the point we'd be connecting to. This is
  1232.     // a heuristic...
  1233.     int i;
  1234.     for (i = 0; i < n; i++)
  1235.     {
  1236.       wxRealPoint *point = & (m_points[i]);
  1237.       if (point->x == 0.0)
  1238.       {
  1239.         if ((y2 > y1) && (point->y > 0.0))
  1240.         {
  1241.           *x3 = point->x + xOffset;
  1242.           *y3 = point->y + yOffset;
  1243.           return TRUE;
  1244.         }
  1245.         else if ((y2 < y1) && (point->y < 0.0))
  1246.         {
  1247.           *x3 = point->x + xOffset;
  1248.           *y3 = point->y + yOffset;
  1249.           return TRUE;
  1250.         }
  1251.       }
  1252.     }
  1253.   }
  1254.  
  1255.   double *xpoints = new double[n];
  1256.   double *ypoints = new double[n];
  1257.  
  1258.   int i = 0;
  1259.   for (i = 0; i < n; i++)
  1260.   {
  1261.     wxRealPoint *point = & (m_points[i]);
  1262.     xpoints[i] = point->x + xOffset;
  1263.     ypoints[i] = point->y + yOffset;
  1264.   }
  1265.  
  1266.   oglFindEndForPolyline(n, xpoints, ypoints,
  1267.                         x1, y1, x2, y2, x3, y3);
  1268.  
  1269.   delete[] xpoints;
  1270.   delete[] ypoints;
  1271.  
  1272.   return TRUE;
  1273. }
  1274.  
  1275.  
  1276. /*
  1277.  * Utilities
  1278.  *
  1279.  */
  1280.  
  1281. static char hexArray[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
  1282.   'C', 'D', 'E', 'F' };
  1283.  
  1284. // Convert unsigned 16-bit integer to 4-character hex string
  1285. static void IntToHex(unsigned int dec, char *buf)
  1286. {
  1287.   int digit1 = (int)(dec/4096);
  1288.   int digit2 = (int)((dec - (digit1*4096))/256);
  1289.   int digit3 = (int)((dec - (digit1*4096) - (digit2*256))/16);
  1290.   int digit4 = dec - (digit1*4096 + digit2*256 + digit3*16);
  1291.  
  1292.   buf[0] = hexArray[digit1];
  1293.   buf[1] = hexArray[digit2];
  1294.   buf[2] = hexArray[digit3];
  1295.   buf[3] = hexArray[digit4];
  1296.   buf[4] = 0;
  1297. }
  1298.  
  1299. // One hex digit to decimal number
  1300. static int HexToInt1(char hex)
  1301. {
  1302.   switch (hex)
  1303.   {
  1304.     case '0':
  1305.       return 0;
  1306.     case '1':
  1307.       return 1;
  1308.     case '2':
  1309.       return 2;
  1310.     case '3':
  1311.       return 3;
  1312.     case '4':
  1313.       return 4;
  1314.     case '5':
  1315.       return 5;
  1316.     case '6':
  1317.       return 6;
  1318.     case '7':
  1319.       return 7;
  1320.     case '8':
  1321.       return 8;
  1322.     case '9':
  1323.       return 9;
  1324.     case 'A':
  1325.       return 10;
  1326.     case 'B':
  1327.       return 11;
  1328.     case 'C':
  1329.       return 12;
  1330.     case 'D':
  1331.       return 13;
  1332.     case 'E':
  1333.       return 14;
  1334.     case 'F':
  1335.       return 15;
  1336.     default:
  1337.       return 0;
  1338.   }
  1339.   return 0;
  1340. }
  1341.  
  1342. // 4-digit hex string to unsigned integer
  1343. static unsigned long HexToInt(char *buf)
  1344. {
  1345.   long d1 = (long)(HexToInt1(buf[0])*4096.0) ;
  1346.   long d2 = (long)(HexToInt1(buf[1])*256.0) ;
  1347.   long d3 = (long)(HexToInt1(buf[2])*16.0) ;
  1348.   long d4 = (long)(HexToInt1(buf[3])) ;
  1349.   unsigned long n = (long)(d1 + d2 + d3 + d4) ;
  1350.   return n;
  1351. }
  1352.  
  1353. /*
  1354.  * wxPseudo meta-file
  1355.  *
  1356.  */
  1357.  
  1358. IMPLEMENT_DYNAMIC_CLASS(wxPseudoMetaFile, wxObject)
  1359.  
  1360. wxPseudoMetaFile::wxPseudoMetaFile()
  1361. {
  1362.   m_currentRotation = 0;
  1363.   m_rotateable = TRUE;
  1364.   m_width = 0.0;
  1365.   m_height = 0.0;
  1366.   m_outlinePen = NULL;
  1367.   m_fillBrush = NULL;
  1368.   m_outlineOp = -1;
  1369. }
  1370.  
  1371. wxPseudoMetaFile::wxPseudoMetaFile(wxPseudoMetaFile& mf)
  1372. {
  1373.   mf.Copy(*this);
  1374. }
  1375.  
  1376. wxPseudoMetaFile::~wxPseudoMetaFile()
  1377. {
  1378.   Clear();
  1379. }
  1380.  
  1381. void wxPseudoMetaFile::Clear()
  1382. {
  1383.   wxNode *node = m_ops.First();
  1384.   while (node)
  1385.   {
  1386.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1387.     delete op;
  1388.     node = node->Next();
  1389.   }
  1390.   m_ops.Clear();
  1391.   m_gdiObjects.Clear();
  1392.   m_outlineColours.Clear();
  1393.   m_fillColours.Clear();
  1394.   m_outlineOp = -1;
  1395. }
  1396.  
  1397. void wxPseudoMetaFile::Draw(wxDC& dc, double xoffset, double yoffset)
  1398. {
  1399.   wxNode *node = m_ops.First();
  1400.   while (node)
  1401.   {
  1402.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1403.     op->Do(dc, xoffset, yoffset);
  1404.     node = node->Next();
  1405.   }
  1406. }
  1407.  
  1408. void wxPseudoMetaFile::Scale(double sx, double sy)
  1409. {
  1410.   wxNode *node = m_ops.First();
  1411.   while (node)
  1412.   {
  1413.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1414.     op->Scale(sx, sy);
  1415.     node = node->Next();
  1416.   }
  1417.   m_width *= sx;
  1418.   m_height *= sy;
  1419. }
  1420.  
  1421. void wxPseudoMetaFile::Translate(double x, double y)
  1422. {
  1423.   wxNode *node = m_ops.First();
  1424.   while (node)
  1425.   {
  1426.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1427.     op->Translate(x, y);
  1428.     node = node->Next();
  1429.   }
  1430. }
  1431.  
  1432. void 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.  
  1439.   wxNode *node = m_ops.First();
  1440.   while (node)
  1441.   {
  1442.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1443.     op->Rotate(x, y, theta, sinTheta, cosTheta);
  1444.     node = node->Next();
  1445.   }
  1446.   m_currentRotation = theta;
  1447. }
  1448.  
  1449. #ifdef PROLOGIO
  1450. void wxPseudoMetaFile::WriteAttributes(wxExpr *clause, int whichAngle)
  1451. {
  1452.   wxString widthStr;
  1453.   widthStr.Printf(wxT("meta_width%d"), whichAngle);
  1454.  
  1455.   wxString heightStr;
  1456.   heightStr.Printf(wxT("meta_height%d"), whichAngle);
  1457.  
  1458.   wxString outlineStr;
  1459.   outlineStr.Printf(wxT("outline_op%d"), whichAngle);
  1460.  
  1461.   wxString rotateableStr;
  1462.   rotateableStr.Printf(wxT("meta_rotateable%d"), whichAngle);
  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
  1471.   char buf[50];
  1472.   int i = 1;
  1473.   wxNode *node = m_gdiObjects.First();
  1474.   while (node)
  1475.   {
  1476.     sprintf(buf, "gdi%d_%d", whichAngle, i);
  1477.     wxObject *obj = (wxObject *)node->Data();
  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.     }
  1526.     node = node->Next();
  1527.   }
  1528.  
  1529.   // Write drawing operations
  1530.   i = 1;
  1531.   node = m_ops.First();
  1532.   while (node)
  1533.   {
  1534.     sprintf(buf, "op%d_%d", whichAngle, i);
  1535.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1536.     wxExpr *expr = op->WriteExpr(this);
  1537.     if (expr)
  1538.     {
  1539.       clause->AddAttributeValue(buf, expr);
  1540.       i ++;
  1541.     }
  1542.     node = node->Next();
  1543.   }
  1544.  
  1545.   // Write outline and fill GDI op lists (if any)
  1546.   if (m_outlineColours.Number() > 0)
  1547.   {
  1548.     wxExpr *outlineExpr = new wxExpr(wxExprList);
  1549.     node = m_outlineColours.First();
  1550.     while (node)
  1551.     {
  1552.       outlineExpr->Append(new wxExpr((long)node->Data()));
  1553.       node = node->Next();
  1554.     }
  1555.     wxString outlineObjectsStr;
  1556.     outlineObjectsStr.Printf(wxT("outline_objects%d"), whichAngle);
  1557.  
  1558.     clause->AddAttributeValue(outlineObjectsStr, outlineExpr);
  1559.   }
  1560.   if (m_fillColours.Number() > 0)
  1561.   {
  1562.     wxExpr *fillExpr = new wxExpr(wxExprList);
  1563.     node = m_fillColours.First();
  1564.     while (node)
  1565.     {
  1566.       fillExpr->Append(new wxExpr((long)node->Data()));
  1567.       node = node->Next();
  1568.     }
  1569.     wxString fillObjectsStr;
  1570.     fillObjectsStr.Printf(wxT("fill_objects%d"), whichAngle);
  1571.  
  1572.     clause->AddAttributeValue(fillObjectsStr, fillExpr);
  1573.   }
  1574.  
  1575. }
  1576.  
  1577. void wxPseudoMetaFile::ReadAttributes(wxExpr *clause, int whichAngle)
  1578. {
  1579.   wxString widthStr;
  1580.   widthStr.Printf(wxT("meta_width%d"), whichAngle);
  1581.  
  1582.   wxString heightStr;
  1583.   heightStr.Printf(wxT("meta_height%d"), whichAngle);
  1584.  
  1585.   wxString outlineStr;
  1586.   outlineStr.Printf(wxT("outline_op%d"), whichAngle);
  1587.  
  1588.   wxString rotateableStr;
  1589.   rotateableStr.Printf(wxT("meta_rotateable%d"), whichAngle);
  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
  1600.   char buf[50];
  1601.   int i = 1;
  1602.   bool keepGoing = TRUE;
  1603.   while (keepGoing)
  1604.   {
  1605.     sprintf(buf, "gdi%d_%d", whichAngle, i);
  1606.     wxExpr *expr = NULL;
  1607.     clause->GetAttributeValue(buf, &expr);
  1608.     if (!expr)
  1609.     {
  1610.       keepGoing = FALSE;
  1611.     }
  1612.     else
  1613.     {
  1614.       wxExpr *idExpr = expr->Nth(0);
  1615.       switch (idExpr->IntegerValue())
  1616.       {
  1617.         case gyTYPE_PEN:
  1618.         {
  1619.           int penWidth = (int)expr->Nth(1)->IntegerValue();
  1620.           int penStyle = (int)expr->Nth(2)->IntegerValue();
  1621.           int penRed = (int)expr->Nth(3)->IntegerValue();
  1622.           int penGreen = (int)expr->Nth(4)->IntegerValue();
  1623.           int penBlue = (int)expr->Nth(5)->IntegerValue();
  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.         {
  1633.           int brushStyle = (int)expr->Nth(1)->IntegerValue();
  1634.           int brushRed = (int)expr->Nth(2)->IntegerValue();
  1635.           int brushGreen = (int)expr->Nth(3)->IntegerValue();
  1636.           int brushBlue = (int)expr->Nth(4)->IntegerValue();
  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.         {
  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();
  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
  1667.   keepGoing = TRUE;
  1668.   i = 1;
  1669.   while (keepGoing)
  1670.   {
  1671.     sprintf(buf, "op%d_%d", whichAngle, i);
  1672.     wxExpr *expr = NULL;
  1673.     clause->GetAttributeValue(buf, &expr);
  1674.     if (!expr)
  1675.     {
  1676.       keepGoing = FALSE;
  1677.     }
  1678.     else
  1679.     {
  1680.       wxExpr *idExpr = expr->Nth(0);
  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.         }
  1696.  
  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;
  1736.   outlineObjectsStr.Printf(wxT("outline_objects%d"), whichAngle);
  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;
  1751.   fillObjectsStr.Printf(wxT("fill_objects%d"), whichAngle);
  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
  1767. void 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
  1780.   wxNode *node = m_gdiObjects.First();
  1781.   while (node)
  1782.   {
  1783.     wxObject *obj = (wxObject *)node->Data();
  1784.     copy.m_gdiObjects.Append(obj);
  1785.     node = node->Next();
  1786.   }
  1787.  
  1788.   // Copy the operations
  1789.   node = m_ops.First();
  1790.   while (node)
  1791.   {
  1792.     wxDrawOp *op = (wxDrawOp *)node->Data();
  1793.     copy.m_ops.Append(op->Copy(©));
  1794.     node = node->Next();
  1795.   }
  1796.  
  1797.   // Copy the outline/fill operations
  1798.   node = m_outlineColours.First();
  1799.   while (node)
  1800.   {
  1801.     copy.m_outlineColours.Append((wxObject *)node->Data());
  1802.     node = node->Next();
  1803.   }
  1804.   node = m_fillColours.First();
  1805.   while (node)
  1806.   {
  1807.     copy.m_fillColours.Append((wxObject *)node->Data());
  1808.     node = node->Next();
  1809.   }
  1810. }
  1811.  
  1812. /*
  1813.  * Pass size of existing image; scale height to
  1814.  * fit width and return new width and height.
  1815.  *
  1816.  */
  1817.  
  1818. bool wxPseudoMetaFile::LoadFromMetaFile(char *filename, double *rwidth, double *rheight)
  1819. {
  1820.   if (!FileExists(filename))
  1821.     return NULL;
  1822.  
  1823.   wxXMetaFile *metaFile = new wxXMetaFile;
  1824.  
  1825.   if (!metaFile->ReadFile(filename))
  1826.   {
  1827.     delete metaFile;
  1828.     return FALSE;
  1829.   }
  1830.  
  1831.   double lastX = 0.0;
  1832.   double lastY = 0.0;
  1833.  
  1834.   // Convert from metafile records to wxDrawnShape records
  1835.   wxNode *node = metaFile->metaRecords.First();
  1836.   while (node)
  1837.   {
  1838.     wxMetaRecord *record = (wxMetaRecord *)node->Data();
  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.         }
  1980.  
  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.         }
  1994.  
  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.
  2010.         wxNode *recNode = metaFile->gdiObjects.Nth((int)record->param2);
  2011.         if (recNode)
  2012.         {
  2013.           wxMetaRecord *gdiRec = (wxMetaRecord *)recNode->Data();
  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.     }
  2128.     node = node->Next();
  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;
  2165.   return TRUE;
  2166. }
  2167.  
  2168. // Scale to fit size
  2169. void 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.  
  2178. void 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.  
  2185.   wxNode *node = m_ops.First();
  2186.   while (node)
  2187.   {
  2188.     wxDrawOp *op = (wxDrawOp *)node->Data();
  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:
  2195.       case DRAWOP_DRAW_POINT:
  2196.       case DRAWOP_DRAW_TEXT:
  2197.       {
  2198.         wxOpDraw *opDraw = (wxOpDraw *)op;
  2199.         if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
  2200.         if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
  2201.         if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
  2202.         if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
  2203.         if (op->GetOp() == DRAWOP_DRAW_LINE)
  2204.         {
  2205.           if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
  2206.           if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
  2207.           if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
  2208.           if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
  2209.         }
  2210.         else if (op->GetOp() == DRAWOP_DRAW_RECT ||
  2211.                  op->GetOp() == DRAWOP_DRAW_ROUNDED_RECT ||
  2212.                  op->GetOp() == DRAWOP_DRAW_ELLIPSE)
  2213.         {
  2214.           if ((opDraw->m_x1 + opDraw->m_x2) < minX) minX = (opDraw->m_x1 + opDraw->m_x2);
  2215.           if ((opDraw->m_x1 + opDraw->m_x2) > maxX) maxX = (opDraw->m_x1 + opDraw->m_x2);
  2216.           if ((opDraw->m_y1 + opDraw->m_y2) < minY) minY = (opDraw->m_y1 + opDraw->m_y2);
  2217.           if ((opDraw->m_y1 + opDraw->m_y2) > maxY) maxY = (opDraw->m_y1 + opDraw->m_y2);
  2218.         }
  2219.         break;
  2220.       }
  2221.       case DRAWOP_DRAW_ARC:
  2222.       {
  2223.         // TODO: don't yet know how to calculate the bounding box
  2224.         // for an arc. So pretend it's a line; to get a correct
  2225.         // bounding box, draw a blank rectangle first, of the correct
  2226.         // size.
  2227.         wxOpDraw *opDraw = (wxOpDraw *)op;
  2228.         if (opDraw->m_x1 < minX) minX = opDraw->m_x1;
  2229.         if (opDraw->m_x1 > maxX) maxX = opDraw->m_x1;
  2230.         if (opDraw->m_y1 < minY) minY = opDraw->m_y1;
  2231.         if (opDraw->m_y1 > maxY) maxY = opDraw->m_y1;
  2232.         if (opDraw->m_x2 < minX) minX = opDraw->m_x2;
  2233.         if (opDraw->m_x2 > maxX) maxX = opDraw->m_x2;
  2234.         if (opDraw->m_y2 < minY) minY = opDraw->m_y2;
  2235.         if (opDraw->m_y2 > maxY) maxY = opDraw->m_y2;
  2236.         break;
  2237.       }
  2238.       case DRAWOP_DRAW_POLYLINE:
  2239.       case DRAWOP_DRAW_POLYGON:
  2240.       case DRAWOP_DRAW_SPLINE:
  2241.       {
  2242.         wxOpPolyDraw *poly = (wxOpPolyDraw *)op;
  2243.         for (int i = 0; i < poly->m_noPoints; i++)
  2244.         {
  2245.           if (poly->m_points[i].x < minX) minX = poly->m_points[i].x;
  2246.           if (poly->m_points[i].x > maxX) maxX = poly->m_points[i].x;
  2247.           if (poly->m_points[i].y < minY) minY = poly->m_points[i].y;
  2248.           if (poly->m_points[i].y > maxY) maxY = poly->m_points[i].y;
  2249.         }
  2250.         break;
  2251.       }
  2252.       default:
  2253.         break;
  2254.     }
  2255.     node = node->Next();
  2256.   }
  2257.  
  2258.   *boundMinX = minX;
  2259.   *boundMinY = minY;
  2260.   *boundMaxX = maxX;
  2261.   *boundMaxY = maxY;
  2262. /*
  2263.   *w = (double)fabs(maxX - minX);
  2264.   *h = (double)fabs(maxY - minY);
  2265. */
  2266. }
  2267.  
  2268. // Calculate size from current operations
  2269. void wxPseudoMetaFile::CalculateSize(wxDrawnShape* shape)
  2270. {
  2271.   double boundMinX, boundMinY, boundMaxX, boundMaxY;
  2272.  
  2273.   GetBounds(& boundMinX, & boundMinY, & boundMaxX, & boundMaxY);
  2274.  
  2275.   SetSize(boundMaxX - boundMinX, boundMaxY - boundMinY);
  2276.  
  2277.   if (shape)
  2278.   {
  2279.     shape->SetWidth(m_width);
  2280.     shape->SetHeight(m_height);
  2281.   }
  2282. }
  2283.  
  2284. // Set of functions for drawing into a pseudo metafile.
  2285. // They use integers, but doubles are used internally for accuracy
  2286. // when scaling.
  2287.  
  2288. void wxPseudoMetaFile::DrawLine(const wxPoint& pt1, const wxPoint& pt2)
  2289. {
  2290.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_LINE,
  2291.           (double) pt1.x, (double) pt1.y, (double) pt2.x, (double) pt2.y);
  2292.  
  2293.     m_ops.Append(theOp);
  2294. }
  2295.  
  2296. void wxPseudoMetaFile::DrawRectangle(const wxRect& rect)
  2297. {
  2298.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_RECT,
  2299.           (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
  2300.  
  2301.     m_ops.Append(theOp);
  2302. }
  2303.  
  2304. void wxPseudoMetaFile::DrawRoundedRectangle(const wxRect& rect, double radius)
  2305. {
  2306.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ROUNDED_RECT,
  2307.           (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
  2308.  
  2309.     theOp->m_radius = radius;
  2310.  
  2311.     m_ops.Append(theOp);
  2312. }
  2313.  
  2314. void wxPseudoMetaFile::DrawEllipse(const wxRect& rect)
  2315. {
  2316.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPSE,
  2317.           (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
  2318.  
  2319.     m_ops.Append(theOp);
  2320. }
  2321.  
  2322. void wxPseudoMetaFile::DrawArc(const wxPoint& centrePt, const wxPoint& startPt, const wxPoint& endPt)
  2323. {
  2324.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ARC,
  2325.           (double) centrePt.x, (double) centrePt.y, (double) startPt.x, (double) startPt.y);
  2326.  
  2327.     theOp->m_x3 = (double) endPt.x;
  2328.     theOp->m_y3 = (double) endPt.y;
  2329.  
  2330.     m_ops.Append(theOp);
  2331. }
  2332.  
  2333. void wxPseudoMetaFile::DrawEllipticArc(const wxRect& rect, double startAngle, double endAngle)
  2334. {
  2335.     const double pi = 3.1415926535897932384626433832795 ;
  2336.  
  2337.     double startAngleRadians = startAngle* (pi*2.0/360.0);
  2338.     double endAngleRadians = endAngle* (pi*2.0/360.0);
  2339.  
  2340.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_ELLIPTIC_ARC,
  2341.           (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
  2342.  
  2343.     theOp->m_x3 = startAngleRadians;
  2344.     theOp->m_y3 = endAngleRadians;
  2345.  
  2346.     m_ops.Append(theOp);
  2347. }
  2348.  
  2349. void wxPseudoMetaFile::DrawPoint(const wxPoint& pt)
  2350. {
  2351.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_POINT,
  2352.           (double) pt.x, (double) pt.y, 0.0, 0.0);
  2353.  
  2354.     m_ops.Append(theOp);
  2355. }
  2356.  
  2357. void wxPseudoMetaFile::DrawText(const wxString& text, const wxPoint& pt)
  2358. {
  2359.     wxOpDraw *theOp = new wxOpDraw(DRAWOP_DRAW_TEXT,
  2360.           (double) pt.x, (double) pt.y, 0.0, 0.0);
  2361.  
  2362.     theOp->m_textString = copystring(text);
  2363.  
  2364.     m_ops.Append(theOp);
  2365. }
  2366.  
  2367. void wxPseudoMetaFile::DrawLines(int n, wxPoint pts[])
  2368. {
  2369.     wxRealPoint* realPoints = new wxRealPoint[n];
  2370.     int i;
  2371.     for (i = 0; i < n; i++)
  2372.     {
  2373.         realPoints[i].x = pts[i].x;
  2374.         realPoints[i].y = pts[i].y;
  2375.     }
  2376.     wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYLINE, n, realPoints);
  2377.     m_ops.Append(theOp);
  2378. }
  2379.  
  2380. void wxPseudoMetaFile::DrawPolygon(int n, wxPoint pts[], int flags)
  2381. {
  2382.     wxRealPoint* realPoints = new wxRealPoint[n];
  2383.     int i;
  2384.     for (i = 0; i < n; i++)
  2385.     {
  2386.         realPoints[i].x = pts[i].x;
  2387.         realPoints[i].y = pts[i].y;
  2388.     }
  2389.     wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_POLYGON, n, realPoints);
  2390.     m_ops.Append(theOp);
  2391.  
  2392.     if (flags & oglMETAFLAGS_OUTLINE)
  2393.         m_outlineOp = (m_ops.Number() - 1);
  2394. }
  2395.  
  2396. void wxPseudoMetaFile::DrawSpline(int n, wxPoint pts[])
  2397. {
  2398.     wxRealPoint* realPoints = new wxRealPoint[n];
  2399.     int i;
  2400.     for (i = 0; i < n; i++)
  2401.     {
  2402.         realPoints[i].x = pts[i].x;
  2403.         realPoints[i].y = pts[i].y;
  2404.     }
  2405.     wxOpPolyDraw* theOp = new wxOpPolyDraw(DRAWOP_DRAW_SPLINE, n, realPoints);
  2406.     m_ops.Append(theOp);
  2407. }
  2408.  
  2409. void wxPseudoMetaFile::SetClippingRect(const wxRect& rect)
  2410. {
  2411.     wxOpSetClipping* theOp = new wxOpSetClipping(DRAWOP_SET_CLIPPING_RECT,
  2412.         (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
  2413. }
  2414.  
  2415. void wxPseudoMetaFile::DestroyClippingRect()
  2416. {
  2417.     wxOpSetClipping* theOp = new wxOpSetClipping(DRAWOP_DESTROY_CLIPPING_RECT,
  2418.         0.0, 0.0, 0.0, 0.0);
  2419.  
  2420.     m_ops.Append(theOp);
  2421. }
  2422.  
  2423. void wxPseudoMetaFile::SetPen(wxPen* pen, bool isOutline)
  2424. {
  2425.     m_gdiObjects.Append(pen);
  2426.     int n = m_gdiObjects.Number();
  2427.  
  2428.     wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_PEN, this, n - 1);
  2429.  
  2430.     m_ops.Append(theOp);
  2431.  
  2432.     if (isOutline)
  2433.     {
  2434.         m_outlineColours.Append((wxObject*) (n - 1));
  2435.     }
  2436. }
  2437.  
  2438. void wxPseudoMetaFile::SetBrush(wxBrush* brush, bool isFill)
  2439. {
  2440.     m_gdiObjects.Append(brush);
  2441.     int n = m_gdiObjects.Number();
  2442.  
  2443.     wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BRUSH, this, n - 1);
  2444.  
  2445.     m_ops.Append(theOp);
  2446.  
  2447.     if (isFill)
  2448.     {
  2449.         m_fillColours.Append((wxObject*) (n - 1));
  2450.     }
  2451. }
  2452.  
  2453. void wxPseudoMetaFile::SetFont(wxFont* font)
  2454. {
  2455.     m_gdiObjects.Append(font);
  2456.     int n = m_gdiObjects.Number();
  2457.  
  2458.     wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_FONT, this, n - 1);
  2459.  
  2460.     m_ops.Append(theOp);
  2461. }
  2462.  
  2463. void wxPseudoMetaFile::SetTextColour(const wxColour& colour)
  2464. {
  2465.    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_TEXT_COLOUR, this, 0);
  2466.    theOp->m_r = colour.Red();
  2467.    theOp->m_g = colour.Green();
  2468.    theOp->m_b = colour.Blue();
  2469.  
  2470.    m_ops.Append(theOp);
  2471. }
  2472.  
  2473. void wxPseudoMetaFile::SetBackgroundColour(const wxColour& colour)
  2474. {
  2475.    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_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::SetBackgroundMode(int mode)
  2484. {
  2485.    wxOpSetGDI* theOp = new wxOpSetGDI(DRAWOP_SET_BK_MODE, this, 0, mode);
  2486.  
  2487.    m_ops.Append(theOp);
  2488. }
  2489.  
  2490.