1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  16     #include "wx/window.h" 
  19     #include "wx/dialog.h" 
  21     #include "wx/bitmap.h" 
  22     #include "wx/dcmemory.h" 
  25     #include "wx/msgdlg.h" 
  27     #include "wx/statusbr.h" 
  31 #include "wx/module.h" 
  32 #include "wx/dcprint.h" 
  36 #include "wx/os2/private.h" 
  38     IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  41 // wxWidgets uses the Microsoft convention that the origin is the UPPER left. 
  42 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  43 // In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 
  44 // perform the following transformation: 
  46 // Parent object height:     POBJHEIGHT 
  47 // Desried origin:           WXORIGINY 
  48 // Object to place's height: OBJHEIGHT 
  50 // To get the OS2 position from the wxWidgets one: 
  52 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  54 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  55 // OS/2 Presentation Space associated with the device context.  y is the 
  56 // desired application's y coordinate of the origin in wxWidgets space. 
  57 // objy is the height of the object we are going to draw. 
  59 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  61 // --------------------------------------------------------------------------- 
  63 // --------------------------------------------------------------------------- 
  65 static const int VIEWPORT_EXTENT 
= 1000; 
  67 static const int MM_POINTS 
= 9; 
  68 static const int MM_METRIC 
= 10; 
  70 // --------------------------------------------------------------------------- 
  72 // --------------------------------------------------------------------------- 
  74 // convert degrees to radians 
  75 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  79 , int                               nForegroundColour
 
  84     vCbnd
.lColor 
=  nForegroundColour
; 
  85     ::GpiSetAttrs( hPS       
// presentation-space handle 
  86                   ,PRIM_CHAR 
// Char primitive. 
  87                   ,CBB_COLOR 
// sets color. 
  89                   ,&vCbnd    
// buffer for attributes. 
 100     ::GpiQueryAttrs( hPS            
// presentation-space handle 
 101                     ,PRIM_CHAR      
// Char primitive. 
 102                     ,CBB_BACK_COLOR 
// Background color. 
 103                     ,&vCbnd         
// buffer for attributes. 
 105     return vCbnd
.lBackColor
; 
 111 , int                               nBackgroundColour
 
 117     rc 
=  QueryTextBkColor(hPS
); 
 119     vCbnd
.lBackColor 
= nBackgroundColour
; 
 120     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 121                   PRIM_CHAR
,      // Char primitive. 
 122                   CBB_BACK_COLOR
, // sets color. 
 124                   &vCbnd          
// buffer for attributes. 
 131 , int                               nBackgroundMode
 
 134     if(nBackgroundMode 
== wxTRANSPARENT
) 
 139         // the background of the primitive takes  over whatever is underneath. 
 146 // =========================================================================== 
 148 // =========================================================================== 
 150 #if wxUSE_DC_CACHEING 
 153  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 154  * improve it in due course, either using arrays, or simply storing pointers to one 
 155  * entry for the bitmap, and two for the DCs. -- JACS 
 158 // --------------------------------------------------------------------------- 
 160 // --------------------------------------------------------------------------- 
 162 wxList 
wxDC::m_svBitmapCache
; 
 163 wxList 
wxDC::m_svDCCache
; 
 165 wxDCCacheEntry::wxDCCacheEntry( 
 177 } // end of wxDCCacheEntry::wxDCCacheEntry 
 179 wxDCCacheEntry::wxDCCacheEntry( 
 184     m_hBitmap 
= NULLHANDLE
; 
 189 } // end of wxDCCacheEntry::wxDCCacheEntry 
 191 wxDCCacheEntry::~wxDCCacheEntry() 
 194         ::GpiDeleteBitmap(m_hBitmap
); 
 196         ::GpiDestroyPS(m_hPS
); 
 197 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 199 wxDCCacheEntry
* wxDC::FindBitmapInCache( 
 205     int                             nDepth 
= 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 206     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 207     BITMAPINFOHEADER2               vBmpHdr
; 
 211         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 213         if (pEntry
->m_nDepth 
== nDepth
) 
 215             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 217             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 219                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 220                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 222                 vBmpHdr
.cy        
= nHeight
; 
 224                 vBmpHdr
.cBitCount 
= nDepth
; 
 226                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 230                 if (!pEntry
->m_hBitmap
) 
 232                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 234                 pEntry
->m_nWidth  
= nWidth
; 
 235                 pEntry
->m_nHeight 
= nHeight
; 
 240         pNode 
= pNode
->Next(); 
 242     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 243     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 245     vBmpHdr
.cy        
= nHeight
; 
 247     vBmpHdr
.cBitCount 
= nDepth
; 
 249     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 255         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 257     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 262     AddToBitmapCache(pEntry
); 
 264 } // end of FindBitmapInCache 
 266 wxDCCacheEntry
* wxDC::FindDCInCache( 
 267   wxDCCacheEntry
*                   pNotThis
 
 271     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 272     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 276         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 279         // Don't return the same one as we already have 
 281         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 283             if (pEntry
->m_nDepth 
== nDepth
) 
 288         pNode 
= pNode
->Next(); 
 290     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 293     AddToDCCache(pEntry
); 
 295 } // end of wxDC::FindDCInCache 
 297 void wxDC::AddToBitmapCache( 
 298   wxDCCacheEntry
*                   pEntry
 
 301     m_svBitmapCache
.Append(pEntry
); 
 302 } // end of wxDC::AddToBitmapCache 
 304 void wxDC::AddToDCCache( 
 305   wxDCCacheEntry
*                   pEntry
 
 308     m_svDCCache
.Append(pEntry
); 
 309 } // end of wxDC::AddToDCCache 
 311 void wxDC::ClearCache() 
 313     m_svBitmapCache
.DeleteContents(true); 
 314     m_svBitmapCache
.Clear(); 
 315     m_svBitmapCache
.DeleteContents(false); 
 316     m_svDCCache
.DeleteContents(true); 
 318     m_svDCCache
.DeleteContents(false); 
 319 } // end of wxDC::ClearCache 
 321 // Clean up cache at app exit 
 322 class wxDCModule 
: public wxModule
 
 325     virtual bool OnInit() { return true; } 
 326     virtual void OnExit() { wxDC::ClearCache(); } 
 329     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 330 }; // end of CLASS wxDCModule 
 332 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 334 #endif // ndef for wxUSE_DC_CACHEING 
 336 // --------------------------------------------------------------------------- 
 338 // --------------------------------------------------------------------------- 
 354     m_bIsPaintTime 
= false; // True at Paint Time 
 356     wxColour 
vColor( wxT("BLACK") ); 
 357     m_pen
.SetColour(vColor
); 
 359     vColor
.Set( wxT("WHITE") ); 
 360     m_brush
