1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  16     #include "wx/window.h" 
  19     #include "wx/dialog.h" 
  21     #include "wx/bitmap.h" 
  22     #include "wx/dcmemory.h" 
  25     #include "wx/msgdlg.h" 
  27     #include "wx/statusbr.h" 
  31 #include "wx/module.h" 
  32 #include "wx/dcprint.h" 
  36 #include "wx/os2/private.h" 
  38     IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  41 // wxWidgets uses the Microsoft convention that the origin is the UPPER left. 
  42 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  43 // In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 
  44 // perform the following transformation: 
  46 // Parent object height:     POBJHEIGHT 
  47 // Desried origin:           WXORIGINY 
  48 // Object to place's height: OBJHEIGHT 
  50 // To get the OS2 position from the wxWidgets one: 
  52 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  54 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  55 // OS/2 Presentation Space associated with the device context.  y is the 
  56 // desired application's y coordinate of the origin in wxWidgets space. 
  57 // objy is the height of the object we are going to draw. 
  59 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  61 // --------------------------------------------------------------------------- 
  63 // --------------------------------------------------------------------------- 
  65 static const int VIEWPORT_EXTENT 
= 1000; 
  67 static const int MM_POINTS 
= 9; 
  68 static const int MM_METRIC 
= 10; 
  70 // --------------------------------------------------------------------------- 
  72 // --------------------------------------------------------------------------- 
  74 // convert degrees to radians 
  75 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  79 , int                               nForegroundColour
 
  84     vCbnd
.lColor 
=  nForegroundColour
; 
  85     ::GpiSetAttrs( hPS       
// presentation-space handle 
  86                   ,PRIM_CHAR 
// Char primitive. 
  87                   ,CBB_COLOR 
// sets color. 
  89                   ,&vCbnd    
// buffer for attributes. 
 100     ::GpiQueryAttrs( hPS            
// presentation-space handle 
 101                     ,PRIM_CHAR      
// Char primitive. 
 102                     ,CBB_BACK_COLOR 
// Background color. 
 103                     ,&vCbnd         
// buffer for attributes. 
 105     return vCbnd
.lBackColor
; 
 111 , int                               nBackgroundColour
 
 117     rc 
=  QueryTextBkColor(hPS
); 
 119     vCbnd
.lBackColor 
= nBackgroundColour
; 
 120     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 121                   PRIM_CHAR
,      // Char primitive. 
 122                   CBB_BACK_COLOR
, // sets color. 
 124                   &vCbnd          
// buffer for attributes. 
 131 , int                               nBackgroundMode
 
 134     if(nBackgroundMode 
== wxTRANSPARENT
) 
 139         // the background of the primitive takes  over whatever is underneath. 
 146 // =========================================================================== 
 148 // =========================================================================== 
 150 #if wxUSE_DC_CACHEING 
 153  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 154  * improve it in due course, either using arrays, or simply storing pointers to one 
 155  * entry for the bitmap, and two for the DCs. -- JACS 
 158 // --------------------------------------------------------------------------- 
 160 // --------------------------------------------------------------------------- 
 162 wxList 
wxDC::m_svBitmapCache
; 
 163 wxList 
wxDC::m_svDCCache
; 
 165 wxDCCacheEntry::wxDCCacheEntry( 
 177 } // end of wxDCCacheEntry::wxDCCacheEntry 
 179 wxDCCacheEntry::wxDCCacheEntry( 
 184     m_hBitmap 
= NULLHANDLE
; 
 189 } // end of wxDCCacheEntry::wxDCCacheEntry 
 191 wxDCCacheEntry::~wxDCCacheEntry() 
 194         ::GpiDeleteBitmap(m_hBitmap
); 
 196         ::GpiDestroyPS(m_hPS
); 
 197 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 199 wxDCCacheEntry
* wxDC::FindBitmapInCache( 
 205     int                             nDepth 
= 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 206     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 207     BITMAPINFOHEADER2               vBmpHdr
; 
 211         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 213         if (pEntry
->m_nDepth 
== nDepth
) 
 215             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 217             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 219                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 220                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 222                 vBmpHdr
.cy        
= nHeight
; 
 224                 vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 226                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 230                 if (!pEntry
->m_hBitmap
) 
 232                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 234                 pEntry
->m_nWidth  
= nWidth
; 
 235                 pEntry
->m_nHeight 
= nHeight
; 
 240         pNode 
= pNode
->Next(); 
 242     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 243     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 245     vBmpHdr
.cy        
= nHeight
; 
 247     vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 249     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 255         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 257     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 262     AddToBitmapCache(pEntry
); 
 264 } // end of FindBitmapInCache 
 266 wxDCCacheEntry
* wxDC::FindDCInCache( 
 267   wxDCCacheEntry
*                   pNotThis
 
 271     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 272     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 276         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 279         // Don't return the same one as we already have 
 281         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 283             if (pEntry
->m_nDepth 
== nDepth
) 
 288         pNode 
= pNode
->Next(); 
 290     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 293     AddToDCCache(pEntry
); 
 295 } // end of wxDC::FindDCInCache 
 297 void wxDC::AddToBitmapCache( 
 298   wxDCCacheEntry
*                   pEntry
 
 301     m_svBitmapCache
.Append(pEntry
); 
 302 } // end of wxDC::AddToBitmapCache 
 304 void wxDC::AddToDCCache( 
 305   wxDCCacheEntry
*                   pEntry
 
 308     m_svDCCache
.Append(pEntry
); 
 309 } // end of wxDC::AddToDCCache 
 311 void wxDC::ClearCache() 
 313     m_svBitmapCache
.DeleteContents(true); 
 314     m_svBitmapCache
.Clear(); 
 315     m_svBitmapCache
.DeleteContents(false); 
 316     m_svDCCache
.DeleteContents(true); 
 318     m_svDCCache
.DeleteContents(false); 
 319 } // end of wxDC::ClearCache 
 321 // Clean up cache at app exit 
 322 class wxDCModule 
: public wxModule
 
 325     virtual bool OnInit() { return true; } 
 326     virtual void OnExit() { wxDC::ClearCache(); } 
 329     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 330 }; // end of CLASS wxDCModule 
 332 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 334 #endif // ndef for wxUSE_DC_CACHEING 
 336 // --------------------------------------------------------------------------- 
 338 // --------------------------------------------------------------------------- 
 354     m_bIsPaintTime 
= false; // True at Paint Time 
 356     wxColour 
vColor( wxT("BLACK") ); 
 357     m_pen
.SetColour(vColor
); 
 359     vColor
.Set( wxT("WHITE") ); 
 360     m_brush
