1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/dc.cpp 
   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" 
  26     #include "wx/dcprint.h" 
  27     #include "wx/statusbr.h" 
  28     #include "wx/module.h" 
  33 #include "wx/os2/private.h" 
  35 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  38 // wxWidgets uses the Microsoft convention that the origin is the UPPER left. 
  39 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  40 // In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 
  41 // perform the following transformation: 
  43 // Parent object height:     POBJHEIGHT 
  44 // Desried origin:           WXORIGINY 
  45 // Object to place's height: OBJHEIGHT 
  47 // To get the OS2 position from the wxWidgets one: 
  49 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  51 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  52 // OS/2 Presentation Space associated with the device context.  y is the 
  53 // desired application's y coordinate of the origin in wxWidgets space. 
  54 // objy is the height of the object we are going to draw. 
  56 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  58 // --------------------------------------------------------------------------- 
  60 // --------------------------------------------------------------------------- 
  62 static const int VIEWPORT_EXTENT 
= 1000; 
  64 static const int MM_POINTS 
= 9; 
  65 static const int MM_METRIC 
= 10; 
  67 // --------------------------------------------------------------------------- 
  69 // --------------------------------------------------------------------------- 
  71 // convert degrees to radians 
  72 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  76 , int                               nForegroundColour
 
  81     vCbnd
.lColor 
=  nForegroundColour
; 
  82     ::GpiSetAttrs( hPS       
// presentation-space handle 
  83                   ,PRIM_CHAR 
// Char primitive. 
  84                   ,CBB_COLOR 
// sets color. 
  86                   ,&vCbnd    
// buffer for attributes. 
  97     ::GpiQueryAttrs( hPS            
// presentation-space handle 
  98                     ,PRIM_CHAR      
// Char primitive. 
  99                     ,CBB_BACK_COLOR 
// Background color. 
 100                     ,&vCbnd         
// buffer for attributes. 
 102     return vCbnd
.lBackColor
; 
 108 , int                               nBackgroundColour
 
 114     rc 
=  QueryTextBkColor(hPS
); 
 116     vCbnd
.lBackColor 
= nBackgroundColour
; 
 117     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 118                   PRIM_CHAR
,      // Char primitive. 
 119                   CBB_BACK_COLOR
, // sets color. 
 121                   &vCbnd          
// buffer for attributes. 
 128 , int                               nBackgroundMode
 
 131     if(nBackgroundMode 
== wxTRANSPARENT
) 
 136         // the background of the primitive takes  over whatever is underneath. 
 143 // =========================================================================== 
 145 // =========================================================================== 
 147 #if wxUSE_DC_CACHEING 
 150  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 151  * improve it in due course, either using arrays, or simply storing pointers to one 
 152  * entry for the bitmap, and two for the DCs. -- JACS 
 155 // --------------------------------------------------------------------------- 
 157 // --------------------------------------------------------------------------- 
 159 wxList 
wxDC::m_svBitmapCache
; 
 160 wxList 
wxDC::m_svDCCache
; 
 162 wxDCCacheEntry::wxDCCacheEntry( 
 174 } // end of wxDCCacheEntry::wxDCCacheEntry 
 176 wxDCCacheEntry::wxDCCacheEntry( 
 181     m_hBitmap 
= NULLHANDLE
; 
 186 } // end of wxDCCacheEntry::wxDCCacheEntry 
 188 wxDCCacheEntry::~wxDCCacheEntry() 
 191         ::GpiDeleteBitmap(m_hBitmap
); 
 193         ::GpiDestroyPS(m_hPS
); 
 194 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 196 wxDCCacheEntry
* wxDC::FindBitmapInCache( 
 202     int                             nDepth 
= 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 203     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 204     BITMAPINFOHEADER2               vBmpHdr
; 
 208         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 210         if (pEntry
->m_nDepth 
== nDepth
) 
 212             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 214             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 216                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 217                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 219                 vBmpHdr
.cy        
= nHeight
; 
 221                 vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 223                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 227                 if (!pEntry
->m_hBitmap
) 
 229                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 231                 pEntry
->m_nWidth  
= nWidth
; 
 232                 pEntry
->m_nHeight 
= nHeight
; 
 237         pNode 
= pNode
->Next(); 
 239     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 240     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 242     vBmpHdr
.cy        
= nHeight
; 
 244     vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 246     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 252         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 254     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 259     AddToBitmapCache(pEntry
); 
 261 } // end of FindBitmapInCache 
 263 wxDCCacheEntry
* wxDC::FindDCInCache( 
 264   wxDCCacheEntry
*                   pNotThis
 
 268     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 269     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 273         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 276         // Don't return the same one as we already have 
 278         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 280             if (pEntry
->m_nDepth 
== nDepth
) 
 285         pNode 
= pNode
->Next(); 
 287     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 290     AddToDCCache(pEntry
); 
 292 } // end of wxDC::FindDCInCache 
 294 void wxDC::AddToBitmapCache( 
 295   wxDCCacheEntry
*                   pEntry
 
 298     m_svBitmapCache
.Append(pEntry
); 
 299 } // end of wxDC::AddToBitmapCache 
 301 void wxDC::AddToDCCache( 
 302   wxDCCacheEntry
*                   pEntry
 
 305     m_svDCCache
.Append(pEntry
); 
 306 } // end of wxDC::AddToDCCache 
 308 void wxDC::ClearCache() 
 310     m_svBitmapCache
.DeleteContents(true); 
 311     m_svBitmapCache
.Clear(); 
 312     m_svBitmapCache
.DeleteContents(false); 
 313     m_svDCCache
.DeleteContents(true); 
 315     m_svDCCache
.DeleteContents(false); 
 316 } // end of wxDC::ClearCache 
 318 // Clean up cache at app exit 
 319 class wxDCModule 
: public wxModule
 
 322     virtual bool OnInit() { return true; } 
 323     virtual void OnExit() { wxDC::ClearCache(); } 
 326     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 327 }; // end of CLASS wxDCModule 
 329 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 331 #endif // ndef for wxUSE_DC_CACHEING 
 333 // --------------------------------------------------------------------------- 
 335 // --------------------------------------------------------------------------- 
 351     m_bIsPaintTime 
= false; // True at Paint Time 
 353     m_pen
.SetColour(*wxBLACK
); 
 354     m_brush
