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/dc.h" 
  34 #include "wx/os2/dcclient.h" 
  35 #include "wx/os2/private.h" 
  37 IMPLEMENT_ABSTRACT_CLASS(wxPMDCImpl
, wxDCImpl
) 
  40 // wxWidgets uses the Microsoft convention that the origin is the UPPER left. 
  41 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  42 // In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 
  43 // perform the following transformation: 
  45 // Parent object height:     POBJHEIGHT 
  46 // Desried origin:           WXORIGINY 
  47 // Object to place's height: OBJHEIGHT 
  49 // To get the OS2 position from the wxWidgets one: 
  51 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  53 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  54 // OS/2 Presentation Space associated with the device context.  y is the 
  55 // desired application's y coordinate of the origin in wxWidgets space. 
  56 // objy is the height of the object we are going to draw. 
  58 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  60 // --------------------------------------------------------------------------- 
  62 // --------------------------------------------------------------------------- 
  64 static const int VIEWPORT_EXTENT 
= 1000; 
  66 static const int MM_POINTS 
= 9; 
  67 static const int MM_METRIC 
= 10; 
  69 // --------------------------------------------------------------------------- 
  71 // --------------------------------------------------------------------------- 
  73 // convert degrees to radians 
  74 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  78 , int                               nForegroundColour
 
  83     vCbnd
.lColor 
=  nForegroundColour
; 
  84     ::GpiSetAttrs( hPS       
// presentation-space handle 
  85                   ,PRIM_CHAR 
// Char primitive. 
  86                   ,CBB_COLOR 
// sets color. 
  88                   ,&vCbnd    
// buffer for attributes. 
  99     ::GpiQueryAttrs( hPS            
// presentation-space handle 
 100                     ,PRIM_CHAR      
// Char primitive. 
 101                     ,CBB_BACK_COLOR 
// Background color. 
 102                     ,&vCbnd         
// buffer for attributes. 
 104     return vCbnd
.lBackColor
; 
 110 , int                               nBackgroundColour
 
 116     rc 
=  QueryTextBkColor(hPS
); 
 118     vCbnd
.lBackColor 
= nBackgroundColour
; 
 119     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 120                   PRIM_CHAR
,      // Char primitive. 
 121                   CBB_BACK_COLOR
, // sets color. 
 123                   &vCbnd          
// buffer for attributes. 
 130 , int                               nBackgroundMode
 
 133     if(nBackgroundMode 
== wxTRANSPARENT
) 
 138         // the background of the primitive takes  over whatever is underneath. 
 145 // =========================================================================== 
 147 // =========================================================================== 
 149 #if wxUSE_DC_CACHEING 
 152  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 153  * improve it in due course, either using arrays, or simply storing pointers to one 
 154  * entry for the bitmap, and two for the DCs. -- JACS 
 157 // --------------------------------------------------------------------------- 
 159 // --------------------------------------------------------------------------- 
 161 wxList 
wxPMDCImpl::m_svBitmapCache
; 
 162 wxList 
wxPMDCImpl::m_svDCCache
; 
 164 wxDCCacheEntry::wxDCCacheEntry( 
 176 } // end of wxDCCacheEntry::wxDCCacheEntry 
 178 wxDCCacheEntry::wxDCCacheEntry( 
 183     m_hBitmap 
= NULLHANDLE
; 
 188 } // end of wxDCCacheEntry::wxDCCacheEntry 
 190 wxDCCacheEntry::~wxDCCacheEntry() 
 193         ::GpiDeleteBitmap(m_hBitmap
); 
 195         ::GpiDestroyPS(m_hPS
); 
 196 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 198 wxDCCacheEntry
* wxPMDCImpl::FindBitmapInCache( 
 204     int                             nDepth 
= 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 205     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 206     BITMAPINFOHEADER2               vBmpHdr
; 
 210         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 212         if (pEntry
->m_nDepth 
== nDepth
) 
 214             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 216             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 218                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 219                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 221                 vBmpHdr
.cy        
= nHeight
; 
 223                 vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 225                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 229                 if (!pEntry
->m_hBitmap
) 
 231                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 233                 pEntry
->m_nWidth  
= nWidth
; 
 234                 pEntry
->m_nHeight 
= nHeight
; 
 239         pNode 
= pNode
->Next(); 
 241     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 242     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 244     vBmpHdr
.cy        
= nHeight
; 
 246     vBmpHdr
.cBitCount 
= (USHORT
)nDepth
; 
 248     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 254         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 256     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 261     AddToBitmapCache(pEntry
); 
 263 } // end of FindBitmapInCache 
 265 wxDCCacheEntry
* wxPMDCImpl::FindDCInCache( 
 266   wxDCCacheEntry
*                   pNotThis
 
 270     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 271     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 275         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 278         // Don't return the same one as we already have 
 280         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 282             if (pEntry
->m_nDepth 
== nDepth
) 
 287         pNode 
= pNode
->Next(); 
 289     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 292     AddToDCCache(pEntry
); 
 294 } // end of wxPMDCImpl::FindDCInCache 
 296 void wxPMDCImpl::AddToBitmapCache( 
 297   wxDCCacheEntry
*                   pEntry
 
 300     m_svBitmapCache
.Append(pEntry
); 
 301 } // end of wxPMDCImpl::AddToBitmapCache 
 303 void wxPMDCImpl::AddToDCCache( 
 304   wxDCCacheEntry
*                   pEntry
 
 307     m_svDCCache
.Append(pEntry
); 
 308 } // end of wxPMDCImpl::AddToDCCache 
 310 void wxPMDCImpl::ClearCache() 
 312     m_svBitmapCache
.DeleteContents(true); 
 313     m_svBitmapCache
.Clear(); 
 314     m_svBitmapCache
.DeleteContents(false); 
 315     m_svDCCache
.DeleteContents(true); 
 317     m_svDCCache
.DeleteContents(false); 
 318 } // end of wxPMDCImpl::ClearCache 
 320 // Clean up cache at app exit 
 321 class wxDCModule 
: public wxModule
 
 324     virtual bool OnInit() { return true; } 
 325     virtual void OnExit() { wxPMDCImpl::ClearCache(); } 
 328     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 329 }; // end of CLASS wxDCModule 
 331 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 333 #endif // ndef for wxUSE_DC_CACHEING 
 335 // --------------------------------------------------------------------------- 
 337 // --------------------------------------------------------------------------- 
 339 wxPMDCImpl::wxPMDCImpl( wxDC 
*owner
, WXHDC hDC 
) : 
 344 } // end of wxPMDCImpl::wxPMDCImpl 
 346 wxPMDCImpl::~wxPMDCImpl(void) 
 350         SelectOldObjects(m_hDC
); 
 352         // if we own the HDC, we delete it, otherwise we just release it 
 358                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 359                 ::GpiDestroyPS(m_hPS
); 
 362             ::DevCloseDC((HDC
)m_hDC
); 
 367             // Just Dissacociate, not destroy if we don't own the DC 
 371                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 375 } // end of wxPMDCImpl::~wxDC 
 377 // This will select current objects out of the DC, 
 378 // which is what you have to do before deleting the 
 380 void wxPMDCImpl::SelectOldObjects( 
 388             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 389             if (m_vSelectedBitmap
.Ok()) 
 391                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 396         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 404     m_brush           
= wxNullBrush
; 
 406     m_palette         
= wxNullPalette
; 
 408     m_backgroundBrush 
= wxNullBrush
; 
 409     m_vSelectedBitmap 
= wxNullBitmap
; 
 410 } // end of wxPMDCImpl::SelectOldObjects 
 412 // --------------------------------------------------------------------------- 
 414 // --------------------------------------------------------------------------- 
 416 #define DO_SET_CLIPPING_BOX()                    \ 
 420     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 422     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 423     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 424     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 425     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 428 void wxPMDCImpl::DoSetClippingRegion( 
 437     vY 
= OS2Y(vY
,vHeight
); 
 440     vRect
.yTop    
= vY 
+ vHeight
; 
 441     vRect
.xRight  
= vX 
+ vWidth
; 
 443     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 444     DO_SET_CLIPPING_BOX() 
 445 } // end of wxPMDCImpl::DoSetClippingRegion 
 447 void wxPMDCImpl::DoSetDeviceClippingRegion( 
 448   const wxRegion
&                   rRegion
 
 451      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 455      ::GpiSetClipRegion( m_hPS
 
 456                         ,(HRGN
)rRegion
.GetHRGN() 
 459     DO_SET_CLIPPING_BOX() 
 460 } // end of wxPMDCImpl::DoSetDeviceClippingRegion 
 462 void wxPMDCImpl::DestroyClippingRegion(void) 
 464     if (m_clipping 
&& m_hPS
) 
 469          // TODO: this should restore the previous clipped region 
 470          //       so that OnPaint processing works correctly, and 
 471          //       the update doesn't get destroyed after the first 
 472          //       DestroyClippingRegion 
 473          vRect
.xLeft   
= XLOG2DEV(0); 
 474          vRect
.yTop    
= YLOG2DEV(32000); 
 475          vRect
.xRight  
= XLOG2DEV(32000); 
 476          vRect
.yBottom 
= YLOG2DEV(0); 
 478          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 480          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 483 } // end of wxPMDCImpl::DestroyClippingRegion 
 485 // --------------------------------------------------------------------------- 
 486 // query capabilities 
 487 // --------------------------------------------------------------------------- 
 489 bool wxPMDCImpl::CanDrawBitmap() const 
 494 bool wxPMDCImpl::CanGetTextExtent() const 
 496     LONG                            lTechnology 