.SetColour(vColor
); 
 362 } // end of wxDC::wxDC 
 368         SelectOldObjects(m_hDC
); 
 370         // if we own the HDC, we delete it, otherwise we just release it 
 376                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 377                 ::GpiDestroyPS(m_hPS
); 
 380             ::DevCloseDC((HDC
)m_hDC
); 
 385             // Just Dissacociate, not destroy if we don't own the DC 
 389                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 393 } // end of wxDC::~wxDC 
 395 // This will select current objects out of the DC, 
 396 // which is what you have to do before deleting the 
 398 void wxDC::SelectOldObjects( 
 406             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 407             if (m_vSelectedBitmap
.Ok()) 
 409                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 414         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 422     m_brush           
= wxNullBrush
; 
 424     m_palette         
= wxNullPalette
; 
 426     m_backgroundBrush 
= wxNullBrush
; 
 427     m_vSelectedBitmap 
= wxNullBitmap
; 
 428 } // end of wxDC::SelectOldObjects 
 430 // --------------------------------------------------------------------------- 
 432 // --------------------------------------------------------------------------- 
 434 #define DO_SET_CLIPPING_BOX()                    \ 
 438     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 440     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 441     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 442     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 443     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 446 void wxDC::DoSetClippingRegion( 
 455     vY 
= OS2Y(vY
,vHeight
); 
 458     vRect
.yTop    
= vY 
+ vHeight
; 
 459     vRect
.xRight  
= vX 
+ vWidth
; 
 461     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 462     DO_SET_CLIPPING_BOX() 
 463 } // end of wxDC::DoSetClippingRegion 
 465 void wxDC::DoSetClippingRegionAsRegion( 
 466   const wxRegion
&                   rRegion
 
 469      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 473      ::GpiSetClipRegion( m_hPS
 
 474                         ,(HRGN
)rRegion
.GetHRGN() 
 477     DO_SET_CLIPPING_BOX() 
 478 } // end of wxDC::DoSetClippingRegionAsRegion 
 480 void wxDC::DestroyClippingRegion(void) 
 482     if (m_clipping 
&& m_hPS
) 
 487          // TODO: this should restore the previous clipped region 
 488          //       so that OnPaint processing works correctly, and 
 489          //       the update doesn't get destroyed after the first 
 490          //       DestroyClippingRegion 
 491          vRect
.xLeft   
= XLOG2DEV(0); 
 492          vRect
.yTop    
= YLOG2DEV(32000); 
 493          vRect
.xRight  
= XLOG2DEV(32000); 
 494          vRect
.yBottom 
= YLOG2DEV(0); 
 496          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 498          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 501 } // end of wxDC::DestroyClippingRegion 
 503 // --------------------------------------------------------------------------- 
 504 // query capabilities 
 505 // --------------------------------------------------------------------------- 
 507 bool wxDC::CanDrawBitmap() const 
 512 bool wxDC::CanGetTextExtent() const 
 514     LONG                            lTechnology 
= 0L; 
 516     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 517     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 518 } // end of wxDC::CanGetTextExtent 
 520 int wxDC::GetDepth() const 
 522     LONG                            lArray
[CAPS_COLOR_BITCOUNT
]; 
 523     int                             nBitsPerPixel 