.SetColour(*wxWHITE
); 
 356 } // end of wxDC::wxDC 
 362         SelectOldObjects(m_hDC
); 
 364         // if we own the HDC, we delete it, otherwise we just release it 
 370                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 371                 ::GpiDestroyPS(m_hPS
); 
 374             ::DevCloseDC((HDC
)m_hDC
); 
 379             // Just Dissacociate, not destroy if we don't own the DC 
 383                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 387 } // end of wxDC::~wxDC 
 389 // This will select current objects out of the DC, 
 390 // which is what you have to do before deleting the 
 392 void wxDC::SelectOldObjects( 
 400             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 401             if (m_vSelectedBitmap
.Ok()) 
 403                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 408         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 416     m_brush           
= wxNullBrush
; 
 418     m_palette         
= wxNullPalette
; 
 420     m_backgroundBrush 
= wxNullBrush
; 
 421     m_vSelectedBitmap 
= wxNullBitmap
; 
 422 } // end of wxDC::SelectOldObjects 
 424 // --------------------------------------------------------------------------- 
 426 // --------------------------------------------------------------------------- 
 428 #define DO_SET_CLIPPING_BOX()                    \ 
 432     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 434     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 435     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 436     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 437     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 440 void wxDC::DoSetClippingRegion( 
 449     vY 
= OS2Y(vY
,vHeight
); 
 452     vRect
.yTop    
= vY 
+ vHeight
; 
 453     vRect
.xRight  
= vX 
+ vWidth
; 
 455     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 456     DO_SET_CLIPPING_BOX() 
 457 } // end of wxDC::DoSetClippingRegion 
 459 void wxDC::DoSetClippingRegionAsRegion( 
 460   const wxRegion
&                   rRegion
 
 463      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 467      ::GpiSetClipRegion( m_hPS
 
 468                         ,(HRGN
)rRegion
.GetHRGN() 
 471     DO_SET_CLIPPING_BOX() 
 472 } // end of wxDC::DoSetClippingRegionAsRegion 
 474 void wxDC::DestroyClippingRegion(void) 
 476     if (m_clipping 
&& m_hPS
) 
 481          // TODO: this should restore the previous clipped region 
 482          //       so that OnPaint processing works correctly, and 
 483          //       the update doesn't get destroyed after the first 
 484          //       DestroyClippingRegion 
 485          vRect
.xLeft   
= XLOG2DEV(0); 
 486          vRect
.yTop    
= YLOG2DEV(32000); 
 487          vRect
.xRight  
= XLOG2DEV(32000); 
 488          vRect
.yBottom 
= YLOG2DEV(0); 
 490          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 492          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 495 } // end of wxDC::DestroyClippingRegion 
 497 // --------------------------------------------------------------------------- 
 498 // query capabilities 
 499 // --------------------------------------------------------------------------- 
 501 bool wxDC::CanDrawBitmap() const 
 506 bool wxDC::CanGetTextExtent() const 
 508     LONG                            lTechnology 
= 0L; 
 510     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 511     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 512 } // end of wxDC::CanGetTextExtent 
 514 int wxDC::GetDepth() const 
 516     LONG                            lArray
[CAPS_COLOR_BITCOUNT
]; 
 517     int                             nBitsPerPixel 