= 0L; 
 498     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 499     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 500 } // end of wxPMDCImpl::CanGetTextExtent 
 502 int wxPMDCImpl::GetDepth() const 
 504     LONG                            lCapsColorBitcount
; 
 505     int                             nBitsPerPixel 
= 0; 
 507     if(::DevQueryCaps( GetHDC() 
 513         nBitsPerPixel 
= (int)lCapsColorBitcount
; 
 515     return nBitsPerPixel
; 
 516 } // end of wxPMDCImpl::GetDepth 
 518 // --------------------------------------------------------------------------- 
 520 // --------------------------------------------------------------------------- 
 522 void wxPMDCImpl::Clear() 
 525     // If this is a canvas DC then just fill with the background color 
 526     // Otherwise purge the whole thing 
 532         ::GpiQueryClipBox(m_hPS
, &vRect
); 
 533         ::WinFillRect(m_hPS
, &vRect
, ::GpiQueryBackColor(m_hPS
)); 
 537 } // end of wxPMDCImpl::Clear 
 539 bool wxPMDCImpl::DoFloodFill( 
 542 , const wxColour
&                   rCol
 
 550     bool                            bSuccess 
= false; 
 552     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 553     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 554     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 555     lColor 
= rCol
.GetPixel(); 
 556     lOptions 
= FF_BOUNDARY
; 
 557     if(wxFLOOD_SURFACE 
== nStyle
) 
 558         lOptions 
= FF_SURFACE
; 
 560     if ((lHits 
= ::GpiFloodFill(m_hPS
, lOptions
, lColor
)) != GPI_ERROR
) 
 564 } // end of wxPMDCImpl::DoFloodFill 
 566 bool wxPMDCImpl::DoGetPixel( 
 576     vPoint
.y 
= OS2Y(vY
,0); 
 577     lColor 
= ::GpiQueryPel(m_hPS
, &vPoint
); 
 580     // return the color of the pixel 
 583         pCol
->Set( GetRValue(lColor
) 
 588 } // end of wxPMDCImpl::DoGetPixel 
 590 void wxPMDCImpl::DoCrossHair( 
 597     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 598     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 599     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 600     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 609     ::GpiMove(m_hPS
, &vPoint
[0]); 
 610     ::GpiLine(m_hPS
, &vPoint
[1]); 
 618     ::GpiMove(m_hPS
, &vPoint
[2]); 
 619     ::GpiLine(m_hPS
, &vPoint
[3]); 
 620     CalcBoundingBox(vX1
, vY1
); 
 621     CalcBoundingBox(vX2
, vY2
); 
 622 } // end of wxPMDCImpl::DoCrossHair 
 624 void wxPMDCImpl::DoDrawLine( 
 632     COLORREF                        vColor 
= 0x00ffffff; 
 635     // Might be a memory DC with no Paint rect. 
 637     if (!(m_vRclPaint
.yTop 
== 0 && 
 638           m_vRclPaint
.yBottom 
== 0 && 
 639           m_vRclPaint
.xRight 
== 0 && 
 640           m_vRclPaint
.xLeft 
== 0)) 
 647         if (m_vSelectedBitmap
.Ok()) 
 649             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 650             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 661         vColor 
= m_pen
.GetColour().GetPixel(); 
 663     ::GpiSetColor(m_hPS
, vColor
); 
 664     ::GpiMove(m_hPS
, &vPoint
[0]); 
 665     ::GpiLine(m_hPS
, &vPoint
[1]); 
 666     CalcBoundingBox(vX1
, vY1
); 
 667     CalcBoundingBox(vX2
, vY2
); 
 668 } // end of wxPMDCImpl::DoDrawLine 
 670 ////////////////////////////////////////////////////////////////////////////// 
 671 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 672 // and ending at (x2, y2). The current pen is used for the outline and the 
 673 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 674 // direction from the start point to the end point. 
 675 ////////////////////////////////////////////////////////////////////////////// 
 676 void wxPMDCImpl::DoDrawArc( 
 686      POINTL                         vPtlArc
[2]; // Structure for current position 
 693      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 695     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 696         return; // Draw point ?? 
 697     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 700                       hypot( (double)(vY2 
- vYc
) 
 705     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 708     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 715     // GpiPointArc can't draw full arc 
 717      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 722         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 723         vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 724         vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 739     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 740     vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 741     vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 744     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 750     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 752     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 753     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 754     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 759     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 760     CalcBoundingBox( (wxCoord
)(vXc 
- dRadius
) 
 761                     ,(wxCoord
)(vYc 
- dRadius
) 
 763     CalcBoundingBox( (wxCoord
)(vXc 
+ dRadius
) 
 764                     ,(wxCoord
)(vYc 
+ dRadius
) 
 766 } // end of wxPMDCImpl::DoDrawArc 
 768 void wxPMDCImpl::DoDrawCheckMark( 
 777     vY1 
= OS2Y(vY1
,vHeight
); 
 781     vPoint
[1].x 
= vX1 
+ vWidth
; 
 782     vPoint
[1].y 
= vY1 
+ vHeight
; 
 784     ::GpiMove(m_hPS
, &vPoint
[0]); 
 785     ::GpiBox( m_hPS       
// handle to a presentation space 
 786              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 787              ,&vPoint
[1]  // address of the corner 
 788              ,0L          // horizontal corner radius 
 789              ,0L          // vertical corner radius 
 791     if(vWidth 
> 4 && vHeight 
> 4) 
 795         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 796         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 797         ::GpiMove(m_hPS
, &vPoint
[0]); 
 798         ::GpiLine(m_hPS
, &vPoint
[1]); 
 800         vPoint
[0].x 
= vPoint
[1].x
; 
 802         ::GpiMove(m_hPS
, &vPoint
[0]); 
 803         ::GpiLine(m_hPS
, &vPoint
[1]); 
 809     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 810     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 815 } // end of wxPMDCImpl::DoDrawCheckMark 
 817 void wxPMDCImpl::DoDrawPoint( 
 823     COLORREF                        vColor 
= 0x00ffffff; 
 827         vColor 
= m_pen
.GetColour().GetPixel(); 
 829     ::GpiSetColor(m_hPS
, vColor
); 
 831     vPoint
.y 
= OS2Y(vY
,0); 
 832     ::GpiSetPel(m_hPS
, &vPoint
); 
 836 } // end of wxPMDCImpl::DoDrawPoint 
 838 void wxPMDCImpl::DoDrawPolygon( int n
, 
 844     ULONG     ulCount 
= 1;    // Number of polygons. 
 845     POLYGON   vPlgn
;          // polygon. 
 846     ULONG     flOptions 
= 0L; // Drawing options. 
 848     ////////////////////////////////////////////////////////////////////////////// 
 849     // This contains fields of option bits... to draw boundary lines as well as 
 850     // the area interior. 
 852     // Drawing boundary lines: 
 853     //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 854     //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 856     // Construction of the area interior: 
 857     //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 859     //   POLYGON_WINDING                 Constructs interior in winding mode. 
 860     ////////////////////////////////////////////////////////////////////////////// 
 862     ULONG     flModel 
= POLYGON_INCL
; // Drawing model. 
 864     ////////////////////////////////////////////////////////////////////////////// 
 866     //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 867     //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 868     //       This is provided to aid migration from other graphics models. 
 869     ////////////////////////////////////////////////////////////////////////////// 
 871     LONG      lHits 
= 0L; // Correlation/error indicator. 
 873     int       nIsTRANSPARENT 
= 0; 
 874     LONG      lBorderColor 
= 0L; 
 877     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 878     lColor       
= m_brush
.GetColour().GetPixel(); 
 879     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 883     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 885                                     ); // well, new will call malloc 
 887     for(i 
= 0; i 
< n
; i
++) 
 889         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
+vXoffset
; 
 890         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
+vYoffset
,0); 
 892     flOptions 
= POLYGON_BOUNDARY
; 
 893     if(nFillStyle 
== wxWINDING_RULE
) 
 894         flOptions 
|= POLYGON_WINDING
; 
 896         flOptions 
|= POLYGON_ALTERNATE
; 
 898     ::GpiSetColor(m_hPS
, lBorderColor
); 
 899     ::GpiMove(m_hPS
, &vPlgn
.aPointl
[0]); 
 900     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 902 } // end of wxPMDCImpl::DoDrawPolygon 
 904 void wxPMDCImpl::DoDrawLines( 
 913     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 917         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 918         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 919         ::GpiMove(m_hPS
, &vPoint
); 
 921         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 923         ::GpiSetColor(m_hPS
, lBorderColor
); 
 924         for(i 
= 1; i 
< n
; i
++) 
 926             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 927             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 928             ::GpiLine(m_hPS
, &vPoint
); 
 935         CalcBoundingBox( vPoints
[0].x
 
 938         vPoint
.x 
= vPoints
[0].x
; 
 939         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 940         ::GpiMove(m_hPS
, &vPoint
); 
 942         for (i 
= 0; i 
< n
; i
++) 
 944             CalcBoundingBox( vPoints
[i
].x
 
 947             vPoint
.x 
= vPoints
[i
].x
; 
 948             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 949             ::GpiLine(m_hPS
, &vPoint
); 
 952 } // end of wxPMDCImpl::DoDrawLines 
 954 void wxPMDCImpl::DoDrawRectangle( 
 965     int                             nIsTRANSPARENT 
= 0; 
 968     // Might be a memory DC with no Paint rect. 
 970     if (!(m_vRclPaint
.yTop 
== 0 && 
 971           m_vRclPaint
.yBottom 
== 0 && 
 972           m_vRclPaint
.xRight 
== 0 && 
 973           m_vRclPaint
.xLeft 
== 0)) 
 974         vY 
= OS2Y(vY
,vHeight
); 
 977         if (m_vSelectedBitmap
.Ok()) 
 979             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 980             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 981             vY 
= OS2Y(vY
,vHeight
); 
 985     wxCoord                         vX2 
= vX 
+ vWidth
; 
 986     wxCoord                         vY2 
= vY 
+ vHeight
; 
 990     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
 991     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
 992     ::GpiMove(m_hPS
, &vPoint
[0]); 
 993     lColor       
= m_brush
.GetColour().GetPixel(); 
 994     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 995     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
 997     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
 999         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1000         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1001             lControl 
= DRO_OUTLINE
; 
1003         ::GpiSetColor(m_hPS
, lBorderColor
); 
1004         ::GpiBox( m_hPS       
// handle to a presentation space 
1005                  ,lControl   
// draw the box outline ? or ? 
1006                  ,&vPoint
[1]  // address of the corner 
1007                  ,0L          // horizontal corner radius 
1008                  ,0L          // vertical corner radius 
1013         lControl 
= DRO_OUTLINE
; 
1014         ::GpiSetColor( m_hPS
 
1023         lControl 
= DRO_FILL
; 
1024         ::GpiSetColor( m_hPS
 
1027         vPoint
[0].x 
= vX 
+ 1; 
1028         vPoint
[0].y 
= vY 
+ 1; 
1029         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1030         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1031         ::GpiMove(m_hPS
, &vPoint
[0]); 
1039     CalcBoundingBox(vX
, vY
); 
1040     CalcBoundingBox(vX2
, vY2
); 
1041 } // end of wxPMDCImpl::DoDrawRectangle 
1043 void wxPMDCImpl::DoDrawRoundedRectangle( 
1055     int                             nIsTRANSPARENT 
= 0; 
1058     // Might be a memory DC with no Paint rect. 
1060     if (!(m_vRclPaint
.yTop 
== 0 && 
1061           m_vRclPaint
.yBottom 
== 0 && 
1062           m_vRclPaint
.xRight 
== 0 && 
1063           m_vRclPaint
.xLeft 
== 0)) 
1064         vY 
= OS2Y(vY
,vHeight
); 
1067         if (m_vSelectedBitmap
.Ok()) 
1069             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1070             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1071             vY 
= OS2Y(vY
,vHeight
); 
1075     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1076     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1080     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1081     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1082     ::GpiMove(m_hPS
, &vPoint
[0]); 
1084     lColor       
= m_brush
.GetColour().GetPixel(); 
1085     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1086     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1087     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1089     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1091         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1092         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1093             lControl 
= DRO_OUTLINE
; 
1095         ::GpiSetColor(m_hPS
, lColor
); 
1096         ::GpiBox( m_hPS         
// handle to a presentation space 
1097                  ,lControl      
// draw the box outline ? or ? 
1098                  ,&vPoint
[1]    // address of the corner 
1099                  ,(LONG
)dRadius 
// horizontal corner radius 
1100                  ,(LONG
)dRadius 
// vertical corner radius 
1105         lControl 
= DRO_OUTLINE
; 
1106         ::GpiSetColor( m_hPS
 
1115         lControl 
= DRO_FILL
; 
1116         ::GpiSetColor( m_hPS
 
1119         vPoint
[0].x 
= vX 
+ 1; 
1120         vPoint
[0].y 
= vY 
+ 1; 
1121         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1122         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1123         ::GpiMove(m_hPS
, &vPoint
[0]); 
1132     CalcBoundingBox(vX
, vY
); 
1133     CalcBoundingBox(vX2
, vY2
); 
1134 } // end of wxPMDCImpl::DoDrawRoundedRectangle 
1136 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1137 void wxPMDCImpl::DoDrawEllipse( 
1144     POINTL                          vPtlPos
; // Structure for current position 
1145     FIXED                           vFxMult
; // Multiplier for ellipse 
1146     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1148     vY 
= OS2Y(vY
,vHeight
); 
1151     vArcp
.lQ 
= vHeight
/2; 
1152     vArcp
.lP 
= vWidth
/2; 
1154     ::GpiSetArcParams( m_hPS
 
1156                      ); // Sets parameters to default 
1157     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1158     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1161              ); // Sets current position 
1162     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1165     // DRO_FILL, DRO_OTLINEFILL - where to get 
1170                 ); // Draws full arc with center at current position 
1172     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1173     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1175     CalcBoundingBox(vX
, vY
); 
1176     CalcBoundingBox(vX2
, vY2
); 
1177 } // end of wxPMDCImpl::DoDrawEllipse 
1179 void wxPMDCImpl::DoDrawEllipticArc( 
1188     POINTL                          vPtlPos
; // Structure for current position 
1189     FIXED                           vFxMult
; // Multiplier for ellipse 
1190     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1192     FIXED                           vFSweepa
; // Start angle, sweep angle 
1196     vY 
= OS2Y(vY
,vHeight
); 
1198     dFractPart 
= modf(dSa
,&dIntPart
); 
1199     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1200     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1201     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1204     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1207     vArcp
.lQ 
= vHeight
/2; 
1208     vArcp
.lP 
= vWidth
/2; 
1210     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1211     vPtlPos
.x 
= (wxCoord
)(vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
)))); // Loads x-coordinate 
1212     vPtlPos
.y 
= (wxCoord
)(vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
)))); // Loads y-coordinate 
1213     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1216     // May be not to the center ? 
1218     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1219     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1220     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1223     // DRO_FILL, DRO_OTLINEFILL - where to get 
1225     ::GpiPartialArc( m_hPS
 
1231     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1232     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1234     CalcBoundingBox(vX
, vY
); 
1235     CalcBoundingBox(vX2
, vY2
); 
1236 } // end of wxPMDCImpl::DoDrawEllipticArc 
1238 void wxPMDCImpl::DoDrawIcon( 
1245     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords 
1246     // and I don't feel like figuring those out for scrollable windows so 
1247     // just convert to a bitmap then let the DoDrawBitmap routine display it 
1251         DoDrawBitmap(rIcon
.GetXpmSrc(), vX
, vY
, true); 
1255         wxBitmap                        
vBitmap(rIcon
); 
1257         DoDrawBitmap(vBitmap
, vX
, vY
, false); 
1259     CalcBoundingBox(vX
, vY
); 
1260     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1261 } // end of wxPMDCImpl::DoDrawIcon 
1263 void wxPMDCImpl::DoDrawBitmap( 
1264   const wxBitmap
&                   rBmp
 
1270 #if wxUSE_PRINTING_ARCHITECTURE 
1271     if (!IsKindOf(CLASSINFO(wxPrinterDC
))) 
1274         HBITMAP                         hBitmap 
=  (HBITMAP
)rBmp
.GetHBITMAP(); 
1275         HBITMAP                         hBitmapOld 
= NULLHANDLE
; 
1278         vY 
= OS2Y(vY
,rBmp
.GetHeight()); 
1281         vPoint
[0].y 
= vY 
+ rBmp
.GetHeight(); 
1282         vPoint
[1].x 
= vX 
+ rBmp
.GetWidth(); 
1286         vPoint
[3].x 
= rBmp
.GetWidth(); 
1287         vPoint
[3].y 
= rBmp
.GetHeight(); 
1290             wxMask
*                     pMask 
= rBmp
.GetMask(); 
1295                 // Need to imitate ::MaskBlt in windows. 
1296                 // 1) Extract the bits from from the bitmap. 
1297                 // 2) Extract the bits from the mask 
1298                 // 3) Using the mask bits do the following: 
1299                 //   A) If the mask byte is 00 leave the bitmap byte alone 
1300                 //   B) If the mask byte is FF copy the screen color into 
1302                 // 4) Create a new bitmap and set its bits to the above result 
1303                 // 5) Blit this to the screen PS 
1305                 HBITMAP                 hMask 
= (HBITMAP
)pMask
->GetMaskBitmap(); 
1306                 HBITMAP                 hOldMask   
= NULLHANDLE
; 
1307                 HBITMAP                 hOldBitmap 
= NULLHANDLE
; 
1308                 HBITMAP                 hNewBitmap 
= NULLHANDLE
; 
1309                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1310                 unsigned char*          pucBitsMask
; // buffer that will contain the mask data 
1311                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1312                 unsigned char*          pucDataMask
; // pointer to use to traverse mask data 
1318                 // The usual Memory context creation stuff 
1320                 DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1321                 SIZEL                           vSize 
= {0, 0}; 
1322                 HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1323                 HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1326                 // The usual bitmap header stuff 
1328                 BITMAPINFOHEADER2               vHeader
; 
1331                 memset(&vHeader
, '\0', 16); 
1334                 memset(&vInfo
, '\0', 16); 
1336                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1337                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1339                 vInfo
.cBitCount       
= 24; // Set to desired count going in 
1342                 // Create the buffers for data....all wxBitmaps are 24 bit internally 
1344                 int                     nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1345                 int                     nSizeDWORD    
= sizeof(DWORD
); 
1346                 int                     nLineBoundary 
= nBytesPerLine 
% nSizeDWORD
; 
1354                 // Need to get a background color for mask blitting 
1356                 if (IsKindOf(CLASSINFO(wxWindowDCImpl
))) 
1358                     wxWindowDCImpl
*  pWindowDC 
= wxDynamicCast(this, wxWindowDCImpl
); 
1360                     lColor 
= pWindowDC
->m_pCanvas
->GetBackgroundColour().GetPixel(); 
1362                 else if (GetBrush().Ok()) 
1363                     lColor 
= GetBrush().GetColour().GetPixel(); 
1365                     lColor 
= m_textBackgroundColour
.GetPixel(); 
1368                 // Bitmap must be in a double-word aligned address so we may 
1369                 // have some padding to worry about 
1371                 if (nLineBoundary 
> 0) 
1373                     nPadding     
= nSizeDWORD 
- nLineBoundary
; 
1374                     nBytesPerLine 
+= nPadding
; 
1376                 pucBits 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1377                 pucBitsMask 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1378                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1379                 memset(pucBitsMask
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1382                 // Extract the bitmap and mask data 
1384                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1386                     vError 
= ::WinGetLastError(vHabmain
); 
1387                     sError 
= wxPMErrorToStr(vError
); 
1389                 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
); 
1390                 vInfo
.cBitCount 
= 24; 
1391                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1393                                                    ,(LONG
)rBmp
.GetHeight() 
1398                     vError 
= ::WinGetLastError(vHabmain
); 
1399                     sError 
= wxPMErrorToStr(vError
); 
1401                 if ((hOldMask 
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
) 
1403                     vError 
= ::WinGetLastError(vHabmain
); 
1404                     sError 
= wxPMErrorToStr(vError
); 
1406                 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
); 
1407                 vInfo
.cBitCount 
= 24; 
1408                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1410                                                    ,(LONG
)rBmp
.GetHeight() 
1415                     vError 
= ::WinGetLastError(vHabmain
); 
1416                     sError 
= wxPMErrorToStr(vError
); 
1418                 if (( hMask 
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
) 
1420                     vError 
= ::WinGetLastError(vHabmain
); 
1421                     sError 
= wxPMErrorToStr(vError
); 
1425                 // Now set the bytes(bits) according to the mask values 
1426                 // 3 bytes per pel...must handle one at a time 
1429                 pucDataMask 
= pucBitsMask
; 
1432                 // 16 bit kludge really only kinda works.  The mask gets applied 
1433                 // where needed but the original bitmap bits are dorked sometimes 
1435                 bool                    bpp16 
= (wxDisplayDepth() == 16); 
1437                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1439                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1442                         if (bpp16 
&& *pucDataMask 
== 0xF8) // 16 bit display gobblygook 
1444                         else if (*pucDataMask 
== 0xFF) // leave bitmap byte alone 
1448                             *pucData 
= ((unsigned char)(lColor 
>> 16)); 
1452                         if (bpp16 
&& *(pucDataMask 
+ 1) == 0xFC) // 16 bit display gobblygook 
1454                         else if (*(pucDataMask 
+ 1) == 0xFF) // leave bitmap byte alone 
1458                             *pucData 
= ((unsigned char)(lColor 
>> 8)); 
1463                         if (bpp16 
&& *(pucDataMask 
+ 2) == 0xF8) // 16 bit display gobblygook 
1465                         else if (*(pucDataMask 
+ 2) == 0xFF) // leave bitmap byte alone 
1469                             *pucData 
= ((unsigned char)lColor
); 
1474                     for (j 
= 0; j 
< nPadding
; j
++) 
1481                 // Create a new bitmap 
1483                 vHeader
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1484                 vHeader
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1485                 vHeader
.cPlanes         
= 1L; 
1486                 vHeader
.cBitCount       
= 24; 
1487                 if ((hNewBitmap 
= ::GpiCreateBitmap( hPS
 
1494                     vError 
= ::WinGetLastError(vHabmain
); 
1495                     sError 
= wxPMErrorToStr(vError
); 
1499                 // Now blit it to the screen PS 
1501                 if ((lHits 
= ::GpiWCBitBlt( (HPS
)GetHPS() 
1509                     vError 
= ::WinGetLastError(vHabmain
); 
1510                     sError 
= wxPMErrorToStr(vError
); 
1518                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1519                 ::GpiDeleteBitmap(hNewBitmap
); 
1520                 ::GpiDestroyPS(hPS
); 
1526             ULONG                       lOldForeGround 
= ::GpiQueryColor((HPS
)GetHPS()); 
1527             ULONG                       lOldBackGround 
= ::GpiQueryBackColor((HPS
)GetHPS()); 
1529             if (m_textForegroundColour
.Ok()) 
1531                 ::GpiSetColor( (HPS
)GetHPS() 
1532                                ,m_textForegroundColour
.GetPixel() 
1535             if (m_textBackgroundColour
.Ok()) 
1537                 ::GpiSetBackColor( (HPS
)GetHPS() 
1538                                   ,m_textBackgroundColour
.GetPixel() 
1542             // Need to alter bits in a mono bitmap to match the new 
1543             // background-foreground if it is different. 
1545             if (rBmp
.IsMono() && 
1546                ((m_textForegroundColour
.GetPixel() != lOldForeGround
) || 
1547                 (m_textBackgroundColour
.GetPixel() != lOldBackGround
))) 
1549                 DEVOPENSTRUC        vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1550                 SIZEL               vSize 
= {0, 0}; 
1551                 HDC                 hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1552                 HPS                 hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1554                 int                 nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1556                 LONG                lForeGround 
= m_textForegroundColour
.GetPixel(); 
1557                 LONG                lBackGround 
= m_textBackgroundColour
.GetPixel(); 
1559                 HBITMAP             hOldBitmap 
= NULLHANDLE
; 
1565                 memset(&vInfo
, '\0', 16); 
1567                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1568                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1570                 vInfo
.cBitCount       
= 24; 
1572                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1573                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1575                 pucBits 
= new unsigned char[nBytesPerLine 
* rBmp
.GetHeight()]; 
1576                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1578                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1580                     vError 
= ::WinGetLastError(vHabmain
); 
1581                     sError 
= wxPMErrorToStr(vError
); 
1584                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1586                                                    ,(LONG
)rBmp
.GetHeight() 
1591                     vError 
= ::WinGetLastError(vHabmain
); 
1592                     sError 
= wxPMErrorToStr(vError
); 
1595                 unsigned char           cOldRedFore   
= (unsigned char)(lOldForeGround 
>> 16); 
1596                 unsigned char           cOldGreenFore 
= (unsigned char)(lOldForeGround 
>> 8); 
1597                 unsigned char           cOldBlueFore  
= (unsigned char)lOldForeGround
; 
1599                 unsigned char           cRedFore   
= (unsigned char)(lForeGround 
>> 16); 
1600                 unsigned char           cGreenFore 
= (unsigned char)(lForeGround 
>> 8); 
1601                 unsigned char           cBlueFore  
= (unsigned char)lForeGround
; 
1603                 unsigned char           cRedBack   
= (unsigned char)(lBackGround 
>> 16); 
1604                 unsigned char           cGreenBack 
= (unsigned char)(lBackGround 
>> 8); 
1605                 unsigned char           cBlueBack  
= (unsigned char)lBackGround
; 
1608                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1610                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1612                         unsigned char    cBmpRed   
= *pucData
; 
1613                         unsigned char    cBmpGreen 
= *(pucData 
+ 1); 
1614                         unsigned char    cBmpBlue  
= *(pucData 
+ 2); 
1616                         if ((cBmpRed 
== cOldRedFore
) && 
1617                             (cBmpGreen 
== cOldGreenFore
) && 
1618                             (cBmpBlue 
== cOldBlueFore
)) 
1620                             *pucData 
= cBlueFore
; 
1622                             *pucData 
= cGreenFore
; 
1624                             *pucData 
= cRedFore
; 
1629                             *pucData 
= cBlueBack
; 
1631                             *pucData 
= cGreenBack
; 
1633                             *pucData 
= cRedBack
; 
1638                 if ((lScans 
= ::GpiSetBitmapBits( hPS
 
1640                                                  ,(LONG
)rBmp
.GetHeight() 
1645                     vError 
= ::WinGetLastError(vHabmain
); 
1646                     sError 
= wxPMErrorToStr(vError
); 
1650                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1651                 ::GpiDestroyPS(hPS
); 
1654             ::GpiWCBitBlt( (HPS
)GetHPS() 
1661             ::GpiSetBitmap((HPS
)GetHPS(), hBitmapOld
); 
1662             ::GpiSetColor((HPS
)GetHPS(), lOldForeGround
); 
1663             ::GpiSetBackColor((HPS
)GetHPS(), lOldBackGround
); 
1666 } // end of wxPMDCImpl::DoDrawBitmap 
1668 void wxPMDCImpl::DoDrawText( 
1669   const wxString
&                   rsText
 
1682     CalcBoundingBox(vX
, vY
); 
1683     GetOwner()->GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1684     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1685 } // end of wxPMDCImpl::DoDrawText 
1687 void wxPMDCImpl::DrawAnyText( const wxString
& rsText
, 
1691     int                             nOldBackground 
= 0; 
1698     // prepare for drawing the text 
1702     // Set text color attributes 
1704     if (m_textForegroundColour
.Ok()) 
1707                      ,(int)m_textForegroundColour
.GetPixel() 
1711     if (m_textBackgroundColour
.Ok()) 
1713         nOldBackground 
= SetTextBkColor( m_hPS
 
1714                                         ,(int)m_textBackgroundColour
.GetPixel() 
1720     GetOwner()->GetTextExtent( rsText
 
1725     if (!(m_vRclPaint
.yTop 
== 0 && 
1726           m_vRclPaint
.yBottom 
== 0 && 
1727           m_vRclPaint
.xRight 
== 0 && 
1728           m_vRclPaint
.xLeft 
== 0)) 
1730         vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1734         if (m_vSelectedBitmap
.Ok()) 
1736             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1737             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1738             vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1744     ::GpiMove(m_hPS
, &vPtlStart
); 
1745     lHits 
= ::GpiCharString( m_hPS
 
1749     if (lHits 
!= GPI_OK
) 
1751         wxLogLastError(wxT("TextOut")); 
1755     // Restore the old parameters (text foreground colour may be left because 
1756     // it never is set to anything else, but background should remain 
1757     // transparent even if we just drew an opaque string) 
1759     if (m_textBackgroundColour
.Ok()) 
1760             SetTextBkColor( m_hPS
 
1768 void wxPMDCImpl::DoDrawRotatedText( 
1769   const wxString
&                   rsText
 
1787         DoDrawText(text, x, y); 
1792         wxFillLogFont(&lf, &m_font); 
1794         // GDI wants the angle in tenth of degree 
1795         long angle10 = (long)(angle * 10); 
1796         lf.lfEscapement = angle10; 
1797         lf. lfOrientation = angle10; 
1799         HFONT hfont = ::CreateFontIndirect(&lf); 
1802             wxLogLastError("CreateFont"); 
1806             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1808             DrawAnyText(text, x, y); 
1810             (void)::SelectObject(GetHdc(), hfontOld); 
1813         // call the bounding box by adding all four vertices of the rectangle 
1814         // containing the text to it (simpler and probably not slower than 
1815         // determining which of them is really topmost/leftmost/...) 
1817         GetTextExtent(text, &w, &h); 
1819         double rad = DegToRad(angle); 
1821         // "upper left" and "upper right" 
1822         CalcBoundingBox(x, y); 
1823         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1824         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1826         // "bottom left" and "bottom right" 
1827         x += (wxCoord)(h*sin(rad)); 
1828         y += (wxCoord)(h*cos(rad)); 
1829         CalcBoundingBox(x, y); 
1830         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1835 // --------------------------------------------------------------------------- 
1837 // --------------------------------------------------------------------------- 
1839 void wxPMDCImpl::DoSelectPalette( bool WXUNUSED(bRealize
) ) 
1842     // Set the old object temporarily, in case the assignment deletes an object 
1843     // that's not yet selected out. 
1854         hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1856             m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1858 } // end of wxPMDCImpl::DoSelectPalette 
1860 void wxPMDCImpl::InitializePalette() 
1862     if (wxDisplayDepth() <= 8 ) 
1865         // Look for any window or parent that has a custom palette. If any has 
1866         // one then we need to use it in drawing operations 
1868         wxWindow
*                   pWin 
= m_pCanvas
->GetAncestorWithCustomPalette(); 
1870         m_hasCustomPalette 
= pWin 
&& pWin
->HasCustomPalette(); 
1871         if (m_hasCustomPalette
) 
1873             m_palette 
= pWin
->GetPalette(); 
1876             // turn on PM translation for this palette 
1881 } // end of wxPMDCImpl::InitializePalette 
1883 void wxPMDCImpl::SetPalette( 
1884   const wxPalette
&                  rPalette
 
1891     m_palette 
= rPalette
; 
1899     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1901         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1902 } // end of wxPMDCImpl::SetPalette 
1904 void wxPMDCImpl::SetFont( 
1909     // Set the old object temporarily, in case the assignment deletes an object 
1910     // that's not yet selected out. 
1922     m_font
.SetPS(m_hPS
); // this will realize the font 
1926         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1927         if (hFont 
== (HFONT
) NULL
) 
1929             wxLogDebug(wxT("::SelectObject failed in wxPMDCImpl::SetFont.")); 
1932             m_hOldFont 
= (WXHFONT
) hFont
; 
1934 } // end of wxPMDCImpl::SetFont 
1936 void wxPMDCImpl::SetPen( 
1954             m_pen
.SetPS((HPS
)m_hOldPen
); 
1961         if (m_pen
.GetResourceHandle()) 
1965                 m_hOldPen 
= m_pen
.GetPS(); 
1967         ::GpiSetColor(m_hPS
, m_pen
.GetColour().GetPixel()); 
1971 void wxPMDCImpl::SetBrush( 
1972   const wxBrush
&                    rBrush
 
1979     if (m_brush 
== rBrush
) 
1989             m_brush
.SetPS((HPS
)m_hOldBrush
); 
1996         if (m_brush
.GetResourceHandle()) 
1998             m_brush
.SetPS(m_hPS
); 
2000                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
2003 } // end of wxPMDCImpl::SetBrush 
2005 void wxPMDCImpl::SetBackground(const wxBrush
& rBrush
) 
2007     m_backgroundBrush 
= rBrush
; 
2009     if (m_backgroundBrush
.Ok()) 
2011         (void)::GpiSetBackColor((HPS
)m_hPS
, m_backgroundBrush
.GetColour().GetPixel()); 
2013 } // end of wxPMDCImpl::SetBackground 
2015 void wxPMDCImpl::SetBackgroundMode(int nMode
) 
2017     m_backgroundMode 
= nMode
; 
2018 } // end of wxPMDCImpl::SetBackgroundMode 
2020 void wxPMDCImpl::SetLogicalFunction(int nFunction
) 
2022     m_logicalFunction 
= nFunction
; 
2023     SetRop((WXHDC
)m_hDC
); 
2024 } // wxPMDCImpl::SetLogicalFunction 
2026 void wxPMDCImpl::SetRop(WXHDC hDC
) 
2028     if (!hDC 
|| m_logicalFunction 
< 0) 
2032     switch (m_logicalFunction
) 
2043             lCRop 
= FM_MERGESRCNOT
; 
2047             lCRop 
= FM_NOTMASKSRC
; 
2059             lCRop 
= FM_MERGENOTSRC
; 
2063             lCRop 
= FM_MERGESRCNOT
; 
2075             lCRop 
= FM_SUBTRACT
; 
2082             lCRop 
= FM_OVERPAINT
; 
2085     ::GpiSetMix((HPS
)hDC
, lCRop
); 
2086 } // end of wxPMDCImpl::SetRop 
2088 bool wxPMDCImpl::StartDoc( const wxString
& WXUNUSED(rsMessage
) ) 
2090     // We might be previewing, so return true to let it continue. 
2092 } // end of wxPMDCImpl::StartDoc 
2094 void wxPMDCImpl::EndDoc() 
2096 } // end of wxPMDCImpl::EndDoc 
2098 void wxPMDCImpl::StartPage() 
2100 } // end of wxPMDCImpl::StartPage 
2102 void wxPMDCImpl::EndPage() 
2104 } // end of wxPMDCImpl::EndPage 
2106 // --------------------------------------------------------------------------- 
2108 // --------------------------------------------------------------------------- 
2110 wxCoord 
wxPMDCImpl::GetCharHeight() const 
2112     FONTMETRICS                     vFM
; // metrics structure 
2114     ::GpiQueryFontMetrics( m_hPS
 
2115                           ,sizeof(FONTMETRICS
) 
2118     return YDEV2LOGREL(vFM
.lXHeight
); 
2121 wxCoord 
wxPMDCImpl::GetCharWidth() const 
2123     FONTMETRICS                     vFM
; // metrics structure 
2125     ::GpiQueryFontMetrics( m_hPS
 
2126                           ,sizeof(FONTMETRICS
) 
2129     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
2132 void wxPMDCImpl::DoGetTextExtent( 
2133   const wxString
&                   rsString
 
2136 , wxCoord
*                          pvDescent
 
2137 , wxCoord
*                          pvExternalLeading
 
2138 , const wxFont
*                     pTheFont
 
2141     POINTL                          avPoint
[TXTBOX_COUNT
]; 
2146     FONTMETRICS                     vFM
; // metrics structure 
2148     ERRORID                         vErrorCode
; // last error id code 
2149     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
2151     wxChar                          zMsg
[128]; // DEBUG 
2155         pFontToUse 
= (wxFont
*)&m_font
; 
2156     l 
= rsString
.length(); 
2159     // In world coordinates. 
2163         (void)wxMessageBox( _T("wxWidgets core library") 
2164                             ,"Using uninitialized DC for measuring text!\n" 
2169     bRc 
= ::GpiQueryTextBox( m_hPS
 
2171                             ,rsString
.char_str() 
2172                             ,TXTBOX_COUNT 
// return maximum information 
2173                             ,avPoint      
// array of coordinates points 
2177        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
2178        sError 
= wxPMErrorToStr(vErrorCode
); 
2180        wxSprintf(zMsg
, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString
.c_str(), vErrorCode
, sError
.c_str()); 
2181        (void)wxMessageBox( _T("wxWidgets core library") 
2187     vPtMin
.x 
= avPoint
[0].x
; 
2188     vPtMax
.x 
= avPoint
[0].x
; 
2189     vPtMin
.y 
= avPoint
[0].y
; 
2190     vPtMax
.y 
= avPoint
[0].y
; 
2191     for (i 
= 1; i 
< 4; i
++) 
2193         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
2194         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
2195         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
2196         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
2198     ::GpiQueryFontMetrics( m_hPS
 
2199                           ,sizeof(FONTMETRICS
) 
2204         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
2206         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
2208         *pvDescent 
= vFM
.lMaxDescender
; 
2209     if (pvExternalLeading
) 
2210         *pvExternalLeading 
= vFM
.lExternalLeading
; 
2213 void wxPMDCImpl::SetMapMode( 
2217     int                             nPixelWidth 
= 0; 
2218     int                             nPixelHeight 
= 0; 
2221     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
+1]; 
2223     m_mappingMode 
= nMode
; 
2225     if(::DevQueryCaps( m_hDC
 
2226                       ,CAPS_FAMILY                  
// id of first item 
2227                       ,CAPS_VERTICAL_RESOLUTION
+1   // number of items wanted 
2234         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
2235         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
2236         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2237         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2238         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
2239         nMmHeight 
= (lVertRes
/1000) * nPixelHeight
; 
2241     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
2246     double dMm2pixelsX 
= nPixelWidth
/(double)nMmWidth
; 
2247     double dMm2pixelsY 
= nPixelHeight
/(double)nMmHeight
; 
2252             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
2253             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
2257             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
2258             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
2262             m_logicalScaleX 
= dMm2pixelsX
; 
2263             m_logicalScaleY 
= dMm2pixelsY
; 
2267             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
2268             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
2273             m_logicalScaleX 
= 1.0; 
2274             m_logicalScaleY 
= 1.0; 
2281     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
2282     if (!ulOptions 
& PU_ARBITRARY
) 
2284         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
2285         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
2287     ComputeScaleAndOrigin(); 
2289 }; // end of wxPMDCImpl::SetMapMode 
2291 void wxPMDCImpl::SetUserScale( double dX
, 
2297     SetMapMode(m_mappingMode
); 
2298 } // end of wxPMDCImpl::SetUserScale 
2300 void wxPMDCImpl::SetAxisOrientation( bool bXLeftRight
, 
2303     m_signX 
= bXLeftRight 
? 1 : -1; 
2304     m_signY 
= bYBottomUp 
? -1 : 1; 
2306     SetMapMode(m_mappingMode
); 
2307 } // end of wxPMDCImpl::SetAxisOrientation 
2309 void wxPMDCImpl::SetLogicalOrigin( 
2316     ::GpiQueryPageViewport( m_hPS
 
2323     ::GpiSetPageViewport( m_hPS
 
2326 }; // end of wxPMDCImpl::SetLogicalOrigin 
2328 void wxPMDCImpl::SetDeviceOrigin( 
2335     m_deviceOriginX 
= vX
; 
2336     m_deviceOriginY 
= vY
; 
2337     ::GpiQueryPageViewport( m_hPS
 
2342     vRect
.yBottom 
-= vY
; 
2344     ::GpiSetPageViewport( m_hPS
 
2347 }; // end of wxPMDCImpl::SetDeviceOrigin 
2349 // --------------------------------------------------------------------------- 
2351 // --------------------------------------------------------------------------- 
2353 bool wxPMDCImpl::DoBlit( wxCoord vXdest
, 
2362                    wxCoord 
WXUNUSED(vXsrcMask
), 
2363                    wxCoord 
WXUNUSED(vYsrcMask
) ) 
2365     wxMask
*                         pMask 
= NULL
; 
2367     COLORREF                        vOldTextColor
; 
2368     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
2370     wxDCImpl 
*impl 
= pSource
->GetImpl(); 
2371     wxPMDCImpl 
*pm_impl 
= wxDynamicCast( impl
, wxPMDCImpl 
); 
2374         // TODO: Do we want to be able to blit 
2375         //       from other DCs too? 
2381         const wxBitmap
&             rBmp 
= pm_impl
->GetSelectedBitmap(); 
2383         pMask 
= rBmp
.GetMask(); 
2384         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
2390     ::GpiQueryAttrs( m_hPS
 
2395     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
2397     if (m_textForegroundColour
.Ok()) 
2399         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
2400         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2401                       ,PRIM_CHAR       
// Char primitive. 
2402                       ,CBB_COLOR       
// sets color. 
2404                       ,&vCbnd          
// buffer for attributes. 
2407     if (m_textBackgroundColour
.Ok()) 
2409         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
2412     LONG                            lRop 
= ROP_SRCCOPY
; 
2416         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
2417         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
2418         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
2419         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
2420         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
2421         case wxSET
:          lRop 
= ROP_ONE
;              break; 
2422         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
2423         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
2424         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
2425         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
2426         case wxNAND
:         lRop 
= 0x007700E6;           break; 
2427         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
2428         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
2429         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
2430         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
2431         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
2433            wxFAIL_MSG( wxT("unsupported logical function") ); 
2442         // Blit bitmap with mask 
2446         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2452         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2453         BITMAPINFOHEADER2               vBmpHdr
; 
2455         SIZEL                           vSize 
= {0, 0}; 
2458         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2459         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2460         vBmpHdr
.cx        
= vWidth
; 
2461         vBmpHdr
.cy        
= vHeight
; 
2462         vBmpHdr
.cPlanes   
= 1; 
2463         vBmpHdr
.cBitCount 
= 24; 
2465 #if wxUSE_DC_CACHEING 
2468             // create a temp buffer bitmap and DCs to access it and the mask 
2470             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2473             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2476             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2481             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2482             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2483             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2484             wxUnusedVar(hDCMask
); 
2488             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2489             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2490             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2491             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2492             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2496         POINTL                          aPoint1
[4] = { {0, 0} 
2499                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2501         POINTL                          aPoint2
[4] = { {0, 0} 
2504                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2506         POINTL                          aPoint3
[4] = { {vXdest
, vYdest
} 
2507                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2509                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2511         POINTL                          aPoint4
[4] = { {vXdest
, vYdest
} 
2512                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2516         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2517         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2520         // Copy dest to buffer 
2522         rc 
= ::GpiBitBlt( hPSBuffer
 
2529         if (rc 
== GPI_ERROR
) 
2531             wxLogLastError(wxT("BitBlt")); 
2535         // Copy src to buffer using selected raster op 
2537         rc 
= ::GpiBitBlt( hPSBuffer
 
2544         if (rc 
== GPI_ERROR
) 
2546             wxLogLastError(wxT("BitBlt")); 
2550         // Set masked area in buffer to BLACK (pixel value 0) 
2552         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2553         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2555         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2556         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2558         rc 
= ::GpiBitBlt( hPSBuffer
 
2565         if (rc 
== GPI_ERROR
) 
2567             wxLogLastError(wxT("BitBlt")); 
2571         // Set unmasked area in dest to BLACK 
2573         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2574         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2575         rc 
= ::GpiBitBlt( GetHPS() 
2582         if (rc 
== GPI_ERROR
) 
2584             wxLogLastError(wxT("BitBlt")); 
2588         // Restore colours to original values 
2590         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2591         ::GpiSetColor(GetHPS(), vPrevCol
); 
2594         // OR buffer to dest 
2596         rc 
= ::GpiBitBlt( GetHPS() 
2603         if (rc 
== GPI_ERROR
) 
2606             wxLogLastError(wxT("BitBlt")); 
2610         // Tidy up temporary DCs and bitmap 
2612         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2613         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2614 #if !wxUSE_DC_CACHEING 
2615         ::GpiDestroyPS(hPSMask
); 
2616         ::GpiDestroyPS(hPSBuffer
); 
2617         ::DevCloseDC(hDCMask
); 
2618         ::DevCloseDC(hDCBuffer
); 
2619         ::GpiDeleteBitmap(hBufBitmap
); 
2623     else // no mask, just BitBlt() it 
2625       POINTL                          aPoint
[4] = { {vXdest
, vYdest
} 
2626                            ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2628                            ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2631         bSuccess 
= (::GpiBitBlt( m_hPS
 
2640             wxLogLastError(wxT("BitBlt")); 
2643     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2644     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2645                   ,PRIM_CHAR       
// Char primitive. 
2646                   ,CBB_COLOR       
// sets color. 
2648                   ,&vCbnd          
// buffer for attributes. 
2650     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2654 void wxPMDCImpl::DoGetSize( int* pnWidth
, 
2655                             int* pnHeight 
) const 
2657     LONG lArray
[CAPS_HEIGHT
+1]; 
2659     if(::DevQueryCaps( m_hDC
 
2666             *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2668             *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2670 }; // end of wxPMDCImpl::DoGetSize( 
2672 void wxPMDCImpl::DoGetSizeMM( int* pnWidth
, 
2673                         int* pnHeight 
) const 
2675     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
+1]; 
2677     if(::DevQueryCaps( m_hDC
 
2679                       ,CAPS_VERTICAL_RESOLUTION
+1 
2685             int nWidth   
= lArray
[CAPS_WIDTH
]; 
2686             int nHorzRes 
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2687             // use fp to avoid returning 0 if nHorzRes < 1000 
2688             *pnWidth  
= (int)((nHorzRes
/1000.0) * nWidth
); 
2693             int nHeight  
= lArray
[CAPS_HEIGHT
]; 
2694             int nVertRes 
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2695             // use fp to avoid returning 0 if nVertRes < 1000 
2696             *pnHeight 
= (int)((nVertRes
/1000.0) * nHeight
); 
2699 }; // end of wxPMDCImpl::DoGetSizeMM 
2701 wxSize 
wxPMDCImpl::GetPPI() const 
2703     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
+1]; 
2707     if(::DevQueryCaps( m_hDC
 
2709                       ,CAPS_VERTICAL_RESOLUTION
+1 
2718         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2719         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2720         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2721         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2722         nWidth   
= (int)((nHorzRes
/39.3) * nPelWidth
); 
2723         nHeight  
= (int)((nVertRes
/39.3) * nPelHeight
); 
2725     wxSize 
ppisize(nWidth
, nHeight
); 
2727 } // end of wxPMDCImpl::GetPPI 
2729 void wxPMDCImpl::SetLogicalScale( double dX
, double dY 
) 
2731     m_logicalScaleX 
= dX
; 
2732     m_logicalScaleY 
= dY
; 
2733 }; // end of wxPMDCImpl::SetLogicalScale