home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / dc.cpp < prev    next >
C/C++ Source or Header  |  2002-08-25  |  97KB  |  2,905 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        dc.cpp
  3. // Purpose:     wxDC class
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/14/99
  7. // RCS-ID:      $Id: DC.CPP,v 1.56 2002/08/25 17:58:43 SN Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #ifndef WX_PRECOMP
  16.     #include "wx/window.h"
  17.     #include "wx/dc.h"
  18.     #include "wx/utils.h"
  19.     #include "wx/dialog.h"
  20.     #include "wx/app.h"
  21.     #include "wx/bitmap.h"
  22.     #include "wx/dcmemory.h"
  23.     #include "wx/log.h"
  24.     #include "wx/icon.h"
  25.     #include "wx/msgdlg.h"
  26.     #include "wx/module.h"
  27. #if wxUSE_STATUSBAR
  28.     #include "wx/statusbr.h"
  29. #endif
  30. #endif
  31.  
  32. #include "wx/dcprint.h"
  33.  
  34. #include <string.h>
  35. #include <math.h>
  36.  
  37. #include "wx/os2/private.h"
  38.  
  39.     IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
  40.  
  41. //
  42. // wxWindows uses the Microsoft convention that the origin is the UPPER left.
  43. // Native OS/2 however in the GPI and PM define the origin as the LOWER left.
  44. // In order to map OS/2 GPI/PM y coordinates to wxWindows coordinates we must
  45. // perform the following transformation:
  46. //
  47. // Parent object height:     POBJHEIGHT
  48. // Desried origin:           WXORIGINY
  49. // Object to place's height: OBJHEIGHT
  50. //
  51. // To get the OS2 position from the wxWindows one:
  52. //
  53. // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT)
  54. //
  55. // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the
  56. // OS/2 Presentation Space associated with the device context.  y is the
  57. // desired application's y coordinate of the origin in wxWindows space.
  58. // objy is the height of the object we are going to draw.
  59. //
  60. #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy))
  61.  
  62. // ---------------------------------------------------------------------------
  63. // constants
  64. // ---------------------------------------------------------------------------
  65.  
  66. static const int VIEWPORT_EXTENT = 1000;
  67.  
  68. static const int MM_POINTS = 9;
  69. static const int MM_METRIC = 10;
  70.  
  71. // usually this is defined in math.h
  72. #ifndef M_PI
  73.     static const double M_PI = 3.14159265358979323846;
  74. #endif // M_PI
  75.  
  76. // ---------------------------------------------------------------------------
  77. // private functions
  78. // ---------------------------------------------------------------------------
  79.  
  80. // convert degrees to radians
  81. static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
  82.  
  83. int SetTextColor(
  84.   HPS                               hPS
  85. , int                               nForegroundColour
  86. )
  87. {
  88.     CHARBUNDLE                      vCbnd;
  89.  
  90.     vCbnd.lColor =  nForegroundColour;
  91.     ::GpiSetAttrs( hPS       // presentation-space handle
  92.                   ,PRIM_CHAR // Char primitive.
  93.                   ,CBB_COLOR // sets color.
  94.                   ,0         //
  95.                   ,&vCbnd    // buffer for attributes.
  96.                  );
  97.     return 0;
  98. }
  99.  
  100. int QueryTextBkColor(
  101.   HPS                               hPS
  102. )
  103. {
  104.     CHARBUNDLE                      vCbnd;
  105.  
  106.     ::GpiQueryAttrs( hPS            // presentation-space handle
  107.                     ,PRIM_CHAR      // Char primitive.
  108.                     ,CBB_BACK_COLOR // Background color.
  109.                     ,&vCbnd         // buffer for attributes.
  110.                    );
  111.     return vCbnd.lBackColor;
  112. }
  113.  
  114.  
  115. int SetTextBkColor(
  116.   HPS                               hPS
  117. , int                               nBackgroundColour
  118. )
  119. {
  120.     CHARBUNDLE                      vCbnd;
  121.     int                             rc;
  122.  
  123.     rc =  QueryTextBkColor(hPS);
  124.  
  125.     vCbnd.lBackColor = nBackgroundColour;
  126.     ::GpiSetAttrs(hPS,            // presentation-space handle
  127.                   PRIM_CHAR,      // Char primitive.
  128.                   CBB_BACK_COLOR, // sets color.
  129.                   0,
  130.                   &vCbnd          // buffer for attributes.
  131.                  );
  132.     return rc;
  133. }
  134.  
  135. int SetBkMode(
  136.   HPS                               hPS
  137. , int                               nBackgroundMode
  138. )
  139. {
  140.     if(nBackgroundMode == wxTRANSPARENT)
  141.         ::GpiSetBackMix( hPS
  142.                         ,BM_LEAVEALONE
  143.                        );
  144.     else
  145.         // the background of the primitive takes  over whatever is underneath.
  146.         ::GpiSetBackMix( hPS
  147.                         ,BM_OVERPAINT
  148.                         );
  149.     return 0;
  150. }
  151.  
  152. // ===========================================================================
  153. // implementation
  154. // ===========================================================================
  155.  
  156. #if wxUSE_DC_CACHEING
  157.  
  158. /*
  159.  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will
  160.  * improve it in due course, either using arrays, or simply storing pointers to one
  161.  * entry for the bitmap, and two for the DCs. -- JACS
  162.  */
  163.  
  164. // ---------------------------------------------------------------------------
  165. // wxDCCacheEntry
  166. // ---------------------------------------------------------------------------
  167.  
  168. wxList wxDC::m_svBitmapCache;
  169. wxList wxDC::m_svDCCache;
  170.  
  171. wxDCCacheEntry::wxDCCacheEntry(
  172.   WXHBITMAP                         hBitmap
  173. , int                               nWidth
  174. , int                               nHeight
  175. , int                               nDepth
  176. )
  177. {
  178.     m_hBitmap = hBitmap;
  179.     m_hPS     = NULLHANDLE;
  180.     m_nWidth  = nWidth;
  181.     m_nHeight = nHeight;
  182.     m_nDepth  = nDepth;
  183. } // end of wxDCCacheEntry::wxDCCacheEntry
  184.  
  185. wxDCCacheEntry::wxDCCacheEntry(
  186.   HPS                               hPS
  187. , int                               nDepth
  188. )
  189. {
  190.     m_hBitmap = NULLHANDLE;
  191.     m_hPS     = hPS;
  192.     m_nWidth  = 0;
  193.     m_nHeight = 0;
  194.     m_nDepth  = nDepth;
  195. } // end of wxDCCacheEntry::wxDCCacheEntry
  196.  
  197. wxDCCacheEntry::~wxDCCacheEntry()
  198. {
  199.     if (m_hBitmap)
  200.         ::GpiDeleteBitmap(m_hBitmap);
  201.     if (m_hPS)
  202.         ::GpiDestroyPS(m_hPS);
  203. } // end of wxDCCacheEntry::~wxDCCacheEntry
  204.  
  205. wxDCCacheEntry* wxDC::FindBitmapInCache(
  206.   HPS                               hPS
  207. , int                               nWidth
  208. , int                               nHeight
  209. )
  210. {
  211.     int                             nDepth = 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
  212.     wxNode*                         pNode = m_svBitmapCache.First();
  213.     BITMAPINFOHEADER2               vBmpHdr;
  214.  
  215.     while(pNode)
  216.     {
  217.         wxDCCacheEntry*             pEntry = (wxDCCacheEntry*)pNode->Data();
  218.  
  219.         if (pEntry->m_nDepth == nDepth)
  220.         {
  221.             memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
  222.  
  223.             if (pEntry->m_nWidth < nWidth || pEntry->m_nHeight < nHeight)
  224.             {
  225.                 ::GpiDeleteBitmap((HBITMAP)pEntry->m_hBitmap);
  226.                 vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
  227.                 vBmpHdr.cx        = nWidth;
  228.                 vBmpHdr.cy        = nHeight;
  229.                 vBmpHdr.cPlanes   = 1;
  230.                 vBmpHdr.cBitCount = nDepth;
  231.  
  232.                 pEntry->m_hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS
  233.                                                                   ,&vBmpHdr
  234.                                                                   ,0L, NULL, NULL
  235.                                                                  );
  236.                 if (!pEntry->m_hBitmap)
  237.                 {
  238.                     wxLogLastError(wxT("CreateCompatibleBitmap"));
  239.                 }
  240.                 pEntry->m_nWidth  = nWidth;
  241.                 pEntry->m_nHeight = nHeight;
  242.                 return pEntry;
  243.             }
  244.             return pEntry;
  245.         }
  246.         pNode = pNode->Next();
  247.     }
  248.     memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
  249.     vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
  250.     vBmpHdr.cx        = nWidth;
  251.     vBmpHdr.cy        = nHeight;
  252.     vBmpHdr.cPlanes   = 1;
  253.     vBmpHdr.cBitCount = nDepth;
  254.  
  255.     WXHBITMAP                       hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS
  256.                                                                             ,&vBmpHdr
  257.                                                                             ,0L, NULL, NULL
  258.                                                                            );
  259.     if (!hBitmap)
  260.     {
  261.         wxLogLastError(wxT("CreateCompatibleBitmap"));
  262.     }
  263.     wxDCCacheEntry*                 pEntry = new wxDCCacheEntry( hBitmap
  264.                                                                 ,nWidth
  265.                                                                 ,nHeight
  266.                                                                 ,nDepth
  267.                                                                );
  268.     AddToBitmapCache(pEntry);
  269.     return pEntry;
  270. } // end of FindBitmapInCache
  271.  
  272. wxDCCacheEntry* wxDC::FindDCInCache(
  273.   wxDCCacheEntry*                   pNotThis
  274. , HPS                               hPS
  275. )
  276. {
  277.     int                             nDepth = 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
  278.     wxNode*                         pNode = m_svDCCache.First();
  279.  
  280.     while(pNode)
  281.     {
  282.         wxDCCacheEntry*             pEntry = (wxDCCacheEntry*)pNode->Data();
  283.  
  284.         //
  285.         // Don't return the same one as we already have
  286.         //
  287.         if (!pNotThis || (pNotThis != pEntry))
  288.         {
  289.             if (pEntry->m_nDepth == nDepth)
  290.             {
  291.                 return pEntry;
  292.             }
  293.         }
  294.         pNode = pNode->Next();
  295.     }
  296.     wxDCCacheEntry*                 pEntry = new wxDCCacheEntry( hPS
  297.                                                                 ,nDepth
  298.                                                                );
  299.     AddToDCCache(pEntry);
  300.     return pEntry;
  301. } // end of wxDC::FindDCInCache
  302.  
  303. void wxDC::AddToBitmapCache(
  304.   wxDCCacheEntry*                   pEntry
  305. )
  306. {
  307.     m_svBitmapCache.Append(pEntry);
  308. } // end of wxDC::AddToBitmapCache
  309.  
  310. void wxDC::AddToDCCache(
  311.   wxDCCacheEntry*                   pEntry
  312. )
  313. {
  314.     m_svDCCache.Append(pEntry);
  315. } // end of wxDC::AddToDCCache
  316.  
  317. void wxDC::ClearCache()
  318. {
  319.     m_svBitmapCache.DeleteContents(TRUE);
  320.     m_svBitmapCache.Clear();
  321.     m_svBitmapCache.DeleteContents(FALSE);
  322.     m_svDCCache.DeleteContents(TRUE);
  323.     m_svDCCache.Clear();
  324.     m_svDCCache.DeleteContents(FALSE);
  325. } // end of wxDC::ClearCache
  326.  
  327. // Clean up cache at app exit
  328. class wxDCModule : public wxModule
  329. {
  330. public:
  331.     virtual bool OnInit() { return TRUE; }
  332.     virtual void OnExit() { wxDC::ClearCache(); }
  333.  
  334. private:
  335.     DECLARE_DYNAMIC_CLASS(wxDCModule)
  336. }; // end of CLASS wxDCModule
  337.  
  338. IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
  339.  
  340. #endif // ndef for wxUSE_DC_CACHEING
  341.  
  342. // ---------------------------------------------------------------------------
  343. // wxDC
  344. // ---------------------------------------------------------------------------
  345.  
  346. wxDC::wxDC(void)
  347. {
  348.     wxColour                        vColor;
  349.  
  350.     m_pCanvas      = NULL;
  351.  
  352.     m_hOldBitmap   = 0;
  353.     m_hOldPen      = 0;
  354.     m_hOldBrush    = 0;
  355.     m_hOldFont     = 0;
  356.     m_hOldPalette  = 0;
  357.  
  358.     m_bOwnsDC      = FALSE;
  359.     m_hDC          = 0;
  360.     m_hOldPS       = NULL;
  361.     m_hPS          = NULL;
  362.     m_bIsPaintTime = FALSE; // True at Paint Time
  363.  
  364.     vColor.InitFromName("BLACK");
  365.     m_pen.SetColour(vColor);
  366.     vColor.Set("WHITE");
  367.     m_brush.SetColour(vColor);
  368. } // end of wxDC::wxDC
  369.  
  370. wxDC::~wxDC(void)
  371. {
  372.     if ( m_hDC != 0 )
  373.     {
  374.         SelectOldObjects(m_hDC);
  375.  
  376.         // if we own the HDC, we delete it, otherwise we just release it
  377.  
  378.         if (m_bOwnsDC)
  379.         {
  380.             if(m_hPS)
  381.             {
  382.                 ::GpiAssociate(m_hPS, NULLHANDLE);
  383.                 ::GpiDestroyPS(m_hPS);
  384.             }
  385.             m_hPS = NULLHANDLE;
  386.             ::DevCloseDC((HDC)m_hDC);
  387.         }
  388.         else
  389.         {
  390.             //
  391.             // Just Dissacociate, not destroy if we don't own the DC
  392.             //
  393.             if(m_hPS)
  394.             {
  395.                 ::GpiAssociate(m_hPS, NULLHANDLE);
  396.             }
  397.         }
  398.     }
  399. } // end of wxDC::~wxDC
  400.  
  401. // This will select current objects out of the DC,
  402. // which is what you have to do before deleting the
  403. // DC.
  404. void wxDC::SelectOldObjects(
  405.   WXHDC                             hPS
  406. )
  407. {
  408.     if (hPS)
  409.     {
  410.         if (m_hOldBitmap)
  411.         {
  412.             ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap);
  413.             if (m_vSelectedBitmap.Ok())
  414.             {
  415.                 m_vSelectedBitmap.SetSelectedInto(NULL);
  416.             }
  417.         }
  418.         m_hOldBitmap = 0;
  419.         //
  420.         // OS/2 has no other native GDI objects to set in a PS/DC like windows
  421.         //
  422.         m_hOldPen = 0;
  423.         m_hOldBrush = 0;
  424.         m_hOldFont = 0;
  425.         m_hOldPalette = 0;
  426.     }
  427.  
  428.     m_brush           = wxNullBrush;
  429.     m_pen             = wxNullPen;
  430.     m_palette         = wxNullPalette;
  431.     m_font            = wxNullFont;
  432.     m_backgroundBrush = wxNullBrush;
  433.     m_vSelectedBitmap = wxNullBitmap;
  434. } // end of wxDC::SelectOldObjects
  435.  
  436. // ---------------------------------------------------------------------------
  437. // clipping
  438. // ---------------------------------------------------------------------------
  439.  
  440. #define DO_SET_CLIPPING_BOX()                    \
  441. {                                                \
  442.     RECTL rect;                                  \
  443.                                                  \
  444.     ::GpiQueryClipBox(m_hPS, &rect);             \
  445.                                                  \
  446.     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \
  447.     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \
  448.     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \
  449.     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \
  450. }
  451.  
  452. void wxDC::DoSetClippingRegion(
  453.   wxCoord                           vX
  454. , wxCoord                           vY
  455. , wxCoord                           vWidth
  456. , wxCoord                           vHeight
  457. )
  458. {
  459.     RECTL                           vRect;
  460.  
  461.     vY = OS2Y(vY,vHeight);
  462.     m_clipping    = TRUE;
  463.     vRect.xLeft   = vX;
  464.     vRect.yTop    = vY + vHeight;
  465.     vRect.xRight  = vX + vWidth;
  466.     vRect.yBottom = vY;
  467.     ::GpiIntersectClipRectangle(m_hPS, &vRect);
  468.     DO_SET_CLIPPING_BOX()
  469. } // end of wxDC::DoSetClippingRegion
  470.  
  471. void wxDC::DoSetClippingRegionAsRegion(
  472.   const wxRegion&                   rRegion
  473. )
  474. {
  475.      wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region"));
  476.      HRGN                           hRgnOld;
  477.  
  478.      m_clipping = TRUE;
  479.      ::GpiSetClipRegion( m_hPS
  480.                         ,(HRGN)rRegion.GetHRGN()
  481.                         ,&hRgnOld
  482.                        );
  483.     DO_SET_CLIPPING_BOX()
  484. } // end of wxDC::DoSetClippingRegionAsRegion
  485.  
  486. void wxDC::DestroyClippingRegion(void)
  487. {
  488.     if (m_clipping && m_hPS)
  489.     {
  490.          HRGN                       hRgnOld;
  491.          RECTL                      vRect;
  492.  
  493.          // TODO: this should restore the previous clipped region
  494.          //       so that OnPaint processing works correctly, and
  495.          //       the update doesn't get destroyed after the first
  496.          //       DestroyClippingRegion
  497.          vRect.xLeft   = XLOG2DEV(0);
  498.          vRect.yTop    = YLOG2DEV(32000);
  499.          vRect.xRight  = XLOG2DEV(32000);
  500.          vRect.yBottom = YLOG2DEV(0);
  501.  
  502.          HRGN                       hRgn = ::GpiCreateRegion(m_hPS, 1, &vRect);
  503.  
  504.          ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld);
  505.      }
  506.       m_clipping = FALSE;
  507. } // end of wxDC::DestroyClippingRegion
  508.  
  509. // ---------------------------------------------------------------------------
  510. // query capabilities
  511. // ---------------------------------------------------------------------------
  512.  
  513. bool wxDC::CanDrawBitmap() const
  514. {
  515.     return TRUE;
  516. }
  517.  
  518. bool wxDC::CanGetTextExtent() const
  519. {
  520.     LONG                            lTechnology = 0L;
  521.  
  522.     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology);
  523.     return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER);
  524. } // end of wxDC::CanGetTextExtent
  525.  
  526. int wxDC::GetDepth() const
  527. {
  528.     LONG                            lArray[CAPS_COLOR_BITCOUNT];
  529.     int                             nBitsPerPixel;
  530.  
  531.     if(::DevQueryCaps( GetHDC()
  532.                       ,CAPS_FAMILY
  533.                       ,CAPS_COLOR_BITCOUNT
  534.                       ,lArray
  535.                      ))
  536.     {
  537.         nBitsPerPixel = (int)lArray[CAPS_COLOR_BITCOUNT];
  538.     }
  539.     return nBitsPerPixel;
  540. } // end of wxDC::GetDepth
  541.  
  542. // ---------------------------------------------------------------------------
  543. // drawing
  544. // ---------------------------------------------------------------------------
  545.  
  546. void wxDC::Clear()
  547. {
  548.     //
  549.     // If this is a canvas DC then just fill with the background color
  550.     // Otherwise purge the whole thing
  551.     //
  552.     if (m_pCanvas)
  553.     {
  554.         RECTL                       vRect;
  555.  
  556.         ::GpiQueryClipBox(m_hPS, &vRect);
  557.         ::WinFillRect(m_hPS, &vRect, ::GpiQueryBackColor(m_hPS));
  558.     }
  559.     else
  560.     ::GpiErase(m_hPS);
  561. } // end of wxDC::Clear
  562.  
  563. bool wxDC::DoFloodFill(
  564.   wxCoord                           vX
  565. , wxCoord                           vY
  566. , const wxColour&                   rCol
  567. , int                               nStyle
  568. )
  569. {
  570.     POINTL                          vPtlPos;
  571.     LONG                            lColor;
  572.     LONG                            lOptions;
  573.     LONG                            lHits;
  574.     bool                            bSuccess = FALSE;
  575.  
  576.     vPtlPos.x = vX;             // Loads x-coordinate
  577.     vPtlPos.y = OS2Y(vY,0);     // Loads y-coordinate
  578.     ::GpiMove(m_hPS, &vPtlPos); // Sets current position
  579.     lColor = rCol.GetPixel();
  580.     lOptions = FF_BOUNDARY;
  581.     if(wxFLOOD_SURFACE == nStyle)
  582.         lOptions = FF_SURFACE;
  583.  
  584.     if ((lHits = ::GpiFloodFill(m_hPS, lOptions, lColor)) != GPI_ERROR)
  585.         bSuccess = TRUE;
  586.     return TRUE;
  587. } // end of wxDC::DoFloodFill
  588.  
  589. bool wxDC::DoGetPixel(
  590.   wxCoord                           vX
  591. , wxCoord                           vY
  592. , wxColour*                         pCol
  593. ) const
  594. {
  595.     POINTL                          vPoint;
  596.     LONG                            lColor;
  597.  
  598.     vPoint.x = vX;
  599.     vPoint.y = OS2Y(vY,0);
  600.     lColor = ::GpiSetPel(m_hPS, &vPoint);
  601.  
  602.     //
  603.     // Get the color of the pen
  604.     //
  605.     LONG                            lPencolor = 0x00ffffff;
  606.  
  607.     if (m_pen.Ok())
  608.     {
  609.         lPencolor = m_pen.GetColour().GetPixel();
  610.     }
  611.  
  612.     //
  613.     // return the color of the pixel
  614.     //
  615.     if(pCol)
  616.         pCol->Set( GetRValue(lColor)
  617.                   ,GetGValue(lColor)
  618.                   ,GetBValue(lColor)
  619.                  );
  620.     return(lColor == lPencolor);
  621. } // end of wxDC::DoGetPixel
  622.  
  623. void wxDC::DoCrossHair(
  624.   wxCoord                           vX
  625. , wxCoord                           vY
  626. )
  627. {
  628.     vY = OS2Y(vY,0);
  629.  
  630.     wxCoord                         vX1 = vX - VIEWPORT_EXTENT;
  631.     wxCoord                         vY1 = vY - VIEWPORT_EXTENT;
  632.     wxCoord                         vX2 = vX + VIEWPORT_EXTENT;
  633.     wxCoord                         vY2 = vY + VIEWPORT_EXTENT;
  634.     POINTL                          vPoint[4];
  635.  
  636.     vPoint[0].x = vX1;
  637.     vPoint[0].y = vY;
  638.  
  639.     vPoint[1].x = vX2;
  640.     vPoint[1].y = vY;
  641.  
  642.     ::GpiMove(m_hPS, &vPoint[0]);
  643.     ::GpiLine(m_hPS, &vPoint[1]);
  644.  
  645.     vPoint[2].x = vX;
  646.     vPoint[2].y = vY1;
  647.  
  648.     vPoint[3].x = vX;
  649.     vPoint[3].y = vY2;
  650.  
  651.     ::GpiMove(m_hPS, &vPoint[2]);
  652.     ::GpiLine(m_hPS, &vPoint[3]);
  653.     CalcBoundingBox(vX1, vY1);
  654.     CalcBoundingBox(vX2, vY2);
  655. } // end of wxDC::DoCrossHair
  656.  
  657. void wxDC::DoDrawLine(
  658.   wxCoord                           vX1
  659. , wxCoord                           vY1
  660. , wxCoord                           vX2
  661. , wxCoord                           vY2
  662. )
  663. {
  664.     POINTL                          vPoint[2];
  665.     COLORREF                        vColor = 0x00ffffff;
  666.  
  667.     //
  668.     // Might be a memory DC with no Paint rect.
  669.     //
  670.     if (!(m_vRclPaint.yTop == 0 &&
  671.           m_vRclPaint.yBottom == 0 &&
  672.           m_vRclPaint.xRight == 0 &&
  673.           m_vRclPaint.xLeft == 0))
  674.     {
  675.         vY1 = OS2Y(vY1,0);
  676.         vY2 = OS2Y(vY2,0);
  677.     }
  678.     else
  679.     {
  680.         if (m_vSelectedBitmap != wxNullBitmap)
  681.         {
  682.             m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
  683.             m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
  684.             vY1 = OS2Y(vY1,0);
  685.             vY2 = OS2Y(vY2,0);
  686.         }
  687.     }
  688.     vPoint[0].x = vX1;
  689.     vPoint[0].y = vY1;
  690.     vPoint[1].x = vX2;
  691.     vPoint[1].y = vY2;
  692.     if (m_pen.Ok())
  693.     {
  694.         vColor = m_pen.GetColour().GetPixel();
  695.     }
  696.     ::GpiSetColor(m_hPS, vColor);
  697.     ::GpiMove(m_hPS, &vPoint[0]);
  698.     ::GpiLine(m_hPS, &vPoint[1]);
  699.     CalcBoundingBox(vX1, vY1);
  700.     CalcBoundingBox(vX2, vY2);
  701. } // end of wxDC::DoDrawLine
  702.  
  703. //////////////////////////////////////////////////////////////////////////////
  704. // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
  705. // and ending at (x2, y2). The current pen is used for the outline and the
  706. // current brush for filling the shape. The arc is drawn in an anticlockwise
  707. // direction from the start point to the end point.
  708. //////////////////////////////////////////////////////////////////////////////
  709. void wxDC::DoDrawArc(
  710.   wxCoord                           vX1
  711. , wxCoord                           vY1
  712. , wxCoord                           vX2
  713. , wxCoord                           vY2
  714. , wxCoord                           vXc
  715. , wxCoord                           vYc
  716. )
  717. {
  718.      POINTL                         vPtlPos;
  719.      POINTL                         vPtlArc[2]; // Structure for current position
  720.      int                            nDx;
  721.      int                            nDy;
  722.      double                         dRadius;
  723.      double                         dAngl1;
  724.      double                         dAngl2;
  725.      double                         dAnglmid;
  726.      wxCoord                        vXm;
  727.      wxCoord                        vYm;
  728.      ARCPARAMS                      vArcp; // Structure for arc parameters
  729.  
  730.     if((vX1 == vXc && vY1 == vXc) || (vX2 == vXc && vY2 == vXc))
  731.         return; // Draw point ??
  732.     dRadius = 0.5 * ( hypot( (double)(vY1 - vYc)
  733.                             ,(double)(vX1 - vXc)
  734.                            ) +
  735.                       hypot( (double)(vY2 - vYc)
  736.                             ,(double)(vX2 - vXc)
  737.                            )
  738.                      );
  739.  
  740.     dAngl1 = atan2( (double)(vY1 - vYc)
  741.                    ,(double)(vX1 - vXc)
  742.                   );
  743.     dAngl2 = atan2( (double)(vY2 - vYc)
  744.                    ,(double)(vX2 - vXc)
  745.                   );
  746.     if(dAngl2 < dAngl1)
  747.         dAngl2 += M_PI * 2;
  748.  
  749.     //
  750.     // GpiPointArc can't draw full arc
  751.     //
  752.      if(dAngl2 == dAngl1 || (vX1 == vX2 && vY1 == vY2) )
  753.      {
  754.         //
  755.         // Medium point
  756.         //
  757.         dAnglmid = (dAngl1 + dAngl2)/2. + M_PI;
  758.         vXm      = vXc + dRadius * cos(dAnglmid);
  759.         vYm      = vYc + dRadius * sin(dAnglmid);
  760.         DoDrawArc( vX1, vY1
  761.                   ,vXm, vYm
  762.                   ,vXc, vYc
  763.                  );
  764.         DoDrawArc( vXm, vYm
  765.                   ,vX2, vY2
  766.                   ,vXc, vYc
  767.                  );
  768.         return;
  769.     }
  770.  
  771.     //
  772.     // Medium point
  773.     //
  774.     dAnglmid = (dAngl1 + dAngl2)/2.;
  775.     vXm      = vXc + dRadius * cos(dAnglmid);
  776.     vYm      = vYc + dRadius * sin(dAnglmid);
  777.  
  778.     //
  779.     // Ellipse main axis (r,q), (p,s) with center at (0,0) */
  780.     //
  781.     vArcp.lR = 0;
  782.     vArcp.lQ = 1;
  783.     vArcp.lP = 1;
  784.     vArcp.lS = 0;
  785.     ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
  786.  
  787.     vPtlPos.x = vX1; // Loads x-coordinate
  788.     vPtlPos.y = vY1; // Loads y-coordinate
  789.     ::GpiMove(m_hPS, &vPtlPos); // Sets current position
  790.     vPtlArc[0].x = vXm;
  791.     vPtlArc[0].y = vYm;
  792.     vPtlArc[1].x = vX2;
  793.     vPtlArc[1].y = vY2;
  794.     ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc
  795.     CalcBoundingBox( (vXc - dRadius)
  796.                     ,(vYc - dRadius)
  797.                    );
  798.     CalcBoundingBox( (vXc + dRadius)
  799.                     ,(vYc + dRadius)
  800.                    );
  801. } // end of wxDC::DoDrawArc
  802.  
  803. void wxDC::DoDrawCheckMark(
  804.   wxCoord                           vX1
  805. , wxCoord                           vY1
  806. , wxCoord                           vWidth
  807. , wxCoord                           vHeight
  808. )
  809. {
  810.     POINTL                          vPoint[2];
  811.  
  812.     vY1 = OS2Y(vY1,vHeight);
  813.  
  814.     vPoint[0].x = vX1;
  815.     vPoint[0].y = vY1;
  816.     vPoint[1].x = vX1 + vWidth;
  817.     vPoint[1].y = vY1 + vHeight;
  818.  
  819.     ::GpiMove(m_hPS, &vPoint[0]);
  820.     ::GpiBox( m_hPS       // handle to a presentation space
  821.              ,DRO_OUTLINE // draw the box outline ? or ?
  822.              ,&vPoint[1]  // address of the corner
  823.              ,0L          // horizontal corner radius
  824.              ,0L          // vertical corner radius
  825.             );
  826.     if(vWidth > 4 && vHeight > 4)
  827.     {
  828.         int                         nTmp;
  829.  
  830.         vPoint[0].x += 2; vPoint[0].y += 2;
  831.         vPoint[1].x -= 2; vPoint[1].y -= 2;
  832.         ::GpiMove(m_hPS, &vPoint[0]);
  833.         ::GpiLine(m_hPS, &vPoint[1]);
  834.         nTmp = vPoint[0].x;
  835.         vPoint[0].x = vPoint[1].x;
  836.         vPoint[1].x = nTmp;
  837.         ::GpiMove(m_hPS, &vPoint[0]);
  838.         ::GpiLine(m_hPS, &vPoint[1]);
  839.     }
  840.     CalcBoundingBox( vX1
  841.                     ,vY1
  842.                    );
  843.  
  844.     wxCoord                         vX2 = vX1 + vWidth;
  845.     wxCoord                         vY2 = vY1 + vHeight;
  846.  
  847.     CalcBoundingBox( vX2
  848.                     ,vY2
  849.                    );
  850. } // end of wxDC::DoDrawCheckMark
  851.  
  852. void wxDC::DoDrawPoint(
  853.   wxCoord                           vX
  854. , wxCoord                           vY
  855. )
  856. {
  857.     POINTL                          vPoint;
  858.     COLORREF                        vColor = 0x00ffffff;
  859.  
  860.     if (m_pen.Ok())
  861.     {
  862.         vColor = m_pen.GetColour().GetPixel();
  863.     }
  864.     ::GpiSetColor(m_hPS, vColor);
  865.     vPoint.x = vX;
  866.     vPoint.y = OS2Y(vY,0);
  867.     ::GpiSetPel(m_hPS, &vPoint);
  868.     CalcBoundingBox( vX
  869.                     ,vY
  870.                    );
  871. } // end of wxDC::DoDrawPoint
  872.  
  873. void wxDC::DoDrawPolygon(
  874.   int                               n
  875. , wxPoint                           vPoints[]
  876. , wxCoord                           vXoffset
  877. , wxCoord                           vYoffset
  878. , int                               nFillStyle
  879. )
  880. {
  881.     ULONG                           ulCount = 1;    // Number of polygons.
  882.     POLYGON                         vPlgn;          // polygon.
  883.     ULONG                           flOptions = 0L; // Drawing options.
  884.  
  885. //////////////////////////////////////////////////////////////////////////////
  886. // This contains fields of option bits... to draw boundary lines as well as
  887. // the area interior.
  888. //
  889. // Drawing boundary lines:
  890. //   POLYGON_NOBOUNDARY              Does not draw boundary lines.
  891. //   POLYGON_BOUNDARY                Draws boundary lines (the default).
  892. //
  893. // Construction of the area interior:
  894. //   POLYGON_ALTERNATE               Constructs interior in alternate mode
  895. //                                   (the default).
  896. //   POLYGON_WINDING                 Constructs interior in winding mode.
  897. //////////////////////////////////////////////////////////////////////////////
  898.  
  899.     ULONG                           flModel = 0L; // Drawing model.
  900.  
  901. //////////////////////////////////////////////////////////////////////////////
  902. // Drawing model.
  903. //   POLYGON_INCL  Fill is inclusive of bottom right (the default).
  904. //   POLYGON_EXCL  Fill is exclusive of bottom right.
  905. //       This is provided to aid migration from other graphics models.
  906. //////////////////////////////////////////////////////////////////////////////
  907.  
  908.     LONG                            lHits = 0L; // Correlation/error indicator.
  909.     POINTL                          vPoint;
  910.     int                             i;
  911.     int                             nIsTRANSPARENT = 0;
  912.     LONG                            lBorderColor = 0L;
  913.     LONG                            lColor = 0L;
  914.  
  915.     lBorderColor = m_pen.GetColour().GetPixel();
  916.     lColor       = m_brush.GetColour().GetPixel();
  917.     if(m_brush.GetStyle() == wxTRANSPARENT)
  918.         nIsTRANSPARENT = 1;
  919.  
  920.     vPlgn.ulPoints = n;
  921.     vPlgn.aPointl = (POINTL*) calloc( n + 1
  922.                                      ,sizeof(POINTL)
  923.                                     ); // well, new will call malloc
  924.  
  925.     for(i = 0; i < n; i++)
  926.     {
  927.         vPlgn.aPointl[i].x = vPoints[i].x;         // +xoffset;
  928.         vPlgn.aPointl[i].y = OS2Y(vPoints[i].y,0); // +yoffset;
  929.     }
  930.     flModel = POLYGON_BOUNDARY;
  931.     if(nFillStyle == wxWINDING_RULE)
  932.         flModel |= POLYGON_WINDING;
  933.     else
  934.         flModel |= POLYGON_ALTERNATE;
  935.  
  936.     vPoint.x = vXoffset;
  937.     vPoint.y = OS2Y(vYoffset,0);
  938.  
  939.     ::GpiSetColor(m_hPS, lBorderColor);
  940.     ::GpiMove(m_hPS, &vPoint);
  941.     lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel);
  942.     free(vPlgn.aPointl);
  943. } // end of wxDC::DoDrawPolygon
  944.  
  945. void wxDC::DoDrawLines(
  946.   int                               n
  947. , wxPoint                           vPoints[]
  948. , wxCoord                           vXoffset
  949. , wxCoord                           vYoffset
  950. )
  951. {
  952.     POINTL                          vPoint;
  953.  
  954.     if (vXoffset != 0L || vXoffset != 0L)
  955.     {
  956.         int                             i;
  957.  
  958.         vPoint.x = vPoints[0].x + vXoffset;
  959.         vPoint.y = OS2Y(vPoints[0].y + vYoffset,0);
  960.         ::GpiMove(m_hPS, &vPoint);
  961.  
  962.         LONG                            lBorderColor = m_pen.GetColour().GetPixel();
  963.  
  964.         ::GpiSetColor(m_hPS, lBorderColor);
  965.         for(i = 1; i < n; i++)
  966.         {
  967.             vPoint.x = vPoints[i].x + vXoffset;
  968.             vPoint.y = OS2Y(vPoints[i].y + vYoffset,0);
  969.             ::GpiLine(m_hPS, &vPoint);
  970.         }
  971.     }
  972.     else
  973.     {
  974.         int                         i;
  975.  
  976.         CalcBoundingBox( vPoints[i].x
  977.                         ,vPoints[i].y
  978.                        );
  979.         vPoint.x = vPoints[0].x;
  980.         vPoint.y = OS2Y(vPoints[0].y,0);
  981.         ::GpiMove(m_hPS, &vPoint);
  982.  
  983.         for (i = 0; i < n; i++)
  984.         {
  985.             CalcBoundingBox( vPoints[i].x
  986.                             ,vPoints[i].y
  987.                            );
  988.             vPoint.x = vPoints[i].x;
  989.             vPoint.y = OS2Y(vPoints[i].y,0);
  990.             ::GpiLine(m_hPS, &vPoint);
  991.         }
  992.     }
  993. } // end of wxDC::DoDrawLines
  994.  
  995. void wxDC::DoDrawRectangle(
  996.   wxCoord                           vX
  997. , wxCoord                           vY
  998. , wxCoord                           vWidth
  999. , wxCoord                           vHeight
  1000. )
  1001. {
  1002.     POINTL                          vPoint[2];
  1003.     LONG                            lControl;
  1004.     LONG                            lColor;
  1005.     LONG                            lBorderColor;
  1006.     int                             nIsTRANSPARENT = 0;
  1007.  
  1008.     //
  1009.     // Might be a memory DC with no Paint rect.
  1010.     //
  1011.     if (!(m_vRclPaint.yTop == 0 &&
  1012.           m_vRclPaint.yBottom == 0 &&
  1013.           m_vRclPaint.xRight == 0 &&
  1014.           m_vRclPaint.xLeft == 0))
  1015.         vY = OS2Y(vY,vHeight);
  1016.     else
  1017.     {
  1018.         if (m_vSelectedBitmap != wxNullBitmap)
  1019.         {
  1020.             m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
  1021.             m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
  1022.             vY = OS2Y(vY,vHeight);
  1023.         }
  1024.     }
  1025.  
  1026.     wxCoord                         vX2 = vX + vWidth;
  1027.     wxCoord                         vY2 = vY + vHeight;
  1028.  
  1029.     vPoint[0].x = vX;
  1030.     vPoint[0].y = vY;
  1031.     vPoint[1].x = vX + vWidth - 1;
  1032.     vPoint[1].y = vY + vHeight - 1;
  1033.     ::GpiMove(m_hPS, &vPoint[0]);
  1034.     lColor       = m_brush.GetColour().GetPixel();
  1035.     lBorderColor = m_pen.GetColour().GetPixel();
  1036.     if (m_brush.GetStyle() == wxTRANSPARENT)
  1037.         nIsTRANSPARENT = 1;
  1038.     if(lColor == lBorderColor || nIsTRANSPARENT)
  1039.     {
  1040.         lControl = DRO_OUTLINEFILL; //DRO_FILL;
  1041.         if(m_brush.GetStyle() == wxTRANSPARENT)
  1042.             lControl = DRO_OUTLINE;
  1043.  
  1044.         ::GpiSetColor(m_hPS, lBorderColor);
  1045.         ::GpiBox( m_hPS       // handle to a presentation space
  1046.                  ,lControl   // draw the box outline ? or ?
  1047.                  ,&vPoint[1]  // address of the corner
  1048.                  ,0L          // horizontal corner radius
  1049.                  ,0L          // vertical corner radius
  1050.                 );
  1051.     }
  1052.     else
  1053.     {
  1054.         lControl = DRO_OUTLINE;
  1055.         ::GpiSetColor( m_hPS
  1056.                       ,lBorderColor
  1057.                      );
  1058.         ::GpiBox( m_hPS
  1059.                  ,lControl
  1060.                  ,&vPoint[1]
  1061.                  ,0L
  1062.                  ,0L
  1063.                 );
  1064.         lControl = DRO_FILL;
  1065.         ::GpiSetColor( m_hPS
  1066.                       ,lColor
  1067.                      );
  1068.         vPoint[0].x = vX + 1;
  1069.         vPoint[0].y = vY + 1;
  1070.         vPoint[1].x = vX + vWidth - 2;
  1071.         vPoint[1].y = vY + vHeight - 2;
  1072.         ::GpiMove(m_hPS, &vPoint[0]);
  1073.         ::GpiBox( m_hPS
  1074.                  ,lControl
  1075.                  ,&vPoint[1]
  1076.                  ,0L
  1077.                  ,0L
  1078.                 );
  1079.     }
  1080.     CalcBoundingBox(vX, vY);
  1081.     CalcBoundingBox(vX2, vY2);
  1082. } // end of wxDC::DoDrawRectangle
  1083.  
  1084. void wxDC::DoDrawRoundedRectangle(
  1085.   wxCoord                           vX
  1086. , wxCoord                           vY
  1087. , wxCoord                           vWidth
  1088. , wxCoord                           vHeight
  1089. , double                            dRadius
  1090. )
  1091. {
  1092.     POINTL                          vPoint[2];
  1093.     LONG                            lControl;
  1094.     LONG                            lColor;
  1095.     LONG                            lBorderColor;
  1096.     int                             nIsTRANSPARENT = 0;
  1097.  
  1098.     //
  1099.     // Might be a memory DC with no Paint rect.
  1100.     //
  1101.     if (!(m_vRclPaint.yTop == 0 &&
  1102.           m_vRclPaint.yBottom == 0 &&
  1103.           m_vRclPaint.xRight == 0 &&
  1104.           m_vRclPaint.xLeft == 0))
  1105.         vY = OS2Y(vY,vHeight);
  1106.     else
  1107.     {
  1108.         if (m_vSelectedBitmap != wxNullBitmap)
  1109.         {
  1110.             m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
  1111.             m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
  1112.             vY = OS2Y(vY,vHeight);
  1113.         }
  1114.     }
  1115.  
  1116.     wxCoord                         vX2 = (vX + vWidth);
  1117.     wxCoord                         vY2 = (vY + vHeight);
  1118.  
  1119.     vPoint[0].x = vX;
  1120.     vPoint[0].y = vY;
  1121.     vPoint[1].x = vX + vWidth - 1;
  1122.     vPoint[1].y = vY + vHeight - 1;
  1123.     ::GpiMove(m_hPS, &vPoint[0]);
  1124.  
  1125.     lColor       = m_brush.GetColour().GetPixel();
  1126.     lBorderColor = m_pen.GetColour().GetPixel();
  1127.     lControl = DRO_OUTLINEFILL; //DRO_FILL;
  1128.     if (m_brush.GetStyle() == wxTRANSPARENT)
  1129.         nIsTRANSPARENT = 1;
  1130.     if(lColor == lBorderColor || nIsTRANSPARENT)
  1131.     {
  1132.         lControl = DRO_OUTLINEFILL; //DRO_FILL;
  1133.         if(m_brush.GetStyle() == wxTRANSPARENT)
  1134.             lControl = DRO_OUTLINE;
  1135.  
  1136.         ::GpiSetColor(m_hPS, lColor);
  1137.         ::GpiBox( m_hPS         // handle to a presentation space
  1138.                  ,lControl      // draw the box outline ? or ?
  1139.                  ,&vPoint[1]    // address of the corner
  1140.                  ,(LONG)dRadius // horizontal corner radius
  1141.                  ,(LONG)dRadius // vertical corner radius
  1142.                 );
  1143.     }
  1144.     else
  1145.     {
  1146.         lControl = DRO_OUTLINE;
  1147.         ::GpiSetColor( m_hPS
  1148.                       ,lBorderColor
  1149.                      );
  1150.         ::GpiBox( m_hPS
  1151.                  ,lControl
  1152.                  ,&vPoint[1]
  1153.                  ,(LONG)dRadius
  1154.                  ,(LONG)dRadius
  1155.                 );
  1156.         lControl = DRO_FILL;
  1157.         ::GpiSetColor( m_hPS
  1158.                       ,lColor
  1159.                      );
  1160.         vPoint[0].x = vX + 1;
  1161.         vPoint[0].y = vY + 1;
  1162.         vPoint[1].x = vX + vWidth - 2;
  1163.         vPoint[1].y = vY + vHeight - 2;
  1164.         ::GpiMove(m_hPS, &vPoint[0]);
  1165.         ::GpiBox( m_hPS
  1166.                  ,lControl
  1167.                  ,&vPoint[1]
  1168.                  ,(LONG)dRadius
  1169.                  ,(LONG)dRadius
  1170.                 );
  1171.     }
  1172.  
  1173.     CalcBoundingBox(vX, vY);
  1174.     CalcBoundingBox(vX2, vY2);
  1175. } // end of wxDC::DoDrawRoundedRectangle
  1176.  
  1177. // Draw Ellipse within box (x,y) - (x+width, y+height)
  1178. void wxDC::DoDrawEllipse(
  1179.   wxCoord                           vX
  1180. , wxCoord                           vY
  1181. , wxCoord                           vWidth
  1182. , wxCoord                           vHeight
  1183. )
  1184. {
  1185.     POINTL                          vPtlPos; // Structure for current position
  1186.     FIXED                           vFxMult; // Multiplier for ellipse
  1187.     ARCPARAMS                       vArcp;   // Structure for arc parameters
  1188.  
  1189.     vY = OS2Y(vY,vHeight);
  1190.  
  1191.     vArcp.lR = 0;
  1192.     vArcp.lQ = vHeight/2;
  1193.     vArcp.lP = vWidth/2;
  1194.     vArcp.lS = 0;
  1195.     ::GpiSetArcParams( m_hPS
  1196.                       ,&vArcp
  1197.                      ); // Sets parameters to default
  1198.     vPtlPos.x = vX + vWidth/2;  // Loads x-coordinate
  1199.     vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
  1200.     ::GpiMove( m_hPS
  1201.               ,&vPtlPos
  1202.              ); // Sets current position
  1203.     vFxMult = MAKEFIXED(1, 0);             /* Sets multiplier            */
  1204.  
  1205.     //
  1206.     // DRO_FILL, DRO_OTLINEFILL - where to get
  1207.     //
  1208.     ::GpiFullArc( m_hPS
  1209.                  ,DRO_OUTLINE
  1210.                  ,vFxMult
  1211.                 ); // Draws full arc with center at current position
  1212.  
  1213.     wxCoord                         vX2 = (vX + vWidth);
  1214.     wxCoord                         vY2 = (vY + vHeight);
  1215.  
  1216.     CalcBoundingBox(vX, vY);
  1217.     CalcBoundingBox(vX2, vY2);
  1218. } // end of wxDC::DoDrawEllipse
  1219.  
  1220. void wxDC::DoDrawEllipticArc(
  1221.   wxCoord                           vX
  1222. , wxCoord                           vY
  1223. , wxCoord                           vWidth
  1224. , wxCoord                           vHeight
  1225. , double                            dSa
  1226. , double                            dEa
  1227. )
  1228. {
  1229.     POINTL                          vPtlPos; // Structure for current position
  1230.     FIXED                           vFxMult; // Multiplier for ellipse
  1231.     ARCPARAMS                       vArcp;   // Structure for arc parameters
  1232.     FIXED                           vFSa;
  1233.     FIXED                           vFSweepa; // Start angle, sweep angle
  1234.     double                          dIntPart;
  1235.     double                          dFractPart;
  1236.     double                          dRadius;
  1237.  
  1238.     vY = OS2Y(vY,vHeight);
  1239.  
  1240.     dFractPart = modf(dSa,&dIntPart);
  1241.     vFSa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
  1242.     dFractPart = modf(dEa - dSa, &dIntPart);
  1243.     vFSweepa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
  1244.  
  1245.     //
  1246.     // Ellipse main axis (r,q), (p,s) with center at (0,0)
  1247.     //
  1248.     vArcp.lR = 0;
  1249.     vArcp.lQ = vHeight/2;
  1250.     vArcp.lP = vWidth/2;
  1251.     vArcp.lS = 0;
  1252.     ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
  1253.     vPtlPos.x = vX + vWidth/2  * (1. + cos(DegToRad(dSa))); // Loads x-coordinate
  1254.     vPtlPos.y = vY + vHeight/2 * (1. + sin(DegToRad(dSa))); // Loads y-coordinate
  1255.     ::GpiMove(m_hPS, &vPtlPos); // Sets current position
  1256.  
  1257.     //
  1258.     // May be not to the center ?
  1259.     //
  1260.     vPtlPos.x = vX + vWidth/2 ; // Loads x-coordinate
  1261.     vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
  1262.     vFxMult = MAKEFIXED(1, 0);  // Sets multiplier
  1263.  
  1264.     //
  1265.     // DRO_FILL, DRO_OTLINEFILL - where to get
  1266.     //
  1267.     ::GpiPartialArc( m_hPS
  1268.                     ,&vPtlPos
  1269.                     ,vFxMult
  1270.                     ,vFSa
  1271.                     ,vFSweepa
  1272.                    );
  1273.     wxCoord                         vX2 = (vX + vWidth);
  1274.     wxCoord                         vY2 = (vY + vHeight);
  1275.  
  1276.     CalcBoundingBox(vX, vY);
  1277.     CalcBoundingBox(vX2, vY2);
  1278. } // end of wxDC::DoDrawEllipticArc
  1279.  
  1280. void wxDC::DoDrawIcon(
  1281.   const wxIcon&                     rIcon
  1282. , wxCoord                           vX
  1283. , wxCoord                           vY
  1284. )
  1285. {
  1286.     //
  1287.     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords
  1288.     // and I don't feel like figuring those out for scrollable windows so
  1289.     // just convert to a bitmap then let the DoDrawBitmap routing display it
  1290.     //
  1291.     if (rIcon.IsXpm())
  1292.     {
  1293.         DoDrawBitmap(rIcon.GetXpmSrc(), vX, vY, TRUE);
  1294.     }
  1295.     else
  1296.     {
  1297.         wxBitmap                        vBitmap(rIcon);
  1298.  
  1299.         DoDrawBitmap(vBitmap, vX, vY, FALSE);
  1300.     }
  1301.     CalcBoundingBox(vX, vY);
  1302.     CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight());
  1303. } // end of wxDC::DoDrawIcon
  1304.  
  1305. void wxDC::DoDrawBitmap(
  1306.   const wxBitmap&                   rBmp
  1307. , wxCoord                           vX
  1308. , wxCoord                           vY
  1309. , bool                              bUseMask
  1310. )
  1311. {
  1312.     if (!IsKindOf(CLASSINFO(wxPrinterDC)))
  1313.     {
  1314.         HBITMAP                         hBitmap =  (HBITMAP)rBmp.GetHBITMAP();
  1315.         HBITMAP                         hBitmapOld;
  1316.         POINTL                          vPoint[4];
  1317.  
  1318.         vY = OS2Y(vY,rBmp.GetHeight());
  1319.  
  1320.         vPoint[0].x = vX;
  1321.         vPoint[0].y = vY + rBmp.GetHeight();
  1322.         vPoint[1].x = vX + rBmp.GetWidth();
  1323.         vPoint[1].y = vY;
  1324.         vPoint[2].x = 0;
  1325.         vPoint[2].y = 0;
  1326.         vPoint[3].x = rBmp.GetWidth();
  1327.         vPoint[3].y = rBmp.GetHeight();
  1328.         if (bUseMask)
  1329.         {
  1330.             wxMask*                     pMask = rBmp.GetMask();
  1331.  
  1332.             if (pMask)
  1333.             {
  1334.                 //
  1335.                 // Need to imitate ::MaskBlt in windows.
  1336.                 // 1) Extract the bits from from the bitmap.
  1337.                 // 2) Extract the bits from the mask
  1338.                 // 3) Using the mask bits do the following:
  1339.                 //   A) If the mask byte is 00 leave the bitmap byte alone
  1340.                 //   B) If the mask byte is FF copy the screen color into
  1341.                 //      bitmap byte
  1342.                 // 4) Create a new bitmap and set its bits to the above result
  1343.                 // 5) Blit this to the screen PS
  1344.                 //
  1345.                 HBITMAP                 hMask = (HBITMAP)pMask->GetMaskBitmap();
  1346.                 HBITMAP                 hOldMask   = NULLHANDLE;
  1347.                 HBITMAP                 hOldBitmap = NULLHANDLE;
  1348.                 HBITMAP                 hNewBitmap = NULLHANDLE;
  1349.                 unsigned char*          pucBits;     // buffer that will contain the bitmap data
  1350.                 unsigned char*          pucBitsMask; // buffer that will contain the mask data
  1351.                 unsigned char*          pucData;     // pointer to use to traverse bitmap data
  1352.                 unsigned char*          pucDataMask; // pointer to use to traverse mask data
  1353.                 LONG                    lHits;
  1354.                 ERRORID                 vError;
  1355.                 wxString                sError;
  1356.  
  1357.                 //
  1358.                 // The usual Memory context creation stuff
  1359.                 //
  1360.                 DEVOPENSTRUC                    vDop  = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1361.                 SIZEL                           vSize = {0, 0};
  1362.                 HDC                             hDC   = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
  1363.                 HPS                             hPS   = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
  1364.  
  1365.                 //
  1366.                 // The usual bitmap header stuff
  1367.                 //
  1368.                 BITMAPINFOHEADER2               vHeader;
  1369.                 BITMAPINFO2                     vInfo;
  1370.  
  1371.                 memset(&vHeader, '\0', 16);
  1372.                 vHeader.cbFix           = 16;
  1373.  
  1374.                 memset(&vInfo, '\0', 16);
  1375.                 vInfo.cbFix           = 16;
  1376.                 vInfo.cx              = (ULONG)rBmp.GetWidth();
  1377.                 vInfo.cy              = (ULONG)rBmp.GetHeight();
  1378.                 vInfo.cPlanes         = 1;
  1379.                 vInfo.cBitCount       = 24; // Set to desired count going in
  1380.  
  1381.                 //
  1382.                 // Create the buffers for data....all wxBitmaps are 24 bit internally
  1383.                 //
  1384.                 int                     nBytesPerLine = rBmp.GetWidth() * 3;
  1385.                 int                     nSizeDWORD    = sizeof(DWORD);
  1386.                 int                     nLineBoundary = nBytesPerLine % nSizeDWORD;
  1387.                 int                     nPadding = 0;
  1388.                 int                     i;
  1389.                 int                     j;
  1390.                 LONG                    lScans = 0L;
  1391.                 LONG                    lColor = 0L;
  1392.  
  1393.                 //
  1394.                 // Need to get a background color for mask blitting
  1395.                 //
  1396.                 if (IsKindOf(CLASSINFO(wxWindowDC)))
  1397.                 {
  1398.                     wxWindowDC*             pWindowDC = wxDynamicCast(this, wxWindowDC);
  1399.  
  1400.                     lColor = pWindowDC->m_pCanvas->GetBackgroundColour().GetPixel();
  1401.                 }
  1402.                 else if (GetBrush() != wxNullBrush)
  1403.                     lColor = GetBrush().GetColour().GetPixel();
  1404.                 else
  1405.                     lColor = m_textBackgroundColour.GetPixel();
  1406.  
  1407.                 //
  1408.                 // Bitmap must be ina double-word alligned address so we may
  1409.                 // have some padding to worry about
  1410.                 //
  1411.                 if (nLineBoundary > 0)
  1412.                 {
  1413.                     nPadding     = nSizeDWORD - nLineBoundary;
  1414.                     nBytesPerLine += nPadding;
  1415.                 }
  1416.                 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
  1417.                 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
  1418.                 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
  1419.                 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
  1420.  
  1421.                 //
  1422.                 // Extract the bitmap and mask data
  1423.                 //
  1424.                 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
  1425.                 {
  1426.                     vError = ::WinGetLastError(vHabmain);
  1427.                     sError = wxPMErrorToStr(vError);
  1428.                 }
  1429.                 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
  1430.                 vInfo.cBitCount = 24;
  1431.                 if ((lScans = ::GpiQueryBitmapBits( hPS
  1432.                                                    ,0L
  1433.                                                    ,(LONG)rBmp.GetHeight()
  1434.                                                    ,(PBYTE)pucBits
  1435.                                                    ,&vInfo
  1436.                                                   )) == GPI_ALTERROR)
  1437.                 {
  1438.                     vError = ::WinGetLastError(vHabmain);
  1439.                     sError = wxPMErrorToStr(vError);
  1440.                 }
  1441.                 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
  1442.                 {
  1443.                     vError = ::WinGetLastError(vHabmain);
  1444.                     sError = wxPMErrorToStr(vError);
  1445.                 }
  1446.                 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
  1447.                 vInfo.cBitCount = 24;
  1448.                 if ((lScans = ::GpiQueryBitmapBits( hPS
  1449.                                                    ,0L
  1450.                                                    ,(LONG)rBmp.GetHeight()
  1451.                                                    ,(PBYTE)pucBitsMask
  1452.                                                    ,&vInfo
  1453.                                                   )) == GPI_ALTERROR)
  1454.                 {
  1455.                     vError = ::WinGetLastError(vHabmain);
  1456.                     sError = wxPMErrorToStr(vError);
  1457.                 }
  1458.                 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
  1459.                 {
  1460.                     vError = ::WinGetLastError(vHabmain);
  1461.                     sError = wxPMErrorToStr(vError);
  1462.                 }
  1463.  
  1464.                 //
  1465.                 // Now set the bytes(bits) according to the mask values
  1466.                 // 3 bytes per pel...must handle one at a time
  1467.                 //
  1468.                 pucData     = pucBits;
  1469.                 pucDataMask = pucBitsMask;
  1470.  
  1471.                 //
  1472.                 // 16 bit kludge really only kinda works.  The mask gets applied
  1473.                 // where needed but the original bitmap bits are dorked sometimes
  1474.                 //
  1475.                 bool                    bpp16 = (wxDisplayDepth() == 16);
  1476.  
  1477.                 for (i = 0; i < rBmp.GetHeight(); i++)
  1478.                 {
  1479.                     for (j = 0; j < rBmp.GetWidth(); j++)
  1480.                     {
  1481.                         // Byte 1
  1482.                         if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
  1483.                             pucData++;
  1484.                         else if (*pucDataMask == 0xFF) // leave bitmap byte alone
  1485.                             pucData++;
  1486.                         else
  1487.                         {
  1488.                             *pucData = ((unsigned char)(lColor >> 16));
  1489.                             pucData++;
  1490.                         }
  1491.                         // Byte 2
  1492.                         if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
  1493.                             pucData++;
  1494.                         else if (*(pucDataMask + 1) == 0xFF) // leave bitmap byte alone
  1495.                             pucData++;
  1496.                         else
  1497.                         {
  1498.                             *pucData = ((unsigned char)(lColor >> 8));
  1499.                             pucData++;
  1500.                         }
  1501.  
  1502.                         // Byte 3
  1503.                         if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
  1504.                             pucData++;
  1505.                         else if (*(pucDataMask + 2) == 0xFF) // leave bitmap byte alone
  1506.                             pucData++;
  1507.                         else
  1508.                         {
  1509.                             *pucData = ((unsigned char)lColor);
  1510.                             pucData++;
  1511.                         }
  1512.                         pucDataMask += 3;
  1513.                     }
  1514.                     for (j = 0; j < nPadding; j++)
  1515.                     {
  1516.                         pucData++;
  1517.                         pucDataMask++;
  1518.                     }
  1519.                 }
  1520.                 //
  1521.                 // Create a new bitmap
  1522.                 //
  1523.                 vHeader.cx              = (ULONG)rBmp.GetWidth();
  1524.                 vHeader.cy              = (ULONG)rBmp.GetHeight();
  1525.                 vHeader.cPlanes         = 1L;
  1526.                 vHeader.cBitCount       = 24;
  1527.                 if ((hNewBitmap = ::GpiCreateBitmap( hPS
  1528.                                                     ,&vHeader
  1529.                                                     ,CBM_INIT
  1530.                                                     ,(PBYTE)pucBits
  1531.                                                     ,&vInfo
  1532.                                                    )) == GPI_ERROR)
  1533.                 {
  1534.                     vError = ::WinGetLastError(vHabmain);
  1535.                     sError = wxPMErrorToStr(vError);
  1536.                 }
  1537.  
  1538.                 //
  1539.                 // Now blit it to the screen PS
  1540.                 //
  1541.                 if ((lHits = ::GpiWCBitBlt( (HPS)GetHPS()
  1542.                                            ,hNewBitmap
  1543.                                            ,4
  1544.                                            ,vPoint
  1545.                                            ,ROP_SRCCOPY
  1546.                                            ,BBO_IGNORE
  1547.                                           )) == GPI_ERROR)
  1548.                 {
  1549.                     vError = ::WinGetLastError(vHabmain);
  1550.                     sError = wxPMErrorToStr(vError);
  1551.                 }
  1552.  
  1553.                 //
  1554.                 // Clean up
  1555.                 //
  1556.                 free(pucBits);
  1557.                 free(pucBitsMask);
  1558.                 ::GpiSetBitmap(hPS, NULLHANDLE);
  1559.                 ::GpiDeleteBitmap(hNewBitmap);
  1560.                 ::GpiDestroyPS(hPS);
  1561.                 ::DevCloseDC(hDC);
  1562.             }
  1563.         }
  1564.         else
  1565.         {
  1566.             LONG                        lOldForeGround = ::GpiQueryColor((HPS)GetHPS());
  1567.             LONG                        lOldBackGround = ::GpiQueryBackColor((HPS)GetHPS());
  1568.  
  1569.             if (m_textForegroundColour.Ok())
  1570.             {
  1571.                 ::GpiSetColor( (HPS)GetHPS()
  1572.                                ,m_textForegroundColour.GetPixel()
  1573.                               );
  1574.             }
  1575.             if (m_textBackgroundColour.Ok())
  1576.             {
  1577.                 ::GpiSetBackColor( (HPS)GetHPS()
  1578.                                   ,m_textBackgroundColour.GetPixel()
  1579.                                  );
  1580.             }
  1581.             //
  1582.             // Need to alter bits in a mono bitmap to match the new
  1583.             // background-foreground if it is different.
  1584.             //
  1585.             if (rBmp.IsMono() &&
  1586.                ((m_textForegroundColour.GetPixel() != lOldForeGround) ||
  1587.                 (m_textBackgroundColour.GetPixel() != lOldBackGround)))
  1588.             {
  1589.                 DEVOPENSTRUC        vDop  = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1590.                 SIZEL               vSize = {0, 0};
  1591.                 HDC                 hDC   = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
  1592.                 HPS                 hPS   = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
  1593.  
  1594.                 int                 nBytesPerLine = rBmp.GetWidth() * 3;
  1595.                 int                 i, j;
  1596.                 LONG                lForeGround = m_textForegroundColour.GetPixel();
  1597.                 LONG                lBackGround = m_textBackgroundColour.GetPixel();
  1598.                 LONG                lScans;
  1599.                 HBITMAP             hOldBitmap = NULLHANDLE;
  1600.                 BITMAPINFO2         vInfo;
  1601.                 ERRORID             vError;
  1602.                 wxString            sError;
  1603.  
  1604.  
  1605.                 memset(&vInfo, '\0', 16);
  1606.                 vInfo.cbFix           = 16;
  1607.                 vInfo.cx              = (ULONG)rBmp.GetWidth();
  1608.                 vInfo.cy              = (ULONG)rBmp.GetHeight();
  1609.                 vInfo.cPlanes         = 1;
  1610.                 vInfo.cBitCount       = 24;
  1611.  
  1612.                 unsigned char*          pucBits;     // buffer that will contain the bitmap data
  1613.                 unsigned char*          pucData;     // pointer to use to traverse bitmap data
  1614.  
  1615.                 pucBits = new unsigned char[nBytesPerLine * rBmp.GetHeight()];
  1616.                 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
  1617.  
  1618.                 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
  1619.                 {
  1620.                     vError = ::WinGetLastError(vHabmain);
  1621.                     sError = wxPMErrorToStr(vError);
  1622.                     return;
  1623.                 }
  1624.                 if ((lScans = ::GpiQueryBitmapBits( hPS
  1625.                                                    ,0L
  1626.                                                    ,(LONG)rBmp.GetHeight()
  1627.                                                    ,(PBYTE)pucBits
  1628.                                                    ,&vInfo
  1629.                                                   )) == GPI_ALTERROR)
  1630.                 {
  1631.                     vError = ::WinGetLastError(vHabmain);
  1632.                     sError = wxPMErrorToStr(vError);
  1633.                     return;
  1634.                 }
  1635.                 unsigned char           cOldRedFore   = (unsigned char)(lOldForeGround >> 16);
  1636.                 unsigned char           cOldGreenFore = (unsigned char)(lOldForeGround >> 8);
  1637.                 unsigned char           cOldBlueFore  = (unsigned char)lOldForeGround;
  1638.  
  1639.                 unsigned char           cOldRedBack   = (unsigned char)(lOldBackGround >> 16);
  1640.                 unsigned char           cOldGreenBack = (unsigned char)(lOldBackGround >> 8);
  1641.                 unsigned char           cOldBlueBack  = (unsigned char)lOldBackGround;
  1642.  
  1643.                 unsigned char           cRedFore   = (unsigned char)(lForeGround >> 16);
  1644.                 unsigned char           cGreenFore = (unsigned char)(lForeGround >> 8);
  1645.                 unsigned char           cBlueFore  = (unsigned char)lForeGround;
  1646.  
  1647.                 unsigned char           cRedBack   = (unsigned char)(lBackGround >> 16);
  1648.                 unsigned char           cGreenBack = (unsigned char)(lBackGround >> 8);
  1649.                 unsigned char           cBlueBack  = (unsigned char)lBackGround;
  1650.  
  1651.                 pucData = pucBits;
  1652.                 for (i = 0; i < rBmp.GetHeight(); i++)
  1653.                 {
  1654.                     for (j = 0; j < rBmp.GetWidth(); j++)
  1655.                     {
  1656.                         unsigned char    cBmpRed   = *pucData;
  1657.                         unsigned char    cBmpGreen = *(pucData + 1);
  1658.                         unsigned char    cBmpBlue  = *(pucData + 2);
  1659.  
  1660.                         if ((cBmpRed == cOldRedFore) &&
  1661.                             (cBmpGreen == cOldGreenFore) &&
  1662.                             (cBmpBlue == cOldBlueFore))
  1663.                         {
  1664.                             *pucData = cBlueFore;
  1665.                             pucData++;
  1666.                             *pucData = cGreenFore;
  1667.                             pucData++;
  1668.                             *pucData = cRedFore;
  1669.                             pucData++;
  1670.                         }
  1671.                         else
  1672.                         {
  1673.                             *pucData = cBlueBack;
  1674.                             pucData++;
  1675.                             *pucData = cGreenBack;
  1676.                             pucData++;
  1677.                             *pucData = cRedBack;
  1678.                             pucData++;
  1679.                         }
  1680.                     }
  1681.                 }
  1682.                 if ((lScans = ::GpiSetBitmapBits( hPS
  1683.                                                  ,0L
  1684.                                                  ,(LONG)rBmp.GetHeight()
  1685.                                                  ,(PBYTE)pucBits
  1686.                                                  ,&vInfo
  1687.                                                 )) == GPI_ALTERROR)
  1688.                 {
  1689.                     vError = ::WinGetLastError(vHabmain);
  1690.                     sError = wxPMErrorToStr(vError);
  1691.                     return;
  1692.                 }
  1693.                 delete [] pucBits;
  1694.                 ::GpiSetBitmap(hPS, NULLHANDLE);
  1695.                 ::GpiDestroyPS(hPS);
  1696.                 ::DevCloseDC(hDC);
  1697.             }
  1698.             ::GpiWCBitBlt( (HPS)GetHPS()
  1699.                           ,hBitmap
  1700.                           ,4
  1701.                           ,vPoint
  1702.                           ,ROP_SRCCOPY
  1703.                           ,BBO_IGNORE
  1704.                          );
  1705.             ::GpiSetBitmap((HPS)GetHPS(), hBitmapOld);
  1706.             ::GpiSetColor((HPS)GetHPS(), lOldForeGround);
  1707.             ::GpiSetBackColor((HPS)GetHPS(), lOldBackGround);
  1708.         }
  1709.     }
  1710. } // end of wxDC::DoDrawBitmap
  1711.  
  1712. void wxDC::DoDrawText(
  1713.   const wxString&                   rsText
  1714. , wxCoord                           vX
  1715. , wxCoord                           vY
  1716. )
  1717. {
  1718.     wxCoord                         vWidth;
  1719.     wxCoord                         vHeight;
  1720.  
  1721.     DrawAnyText( rsText
  1722.                 ,vX
  1723.                 ,vY
  1724.                );
  1725.  
  1726.     CalcBoundingBox(vX, vY);
  1727.     GetTextExtent(rsText, &vWidth, &vHeight);
  1728.     CalcBoundingBox((vX + vWidth), (vY + vHeight));
  1729. } // end of wxDC::DoDrawText
  1730.  
  1731. void wxDC::DrawAnyText(
  1732.   const wxString&                   rsText
  1733. , wxCoord                           vX
  1734. , wxCoord                           vY
  1735. )
  1736. {
  1737.     int                             nOldBackground = 0;
  1738.     POINTL                          vPtlStart;
  1739.     LONG                            lHits;
  1740.     wxCoord                         vTextX = 0;
  1741.     wxCoord                         vTextY = 0;
  1742.  
  1743.     //
  1744.     // prepare for drawing the text
  1745.     //
  1746.  
  1747.     //
  1748.     // Set text color attributes
  1749.     //
  1750.     if (m_textForegroundColour.Ok())
  1751.     {
  1752.         SetTextColor( m_hPS
  1753.                      ,(int)m_textForegroundColour.GetPixel()
  1754.                     );
  1755.     }
  1756.  
  1757.     if (m_textBackgroundColour.Ok())
  1758.     {
  1759.         nOldBackground = SetTextBkColor( m_hPS
  1760.                                         ,(int)m_textBackgroundColour.GetPixel()
  1761.                                        );
  1762.     }
  1763.     SetBkMode( m_hPS
  1764.               ,m_backgroundMode
  1765.              );
  1766.     GetTextExtent( rsText
  1767.                   ,&vTextX
  1768.                   ,&vTextY
  1769.                  );
  1770.     vPtlStart.x = vX;
  1771.     if (!(m_vRclPaint.yTop == 0 &&
  1772.           m_vRclPaint.yBottom == 0 &&
  1773.           m_vRclPaint.xRight == 0 &&
  1774.           m_vRclPaint.xLeft == 0))
  1775.     {
  1776.         //
  1777.         // Position Text a little differently in the Statusbar from other panels
  1778.         //
  1779.         if (m_pCanvas && m_pCanvas->IsKindOf(CLASSINFO(wxStatusBar)))
  1780.             vPtlStart.y = OS2Y(vY,vTextY);
  1781.         else
  1782.             vPtlStart.y = OS2Y(vY,vTextY/1.5); // Full extent is a bit much
  1783.     }
  1784.     else
  1785.     {
  1786.         if (m_vSelectedBitmap != wxNullBitmap)
  1787.         {
  1788.             m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
  1789.             m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
  1790.             if (m_pCanvas && m_pCanvas->IsKindOf(CLASSINFO(wxStatusBar)))
  1791.                 vPtlStart.y = OS2Y(vY,vTextY);
  1792.             else
  1793.                 vPtlStart.y = OS2Y(vY,vTextY/1.5);
  1794.         }
  1795.         else
  1796.             vPtlStart.y = vY;
  1797.     }
  1798.  
  1799.     PCH                             pzStr = (PCH)rsText.c_str();
  1800.  
  1801.     ::GpiMove(m_hPS, &vPtlStart);
  1802.     lHits = ::GpiCharString( m_hPS
  1803.                             ,rsText.length()
  1804.                             ,pzStr
  1805.                            );
  1806.     if (lHits != GPI_OK)
  1807.     {
  1808.         wxLogLastError(wxT("TextOut"));
  1809.     }
  1810.  
  1811.     //
  1812.     // Restore the old parameters (text foreground colour may be left because
  1813.     // it never is set to anything else, but background should remain
  1814.     // transparent even if we just drew an opaque string)
  1815.     //
  1816.     if (m_textBackgroundColour.Ok())
  1817.             SetTextBkColor( m_hPS
  1818.                            ,nOldBackground
  1819.                           );
  1820.     SetBkMode( m_hPS
  1821.               ,wxTRANSPARENT
  1822.              );
  1823. }
  1824.  
  1825. void wxDC::DoDrawRotatedText(
  1826.   const wxString&                   rsText
  1827. , wxCoord                           vX
  1828. , wxCoord                           vY
  1829. , double                            dAngle
  1830. )
  1831. {
  1832.     if (dAngle == 0.0)
  1833.     {
  1834.         DoDrawText( rsText
  1835.                    ,vX
  1836.                    ,vY
  1837.                   );
  1838.     }
  1839.  
  1840.    // TODO:
  1841.    /*
  1842.     if ( angle == 0.0 )
  1843.     {
  1844.         DoDrawText(text, x, y);
  1845.     }
  1846.     else
  1847.     {
  1848.         LOGFONT lf;
  1849.         wxFillLogFont(&lf, &m_font);
  1850.  
  1851.         // GDI wants the angle in tenth of degree
  1852.         long angle10 = (long)(angle * 10);
  1853.         lf.lfEscapement = angle10;
  1854.         lf. lfOrientation = angle10;
  1855.  
  1856.         HFONT hfont = ::CreateFontIndirect(&lf);
  1857.         if ( !hfont )
  1858.         {
  1859.             wxLogLastError("CreateFont");
  1860.         }
  1861.         else
  1862.         {
  1863.             HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
  1864.  
  1865.             DrawAnyText(text, x, y);
  1866.  
  1867.             (void)::SelectObject(GetHdc(), hfontOld);
  1868.         }
  1869.  
  1870.         // call the bounding box by adding all four vertices of the rectangle
  1871.         // containing the text to it (simpler and probably not slower than
  1872.         // determining which of them is really topmost/leftmost/...)
  1873.         wxCoord w, h;
  1874.         GetTextExtent(text, &w, &h);
  1875.  
  1876.         double rad = DegToRad(angle);
  1877.  
  1878.         // "upper left" and "upper right"
  1879.         CalcBoundingBox(x, y);
  1880.         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
  1881.         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
  1882.  
  1883.         // "bottom left" and "bottom right"
  1884.         x += (wxCoord)(h*sin(rad));
  1885.         y += (wxCoord)(h*cos(rad));
  1886.         CalcBoundingBox(x, y);
  1887.         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
  1888.     }
  1889. */
  1890. }
  1891.  
  1892. // ---------------------------------------------------------------------------
  1893. // set GDI objects
  1894. // ---------------------------------------------------------------------------
  1895.  
  1896. void wxDC::DoSelectPalette(
  1897.   bool                              bRealize
  1898. )
  1899. {
  1900.     //
  1901.     // Set the old object temporarily, in case the assignment deletes an object
  1902.     // that's not yet selected out.
  1903.     //
  1904.     if (m_hOldPalette)
  1905.     {
  1906.         m_hOldPalette = 0;
  1907.     }
  1908.  
  1909.     if (m_palette.Ok())
  1910.     {
  1911.         HPALETTE                    hOldPal;
  1912.  
  1913.         hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE());
  1914.         if (!m_hOldPalette)
  1915.             m_hOldPalette = (WXHPALETTE)hOldPal;
  1916.     }
  1917. } // end of wxDC::DoSelectPalette
  1918.  
  1919. void wxDC::InitializePalette()
  1920. {
  1921.     if (wxDisplayDepth() <= 8 )
  1922.     {
  1923.         //
  1924.         // Look for any window or parent that has a custom palette. If any has
  1925.         // one then we need to use it in drawing operations
  1926.         //
  1927.         wxWindow*                   pWin = m_pCanvas->GetAncestorWithCustomPalette();
  1928.  
  1929.         m_hasCustomPalette = pWin && pWin->HasCustomPalette();
  1930.         if (m_hasCustomPalette)
  1931.         {
  1932.             m_palette = pWin->GetPalette();
  1933.  
  1934.             //
  1935.             // turn on PM translation for this palette
  1936.             //
  1937.             DoSelectPalette();
  1938.         }
  1939.     }
  1940. } // end of wxDC::InitializePalette
  1941.  
  1942. void wxDC::SetPalette(
  1943.   const wxPalette&                  rPalette
  1944. )
  1945. {
  1946.     if (m_hOldFont)
  1947.     {
  1948.         m_hOldFont = 0;
  1949.     }
  1950.     m_palette = rPalette;
  1951.     if (!rPalette.Ok())
  1952.     {
  1953.         if (m_hOldFont)
  1954.         {
  1955.             m_hOldFont = 0;
  1956.         }
  1957.     }
  1958.     HPALETTE                    hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE());
  1959.     if (!m_hOldPalette)
  1960.         m_hOldPalette = (WXHPALETTE)hOldPal;
  1961. } // end of wxDC::SetPalette
  1962.  
  1963. void wxDC::SetFont(
  1964.   const wxFont&                     rFont
  1965. )
  1966. {
  1967.     //
  1968.     // Set the old object temporarily, in case the assignment deletes an object
  1969.     // that's not yet selected out.
  1970.     //
  1971.     if (m_hOldFont)
  1972.     {
  1973.         m_hOldFont = 0;
  1974.     }
  1975.     m_font = rFont;
  1976.     if (!rFont.Ok())
  1977.     {
  1978.         m_hOldFont = 0;
  1979.     }
  1980.  
  1981.     m_font.SetPS(m_hPS); // this will realize the font
  1982.  
  1983.     if (m_font.Ok())
  1984.     {
  1985.         HFONT                       hFont = m_font.GetResourceHandle();
  1986.         if (hFont == (HFONT) NULL)
  1987.         {
  1988.             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
  1989.         }
  1990.         if (!m_hOldFont)
  1991.             m_hOldFont = (WXHFONT) hFont;
  1992.     }
  1993. } // end of wxDC::SetFont
  1994.  
  1995. void wxDC::SetPen(
  1996.   const wxPen&                      rPen
  1997. )
  1998. {
  1999.     wxCHECK_RET( Ok(), wxT("invalid window dc") );
  2000.  
  2001.     if (m_pen == rPen)
  2002.         return;
  2003.     m_pen = rPen;
  2004.     if (!m_pen.Ok())
  2005.         return;
  2006.  
  2007.     if (m_hOldPen)
  2008.         m_hOldPen = 0L;
  2009.     m_pen = rPen;
  2010.  
  2011.     if (!m_pen.Ok())
  2012.     {
  2013.         if (m_hOldPen)
  2014.         {
  2015.             m_pen.SetPS((HPS)m_hOldPen);
  2016.         }
  2017.         m_hOldPen = 0L;
  2018.     }
  2019.  
  2020.     if (m_pen.Ok())
  2021.     {
  2022.         if (m_pen.GetResourceHandle())
  2023.         {
  2024.             m_pen.SetPS(m_hPS);
  2025.             if (!m_hOldPen)
  2026.                 m_hOldPen = m_pen.GetPS();
  2027.         }
  2028.         ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel());
  2029.     }
  2030. }
  2031.  
  2032. void wxDC::SetBrush(
  2033.   const wxBrush&                    rBrush
  2034. )
  2035. {
  2036.     wxCHECK_RET( Ok(), wxT("invalid window dc") );
  2037.  
  2038.     if (m_hOldBrush)
  2039.         m_hOldBrush = 0L;
  2040.     m_brush = rBrush;
  2041.     if (!m_brush.Ok())
  2042.     if (m_brush == rBrush)
  2043.         return;
  2044.     if (!m_brush.Ok())
  2045.         if (m_hOldBrush)
  2046.             m_hOldBrush = 0L;
  2047.  
  2048.     if (!m_brush.Ok())
  2049.     {
  2050.         if (m_hOldBrush)
  2051.         {
  2052.             m_brush.SetPS((HPS)m_hOldBrush);
  2053.         }
  2054.         m_hOldBrush = 0L;
  2055.     }
  2056.  
  2057.     if (m_brush.Ok())
  2058.     {
  2059.         if (m_brush.GetResourceHandle())
  2060.         {
  2061.             m_brush.SetPS(m_hPS);
  2062.             if (!m_hOldBrush)
  2063.                 m_hOldBrush = (WXHWND)m_brush.GetPS();
  2064.         }
  2065.     }
  2066. } // end of wxDC::SetBrush
  2067.  
  2068. void wxDC::SetBackground(
  2069.   const wxBrush&                    rBrush
  2070. )
  2071. {
  2072.     m_backgroundBrush = rBrush;
  2073.     if (!m_backgroundBrush.Ok())
  2074.         return;
  2075.     if (m_pCanvas)
  2076.     {
  2077.         bool                        bCustomColours = TRUE;
  2078.  
  2079.         //
  2080.         // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
  2081.         // change background colours from the control-panel specified colours.
  2082.         //
  2083.         if (m_pCanvas->IsKindOf(CLASSINFO(wxWindow)) &&
  2084.             ((m_pCanvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
  2085.             bCustomColours = FALSE;
  2086.         if (bCustomColours)
  2087.         {
  2088.             if (m_backgroundBrush.GetStyle()==wxTRANSPARENT)
  2089.             {
  2090.                 m_pCanvas->SetTransparent(TRUE);
  2091.             }
  2092.             else
  2093.             {
  2094.                 //
  2095.                 // Setting the background brush of a DC
  2096.                 // doesn't affect the window background colour. However,
  2097.                 // I'm leaving in the transparency setting because it's needed by
  2098.                 // various controls (e.g. wxStaticText) to determine whether to draw
  2099.                 // transparently or not. TODO: maybe this should be a new function
  2100.                 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
  2101.                 // parent?
  2102.                 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
  2103.                 //
  2104.                 m_pCanvas->SetTransparent(FALSE);
  2105.             }
  2106.         }
  2107.     }
  2108.     COLORREF                        vNewColor = m_backgroundBrush.GetColour().GetPixel();
  2109.     (void)::GpiSetBackColor((HPS)m_hPS, (LONG)vNewColor);
  2110. } // end of wxDC::SetBackground
  2111.  
  2112. void wxDC::SetBackgroundMode(
  2113.   int                               nMode
  2114. )
  2115. {
  2116.     m_backgroundMode = nMode;
  2117. } // end of wxDC::SetBackgroundMode
  2118.  
  2119. void wxDC::SetLogicalFunction(
  2120.   int                               nFunction
  2121. )
  2122. {
  2123.     m_logicalFunction = nFunction;
  2124.     SetRop((WXHDC)m_hDC);
  2125. } // wxDC::SetLogicalFunction
  2126.  
  2127. void wxDC::SetRop(
  2128.   WXHDC                             hDC
  2129. )
  2130. {
  2131.     if (!hDC || m_logicalFunction < 0)
  2132.         return;
  2133.  
  2134.     LONG                            lCRop;
  2135.     switch (m_logicalFunction)
  2136.     {
  2137.         case wxXOR:
  2138.             lCRop = FM_XOR;
  2139.             break;
  2140.  
  2141.         case wxINVERT:
  2142.             lCRop = FM_INVERT;
  2143.             break;
  2144.  
  2145.         case wxOR_REVERSE:
  2146.             lCRop = FM_MERGESRCNOT;
  2147.             break;
  2148.  
  2149.         case wxAND_REVERSE:
  2150.             lCRop = FM_NOTMASKSRC;
  2151.             break;
  2152.  
  2153.         case wxCLEAR:
  2154.             lCRop = FM_ONE;
  2155.             break;
  2156.  
  2157.         case wxSET:
  2158.             lCRop = FM_ZERO;
  2159.             break;
  2160.  
  2161.         case wxSRC_INVERT:
  2162.             lCRop = FM_MERGENOTSRC;
  2163.             break;
  2164.  
  2165.         case wxOR_INVERT:
  2166.             lCRop = FM_MERGESRCNOT;
  2167.             break;
  2168.  
  2169.         case wxAND:
  2170.             lCRop = FM_AND;
  2171.             break;
  2172.  
  2173.         case wxOR:
  2174.             lCRop = FM_OR;
  2175.             break;
  2176.  
  2177.         case wxAND_INVERT:
  2178.             lCRop = FM_SUBTRACT;
  2179.             break;
  2180.  
  2181.         case wxEQUIV:
  2182.         case wxNAND:
  2183.         case wxCOPY:
  2184.         default:
  2185.             lCRop = FM_OVERPAINT;
  2186.             break;
  2187.     }
  2188.     ::GpiSetMix((HPS)hDC, lCRop);
  2189. } // end of wxDC::SetRop
  2190.  
  2191. bool wxDC::StartDoc(
  2192.   const wxString&                   rsMessage
  2193. )
  2194. {
  2195.     // We might be previewing, so return TRUE to let it continue.
  2196.     return TRUE;
  2197. } // end of wxDC::StartDoc
  2198.  
  2199. void wxDC::EndDoc()
  2200. {
  2201. } // end of wxDC::EndDoc
  2202.  
  2203. void wxDC::StartPage()
  2204. {
  2205. } // end of wxDC::StartPage
  2206.  
  2207. void wxDC::EndPage()
  2208. {
  2209. } // end of wxDC::EndPage
  2210.  
  2211. // ---------------------------------------------------------------------------
  2212. // text metrics
  2213. // ---------------------------------------------------------------------------
  2214.  
  2215. wxCoord wxDC::GetCharHeight() const
  2216. {
  2217.     FONTMETRICS                     vFM; // metrics structure
  2218.  
  2219.     ::GpiQueryFontMetrics( m_hPS
  2220.                           ,sizeof(FONTMETRICS)
  2221.                           ,&vFM
  2222.                          );
  2223.     return YDEV2LOGREL(vFM.lXHeight);
  2224. }
  2225.  
  2226. wxCoord wxDC::GetCharWidth() const
  2227. {
  2228.     FONTMETRICS                     vFM; // metrics structure
  2229.  
  2230.     ::GpiQueryFontMetrics( m_hPS
  2231.                           ,sizeof(FONTMETRICS)
  2232.                           ,&vFM
  2233.                          );
  2234.     return XDEV2LOGREL(vFM.lAveCharWidth);
  2235. }
  2236.  
  2237. void wxDC::DoGetTextExtent(
  2238.   const wxString&                   rsString
  2239. , wxCoord*                          pvX
  2240. , wxCoord*                          pvY
  2241. , wxCoord*                          pvDescent
  2242. , wxCoord*                          pvExternalLeading
  2243. , wxFont*                           pTheFont
  2244. ) const
  2245. {
  2246.     POINTL                          avPoint[TXTBOX_COUNT];
  2247.     POINTL                          vPtMin;
  2248.     POINTL                          vPtMax;
  2249.     int                             i;
  2250.     int                             l;
  2251.     FONTMETRICS                     vFM; // metrics structure
  2252.     BOOL                            bRc;
  2253.     char*                           pStr;
  2254.     ERRORID                         vErrorCode; // last error id code
  2255.     wxFont*                         pFontToUse = (wxFont*)pTheFont;
  2256.  
  2257.     char                            zMsg[128]; // DEBUG
  2258.     wxString                        sError;
  2259.  
  2260.     if (!pFontToUse)
  2261.         pFontToUse = (wxFont*)&m_font;
  2262.     l = rsString.length();
  2263.     pStr = (PCH) rsString.c_str();
  2264.  
  2265.     //
  2266.     // In world coordinates.
  2267.     //
  2268.     bRc = ::GpiQueryTextBox( m_hPS
  2269.                             ,l
  2270.                             ,pStr
  2271.                             ,TXTBOX_COUNT // return maximum information
  2272.                             ,avPoint      // array of coordinates points
  2273.                            );
  2274.     if(!bRc)
  2275.     {
  2276.        vErrorCode = ::WinGetLastError(wxGetInstance());
  2277.        sError = wxPMErrorToStr(vErrorCode);
  2278.        // DEBUG
  2279.        sprintf(zMsg, "GpiQueryTextBox for %s: failed with Error: %x - %s", pStr, vErrorCode, sError.c_str());
  2280.        (void)wxMessageBox( "wxWindows Menu sample"
  2281.                           ,zMsg
  2282.                           ,wxICON_INFORMATION
  2283.                          );
  2284.     }
  2285.  
  2286.     vPtMin.x = avPoint[0].x;
  2287.     vPtMax.x = avPoint[0].x;
  2288.     vPtMin.y = avPoint[0].y;
  2289.     vPtMax.y = avPoint[0].y;
  2290.     for (i = 1; i < 4; i++)
  2291.     {
  2292.         if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
  2293.         if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
  2294.         if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
  2295.         if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
  2296.     }
  2297.     ::GpiQueryFontMetrics( m_hPS
  2298.                           ,sizeof(FONTMETRICS)
  2299.                           ,&vFM
  2300.                          );
  2301.  
  2302.     if (pvX)
  2303.         *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1);
  2304.     if (pvY)
  2305.         *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1);
  2306.     if (pvDescent)
  2307.         *pvDescent = vFM.lMaxDescender;
  2308.     if (pvExternalLeading)
  2309.         *pvExternalLeading = vFM.lExternalLeading;
  2310. }
  2311.  
  2312. void wxDC::SetMapMode(
  2313.   int                               nMode
  2314. )
  2315. {
  2316.     int                             nPixelWidth = 0;
  2317.     int                             nPixelHeight = 0;
  2318.     int                             nMmWidth = 1;
  2319.     int                             nMmHeight = 1;
  2320.     LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
  2321.  
  2322.     m_mappingMode = nMode;
  2323.  
  2324.     if(::DevQueryCaps( m_hDC
  2325.                       ,CAPS_FAMILY
  2326.                       ,CAPS_VERTICAL_RESOLUTION
  2327.                       ,lArray
  2328.                      ))
  2329.     {
  2330.         LONG                        lHorzRes;
  2331.         LONG                        lVertRes;
  2332.  
  2333.         nPixelWidth    = lArray[CAPS_WIDTH];
  2334.         nPixelHeight   = lArray[CAPS_HEIGHT];
  2335.         lHorzRes  = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
  2336.         lVertRes  = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
  2337.         nMmWidth  = (lHorzRes/1000) * nPixelWidth;
  2338.         nMmWidth = (lVertRes/1000) * nPixelHeight;
  2339.     }
  2340.     if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0))
  2341.     {
  2342.         return;
  2343.     }
  2344.  
  2345.     double                          dMm2pixelsX = nPixelWidth/nMmWidth;
  2346.     double                          dMm2pixelsY = nPixelHeight/nMmHeight;
  2347.  
  2348.     switch (nMode)
  2349.     {
  2350.         case wxMM_TWIPS:
  2351.             m_logicalScaleX = (twips2mm * dMm2pixelsX);
  2352.             m_logicalScaleY = (twips2mm * dMm2pixelsY);
  2353.             break;
  2354.  
  2355.         case wxMM_POINTS:
  2356.             m_logicalScaleX = (pt2mm * dMm2pixelsX);
  2357.             m_logicalScaleY = (pt2mm * dMm2pixelsY);
  2358.             break;
  2359.  
  2360.         case wxMM_METRIC:
  2361.             m_logicalScaleX = dMm2pixelsX;
  2362.             m_logicalScaleY = dMm2pixelsY;
  2363.             break;
  2364.  
  2365.         case wxMM_LOMETRIC:
  2366.             m_logicalScaleX = (dMm2pixelsX/10.0);
  2367.             m_logicalScaleY = (dMm2pixelsY/10.0);
  2368.             break;
  2369.  
  2370.         case wxMM_TEXT:
  2371.         default:
  2372.             m_logicalScaleX = 1.0;
  2373.             m_logicalScaleY = 1.0;
  2374.             break;
  2375.     }
  2376.     SIZEL                           vSize;
  2377.     ULONG                           ulOptions;
  2378.  
  2379.     ulOptions = ::GpiQueryPS(m_hPS, &vSize);
  2380.     if (!ulOptions & PU_ARBITRARY)
  2381.     {
  2382.         ulOptions = PU_ARBITRARY | GPIF_DEFAULT;
  2383.         ::GpiSetPS(m_hPS, &vSize, ulOptions);
  2384.     }
  2385.     m_nWindowExtX = (int)MS_XDEV2LOG(VIEWPORT_EXTENT);
  2386.     m_nWindowExtY = (int)MS_YDEV2LOG(VIEWPORT_EXTENT);
  2387.     // ????
  2388. }; // end of wxDC::SetMapMode
  2389.  
  2390. void wxDC::SetUserScale(
  2391.   double                            dX
  2392. , double                            dY
  2393. )
  2394. {
  2395.     m_userScaleX = dX;
  2396.     m_userScaleY = dY;
  2397.  
  2398.     SetMapMode(m_mappingMode);
  2399. } // end of wxDC::SetUserScale
  2400.  
  2401. void wxDC::SetAxisOrientation(
  2402.   bool                              bXLeftRight
  2403. , bool                              bYBottomUp
  2404. )
  2405. {
  2406.     m_signX = bXLeftRight ? 1 : -1;
  2407.     m_signY = bYBottomUp ? -1 : 1;
  2408.  
  2409.     SetMapMode(m_mappingMode);
  2410. } // end of wxDC::SetAxisOrientation
  2411.  
  2412. void wxDC::SetSystemScale(
  2413.   double                            dX
  2414. , double                            dY
  2415. )
  2416. {
  2417.     m_scaleX = dX;
  2418.     m_scaleY = dY;
  2419.  
  2420.     SetMapMode(m_mappingMode);
  2421. } // end of wxDC::SetSystemScale
  2422.  
  2423. void wxDC::SetLogicalOrigin(
  2424.   wxCoord                           vX
  2425. , wxCoord                           vY
  2426. )
  2427. {
  2428.     RECTL                           vRect;
  2429.  
  2430.     ::GpiQueryPageViewport( m_hPS
  2431.                            ,&vRect
  2432.                           );
  2433.     vRect.xRight -= vX;
  2434.     vRect.yTop += vY;
  2435.     vRect.xLeft = vX;
  2436.     vRect.yBottom = vY;
  2437.     ::GpiSetPageViewport( m_hPS
  2438.                          ,&vRect
  2439.                         );
  2440. }; // end of wxDC::SetLogicalOrigin
  2441.  
  2442. void wxDC::SetDeviceOrigin(
  2443.   wxCoord                           vX
  2444. , wxCoord                           vY
  2445. )
  2446. {
  2447.     RECTL                           vRect;
  2448.  
  2449.     m_deviceOriginX = vX;
  2450.     m_deviceOriginY = vY;
  2451.     ::GpiQueryPageViewport( m_hPS
  2452.                            ,&vRect
  2453.                           );
  2454.     vRect.xLeft += vX;
  2455.     vRect.xRight += vX;
  2456.     vRect.yBottom -= vY;
  2457.     vRect.yTop -= vY;
  2458.     ::GpiSetPageViewport( m_hPS
  2459.                          ,&vRect
  2460.                         );
  2461. }; // end of wxDC::SetDeviceOrigin
  2462.  
  2463. // ---------------------------------------------------------------------------
  2464. // coordinates transformations
  2465. // ---------------------------------------------------------------------------
  2466.  
  2467. wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
  2468. {
  2469.     return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX);
  2470. }
  2471.  
  2472. wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
  2473. {
  2474.     // axis orientation is not taken into account for conversion of a distance
  2475.     return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_scaleX));
  2476. }
  2477.  
  2478. wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
  2479. {
  2480.     return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
  2481. }
  2482.  
  2483. wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
  2484. {
  2485.     // axis orientation is not taken into account for conversion of a distance
  2486.     return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_scaleY));
  2487. }
  2488.  
  2489. wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
  2490. {
  2491.     return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
  2492. }
  2493.  
  2494. wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
  2495. {
  2496.     // axis orientation is not taken into account for conversion of a distance
  2497.     return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_scaleX);
  2498. }
  2499.  
  2500. wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
  2501. {
  2502.     return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
  2503. }
  2504.  
  2505. wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
  2506. {
  2507.     // axis orientation is not taken into account for conversion of a distance
  2508.     return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_scaleY);
  2509. }
  2510.  
  2511. // ---------------------------------------------------------------------------
  2512. // bit blit
  2513. // ---------------------------------------------------------------------------
  2514.  
  2515. bool wxDC::DoBlit(
  2516.   wxCoord                           vXdest
  2517. , wxCoord                           vYdest
  2518. , wxCoord                           vWidth
  2519. , wxCoord                           vHeight
  2520. , wxDC*                             pSource
  2521. , wxCoord                           vXsrc
  2522. , wxCoord                           vYsrc
  2523. , int                               nRop
  2524. , bool                              bUseMask
  2525. , wxCoord                           vXsrcMask
  2526. , wxCoord                           vYsrcMask
  2527. )
  2528. {
  2529.     wxMask*                         pMask = NULL;
  2530.     CHARBUNDLE                      vCbnd;
  2531.     COLORREF                        vOldTextColor;
  2532.     COLORREF                        vOldBackground = ::GpiQueryBackColor(m_hPS);
  2533.  
  2534.     if (bUseMask)
  2535.     {
  2536.         const wxBitmap&             rBmp = pSource->m_vSelectedBitmap;
  2537.  
  2538.         pMask = rBmp.GetMask();
  2539.         if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap()))
  2540.         {
  2541.             bUseMask = FALSE;
  2542.         }
  2543.     }
  2544.  
  2545.     ::GpiQueryAttrs( m_hPS
  2546.                     ,PRIM_CHAR
  2547.                     ,CBB_COLOR
  2548.                     ,&vCbnd
  2549.                    );
  2550.     vOldTextColor = (COLORREF)vCbnd.lColor;
  2551.  
  2552.     if (m_textForegroundColour.Ok())
  2553.     {
  2554.         vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel();
  2555.         ::GpiSetAttrs( m_hPS           // presentation-space handle
  2556.                       ,PRIM_CHAR       // Char primitive.
  2557.                       ,CBB_COLOR       // sets color.
  2558.                       ,0
  2559.                       ,&vCbnd          // buffer for attributes.
  2560.                      );
  2561.     }
  2562.     if (m_textBackgroundColour.Ok())
  2563.     {
  2564.         ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel());
  2565.     }
  2566.  
  2567.     LONG                            lRop = ROP_SRCCOPY;
  2568.  
  2569.     switch (nRop)
  2570.     {
  2571.         case wxXOR:          lRop = ROP_SRCINVERT;        break;
  2572.         case wxINVERT:       lRop = ROP_DSTINVERT;        break;
  2573.         case wxOR_REVERSE:   lRop = 0x00DD0228;           break;
  2574.         case wxAND_REVERSE:  lRop = ROP_SRCERASE;         break;
  2575.         case wxCLEAR:        lRop = ROP_ZERO;             break;
  2576.         case wxSET:          lRop = ROP_ONE;              break;
  2577.         case wxOR_INVERT:    lRop = ROP_MERGEPAINT;       break;
  2578.         case wxAND:          lRop = ROP_SRCAND;           break;
  2579.         case wxOR:           lRop = ROP_SRCPAINT;         break;
  2580.         case wxEQUIV:        lRop = 0x00990066;           break;
  2581.         case wxNAND:         lRop = 0x007700E6;           break;
  2582.         case wxAND_INVERT:   lRop = 0x00220326;           break;
  2583.         case wxCOPY:         lRop = ROP_SRCCOPY;          break;
  2584.         case wxNO_OP:        lRop = ROP_NOTSRCERASE;      break;
  2585.         case wxSRC_INVERT:   lRop = ROP_SRCINVERT;        break;
  2586.         case wxNOR:          lRop = ROP_NOTSRCCOPY;       break;
  2587.         default:
  2588.            wxFAIL_MSG( wxT("unsupported logical function") );
  2589.            return FALSE;
  2590.     }
  2591.  
  2592.     bool                            bSuccess;
  2593.  
  2594.     if (bUseMask)
  2595.     {
  2596.         //
  2597.         // Blit bitmap with mask
  2598.         //
  2599.  
  2600.         //
  2601.         // Create a temp buffer bitmap and DCs/PSs to access it and the mask
  2602.         //
  2603.         HDC                             hDCMask;
  2604.         HDC                             hDCBuffer;
  2605.         HPS                             hPSMask;
  2606.         HPS                             hPSBuffer;
  2607.         DEVOPENSTRUC                    vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  2608.         BITMAPINFOHEADER2               vBmpHdr;
  2609.         HBITMAP                         hBufBitmap;
  2610.         SIZEL                           vSize = {0, 0};
  2611.         LONG                            rc;
  2612.  
  2613.         memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
  2614.         vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
  2615.         vBmpHdr.cx        = vWidth;
  2616.         vBmpHdr.cy        = vHeight;
  2617.         vBmpHdr.cPlanes   = 1;
  2618.         vBmpHdr.cBitCount = 24;
  2619.  
  2620. #if wxUSE_DC_CACHEING
  2621.         if (TRUE)
  2622.         {
  2623.             //
  2624.             // create a temp buffer bitmap and DCs to access it and the mask
  2625.             //
  2626.             wxDCCacheEntry*         pDCCacheEntry1    = FindDCInCache( NULL
  2627.                                                                       ,pSource->GetHPS()
  2628.                                                                      );
  2629.             wxDCCacheEntry*         pDCCacheEntry2    = FindDCInCache( pDCCacheEntry1
  2630.                                                                       ,GetHPS()
  2631.                                                                      );
  2632.             wxDCCacheEntry*         pBitmapCacheEntry = FindBitmapInCache( GetHPS()
  2633.                                                                           ,vWidth
  2634.                                                                           ,vHeight
  2635.                                                                          );
  2636.  
  2637.             hPSMask = pDCCacheEntry1->m_hPS;
  2638.             hDCBuffer = (HDC)pDCCacheEntry2->m_hPS;
  2639.             hBufBitmap = (HBITMAP)pBitmapCacheEntry->m_hBitmap;
  2640.         }
  2641.         else
  2642. #endif
  2643.         {
  2644.             hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
  2645.             hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
  2646.             hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
  2647.             hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
  2648.             hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL);
  2649.         }
  2650.  
  2651.         POINTL                          aPoint1[4] = { 0, 0
  2652.                                                       ,vWidth, vHeight
  2653.                                                       ,vXdest, vYdest
  2654.                                                       ,vXdest + vWidth, vYdest + vHeight
  2655.                                                      };
  2656.         POINTL                          aPoint2[4] = { 0, 0
  2657.                                                       ,vWidth, vHeight
  2658.                                                       ,vXsrc, vYsrc
  2659.                                                       ,vXsrc + vWidth, vYsrc + vHeight
  2660.                                                      };
  2661.         POINTL                          aPoint3[4] = { vXdest, vYdest
  2662.                                                       ,vXdest + vWidth, vYdest + vHeight
  2663.                                                       ,vXsrc, vYsrc
  2664.                                                       ,vXsrc + vWidth, vYsrc + vHeight
  2665.                                                      };
  2666.         POINTL                          aPoint4[4] = { vXdest, vYdest
  2667.                                                       ,vXdest + vWidth, vYdest + vHeight
  2668.                                                       ,0, 0
  2669.                                                       ,vWidth, vHeight
  2670.                                                      };
  2671.         ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap());
  2672.         ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap);
  2673.  
  2674.         //
  2675.         // Copy dest to buffer
  2676.         //
  2677.         rc = ::GpiBitBlt( hPSBuffer
  2678.                          ,GetHPS()
  2679.                          ,4L
  2680.                          ,aPoint1
  2681.                          ,ROP_SRCCOPY
  2682.                          ,BBO_IGNORE
  2683.                         );
  2684.         if (rc == GPI_ERROR)
  2685.         {
  2686.             wxLogLastError(wxT("BitBlt"));
  2687.         }
  2688.  
  2689.         //
  2690.         // Copy src to buffer using selected raster op
  2691.         //
  2692.         rc = ::GpiBitBlt( hPSBuffer
  2693.                          ,GetHPS()
  2694.                          ,4L
  2695.                          ,aPoint2
  2696.                          ,lRop
  2697.                          ,BBO_IGNORE
  2698.                         );
  2699.         if (rc == GPI_ERROR)
  2700.         {
  2701.             wxLogLastError(wxT("BitBlt"));
  2702.         }
  2703.  
  2704.         //
  2705.         // Set masked area in buffer to BLACK (pixel value 0)
  2706.         //
  2707.         COLORREF                        vPrevBkCol = ::GpiQueryBackColor(GetHPS());
  2708.         COLORREF                        vPrevCol = ::GpiQueryColor(GetHPS());
  2709.  
  2710.         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255));
  2711.         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0));
  2712.  
  2713.         rc = ::GpiBitBlt( hPSBuffer
  2714.                          ,hPSMask
  2715.                          ,4L
  2716.                          ,aPoint2
  2717.                          ,ROP_SRCAND
  2718.                          ,BBO_IGNORE
  2719.                         );
  2720.         if (rc == GPI_ERROR)
  2721.         {
  2722.             wxLogLastError(wxT("BitBlt"));
  2723.         }
  2724.  
  2725.         //
  2726.         // Set unmasked area in dest to BLACK
  2727.         //
  2728.         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0));
  2729.         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255));
  2730.         rc = ::GpiBitBlt( GetHPS()
  2731.                          ,hPSMask
  2732.                          ,4L
  2733.                          ,aPoint3
  2734.                          ,ROP_SRCAND
  2735.                          ,BBO_IGNORE
  2736.                         );
  2737.         if (rc == GPI_ERROR)
  2738.         {
  2739.             wxLogLastError(wxT("BitBlt"));
  2740.         }
  2741.  
  2742.         //
  2743.         // Restore colours to original values
  2744.         //
  2745.         ::GpiSetBackColor(GetHPS(), vPrevBkCol);
  2746.         ::GpiSetColor(GetHPS(), vPrevCol);
  2747.  
  2748.         //
  2749.         // OR buffer to dest
  2750.         //
  2751.         rc = ::GpiBitBlt( GetHPS()
  2752.                          ,hPSMask
  2753.                          ,4L
  2754.                          ,aPoint4
  2755.                          ,ROP_SRCPAINT
  2756.                          ,BBO_IGNORE
  2757.                         );
  2758.         if (rc == GPI_ERROR)
  2759.         {
  2760.             bSuccess = FALSE;
  2761.             wxLogLastError(wxT("BitBlt"));
  2762.         }
  2763.  
  2764.         //
  2765.         // Tidy up temporary DCs and bitmap
  2766.         //
  2767.         ::GpiSetBitmap(hPSMask, NULLHANDLE);
  2768.         ::GpiSetBitmap(hPSBuffer, NULLHANDLE);
  2769. #if !wxUSE_DC_CACHEING
  2770.         ::GpiDestroyPS(hPSMask);
  2771.         ::GpiDestroyPS(hPSBuffer);
  2772.         ::DevCloseDC(hDCMask);
  2773.         ::DevCloseDC(hDCBuffer);
  2774.         ::GpiDeleteBitmap(hBufBitmap);
  2775. #endif
  2776.         bSuccess = TRUE;
  2777.     }
  2778.     else // no mask, just BitBlt() it
  2779.     {
  2780.         POINTL                          aPoint[4] = { vXdest, vYdest
  2781.                                                      ,vXdest + vWidth, vYdest + vHeight
  2782.                                                      ,vXsrc, vYsrc
  2783.                                                      ,vXsrc + vWidth, vYsrc + vHeight
  2784.                                                     };
  2785.  
  2786.         bSuccess = (::GpiBitBlt( m_hPS
  2787.                                 ,pSource->GetHPS()
  2788.                                 ,4L
  2789.                                 ,aPoint
  2790.                                 ,lRop
  2791.                                 ,BBO_IGNORE
  2792.                                ) != GPI_ERROR);
  2793.         if (!bSuccess )
  2794.         {
  2795.             wxLogLastError(wxT("BitBlt"));
  2796.         }
  2797.     }
  2798.     vCbnd.lColor = (LONG)vOldTextColor;
  2799.     ::GpiSetAttrs( m_hPS           // presentation-space handle
  2800.                   ,PRIM_CHAR       // Char primitive.
  2801.                   ,CBB_COLOR       // sets color.
  2802.                   ,0
  2803.                   ,&vCbnd          // buffer for attributes.
  2804.                  );
  2805.     ::GpiSetBackColor(m_hPS, (LONG)vOldBackground);
  2806.     return bSuccess;
  2807. }
  2808.  
  2809. void wxDC::DoGetSize(
  2810.   int*                              pnWidth
  2811. , int*                              pnHeight
  2812. ) const
  2813. {
  2814.     LONG                            lArray[CAPS_HEIGHT];
  2815.  
  2816.     if(::DevQueryCaps( m_hDC
  2817.                       ,CAPS_FAMILY
  2818.                       ,CAPS_HEIGHT
  2819.                       ,lArray
  2820.                      ))
  2821.     {
  2822.         *pnWidth  = lArray[CAPS_WIDTH];
  2823.         *pnHeight = lArray[CAPS_HEIGHT];
  2824.     }
  2825. }; // end of wxDC::DoGetSize(
  2826.  
  2827. void wxDC::DoGetSizeMM(
  2828.   int*                              pnWidth
  2829. , int*                              pnHeight
  2830. ) const
  2831. {
  2832.     LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
  2833.  
  2834.     if(::DevQueryCaps( m_hDC
  2835.                       ,CAPS_FAMILY
  2836.                       ,CAPS_VERTICAL_RESOLUTION
  2837.                       ,lArray
  2838.                      ))
  2839.     {
  2840.         int                         nWidth;
  2841.         int                         nHeight;
  2842.         int                         nHorzRes;
  2843.         int                         nVertRes;
  2844.  
  2845.         nWidth    = lArray[CAPS_WIDTH];
  2846.         nHeight   = lArray[CAPS_HEIGHT];
  2847.         nHorzRes  = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
  2848.         nVertRes  = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
  2849.         nWidth  = (nHorzRes/1000) * nWidth;
  2850.         nHeight = (nVertRes/1000) * nHeight;
  2851.     }
  2852. }; // end of wxDC::DoGetSizeMM
  2853.  
  2854. wxSize wxDC::GetPPI() const
  2855. {
  2856.     LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
  2857.     int                             nWidth;
  2858.     int                             nHeight;
  2859.  
  2860.     if(::DevQueryCaps( m_hDC
  2861.                       ,CAPS_FAMILY
  2862.                       ,CAPS_VERTICAL_RESOLUTION
  2863.                       ,lArray
  2864.                      ))
  2865.     {
  2866.         int                         nPelWidth;
  2867.         int                         nPelHeight;
  2868.         int                         nHorzRes;
  2869.         int                         nVertRes;
  2870.  
  2871.         nPelWidth  = lArray[CAPS_WIDTH];
  2872.         nPelHeight = lArray[CAPS_HEIGHT];
  2873.         nHorzRes   = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
  2874.         nVertRes   = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
  2875.         nWidth   = (nHorzRes/39.3) * nPelWidth;
  2876.         nHeight  = (nVertRes/39.3) * nPelHeight;
  2877.     }
  2878.     return (wxSize(nWidth,nHeight));
  2879. } // end of wxDC::GetPPI
  2880.  
  2881. void wxDC::SetLogicalScale(
  2882.   double                            dX
  2883. , double                            dY
  2884. )
  2885. {
  2886.     m_logicalScaleX = dX;
  2887.     m_logicalScaleY = dY;
  2888. }; // end of wxDC::SetLogicalScale
  2889.  
  2890. #if WXWIN_COMPATIBILITY
  2891. void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
  2892.                          float *descent, float *externalLeading,
  2893.                          wxFont *theFont, bool use16bit) const
  2894. {
  2895.     wxCoord x1, y1, descent1, externalLeading1;
  2896.     GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
  2897.     *x = x1; *y = y1;
  2898.     if (descent)
  2899.         *descent = descent1;
  2900.     if (externalLeading)
  2901.         *externalLeading = externalLeading1;
  2902. }
  2903. #endif
  2904.  
  2905.