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" 
  37 #include "wx/os2/private.h" 
  39     IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  42 // wxWidgets uses the Microsoft convention that the origin is the UPPER left. 
  43 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  44 // In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must 
  45 // perform the following transformation: 
  47 // Parent object height:     POBJHEIGHT 
  48 // Desried origin:           WXORIGINY 
  49 // Object to place's height: OBJHEIGHT 
  51 // To get the OS2 position from the wxWidgets one: 
  53 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  55 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  56 // OS/2 Presentation Space associated with the device context.  y is the 
  57 // desired application's y coordinate of the origin in wxWidgets space. 
  58 // objy is the height of the object we are going to draw. 
  60 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  62 // --------------------------------------------------------------------------- 
  64 // --------------------------------------------------------------------------- 
  66 static const int VIEWPORT_EXTENT 
= 1000; 
  68 static const int MM_POINTS 
= 9; 
  69 static const int MM_METRIC 
= 10; 
  71 // usually this is defined in math.h 
  73     static const double M_PI 
= 3.14159265358979323846; 
  76 // --------------------------------------------------------------------------- 
  78 // --------------------------------------------------------------------------- 
  80 // convert degrees to radians 
  81 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  85 , int                               nForegroundColour
 
  90     vCbnd
.lColor 
=  nForegroundColour
; 
  91     ::GpiSetAttrs( hPS       
// presentation-space handle 
  92                   ,PRIM_CHAR 
// Char primitive. 
  93                   ,CBB_COLOR 
// sets color. 
  95                   ,&vCbnd    
// buffer for attributes. 
 100 int QueryTextBkColor( 
 106     ::GpiQueryAttrs( hPS            
// presentation-space handle 
 107                     ,PRIM_CHAR      
// Char primitive. 
 108                     ,CBB_BACK_COLOR 
// Background color. 
 109                     ,&vCbnd         
// buffer for attributes. 
 111     return vCbnd
.lBackColor
; 
 117 , int                               nBackgroundColour
 
 123     rc 
=  QueryTextBkColor(hPS
); 
 125     vCbnd
.lBackColor 
= nBackgroundColour
; 
 126     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 127                   PRIM_CHAR
,      // Char primitive. 
 128                   CBB_BACK_COLOR
, // sets color. 
 130                   &vCbnd          
// buffer for attributes. 
 137 , int                               nBackgroundMode
 
 140     if(nBackgroundMode 
== wxTRANSPARENT
) 
 145         // the background of the primitive takes  over whatever is underneath. 
 152 // =========================================================================== 
 154 // =========================================================================== 
 156 #if wxUSE_DC_CACHEING 
 159  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 160  * improve it in due course, either using arrays, or simply storing pointers to one 
 161  * entry for the bitmap, and two for the DCs. -- JACS 
 164 // --------------------------------------------------------------------------- 
 166 // --------------------------------------------------------------------------- 
 168 wxList 
wxDC::m_svBitmapCache
; 
 169 wxList 
wxDC::m_svDCCache
; 
 171 wxDCCacheEntry::wxDCCacheEntry( 
 183 } // end of wxDCCacheEntry::wxDCCacheEntry 
 185 wxDCCacheEntry::wxDCCacheEntry( 
 190     m_hBitmap 
= NULLHANDLE
; 
 195 } // end of wxDCCacheEntry::wxDCCacheEntry 
 197 wxDCCacheEntry::~wxDCCacheEntry() 
 200         ::GpiDeleteBitmap(m_hBitmap
); 
 202         ::GpiDestroyPS(m_hPS
); 
 203 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 205 wxDCCacheEntry
* wxDC::FindBitmapInCache( 
 211     int                             nDepth 
= 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 212     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 213     BITMAPINFOHEADER2               vBmpHdr
; 
 217         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 219         if (pEntry
->m_nDepth 
== nDepth
) 
 221             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 223             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 225                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 226                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 228                 vBmpHdr
.cy        
= nHeight
; 
 230                 vBmpHdr
.cBitCount 
= nDepth
; 
 232                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 236                 if (!pEntry
->m_hBitmap
) 
 238                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 240                 pEntry
->m_nWidth  
= nWidth
; 
 241                 pEntry
->m_nHeight 
= nHeight
; 
 246         pNode 
= pNode
->Next(); 
 248     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 249     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 251     vBmpHdr
.cy        
= nHeight
; 
 253     vBmpHdr
.cBitCount 
= nDepth
; 
 255     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 261         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 263     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 268     AddToBitmapCache(pEntry
); 
 270 } // end of FindBitmapInCache 
 272 wxDCCacheEntry
* wxDC::FindDCInCache( 
 273   wxDCCacheEntry
*                   pNotThis
 
 277     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 278     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 282         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 285         // Don't return the same one as we already have 
 287         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 289             if (pEntry
->m_nDepth 
== nDepth
) 
 294         pNode 
= pNode
->Next(); 
 296     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 299     AddToDCCache(pEntry
); 
 301 } // end of wxDC::FindDCInCache 
 303 void wxDC::AddToBitmapCache( 
 304   wxDCCacheEntry
*                   pEntry
 
 307     m_svBitmapCache
.Append(pEntry
); 
 308 } // end of wxDC::AddToBitmapCache 
 310 void wxDC::AddToDCCache( 
 311   wxDCCacheEntry
*                   pEntry
 
 314     m_svDCCache
.Append(pEntry
); 
 315 } // end of wxDC::AddToDCCache 
 317 void wxDC::ClearCache() 
 319     m_svBitmapCache
.DeleteContents(true); 
 320     m_svBitmapCache
.Clear(); 
 321     m_svBitmapCache
.DeleteContents(false); 
 322     m_svDCCache
.DeleteContents(true); 
 324     m_svDCCache
.DeleteContents(false); 
 325 } // end of wxDC::ClearCache 
 327 // Clean up cache at app exit 
 328 class wxDCModule 
: public wxModule
 
 331     virtual bool OnInit() { return true; } 
 332     virtual void OnExit() { wxDC::ClearCache(); } 
 335     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 336 }; // end of CLASS wxDCModule 
 338 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 340 #endif // ndef for wxUSE_DC_CACHEING 
 342 // --------------------------------------------------------------------------- 
 344 // --------------------------------------------------------------------------- 
 360     m_bIsPaintTime 
= false; // True at Paint Time 
 362     wxColour 
vColor( wxT("BLACK") ); 
 363     m_pen
.SetColour(vColor
); 
 365     vColor
.Set( wxT("WHITE") ); 
 366     m_brush
.SetColour(vColor
); 
 368 } // end of wxDC::wxDC 
 374         SelectOldObjects(m_hDC
); 
 376         // if we own the HDC, we delete it, otherwise we just release it 
 382                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 383                 ::GpiDestroyPS(m_hPS
); 
 386             ::DevCloseDC((HDC
)m_hDC
); 
 391             // Just Dissacociate, not destroy if we don't own the DC 
 395                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 399 } // end of wxDC::~wxDC 
 401 // This will select current objects out of the DC, 
 402 // which is what you have to do before deleting the 
 404 void wxDC::SelectOldObjects( 
 412             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 413             if (m_vSelectedBitmap
.Ok()) 
 415                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 420         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 428     m_brush           
= wxNullBrush
; 
 430     m_palette         
= wxNullPalette
; 
 432     m_backgroundBrush 
= wxNullBrush
; 
 433     m_vSelectedBitmap 
= wxNullBitmap
; 
 434 } // end of wxDC::SelectOldObjects 
 436 // --------------------------------------------------------------------------- 
 438 // --------------------------------------------------------------------------- 
 440 #define DO_SET_CLIPPING_BOX()                    \ 
 444     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 446     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 447     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 448     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 449     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 452 void wxDC::DoSetClippingRegion( 
 461     vY 
= OS2Y(vY
,vHeight
); 
 464     vRect
.yTop    
= vY 
+ vHeight
; 
 465     vRect
.xRight  
= vX 
+ vWidth
; 
 467     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 468     DO_SET_CLIPPING_BOX() 
 469 } // end of wxDC::DoSetClippingRegion 
 471 void wxDC::DoSetClippingRegionAsRegion( 
 472   const wxRegion
&                   rRegion
 
 475      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 479      ::GpiSetClipRegion( m_hPS
 
 480                         ,(HRGN
)rRegion
.GetHRGN() 
 483     DO_SET_CLIPPING_BOX() 
 484 } // end of wxDC::DoSetClippingRegionAsRegion 
 486 void wxDC::DestroyClippingRegion(void) 
 488     if (m_clipping 
&& m_hPS
) 
 493          // TODO: this should restore the previous clipped region 
 494          //       so that OnPaint processing works correctly, and 
 495          //       the update doesn't get destroyed after the first 
 496          //       DestroyClippingRegion 
 497          vRect
.xLeft   
= XLOG2DEV(0); 
 498          vRect
.yTop    
= YLOG2DEV(32000); 
 499          vRect
.xRight  
= XLOG2DEV(32000); 
 500          vRect
.yBottom 
= YLOG2DEV(0); 
 502          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 504          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 507 } // end of wxDC::DestroyClippingRegion 
 509 // --------------------------------------------------------------------------- 
 510 // query capabilities 
 511 // --------------------------------------------------------------------------- 
 513 bool wxDC::CanDrawBitmap() const 
 518 bool wxDC::CanGetTextExtent() const 
 520     LONG                            lTechnology 