.SetColour(vColor
); 
 362 } // end of wxDC::wxDC 
 368         SelectOldObjects(m_hDC
); 
 370         // if we own the HDC, we delete it, otherwise we just release it 
 376                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 377                 ::GpiDestroyPS(m_hPS
); 
 380             ::DevCloseDC((HDC
)m_hDC
); 
 385             // Just Dissacociate, not destroy if we don't own the DC 
 389                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 393 } // end of wxDC::~wxDC 
 395 // This will select current objects out of the DC, 
 396 // which is what you have to do before deleting the 
 398 void wxDC::SelectOldObjects( 
 406             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 407             if (m_vSelectedBitmap
.Ok()) 
 409                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 414         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 422     m_brush           
= wxNullBrush
; 
 424     m_palette         
= wxNullPalette
; 
 426     m_backgroundBrush 
= wxNullBrush
; 
 427     m_vSelectedBitmap 
= wxNullBitmap
; 
 428 } // end of wxDC::SelectOldObjects 
 430 // --------------------------------------------------------------------------- 
 432 // --------------------------------------------------------------------------- 
 434 #define DO_SET_CLIPPING_BOX()                    \ 
 438     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 440     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 441     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 442     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 443     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 446 void wxDC::DoSetClippingRegion( 
 455     vY 
= OS2Y(vY
,vHeight
); 
 458     vRect
.yTop    
= vY 
+ vHeight
; 
 459     vRect
.xRight  
= vX 
+ vWidth
; 
 461     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 462     DO_SET_CLIPPING_BOX() 
 463 } // end of wxDC::DoSetClippingRegion 
 465 void wxDC::DoSetClippingRegionAsRegion( 
 466   const wxRegion
&                   rRegion
 
 469      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 473      ::GpiSetClipRegion( m_hPS
 
 474                         ,(HRGN
)rRegion
.GetHRGN() 
 477     DO_SET_CLIPPING_BOX() 
 478 } // end of wxDC::DoSetClippingRegionAsRegion 
 480 void wxDC::DestroyClippingRegion(void) 
 482     if (m_clipping 
&& m_hPS
) 
 487          // TODO: this should restore the previous clipped region 
 488          //       so that OnPaint processing works correctly, and 
 489          //       the update doesn't get destroyed after the first 
 490          //       DestroyClippingRegion 
 491          vRect
.xLeft   
= XLOG2DEV(0); 
 492          vRect
.yTop    
= YLOG2DEV(32000); 
 493          vRect
.xRight  
= XLOG2DEV(32000); 
 494          vRect
.yBottom 
= YLOG2DEV(0); 
 496          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 498          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 501 } // end of wxDC::DestroyClippingRegion 
 503 // --------------------------------------------------------------------------- 
 504 // query capabilities 
 505 // --------------------------------------------------------------------------- 
 507 bool wxDC::CanDrawBitmap() const 
 512 bool wxDC::CanGetTextExtent() const 
 514     LONG                            lTechnology 
= 0L; 
 516     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 517     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 518 } // end of wxDC::CanGetTextExtent 
 520 int wxDC::GetDepth() const 
 522     LONG                            lArray
[CAPS_COLOR_BITCOUNT
]; 
 523     int                             nBitsPerPixel 