= 0; 
 519     if(::DevQueryCaps( GetHDC() 
 525         nBitsPerPixel 
= (int)lArray
[CAPS_COLOR_BITCOUNT
]; 
 527     return nBitsPerPixel
; 
 528 } // end of wxDC::GetDepth 
 530 // --------------------------------------------------------------------------- 
 532 // --------------------------------------------------------------------------- 
 537     // If this is a canvas DC then just fill with the background color 
 538     // Otherwise purge the whole thing 
 544         ::GpiQueryClipBox(m_hPS
, &vRect
); 
 545         ::WinFillRect(m_hPS
, &vRect
, ::GpiQueryBackColor(m_hPS
)); 
 549 } // end of wxDC::Clear 
 551 bool wxDC::DoFloodFill( 
 554 , const wxColour
&                   rCol
 
 562     bool                            bSuccess 
= false; 
 564     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 565     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 566     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 567     lColor 
= rCol
.GetPixel(); 
 568     lOptions 
= FF_BOUNDARY
; 
 569     if(wxFLOOD_SURFACE 
== nStyle
) 
 570         lOptions 
= FF_SURFACE
; 
 572     if ((lHits 
= ::GpiFloodFill(m_hPS
, lOptions
, lColor
)) != GPI_ERROR
) 
 576 } // end of wxDC::DoFloodFill 
 578 bool wxDC::DoGetPixel( 
 588     vPoint
.y 
= OS2Y(vY
,0); 
 589     lColor 
= ::GpiQueryPel(m_hPS
, &vPoint
); 
 592     // return the color of the pixel 
 595         pCol
->Set( GetRValue(lColor
) 
 600 } // end of wxDC::DoGetPixel 
 602 void wxDC::DoCrossHair( 
 609     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 610     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 611     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 612     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 621     ::GpiMove(m_hPS
, &vPoint
[0]); 
 622     ::GpiLine(m_hPS
, &vPoint
[1]); 
 630     ::GpiMove(m_hPS
, &vPoint
[2]); 
 631     ::GpiLine(m_hPS
, &vPoint
[3]); 
 632     CalcBoundingBox(vX1
, vY1
); 
 633     CalcBoundingBox(vX2
, vY2
); 
 634 } // end of wxDC::DoCrossHair 
 636 void wxDC::DoDrawLine( 
 644     COLORREF                        vColor 
= 0x00ffffff; 
 647     // Might be a memory DC with no Paint rect. 
 649     if (!(m_vRclPaint
.yTop 
== 0 && 
 650           m_vRclPaint
.yBottom 
== 0 && 
 651           m_vRclPaint
.xRight 
== 0 && 
 652           m_vRclPaint
.xLeft 
== 0)) 
 659         if (m_vSelectedBitmap
.Ok()) 
 661             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 662             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 673         vColor 
= m_pen
.GetColour().GetPixel(); 
 675     ::GpiSetColor(m_hPS
, vColor
); 
 676     ::GpiMove(m_hPS
, &vPoint
[0]); 
 677     ::GpiLine(m_hPS
, &vPoint
[1]); 
 678     CalcBoundingBox(vX1
, vY1
); 
 679     CalcBoundingBox(vX2
, vY2
); 
 680 } // end of wxDC::DoDrawLine 
 682 ////////////////////////////////////////////////////////////////////////////// 
 683 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 684 // and ending at (x2, y2). The current pen is used for the outline and the 
 685 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 686 // direction from the start point to the end point. 
 687 ////////////////////////////////////////////////////////////////////////////// 
 688 void wxDC::DoDrawArc( 
 698      POINTL                         vPtlArc
[2]; // Structure for current position 
 705      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 707     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 708         return; // Draw point ?? 
 709     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 712                       hypot( (double)(vY2 
- vYc
) 
 717     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 720     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 727     // GpiPointArc can't draw full arc 
 729      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 734         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 735         vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 736         vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 751     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 752     vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 753     vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 756     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 762     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 764     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 765     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 766     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 771     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 772     CalcBoundingBox( (wxCoord
)(vXc 
- dRadius
) 
 773                     ,(wxCoord
)(vYc 
- dRadius
) 
 775     CalcBoundingBox( (wxCoord
)(vXc 
+ dRadius
) 
 776                     ,(wxCoord
)(vYc 
+ dRadius
) 
 778 } // end of wxDC::DoDrawArc 
 780 void wxDC::DoDrawCheckMark( 
 789     vY1 
= OS2Y(vY1
,vHeight
); 
 793     vPoint
[1].x 
= vX1 
+ vWidth
; 
 794     vPoint
[1].y 
= vY1 
+ vHeight
; 
 796     ::GpiMove(m_hPS
, &vPoint
[0]); 
 797     ::GpiBox( m_hPS       
// handle to a presentation space 
 798              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 799              ,&vPoint
[1]  // address of the corner 
 800              ,0L          // horizontal corner radius 
 801              ,0L          // vertical corner radius 
 803     if(vWidth 
> 4 && vHeight 
> 4) 
 807         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 808         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 809         ::GpiMove(m_hPS
, &vPoint
[0]); 
 810         ::GpiLine(m_hPS
, &vPoint
[1]); 
 812         vPoint
[0].x 
= vPoint
[1].x
; 
 814         ::GpiMove(m_hPS
, &vPoint
[0]); 
 815         ::GpiLine(m_hPS
, &vPoint
[1]); 
 821     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 822     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 827 } // end of wxDC::DoDrawCheckMark 
 829 void wxDC::DoDrawPoint( 
 835     COLORREF                        vColor 
= 0x00ffffff; 
 839         vColor 
= m_pen
.GetColour().GetPixel(); 
 841     ::GpiSetColor(m_hPS
, vColor
); 
 843     vPoint
.y 
= OS2Y(vY
,0); 
 844     ::GpiSetPel(m_hPS
, &vPoint
); 
 848 } // end of wxDC::DoDrawPoint 
 850 void wxDC::DoDrawPolygon( int n
, 
 856     ULONG     ulCount 
= 1;    // Number of polygons. 
 857     POLYGON   vPlgn
;          // polygon. 
 858     ULONG     flOptions 
= 0L; // Drawing options. 
 860     ////////////////////////////////////////////////////////////////////////////// 
 861     // This contains fields of option bits... to draw boundary lines as well as 
 862     // the area interior. 
 864     // Drawing boundary lines: 
 865     //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 866     //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 868     // Construction of the area interior: 
 869     //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 871     //   POLYGON_WINDING                 Constructs interior in winding mode. 
 872     ////////////////////////////////////////////////////////////////////////////// 
 874     ULONG     flModel 
= POLYGON_INCL
; // Drawing model. 
 876     ////////////////////////////////////////////////////////////////////////////// 
 878     //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 879     //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 880     //       This is provided to aid migration from other graphics models. 
 881     ////////////////////////////////////////////////////////////////////////////// 
 883     LONG      lHits 
= 0L; // Correlation/error indicator. 
 885     int       nIsTRANSPARENT 
= 0; 
 886     LONG      lBorderColor 
= 0L; 
 889     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 890     lColor       
= m_brush
.GetColour().GetPixel(); 
 891     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 895     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 897                                     ); // well, new will call malloc 
 899     for(i 
= 0; i 
< n
; i
++) 
 901         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
+vXoffset
; 
 902         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
+vYoffset
,0); 
 904     flOptions 
= POLYGON_BOUNDARY
; 
 905     if(nFillStyle 
== wxWINDING_RULE
) 
 906         flOptions 
|= POLYGON_WINDING
; 
 908         flOptions 
|= POLYGON_ALTERNATE
; 
 910     ::GpiSetColor(m_hPS
, lBorderColor
); 
 911     ::GpiMove(m_hPS
, &vPlgn
.aPointl
[0]); 
 912     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 914 } // end of wxDC::DoDrawPolygon 
 916 void wxDC::DoDrawLines( 
 925     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 929         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 930         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 931         ::GpiMove(m_hPS
, &vPoint
); 
 933         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 935         ::GpiSetColor(m_hPS
, lBorderColor
); 
 936         for(i 
= 1; i 
< n
; i
++) 
 938             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 939             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 940             ::GpiLine(m_hPS
, &vPoint
); 
 947         CalcBoundingBox( vPoints
[0].x
 
 950         vPoint
.x 
= vPoints
[0].x
; 
 951         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 952         ::GpiMove(m_hPS
, &vPoint
); 
 954         for (i 
= 0; i 
< n
; i
++) 
 956             CalcBoundingBox( vPoints
[i
].x
 
 959             vPoint
.x 
= vPoints
[i
].x
; 
 960             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 961             ::GpiLine(m_hPS
, &vPoint
); 
 964 } // end of wxDC::DoDrawLines 
 966 void wxDC::DoDrawRectangle( 
 977     int                             nIsTRANSPARENT 
= 0; 
 980     // Might be a memory DC with no Paint rect. 
 982     if (!(m_vRclPaint
.yTop 
== 0 && 
 983           m_vRclPaint
.yBottom 
== 0 && 
 984           m_vRclPaint
.xRight 
== 0 && 
 985           m_vRclPaint
.xLeft 
== 0)) 
 986         vY 
= OS2Y(vY
,vHeight
); 
 989         if (m_vSelectedBitmap
.Ok()) 
 991             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 992             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 993             vY 
= OS2Y(vY
,vHeight
); 
 997     wxCoord                         vX2 
= vX 
+ vWidth
; 
 998     wxCoord                         vY2 
= vY 
+ vHeight
; 
1002     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1003     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1004     ::GpiMove(m_hPS
, &vPoint
[0]); 
1005     lColor       
= m_brush
.GetColour().GetPixel(); 
1006     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1007     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1009     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1011         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1012         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1013             lControl 
= DRO_OUTLINE
; 
1015         ::GpiSetColor(m_hPS
, lBorderColor
); 
1016         ::GpiBox( m_hPS       
// handle to a presentation space 
1017                  ,lControl   
// draw the box outline ? or ? 
1018                  ,&vPoint
[1]  // address of the corner 
1019                  ,0L          // horizontal corner radius 
1020                  ,0L          // vertical corner radius 
1025         lControl 
= DRO_OUTLINE
; 
1026         ::GpiSetColor( m_hPS
 
1035         lControl 
= DRO_FILL
; 
1036         ::GpiSetColor( m_hPS
 
1039         vPoint
[0].x 
= vX 
+ 1; 
1040         vPoint
[0].y 
= vY 
+ 1; 
1041         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1042         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1043         ::GpiMove(m_hPS
, &vPoint
[0]); 
1051     CalcBoundingBox(vX
, vY
); 
1052     CalcBoundingBox(vX2
, vY2
); 
1053 } // end of wxDC::DoDrawRectangle 
1055 void wxDC::DoDrawRoundedRectangle( 
1067     int                             nIsTRANSPARENT 
= 0; 
1070     // Might be a memory DC with no Paint rect. 
1072     if (!(m_vRclPaint
.yTop 
== 0 && 
1073           m_vRclPaint
.yBottom 
== 0 && 
1074           m_vRclPaint
.xRight 
== 0 && 
1075           m_vRclPaint
.xLeft 
== 0)) 
1076         vY 
= OS2Y(vY
,vHeight
); 
1079         if (m_vSelectedBitmap
.Ok()) 
1081             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1082             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1083             vY 
= OS2Y(vY
,vHeight
); 
1087     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1088     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1092     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1093     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1094     ::GpiMove(m_hPS
, &vPoint
[0]); 
1096     lColor       
= m_brush
.GetColour().GetPixel(); 
1097     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1098     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1099     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1101     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1103         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1104         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1105             lControl 
= DRO_OUTLINE
; 
1107         ::GpiSetColor(m_hPS
, lColor
); 
1108         ::GpiBox( m_hPS         
// handle to a presentation space 
1109                  ,lControl      
// draw the box outline ? or ? 
1110                  ,&vPoint
[1]    // address of the corner 
1111                  ,(LONG
)dRadius 
// horizontal corner radius 
1112                  ,(LONG
)dRadius 
// vertical corner radius 
1117         lControl 
= DRO_OUTLINE
; 
1118         ::GpiSetColor( m_hPS
 
1127         lControl 
= DRO_FILL
; 
1128         ::GpiSetColor( m_hPS
 
1131         vPoint
[0].x 
= vX 
+ 1; 
1132         vPoint
[0].y 
= vY 
+ 1; 
1133         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1134         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1135         ::GpiMove(m_hPS
, &vPoint
[0]); 
1144     CalcBoundingBox(vX
, vY
); 
1145     CalcBoundingBox(vX2
, vY2
); 
1146 } // end of wxDC::DoDrawRoundedRectangle 
1148 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1149 void wxDC::DoDrawEllipse( 
1156     POINTL                          vPtlPos
; // Structure for current position 
1157     FIXED                           vFxMult
; // Multiplier for ellipse 
1158     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1160     vY 
= OS2Y(vY
,vHeight
); 
1163     vArcp
.lQ 
= vHeight
/2; 
1164     vArcp
.lP 
= vWidth
/2; 
1166     ::GpiSetArcParams( m_hPS
 
1168                      ); // Sets parameters to default 
1169     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1170     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1173              ); // Sets current position 
1174     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1177     // DRO_FILL, DRO_OTLINEFILL - where to get 
1182                 ); // Draws full arc with center at current position 
1184     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1185     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1187     CalcBoundingBox(vX
, vY
); 
1188     CalcBoundingBox(vX2
, vY2
); 
1189 } // end of wxDC::DoDrawEllipse 
1191 void wxDC::DoDrawEllipticArc( 
1200     POINTL                          vPtlPos
; // Structure for current position 
1201     FIXED                           vFxMult
; // Multiplier for ellipse 
1202     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1204     FIXED                           vFSweepa
; // Start angle, sweep angle 
1208     vY 
= OS2Y(vY
,vHeight
); 
1210     dFractPart 
= modf(dSa
,&dIntPart
); 
1211     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1212     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1213     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1216     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1219     vArcp
.lQ 
= vHeight
/2; 
1220     vArcp
.lP 
= vWidth
/2; 
1222     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1223     vPtlPos
.x 
= (wxCoord
)(vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
)))); // Loads x-coordinate 
1224     vPtlPos
.y 
= (wxCoord
)(vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
)))); // Loads y-coordinate 
1225     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1228     // May be not to the center ? 
1230     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1231     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1232     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1235     // DRO_FILL, DRO_OTLINEFILL - where to get 
1237     ::GpiPartialArc( m_hPS
 
1243     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1244     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1246     CalcBoundingBox(vX
, vY
); 
1247     CalcBoundingBox(vX2
, vY2
); 
1248 } // end of wxDC::DoDrawEllipticArc 
1250 void wxDC::DoDrawIcon( 
1257     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords 
1258     // and I don't feel like figuring those out for scrollable windows so 
1259     // just convert to a bitmap then let the DoDrawBitmap routine display it 
1263         DoDrawBitmap(rIcon
.GetXpmSrc(), vX
, vY
, true); 
1267         wxBitmap                        
vBitmap(rIcon
); 
1269         DoDrawBitmap(vBitmap
, vX
, vY
, false); 
1271     CalcBoundingBox(vX
, vY
); 
1272     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1273 } // end of wxDC::DoDrawIcon 
1275 void wxDC::DoDrawBitmap( 
1276   const wxBitmap
&                   rBmp
 
1282 #if wxUSE_PRINTING_ARCHITECTURE 
1283     if (!IsKindOf(CLASSINFO(wxPrinterDC
))) 
1286         HBITMAP                         hBitmap 
=  (HBITMAP
)rBmp
.GetHBITMAP(); 
1287         HBITMAP                         hBitmapOld 
= NULLHANDLE
; 
1290         vY 
= OS2Y(vY
,rBmp
.GetHeight()); 
1293         vPoint
[0].y 
= vY 
+ rBmp
.GetHeight(); 
1294         vPoint
[1].x 
= vX 
+ rBmp
.GetWidth(); 
1298         vPoint
[3].x 
= rBmp
.GetWidth(); 
1299         vPoint
[3].y 
= rBmp
.GetHeight(); 
1302             wxMask
*                     pMask 
= rBmp
.GetMask(); 
1307                 // Need to imitate ::MaskBlt in windows. 
1308                 // 1) Extract the bits from from the bitmap. 
1309                 // 2) Extract the bits from the mask 
1310                 // 3) Using the mask bits do the following: 
1311                 //   A) If the mask byte is 00 leave the bitmap byte alone 
1312                 //   B) If the mask byte is FF copy the screen color into 
1314                 // 4) Create a new bitmap and set its bits to the above result 
1315                 // 5) Blit this to the screen PS 
1317                 HBITMAP                 hMask 
= (HBITMAP
)pMask
->GetMaskBitmap(); 
1318                 HBITMAP                 hOldMask   
= NULLHANDLE
; 
1319                 HBITMAP                 hOldBitmap 
= NULLHANDLE
; 
1320                 HBITMAP                 hNewBitmap 
= NULLHANDLE
; 
1321                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1322                 unsigned char*          pucBitsMask
; // buffer that will contain the mask data 
1323                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1324                 unsigned char*          pucDataMask
; // pointer to use to traverse mask data 
1330                 // The usual Memory context creation stuff 
1332                 DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1333                 SIZEL                           vSize 
= {0, 0}; 
1334                 HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1335                 HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1338                 // The usual bitmap header stuff 
1340                 BITMAPINFOHEADER2               vHeader
; 
1343                 memset(&vHeader
, '\0', 16); 
1346                 memset(&vInfo
, '\0', 16); 
1348                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1349                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1351                 vInfo
.cBitCount       
= 24; // Set to desired count going in 
1354                 // Create the buffers for data....all wxBitmaps are 24 bit internally 
1356                 int                     nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1357                 int                     nSizeDWORD    
= sizeof(DWORD
); 
1358                 int                     nLineBoundary 
= nBytesPerLine 
% nSizeDWORD
; 
1366                 // Need to get a background color for mask blitting 
1368                 if (IsKindOf(CLASSINFO(wxWindowDC
))) 
1370                     wxWindowDC
*             pWindowDC 
= wxDynamicCast(this, wxWindowDC
); 
1372                     lColor 
= pWindowDC
->m_pCanvas
->GetBackgroundColour().GetPixel(); 
1374                 else if (GetBrush().Ok()) 
1375                     lColor 
= GetBrush().GetColour().GetPixel(); 
1377                     lColor 
= m_textBackgroundColour
.GetPixel(); 
1380                 // Bitmap must be in a double-word aligned address so we may 
1381                 // have some padding to worry about 
1383                 if (nLineBoundary 
> 0) 
1385                     nPadding     
= nSizeDWORD 
- nLineBoundary
; 
1386                     nBytesPerLine 
+= nPadding
; 
1388                 pucBits 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1389                 pucBitsMask 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1390                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1391                 memset(pucBitsMask
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1394                 // Extract the bitmap and mask data 
1396                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1398                     vError 
= ::WinGetLastError(vHabmain
); 
1399                     sError 
= wxPMErrorToStr(vError
); 
1401                 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
); 
1402                 vInfo
.cBitCount 
= 24; 
1403                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1405                                                    ,(LONG
)rBmp
.GetHeight() 
1410                     vError 
= ::WinGetLastError(vHabmain
); 
1411                     sError 
= wxPMErrorToStr(vError
); 
1413                 if ((hOldMask 
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
) 
1415                     vError 
= ::WinGetLastError(vHabmain
); 
1416                     sError 
= wxPMErrorToStr(vError
); 
1418                 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
); 
1419                 vInfo
.cBitCount 
= 24; 
1420                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1422                                                    ,(LONG
)rBmp
.GetHeight() 
1427                     vError 
= ::WinGetLastError(vHabmain
); 
1428                     sError 
= wxPMErrorToStr(vError
); 
1430                 if (( hMask 
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
) 
1432                     vError 
= ::WinGetLastError(vHabmain
); 
1433                     sError 
= wxPMErrorToStr(vError
); 
1437                 // Now set the bytes(bits) according to the mask values 
1438                 // 3 bytes per pel...must handle one at a time 
1441                 pucDataMask 
= pucBitsMask
; 
1444                 // 16 bit kludge really only kinda works.  The mask gets applied 
1445                 // where needed but the original bitmap bits are dorked sometimes 
1447                 bool                    bpp16 
= (wxDisplayDepth() == 16); 
1449                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1451                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1454                         if (bpp16 
&& *pucDataMask 
== 0xF8) // 16 bit display gobblygook 
1456                         else if (*pucDataMask 
== 0xFF) // leave bitmap byte alone 
1460                             *pucData 
= ((unsigned char)(lColor 
>> 16)); 
1464                         if (bpp16 
&& *(pucDataMask 
+ 1) == 0xFC) // 16 bit display gobblygook 
1466                         else if (*(pucDataMask 
+ 1) == 0xFF) // leave bitmap byte alone 
1470                             *pucData 
= ((unsigned char)(lColor 
>> 8)); 
1475                         if (bpp16 
&& *(pucDataMask 
+ 2) == 0xF8) // 16 bit display gobblygook 
1477                         else if (*(pucDataMask 
+ 2) == 0xFF) // leave bitmap byte alone 
1481                             *pucData 
= ((unsigned char)lColor
); 
1486                     for (j 
= 0; j 
< nPadding
; j
++) 
1493                 // Create a new bitmap 
1495                 vHeader
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1496                 vHeader
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1497                 vHeader
.cPlanes         
= 1L; 
1498                 vHeader
.cBitCount       
= 24; 
1499                 if ((hNewBitmap 
= ::GpiCreateBitmap( hPS
 
1506                     vError 
= ::WinGetLastError(vHabmain
); 
1507                     sError 
= wxPMErrorToStr(vError
); 
1511                 // Now blit it to the screen PS 
1513                 if ((lHits 
= ::GpiWCBitBlt( (HPS
)GetHPS() 
1521                     vError 
= ::WinGetLastError(vHabmain
); 
1522                     sError 
= wxPMErrorToStr(vError
); 
1530                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1531                 ::GpiDeleteBitmap(hNewBitmap
); 
1532                 ::GpiDestroyPS(hPS
); 
1538             ULONG                       lOldForeGround 
= ::GpiQueryColor((HPS
)GetHPS()); 
1539             ULONG                       lOldBackGround 
= ::GpiQueryBackColor((HPS
)GetHPS()); 
1541             if (m_textForegroundColour
.Ok()) 
1543                 ::GpiSetColor( (HPS
)GetHPS() 
1544                                ,m_textForegroundColour
.GetPixel() 
1547             if (m_textBackgroundColour
.Ok()) 
1549                 ::GpiSetBackColor( (HPS
)GetHPS() 
1550                                   ,m_textBackgroundColour
.GetPixel() 
1554             // Need to alter bits in a mono bitmap to match the new 
1555             // background-foreground if it is different. 
1557             if (rBmp
.IsMono() && 
1558                ((m_textForegroundColour
.GetPixel() != lOldForeGround
) || 
1559                 (m_textBackgroundColour
.GetPixel() != lOldBackGround
))) 
1561                 DEVOPENSTRUC        vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1562                 SIZEL               vSize 
= {0, 0}; 
1563                 HDC                 hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1564                 HPS                 hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1566                 int                 nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1568                 LONG                lForeGround 
= m_textForegroundColour
.GetPixel(); 
1569                 LONG                lBackGround 
= m_textBackgroundColour
.GetPixel(); 
1571                 HBITMAP             hOldBitmap 
= NULLHANDLE
; 
1577                 memset(&vInfo
, '\0', 16); 
1579                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1580                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1582                 vInfo
.cBitCount       
= 24; 
1584                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1585                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1587                 pucBits 
= new unsigned char[nBytesPerLine 
* rBmp
.GetHeight()]; 
1588                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1590                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1592                     vError 
= ::WinGetLastError(vHabmain
); 
1593                     sError 
= wxPMErrorToStr(vError
); 
1596                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1598                                                    ,(LONG
)rBmp
.GetHeight() 
1603                     vError 
= ::WinGetLastError(vHabmain
); 
1604                     sError 
= wxPMErrorToStr(vError
); 
1607                 unsigned char           cOldRedFore   
= (unsigned char)(lOldForeGround 
>> 16); 
1608                 unsigned char           cOldGreenFore 
= (unsigned char)(lOldForeGround 
>> 8); 
1609                 unsigned char           cOldBlueFore  
= (unsigned char)lOldForeGround
; 
1611                 unsigned char           cRedFore   
= (unsigned char)(lForeGround 
>> 16); 
1612                 unsigned char           cGreenFore 
= (unsigned char)(lForeGround 
>> 8); 
1613                 unsigned char           cBlueFore  
= (unsigned char)lForeGround
; 
1615                 unsigned char           cRedBack   
= (unsigned char)(lBackGround 
>> 16); 
1616                 unsigned char           cGreenBack 
= (unsigned char)(lBackGround 
>> 8); 
1617                 unsigned char           cBlueBack  
= (unsigned char)lBackGround
; 
1620                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1622                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1624                         unsigned char    cBmpRed   
= *pucData
; 
1625                         unsigned char    cBmpGreen 
= *(pucData 
+ 1); 
1626                         unsigned char    cBmpBlue  
= *(pucData 
+ 2); 
1628                         if ((cBmpRed 
== cOldRedFore
) && 
1629                             (cBmpGreen 
== cOldGreenFore
) && 
1630                             (cBmpBlue 
== cOldBlueFore
)) 
1632                             *pucData 
= cBlueFore
; 
1634                             *pucData 
= cGreenFore
; 
1636                             *pucData 
= cRedFore
; 
1641                             *pucData 
= cBlueBack
; 
1643                             *pucData 
= cGreenBack
; 
1645                             *pucData 
= cRedBack
; 
1650                 if ((lScans 
= ::GpiSetBitmapBits( hPS
 
1652                                                  ,(LONG
)rBmp
.GetHeight() 
1657                     vError 
= ::WinGetLastError(vHabmain
); 
1658                     sError 
= wxPMErrorToStr(vError
); 
1662                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1663                 ::GpiDestroyPS(hPS
); 
1666             ::GpiWCBitBlt( (HPS
)GetHPS() 
1673             ::GpiSetBitmap((HPS
)GetHPS(), hBitmapOld
); 
1674             ::GpiSetColor((HPS
)GetHPS(), lOldForeGround
); 
1675             ::GpiSetBackColor((HPS
)GetHPS(), lOldBackGround
); 
1678 } // end of wxDC::DoDrawBitmap 
1680 void wxDC::DoDrawText( 
1681   const wxString
&                   rsText
 
1694     CalcBoundingBox(vX
, vY
); 
1695     GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1696     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1697 } // end of wxDC::DoDrawText 
1699 void wxDC::DrawAnyText( const wxString
& rsText
, 
1703     int                             nOldBackground 
= 0; 
1710     // prepare for drawing the text 
1714     // Set text color attributes 
1716     if (m_textForegroundColour
.Ok()) 
1719                      ,(int)m_textForegroundColour
.GetPixel() 
1723     if (m_textBackgroundColour
.Ok()) 
1725         nOldBackground 
= SetTextBkColor( m_hPS
 
1726                                         ,(int)m_textBackgroundColour
.GetPixel() 
1732     GetTextExtent( rsText
 
1737     if (!(m_vRclPaint
.yTop 
== 0 && 
1738           m_vRclPaint
.yBottom 
== 0 && 
1739           m_vRclPaint
.xRight 
== 0 && 
1740           m_vRclPaint
.xLeft 
== 0)) 
1742         vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1746         if (m_vSelectedBitmap
.Ok()) 
1748             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1749             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1750             vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1756     ::GpiMove(m_hPS
, &vPtlStart
); 
1757     lHits 
= ::GpiCharString( m_hPS
 
1761     if (lHits 
!= GPI_OK
) 
1763         wxLogLastError(wxT("TextOut")); 
1767     // Restore the old parameters (text foreground colour may be left because 
1768     // it never is set to anything else, but background should remain 
1769     // transparent even if we just drew an opaque string) 
1771     if (m_textBackgroundColour
.Ok()) 
1772             SetTextBkColor( m_hPS
 
1780 void wxDC::DoDrawRotatedText( 
1781   const wxString
&                   rsText
 
1799         DoDrawText(text, x, y); 
1804         wxFillLogFont(&lf, &m_font); 
1806         // GDI wants the angle in tenth of degree 
1807         long angle10 = (long)(angle * 10); 
1808         lf.lfEscapement = angle10; 
1809         lf. lfOrientation = angle10; 
1811         HFONT hfont = ::CreateFontIndirect(&lf); 
1814             wxLogLastError("CreateFont"); 
1818             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1820             DrawAnyText(text, x, y); 
1822             (void)::SelectObject(GetHdc(), hfontOld); 
1825         // call the bounding box by adding all four vertices of the rectangle 
1826         // containing the text to it (simpler and probably not slower than 
1827         // determining which of them is really topmost/leftmost/...) 
1829         GetTextExtent(text, &w, &h); 
1831         double rad = DegToRad(angle); 
1833         // "upper left" and "upper right" 
1834         CalcBoundingBox(x, y); 
1835         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1836         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1838         // "bottom left" and "bottom right" 
1839         x += (wxCoord)(h*sin(rad)); 
1840         y += (wxCoord)(h*cos(rad)); 
1841         CalcBoundingBox(x, y); 
1842         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1847 // --------------------------------------------------------------------------- 
1849 // --------------------------------------------------------------------------- 
1851 void wxDC::DoSelectPalette( bool WXUNUSED(bRealize
) ) 
1854     // Set the old object temporarily, in case the assignment deletes an object 
1855     // that's not yet selected out. 
1866         hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1868             m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1870 } // end of wxDC::DoSelectPalette 
1872 void wxDC::InitializePalette() 
1874     if (wxDisplayDepth() <= 8 ) 
1877         // Look for any window or parent that has a custom palette. If any has 
1878         // one then we need to use it in drawing operations 
1880         wxWindow
*                   pWin 
= m_pCanvas
->GetAncestorWithCustomPalette(); 
1882         m_hasCustomPalette 
= pWin 
&& pWin
->HasCustomPalette(); 
1883         if (m_hasCustomPalette
) 
1885             m_palette 
= pWin
->GetPalette(); 
1888             // turn on PM translation for this palette 
1893 } // end of wxDC::InitializePalette 
1895 void wxDC::SetPalette( 
1896   const wxPalette
&                  rPalette
 
1903     m_palette 
= rPalette
; 
1911     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1913         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1914 } // end of wxDC::SetPalette 
1921     // Set the old object temporarily, in case the assignment deletes an object 
1922     // that's not yet selected out. 
1934     m_font
.SetPS(m_hPS
); // this will realize the font 
1938         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1939         if (hFont 
== (HFONT
) NULL
) 
1941             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
1944             m_hOldFont 
= (WXHFONT
) hFont
; 
1946 } // end of wxDC::SetFont 
1952     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1968             m_pen
.SetPS((HPS
)m_hOldPen
); 
1975         if (m_pen
.GetResourceHandle()) 
1979                 m_hOldPen 
= m_pen
.GetPS(); 
1981         ::GpiSetColor(m_hPS
, m_pen
.GetColour().GetPixel()); 
1985 void wxDC::SetBrush( 
1986   const wxBrush
&                    rBrush
 
1989     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1995     if (m_brush 
== rBrush
) 
2005             m_brush
.SetPS((HPS
)m_hOldBrush
); 
2012         if (m_brush
.GetResourceHandle()) 
2014             m_brush
.SetPS(m_hPS
); 
2016                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
2019 } // end of wxDC::SetBrush 
2021 void wxDC::SetBackground(const wxBrush
& rBrush
) 
2023     m_backgroundBrush 
= rBrush
; 
2025     if (m_backgroundBrush
.Ok()) 
2027         (void)::GpiSetBackColor((HPS
)m_hPS
, m_backgroundBrush
.GetColour().GetPixel()); 
2029 } // end of wxDC::SetBackground 
2031 void wxDC::SetBackgroundMode(int nMode
) 
2033     m_backgroundMode 
= nMode
; 
2034 } // end of wxDC::SetBackgroundMode 
2036 void wxDC::SetLogicalFunction(int nFunction
) 
2038     m_logicalFunction 
= nFunction
; 
2039     SetRop((WXHDC
)m_hDC
); 
2040 } // wxDC::SetLogicalFunction 
2042 void wxDC::SetRop(WXHDC hDC
) 
2044     if (!hDC 
|| m_logicalFunction 
< 0) 
2048     switch (m_logicalFunction
) 
2059             lCRop 
= FM_MERGESRCNOT
; 
2063             lCRop 
= FM_NOTMASKSRC
; 
2075             lCRop 
= FM_MERGENOTSRC
; 
2079             lCRop 
= FM_MERGESRCNOT
; 
2091             lCRop 
= FM_SUBTRACT
; 
2098             lCRop 
= FM_OVERPAINT
; 
2101     ::GpiSetMix((HPS
)hDC
, lCRop
); 
2102 } // end of wxDC::SetRop 
2104 bool wxDC::StartDoc( const wxString
& WXUNUSED(rsMessage
) ) 
2106     // We might be previewing, so return true to let it continue. 
2108 } // end of wxDC::StartDoc 
2112 } // end of wxDC::EndDoc 
2114 void wxDC::StartPage() 
2116 } // end of wxDC::StartPage 
2118 void wxDC::EndPage() 
2120 } // end of wxDC::EndPage 
2122 // --------------------------------------------------------------------------- 
2124 // --------------------------------------------------------------------------- 
2126 wxCoord 
wxDC::GetCharHeight() const 
2128     FONTMETRICS                     vFM
; // metrics structure 
2130     ::GpiQueryFontMetrics( m_hPS
 
2131                           ,sizeof(FONTMETRICS
) 
2134     return YDEV2LOGREL(vFM
.lXHeight
); 
2137 wxCoord 
wxDC::GetCharWidth() const 
2139     FONTMETRICS                     vFM
; // metrics structure 
2141     ::GpiQueryFontMetrics( m_hPS
 
2142                           ,sizeof(FONTMETRICS
) 
2145     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
2148 void wxDC::DoGetTextExtent( 
2149   const wxString
&                   rsString
 
2152 , wxCoord
*                          pvDescent
 
2153 , wxCoord
*                          pvExternalLeading
 
2154 , const wxFont
*                     pTheFont
 
2157     POINTL                          avPoint
[TXTBOX_COUNT
]; 
2162     FONTMETRICS                     vFM
; // metrics structure 
2164     ERRORID                         vErrorCode
; // last error id code 
2165     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
2167     wxChar                          zMsg
[128]; // DEBUG 
2171         pFontToUse 
= (wxFont
*)&m_font
; 
2172     l 
= rsString
.length(); 
2175     // In world coordinates. 
2177     bRc 
= ::GpiQueryTextBox( m_hPS
 
2179                             ,rsString
.char_str() 
2180                             ,TXTBOX_COUNT 
// return maximum information 
2181                             ,avPoint      
// array of coordinates points 
2185        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
2186        sError 
= wxPMErrorToStr(vErrorCode
); 
2188        wxSprintf(zMsg
, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString
.c_str(), vErrorCode
, sError
.c_str()); 
2189        (void)wxMessageBox( _T("wxWidgets Menu sample") 
2195     vPtMin
.x 
= avPoint
[0].x
; 
2196     vPtMax
.x 
= avPoint
[0].x
; 
2197     vPtMin
.y 
= avPoint
[0].y
; 
2198     vPtMax
.y 
= avPoint
[0].y
; 
2199     for (i 
= 1; i 
< 4; i
++) 
2201         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
2202         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
2203         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
2204         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
2206     ::GpiQueryFontMetrics( m_hPS
 
2207                           ,sizeof(FONTMETRICS
) 
2212         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
2214         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
2216         *pvDescent 
= vFM
.lMaxDescender
; 
2217     if (pvExternalLeading
) 
2218         *pvExternalLeading 
= vFM
.lExternalLeading
; 
2221 void wxDC::SetMapMode( 
2225     int                             nPixelWidth 
= 0; 
2226     int                             nPixelHeight 
= 0; 
2229     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2231     m_mappingMode 
= nMode
; 
2233     if(::DevQueryCaps( m_hDC
 
2235                       ,CAPS_VERTICAL_RESOLUTION
 
2242         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
2243         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
2244         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2245         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2246         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
2247         nMmWidth 
= (lVertRes
/1000) * nPixelHeight
; 
2249     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
2254     double                          dMm2pixelsX 
= nPixelWidth
/nMmWidth
; 
2255     double                          dMm2pixelsY 
= nPixelHeight
/nMmHeight
; 
2260             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
2261             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
2265             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
2266             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
2270             m_logicalScaleX 
= dMm2pixelsX
; 
2271             m_logicalScaleY 
= dMm2pixelsY
; 
2275             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
2276             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
2281             m_logicalScaleX 
= 1.0; 
2282             m_logicalScaleY 
= 1.0; 
2288     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
2289     if (!ulOptions 
& PU_ARBITRARY
) 
2291         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
2292         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
2294     m_nWindowExtX 
= (int)MS_XDEV2LOG(VIEWPORT_EXTENT
); 
2295     m_nWindowExtY 
= (int)MS_YDEV2LOG(VIEWPORT_EXTENT
); 
2298     ComputeScaleAndOrigin(); 
2300 }; // end of wxDC::SetMapMode 
2302 void wxDC::SetUserScale( double dX
, 
2308     SetMapMode(m_mappingMode
); 
2309 } // end of wxDC::SetUserScale 
2311 void wxDC::SetAxisOrientation( bool bXLeftRight
, 
2314     m_signX 
= bXLeftRight 
? 1 : -1; 
2315     m_signY 
= bYBottomUp 
? -1 : 1; 
2317     SetMapMode(m_mappingMode
); 
2318 } // end of wxDC::SetAxisOrientation 
2320 void wxDC::SetLogicalOrigin( 
2327     ::GpiQueryPageViewport( m_hPS
 
2334     ::GpiSetPageViewport( m_hPS
 
2337 }; // end of wxDC::SetLogicalOrigin 
2339 void wxDC::SetDeviceOrigin( 
2346     m_deviceOriginX 
= vX
; 
2347     m_deviceOriginY 
= vY
; 
2348     ::GpiQueryPageViewport( m_hPS
 
2353     vRect
.yBottom 
-= vY
; 
2355     ::GpiSetPageViewport( m_hPS
 
2358 }; // end of wxDC::SetDeviceOrigin 
2360 // --------------------------------------------------------------------------- 
2362 // --------------------------------------------------------------------------- 
2364 bool wxDC::DoBlit( wxCoord vXdest
, 
2373                    wxCoord 
WXUNUSED(vXsrcMask
), 
2374                    wxCoord 
WXUNUSED(vYsrcMask
) ) 
2376     wxMask
*                         pMask 
= NULL
; 
2378     COLORREF                        vOldTextColor
; 
2379     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
2383         const wxBitmap
&             rBmp 
= pSource
->m_vSelectedBitmap
; 
2385         pMask 
= rBmp
.GetMask(); 
2386         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
2392     ::GpiQueryAttrs( m_hPS
 
2397     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
2399     if (m_textForegroundColour
.Ok()) 
2401         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
2402         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2403                       ,PRIM_CHAR       
// Char primitive. 
2404                       ,CBB_COLOR       
// sets color. 
2406                       ,&vCbnd          
// buffer for attributes. 
2409     if (m_textBackgroundColour
.Ok()) 
2411         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
2414     LONG                            lRop 
= ROP_SRCCOPY
; 
2418         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
2419         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
2420         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
2421         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
2422         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
2423         case wxSET
:          lRop 
= ROP_ONE
;              break; 
2424         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
2425         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
2426         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
2427         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
2428         case wxNAND
:         lRop 
= 0x007700E6;           break; 
2429         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
2430         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
2431         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
2432         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
2433         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
2435            wxFAIL_MSG( wxT("unsupported logical function") ); 
2444         // Blit bitmap with mask 
2448         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2454         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2455         BITMAPINFOHEADER2               vBmpHdr
; 
2457         SIZEL                           vSize 
= {0, 0}; 
2460         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2461         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2462         vBmpHdr
.cx        
= vWidth
; 
2463         vBmpHdr
.cy        
= vHeight
; 
2464         vBmpHdr
.cPlanes   
= 1; 
2465         vBmpHdr
.cBitCount 
= 24; 
2467 #if wxUSE_DC_CACHEING 
2470             // create a temp buffer bitmap and DCs to access it and the mask 
2472             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2475             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2478             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2483             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2484             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2485             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2486             wxUnusedVar(hDCMask
); 
2490             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2491             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2492             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2493             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2494             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2498         POINTL                          aPoint1
[4] = { {0, 0} 
2501                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2503         POINTL                          aPoint2
[4] = { {0, 0} 
2506                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2508         POINTL                          aPoint3
[4] = { {vXdest
, vYdest
} 
2509                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2511                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2513         POINTL                          aPoint4
[4] = { {vXdest
, vYdest
} 
2514                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2518         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2519         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2522         // Copy dest to buffer 
2524         rc 
= ::GpiBitBlt( hPSBuffer
 
2531         if (rc 
== GPI_ERROR
) 
2533             wxLogLastError(wxT("BitBlt")); 
2537         // Copy src to buffer using selected raster op 
2539         rc 
= ::GpiBitBlt( hPSBuffer
 
2546         if (rc 
== GPI_ERROR
) 
2548             wxLogLastError(wxT("BitBlt")); 
2552         // Set masked area in buffer to BLACK (pixel value 0) 
2554         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2555         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2557         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2558         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2560         rc 
= ::GpiBitBlt( hPSBuffer
 
2567         if (rc 
== GPI_ERROR
) 
2569             wxLogLastError(wxT("BitBlt")); 
2573         // Set unmasked area in dest to BLACK 
2575         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2576         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2577         rc 
= ::GpiBitBlt( GetHPS() 
2584         if (rc 
== GPI_ERROR
) 
2586             wxLogLastError(wxT("BitBlt")); 
2590         // Restore colours to original values 
2592         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2593         ::GpiSetColor(GetHPS(), vPrevCol
); 
2596         // OR buffer to dest 
2598         rc 
= ::GpiBitBlt( GetHPS() 
2605         if (rc 
== GPI_ERROR
) 
2608             wxLogLastError(wxT("BitBlt")); 
2612         // Tidy up temporary DCs and bitmap 
2614         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2615         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2616 #if !wxUSE_DC_CACHEING 
2617         ::GpiDestroyPS(hPSMask
); 
2618         ::GpiDestroyPS(hPSBuffer
); 
2619         ::DevCloseDC(hDCMask
); 
2620         ::DevCloseDC(hDCBuffer
); 
2621         ::GpiDeleteBitmap(hBufBitmap
); 
2625     else // no mask, just BitBlt() it 
2627       POINTL                          aPoint
[4] = { {vXdest
, vYdest
} 
2628                            ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2630                            ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2633         bSuccess 
= (::GpiBitBlt( m_hPS
 
2642             wxLogLastError(wxT("BitBlt")); 
2645     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2646     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2647                   ,PRIM_CHAR       
// Char primitive. 
2648                   ,CBB_COLOR       
// sets color. 
2650                   ,&vCbnd          
// buffer for attributes. 
2652     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2656 void wxDC::DoGetSize( int* pnWidth
, 
2657                       int* pnHeight 
) const 
2659     LONG lArray
[CAPS_HEIGHT
]; 
2661     if(::DevQueryCaps( m_hDC
 
2667         *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2668         *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2670 }; // end of wxDC::DoGetSize( 
2672 void wxDC::DoGetSizeMM( int* pnWidth
, 
2673                         int* pnHeight 
) const 
2675     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2677     if(::DevQueryCaps( m_hDC
 
2679                       ,CAPS_VERTICAL_RESOLUTION
 
2685             int nWidth 
= lArray
[CAPS_WIDTH
]; 
2686             int nHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2687             *pnWidth  
= (nHorzRes
/1000) * nWidth
; 
2692             int nHeight   
= lArray
[CAPS_HEIGHT
]; 
2693             int nVertRes 
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2694             *pnHeight 
= (nVertRes
/1000) * nHeight
; 
2697 }; // end of wxDC::DoGetSizeMM 
2699 wxSize 
wxDC::GetPPI() const 
2701     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2705     if(::DevQueryCaps( m_hDC
 
2707                       ,CAPS_VERTICAL_RESOLUTION
 
2716         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2717         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2718         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2719         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2720         nWidth   
= (int)((nHorzRes
/39.3) * nPelWidth
); 
2721         nHeight  
= (int)((nVertRes
/39.3) * nPelHeight
); 
2723     wxSize 
ppisize(nWidth
, nHeight
); 
2725 } // end of wxDC::GetPPI 
2727 void wxDC::SetLogicalScale( double dX
, double dY 
) 
2729     m_logicalScaleX 
= dX
; 
2730     m_logicalScaleY 
= dY
; 
2731 }; // end of wxDC::SetLogicalScale