= 0; 
 525     if(::DevQueryCaps( GetHDC() 
 531         nBitsPerPixel 
= (int)lArray
[CAPS_COLOR_BITCOUNT
]; 
 533     return nBitsPerPixel
; 
 534 } // end of wxDC::GetDepth 
 536 // --------------------------------------------------------------------------- 
 538 // --------------------------------------------------------------------------- 
 543     // If this is a canvas DC then just fill with the background color 
 544     // Otherwise purge the whole thing 
 550         ::GpiQueryClipBox(m_hPS
, &vRect
); 
 551         ::WinFillRect(m_hPS
, &vRect
, ::GpiQueryBackColor(m_hPS
)); 
 555 } // end of wxDC::Clear 
 557 bool wxDC::DoFloodFill( 
 560 , const wxColour
&                   rCol
 
 568     bool                            bSuccess 
= false; 
 570     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 571     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 572     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 573     lColor 
= rCol
.GetPixel(); 
 574     lOptions 
= FF_BOUNDARY
; 
 575     if(wxFLOOD_SURFACE 
== nStyle
) 
 576         lOptions 
= FF_SURFACE
; 
 578     if ((lHits 
= ::GpiFloodFill(m_hPS
, lOptions
, lColor
)) != GPI_ERROR
) 
 582 } // end of wxDC::DoFloodFill 
 584 bool wxDC::DoGetPixel( 
 594     vPoint
.y 
= OS2Y(vY
,0); 
 595     lColor 
= ::GpiSetPel(m_hPS
, &vPoint
); 
 598     // Get the color of the pen 
 600     LONG                            lPencolor 
= 0x00ffffff; 
 604         lPencolor 
= m_pen
.GetColour().GetPixel(); 
 608     // return the color of the pixel 
 611         pCol
->Set( GetRValue(lColor
) 
 615     return(lColor 
== lPencolor
); 
 616 } // end of wxDC::DoGetPixel 
 618 void wxDC::DoCrossHair( 
 625     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 626     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 627     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 628     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 637     ::GpiMove(m_hPS
, &vPoint
[0]); 
 638     ::GpiLine(m_hPS
, &vPoint
[1]); 
 646     ::GpiMove(m_hPS
, &vPoint
[2]); 
 647     ::GpiLine(m_hPS
, &vPoint
[3]); 
 648     CalcBoundingBox(vX1
, vY1
); 
 649     CalcBoundingBox(vX2
, vY2
); 
 650 } // end of wxDC::DoCrossHair 
 652 void wxDC::DoDrawLine( 
 660     COLORREF                        vColor 
= 0x00ffffff; 
 663     // Might be a memory DC with no Paint rect. 
 665     if (!(m_vRclPaint
.yTop 
== 0 && 
 666           m_vRclPaint
.yBottom 
== 0 && 
 667           m_vRclPaint
.xRight 
== 0 && 
 668           m_vRclPaint
.xLeft 
== 0)) 
 675         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
 677             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 678             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 689         vColor 
= m_pen
.GetColour().GetPixel(); 
 691     ::GpiSetColor(m_hPS
, vColor
); 
 692     ::GpiMove(m_hPS
, &vPoint
[0]); 
 693     ::GpiLine(m_hPS
, &vPoint
[1]); 
 694     CalcBoundingBox(vX1
, vY1
); 
 695     CalcBoundingBox(vX2
, vY2
); 
 696 } // end of wxDC::DoDrawLine 
 698 ////////////////////////////////////////////////////////////////////////////// 
 699 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 700 // and ending at (x2, y2). The current pen is used for the outline and the 
 701 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 702 // direction from the start point to the end point. 
 703 ////////////////////////////////////////////////////////////////////////////// 
 704 void wxDC::DoDrawArc( 
 714      POINTL                         vPtlArc
[2]; // Structure for current position 
 721      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 723     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 724         return; // Draw point ?? 
 725     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 728                       hypot( (double)(vY2 
- vYc
) 
 733     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 736     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 743     // GpiPointArc can't draw full arc 
 745      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 750         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 751         vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 752         vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 767     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 768     vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 769     vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 772     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 778     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 780     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 781     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 782     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 787     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 788     CalcBoundingBox( (wxCoord
)(vXc 
- dRadius
) 
 789                     ,(wxCoord
)(vYc 
- dRadius
) 
 791     CalcBoundingBox( (wxCoord
)(vXc 
+ dRadius
) 
 792                     ,(wxCoord
)(vYc 
+ dRadius
) 
 794 } // end of wxDC::DoDrawArc 
 796 void wxDC::DoDrawCheckMark( 
 805     vY1 
= OS2Y(vY1
,vHeight
); 
 809     vPoint
[1].x 
= vX1 
+ vWidth
; 
 810     vPoint
[1].y 
= vY1 
+ vHeight
; 
 812     ::GpiMove(m_hPS
, &vPoint
[0]); 
 813     ::GpiBox( m_hPS       
// handle to a presentation space 
 814              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 815              ,&vPoint
[1]  // address of the corner 
 816              ,0L          // horizontal corner radius 
 817              ,0L          // vertical corner radius 
 819     if(vWidth 
> 4 && vHeight 
> 4) 
 823         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 824         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 825         ::GpiMove(m_hPS
, &vPoint
[0]); 
 826         ::GpiLine(m_hPS
, &vPoint
[1]); 
 828         vPoint
[0].x 
= vPoint
[1].x
; 
 830         ::GpiMove(m_hPS
, &vPoint
[0]); 
 831         ::GpiLine(m_hPS
, &vPoint
[1]); 
 837     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 838     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 843 } // end of wxDC::DoDrawCheckMark 
 845 void wxDC::DoDrawPoint( 
 851     COLORREF                        vColor 
= 0x00ffffff; 
 855         vColor 
= m_pen
.GetColour().GetPixel(); 
 857     ::GpiSetColor(m_hPS
, vColor
); 
 859     vPoint
.y 
= OS2Y(vY
,0); 
 860     ::GpiSetPel(m_hPS
, &vPoint
); 
 864 } // end of wxDC::DoDrawPoint 
 866 void wxDC::DoDrawPolygon( 
 874     ULONG                           ulCount 
= 1;    // Number of polygons. 
 875     POLYGON                         vPlgn
;          // polygon. 
 876     ULONG                           flOptions 
= 0L; // Drawing options. 
 878 ////////////////////////////////////////////////////////////////////////////// 
 879 // This contains fields of option bits... to draw boundary lines as well as 
 880 // the area interior. 
 882 // Drawing boundary lines: 
 883 //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 884 //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 886 // Construction of the area interior: 
 887 //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 889 //   POLYGON_WINDING                 Constructs interior in winding mode. 
 890 ////////////////////////////////////////////////////////////////////////////// 
 892     ULONG                           flModel 
= 0L; // Drawing model. 
 894 ////////////////////////////////////////////////////////////////////////////// 
 896 //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 897 //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 898 //       This is provided to aid migration from other graphics models. 
 899 ////////////////////////////////////////////////////////////////////////////// 
 901     LONG                            lHits 
= 0L; // Correlation/error indicator. 
 904     int                             nIsTRANSPARENT 
= 0; 
 905     LONG                            lBorderColor 
= 0L; 
 908     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 909     lColor       
= m_brush
.GetColour().GetPixel(); 
 910     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 914     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 916                                     ); // well, new will call malloc 
 918     for(i 
= 0; i 
< n
; i
++) 
 920         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
;         // +xoffset; 
 921         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
,0); // +yoffset; 
 923     flModel 
= POLYGON_BOUNDARY
; 
 924     if(nFillStyle 
== wxWINDING_RULE
) 
 925         flModel 
|= POLYGON_WINDING
; 
 927         flModel 
|= POLYGON_ALTERNATE
; 
 930     vPoint
.y 
= OS2Y(vYoffset
,0); 
 932     ::GpiSetColor(m_hPS
, lBorderColor
); 
 933     ::GpiMove(m_hPS
, &vPoint
); 
 934     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 936 } // end of wxDC::DoDrawPolygon 
 938 void wxDC::DoDrawLines( 
 947     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 951         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 952         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 953         ::GpiMove(m_hPS
, &vPoint
); 
 955         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 957         ::GpiSetColor(m_hPS
, lBorderColor
); 
 958         for(i 
= 1; i 
< n
; i
++) 
 960             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 961             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 962             ::GpiLine(m_hPS
, &vPoint
); 
 969         CalcBoundingBox( vPoints
[0].x
 
 972         vPoint
.x 
= vPoints
[0].x
; 
 973         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 974         ::GpiMove(m_hPS
, &vPoint
); 
 976         for (i 
= 0; i 
< n
; i
++) 
 978             CalcBoundingBox( vPoints
[i
].x
 
 981             vPoint
.x 
= vPoints
[i
].x
; 
 982             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 983             ::GpiLine(m_hPS
, &vPoint
); 
 986 } // end of wxDC::DoDrawLines 
 988 void wxDC::DoDrawRectangle( 
 999     int                             nIsTRANSPARENT 
= 0; 
1002     // Might be a memory DC with no Paint rect. 
1004     if (!(m_vRclPaint
.yTop 
== 0 && 
1005           m_vRclPaint
.yBottom 
== 0 && 
1006           m_vRclPaint
.xRight 
== 0 && 
1007           m_vRclPaint
.xLeft 
== 0)) 
1008         vY 
= OS2Y(vY
,vHeight
); 
1011         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1013             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1014             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1015             vY 
= OS2Y(vY
,vHeight
); 
1019     wxCoord                         vX2 
= vX 
+ vWidth
; 
1020     wxCoord                         vY2 
= vY 
+ vHeight
; 
1024     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1025     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1026     ::GpiMove(m_hPS
, &vPoint
[0]); 
1027     lColor       
= m_brush
.GetColour().GetPixel(); 
1028     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1029     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1031     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1033         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1034         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1035             lControl 
= DRO_OUTLINE
; 
1037         ::GpiSetColor(m_hPS
, lBorderColor
); 
1038         ::GpiBox( m_hPS       
// handle to a presentation space 
1039                  ,lControl   
// draw the box outline ? or ? 
1040                  ,&vPoint
[1]  // address of the corner 
1041                  ,0L          // horizontal corner radius 
1042                  ,0L          // vertical corner radius 
1047         lControl 
= DRO_OUTLINE
; 
1048         ::GpiSetColor( m_hPS
 
1057         lControl 
= DRO_FILL
; 
1058         ::GpiSetColor( m_hPS
 
1061         vPoint
[0].x 
= vX 
+ 1; 
1062         vPoint
[0].y 
= vY 
+ 1; 
1063         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1064         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1065         ::GpiMove(m_hPS
, &vPoint
[0]); 
1073     CalcBoundingBox(vX
, vY
); 
1074     CalcBoundingBox(vX2
, vY2
); 
1075 } // end of wxDC::DoDrawRectangle 
1077 void wxDC::DoDrawRoundedRectangle( 
1089     int                             nIsTRANSPARENT 
= 0; 
1092     // Might be a memory DC with no Paint rect. 
1094     if (!(m_vRclPaint
.yTop 
== 0 && 
1095           m_vRclPaint
.yBottom 
== 0 && 
1096           m_vRclPaint
.xRight 
== 0 && 
1097           m_vRclPaint
.xLeft 
== 0)) 
1098         vY 
= OS2Y(vY
,vHeight
); 
1101         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1103             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1104             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1105             vY 
= OS2Y(vY
,vHeight
); 
1109     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1110     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1114     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1115     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1116     ::GpiMove(m_hPS
, &vPoint
[0]); 
1118     lColor       
= m_brush
.GetColour().GetPixel(); 
1119     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1120     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1121     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1123     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1125         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1126         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1127             lControl 
= DRO_OUTLINE
; 
1129         ::GpiSetColor(m_hPS
, lColor
); 
1130         ::GpiBox( m_hPS         
// handle to a presentation space 
1131                  ,lControl      
// draw the box outline ? or ? 
1132                  ,&vPoint
[1]    // address of the corner 
1133                  ,(LONG
)dRadius 
// horizontal corner radius 
1134                  ,(LONG
)dRadius 
// vertical corner radius 
1139         lControl 
= DRO_OUTLINE
; 
1140         ::GpiSetColor( m_hPS
 
1149         lControl 
= DRO_FILL
; 
1150         ::GpiSetColor( m_hPS
 
1153         vPoint
[0].x 
= vX 
+ 1; 
1154         vPoint
[0].y 
= vY 
+ 1; 
1155         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1156         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1157         ::GpiMove(m_hPS
, &vPoint
[0]); 
1166     CalcBoundingBox(vX
, vY
); 
1167     CalcBoundingBox(vX2
, vY2
); 
1168 } // end of wxDC::DoDrawRoundedRectangle 
1170 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1171 void wxDC::DoDrawEllipse( 
1178     POINTL                          vPtlPos
; // Structure for current position 
1179     FIXED                           vFxMult
; // Multiplier for ellipse 
1180     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1182     vY 
= OS2Y(vY
,vHeight
); 
1185     vArcp
.lQ 
= vHeight
/2; 
1186     vArcp
.lP 
= vWidth
/2; 
1188     ::GpiSetArcParams( m_hPS
 
1190                      ); // Sets parameters to default 
1191     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1192     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1195              ); // Sets current position 
1196     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1199     // DRO_FILL, DRO_OTLINEFILL - where to get 
1204                 ); // Draws full arc with center at current position 
1206     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1207     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1209     CalcBoundingBox(vX
, vY
); 
1210     CalcBoundingBox(vX2
, vY2
); 
1211 } // end of wxDC::DoDrawEllipse 
1213 void wxDC::DoDrawEllipticArc( 
1222     POINTL                          vPtlPos
; // Structure for current position 
1223     FIXED                           vFxMult
; // Multiplier for ellipse 
1224     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1226     FIXED                           vFSweepa
; // Start angle, sweep angle 
1230     vY 
= OS2Y(vY
,vHeight
); 
1232     dFractPart 
= modf(dSa
,&dIntPart
); 
1233     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1234     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1235     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1238     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1241     vArcp
.lQ 
= vHeight
/2; 
1242     vArcp
.lP 
= vWidth
/2; 
1244     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1245     vPtlPos
.x 
= (wxCoord
)(vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
)))); // Loads x-coordinate 
1246     vPtlPos
.y 
= (wxCoord
)(vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
)))); // Loads y-coordinate 
1247     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1250     // May be not to the center ? 
1252     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1253     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1254     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1257     // DRO_FILL, DRO_OTLINEFILL - where to get 
1259     ::GpiPartialArc( m_hPS
 
1265     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1266     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1268     CalcBoundingBox(vX
, vY
); 
1269     CalcBoundingBox(vX2
, vY2
); 
1270 } // end of wxDC::DoDrawEllipticArc 
1272 void wxDC::DoDrawIcon( 
1279     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords 
1280     // and I don't feel like figuring those out for scrollable windows so 
1281     // just convert to a bitmap then let the DoDrawBitmap routing display it 
1285         DoDrawBitmap(rIcon
.GetXpmSrc(), vX
, vY
, true); 
1289         wxBitmap                        
vBitmap(rIcon
); 
1291         DoDrawBitmap(vBitmap
, vX
, vY
, false); 
1293     CalcBoundingBox(vX
, vY
); 
1294     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1295 } // end of wxDC::DoDrawIcon 
1297 void wxDC::DoDrawBitmap( 
1298   const wxBitmap
&                   rBmp
 
1304     if (!IsKindOf(CLASSINFO(wxPrinterDC
))) 
1306         HBITMAP                         hBitmap 
=  (HBITMAP
)rBmp
.GetHBITMAP(); 
1310         vY 
= OS2Y(vY
,rBmp
.GetHeight()); 
1313         vPoint
[0].y 
= vY 
+ rBmp
.GetHeight(); 
1314         vPoint
[1].x 
= vX 
+ rBmp
.GetWidth(); 
1318         vPoint
[3].x 
= rBmp
.GetWidth(); 
1319         vPoint
[3].y 
= rBmp
.GetHeight(); 
1322             wxMask
*                     pMask 
= rBmp
.GetMask(); 
1327                 // Need to imitate ::MaskBlt in windows. 
1328                 // 1) Extract the bits from from the bitmap. 
1329                 // 2) Extract the bits from the mask 
1330                 // 3) Using the mask bits do the following: 
1331                 //   A) If the mask byte is 00 leave the bitmap byte alone 
1332                 //   B) If the mask byte is FF copy the screen color into 
1334                 // 4) Create a new bitmap and set its bits to the above result 
1335                 // 5) Blit this to the screen PS 
1337                 HBITMAP                 hMask 
= (HBITMAP
)pMask
->GetMaskBitmap(); 
1338                 HBITMAP                 hOldMask   
= NULLHANDLE
; 
1339                 HBITMAP                 hOldBitmap 
= NULLHANDLE
; 
1340                 HBITMAP                 hNewBitmap 
= NULLHANDLE
; 
1341                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1342                 unsigned char*          pucBitsMask
; // buffer that will contain the mask data 
1343                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1344                 unsigned char*          pucDataMask
; // pointer to use to traverse mask data 
1350                 // The usual Memory context creation stuff 
1352                 DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1353                 SIZEL                           vSize 
= {0, 0}; 
1354                 HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1355                 HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1358                 // The usual bitmap header stuff 
1360                 BITMAPINFOHEADER2               vHeader
; 
1363                 memset(&vHeader
, '\0', 16); 
1366                 memset(&vInfo
, '\0', 16); 
1368                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1369                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1371                 vInfo
.cBitCount       
= 24; // Set to desired count going in 
1374                 // Create the buffers for data....all wxBitmaps are 24 bit internally 
1376                 int                     nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1377                 int                     nSizeDWORD    
= sizeof(DWORD
); 
1378                 int                     nLineBoundary 
= nBytesPerLine 
% nSizeDWORD
; 
1386                 // Need to get a background color for mask blitting 
1388                 if (IsKindOf(CLASSINFO(wxWindowDC
))) 
1390                     wxWindowDC
*             pWindowDC 
= wxDynamicCast(this, wxWindowDC
); 
1392                     lColor 
= pWindowDC
->m_pCanvas
->GetBackgroundColour().GetPixel(); 
1394                 else if (GetBrush().Ok()) 
1395                     lColor 
= GetBrush().GetColour().GetPixel(); 
1397                     lColor 
= m_textBackgroundColour
.GetPixel(); 
1400                 // Bitmap must be ina double-word alligned address so we may 
1401                 // have some padding to worry about 
1403                 if (nLineBoundary 
> 0) 
1405                     nPadding     
= nSizeDWORD 
- nLineBoundary
; 
1406                     nBytesPerLine 
+= nPadding
; 
1408                 pucBits 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1409                 pucBitsMask 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1410                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1411                 memset(pucBitsMask
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1414                 // Extract the bitmap and mask data 
1416                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1418                     vError 
= ::WinGetLastError(vHabmain
); 
1419                     sError 
= wxPMErrorToStr(vError
); 
1421                 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
); 
1422                 vInfo
.cBitCount 
= 24; 
1423                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1425                                                    ,(LONG
)rBmp
.GetHeight() 
1430                     vError 
= ::WinGetLastError(vHabmain
); 
1431                     sError 
= wxPMErrorToStr(vError
); 
1433                 if ((hOldMask 
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
) 
1435                     vError 
= ::WinGetLastError(vHabmain
); 
1436                     sError 
= wxPMErrorToStr(vError
); 
1438                 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
); 
1439                 vInfo
.cBitCount 
= 24; 
1440                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1442                                                    ,(LONG
)rBmp
.GetHeight() 
1447                     vError 
= ::WinGetLastError(vHabmain
); 
1448                     sError 
= wxPMErrorToStr(vError
); 
1450                 if (( hMask 
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
) 
1452                     vError 
= ::WinGetLastError(vHabmain
); 
1453                     sError 
= wxPMErrorToStr(vError
); 
1457                 // Now set the bytes(bits) according to the mask values 
1458                 // 3 bytes per pel...must handle one at a time 
1461                 pucDataMask 
= pucBitsMask
; 
1464                 // 16 bit kludge really only kinda works.  The mask gets applied 
1465                 // where needed but the original bitmap bits are dorked sometimes 
1467                 bool                    bpp16 
= (wxDisplayDepth() == 16); 
1469                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1471                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1474                         if (bpp16 
&& *pucDataMask 
== 0xF8) // 16 bit display gobblygook 
1476                         else if (*pucDataMask 
== 0xFF) // leave bitmap byte alone 
1480                             *pucData 
= ((unsigned char)(lColor 
>> 16)); 
1484                         if (bpp16 
&& *(pucDataMask 
+ 1) == 0xFC) // 16 bit display gobblygook 
1486                         else if (*(pucDataMask 
+ 1) == 0xFF) // leave bitmap byte alone 
1490                             *pucData 
= ((unsigned char)(lColor 
>> 8)); 
1495                         if (bpp16 
&& *(pucDataMask 
+ 2) == 0xF8) // 16 bit display gobblygook 
1497                         else if (*(pucDataMask 
+ 2) == 0xFF) // leave bitmap byte alone 
1501                             *pucData 
= ((unsigned char)lColor
); 
1506                     for (j 
= 0; j 
< nPadding
; j
++) 
1513                 // Create a new bitmap 
1515                 vHeader
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1516                 vHeader
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1517                 vHeader
.cPlanes         
= 1L; 
1518                 vHeader
.cBitCount       
= 24; 
1519                 if ((hNewBitmap 
= ::GpiCreateBitmap( hPS
 
1526                     vError 
= ::WinGetLastError(vHabmain
); 
1527                     sError 
= wxPMErrorToStr(vError
); 
1531                 // Now blit it to the screen PS 
1533                 if ((lHits 
= ::GpiWCBitBlt( (HPS
)GetHPS() 
1541                     vError 
= ::WinGetLastError(vHabmain
); 
1542                     sError 
= wxPMErrorToStr(vError
); 
1550                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1551                 ::GpiDeleteBitmap(hNewBitmap
); 
1552                 ::GpiDestroyPS(hPS
); 
1558             ULONG                       lOldForeGround 
= ::GpiQueryColor((HPS
)GetHPS()); 
1559             ULONG                       lOldBackGround 
= ::GpiQueryBackColor((HPS
)GetHPS()); 
1561             if (m_textForegroundColour
.Ok()) 
1563                 ::GpiSetColor( (HPS
)GetHPS() 
1564                                ,m_textForegroundColour
.GetPixel() 
1567             if (m_textBackgroundColour
.Ok()) 
1569                 ::GpiSetBackColor( (HPS
)GetHPS() 
1570                                   ,m_textBackgroundColour
.GetPixel() 
1574             // Need to alter bits in a mono bitmap to match the new 
1575             // background-foreground if it is different. 
1577             if (rBmp
.IsMono() && 
1578                ((m_textForegroundColour
.GetPixel() != lOldForeGround
) || 
1579                 (m_textBackgroundColour
.GetPixel() != lOldBackGround
))) 
1581                 DEVOPENSTRUC        vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1582                 SIZEL               vSize 
= {0, 0}; 
1583                 HDC                 hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1584                 HPS                 hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1586                 int                 nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1588                 LONG                lForeGround 
= m_textForegroundColour
.GetPixel(); 
1589                 LONG                lBackGround 
= m_textBackgroundColour
.GetPixel(); 
1591                 HBITMAP             hOldBitmap 
= NULLHANDLE
; 
1597                 memset(&vInfo
, '\0', 16); 
1599                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1600                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1602                 vInfo
.cBitCount       
= 24; 
1604                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1605                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1607                 pucBits 
= new unsigned char[nBytesPerLine 
* rBmp
.GetHeight()]; 
1608                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1610                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1612                     vError 
= ::WinGetLastError(vHabmain
); 
1613                     sError 
= wxPMErrorToStr(vError
); 
1616                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1618                                                    ,(LONG
)rBmp
.GetHeight() 
1623                     vError 
= ::WinGetLastError(vHabmain
); 
1624                     sError 
= wxPMErrorToStr(vError
); 
1627                 unsigned char           cOldRedFore   
= (unsigned char)(lOldForeGround 
>> 16); 
1628                 unsigned char           cOldGreenFore 
= (unsigned char)(lOldForeGround 
>> 8); 
1629                 unsigned char           cOldBlueFore  
= (unsigned char)lOldForeGround
; 
1631                 unsigned char           cRedFore   
= (unsigned char)(lForeGround 
>> 16); 
1632                 unsigned char           cGreenFore 
= (unsigned char)(lForeGround 
>> 8); 
1633                 unsigned char           cBlueFore  
= (unsigned char)lForeGround
; 
1635                 unsigned char           cRedBack   
= (unsigned char)(lBackGround 
>> 16); 
1636                 unsigned char           cGreenBack 
= (unsigned char)(lBackGround 
>> 8); 
1637                 unsigned char           cBlueBack  
= (unsigned char)lBackGround
; 
1640                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1642                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1644                         unsigned char    cBmpRed   
= *pucData
; 
1645                         unsigned char    cBmpGreen 
= *(pucData 
+ 1); 
1646                         unsigned char    cBmpBlue  
= *(pucData 
+ 2); 
1648                         if ((cBmpRed 
== cOldRedFore
) && 
1649                             (cBmpGreen 
== cOldGreenFore
) && 
1650                             (cBmpBlue 
== cOldBlueFore
)) 
1652                             *pucData 
= cBlueFore
; 
1654                             *pucData 
= cGreenFore
; 
1656                             *pucData 
= cRedFore
; 
1661                             *pucData 
= cBlueBack
; 
1663                             *pucData 
= cGreenBack
; 
1665                             *pucData 
= cRedBack
; 
1670                 if ((lScans 
= ::GpiSetBitmapBits( hPS
 
1672                                                  ,(LONG
)rBmp
.GetHeight() 
1677                     vError 
= ::WinGetLastError(vHabmain
); 
1678                     sError 
= wxPMErrorToStr(vError
); 
1682                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1683                 ::GpiDestroyPS(hPS
); 
1686             ::GpiWCBitBlt( (HPS
)GetHPS() 
1693             ::GpiSetBitmap((HPS
)GetHPS(), hBitmapOld
); 
1694             ::GpiSetColor((HPS
)GetHPS(), lOldForeGround
); 
1695             ::GpiSetBackColor((HPS
)GetHPS(), lOldBackGround
); 
1698 } // end of wxDC::DoDrawBitmap 
1700 void wxDC::DoDrawText( 
1701   const wxString
&                   rsText
 
1714     CalcBoundingBox(vX
, vY
); 
1715     GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1716     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1717 } // end of wxDC::DoDrawText 
1719 void wxDC::DrawAnyText( 
1720   const wxString
&                   rsText
 
1725     int                             nOldBackground 
= 0; 
1732     // prepare for drawing the text 
1736     // Set text color attributes 
1738     if (m_textForegroundColour
.Ok()) 
1741                      ,(int)m_textForegroundColour
.GetPixel() 
1745     if (m_textBackgroundColour
.Ok()) 
1747         nOldBackground 
= SetTextBkColor( m_hPS
 
1748                                         ,(int)m_textBackgroundColour
.GetPixel() 
1754     GetTextExtent( rsText
 
1759     if (!(m_vRclPaint
.yTop 
== 0 && 
1760           m_vRclPaint
.yBottom 
== 0 && 
1761           m_vRclPaint
.xRight 
== 0 && 
1762           m_vRclPaint
.xLeft 
== 0)) 
1765         // Position Text a little differently in the Statusbar from other panels 
1767         if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1768             vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1770             vPtlStart
.y 
= (wxCoord
)(OS2Y(vY
,vTextY
/1.5)); // Full extent is a bit much 
1774         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1776             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1777             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1778             if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1779                 vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1781                 vPtlStart
.y 
= (LONG
)(OS2Y(vY
,vTextY
/1.5)); 
1787     PCH                             pzStr 
= (PCH
)rsText
.c_str(); 
1789     ::GpiMove(m_hPS
, &vPtlStart
); 
1790     lHits 
= ::GpiCharString( m_hPS
 
1794     if (lHits 
!= GPI_OK
) 
1796         wxLogLastError(wxT("TextOut")); 
1800     // Restore the old parameters (text foreground colour may be left because 
1801     // it never is set to anything else, but background should remain 
1802     // transparent even if we just drew an opaque string) 
1804     if (m_textBackgroundColour
.Ok()) 
1805             SetTextBkColor( m_hPS
 
1813 void wxDC::DoDrawRotatedText( 
1814   const wxString
&                   rsText
 
1832         DoDrawText(text, x, y); 
1837         wxFillLogFont(&lf, &m_font); 
1839         // GDI wants the angle in tenth of degree 
1840         long angle10 = (long)(angle * 10); 
1841         lf.lfEscapement = angle10; 
1842         lf. lfOrientation = angle10; 
1844         HFONT hfont = ::CreateFontIndirect(&lf); 
1847             wxLogLastError("CreateFont"); 
1851             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1853             DrawAnyText(text, x, y); 
1855             (void)::SelectObject(GetHdc(), hfontOld); 
1858         // call the bounding box by adding all four vertices of the rectangle 
1859         // containing the text to it (simpler and probably not slower than 
1860         // determining which of them is really topmost/leftmost/...) 
1862         GetTextExtent(text, &w, &h); 
1864         double rad = DegToRad(angle); 
1866         // "upper left" and "upper right" 
1867         CalcBoundingBox(x, y); 
1868         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1869         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1871         // "bottom left" and "bottom right" 
1872         x += (wxCoord)(h*sin(rad)); 
1873         y += (wxCoord)(h*cos(rad)); 
1874         CalcBoundingBox(x, y); 
1875         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1880 // --------------------------------------------------------------------------- 
1882 // --------------------------------------------------------------------------- 
1884 void wxDC::DoSelectPalette( 
1889     // Set the old object temporarily, in case the assignment deletes an object 
1890     // that's not yet selected out. 
1901         hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1903             m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1905 } // end of wxDC::DoSelectPalette 
1907 void wxDC::InitializePalette() 
1909     if (wxDisplayDepth() <= 8 ) 
1912         // Look for any window or parent that has a custom palette. If any has 
1913         // one then we need to use it in drawing operations 
1915         wxWindow
*                   pWin 
= m_pCanvas
->GetAncestorWithCustomPalette(); 
1917         m_hasCustomPalette 
= pWin 
&& pWin
->HasCustomPalette(); 
1918         if (m_hasCustomPalette
) 
1920             m_palette 
= pWin
->GetPalette(); 
1923             // turn on PM translation for this palette 
1928 } // end of wxDC::InitializePalette 
1930 void wxDC::SetPalette( 
1931   const wxPalette
&                  rPalette
 
1938     m_palette 
= rPalette
; 
1946     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1948         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1949 } // end of wxDC::SetPalette 
1956     // Set the old object temporarily, in case the assignment deletes an object 
1957     // that's not yet selected out. 
1969     m_font
.SetPS(m_hPS
); // this will realize the font 
1973         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1974         if (hFont 
== (HFONT
) NULL
) 
1976             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
1979             m_hOldFont 
= (WXHFONT
) hFont
; 
1981 } // end of wxDC::SetFont 
1987     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2003             m_pen
.SetPS((HPS
)m_hOldPen
); 
2010         if (m_pen
.GetResourceHandle()) 
2014                 m_hOldPen 
= m_pen
.GetPS(); 
2016         ::GpiSetColor(m_hPS
, m_pen
.GetColour().GetPixel()); 
2020 void wxDC::SetBrush( 
2021   const wxBrush
&                    rBrush
 
2024     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2030     if (m_brush 
== rBrush
) 
2040             m_brush
.SetPS((HPS
)m_hOldBrush
); 
2047         if (m_brush
.GetResourceHandle()) 
2049             m_brush
.SetPS(m_hPS
); 
2051                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
2054 } // end of wxDC::SetBrush 
2056 void wxDC::SetBackground( 
2057   const wxBrush
&                    rBrush
 
2060     m_backgroundBrush 
= rBrush
; 
2061     if (!m_backgroundBrush
.Ok()) 
2065         bool                        bCustomColours 
= true; 
2068         // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to 
2069         // change background colours from the control-panel specified colours. 
2071         if (m_pCanvas
->IsKindOf(CLASSINFO(wxWindow
)) && 
2072             ((m_pCanvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
)) 
2073             bCustomColours 
= false; 
2076             if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
) 
2078                 m_pCanvas
->SetTransparent(true); 
2083                 // Setting the background brush of a DC 
2084                 // doesn't affect the window background colour. However, 
2085                 // I'm leaving in the transparency setting because it's needed by 
2086                 // various controls (e.g. wxStaticText) to determine whether to draw 
2087                 // transparently or not. TODO: maybe this should be a new function 
2088                 // wxWindow::SetTransparency(). Should that apply to the child itself, or the 
2090                 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour()); 
2092                 m_pCanvas
->SetTransparent(false); 
2096     COLORREF                        vNewColor 
= m_backgroundBrush
.GetColour().GetPixel(); 
2097     (void)::GpiSetBackColor((HPS
)m_hPS
, (LONG
)vNewColor
); 
2098 } // end of wxDC::SetBackground 
2100 void wxDC::SetBackgroundMode( 
2104     m_backgroundMode 
= nMode
; 
2105 } // end of wxDC::SetBackgroundMode 
2107 void wxDC::SetLogicalFunction( 
2111     m_logicalFunction 
= nFunction
; 
2112     SetRop((WXHDC
)m_hDC
); 
2113 } // wxDC::SetLogicalFunction 
2119     if (!hDC 
|| m_logicalFunction 
< 0) 
2123     switch (m_logicalFunction
) 
2134             lCRop 
= FM_MERGESRCNOT
; 
2138             lCRop 
= FM_NOTMASKSRC
; 
2150             lCRop 
= FM_MERGENOTSRC
; 
2154             lCRop 
= FM_MERGESRCNOT
; 
2166             lCRop 
= FM_SUBTRACT
; 
2173             lCRop 
= FM_OVERPAINT
; 
2176     ::GpiSetMix((HPS
)hDC
, lCRop
); 
2177 } // end of wxDC::SetRop 
2179 bool wxDC::StartDoc( 
2180   const wxString
&                   rsMessage
 
2183     // We might be previewing, so return true to let it continue. 
2185 } // end of wxDC::StartDoc 
2189 } // end of wxDC::EndDoc 
2191 void wxDC::StartPage() 
2193 } // end of wxDC::StartPage 
2195 void wxDC::EndPage() 
2197 } // end of wxDC::EndPage 
2199 // --------------------------------------------------------------------------- 
2201 // --------------------------------------------------------------------------- 
2203 wxCoord 
wxDC::GetCharHeight() const 
2205     FONTMETRICS                     vFM
; // metrics structure 
2207     ::GpiQueryFontMetrics( m_hPS
 
2208                           ,sizeof(FONTMETRICS
) 
2211     return YDEV2LOGREL(vFM
.lXHeight
); 
2214 wxCoord 
wxDC::GetCharWidth() const 
2216     FONTMETRICS                     vFM
; // metrics structure 
2218     ::GpiQueryFontMetrics( m_hPS
 
2219                           ,sizeof(FONTMETRICS
) 
2222     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
2225 void wxDC::DoGetTextExtent( 
2226   const wxString
&                   rsString
 
2229 , wxCoord
*                          pvDescent
 
2230 , wxCoord
*                          pvExternalLeading
 
2234     POINTL                          avPoint
[TXTBOX_COUNT
]; 
2239     FONTMETRICS                     vFM
; // metrics structure 
2242     ERRORID                         vErrorCode
; // last error id code 
2243     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
2245     char                            zMsg
[128]; // DEBUG 
2249         pFontToUse 
= (wxFont
*)&m_font
; 
2250     l 
= rsString
.length(); 
2251     pStr 
= (PCH
) rsString
.c_str(); 
2254     // In world coordinates. 
2256     bRc 
= ::GpiQueryTextBox( m_hPS
 
2259                             ,TXTBOX_COUNT 
// return maximum information 
2260                             ,avPoint      
// array of coordinates points 
2264        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
2265        sError 
= wxPMErrorToStr(vErrorCode
); 
2267        sprintf(zMsg
, "GpiQueryTextBox for %s: failed with Error: %lx - %s", pStr
, vErrorCode
, sError
.c_str()); 
2268        (void)wxMessageBox( "wxWidgets Menu sample" 
2274     vPtMin
.x 
= avPoint
[0].x
; 
2275     vPtMax
.x 
= avPoint
[0].x
; 
2276     vPtMin
.y 
= avPoint
[0].y
; 
2277     vPtMax
.y 
= avPoint
[0].y
; 
2278     for (i 
= 1; i 
< 4; i
++) 
2280         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
2281         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
2282         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
2283         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
2285     ::GpiQueryFontMetrics( m_hPS
 
2286                           ,sizeof(FONTMETRICS
) 
2291         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
2293         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
2295         *pvDescent 
= vFM
.lMaxDescender
; 
2296     if (pvExternalLeading
) 
2297         *pvExternalLeading 
= vFM
.lExternalLeading
; 
2300 void wxDC::SetMapMode( 
2304     int                             nPixelWidth 
= 0; 
2305     int                             nPixelHeight 
= 0; 
2308     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2310     m_mappingMode 
= nMode
; 
2312     if(::DevQueryCaps( m_hDC
 
2314                       ,CAPS_VERTICAL_RESOLUTION
 
2321         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
2322         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
2323         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2324         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2325         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
2326         nMmWidth 
= (lVertRes
/1000) * nPixelHeight
; 
2328     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
2333     double                          dMm2pixelsX 
= nPixelWidth
/nMmWidth
; 
2334     double                          dMm2pixelsY 
= nPixelHeight
/nMmHeight
; 
2339             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
2340             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
2344             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
2345             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
2349             m_logicalScaleX 
= dMm2pixelsX
; 
2350             m_logicalScaleY 
= dMm2pixelsY
; 
2354             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
2355             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
2360             m_logicalScaleX 
= 1.0; 
2361             m_logicalScaleY 
= 1.0; 
2367     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
2368     if (!ulOptions 
& PU_ARBITRARY
) 
2370         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
2371         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
2373     m_nWindowExtX 
= (int)MS_XDEV2LOG(VIEWPORT_EXTENT
); 
2374     m_nWindowExtY 
= (int)MS_YDEV2LOG(VIEWPORT_EXTENT
); 
2376 }; // end of wxDC::SetMapMode 
2378 void wxDC::SetUserScale( 
2386     SetMapMode(m_mappingMode
); 
2387 } // end of wxDC::SetUserScale 
2389 void wxDC::SetAxisOrientation( 
2394     m_signX 
= bXLeftRight 
? 1 : -1; 
2395     m_signY 
= bYBottomUp 
? -1 : 1; 
2397     SetMapMode(m_mappingMode
); 
2398 } // end of wxDC::SetAxisOrientation 
2400 void wxDC::SetSystemScale( 
2408     SetMapMode(m_mappingMode
); 
2409 } // end of wxDC::SetSystemScale 
2411 void wxDC::SetLogicalOrigin( 
2418     ::GpiQueryPageViewport( m_hPS
 
2425     ::GpiSetPageViewport( m_hPS
 
2428 }; // end of wxDC::SetLogicalOrigin 
2430 void wxDC::SetDeviceOrigin( 
2437     m_deviceOriginX 
= vX
; 
2438     m_deviceOriginY 
= vY
; 
2439     ::GpiQueryPageViewport( m_hPS
 
2444     vRect
.yBottom 
-= vY
; 
2446     ::GpiSetPageViewport( m_hPS
 
2449 }; // end of wxDC::SetDeviceOrigin 
2451 // --------------------------------------------------------------------------- 
2452 // coordinates transformations 
2453 // --------------------------------------------------------------------------- 
2455 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
2457     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
2460 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
2462     // axis orientation is not taken into account for conversion of a distance 
2463     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_scaleX
)); 
2466 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
2468     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
2471 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
2473     // axis orientation is not taken into account for conversion of a distance 
2474     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_scaleY
)); 
2477 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
2479     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
2482 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
2484     // axis orientation is not taken into account for conversion of a distance 
2485     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_scaleX
); 
2488 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
2490     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
2493 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
2495     // axis orientation is not taken into account for conversion of a distance 
2496     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_scaleY
); 
2499 // --------------------------------------------------------------------------- 
2501 // --------------------------------------------------------------------------- 
2517     wxMask
*                         pMask 
= NULL
; 
2519     COLORREF                        vOldTextColor
; 
2520     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
2524         const wxBitmap
&             rBmp 
= pSource
->m_vSelectedBitmap
; 
2526         pMask 
= rBmp
.GetMask(); 
2527         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
2533     ::GpiQueryAttrs( m_hPS
 
2538     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
2540     if (m_textForegroundColour
.Ok()) 
2542         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
2543         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2544                       ,PRIM_CHAR       
// Char primitive. 
2545                       ,CBB_COLOR       
// sets color. 
2547                       ,&vCbnd          
// buffer for attributes. 
2550     if (m_textBackgroundColour
.Ok()) 
2552         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
2555     LONG                            lRop 
= ROP_SRCCOPY
; 
2559         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
2560         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
2561         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
2562         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
2563         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
2564         case wxSET
:          lRop 
= ROP_ONE
;              break; 
2565         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
2566         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
2567         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
2568         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
2569         case wxNAND
:         lRop 
= 0x007700E6;           break; 
2570         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
2571         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
2572         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
2573         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
2574         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
2576            wxFAIL_MSG( wxT("unsupported logical function") ); 
2585         // Blit bitmap with mask 
2589         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2595         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2596         BITMAPINFOHEADER2               vBmpHdr
; 
2598         SIZEL                           vSize 
= {0, 0}; 
2601         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2602         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2603         vBmpHdr
.cx        
= vWidth
; 
2604         vBmpHdr
.cy        
= vHeight
; 
2605         vBmpHdr
.cPlanes   
= 1; 
2606         vBmpHdr
.cBitCount 
= 24; 
2608 #if wxUSE_DC_CACHEING 
2612             // create a temp buffer bitmap and DCs to access it and the mask 
2614             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2617             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2620             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2625             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2626             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2627             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2632             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2633             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2634             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2635             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2636             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2639         POINTL                          aPoint1
[4] = { {0, 0} 
2642                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2644         POINTL                          aPoint2
[4] = { {0, 0} 
2647                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2649         POINTL                          aPoint3
[4] = { {vXdest
, vYdest
} 
2650                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2652                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2654         POINTL                          aPoint4
[4] = { {vXdest
, vYdest
} 
2655                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2659         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2660         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2663         // Copy dest to buffer 
2665         rc 
= ::GpiBitBlt( hPSBuffer
 
2672         if (rc 
== GPI_ERROR
) 
2674             wxLogLastError(wxT("BitBlt")); 
2678         // Copy src to buffer using selected raster op 
2680         rc 
= ::GpiBitBlt( hPSBuffer
 
2687         if (rc 
== GPI_ERROR
) 
2689             wxLogLastError(wxT("BitBlt")); 
2693         // Set masked area in buffer to BLACK (pixel value 0) 
2695         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2696         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2698         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2699         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2701         rc 
= ::GpiBitBlt( hPSBuffer
 
2708         if (rc 
== GPI_ERROR
) 
2710             wxLogLastError(wxT("BitBlt")); 
2714         // Set unmasked area in dest to BLACK 
2716         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2717         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2718         rc 
= ::GpiBitBlt( GetHPS() 
2725         if (rc 
== GPI_ERROR
) 
2727             wxLogLastError(wxT("BitBlt")); 
2731         // Restore colours to original values 
2733         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2734         ::GpiSetColor(GetHPS(), vPrevCol
); 
2737         // OR buffer to dest 
2739         rc 
= ::GpiBitBlt( GetHPS() 
2746         if (rc 
== GPI_ERROR
) 
2749             wxLogLastError(wxT("BitBlt")); 
2753         // Tidy up temporary DCs and bitmap 
2755         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2756         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2757 #if !wxUSE_DC_CACHEING 
2758         ::GpiDestroyPS(hPSMask
); 
2759         ::GpiDestroyPS(hPSBuffer
); 
2760         ::DevCloseDC(hDCMask
); 
2761         ::DevCloseDC(hDCBuffer
); 
2762         ::GpiDeleteBitmap(hBufBitmap
); 
2766     else // no mask, just BitBlt() it 
2768       POINTL                          aPoint
[4] = { {vXdest
, vYdest
} 
2769                            ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2771                            ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2774         bSuccess 
= (::GpiBitBlt( m_hPS
 
2783             wxLogLastError(wxT("BitBlt")); 
2786     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2787     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2788                   ,PRIM_CHAR       
// Char primitive. 
2789                   ,CBB_COLOR       
// sets color. 
2791                   ,&vCbnd          
// buffer for attributes. 
2793     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2797 void wxDC::DoGetSize( 
2802     LONG                            lArray
[CAPS_HEIGHT
]; 
2804     if(::DevQueryCaps( m_hDC
 
2810         *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2811         *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2813 }; // end of wxDC::DoGetSize( 
2815 void wxDC::DoGetSizeMM( 
2820     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2822     if(::DevQueryCaps( m_hDC
 
2824                       ,CAPS_VERTICAL_RESOLUTION
 
2833         nWidth    
= lArray
[CAPS_WIDTH
]; 
2834         nHeight   
= lArray
[CAPS_HEIGHT
]; 
2835         nHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2836         nVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2837         nWidth  
= (nHorzRes
/1000) * nWidth
; 
2838         nHeight 
= (nVertRes
/1000) * nHeight
; 
2840 }; // end of wxDC::DoGetSizeMM 
2842 wxSize 
wxDC::GetPPI() const 
2844     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2848     if(::DevQueryCaps( m_hDC
 
2850                       ,CAPS_VERTICAL_RESOLUTION
 
2859         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2860         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2861         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2862         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2863         nWidth   
= (int)((nHorzRes
/39.3) * nPelWidth
); 
2864         nHeight  
= (int)((nVertRes
/39.3) * nPelHeight
); 
2866     return (wxSize(nWidth
,nHeight
)); 
2867 } // end of wxDC::GetPPI 
2869 void wxDC::SetLogicalScale( 
2874     m_logicalScaleX 
= dX
; 
2875     m_logicalScaleY 
= dY
; 
2876 }; // end of wxDC::SetLogicalScale