= 0; 
 525     if(::DevQueryCaps( GetHDC() 
 531         nBitsPerPixel 
= (int)lArray
[CAPS_COLOR_BITCOUNT
]; 
 533     return nBitsPerPixel
; 
 534 } // end of wxDC::GetDepth 
 536 // --------------------------------------------------------------------------- 
 538 // --------------------------------------------------------------------------- 
 543     // If this is a canvas DC then just fill with the background color 
 544     // Otherwise purge the whole thing 
 550         ::GpiQueryClipBox(m_hPS
, &vRect
); 
 551         ::WinFillRect(m_hPS
, &vRect
, ::GpiQueryBackColor(m_hPS
)); 
 555 } // end of wxDC::Clear 
 557 bool wxDC::DoFloodFill( 
 560 , const wxColour
&                   rCol
 
 568     bool                            bSuccess 
= false; 
 570     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 571     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 572     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 573     lColor 
= rCol
.GetPixel(); 
 574     lOptions 
= FF_BOUNDARY
; 
 575     if(wxFLOOD_SURFACE 
== nStyle
) 
 576         lOptions 
= FF_SURFACE
; 
 578     if ((lHits 
= ::GpiFloodFill(m_hPS
, lOptions
, lColor
)) != GPI_ERROR
) 
 582 } // end of wxDC::DoFloodFill 
 584 bool wxDC::DoGetPixel( 
 594     vPoint
.y 
= OS2Y(vY
,0); 
 595     lColor 
= ::GpiQueryPel(m_hPS
, &vPoint
); 
 598     // return the color of the pixel 
 601         pCol
->Set( GetRValue(lColor
) 
 606 } // end of wxDC::DoGetPixel 
 608 void wxDC::DoCrossHair( 
 615     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 616     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 617     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 618     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 627     ::GpiMove(m_hPS
, &vPoint
[0]); 
 628     ::GpiLine(m_hPS
, &vPoint
[1]); 
 636     ::GpiMove(m_hPS
, &vPoint
[2]); 
 637     ::GpiLine(m_hPS
, &vPoint
[3]); 
 638     CalcBoundingBox(vX1
, vY1
); 
 639     CalcBoundingBox(vX2
, vY2
); 
 640 } // end of wxDC::DoCrossHair 
 642 void wxDC::DoDrawLine( 
 650     COLORREF                        vColor 
= 0x00ffffff; 
 653     // Might be a memory DC with no Paint rect. 
 655     if (!(m_vRclPaint
.yTop 
== 0 && 
 656           m_vRclPaint
.yBottom 
== 0 && 
 657           m_vRclPaint
.xRight 
== 0 && 
 658           m_vRclPaint
.xLeft 
== 0)) 
 665         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
 667             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 668             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 679         vColor 
= m_pen
.GetColour().GetPixel(); 
 681     ::GpiSetColor(m_hPS
, vColor
); 
 682     ::GpiMove(m_hPS
, &vPoint
[0]); 
 683     ::GpiLine(m_hPS
, &vPoint
[1]); 
 684     CalcBoundingBox(vX1
, vY1
); 
 685     CalcBoundingBox(vX2
, vY2
); 
 686 } // end of wxDC::DoDrawLine 
 688 ////////////////////////////////////////////////////////////////////////////// 
 689 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 690 // and ending at (x2, y2). The current pen is used for the outline and the 
 691 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 692 // direction from the start point to the end point. 
 693 ////////////////////////////////////////////////////////////////////////////// 
 694 void wxDC::DoDrawArc( 
 704      POINTL                         vPtlArc
[2]; // Structure for current position 
 711      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 713     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 714         return; // Draw point ?? 
 715     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 718                       hypot( (double)(vY2 
- vYc
) 
 723     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 726     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 733     // GpiPointArc can't draw full arc 
 735      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 740         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 741         vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 742         vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 757     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 758     vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 759     vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 762     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 768     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 770     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 771     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 772     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 777 #if !(defined(__WATCOMC__) && __WATCOMC__ < 1240 ) 
 778 // Open Watcom 1.3 had incomplete headers 
 779 // that's reported and should be fixed for OW 1.4 
 780     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 782     CalcBoundingBox( (wxCoord
)(vXc 
- dRadius
) 
 783                     ,(wxCoord
)(vYc 
- dRadius
) 
 785     CalcBoundingBox( (wxCoord
)(vXc 
+ dRadius
) 
 786                     ,(wxCoord
)(vYc 
+ dRadius
) 
 788 } // end of wxDC::DoDrawArc 
 790 void wxDC::DoDrawCheckMark( 
 799     vY1 
= OS2Y(vY1
,vHeight
); 
 803     vPoint
[1].x 
= vX1 
+ vWidth
; 
 804     vPoint
[1].y 
= vY1 
+ vHeight
; 
 806     ::GpiMove(m_hPS
, &vPoint
[0]); 
 807     ::GpiBox( m_hPS       
// handle to a presentation space 
 808              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 809              ,&vPoint
[1]  // address of the corner 
 810              ,0L          // horizontal corner radius 
 811              ,0L          // vertical corner radius 
 813     if(vWidth 
> 4 && vHeight 
> 4) 
 817         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 818         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 819         ::GpiMove(m_hPS
, &vPoint
[0]); 
 820         ::GpiLine(m_hPS
, &vPoint
[1]); 
 822         vPoint
[0].x 
= vPoint
[1].x
; 
 824         ::GpiMove(m_hPS
, &vPoint
[0]); 
 825         ::GpiLine(m_hPS
, &vPoint
[1]); 
 831     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 832     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 837 } // end of wxDC::DoDrawCheckMark 
 839 void wxDC::DoDrawPoint( 
 845     COLORREF                        vColor 
= 0x00ffffff; 
 849         vColor 
= m_pen
.GetColour().GetPixel(); 
 851     ::GpiSetColor(m_hPS
, vColor
); 
 853     vPoint
.y 
= OS2Y(vY
,0); 
 854     ::GpiSetPel(m_hPS
, &vPoint
); 
 858 } // end of wxDC::DoDrawPoint 
 860 void wxDC::DoDrawPolygon( 
 868     ULONG                           ulCount 
= 1;    // Number of polygons. 
 869     POLYGON                         vPlgn
;          // polygon. 
 870     ULONG                           flOptions 
= 0L; // Drawing options. 
 872 ////////////////////////////////////////////////////////////////////////////// 
 873 // This contains fields of option bits... to draw boundary lines as well as 
 874 // the area interior. 
 876 // Drawing boundary lines: 
 877 //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 878 //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 880 // Construction of the area interior: 
 881 //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 883 //   POLYGON_WINDING                 Constructs interior in winding mode. 
 884 ////////////////////////////////////////////////////////////////////////////// 
 886     ULONG                           flModel 
= 0L; // Drawing model. 
 888 ////////////////////////////////////////////////////////////////////////////// 
 890 //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 891 //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 892 //       This is provided to aid migration from other graphics models. 
 893 ////////////////////////////////////////////////////////////////////////////// 
 895     LONG                            lHits 
= 0L; // Correlation/error indicator. 
 898     int                             nIsTRANSPARENT 
= 0; 
 899     LONG                            lBorderColor 
= 0L; 
 902     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 903     lColor       
= m_brush
.GetColour().GetPixel(); 
 904     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 908     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 910                                     ); // well, new will call malloc 
 912     for(i 
= 0; i 
< n
; i
++) 
 914         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
;         // +xoffset; 
 915         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
,0); // +yoffset; 
 917     flModel 
= POLYGON_BOUNDARY
; 
 918     if(nFillStyle 
== wxWINDING_RULE
) 
 919         flModel 
|= POLYGON_WINDING
; 
 921         flModel 
|= POLYGON_ALTERNATE
; 
 924     vPoint
.y 
= OS2Y(vYoffset
,0); 
 926     ::GpiSetColor(m_hPS
, lBorderColor
); 
 927     ::GpiMove(m_hPS
, &vPoint
); 
 928     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 930 } // end of wxDC::DoDrawPolygon 
 932 void wxDC::DoDrawLines( 
 941     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 945         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 946         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 947         ::GpiMove(m_hPS
, &vPoint
); 
 949         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 951         ::GpiSetColor(m_hPS
, lBorderColor
); 
 952         for(i 
= 1; i 
< n
; i
++) 
 954             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 955             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 956             ::GpiLine(m_hPS
, &vPoint
); 
 963         CalcBoundingBox( vPoints
[0].x
 
 966         vPoint
.x 
= vPoints
[0].x
; 
 967         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 968         ::GpiMove(m_hPS
, &vPoint
); 
 970         for (i 
= 0; i 
< n
; i
++) 
 972             CalcBoundingBox( vPoints
[i
].x
 
 975             vPoint
.x 
= vPoints
[i
].x
; 
 976             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 977             ::GpiLine(m_hPS
, &vPoint
); 
 980 } // end of wxDC::DoDrawLines 
 982 void wxDC::DoDrawRectangle( 
 993     int                             nIsTRANSPARENT 
= 0; 
 996     // Might be a memory DC with no Paint rect. 
 998     if (!(m_vRclPaint
.yTop 
== 0 && 
 999           m_vRclPaint
.yBottom 
== 0 && 
1000           m_vRclPaint
.xRight 
== 0 && 
1001           m_vRclPaint
.xLeft 
== 0)) 
1002         vY 
= OS2Y(vY
,vHeight
); 
1005         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1007             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1008             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1009             vY 
= OS2Y(vY
,vHeight
); 
1013     wxCoord                         vX2 
= vX 
+ vWidth
; 
1014     wxCoord                         vY2 
= vY 
+ vHeight
; 
1018     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1019     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1020     ::GpiMove(m_hPS
, &vPoint
[0]); 
1021     lColor       
= m_brush
.GetColour().GetPixel(); 
1022     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1023     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1025     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1027         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1028         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1029             lControl 
= DRO_OUTLINE
; 
1031         ::GpiSetColor(m_hPS
, lBorderColor
); 
1032         ::GpiBox( m_hPS       
// handle to a presentation space 
1033                  ,lControl   
// draw the box outline ? or ? 
1034                  ,&vPoint
[1]  // address of the corner 
1035                  ,0L          // horizontal corner radius 
1036                  ,0L          // vertical corner radius 
1041         lControl 
= DRO_OUTLINE
; 
1042         ::GpiSetColor( m_hPS
 
1051         lControl 
= DRO_FILL
; 
1052         ::GpiSetColor( m_hPS
 
1055         vPoint
[0].x 
= vX 
+ 1; 
1056         vPoint
[0].y 
= vY 
+ 1; 
1057         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1058         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1059         ::GpiMove(m_hPS
, &vPoint
[0]); 
1067     CalcBoundingBox(vX
, vY
); 
1068     CalcBoundingBox(vX2
, vY2
); 
1069 } // end of wxDC::DoDrawRectangle 
1071 void wxDC::DoDrawRoundedRectangle( 
1083     int                             nIsTRANSPARENT 
= 0; 
1086     // Might be a memory DC with no Paint rect. 
1088     if (!(m_vRclPaint
.yTop 
== 0 && 
1089           m_vRclPaint
.yBottom 
== 0 && 
1090           m_vRclPaint
.xRight 
== 0 && 
1091           m_vRclPaint
.xLeft 
== 0)) 
1092         vY 
= OS2Y(vY
,vHeight
); 
1095         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1097             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1098             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1099             vY 
= OS2Y(vY
,vHeight
); 
1103     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1104     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1108     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1109     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1110     ::GpiMove(m_hPS
, &vPoint
[0]); 
1112     lColor       
= m_brush
.GetColour().GetPixel(); 
1113     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1114     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1115     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1117     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1119         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1120         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1121             lControl 
= DRO_OUTLINE
; 
1123         ::GpiSetColor(m_hPS
, lColor
); 
1124         ::GpiBox( m_hPS         
// handle to a presentation space 
1125                  ,lControl      
// draw the box outline ? or ? 
1126                  ,&vPoint
[1]    // address of the corner 
1127                  ,(LONG
)dRadius 
// horizontal corner radius 
1128                  ,(LONG
)dRadius 
// vertical corner radius 
1133         lControl 
= DRO_OUTLINE
; 
1134         ::GpiSetColor( m_hPS
 
1143         lControl 
= DRO_FILL
; 
1144         ::GpiSetColor( m_hPS
 
1147         vPoint
[0].x 
= vX 
+ 1; 
1148         vPoint
[0].y 
= vY 
+ 1; 
1149         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1150         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1151         ::GpiMove(m_hPS
, &vPoint
[0]); 
1160     CalcBoundingBox(vX
, vY
); 
1161     CalcBoundingBox(vX2
, vY2
); 
1162 } // end of wxDC::DoDrawRoundedRectangle 
1164 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1165 void wxDC::DoDrawEllipse( 
1172     POINTL                          vPtlPos
; // Structure for current position 
1173     FIXED                           vFxMult
; // Multiplier for ellipse 
1174     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1176     vY 
= OS2Y(vY
,vHeight
); 
1179     vArcp
.lQ 
= vHeight
/2; 
1180     vArcp
.lP 
= vWidth
/2; 
1182     ::GpiSetArcParams( m_hPS
 
1184                      ); // Sets parameters to default 
1185     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1186     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1189              ); // Sets current position 
1190     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1193     // DRO_FILL, DRO_OTLINEFILL - where to get 
1198                 ); // Draws full arc with center at current position 
1200     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1201     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1203     CalcBoundingBox(vX
, vY
); 
1204     CalcBoundingBox(vX2
, vY2
); 
1205 } // end of wxDC::DoDrawEllipse 
1207 void wxDC::DoDrawEllipticArc( 
1216     POINTL                          vPtlPos
; // Structure for current position 
1217     FIXED                           vFxMult
; // Multiplier for ellipse 
1218     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1220     FIXED                           vFSweepa
; // Start angle, sweep angle 
1224     vY 
= OS2Y(vY
,vHeight
); 
1226     dFractPart 
= modf(dSa
,&dIntPart
); 
1227     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1228     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1229     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1232     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1235     vArcp
.lQ 
= vHeight
/2; 
1236     vArcp
.lP 
= vWidth
/2; 
1238     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1239     vPtlPos
.x 
= (wxCoord
)(vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
)))); // Loads x-coordinate 
1240     vPtlPos
.y 
= (wxCoord
)(vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
)))); // Loads y-coordinate 
1241     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1244     // May be not to the center ? 
1246     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1247     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1248     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1251     // DRO_FILL, DRO_OTLINEFILL - where to get 
1253     ::GpiPartialArc( m_hPS
 
1259     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1260     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1262     CalcBoundingBox(vX
, vY
); 
1263     CalcBoundingBox(vX2
, vY2
); 
1264 } // end of wxDC::DoDrawEllipticArc 
1266 void wxDC::DoDrawIcon( 
1273     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords 
1274     // and I don't feel like figuring those out for scrollable windows so 
1275     // just convert to a bitmap then let the DoDrawBitmap routing display it 
1279         DoDrawBitmap(rIcon
.GetXpmSrc(), vX
, vY
, true); 
1283         wxBitmap                        
vBitmap(rIcon
); 
1285         DoDrawBitmap(vBitmap
, vX
, vY
, false); 
1287     CalcBoundingBox(vX
, vY
); 
1288     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1289 } // end of wxDC::DoDrawIcon 
1291 void wxDC::DoDrawBitmap( 
1292   const wxBitmap
&                   rBmp
 
1298 #if wxUSE_PRINTING_ARCHITECTURE 
1299     if (!IsKindOf(CLASSINFO(wxPrinterDC
))) 
1302         HBITMAP                         hBitmap 
=  (HBITMAP
)rBmp
.GetHBITMAP(); 
1303         HBITMAP                         hBitmapOld 
= NULLHANDLE
; 
1306         vY 
= OS2Y(vY
,rBmp
.GetHeight()); 
1309         vPoint
[0].y 
= vY 
+ rBmp
.GetHeight(); 
1310         vPoint
[1].x 
= vX 
+ rBmp
.GetWidth(); 
1314         vPoint
[3].x 
= rBmp
.GetWidth(); 
1315         vPoint
[3].y 
= rBmp
.GetHeight(); 
1318             wxMask
*                     pMask 
= rBmp
.GetMask(); 
1323                 // Need to imitate ::MaskBlt in windows. 
1324                 // 1) Extract the bits from from the bitmap. 
1325                 // 2) Extract the bits from the mask 
1326                 // 3) Using the mask bits do the following: 
1327                 //   A) If the mask byte is 00 leave the bitmap byte alone 
1328                 //   B) If the mask byte is FF copy the screen color into 
1330                 // 4) Create a new bitmap and set its bits to the above result 
1331                 // 5) Blit this to the screen PS 
1333                 HBITMAP                 hMask 
= (HBITMAP
)pMask
->GetMaskBitmap(); 
1334                 HBITMAP                 hOldMask   
= NULLHANDLE
; 
1335                 HBITMAP                 hOldBitmap 
= NULLHANDLE
; 
1336                 HBITMAP                 hNewBitmap 
= NULLHANDLE
; 
1337                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1338                 unsigned char*          pucBitsMask
; // buffer that will contain the mask data 
1339                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1340                 unsigned char*          pucDataMask
; // pointer to use to traverse mask data 
1346                 // The usual Memory context creation stuff 
1348                 DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1349                 SIZEL                           vSize 
= {0, 0}; 
1350                 HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1351                 HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1354                 // The usual bitmap header stuff 
1356                 BITMAPINFOHEADER2               vHeader
; 
1359                 memset(&vHeader
, '\0', 16); 
1362                 memset(&vInfo
, '\0', 16); 
1364                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1365                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1367                 vInfo
.cBitCount       
= 24; // Set to desired count going in 
1370                 // Create the buffers for data....all wxBitmaps are 24 bit internally 
1372                 int                     nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1373                 int                     nSizeDWORD    
= sizeof(DWORD
); 
1374                 int                     nLineBoundary 
= nBytesPerLine 
% nSizeDWORD
; 
1382                 // Need to get a background color for mask blitting 
1384                 if (IsKindOf(CLASSINFO(wxWindowDC
))) 
1386                     wxWindowDC
*             pWindowDC 
= wxDynamicCast(this, wxWindowDC
); 
1388                     lColor 
= pWindowDC
->m_pCanvas
->GetBackgroundColour().GetPixel(); 
1390                 else if (GetBrush().Ok()) 
1391                     lColor 
= GetBrush().GetColour().GetPixel(); 
1393                     lColor 
= m_textBackgroundColour
.GetPixel(); 
1396                 // Bitmap must be in a double-word aligned address so we may 
1397                 // have some padding to worry about 
1399                 if (nLineBoundary 
> 0) 
1401                     nPadding     
= nSizeDWORD 
- nLineBoundary
; 
1402                     nBytesPerLine 
+= nPadding
; 
1404                 pucBits 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1405                 pucBitsMask 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1406                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1407                 memset(pucBitsMask
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1410                 // Extract the bitmap and mask data 
1412                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1414                     vError 
= ::WinGetLastError(vHabmain
); 
1415                     sError 
= wxPMErrorToStr(vError
); 
1417                 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
); 
1418                 vInfo
.cBitCount 
= 24; 
1419                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1421                                                    ,(LONG
)rBmp
.GetHeight() 
1426                     vError 
= ::WinGetLastError(vHabmain
); 
1427                     sError 
= wxPMErrorToStr(vError
); 
1429                 if ((hOldMask 
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
) 
1431                     vError 
= ::WinGetLastError(vHabmain
); 
1432                     sError 
= wxPMErrorToStr(vError
); 
1434                 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
); 
1435                 vInfo
.cBitCount 
= 24; 
1436                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1438                                                    ,(LONG
)rBmp
.GetHeight() 
1443                     vError 
= ::WinGetLastError(vHabmain
); 
1444                     sError 
= wxPMErrorToStr(vError
); 
1446                 if (( hMask 
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
) 
1448                     vError 
= ::WinGetLastError(vHabmain
); 
1449                     sError 
= wxPMErrorToStr(vError
); 
1453                 // Now set the bytes(bits) according to the mask values 
1454                 // 3 bytes per pel...must handle one at a time 
1457                 pucDataMask 
= pucBitsMask
; 
1460                 // 16 bit kludge really only kinda works.  The mask gets applied 
1461                 // where needed but the original bitmap bits are dorked sometimes 
1463                 bool                    bpp16 
= (wxDisplayDepth() == 16); 
1465                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1467                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1470                         if (bpp16 
&& *pucDataMask 
== 0xF8) // 16 bit display gobblygook 
1472                         else if (*pucDataMask 
== 0xFF) // leave bitmap byte alone 
1476                             *pucData 
= ((unsigned char)(lColor 
>> 16)); 
1480                         if (bpp16 
&& *(pucDataMask 
+ 1) == 0xFC) // 16 bit display gobblygook 
1482                         else if (*(pucDataMask 
+ 1) == 0xFF) // leave bitmap byte alone 
1486                             *pucData 
= ((unsigned char)(lColor 
>> 8)); 
1491                         if (bpp16 
&& *(pucDataMask 
+ 2) == 0xF8) // 16 bit display gobblygook 
1493                         else if (*(pucDataMask 
+ 2) == 0xFF) // leave bitmap byte alone 
1497                             *pucData 
= ((unsigned char)lColor
); 
1502                     for (j 
= 0; j 
< nPadding
; j
++) 
1509                 // Create a new bitmap 
1511                 vHeader
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1512                 vHeader
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1513                 vHeader
.cPlanes         
= 1L; 
1514                 vHeader
.cBitCount       
= 24; 
1515                 if ((hNewBitmap 
= ::GpiCreateBitmap( hPS
 
1522                     vError 
= ::WinGetLastError(vHabmain
); 
1523                     sError 
= wxPMErrorToStr(vError
); 
1527                 // Now blit it to the screen PS 
1529                 if ((lHits 
= ::GpiWCBitBlt( (HPS
)GetHPS() 
1537                     vError 
= ::WinGetLastError(vHabmain
); 
1538                     sError 
= wxPMErrorToStr(vError
); 
1546                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1547                 ::GpiDeleteBitmap(hNewBitmap
); 
1548                 ::GpiDestroyPS(hPS
); 
1554             ULONG                       lOldForeGround 
= ::GpiQueryColor((HPS
)GetHPS()); 
1555             ULONG                       lOldBackGround 
= ::GpiQueryBackColor((HPS
)GetHPS()); 
1557             if (m_textForegroundColour
.Ok()) 
1559                 ::GpiSetColor( (HPS
)GetHPS() 
1560                                ,m_textForegroundColour
.GetPixel() 
1563             if (m_textBackgroundColour
.Ok()) 
1565                 ::GpiSetBackColor( (HPS
)GetHPS() 
1566                                   ,m_textBackgroundColour
.GetPixel() 
1570             // Need to alter bits in a mono bitmap to match the new 
1571             // background-foreground if it is different. 
1573             if (rBmp
.IsMono() && 
1574                ((m_textForegroundColour
.GetPixel() != lOldForeGround
) || 
1575                 (m_textBackgroundColour
.GetPixel() != lOldBackGround
))) 
1577                 DEVOPENSTRUC        vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1578                 SIZEL               vSize 
= {0, 0}; 
1579                 HDC                 hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1580                 HPS                 hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1582                 int                 nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1584                 LONG                lForeGround 
= m_textForegroundColour
.GetPixel(); 
1585                 LONG                lBackGround 
= m_textBackgroundColour
.GetPixel(); 
1587                 HBITMAP             hOldBitmap 
= NULLHANDLE
; 
1593                 memset(&vInfo
, '\0', 16); 
1595                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1596                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1598                 vInfo
.cBitCount       
= 24; 
1600                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1601                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1603                 pucBits 
= new unsigned char[nBytesPerLine 
* rBmp
.GetHeight()]; 
1604                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1606                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1608                     vError 
= ::WinGetLastError(vHabmain
); 
1609                     sError 
= wxPMErrorToStr(vError
); 
1612                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1614                                                    ,(LONG
)rBmp
.GetHeight() 
1619                     vError 
= ::WinGetLastError(vHabmain
); 
1620                     sError 
= wxPMErrorToStr(vError
); 
1623                 unsigned char           cOldRedFore   
= (unsigned char)(lOldForeGround 
>> 16); 
1624                 unsigned char           cOldGreenFore 
= (unsigned char)(lOldForeGround 
>> 8); 
1625                 unsigned char           cOldBlueFore  
= (unsigned char)lOldForeGround
; 
1627                 unsigned char           cRedFore   
= (unsigned char)(lForeGround 
>> 16); 
1628                 unsigned char           cGreenFore 
= (unsigned char)(lForeGround 
>> 8); 
1629                 unsigned char           cBlueFore  
= (unsigned char)lForeGround
; 
1631                 unsigned char           cRedBack   
= (unsigned char)(lBackGround 
>> 16); 
1632                 unsigned char           cGreenBack 
= (unsigned char)(lBackGround 
>> 8); 
1633                 unsigned char           cBlueBack  
= (unsigned char)lBackGround
; 
1636                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1638                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1640                         unsigned char    cBmpRed   
= *pucData
; 
1641                         unsigned char    cBmpGreen 
= *(pucData 
+ 1); 
1642                         unsigned char    cBmpBlue  
= *(pucData 
+ 2); 
1644                         if ((cBmpRed 
== cOldRedFore
) && 
1645                             (cBmpGreen 
== cOldGreenFore
) && 
1646                             (cBmpBlue 
== cOldBlueFore
)) 
1648                             *pucData 
= cBlueFore
; 
1650                             *pucData 
= cGreenFore
; 
1652                             *pucData 
= cRedFore
; 
1657                             *pucData 
= cBlueBack
; 
1659                             *pucData 
= cGreenBack
; 
1661                             *pucData 
= cRedBack
; 
1666                 if ((lScans 
= ::GpiSetBitmapBits( hPS
 
1668                                                  ,(LONG
)rBmp
.GetHeight() 
1673                     vError 
= ::WinGetLastError(vHabmain
); 
1674                     sError 
= wxPMErrorToStr(vError
); 
1678                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1679                 ::GpiDestroyPS(hPS
); 
1682             ::GpiWCBitBlt( (HPS
)GetHPS() 
1689             ::GpiSetBitmap((HPS
)GetHPS(), hBitmapOld
); 
1690             ::GpiSetColor((HPS
)GetHPS(), lOldForeGround
); 
1691             ::GpiSetBackColor((HPS
)GetHPS(), lOldBackGround
); 
1694 } // end of wxDC::DoDrawBitmap 
1696 void wxDC::DoDrawText( 
1697   const wxString
&                   rsText
 
1710     CalcBoundingBox(vX
, vY
); 
1711     GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1712     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1713 } // end of wxDC::DoDrawText 
1715 void wxDC::DrawAnyText( 
1716   const wxString
&                   rsText
 
1721     int                             nOldBackground 
= 0; 
1728     // prepare for drawing the text 
1732     // Set text color attributes 
1734     if (m_textForegroundColour
.Ok()) 
1737                      ,(int)m_textForegroundColour
.GetPixel() 
1741     if (m_textBackgroundColour
.Ok()) 
1743         nOldBackground 
= SetTextBkColor( m_hPS
 
1744                                         ,(int)m_textBackgroundColour
.GetPixel() 
1750     GetTextExtent( rsText
 
1755     if (!(m_vRclPaint
.yTop 
== 0 && 
1756           m_vRclPaint
.yBottom 
== 0 && 
1757           m_vRclPaint
.xRight 
== 0 && 
1758           m_vRclPaint
.xLeft 
== 0)) 
1761         // Position Text a little differently in the Statusbar from other panels 
1763         if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1764             vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1766             vPtlStart
.y 
= (wxCoord
)(OS2Y(vY
,vTextY
/1.5)); // Full extent is a bit much 
1770         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1772             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1773             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1774             if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1775                 vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1777                 vPtlStart
.y 
= (LONG
)(OS2Y(vY
,vTextY
/1.5)); 
1783     PCH                             pzStr 
= (PCH
)rsText
.c_str(); 
1785     ::GpiMove(m_hPS
, &vPtlStart
); 
1786     lHits 
= ::GpiCharString( m_hPS
 
1790     if (lHits 
!= GPI_OK
) 
1792         wxLogLastError(wxT("TextOut")); 
1796     // Restore the old parameters (text foreground colour may be left because 
1797     // it never is set to anything else, but background should remain 
1798     // transparent even if we just drew an opaque string) 
1800     if (m_textBackgroundColour
.Ok()) 
1801             SetTextBkColor( m_hPS
 
1809 void wxDC::DoDrawRotatedText( 
1810   const wxString
&                   rsText
 
1828         DoDrawText(text, x, y); 
1833         wxFillLogFont(&lf, &m_font); 
1835         // GDI wants the angle in tenth of degree 
1836         long angle10 = (long)(angle * 10); 
1837         lf.lfEscapement = angle10; 
1838         lf. lfOrientation = angle10; 
1840         HFONT hfont = ::CreateFontIndirect(&lf); 
1843             wxLogLastError("CreateFont"); 
1847             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1849             DrawAnyText(text, x, y); 
1851             (void)::SelectObject(GetHdc(), hfontOld); 
1854         // call the bounding box by adding all four vertices of the rectangle 
1855         // containing the text to it (simpler and probably not slower than 
1856         // determining which of them is really topmost/leftmost/...) 
1858         GetTextExtent(text, &w, &h); 
1860         double rad = DegToRad(angle); 
1862         // "upper left" and "upper right" 
1863         CalcBoundingBox(x, y); 
1864         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1865         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1867         // "bottom left" and "bottom right" 
1868         x += (wxCoord)(h*sin(rad)); 
1869         y += (wxCoord)(h*cos(rad)); 
1870         CalcBoundingBox(x, y); 
1871         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1876 // --------------------------------------------------------------------------- 
1878 // --------------------------------------------------------------------------- 
1880 void wxDC::DoSelectPalette( bool WXUNUSED(bRealize
) ) 
1883     // Set the old object temporarily, in case the assignment deletes an object 
1884     // that's not yet selected out. 
1895         hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1897             m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1899 } // end of wxDC::DoSelectPalette 
1901 void wxDC::InitializePalette() 
1903     if (wxDisplayDepth() <= 8 ) 
1906         // Look for any window or parent that has a custom palette. If any has 
1907         // one then we need to use it in drawing operations 
1909         wxWindow
*                   pWin 
= m_pCanvas
->GetAncestorWithCustomPalette(); 
1911         m_hasCustomPalette 
= pWin 
&& pWin
->HasCustomPalette(); 
1912         if (m_hasCustomPalette
) 
1914             m_palette 
= pWin
->GetPalette(); 
1917             // turn on PM translation for this palette 
1922 } // end of wxDC::InitializePalette 
1924 void wxDC::SetPalette( 
1925   const wxPalette
&                  rPalette
 
1932     m_palette 
= rPalette
; 
1940     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1942         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1943 } // end of wxDC::SetPalette 
1950     // Set the old object temporarily, in case the assignment deletes an object 
1951     // that's not yet selected out. 
1963     m_font
.SetPS(m_hPS
); // this will realize the font 
1967         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1968         if (hFont 
== (HFONT
) NULL
) 
1970             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
1973             m_hOldFont 
= (WXHFONT
) hFont
; 
1975 } // end of wxDC::SetFont 
1981     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1997             m_pen
.SetPS((HPS
)m_hOldPen
); 
2004         if (m_pen
.GetResourceHandle()) 
2008                 m_hOldPen 
= m_pen
.GetPS(); 
2010         ::GpiSetColor(m_hPS
, m_pen
.GetColour().GetPixel()); 
2014 void wxDC::SetBrush( 
2015   const wxBrush
&                    rBrush
 
2018     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2024     if (m_brush 
== rBrush
) 
2034             m_brush
.SetPS((HPS
)m_hOldBrush
); 
2041         if (m_brush
.GetResourceHandle()) 
2043             m_brush
.SetPS(m_hPS
); 
2045                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
2048 } // end of wxDC::SetBrush 
2050 void wxDC::SetBackground( 
2051   const wxBrush
&                    rBrush
 
2054     m_backgroundBrush 
= rBrush
; 
2055     if (!m_backgroundBrush
.Ok()) 
2059         bool                        bCustomColours 
= true; 
2062         // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to 
2063         // change background colours from the control-panel specified colours. 
2065         if (m_pCanvas
->IsKindOf(CLASSINFO(wxWindow
)) && 
2066             ((m_pCanvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
)) 
2067             bCustomColours 
= false; 
2070             if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
) 
2072                 m_pCanvas
->SetTransparent(true); 
2077                 // Setting the background brush of a DC 
2078                 // doesn't affect the window background colour. However, 
2079                 // I'm leaving in the transparency setting because it's needed by 
2080                 // various controls (e.g. wxStaticText) to determine whether to draw 
2081                 // transparently or not. TODO: maybe this should be a new function 
2082                 // wxWindow::SetTransparency(). Should that apply to the child itself, or the 
2084                 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour()); 
2086                 m_pCanvas
->SetTransparent(false); 
2090     COLORREF                        vNewColor 
= m_backgroundBrush
.GetColour().GetPixel(); 
2091     (void)::GpiSetBackColor((HPS
)m_hPS
, (LONG
)vNewColor
); 
2092 } // end of wxDC::SetBackground 
2094 void wxDC::SetBackgroundMode( 
2098     m_backgroundMode 
= nMode
; 
2099 } // end of wxDC::SetBackgroundMode 
2101 void wxDC::SetLogicalFunction( 
2105     m_logicalFunction 
= nFunction
; 
2106     SetRop((WXHDC
)m_hDC
); 
2107 } // wxDC::SetLogicalFunction 
2113     if (!hDC 
|| m_logicalFunction 
< 0) 
2117     switch (m_logicalFunction
) 
2128             lCRop 
= FM_MERGESRCNOT
; 
2132             lCRop 
= FM_NOTMASKSRC
; 
2144             lCRop 
= FM_MERGENOTSRC
; 
2148             lCRop 
= FM_MERGESRCNOT
; 
2160             lCRop 
= FM_SUBTRACT
; 
2167             lCRop 
= FM_OVERPAINT
; 
2170     ::GpiSetMix((HPS
)hDC
, lCRop
); 
2171 } // end of wxDC::SetRop 
2173 bool wxDC::StartDoc( const wxString
& WXUNUSED(rsMessage
) ) 
2175     // We might be previewing, so return true to let it continue. 
2177 } // end of wxDC::StartDoc 
2181 } // end of wxDC::EndDoc 
2183 void wxDC::StartPage() 
2185 } // end of wxDC::StartPage 
2187 void wxDC::EndPage() 
2189 } // end of wxDC::EndPage 
2191 // --------------------------------------------------------------------------- 
2193 // --------------------------------------------------------------------------- 
2195 wxCoord 
wxDC::GetCharHeight() const 
2197     FONTMETRICS                     vFM
; // metrics structure 
2199     ::GpiQueryFontMetrics( m_hPS
 
2200                           ,sizeof(FONTMETRICS
) 
2203     return YDEV2LOGREL(vFM
.lXHeight
); 
2206 wxCoord 
wxDC::GetCharWidth() const 
2208     FONTMETRICS                     vFM
; // metrics structure 
2210     ::GpiQueryFontMetrics( m_hPS
 
2211                           ,sizeof(FONTMETRICS
) 
2214     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
2217 void wxDC::DoGetTextExtent( 
2218   const wxString
&                   rsString
 
2221 , wxCoord
*                          pvDescent
 
2222 , wxCoord
*                          pvExternalLeading
 
2226     POINTL                          avPoint
[TXTBOX_COUNT
]; 
2231     FONTMETRICS                     vFM
; // metrics structure 
2233     ERRORID                         vErrorCode
; // last error id code 
2234     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
2236     wxChar                          zMsg
[128]; // DEBUG 
2240         pFontToUse 
= (wxFont
*)&m_font
; 
2241     l 
= rsString
.length(); 
2244     // In world coordinates. 
2246     bRc 
= ::GpiQueryTextBox( m_hPS
 
2248                             ,(PCH
)rsString
.c_str() 
2249                             ,TXTBOX_COUNT 
// return maximum information 
2250                             ,avPoint      
// array of coordinates points 
2254        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
2255        sError 
= wxPMErrorToStr(vErrorCode
); 
2257        wxSprintf(zMsg
, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString
.c_str(), vErrorCode
, sError
.c_str()); 
2258        (void)wxMessageBox( _T("wxWidgets Menu sample") 
2264     vPtMin
.x 
= avPoint
[0].x
; 
2265     vPtMax
.x 
= avPoint
[0].x
; 
2266     vPtMin
.y 
= avPoint
[0].y
; 
2267     vPtMax
.y 
= avPoint
[0].y
; 
2268     for (i 
= 1; i 
< 4; i
++) 
2270         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
2271         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
2272         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
2273         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
2275     ::GpiQueryFontMetrics( m_hPS
 
2276                           ,sizeof(FONTMETRICS
) 
2281         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
2283         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
2285         *pvDescent 
= vFM
.lMaxDescender
; 
2286     if (pvExternalLeading
) 
2287         *pvExternalLeading 
= vFM
.lExternalLeading
; 
2290 void wxDC::SetMapMode( 
2294     int                             nPixelWidth 
= 0; 
2295     int                             nPixelHeight 
= 0; 
2298     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2300     m_mappingMode 
= nMode
; 
2302     if(::DevQueryCaps( m_hDC
 
2304                       ,CAPS_VERTICAL_RESOLUTION
 
2311         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
2312         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
2313         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2314         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2315         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
2316         nMmWidth 
= (lVertRes
/1000) * nPixelHeight
; 
2318     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
2323     double                          dMm2pixelsX 
= nPixelWidth
/nMmWidth
; 
2324     double                          dMm2pixelsY 
= nPixelHeight
/nMmHeight
; 
2329             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
2330             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
2334             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
2335             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
2339             m_logicalScaleX 
= dMm2pixelsX
; 
2340             m_logicalScaleY 
= dMm2pixelsY
; 
2344             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
2345             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
2350             m_logicalScaleX 
= 1.0; 
2351             m_logicalScaleY 
= 1.0; 
2357     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
2358     if (!ulOptions 
& PU_ARBITRARY
) 
2360         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
2361         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
2363     m_nWindowExtX 
= (int)MS_XDEV2LOG(VIEWPORT_EXTENT
); 
2364     m_nWindowExtY 
= (int)MS_YDEV2LOG(VIEWPORT_EXTENT
); 
2366 }; // end of wxDC::SetMapMode 
2368 void wxDC::SetUserScale( double dX
, 
2374     SetMapMode(m_mappingMode
); 
2375 } // end of wxDC::SetUserScale 
2377 void wxDC::SetAxisOrientation( bool bXLeftRight
, 
2380     m_signX 
= bXLeftRight 
? 1 : -1; 
2381     m_signY 
= bYBottomUp 
? -1 : 1; 
2383     SetMapMode(m_mappingMode
); 
2384 } // end of wxDC::SetAxisOrientation 
2386 void wxDC::SetSystemScale( 
2394     SetMapMode(m_mappingMode
); 
2395 } // end of wxDC::SetSystemScale 
2397 void wxDC::SetLogicalOrigin( 
2404     ::GpiQueryPageViewport( m_hPS
 
2411     ::GpiSetPageViewport( m_hPS
 
2414 }; // end of wxDC::SetLogicalOrigin 
2416 void wxDC::SetDeviceOrigin( 
2423     m_deviceOriginX 
= vX
; 
2424     m_deviceOriginY 
= vY
; 
2425     ::GpiQueryPageViewport( m_hPS
 
2430     vRect
.yBottom 
-= vY
; 
2432     ::GpiSetPageViewport( m_hPS
 
2435 }; // end of wxDC::SetDeviceOrigin 
2437 // --------------------------------------------------------------------------- 
2438 // coordinates transformations 
2439 // --------------------------------------------------------------------------- 
2441 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
2443     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
2446 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
2448     // axis orientation is not taken into account for conversion of a distance 
2449     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_scaleX
)); 
2452 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
2454     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
2457 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
2459     // axis orientation is not taken into account for conversion of a distance 
2460     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_scaleY
)); 
2463 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
2465     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
2468 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
2470     // axis orientation is not taken into account for conversion of a distance 
2471     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_scaleX
); 
2474 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
2476     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
2479 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
2481     // axis orientation is not taken into account for conversion of a distance 
2482     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_scaleY
); 
2485 // --------------------------------------------------------------------------- 
2487 // --------------------------------------------------------------------------- 
2489 bool wxDC::DoBlit( wxCoord vXdest
, 
2498                    wxCoord 
WXUNUSED(vXsrcMask
), 
2499                    wxCoord 
WXUNUSED(vYsrcMask
) ) 
2501     wxMask
*                         pMask 
= NULL
; 
2503     COLORREF                        vOldTextColor
; 
2504     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
2508         const wxBitmap
&             rBmp 
= pSource
->m_vSelectedBitmap
; 
2510         pMask 
= rBmp
.GetMask(); 
2511         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
2517     ::GpiQueryAttrs( m_hPS
 
2522     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
2524     if (m_textForegroundColour
.Ok()) 
2526         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
2527         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2528                       ,PRIM_CHAR       
// Char primitive. 
2529                       ,CBB_COLOR       
// sets color. 
2531                       ,&vCbnd          
// buffer for attributes. 
2534     if (m_textBackgroundColour
.Ok()) 
2536         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
2539     LONG                            lRop 
= ROP_SRCCOPY
; 
2543         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
2544         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
2545         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
2546         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
2547         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
2548         case wxSET
:          lRop 
= ROP_ONE
;              break; 
2549         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
2550         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
2551         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
2552         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
2553         case wxNAND
:         lRop 
= 0x007700E6;           break; 
2554         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
2555         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
2556         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
2557         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
2558         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
2560            wxFAIL_MSG( wxT("unsupported logical function") ); 
2569         // Blit bitmap with mask 
2573         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2579         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2580         BITMAPINFOHEADER2               vBmpHdr
; 
2582         SIZEL                           vSize 
= {0, 0}; 
2585         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2586         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2587         vBmpHdr
.cx        
= vWidth
; 
2588         vBmpHdr
.cy        
= vHeight
; 
2589         vBmpHdr
.cPlanes   
= 1; 
2590         vBmpHdr
.cBitCount 
= 24; 
2592 #if wxUSE_DC_CACHEING 
2595             // create a temp buffer bitmap and DCs to access it and the mask 
2597             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2600             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2603             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2608             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2609             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2610             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2611             wxUnusedVar(hDCMask
); 
2615             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2616             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2617             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2618             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2619             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2623         POINTL                          aPoint1
[4] = { {0, 0} 
2626                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2628         POINTL                          aPoint2
[4] = { {0, 0} 
2631                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2633         POINTL                          aPoint3
[4] = { {vXdest
, vYdest
} 
2634                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2636                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2638         POINTL                          aPoint4
[4] = { {vXdest
, vYdest
} 
2639                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2643         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2644         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2647         // Copy dest to buffer 
2649         rc 
= ::GpiBitBlt( hPSBuffer
 
2656         if (rc 
== GPI_ERROR
) 
2658             wxLogLastError(wxT("BitBlt")); 
2662         // Copy src to buffer using selected raster op 
2664         rc 
= ::GpiBitBlt( hPSBuffer
 
2671         if (rc 
== GPI_ERROR
) 
2673             wxLogLastError(wxT("BitBlt")); 
2677         // Set masked area in buffer to BLACK (pixel value 0) 
2679         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2680         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2682         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2683         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2685         rc 
= ::GpiBitBlt( hPSBuffer
 
2692         if (rc 
== GPI_ERROR
) 
2694             wxLogLastError(wxT("BitBlt")); 
2698         // Set unmasked area in dest to BLACK 
2700         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2701         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2702         rc 
= ::GpiBitBlt( GetHPS() 
2709         if (rc 
== GPI_ERROR
) 
2711             wxLogLastError(wxT("BitBlt")); 
2715         // Restore colours to original values 
2717         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2718         ::GpiSetColor(GetHPS(), vPrevCol
); 
2721         // OR buffer to dest 
2723         rc 
= ::GpiBitBlt( GetHPS() 
2730         if (rc 
== GPI_ERROR
) 
2733             wxLogLastError(wxT("BitBlt")); 
2737         // Tidy up temporary DCs and bitmap 
2739         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2740         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2741 #if !wxUSE_DC_CACHEING 
2742         ::GpiDestroyPS(hPSMask
); 
2743         ::GpiDestroyPS(hPSBuffer
); 
2744         ::DevCloseDC(hDCMask
); 
2745         ::DevCloseDC(hDCBuffer
); 
2746         ::GpiDeleteBitmap(hBufBitmap
); 
2750     else // no mask, just BitBlt() it 
2752       POINTL                          aPoint
[4] = { {vXdest
, vYdest
} 
2753                            ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2755                            ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2758         bSuccess 
= (::GpiBitBlt( m_hPS
 
2767             wxLogLastError(wxT("BitBlt")); 
2770     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2771     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2772                   ,PRIM_CHAR       
// Char primitive. 
2773                   ,CBB_COLOR       
// sets color. 
2775                   ,&vCbnd          
// buffer for attributes. 
2777     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2781 void wxDC::DoGetSize( 
2786     LONG                            lArray
[CAPS_HEIGHT
]; 
2788     if(::DevQueryCaps( m_hDC
 
2794         *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2795         *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2797 }; // end of wxDC::DoGetSize( 
2799 void wxDC::DoGetSizeMM( int* pnWidth
, 
2800                         int* pnHeight 
) const 
2802     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2804     if(::DevQueryCaps( m_hDC
 
2806                       ,CAPS_VERTICAL_RESOLUTION
 
2812             int nWidth 
= lArray
[CAPS_WIDTH
]; 
2813             int nHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2814             *pnWidth  
= (nHorzRes
/1000) * nWidth
; 
2819             int nHeight   
= lArray
[CAPS_HEIGHT
]; 
2820             int nVertRes 
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2821             *pnHeight 
= (nVertRes
/1000) * nHeight
; 
2824 }; // end of wxDC::DoGetSizeMM 
2826 wxSize 
wxDC::GetPPI() const 
2828     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2832     if(::DevQueryCaps( m_hDC
 
2834                       ,CAPS_VERTICAL_RESOLUTION
 
2843         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2844         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2845         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2846         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2847         nWidth   
= (int)((nHorzRes
/39.3) * nPelWidth
); 
2848         nHeight  
= (int)((nVertRes
/39.3) * nPelHeight
); 
2850     wxSize 
ppisize(nWidth
, nHeight
); 
2852 } // end of wxDC::GetPPI 
2854 void wxDC::SetLogicalScale( 
2859     m_logicalScaleX 
= dX
; 
2860     m_logicalScaleY 
= dY
; 
2861 }; // end of wxDC::SetLogicalScale