= 0L; 
 522     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 523     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 524 } // end of wxDC::CanGetTextExtent 
 526 int wxDC::GetDepth() const 
 528     LONG                            lArray
[CAPS_COLOR_BITCOUNT
]; 
 529     int                             nBitsPerPixel 
= 0; 
 531     if(::DevQueryCaps( GetHDC() 
 537         nBitsPerPixel 
= (int)lArray
[CAPS_COLOR_BITCOUNT
]; 
 539     return nBitsPerPixel
; 
 540 } // end of wxDC::GetDepth 
 542 // --------------------------------------------------------------------------- 
 544 // --------------------------------------------------------------------------- 
 549     // If this is a canvas DC then just fill with the background color 
 550     // Otherwise purge the whole thing 
 556         ::GpiQueryClipBox(m_hPS
, &vRect
); 
 557         ::WinFillRect(m_hPS
, &vRect
, ::GpiQueryBackColor(m_hPS
)); 
 561 } // end of wxDC::Clear 
 563 bool wxDC::DoFloodFill( 
 566 , const wxColour
&                   rCol
 
 574     bool                            bSuccess 
= false; 
 576     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 577     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 578     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 579     lColor 
= rCol
.GetPixel(); 
 580     lOptions 
= FF_BOUNDARY
; 
 581     if(wxFLOOD_SURFACE 
== nStyle
) 
 582         lOptions 
= FF_SURFACE
; 
 584     if ((lHits 
= ::GpiFloodFill(m_hPS
, lOptions
, lColor
)) != GPI_ERROR
) 
 588 } // end of wxDC::DoFloodFill 
 590 bool wxDC::DoGetPixel( 
 600     vPoint
.y 
= OS2Y(vY
,0); 
 601     lColor 
= ::GpiSetPel(m_hPS
, &vPoint
); 
 604     // Get the color of the pen 
 606     LONG                            lPencolor 
= 0x00ffffff; 
 610         lPencolor 
= m_pen
.GetColour().GetPixel(); 
 614     // return the color of the pixel 
 617         pCol
->Set( GetRValue(lColor
) 
 621     return(lColor 
== lPencolor
); 
 622 } // end of wxDC::DoGetPixel 
 624 void wxDC::DoCrossHair( 
 631     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 632     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 633     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 634     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 643     ::GpiMove(m_hPS
, &vPoint
[0]); 
 644     ::GpiLine(m_hPS
, &vPoint
[1]); 
 652     ::GpiMove(m_hPS
, &vPoint
[2]); 
 653     ::GpiLine(m_hPS
, &vPoint
[3]); 
 654     CalcBoundingBox(vX1
, vY1
); 
 655     CalcBoundingBox(vX2
, vY2
); 
 656 } // end of wxDC::DoCrossHair 
 658 void wxDC::DoDrawLine( 
 666     COLORREF                        vColor 
= 0x00ffffff; 
 669     // Might be a memory DC with no Paint rect. 
 671     if (!(m_vRclPaint
.yTop 
== 0 && 
 672           m_vRclPaint
.yBottom 
== 0 && 
 673           m_vRclPaint
.xRight 
== 0 && 
 674           m_vRclPaint
.xLeft 
== 0)) 
 681         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
 683             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
 684             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
 695         vColor 
= m_pen
.GetColour().GetPixel(); 
 697     ::GpiSetColor(m_hPS
, vColor
); 
 698     ::GpiMove(m_hPS
, &vPoint
[0]); 
 699     ::GpiLine(m_hPS
, &vPoint
[1]); 
 700     CalcBoundingBox(vX1
, vY1
); 
 701     CalcBoundingBox(vX2
, vY2
); 
 702 } // end of wxDC::DoDrawLine 
 704 ////////////////////////////////////////////////////////////////////////////// 
 705 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 706 // and ending at (x2, y2). The current pen is used for the outline and the 
 707 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 708 // direction from the start point to the end point. 
 709 ////////////////////////////////////////////////////////////////////////////// 
 710 void wxDC::DoDrawArc( 
 720      POINTL                         vPtlArc
[2]; // Structure for current position 
 727      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 729     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 730         return; // Draw point ?? 
 731     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 734                       hypot( (double)(vY2 
- vYc
) 
 739     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 742     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 749     // GpiPointArc can't draw full arc 
 751      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 756         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 757         vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 758         vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 773     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 774     vXm      
= (wxCoord
)(vXc 
+ dRadius 
* cos(dAnglmid
)); 
 775     vYm      
= (wxCoord
)(vYc 
+ dRadius 
* sin(dAnglmid
)); 
 778     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 784     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 786     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 787     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 788     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 793     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 794     CalcBoundingBox( (wxCoord
)(vXc 
- dRadius
) 
 795                     ,(wxCoord
)(vYc 
- dRadius
) 
 797     CalcBoundingBox( (wxCoord
)(vXc 
+ dRadius
) 
 798                     ,(wxCoord
)(vYc 
+ dRadius
) 
 800 } // end of wxDC::DoDrawArc 
 802 void wxDC::DoDrawCheckMark( 
 811     vY1 
= OS2Y(vY1
,vHeight
); 
 815     vPoint
[1].x 
= vX1 
+ vWidth
; 
 816     vPoint
[1].y 
= vY1 
+ vHeight
; 
 818     ::GpiMove(m_hPS
, &vPoint
[0]); 
 819     ::GpiBox( m_hPS       
// handle to a presentation space 
 820              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 821              ,&vPoint
[1]  // address of the corner 
 822              ,0L          // horizontal corner radius 
 823              ,0L          // vertical corner radius 
 825     if(vWidth 
> 4 && vHeight 
> 4) 
 829         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 830         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 831         ::GpiMove(m_hPS
, &vPoint
[0]); 
 832         ::GpiLine(m_hPS
, &vPoint
[1]); 
 834         vPoint
[0].x 
= vPoint
[1].x
; 
 836         ::GpiMove(m_hPS
, &vPoint
[0]); 
 837         ::GpiLine(m_hPS
, &vPoint
[1]); 
 843     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 844     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 849 } // end of wxDC::DoDrawCheckMark 
 851 void wxDC::DoDrawPoint( 
 857     COLORREF                        vColor 
= 0x00ffffff; 
 861         vColor 
= m_pen
.GetColour().GetPixel(); 
 863     ::GpiSetColor(m_hPS
, vColor
); 
 865     vPoint
.y 
= OS2Y(vY
,0); 
 866     ::GpiSetPel(m_hPS
, &vPoint
); 
 870 } // end of wxDC::DoDrawPoint 
 872 void wxDC::DoDrawPolygon( 
 880     ULONG                           ulCount 
= 1;    // Number of polygons. 
 881     POLYGON                         vPlgn
;          // polygon. 
 882     ULONG                           flOptions 
= 0L; // Drawing options. 
 884 ////////////////////////////////////////////////////////////////////////////// 
 885 // This contains fields of option bits... to draw boundary lines as well as 
 886 // the area interior. 
 888 // Drawing boundary lines: 
 889 //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 890 //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 892 // Construction of the area interior: 
 893 //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 895 //   POLYGON_WINDING                 Constructs interior in winding mode. 
 896 ////////////////////////////////////////////////////////////////////////////// 
 898     ULONG                           flModel 
= 0L; // Drawing model. 
 900 ////////////////////////////////////////////////////////////////////////////// 
 902 //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 903 //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 904 //       This is provided to aid migration from other graphics models. 
 905 ////////////////////////////////////////////////////////////////////////////// 
 907     LONG                            lHits 
= 0L; // Correlation/error indicator. 
 910     int                             nIsTRANSPARENT 
= 0; 
 911     LONG                            lBorderColor 
= 0L; 
 914     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 915     lColor       
= m_brush
.GetColour().GetPixel(); 
 916     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 920     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 922                                     ); // well, new will call malloc 
 924     for(i 
= 0; i 
< n
; i
++) 
 926         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
;         // +xoffset; 
 927         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
,0); // +yoffset; 
 929     flModel 
= POLYGON_BOUNDARY
; 
 930     if(nFillStyle 
== wxWINDING_RULE
) 
 931         flModel 
|= POLYGON_WINDING
; 
 933         flModel 
|= POLYGON_ALTERNATE
; 
 936     vPoint
.y 
= OS2Y(vYoffset
,0); 
 938     ::GpiSetColor(m_hPS
, lBorderColor
); 
 939     ::GpiMove(m_hPS
, &vPoint
); 
 940     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 942 } // end of wxDC::DoDrawPolygon 
 944 void wxDC::DoDrawLines( 
 953     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 957         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 958         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 959         ::GpiMove(m_hPS
, &vPoint
); 
 961         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 963         ::GpiSetColor(m_hPS
, lBorderColor
); 
 964         for(i 
= 1; i 
< n
; i
++) 
 966             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 967             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 968             ::GpiLine(m_hPS
, &vPoint
); 
 975         CalcBoundingBox( vPoints
[0].x
 
 978         vPoint
.x 
= vPoints
[0].x
; 
 979         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 980         ::GpiMove(m_hPS
, &vPoint
); 
 982         for (i 
= 0; i 
< n
; i
++) 
 984             CalcBoundingBox( vPoints
[i
].x
 
 987             vPoint
.x 
= vPoints
[i
].x
; 
 988             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 989             ::GpiLine(m_hPS
, &vPoint
); 
 992 } // end of wxDC::DoDrawLines 
 994 void wxDC::DoDrawRectangle( 
1005     int                             nIsTRANSPARENT 
= 0; 
1008     // Might be a memory DC with no Paint rect. 
1010     if (!(m_vRclPaint
.yTop 
== 0 && 
1011           m_vRclPaint
.yBottom 
== 0 && 
1012           m_vRclPaint
.xRight 
== 0 && 
1013           m_vRclPaint
.xLeft 
== 0)) 
1014         vY 
= OS2Y(vY
,vHeight
); 
1017         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1019             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1020             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1021             vY 
= OS2Y(vY
,vHeight
); 
1025     wxCoord                         vX2 
= vX 
+ vWidth
; 
1026     wxCoord                         vY2 
= vY 
+ vHeight
; 
1030     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1031     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1032     ::GpiMove(m_hPS
, &vPoint
[0]); 
1033     lColor       
= m_brush
.GetColour().GetPixel(); 
1034     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1035     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1037     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1039         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1040         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1041             lControl 
= DRO_OUTLINE
; 
1043         ::GpiSetColor(m_hPS
, lBorderColor
); 
1044         ::GpiBox( m_hPS       
// handle to a presentation space 
1045                  ,lControl   
// draw the box outline ? or ? 
1046                  ,&vPoint
[1]  // address of the corner 
1047                  ,0L          // horizontal corner radius 
1048                  ,0L          // vertical corner radius 
1053         lControl 
= DRO_OUTLINE
; 
1054         ::GpiSetColor( m_hPS
 
1063         lControl 
= DRO_FILL
; 
1064         ::GpiSetColor( m_hPS
 
1067         vPoint
[0].x 
= vX 
+ 1; 
1068         vPoint
[0].y 
= vY 
+ 1; 
1069         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1070         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1071         ::GpiMove(m_hPS
, &vPoint
[0]); 
1079     CalcBoundingBox(vX
, vY
); 
1080     CalcBoundingBox(vX2
, vY2
); 
1081 } // end of wxDC::DoDrawRectangle 
1083 void wxDC::DoDrawRoundedRectangle( 
1095     int                             nIsTRANSPARENT 
= 0; 
1098     // Might be a memory DC with no Paint rect. 
1100     if (!(m_vRclPaint
.yTop 
== 0 && 
1101           m_vRclPaint
.yBottom 
== 0 && 
1102           m_vRclPaint
.xRight 
== 0 && 
1103           m_vRclPaint
.xLeft 
== 0)) 
1104         vY 
= OS2Y(vY
,vHeight
); 
1107         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1109             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1110             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1111             vY 
= OS2Y(vY
,vHeight
); 
1115     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1116     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1120     vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1121     vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1122     ::GpiMove(m_hPS
, &vPoint
[0]); 
1124     lColor       
= m_brush
.GetColour().GetPixel(); 
1125     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
1126     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1127     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1129     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
1131         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1132         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
1133             lControl 
= DRO_OUTLINE
; 
1135         ::GpiSetColor(m_hPS
, lColor
); 
1136         ::GpiBox( m_hPS         
// handle to a presentation space 
1137                  ,lControl      
// draw the box outline ? or ? 
1138                  ,&vPoint
[1]    // address of the corner 
1139                  ,(LONG
)dRadius 
// horizontal corner radius 
1140                  ,(LONG
)dRadius 
// vertical corner radius 
1145         lControl 
= DRO_OUTLINE
; 
1146         ::GpiSetColor( m_hPS
 
1155         lControl 
= DRO_FILL
; 
1156         ::GpiSetColor( m_hPS
 
1159         vPoint
[0].x 
= vX 
+ 1; 
1160         vPoint
[0].y 
= vY 
+ 1; 
1161         vPoint
[1].x 
= vX 
+ vWidth 
- 2; 
1162         vPoint
[1].y 
= vY 
+ vHeight 
- 2; 
1163         ::GpiMove(m_hPS
, &vPoint
[0]); 
1172     CalcBoundingBox(vX
, vY
); 
1173     CalcBoundingBox(vX2
, vY2
); 
1174 } // end of wxDC::DoDrawRoundedRectangle 
1176 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1177 void wxDC::DoDrawEllipse( 
1184     POINTL                          vPtlPos
; // Structure for current position 
1185     FIXED                           vFxMult
; // Multiplier for ellipse 
1186     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1188     vY 
= OS2Y(vY
,vHeight
); 
1191     vArcp
.lQ 
= vHeight
/2; 
1192     vArcp
.lP 
= vWidth
/2; 
1194     ::GpiSetArcParams( m_hPS
 
1196                      ); // Sets parameters to default 
1197     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1198     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1201              ); // Sets current position 
1202     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1205     // DRO_FILL, DRO_OTLINEFILL - where to get 
1210                 ); // Draws full arc with center at current position 
1212     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1213     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1215     CalcBoundingBox(vX
, vY
); 
1216     CalcBoundingBox(vX2
, vY2
); 
1217 } // end of wxDC::DoDrawEllipse 
1219 void wxDC::DoDrawEllipticArc( 
1228     POINTL                          vPtlPos
; // Structure for current position 
1229     FIXED                           vFxMult
; // Multiplier for ellipse 
1230     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1232     FIXED                           vFSweepa
; // Start angle, sweep angle 
1236     vY 
= OS2Y(vY
,vHeight
); 
1238     dFractPart 
= modf(dSa
,&dIntPart
); 
1239     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1240     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1241     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1244     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1247     vArcp
.lQ 
= vHeight
/2; 
1248     vArcp
.lP 
= vWidth
/2; 
1250     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1251     vPtlPos
.x 
= (wxCoord
)(vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
)))); // Loads x-coordinate 
1252     vPtlPos
.y 
= (wxCoord
)(vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
)))); // Loads y-coordinate 
1253     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1256     // May be not to the center ? 
1258     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1259     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1260     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1263     // DRO_FILL, DRO_OTLINEFILL - where to get 
1265     ::GpiPartialArc( m_hPS
 
1271     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1272     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1274     CalcBoundingBox(vX
, vY
); 
1275     CalcBoundingBox(vX2
, vY2
); 
1276 } // end of wxDC::DoDrawEllipticArc 
1278 void wxDC::DoDrawIcon( 
1285     // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords 
1286     // and I don't feel like figuring those out for scrollable windows so 
1287     // just convert to a bitmap then let the DoDrawBitmap routing display it 
1291         DoDrawBitmap(rIcon
.GetXpmSrc(), vX
, vY
, true); 
1295         wxBitmap                        
vBitmap(rIcon
); 
1297         DoDrawBitmap(vBitmap
, vX
, vY
, false); 
1299     CalcBoundingBox(vX
, vY
); 
1300     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1301 } // end of wxDC::DoDrawIcon 
1303 void wxDC::DoDrawBitmap( 
1304   const wxBitmap
&                   rBmp
 
1310     if (!IsKindOf(CLASSINFO(wxPrinterDC
))) 
1312         HBITMAP                         hBitmap 
=  (HBITMAP
)rBmp
.GetHBITMAP(); 
1316         vY 
= OS2Y(vY
,rBmp
.GetHeight()); 
1319         vPoint
[0].y 
= vY 
+ rBmp
.GetHeight(); 
1320         vPoint
[1].x 
= vX 
+ rBmp
.GetWidth(); 
1324         vPoint
[3].x 
= rBmp
.GetWidth(); 
1325         vPoint
[3].y 
= rBmp
.GetHeight(); 
1328             wxMask
*                     pMask 
= rBmp
.GetMask(); 
1333                 // Need to imitate ::MaskBlt in windows. 
1334                 // 1) Extract the bits from from the bitmap. 
1335                 // 2) Extract the bits from the mask 
1336                 // 3) Using the mask bits do the following: 
1337                 //   A) If the mask byte is 00 leave the bitmap byte alone 
1338                 //   B) If the mask byte is FF copy the screen color into 
1340                 // 4) Create a new bitmap and set its bits to the above result 
1341                 // 5) Blit this to the screen PS 
1343                 HBITMAP                 hMask 
= (HBITMAP
)pMask
->GetMaskBitmap(); 
1344                 HBITMAP                 hOldMask   
= NULLHANDLE
; 
1345                 HBITMAP                 hOldBitmap 
= NULLHANDLE
; 
1346                 HBITMAP                 hNewBitmap 
= NULLHANDLE
; 
1347                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1348                 unsigned char*          pucBitsMask
; // buffer that will contain the mask data 
1349                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1350                 unsigned char*          pucDataMask
; // pointer to use to traverse mask data 
1356                 // The usual Memory context creation stuff 
1358                 DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1359                 SIZEL                           vSize 
= {0, 0}; 
1360                 HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1361                 HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1364                 // The usual bitmap header stuff 
1366                 BITMAPINFOHEADER2               vHeader
; 
1369                 memset(&vHeader
, '\0', 16); 
1372                 memset(&vInfo
, '\0', 16); 
1374                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1375                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1377                 vInfo
.cBitCount       
= 24; // Set to desired count going in 
1380                 // Create the buffers for data....all wxBitmaps are 24 bit internally 
1382                 int                     nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1383                 int                     nSizeDWORD    
= sizeof(DWORD
); 
1384                 int                     nLineBoundary 
= nBytesPerLine 
% nSizeDWORD
; 
1392                 // Need to get a background color for mask blitting 
1394                 if (IsKindOf(CLASSINFO(wxWindowDC
))) 
1396                     wxWindowDC
*             pWindowDC 
= wxDynamicCast(this, wxWindowDC
); 
1398                     lColor 
= pWindowDC
->m_pCanvas
->GetBackgroundColour().GetPixel(); 
1400                 else if (GetBrush().Ok()) 
1401                     lColor 
= GetBrush().GetColour().GetPixel(); 
1403                     lColor 
= m_textBackgroundColour
.GetPixel(); 
1406                 // Bitmap must be ina double-word alligned address so we may 
1407                 // have some padding to worry about 
1409                 if (nLineBoundary 
> 0) 
1411                     nPadding     
= nSizeDWORD 
- nLineBoundary
; 
1412                     nBytesPerLine 
+= nPadding
; 
1414                 pucBits 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1415                 pucBitsMask 
= (unsigned char *)malloc(nBytesPerLine 
* rBmp
.GetHeight()); 
1416                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1417                 memset(pucBitsMask
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1420                 // Extract the bitmap and mask data 
1422                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1424                     vError 
= ::WinGetLastError(vHabmain
); 
1425                     sError 
= wxPMErrorToStr(vError
); 
1427                 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
); 
1428                 vInfo
.cBitCount 
= 24; 
1429                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1431                                                    ,(LONG
)rBmp
.GetHeight() 
1436                     vError 
= ::WinGetLastError(vHabmain
); 
1437                     sError 
= wxPMErrorToStr(vError
); 
1439                 if ((hOldMask 
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
) 
1441                     vError 
= ::WinGetLastError(vHabmain
); 
1442                     sError 
= wxPMErrorToStr(vError
); 
1444                 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
); 
1445                 vInfo
.cBitCount 
= 24; 
1446                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1448                                                    ,(LONG
)rBmp
.GetHeight() 
1453                     vError 
= ::WinGetLastError(vHabmain
); 
1454                     sError 
= wxPMErrorToStr(vError
); 
1456                 if (( hMask 
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
) 
1458                     vError 
= ::WinGetLastError(vHabmain
); 
1459                     sError 
= wxPMErrorToStr(vError
); 
1463                 // Now set the bytes(bits) according to the mask values 
1464                 // 3 bytes per pel...must handle one at a time 
1467                 pucDataMask 
= pucBitsMask
; 
1470                 // 16 bit kludge really only kinda works.  The mask gets applied 
1471                 // where needed but the original bitmap bits are dorked sometimes 
1473                 bool                    bpp16 
= (wxDisplayDepth() == 16); 
1475                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1477                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1480                         if (bpp16 
&& *pucDataMask 
== 0xF8) // 16 bit display gobblygook 
1482                         else if (*pucDataMask 
== 0xFF) // leave bitmap byte alone 
1486                             *pucData 
= ((unsigned char)(lColor 
>> 16)); 
1490                         if (bpp16 
&& *(pucDataMask 
+ 1) == 0xFC) // 16 bit display gobblygook 
1492                         else if (*(pucDataMask 
+ 1) == 0xFF) // leave bitmap byte alone 
1496                             *pucData 
= ((unsigned char)(lColor 
>> 8)); 
1501                         if (bpp16 
&& *(pucDataMask 
+ 2) == 0xF8) // 16 bit display gobblygook 
1503                         else if (*(pucDataMask 
+ 2) == 0xFF) // leave bitmap byte alone 
1507                             *pucData 
= ((unsigned char)lColor
); 
1512                     for (j 
= 0; j 
< nPadding
; j
++) 
1519                 // Create a new bitmap 
1521                 vHeader
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1522                 vHeader
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1523                 vHeader
.cPlanes         
= 1L; 
1524                 vHeader
.cBitCount       
= 24; 
1525                 if ((hNewBitmap 
= ::GpiCreateBitmap( hPS
 
1532                     vError 
= ::WinGetLastError(vHabmain
); 
1533                     sError 
= wxPMErrorToStr(vError
); 
1537                 // Now blit it to the screen PS 
1539                 if ((lHits 
= ::GpiWCBitBlt( (HPS
)GetHPS() 
1547                     vError 
= ::WinGetLastError(vHabmain
); 
1548                     sError 
= wxPMErrorToStr(vError
); 
1556                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1557                 ::GpiDeleteBitmap(hNewBitmap
); 
1558                 ::GpiDestroyPS(hPS
); 
1564             ULONG                       lOldForeGround 
= ::GpiQueryColor((HPS
)GetHPS()); 
1565             ULONG                       lOldBackGround 
= ::GpiQueryBackColor((HPS
)GetHPS()); 
1567             if (m_textForegroundColour
.Ok()) 
1569                 ::GpiSetColor( (HPS
)GetHPS() 
1570                                ,m_textForegroundColour
.GetPixel() 
1573             if (m_textBackgroundColour
.Ok()) 
1575                 ::GpiSetBackColor( (HPS
)GetHPS() 
1576                                   ,m_textBackgroundColour
.GetPixel() 
1580             // Need to alter bits in a mono bitmap to match the new 
1581             // background-foreground if it is different. 
1583             if (rBmp
.IsMono() && 
1584                ((m_textForegroundColour
.GetPixel() != lOldForeGround
) || 
1585                 (m_textBackgroundColour
.GetPixel() != lOldBackGround
))) 
1587                 DEVOPENSTRUC        vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1588                 SIZEL               vSize 
= {0, 0}; 
1589                 HDC                 hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1590                 HPS                 hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1592                 int                 nBytesPerLine 
= rBmp
.GetWidth() * 3; 
1594                 LONG                lForeGround 
= m_textForegroundColour
.GetPixel(); 
1595                 LONG                lBackGround 
= m_textBackgroundColour
.GetPixel(); 
1597                 HBITMAP             hOldBitmap 
= NULLHANDLE
; 
1603                 memset(&vInfo
, '\0', 16); 
1605                 vInfo
.cx              
= (ULONG
)rBmp
.GetWidth(); 
1606                 vInfo
.cy              
= (ULONG
)rBmp
.GetHeight(); 
1608                 vInfo
.cBitCount       
= 24; 
1610                 unsigned char*          pucBits
;     // buffer that will contain the bitmap data 
1611                 unsigned char*          pucData
;     // pointer to use to traverse bitmap data 
1613                 pucBits 
= new unsigned char[nBytesPerLine 
* rBmp
.GetHeight()]; 
1614                 memset(pucBits
, '\0', (nBytesPerLine 
* rBmp
.GetHeight())); 
1616                 if ((hOldBitmap 
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
) 
1618                     vError 
= ::WinGetLastError(vHabmain
); 
1619                     sError 
= wxPMErrorToStr(vError
); 
1622                 if ((lScans 
= ::GpiQueryBitmapBits( hPS
 
1624                                                    ,(LONG
)rBmp
.GetHeight() 
1629                     vError 
= ::WinGetLastError(vHabmain
); 
1630                     sError 
= wxPMErrorToStr(vError
); 
1633                 unsigned char           cOldRedFore   
= (unsigned char)(lOldForeGround 
>> 16); 
1634                 unsigned char           cOldGreenFore 
= (unsigned char)(lOldForeGround 
>> 8); 
1635                 unsigned char           cOldBlueFore  
= (unsigned char)lOldForeGround
; 
1637                 unsigned char           cRedFore   
= (unsigned char)(lForeGround 
>> 16); 
1638                 unsigned char           cGreenFore 
= (unsigned char)(lForeGround 
>> 8); 
1639                 unsigned char           cBlueFore  
= (unsigned char)lForeGround
; 
1641                 unsigned char           cRedBack   
= (unsigned char)(lBackGround 
>> 16); 
1642                 unsigned char           cGreenBack 
= (unsigned char)(lBackGround 
>> 8); 
1643                 unsigned char           cBlueBack  
= (unsigned char)lBackGround
; 
1646                 for (i 
= 0; i 
< rBmp
.GetHeight(); i
++) 
1648                     for (j 
= 0; j 
< rBmp
.GetWidth(); j
++) 
1650                         unsigned char    cBmpRed   
= *pucData
; 
1651                         unsigned char    cBmpGreen 
= *(pucData 
+ 1); 
1652                         unsigned char    cBmpBlue  
= *(pucData 
+ 2); 
1654                         if ((cBmpRed 
== cOldRedFore
) && 
1655                             (cBmpGreen 
== cOldGreenFore
) && 
1656                             (cBmpBlue 
== cOldBlueFore
)) 
1658                             *pucData 
= cBlueFore
; 
1660                             *pucData 
= cGreenFore
; 
1662                             *pucData 
= cRedFore
; 
1667                             *pucData 
= cBlueBack
; 
1669                             *pucData 
= cGreenBack
; 
1671                             *pucData 
= cRedBack
; 
1676                 if ((lScans 
= ::GpiSetBitmapBits( hPS
 
1678                                                  ,(LONG
)rBmp
.GetHeight() 
1683                     vError 
= ::WinGetLastError(vHabmain
); 
1684                     sError 
= wxPMErrorToStr(vError
); 
1688                 ::GpiSetBitmap(hPS
, NULLHANDLE
); 
1689                 ::GpiDestroyPS(hPS
); 
1692             ::GpiWCBitBlt( (HPS
)GetHPS() 
1699             ::GpiSetBitmap((HPS
)GetHPS(), hBitmapOld
); 
1700             ::GpiSetColor((HPS
)GetHPS(), lOldForeGround
); 
1701             ::GpiSetBackColor((HPS
)GetHPS(), lOldBackGround
); 
1704 } // end of wxDC::DoDrawBitmap 
1706 void wxDC::DoDrawText( 
1707   const wxString
&                   rsText
 
1720     CalcBoundingBox(vX
, vY
); 
1721     GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1722     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1723 } // end of wxDC::DoDrawText 
1725 void wxDC::DrawAnyText( 
1726   const wxString
&                   rsText
 
1731     int                             nOldBackground 
= 0; 
1738     // prepare for drawing the text 
1742     // Set text color attributes 
1744     if (m_textForegroundColour
.Ok()) 
1747                      ,(int)m_textForegroundColour
.GetPixel() 
1751     if (m_textBackgroundColour
.Ok()) 
1753         nOldBackground 
= SetTextBkColor( m_hPS
 
1754                                         ,(int)m_textBackgroundColour
.GetPixel() 
1760     GetTextExtent( rsText
 
1765     if (!(m_vRclPaint
.yTop 
== 0 && 
1766           m_vRclPaint
.yBottom 
== 0 && 
1767           m_vRclPaint
.xRight 
== 0 && 
1768           m_vRclPaint
.xLeft 
== 0)) 
1771         // Position Text a little differently in the Statusbar from other panels 
1773         if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1774             vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1776             vPtlStart
.y 
= (wxCoord
)(OS2Y(vY
,vTextY
/1.5)); // Full extent is a bit much 
1780         if (m_vSelectedBitmap 
!= wxNullBitmap
) 
1782             m_vRclPaint
.yTop 
= m_vSelectedBitmap
.GetHeight(); 
1783             m_vRclPaint
.xRight 
= m_vSelectedBitmap
.GetWidth(); 
1784             if (m_pCanvas 
&& m_pCanvas
->IsKindOf(CLASSINFO(wxStatusBar
))) 
1785                 vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1787                 vPtlStart
.y 
= (LONG
)(OS2Y(vY
,vTextY
/1.5)); 
1793     PCH                             pzStr 
= (PCH
)rsText
.c_str(); 
1795     ::GpiMove(m_hPS
, &vPtlStart
); 
1796     lHits 
= ::GpiCharString( m_hPS
 
1800     if (lHits 
!= GPI_OK
) 
1802         wxLogLastError(wxT("TextOut")); 
1806     // Restore the old parameters (text foreground colour may be left because 
1807     // it never is set to anything else, but background should remain 
1808     // transparent even if we just drew an opaque string) 
1810     if (m_textBackgroundColour
.Ok()) 
1811             SetTextBkColor( m_hPS
 
1819 void wxDC::DoDrawRotatedText( 
1820   const wxString
&                   rsText
 
1838         DoDrawText(text, x, y); 
1843         wxFillLogFont(&lf, &m_font); 
1845         // GDI wants the angle in tenth of degree 
1846         long angle10 = (long)(angle * 10); 
1847         lf.lfEscapement = angle10; 
1848         lf. lfOrientation = angle10; 
1850         HFONT hfont = ::CreateFontIndirect(&lf); 
1853             wxLogLastError("CreateFont"); 
1857             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1859             DrawAnyText(text, x, y); 
1861             (void)::SelectObject(GetHdc(), hfontOld); 
1864         // call the bounding box by adding all four vertices of the rectangle 
1865         // containing the text to it (simpler and probably not slower than 
1866         // determining which of them is really topmost/leftmost/...) 
1868         GetTextExtent(text, &w, &h); 
1870         double rad = DegToRad(angle); 
1872         // "upper left" and "upper right" 
1873         CalcBoundingBox(x, y); 
1874         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1875         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1877         // "bottom left" and "bottom right" 
1878         x += (wxCoord)(h*sin(rad)); 
1879         y += (wxCoord)(h*cos(rad)); 
1880         CalcBoundingBox(x, y); 
1881         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1886 // --------------------------------------------------------------------------- 
1888 // --------------------------------------------------------------------------- 
1890 void wxDC::DoSelectPalette( 
1895     // Set the old object temporarily, in case the assignment deletes an object 
1896     // that's not yet selected out. 
1907         hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1909             m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1911 } // end of wxDC::DoSelectPalette 
1913 void wxDC::InitializePalette() 
1915     if (wxDisplayDepth() <= 8 ) 
1918         // Look for any window or parent that has a custom palette. If any has 
1919         // one then we need to use it in drawing operations 
1921         wxWindow
*                   pWin 
= m_pCanvas
->GetAncestorWithCustomPalette(); 
1923         m_hasCustomPalette 
= pWin 
&& pWin
->HasCustomPalette(); 
1924         if (m_hasCustomPalette
) 
1926             m_palette 
= pWin
->GetPalette(); 
1929             // turn on PM translation for this palette 
1934 } // end of wxDC::InitializePalette 
1936 void wxDC::SetPalette( 
1937   const wxPalette
&                  rPalette
 
1944     m_palette 
= rPalette
; 
1952     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1954         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1955 } // end of wxDC::SetPalette 
1962     // Set the old object temporarily, in case the assignment deletes an object 
1963     // that's not yet selected out. 
1975     m_font
.SetPS(m_hPS
); // this will realize the font 
1979         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1980         if (hFont 
== (HFONT
) NULL
) 
1982             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
1985             m_hOldFont 
= (WXHFONT
) hFont
; 
1987 } // end of wxDC::SetFont 
1993     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2009             m_pen
.SetPS((HPS
)m_hOldPen
); 
2016         if (m_pen
.GetResourceHandle()) 
2020                 m_hOldPen 
= m_pen
.GetPS(); 
2022         ::GpiSetColor(m_hPS
, m_pen
.GetColour().GetPixel()); 
2026 void wxDC::SetBrush( 
2027   const wxBrush
&                    rBrush
 
2030     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2036     if (m_brush 
== rBrush
) 
2046             m_brush
.SetPS((HPS
)m_hOldBrush
); 
2053         if (m_brush
.GetResourceHandle()) 
2055             m_brush
.SetPS(m_hPS
); 
2057                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
2060 } // end of wxDC::SetBrush 
2062 void wxDC::SetBackground( 
2063   const wxBrush
&                    rBrush
 
2066     m_backgroundBrush 
= rBrush
; 
2067     if (!m_backgroundBrush
.Ok()) 
2071         bool                        bCustomColours 
= true; 
2074         // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to 
2075         // change background colours from the control-panel specified colours. 
2077         if (m_pCanvas
->IsKindOf(CLASSINFO(wxWindow
)) && 
2078             ((m_pCanvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
)) 
2079             bCustomColours 
= false; 
2082             if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
) 
2084                 m_pCanvas
->SetTransparent(true); 
2089                 // Setting the background brush of a DC 
2090                 // doesn't affect the window background colour. However, 
2091                 // I'm leaving in the transparency setting because it's needed by 
2092                 // various controls (e.g. wxStaticText) to determine whether to draw 
2093                 // transparently or not. TODO: maybe this should be a new function 
2094                 // wxWindow::SetTransparency(). Should that apply to the child itself, or the 
2096                 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour()); 
2098                 m_pCanvas
->SetTransparent(false); 
2102     COLORREF                        vNewColor 
= m_backgroundBrush
.GetColour().GetPixel(); 
2103     (void)::GpiSetBackColor((HPS
)m_hPS
, (LONG
)vNewColor
); 
2104 } // end of wxDC::SetBackground 
2106 void wxDC::SetBackgroundMode( 
2110     m_backgroundMode 
= nMode
; 
2111 } // end of wxDC::SetBackgroundMode 
2113 void wxDC::SetLogicalFunction( 
2117     m_logicalFunction 
= nFunction
; 
2118     SetRop((WXHDC
)m_hDC
); 
2119 } // wxDC::SetLogicalFunction 
2125     if (!hDC 
|| m_logicalFunction 
< 0) 
2129     switch (m_logicalFunction
) 
2140             lCRop 
= FM_MERGESRCNOT
; 
2144             lCRop 
= FM_NOTMASKSRC
; 
2156             lCRop 
= FM_MERGENOTSRC
; 
2160             lCRop 
= FM_MERGESRCNOT
; 
2172             lCRop 
= FM_SUBTRACT
; 
2179             lCRop 
= FM_OVERPAINT
; 
2182     ::GpiSetMix((HPS
)hDC
, lCRop
); 
2183 } // end of wxDC::SetRop 
2185 bool wxDC::StartDoc( 
2186   const wxString
&                   rsMessage
 
2189     // We might be previewing, so return true to let it continue. 
2191 } // end of wxDC::StartDoc 
2195 } // end of wxDC::EndDoc 
2197 void wxDC::StartPage() 
2199 } // end of wxDC::StartPage 
2201 void wxDC::EndPage() 
2203 } // end of wxDC::EndPage 
2205 // --------------------------------------------------------------------------- 
2207 // --------------------------------------------------------------------------- 
2209 wxCoord 
wxDC::GetCharHeight() const 
2211     FONTMETRICS                     vFM
; // metrics structure 
2213     ::GpiQueryFontMetrics( m_hPS
 
2214                           ,sizeof(FONTMETRICS
) 
2217     return YDEV2LOGREL(vFM
.lXHeight
); 
2220 wxCoord 
wxDC::GetCharWidth() const 
2222     FONTMETRICS                     vFM
; // metrics structure 
2224     ::GpiQueryFontMetrics( m_hPS
 
2225                           ,sizeof(FONTMETRICS
) 
2228     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
2231 void wxDC::DoGetTextExtent( 
2232   const wxString
&                   rsString
 
2235 , wxCoord
*                          pvDescent
 
2236 , wxCoord
*                          pvExternalLeading
 
2240     POINTL                          avPoint
[TXTBOX_COUNT
]; 
2245     FONTMETRICS                     vFM
; // metrics structure 
2248     ERRORID                         vErrorCode
; // last error id code 
2249     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
2251     char                            zMsg
[128]; // DEBUG 
2255         pFontToUse 
= (wxFont
*)&m_font
; 
2256     l 
= rsString
.length(); 
2257     pStr 
= (PCH
) rsString
.c_str(); 
2260     // In world coordinates. 
2262     bRc 
= ::GpiQueryTextBox( m_hPS
 
2265                             ,TXTBOX_COUNT 
// return maximum information 
2266                             ,avPoint      
// array of coordinates points 
2270        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
2271        sError 
= wxPMErrorToStr(vErrorCode
); 
2273        sprintf(zMsg
, "GpiQueryTextBox for %s: failed with Error: %lx - %s", pStr
, vErrorCode
, sError
.c_str()); 
2274        (void)wxMessageBox( "wxWidgets Menu sample" 
2280     vPtMin
.x 
= avPoint
[0].x
; 
2281     vPtMax
.x 
= avPoint
[0].x
; 
2282     vPtMin
.y 
= avPoint
[0].y
; 
2283     vPtMax
.y 
= avPoint
[0].y
; 
2284     for (i 
= 1; i 
< 4; i
++) 
2286         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
2287         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
2288         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
2289         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
2291     ::GpiQueryFontMetrics( m_hPS
 
2292                           ,sizeof(FONTMETRICS
) 
2297         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
2299         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
2301         *pvDescent 
= vFM
.lMaxDescender
; 
2302     if (pvExternalLeading
) 
2303         *pvExternalLeading 
= vFM
.lExternalLeading
; 
2306 void wxDC::SetMapMode( 
2310     int                             nPixelWidth 
= 0; 
2311     int                             nPixelHeight 
= 0; 
2314     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2316     m_mappingMode 
= nMode
; 
2318     if(::DevQueryCaps( m_hDC
 
2320                       ,CAPS_VERTICAL_RESOLUTION
 
2327         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
2328         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
2329         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2330         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2331         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
2332         nMmWidth 
= (lVertRes
/1000) * nPixelHeight
; 
2334     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
2339     double                          dMm2pixelsX 
= nPixelWidth
/nMmWidth
; 
2340     double                          dMm2pixelsY 
= nPixelHeight
/nMmHeight
; 
2345             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
2346             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
2350             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
2351             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
2355             m_logicalScaleX 
= dMm2pixelsX
; 
2356             m_logicalScaleY 
= dMm2pixelsY
; 
2360             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
2361             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
2366             m_logicalScaleX 
= 1.0; 
2367             m_logicalScaleY 
= 1.0; 
2373     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
2374     if (!ulOptions 
& PU_ARBITRARY
) 
2376         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
2377         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
2379     m_nWindowExtX 
= (int)MS_XDEV2LOG(VIEWPORT_EXTENT
); 
2380     m_nWindowExtY 
= (int)MS_YDEV2LOG(VIEWPORT_EXTENT
); 
2382 }; // end of wxDC::SetMapMode 
2384 void wxDC::SetUserScale( 
2392     SetMapMode(m_mappingMode
); 
2393 } // end of wxDC::SetUserScale 
2395 void wxDC::SetAxisOrientation( 
2400     m_signX 
= bXLeftRight 
? 1 : -1; 
2401     m_signY 
= bYBottomUp 
? -1 : 1; 
2403     SetMapMode(m_mappingMode
); 
2404 } // end of wxDC::SetAxisOrientation 
2406 void wxDC::SetSystemScale( 
2414     SetMapMode(m_mappingMode
); 
2415 } // end of wxDC::SetSystemScale 
2417 void wxDC::SetLogicalOrigin( 
2424     ::GpiQueryPageViewport( m_hPS
 
2431     ::GpiSetPageViewport( m_hPS
 
2434 }; // end of wxDC::SetLogicalOrigin 
2436 void wxDC::SetDeviceOrigin( 
2443     m_deviceOriginX 
= vX
; 
2444     m_deviceOriginY 
= vY
; 
2445     ::GpiQueryPageViewport( m_hPS
 
2450     vRect
.yBottom 
-= vY
; 
2452     ::GpiSetPageViewport( m_hPS
 
2455 }; // end of wxDC::SetDeviceOrigin 
2457 // --------------------------------------------------------------------------- 
2458 // coordinates transformations 
2459 // --------------------------------------------------------------------------- 
2461 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
2463     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
2466 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
2468     // axis orientation is not taken into account for conversion of a distance 
2469     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_scaleX
)); 
2472 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
2474     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
2477 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
2479     // axis orientation is not taken into account for conversion of a distance 
2480     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_scaleY
)); 
2483 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
2485     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
2488 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
2490     // axis orientation is not taken into account for conversion of a distance 
2491     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_scaleX
); 
2494 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
2496     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
2499 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
2501     // axis orientation is not taken into account for conversion of a distance 
2502     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_scaleY
); 
2505 // --------------------------------------------------------------------------- 
2507 // --------------------------------------------------------------------------- 
2523     wxMask
*                         pMask 
= NULL
; 
2525     COLORREF                        vOldTextColor
; 
2526     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
2530         const wxBitmap
&             rBmp 
= pSource
->m_vSelectedBitmap
; 
2532         pMask 
= rBmp
.GetMask(); 
2533         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
2539     ::GpiQueryAttrs( m_hPS
 
2544     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
2546     if (m_textForegroundColour
.Ok()) 
2548         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
2549         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2550                       ,PRIM_CHAR       
// Char primitive. 
2551                       ,CBB_COLOR       
// sets color. 
2553                       ,&vCbnd          
// buffer for attributes. 
2556     if (m_textBackgroundColour
.Ok()) 
2558         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
2561     LONG                            lRop 
= ROP_SRCCOPY
; 
2565         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
2566         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
2567         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
2568         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
2569         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
2570         case wxSET
:          lRop 
= ROP_ONE
;              break; 
2571         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
2572         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
2573         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
2574         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
2575         case wxNAND
:         lRop 
= 0x007700E6;           break; 
2576         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
2577         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
2578         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
2579         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
2580         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
2582            wxFAIL_MSG( wxT("unsupported logical function") ); 
2591         // Blit bitmap with mask 
2595         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2601         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2602         BITMAPINFOHEADER2               vBmpHdr
; 
2604         SIZEL                           vSize 
= {0, 0}; 
2607         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2608         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2609         vBmpHdr
.cx        
= vWidth
; 
2610         vBmpHdr
.cy        
= vHeight
; 
2611         vBmpHdr
.cPlanes   
= 1; 
2612         vBmpHdr
.cBitCount 
= 24; 
2614 #if wxUSE_DC_CACHEING 
2618             // create a temp buffer bitmap and DCs to access it and the mask 
2620             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2623             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2626             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2631             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2632             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2633             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2638             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2639             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2640             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2641             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2642             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2645         POINTL                          aPoint1
[4] = { {0, 0} 
2648                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2650         POINTL                          aPoint2
[4] = { {0, 0} 
2653                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2655         POINTL                          aPoint3
[4] = { {vXdest
, vYdest
} 
2656                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2658                               ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2660         POINTL                          aPoint4
[4] = { {vXdest
, vYdest
} 
2661                               ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2665         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2666         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2669         // Copy dest to buffer 
2671         rc 
= ::GpiBitBlt( hPSBuffer
 
2678         if (rc 
== GPI_ERROR
) 
2680             wxLogLastError(wxT("BitBlt")); 
2684         // Copy src to buffer using selected raster op 
2686         rc 
= ::GpiBitBlt( hPSBuffer
 
2693         if (rc 
== GPI_ERROR
) 
2695             wxLogLastError(wxT("BitBlt")); 
2699         // Set masked area in buffer to BLACK (pixel value 0) 
2701         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2702         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2704         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2705         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2707         rc 
= ::GpiBitBlt( hPSBuffer
 
2714         if (rc 
== GPI_ERROR
) 
2716             wxLogLastError(wxT("BitBlt")); 
2720         // Set unmasked area in dest to BLACK 
2722         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2723         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2724         rc 
= ::GpiBitBlt( GetHPS() 
2731         if (rc 
== GPI_ERROR
) 
2733             wxLogLastError(wxT("BitBlt")); 
2737         // Restore colours to original values 
2739         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2740         ::GpiSetColor(GetHPS(), vPrevCol
); 
2743         // OR buffer to dest 
2745         rc 
= ::GpiBitBlt( GetHPS() 
2752         if (rc 
== GPI_ERROR
) 
2755             wxLogLastError(wxT("BitBlt")); 
2759         // Tidy up temporary DCs and bitmap 
2761         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2762         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2763 #if !wxUSE_DC_CACHEING 
2764         ::GpiDestroyPS(hPSMask
); 
2765         ::GpiDestroyPS(hPSBuffer
); 
2766         ::DevCloseDC(hDCMask
); 
2767         ::DevCloseDC(hDCBuffer
); 
2768         ::GpiDeleteBitmap(hBufBitmap
); 
2772     else // no mask, just BitBlt() it 
2774       POINTL                          aPoint
[4] = { {vXdest
, vYdest
} 
2775                            ,{vXdest 
+ vWidth
, vYdest 
+ vHeight
} 
2777                            ,{vXsrc 
+ vWidth
, vYsrc 
+ vHeight
} 
2780         bSuccess 
= (::GpiBitBlt( m_hPS
 
2789             wxLogLastError(wxT("BitBlt")); 
2792     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2793     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2794                   ,PRIM_CHAR       
// Char primitive. 
2795                   ,CBB_COLOR       
// sets color. 
2797                   ,&vCbnd          
// buffer for attributes. 
2799     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2803 void wxDC::DoGetSize( 
2808     LONG                            lArray
[CAPS_HEIGHT
]; 
2810     if(::DevQueryCaps( m_hDC
 
2816         *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2817         *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2819 }; // end of wxDC::DoGetSize( 
2821 void wxDC::DoGetSizeMM( 
2826     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2828     if(::DevQueryCaps( m_hDC
 
2830                       ,CAPS_VERTICAL_RESOLUTION
 
2839         nWidth    
= lArray
[CAPS_WIDTH
]; 
2840         nHeight   
= lArray
[CAPS_HEIGHT
]; 
2841         nHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2842         nVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2843         nWidth  
= (nHorzRes
/1000) * nWidth
; 
2844         nHeight 
= (nVertRes
/1000) * nHeight
; 
2846 }; // end of wxDC::DoGetSizeMM 
2848 wxSize 
wxDC::GetPPI() const 
2850     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2854     if(::DevQueryCaps( m_hDC
 
2856                       ,CAPS_VERTICAL_RESOLUTION
 
2865         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2866         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2867         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2868         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2869         nWidth   
= (int)((nHorzRes
/39.3) * nPelWidth
); 
2870         nHeight  
= (int)((nVertRes
/39.3) * nPelHeight
); 
2872     return (wxSize(nWidth
,nHeight
)); 
2873 } // end of wxDC::GetPPI 
2875 void wxDC::SetLogicalScale( 
2880     m_logicalScaleX 
= dX
; 
2881     m_logicalScaleY 
= dY
; 
2882 }; // end of wxDC::SetLogicalScale