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" 
  28 #include "wx/dcprint.h" 
  33 #include "wx/os2/private.h" 
  35     IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  38 // wxWindows uses the Microsoft convention that the origin is the UPPER left. 
  39 // Native OS/2 however in the GPI and PM define the origin as the LOWER left. 
  40 // In order to map OS/2 GPI/PM y coordinates to wxWindows coordinates we must 
  41 // perform the following transformation: 
  43 // Parent object height:     POBJHEIGHT 
  44 // Desried origin:           WXORIGINY 
  45 // Object to place's height: OBJHEIGHT 
  47 // To get the OS2 position from the wxWindows one: 
  49 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT) 
  51 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the 
  52 // OS/2 Presentation Space associated with the device context.  y is the 
  53 // desired application's y coordinate of the origin in wxWindows space. 
  54 // objy is the height of the object we are going to draw. 
  56 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy)) 
  58 // --------------------------------------------------------------------------- 
  60 // --------------------------------------------------------------------------- 
  62 static const int VIEWPORT_EXTENT 
= 1000; 
  64 static const int MM_POINTS 
= 9; 
  65 static const int MM_METRIC 
= 10; 
  67 // usually this is defined in math.h 
  69     static const double M_PI 
= 3.14159265358979323846; 
  72 // --------------------------------------------------------------------------- 
  74 // --------------------------------------------------------------------------- 
  76 // convert degrees to radians 
  77 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  81 , int                               nForegroundColour
 
  86     vCbnd
.lColor 
=  nForegroundColour
; 
  87     ::GpiSetAttrs( hPS       
// presentation-space handle 
  88                   ,PRIM_CHAR 
// Char primitive. 
  89                   ,CBB_COLOR 
// sets color. 
  91                   ,&vCbnd    
// buffer for attributes. 
 102     ::GpiQueryAttrs( hPS            
// presentation-space handle 
 103                     ,PRIM_CHAR      
// Char primitive. 
 104                     ,CBB_BACK_COLOR 
// Background color. 
 105                     ,&vCbnd         
// buffer for attributes. 
 107     return vCbnd
.lBackColor
; 
 113 , int                               nBackgroundColour
 
 119     rc 
=  QueryTextBkColor(hPS
); 
 121     vCbnd
.lBackColor 
= nBackgroundColour
; 
 122     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 123                   PRIM_CHAR
,      // Char primitive. 
 124                   CBB_BACK_COLOR
, // sets color. 
 126                   &vCbnd          
// buffer for attributes. 
 133 , int                               nBackgroundMode
 
 136     if(nBackgroundMode 
== wxTRANSPARENT
) 
 141         // the background of the primitive takes  over whatever is underneath. 
 148 // =========================================================================== 
 150 // =========================================================================== 
 152 #if wxUSE_DC_CACHEING 
 155  * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will 
 156  * improve it in due course, either using arrays, or simply storing pointers to one 
 157  * entry for the bitmap, and two for the DCs. -- JACS 
 160 // --------------------------------------------------------------------------- 
 162 // --------------------------------------------------------------------------- 
 164 wxList 
wxDC::m_svBitmapCache
; 
 165 wxList 
wxDC::m_svDCCache
; 
 167 wxDCCacheEntry::wxDCCacheEntry( 
 179 } // end of wxDCCacheEntry::wxDCCacheEntry 
 181 wxDCCacheEntry::wxDCCacheEntry( 
 186     m_hBitmap 
= NULLHANDLE
; 
 191 } // end of wxDCCacheEntry::wxDCCacheEntry 
 193 wxDCCacheEntry::~wxDCCacheEntry() 
 196         ::GpiDeleteBitmap(m_hBitmap
); 
 198         ::GpiDestroyPS(m_hPS
); 
 199 } // end of wxDCCacheEntry::~wxDCCacheEntry 
 201 wxDCCacheEntry
* wxDC::FindBitmapInCache( 
 207     int                             nDepth 
= 24 // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 208     wxNode
*                         pNode 
= m_svBitmapCache
.First(); 
 209     BITMAPINFOHEADER2               vBmpHdr
; 
 213         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 215         if (pEntry
->m_nDepth 
== nDepth
) 
 217             memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 219             if (pEntry
->m_nWidth 
< nWidth 
|| pEntry
->m_nHeight 
< nHeight
) 
 221                 ::GpiDeleteBitmap((HBITMAP
)pEntry
->m_hBitmap
); 
 222                 vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 224                 vBmpHdr
.cy        
= nHeight
; 
 226                 vBmpHdr
.cBitCount 
= nDepth
; 
 228                 pEntry
->m_hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 232                 if (!pEntry
->m_hBitmap
) 
 234                     wxLogLastError(wxT("CreateCompatibleBitmap")); 
 236                 pEntry
->m_nWidth  
= nWidth
; 
 237                 pEntry
->m_nHeight 
= nHeight
; 
 242         pNode 
= pNode
->Next(); 
 244     memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
 245     vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
 247     vBmpHdr
.cy        
= nHeight
; 
 249     vBmpHdr
.cBitCount 
= nDepth
; 
 251     WXHBITMAP                       hBitmap 
= (WXHBITMAP
) ::GpiCreateBitmap( hPS
 
 257         wxLogLastError(wxT("CreateCompatibleBitmap")); 
 259     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hBitmap
 
 264     AddToBitmapCache(pEntry
); 
 266 } // end of FindBitmapInCache 
 268 wxDCCacheEntry
* wxDC::FindDCInCache( 
 269   wxDCCacheEntry
*                   pNotThis
 
 273     int                             nDepth 
= 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL); 
 274     wxNode
*                         pNode 
= m_svDCCache
.First(); 
 278         wxDCCacheEntry
*             pEntry 
= (wxDCCacheEntry
*)pNode
->Data(); 
 281         // Don't return the same one as we already have 
 283         if (!pNotThis 
|| (pNotThis 
!= pEntry
)) 
 285             if (pEntry
->m_nDepth 
== nDepth
) 
 290         pNode 
= pNode
->Next(); 
 292     wxDCCacheEntry
*                 pEntry 
= new wxDCCacheEntry( hPS
 
 295     AddToDCCache(pEntry
); 
 297 } // end of wxDC::FindDCInCache 
 299 void wxDC::AddToBitmapCache( 
 300   wxDCCacheEntry
*                   pEntry
 
 303     m_svBitmapCache
.Append(pEntry
); 
 304 } // end of wxDC::AddToBitmapCache 
 306 void wxDC::AddToDCCache( 
 307   wxDCCacheEntry
*                   pEntry
 
 310     m_svDCCache
.Append(pEntry
); 
 311 } // end of wxDC::AddToDCCache 
 313 void wxDC::ClearCache() 
 315     m_svBitmapCache
.DeleteContents(TRUE
); 
 316     m_svBitmapCache
.Clear(); 
 317     m_svBitmapCache
.DeleteContents(FALSE
); 
 318     m_svDCCache
.DeleteContents(TRUE
); 
 320     m_svDCCache
.DeleteContents(FALSE
); 
 321 } // end of wxDC::ClearCache 
 323 // Clean up cache at app exit 
 324 class wxDCModule 
: public wxModule
 
 327     virtual bool OnInit() { return TRUE
; } 
 328     virtual void OnExit() { wxDC::ClearCache(); } 
 331     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
 332 }; // end of CLASS wxDCModule 
 334 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
 336 #endif // ndef for wxUSE_DC_CACHEING 
 338 // --------------------------------------------------------------------------- 
 340 // --------------------------------------------------------------------------- 
 358     m_bIsPaintTime 
= FALSE
; // True at Paint Time 
 360     vColor
.InitFromName("BLACK"); 
 361     m_pen
.SetColour(vColor
); 
 363     m_brush
.SetColour(vColor
); 
 364 } // end of wxDC::wxDC 
 370         SelectOldObjects(m_hDC
); 
 372         // if we own the HDC, we delete it, otherwise we just release it 
 378                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 379                 ::GpiDestroyPS(m_hPS
); 
 382             ::DevCloseDC((HDC
)m_hDC
); 
 387             // Just Dissacociate, not destroy if we don't own the DC 
 391                 ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 395 } // end of wxDC::~wxDC 
 397 // This will select current objects out of the DC, 
 398 // which is what you have to do before deleting the 
 400 void wxDC::SelectOldObjects( 
 408             ::GpiSetBitmap(hPS
, (HBITMAP
) m_hOldBitmap
); 
 409             if (m_vSelectedBitmap
.Ok()) 
 411                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 416         // OS/2 has no other native GDI objects to set in a PS/DC like windows 
 424     m_brush           
= wxNullBrush
; 
 426     m_palette         
= wxNullPalette
; 
 428     m_backgroundBrush 
= wxNullBrush
; 
 429     m_vSelectedBitmap 
= wxNullBitmap
; 
 430 } // end of wxDC::SelectOldObjects 
 432 // --------------------------------------------------------------------------- 
 434 // --------------------------------------------------------------------------- 
 436 #define DO_SET_CLIPPING_BOX()                    \ 
 440     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 442     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 443     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 444     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 445     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 448 void wxDC::DoSetClippingRegion( 
 457     vY 
= OS2Y(vY
,vHeight
); 
 460     vRect
.yTop    
= vY 
+ vHeight
; 
 461     vRect
.xRight  
= vX 
+ vWidth
; 
 463     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 464     DO_SET_CLIPPING_BOX() 
 465 } // end of wxDC::DoSetClippingRegion 
 467 void wxDC::DoSetClippingRegionAsRegion( 
 468   const wxRegion
&                   rRegion
 
 471      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 475      ::GpiSetClipRegion( m_hPS
 
 476                         ,(HRGN
)rRegion
.GetHRGN() 
 479     DO_SET_CLIPPING_BOX() 
 480 } // end of wxDC::DoSetClippingRegionAsRegion 
 482 void wxDC::DestroyClippingRegion(void) 
 484     if (m_clipping 
&& m_hPS
) 
 489          // TODO: this should restore the previous clipped region 
 490          //       so that OnPaint processing works correctly, and 
 491          //       the update doesn't get destroyed after the first 
 492          //       DestroyClippingRegion 
 493          vRect
.xLeft   
= XLOG2DEV(0); 
 494          vRect
.yTop    
= YLOG2DEV(32000); 
 495          vRect
.xRight  
= XLOG2DEV(32000); 
 496          vRect
.yBottom 
= YLOG2DEV(0); 
 498          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 500          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 503 } // end of wxDC::DestroyClippingRegion 
 505 // --------------------------------------------------------------------------- 
 506 // query capabilities 
 507 // --------------------------------------------------------------------------- 
 509 bool wxDC::CanDrawBitmap() const 
 514 bool wxDC::CanGetTextExtent() const 
 516     LONG                            lTechnology 
= 0L; 
 518     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY
, 1L, &lTechnology
); 
 519     return (lTechnology 
== CAPS_TECH_RASTER_DISPLAY
) || (lTechnology 
== CAPS_TECH_RASTER_PRINTER
); 
 520 } // end of wxDC::CanGetTextExtent 
 522 int wxDC::GetDepth() const 
 524     LONG                            lArray
[CAPS_COLOR_BITCOUNT
]; 
 527     if(::DevQueryCaps( GetHDC() 
 533         nBitsPerPixel 
= (int)lArray
[CAPS_COLOR_BITCOUNT
]; 
 535     return nBitsPerPixel
; 
 536 } // end of wxDC::GetDepth 
 538 // --------------------------------------------------------------------------- 
 540 // --------------------------------------------------------------------------- 
 545 } // end of wxDC::Clear 
 547 void wxDC::DoFloodFill( 
 550 , const wxColour
&                   rCol
 
 558     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 559     vPtlPos
.y 
= OS2Y(vY
,0);     // Loads y-coordinate 
 560     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 561     lColor 
= rCol
.GetPixel(); 
 562     lOptions 
= FF_BOUNDARY
; 
 563     if(wxFLOOD_SURFACE 
== nStyle
) 
 564         lOptions 
= FF_SURFACE
; 
 566     ::GpiFloodFill(m_hPS
, lOptions
, lColor
); 
 567 } // end of wxDC::DoFloodFill 
 569 bool wxDC::DoGetPixel( 
 579     vPoint
.y 
= OS2Y(vY
,0); 
 580     lColor 
= ::GpiSetPel(m_hPS
, &vPoint
); 
 583     // Get the color of the pen 
 585     LONG                            lPencolor 
= 0x00ffffff; 
 589         lPencolor 
= m_pen
.GetColour().GetPixel(); 
 593     // return the color of the pixel 
 596         pCol
->Set( GetRValue(lColor
) 
 600     return(lColor 
== lPencolor
); 
 601 } // end of wxDC::DoGetPixel 
 603 void wxDC::DoCrossHair( 
 610     wxCoord                         vX1 
= vX 
- VIEWPORT_EXTENT
; 
 611     wxCoord                         vY1 
= vY 
- VIEWPORT_EXTENT
; 
 612     wxCoord                         vX2 
= vX 
+ VIEWPORT_EXTENT
; 
 613     wxCoord                         vY2 
= vY 
+ VIEWPORT_EXTENT
; 
 622     ::GpiMove(m_hPS
, &vPoint
[0]); 
 623     ::GpiLine(m_hPS
, &vPoint
[1]); 
 631     ::GpiMove(m_hPS
, &vPoint
[2]); 
 632     ::GpiLine(m_hPS
, &vPoint
[3]); 
 633     CalcBoundingBox(vX1
, vY1
); 
 634     CalcBoundingBox(vX2
, vY2
); 
 635 } // end of wxDC::DoCrossHair 
 637 void wxDC::DoDrawLine( 
 653     ::GpiMove(m_hPS
, &vPoint
[0]); 
 654     ::GpiLine(m_hPS
, &vPoint
[1]); 
 655     CalcBoundingBox(vX1
, vY1
); 
 656     CalcBoundingBox(vX2
, vY2
); 
 657 } // end of wxDC::DoDrawLine 
 659 ////////////////////////////////////////////////////////////////////////////// 
 660 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 661 // and ending at (x2, y2). The current pen is used for the outline and the 
 662 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 663 // direction from the start point to the end point. 
 664 ////////////////////////////////////////////////////////////////////////////// 
 665 void wxDC::DoDrawArc( 
 675      POINTL                         vPtlArc
[2]; // Structure for current position 
 684      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 686     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 687         return; // Draw point ?? 
 688     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 691                       hypot( (double)(vY2 
- vYc
) 
 696     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 699     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 706     // GpiPointArc can't draw full arc 
 708      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 713         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 714         vXm      
= vXc 
+ dRadius 
* cos(dAnglmid
); 
 715         vYm      
= vYc 
+ dRadius 
* sin(dAnglmid
); 
 730     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 731     vXm      
= vXc 
+ dRadius 
* cos(dAnglmid
); 
 732     vYm      
= vYc 
+ dRadius 
* sin(dAnglmid
); 
 735     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 741     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 743     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 744     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 745     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 750     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 751     CalcBoundingBox( (vXc 
- dRadius
) 
 754     CalcBoundingBox( (vXc 
+ dRadius
) 
 757 } // end of wxDC::DoDrawArc 
 759 void wxDC::DoDrawCheckMark( 
 768     vY1 
= OS2Y(vY1
,vHeight
); 
 772     vPoint
[1].x 
= vX1 
+ vWidth
; 
 773     vPoint
[1].y 
= vY1 
+ vHeight
; 
 775     ::GpiMove(m_hPS
, &vPoint
[0]); 
 776     ::GpiBox( m_hPS       
// handle to a presentation space 
 777              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 778              ,&vPoint
[1]  // address of the corner 
 779              ,0L          // horizontal corner radius 
 780              ,0L          // vertical corner radius 
 782     if(vWidth 
> 4 && vHeight 
> 4) 
 786         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 787         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 788         ::GpiMove(m_hPS
, &vPoint
[0]); 
 789         ::GpiLine(m_hPS
, &vPoint
[1]); 
 791         vPoint
[0].x 
= vPoint
[1].x
; 
 793         ::GpiMove(m_hPS
, &vPoint
[0]); 
 794         ::GpiLine(m_hPS
, &vPoint
[1]); 
 800     wxCoord                         vX2 
= vX1 
+ vWidth
; 
 801     wxCoord                         vY2 
= vY1 
+ vHeight
; 
 806 } // end of wxDC::DoDrawCheckMark 
 808 void wxDC::DoDrawPoint( 
 814     COLORREF                        vColor 
= 0x00ffffff; 
 818         vColor 
= m_pen
.GetColour().GetPixel(); 
 820     ::GpiSetColor(m_hPS
, vColor
); 
 822     vPoint
.y 
= OS2Y(vY
,0); 
 823     ::GpiSetPel(m_hPS
, &vPoint
); 
 827 } // end of wxDC::DoDrawPoint 
 829 void wxDC::DoDrawPolygon( 
 837     ULONG                           ulCount 
= 1;    // Number of polygons. 
 838     POLYGON                         vPlgn
;          // polygon. 
 839     ULONG                           flOptions 
= 0L; // Drawing options. 
 841 ////////////////////////////////////////////////////////////////////////////// 
 842 // This contains fields of option bits... to draw boundary lines as well as 
 843 // the area interior. 
 845 // Drawing boundary lines: 
 846 //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 847 //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 849 // Construction of the area interior: 
 850 //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 852 //   POLYGON_WINDING                 Constructs interior in winding mode. 
 853 ////////////////////////////////////////////////////////////////////////////// 
 855     ULONG                           flModel 
= 0L; // Drawing model. 
 857 ////////////////////////////////////////////////////////////////////////////// 
 859 //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 860 //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 861 //       This is provided to aid migration from other graphics models. 
 862 ////////////////////////////////////////////////////////////////////////////// 
 864     LONG                            lHits 
= 0L; // Correlation/error indicator. 
 867     int                             nIsTRANSPARENT 
= 0; 
 868     LONG                            lBorderColor 
= 0L; 
 871     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 872     lColor       
= m_brush
.GetColour().GetPixel(); 
 873     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 877     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 879                                     ); // well, new will call malloc 
 881     for(i 
= 0; i 
< n
; i
++) 
 883         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
;         // +xoffset; 
 884         vPlgn
.aPointl
[i
].y 
= OS2Y(vPoints
[i
].y
,0); // +yoffset; 
 886     flModel 
= POLYGON_BOUNDARY
; 
 887     if(nFillStyle 
== wxWINDING_RULE
) 
 888         flModel 
|= POLYGON_WINDING
; 
 890         flModel 
|= POLYGON_ALTERNATE
; 
 893     vPoint
.y 
= OS2Y(vYoffset
,0); 
 895     ::GpiSetColor(m_hPS
, lBorderColor
); 
 896     ::GpiMove(m_hPS
, &vPoint
); 
 897     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 899 } // end of wxDC::DoDrawPolygon 
 901 void wxDC::DoDrawLines( 
 910     if (vXoffset 
!= 0L || vXoffset 
!= 0L) 
 914         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 915         vPoint
.y 
= OS2Y(vPoints
[0].y 
+ vYoffset
,0); 
 916         ::GpiMove(m_hPS
, &vPoint
); 
 918         LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 920         ::GpiSetColor(m_hPS
, lBorderColor
); 
 921         for(i 
= 1; i 
< n
; i
++) 
 923             vPoint
.x 
= vPoints
[i
].x 
+ vXoffset
; 
 924             vPoint
.y 
= OS2Y(vPoints
[i
].y 
+ vYoffset
,0); 
 925             ::GpiLine(m_hPS
, &vPoint
); 
 932         CalcBoundingBox( vPoints
[i
].x
 
 935         vPoint
.x 
= vPoints
[0].x
; 
 936         vPoint
.y 
= OS2Y(vPoints
[0].y
,0); 
 937         ::GpiMove(m_hPS
, &vPoint
); 
 939         for (i 
= 0; i 
< n
; i
++) 
 941             CalcBoundingBox( vPoints
[i
].x
 
 944             vPoint
.x 
= vPoints
[i
].x
; 
 945             vPoint
.y 
= OS2Y(vPoints
[i
].y
,0); 
 946             ::GpiLine(m_hPS
, &vPoint
); 
 949 } // end of wxDC::DoDrawLines 
 951 void wxDC::DoDrawRectangle( 
 962     int                             nIsTRANSPARENT 
= 0; 
 964     vY 
= OS2Y(vY
,vHeight
); 
 966     wxCoord                         vX2 
= vX 
+ vWidth
; 
 967     wxCoord                         vY2 
= vY 
+ vHeight
; 
 971     vPoint
[1].x 
= vX 
+ vWidth
; 
 972     vPoint
[1].y 
= vY 
+ vHeight
; 
 973     ::GpiMove(m_hPS
, &vPoint
[0]); 
 974     lColor       
= m_brush
.GetColour().GetPixel(); 
 975     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 976     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
 978     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
 980         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
 981         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 982             lControl 
= DRO_OUTLINE
; 
 984         ::GpiSetColor(m_hPS
, lColor
); 
 985         ::GpiBox( m_hPS       
// handle to a presentation space 
 986                  ,lControl   
// draw the box outline ? or ? 
 987                  ,&vPoint
[1]  // address of the corner 
 988                  ,0L          // horizontal corner radius 
 989                  ,0L          // vertical corner radius 
 994         lControl 
= DRO_OUTLINE
; 
1004         lControl 
= DRO_FILL
; 
1005         ::GpiSetColor( m_hPS
 
1008         vPoint
[0].x 
= vX 
+ 1; 
1009         vPoint
[0].y 
= vY 
+ 1; 
1010         vPoint
[1].x 
= vX 
+ vWidth 
- 1; 
1011         vPoint
[1].y 
= vY 
+ vHeight 
- 1; 
1012         ::GpiMove(m_hPS
, &vPoint
[0]); 
1020     CalcBoundingBox(vX
, vY
); 
1021     CalcBoundingBox(vX2
, vY2
); 
1022 } // end of wxDC::DoDrawRectangle 
1024 void wxDC::DoDrawRoundedRectangle( 
1035     vY 
= OS2Y(vY
,vHeight
); 
1037     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1038     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1041     vPoint
[0].y 
= YLOG2DEV(vY
) - vHeight
; 
1042     vPoint
[1].x 
= vX 
+ vWidth
; 
1044     ::GpiMove(m_hPS
, &vPoint
[0]); 
1046     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
1047     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
1048         lControl 
= DRO_OUTLINE
; 
1049     ::GpiBox( m_hPS         
// handle to a presentation space 
1050              ,DRO_OUTLINE   
// draw the box outline ? or ? 
1051              ,&vPoint
[1]    // address of the corner 
1052              ,(LONG
)dRadius 
// horizontal corner radius 
1053              ,(LONG
)dRadius 
// vertical corner radius 
1055     CalcBoundingBox(vX
, vY
); 
1056     CalcBoundingBox(vX2
, vY2
); 
1057 } // end of wxDC::DoDrawRoundedRectangle 
1059 // Draw Ellipse within box (x,y) - (x+width, y+height) 
1060 void wxDC::DoDrawEllipse( 
1067     POINTL                          vPtlPos
; // Structure for current position 
1068     FIXED                           vFxMult
; // Multiplier for ellipse 
1069     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1071     vY 
= OS2Y(vY
,vHeight
); 
1074     vArcp
.lQ 
= vHeight
/2; 
1075     vArcp
.lP 
= vWidth
/2; 
1077     ::GpiSetArcParams( m_hPS
 
1079                      ); // Sets parameters to default 
1080     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
1081     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1084              ); // Sets current position 
1085     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
1088     // DRO_FILL, DRO_OTLINEFILL - where to get 
1093                 ); // Draws full arc with center at current position 
1095     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1096     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1098     CalcBoundingBox(vX
, vY
); 
1099     CalcBoundingBox(vX2
, vY2
); 
1100 } // end of wxDC::DoDrawEllipse 
1102 void wxDC::DoDrawEllipticArc( 
1111     POINTL                          vPtlPos
; // Structure for current position 
1112     FIXED                           vFxMult
; // Multiplier for ellipse 
1113     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
1115     FIXED                           vFSweepa
; // Start angle, sweep angle 
1120     vY 
= OS2Y(vY
,vHeight
); 
1122     dFractPart 
= modf(dSa
,&dIntPart
); 
1123     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1124     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
1125     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
1128     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
1131     vArcp
.lQ 
= vHeight
/2; 
1132     vArcp
.lP 
= vWidth
/2; 
1134     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
1135     vPtlPos
.x 
= vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate 
1136     vPtlPos
.y 
= vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate 
1137     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
1140     // May be not to the center ? 
1142     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
1143     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
1144     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
1147     // DRO_FILL, DRO_OTLINEFILL - where to get 
1149     ::GpiPartialArc( m_hPS
 
1155     wxCoord                         vX2 
= (vX 
+ vWidth
); 
1156     wxCoord                         vY2 
= (vY 
+ vHeight
); 
1158     CalcBoundingBox(vX
, vY
); 
1159     CalcBoundingBox(vX2
, vY2
); 
1160 } // end of wxDC::DoDrawEllipticArc 
1162 void wxDC::DoDrawIcon( 
1168     vY 
= OS2Y(vY
,rIcon
.GetHeight()); 
1169     wxCHECK_RET( rIcon
.Ok(), wxT("invalid icon in DrawIcon") ); 
1171     ::WinDrawPointer( GetHPS() 
1174                      ,(HPOINTER
)GetHiconOf(rIcon
) 
1177     CalcBoundingBox(vX
, vY
); 
1178     CalcBoundingBox(vX 
+ rIcon
.GetWidth(), vY 
+ rIcon
.GetHeight()); 
1179 } // end of wxDC::DoDrawIcon 
1181 void wxDC::DoDrawBitmap( 
1182   const wxBitmap
&                   rBmp
 
1188     POINTL                          vPoint 
= {vX
, vY
}; 
1190     ::WinDrawBitmap( GetHPS() 
1191                     ,(HBITMAP
)GetHbitmapOf(rBmp
) 
1198 } // end of wxDC::DoDrawBitmap 
1200 void wxDC::DoDrawText( 
1201   const wxString
&                   rsText
 
1214     CalcBoundingBox(vX
, vY
); 
1215     GetTextExtent(rsText
, &vWidth
, &vHeight
); 
1216     CalcBoundingBox((vX 
+ vWidth
), (vY 
+ vHeight
)); 
1217 } // end of wxDC::DoDrawText 
1219 void wxDC::DrawAnyText( 
1220   const wxString
&                   rsText
 
1225     int                             nOldBackground 
= 0; 
1232     // prepare for drawing the text 
1236     // Set text color attributes 
1238     if (m_textForegroundColour
.Ok()) 
1241                      ,(int)m_textForegroundColour
.GetPixel() 
1245     if (m_textBackgroundColour
.Ok()) 
1247         nOldBackground 
= SetTextBkColor( m_hPS
 
1248                                         ,(int)m_textBackgroundColour
.GetPixel() 
1254     GetTextExtent( rsText
 
1259     vPtlStart
.y 
= OS2Y(vY
,vTextY
); 
1261     lHits 
= ::GpiCharStringAt( m_hPS
 
1264                               ,(PCH
)rsText
.c_str() 
1266     if (lHits 
!= GPI_OK
) 
1268         wxLogLastError(wxT("TextOut")); 
1272     // Restore the old parameters (text foreground colour may be left because 
1273     // it never is set to anything else, but background should remain 
1274     // transparent even if we just drew an opaque string) 
1276     if (m_textBackgroundColour
.Ok()) 
1277             SetTextBkColor( m_hPS
 
1285 void wxDC::DoDrawRotatedText( 
1286   const wxString
&                   rsText
 
1304         DoDrawText(text, x, y); 
1309         wxFillLogFont(&lf, &m_font); 
1311         // GDI wants the angle in tenth of degree 
1312         long angle10 = (long)(angle * 10); 
1313         lf.lfEscapement = angle10; 
1314         lf. lfOrientation = angle10; 
1316         HFONT hfont = ::CreateFontIndirect(&lf); 
1319             wxLogLastError("CreateFont"); 
1323             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
1325             DrawAnyText(text, x, y); 
1327             (void)::SelectObject(GetHdc(), hfontOld); 
1330         // call the bounding box by adding all four vertices of the rectangle 
1331         // containing the text to it (simpler and probably not slower than 
1332         // determining which of them is really topmost/leftmost/...) 
1334         GetTextExtent(text, &w, &h); 
1336         double rad = DegToRad(angle); 
1338         // "upper left" and "upper right" 
1339         CalcBoundingBox(x, y); 
1340         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
1341         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1343         // "bottom left" and "bottom right" 
1344         x += (wxCoord)(h*sin(rad)); 
1345         y += (wxCoord)(h*cos(rad)); 
1346         CalcBoundingBox(x, y); 
1347         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
1352 // --------------------------------------------------------------------------- 
1354 // --------------------------------------------------------------------------- 
1356 void wxDC::SetPalette( 
1357   const wxPalette
&                  rPalette
 
1364     m_palette 
= rPalette
; 
1372     HPALETTE                    hOldPal 
= ::GpiSelectPalette((HDC
) m_hPS
, (HPALETTE
) m_palette
.GetHPALETTE()); 
1374         m_hOldPalette 
= (WXHPALETTE
)hOldPal
; 
1375 } // end of wxDC::SetPalette 
1382     // Set the old object temporarily, in case the assignment deletes an object 
1383     // that's not yet selected out. 
1395     m_font
.SetPS(m_hPS
); // this will realize the font 
1399         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
1400         if (hFont 
== (HFONT
) NULL
) 
1402             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
1405             m_hOldFont 
= (WXHFONT
) hFont
; 
1407 } // end of wxDC::SetFont 
1413     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1429             m_pen
.SetPS((HPS
)m_hOldPen
); 
1436         if (m_pen
.GetResourceHandle()) 
1440                 m_hOldPen 
= m_pen
.GetPS(); 
1445 void wxDC::SetBrush( 
1446   const wxBrush
&                    rBrush
 
1449     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1455     if (m_brush 
== rBrush
) 
1465             m_brush
.SetPS((HPS
)m_hOldBrush
); 
1472         if (m_brush
.GetResourceHandle()) 
1474             m_brush
.SetPS(m_hPS
); 
1476                 m_hOldBrush 
= (WXHWND
)m_brush
.GetPS(); 
1479 } // end of wxDC::SetBrush 
1481 void wxDC::SetBackground( 
1482   const wxBrush
&                    rBrush
 
1485     m_backgroundBrush 
= rBrush
; 
1486     if (!m_backgroundBrush
.Ok()) 
1490         bool                        bCustomColours 
= TRUE
; 
1493         // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to 
1494         // change background colours from the control-panel specified colours. 
1496         if (m_pCanvas
->IsKindOf(CLASSINFO(wxWindow
)) && 
1497             ((m_pCanvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
)) 
1498             bCustomColours 
= FALSE
; 
1501             if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
) 
1503                 m_pCanvas
->SetTransparent(TRUE
); 
1508                 // Setting the background brush of a DC 
1509                 // doesn't affect the window background colour. However, 
1510                 // I'm leaving in the transparency setting because it's needed by 
1511                 // various controls (e.g. wxStaticText) to determine whether to draw 
1512                 // transparently or not. TODO: maybe this should be a new function 
1513                 // wxWindow::SetTransparency(). Should that apply to the child itself, or the 
1515                 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour()); 
1517                 m_pCanvas
->SetTransparent(FALSE
); 
1521     COLORREF                        vNewColor 
= m_backgroundBrush
.GetColour().GetPixel(); 
1522     (void)::GpiSetBackColor((HPS
)m_hPS
, (LONG
)vNewColor
); 
1523 } // end of wxDC::SetBackground 
1525 void wxDC::SetBackgroundMode( 
1529     m_backgroundMode 
= nMode
; 
1530 } // end of wxDC::SetBackgroundMode 
1532 void wxDC::SetLogicalFunction( 
1536     m_logicalFunction 
= nFunction
; 
1537     SetRop((WXHDC
)m_hDC
); 
1538 } // wxDC::SetLogicalFunction 
1544     if (!hDC 
|| m_logicalFunction 
< 0) 
1548     switch (m_logicalFunction
) 
1559             lCRop 
= FM_MERGESRCNOT
; 
1563             lCRop 
= FM_NOTMASKSRC
; 
1575             lCRop 
= FM_MERGENOTSRC
; 
1579             lCRop 
= FM_MERGESRCNOT
; 
1591             lCRop 
= FM_SUBTRACT
; 
1598             lCRop 
= FM_OVERPAINT
; 
1601     ::GpiSetMix((HPS
)hDC
, lCRop
); 
1602 } // end of wxDC::SetRop 
1604 bool wxDC::StartDoc( 
1605   const wxString
&                   rsMessage
 
1608     // We might be previewing, so return TRUE to let it continue. 
1610 } // end of wxDC::StartDoc 
1614 } // end of wxDC::EndDoc 
1616 void wxDC::StartPage() 
1618 } // end of wxDC::StartPage 
1620 void wxDC::EndPage() 
1622 } // end of wxDC::EndPage 
1624 // --------------------------------------------------------------------------- 
1626 // --------------------------------------------------------------------------- 
1628 wxCoord 
wxDC::GetCharHeight() const 
1630     FONTMETRICS                     vFM
; // metrics structure 
1632     ::GpiQueryFontMetrics( m_hPS
 
1633                           ,sizeof(FONTMETRICS
) 
1636     return YDEV2LOGREL(vFM
.lXHeight
); 
1639 wxCoord 
wxDC::GetCharWidth() const 
1641     FONTMETRICS                     vFM
; // metrics structure 
1643     ::GpiQueryFontMetrics( m_hPS
 
1644                           ,sizeof(FONTMETRICS
) 
1647     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
1650 void wxDC::DoGetTextExtent( 
1651   const wxString
&                   rsString
 
1654 , wxCoord
*                          pvDescent
 
1655 , wxCoord
*                          pvExternalLeading
 
1659     POINTL                          avPoint
[TXTBOX_COUNT
]; 
1664     FONTMETRICS                     vFM
; // metrics structure 
1667     ERRORID                         vErrorCode
; // last error id code 
1668     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
1670     char                            zMsg
[128]; // DEBUG 
1674         pFontToUse 
= (wxFont
*)&m_font
; 
1675     l 
= rsString
.length(); 
1676     pStr 
= (PCH
) rsString
.c_str(); 
1679     // In world coordinates. 
1681     bRc 
= ::GpiQueryTextBox( m_hPS
 
1684                             ,TXTBOX_COUNT 
// return maximum information 
1685                             ,avPoint      
// array of coordinates points 
1689        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
1690        sError 
= wxPMErrorToStr(vErrorCode
); 
1692        sprintf(zMsg
, "GpiQueryTextBox for %s: failed with Error: %x - %s", pStr
, vErrorCode
, sError
.c_str()); 
1693        (void)wxMessageBox( "wxWindows Menu sample" 
1699     vPtMin
.x 
= avPoint
[0].x
; 
1700     vPtMax
.x 
= avPoint
[0].x
; 
1701     vPtMin
.y 
= avPoint
[0].y
; 
1702     vPtMax
.y 
= avPoint
[0].y
; 
1703     for (i 
= 1; i 
< 4; i
++) 
1705         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
1706         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
1707         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
1708         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
1710     ::GpiQueryFontMetrics( m_hPS
 
1711                           ,sizeof(FONTMETRICS
) 
1716         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
1718         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
1720         *pvDescent 
= vFM
.lMaxDescender
; 
1721     if (pvExternalLeading
) 
1722         *pvExternalLeading 
= vFM
.lExternalLeading
; 
1725 void wxDC::SetMapMode( 
1729     int                             nPixelWidth 
= 0; 
1730     int                             nPixelHeight 
= 0; 
1733     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
1735     m_mappingMode 
= nMode
; 
1737     if(::DevQueryCaps( m_hDC
 
1739                       ,CAPS_VERTICAL_RESOLUTION
 
1746         nPixelWidth    
= lArray
[CAPS_WIDTH
]; 
1747         nPixelHeight   
= lArray
[CAPS_HEIGHT
]; 
1748         lHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
1749         lVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
1750         nMmWidth  
= (lHorzRes
/1000) * nPixelWidth
; 
1751         nMmWidth 
= (lVertRes
/1000) * nPixelHeight
; 
1753     if ((nPixelWidth 
== 0) || (nPixelHeight 
== 0) || (nMmWidth 
== 0) || (nMmHeight 
== 0)) 
1758     double                          dMm2pixelsX 
= nPixelWidth
/nMmWidth
; 
1759     double                          dMm2pixelsY 
= nPixelHeight
/nMmHeight
; 
1764             m_logicalScaleX 
= (twips2mm 
* dMm2pixelsX
); 
1765             m_logicalScaleY 
= (twips2mm 
* dMm2pixelsY
); 
1769             m_logicalScaleX 
= (pt2mm 
* dMm2pixelsX
); 
1770             m_logicalScaleY 
= (pt2mm 
* dMm2pixelsY
); 
1774             m_logicalScaleX 
= dMm2pixelsX
; 
1775             m_logicalScaleY 
= dMm2pixelsY
; 
1779             m_logicalScaleX 
= (dMm2pixelsX
/10.0); 
1780             m_logicalScaleY 
= (dMm2pixelsY
/10.0); 
1785             m_logicalScaleX 
= 1.0; 
1786             m_logicalScaleY 
= 1.0; 
1792     ulOptions 
= ::GpiQueryPS(m_hPS
, &vSize
); 
1793     if (!ulOptions 
& PU_ARBITRARY
) 
1795         ulOptions 
= PU_ARBITRARY 
| GPIF_DEFAULT
; 
1796         ::GpiSetPS(m_hPS
, &vSize
, ulOptions
); 
1798     m_nWindowExtX 
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
); 
1799     m_nWindowExtY 
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
); 
1801 }; // end of wxDC::SetMapMode 
1803 void wxDC::SetUserScale( 
1811     SetMapMode(m_mappingMode
); 
1812 } // end of wxDC::SetUserScale 
1814 void wxDC::SetAxisOrientation( 
1819     m_signX 
= bXLeftRight 
? 1 : -1; 
1820     m_signY 
= bYBottomUp 
? -1 : 1; 
1822     SetMapMode(m_mappingMode
); 
1823 } // end of wxDC::SetAxisOrientation 
1825 void wxDC::SetSystemScale( 
1833     SetMapMode(m_mappingMode
); 
1834 } // end of wxDC::SetSystemScale 
1836 void wxDC::SetLogicalOrigin( 
1843     ::GpiQueryPageViewport( m_hPS
 
1850     ::GpiSetPageViewport( m_hPS
 
1853 }; // end of wxDC::SetLogicalOrigin 
1855 void wxDC::SetDeviceOrigin( 
1862     m_deviceOriginX 
= vX
; 
1863     m_deviceOriginY 
= vY
; 
1864     ::GpiQueryPageViewport( m_hPS
 
1869     vRect
.yBottom 
-= vY
; 
1871     ::GpiSetPageViewport( m_hPS
 
1874 }; // end of wxDC::SetDeviceOrigin 
1876 // --------------------------------------------------------------------------- 
1877 // coordinates transformations 
1878 // --------------------------------------------------------------------------- 
1880 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
1882     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
1885 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
1887     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
)); 
1890 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
1892     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
1895 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
1897     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
)); 
1900 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
1902     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
1905 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
1907     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
); 
1910 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
1912     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
1915 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
1917     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
); 
1920 // --------------------------------------------------------------------------- 
1922 // --------------------------------------------------------------------------- 
1938     wxMask
*                         pMask 
= NULL
; 
1940     COLORREF                        vOldTextColor
; 
1941     COLORREF                        vOldBackground 
= ::GpiQueryBackColor(m_hPS
); 
1945         const wxBitmap
&             rBmp 
= pSource
->m_vSelectedBitmap
; 
1947         pMask 
= rBmp
.GetMask(); 
1948         if (!(rBmp
.Ok() && pMask 
&& pMask
->GetMaskBitmap())) 
1954     ::GpiQueryAttrs( m_hPS
 
1959     vOldTextColor 
= (COLORREF
)vCbnd
.lColor
; 
1961     if (m_textForegroundColour
.Ok()) 
1963         vCbnd
.lColor 
= (LONG
)m_textForegroundColour
.GetPixel(); 
1964         ::GpiSetAttrs( m_hPS           
// presentation-space handle 
1965                       ,PRIM_CHAR       
// Char primitive. 
1966                       ,CBB_COLOR       
// sets color. 
1968                       ,&vCbnd          
// buffer for attributes. 
1971     if (m_textBackgroundColour
.Ok()) 
1973         ::GpiSetBackColor(m_hPS
, (LONG
)m_textBackgroundColour
.GetPixel()); 
1976     LONG                            lRop 
= ROP_SRCCOPY
; 
1980         case wxXOR
:          lRop 
= ROP_SRCINVERT
;        break; 
1981         case wxINVERT
:       lRop 
= ROP_DSTINVERT
;        break; 
1982         case wxOR_REVERSE
:   lRop 
= 0x00DD0228;           break; 
1983         case wxAND_REVERSE
:  lRop 
= ROP_SRCERASE
;         break; 
1984         case wxCLEAR
:        lRop 
= ROP_ZERO
;             break; 
1985         case wxSET
:          lRop 
= ROP_ONE
;              break; 
1986         case wxOR_INVERT
:    lRop 
= ROP_MERGEPAINT
;       break; 
1987         case wxAND
:          lRop 
= ROP_SRCAND
;           break; 
1988         case wxOR
:           lRop 
= ROP_SRCPAINT
;         break; 
1989         case wxEQUIV
:        lRop 
= 0x00990066;           break; 
1990         case wxNAND
:         lRop 
= 0x007700E6;           break; 
1991         case wxAND_INVERT
:   lRop 
= 0x00220326;           break; 
1992         case wxCOPY
:         lRop 
= ROP_SRCCOPY
;          break; 
1993         case wxNO_OP
:        lRop 
= ROP_NOTSRCERASE
;      break; 
1994         case wxSRC_INVERT
:   lRop 
= ROP_SRCINVERT
;        break; 
1995         case wxNOR
:          lRop 
= ROP_NOTSRCCOPY
;       break; 
1997            wxFAIL_MSG( wxT("unsupported logical function") ); 
2006         // Blit bitmap with mask 
2010         // Create a temp buffer bitmap and DCs/PSs to access it and the mask 
2016         DEVOPENSTRUC                    vDOP 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
2017         BITMAPINFOHEADER2               vBmpHdr
; 
2019         SIZEL                           vSize 
= {0, 0}; 
2022         memset(&vBmpHdr
, 0, sizeof(BITMAPINFOHEADER2
)); 
2023         vBmpHdr
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
2024         vBmpHdr
.cx        
= vWidth
; 
2025         vBmpHdr
.cy        
= vHeight
; 
2026         vBmpHdr
.cPlanes   
= 1; 
2027         vBmpHdr
.cBitCount 
= 24; 
2029 #if wxUSE_DC_CACHEING 
2033             // create a temp buffer bitmap and DCs to access it and the mask 
2035             wxDCCacheEntry
*         pDCCacheEntry1    
= FindDCInCache( NULL
 
2038             wxDCCacheEntry
*         pDCCacheEntry2    
= FindDCInCache( pDCCacheEntry1
 
2041             wxDCCacheEntry
*         pBitmapCacheEntry 
= FindBitmapInCache( GetHPS() 
2046             hPSMask 
= pDCCacheEntry1
->m_hPS
; 
2047             hDCBuffer 
= (HDC
)pDCCacheEntry2
->m_hPS
; 
2048             hBufBitmap 
= (HBITMAP
)pBitmapCacheEntry
->m_hBitmap
; 
2053             hDCMask 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2054             hDCBuffer 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDOP
, NULLHANDLE
); 
2055             hPSMask 
= ::GpiCreatePS(vHabmain
, hDCMask
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2056             hPSBuffer 
= ::GpiCreatePS(vHabmain
, hDCBuffer
, &vSize
, PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
); 
2057             hBufBitmap 
= ::GpiCreateBitmap(GetHPS(), &vBmpHdr
, 0L, NULL
, NULL
); 
2060         POINTL                          aPoint1
[4] = { 0, 0 
2063                                                       ,vXdest 
+ vWidth
, vYdest 
+ vHeight
 
2065         POINTL                          aPoint2
[4] = { 0, 0 
2068                                                       ,vXsrc 
+ vWidth
, vYsrc 
+ vHeight
 
2070         POINTL                          aPoint3
[4] = { vXdest
, vYdest
 
2071                                                       ,vXdest 
+ vWidth
, vYdest 
+ vHeight
 
2073                                                       ,vXsrc 
+ vWidth
, vYsrc 
+ vHeight
 
2075         POINTL                          aPoint4
[4] = { vXdest
, vYdest
 
2076                                                       ,vXdest 
+ vWidth
, vYdest 
+ vHeight
 
2080         ::GpiSetBitmap(hPSMask
, (HBITMAP
) pMask
->GetMaskBitmap()); 
2081         ::GpiSetBitmap(hPSBuffer
, (HBITMAP
) hBufBitmap
); 
2084         // Copy dest to buffer 
2086         rc 
= ::GpiBitBlt( hPSBuffer
 
2093         if (rc 
== GPI_ERROR
) 
2095             wxLogLastError(wxT("BitBlt")); 
2099         // Copy src to buffer using selected raster op 
2101         rc 
= ::GpiBitBlt( hPSBuffer
 
2108         if (rc 
== GPI_ERROR
) 
2110             wxLogLastError(wxT("BitBlt")); 
2114         // Set masked area in buffer to BLACK (pixel value 0) 
2116         COLORREF                        vPrevBkCol 
= ::GpiQueryBackColor(GetHPS()); 
2117         COLORREF                        vPrevCol 
= ::GpiQueryColor(GetHPS()); 
2119         ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255)); 
2120         ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0)); 
2122         rc 
= ::GpiBitBlt( hPSBuffer
 
2129         if (rc 
== GPI_ERROR
) 
2131             wxLogLastError(wxT("BitBlt")); 
2135         // Set unmasked area in dest to BLACK 
2137         ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0)); 
2138         ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255)); 
2139         rc 
= ::GpiBitBlt( GetHPS() 
2146         if (rc 
== GPI_ERROR
) 
2148             wxLogLastError(wxT("BitBlt")); 
2152         // Restore colours to original values 
2154         ::GpiSetBackColor(GetHPS(), vPrevBkCol
); 
2155         ::GpiSetColor(GetHPS(), vPrevCol
); 
2158         // OR buffer to dest 
2160         rc 
= ::GpiBitBlt( GetHPS() 
2167         if (rc 
== GPI_ERROR
) 
2170             wxLogLastError(wxT("BitBlt")); 
2174         // Tidy up temporary DCs and bitmap 
2176         ::GpiSetBitmap(hPSMask
, NULLHANDLE
); 
2177         ::GpiSetBitmap(hPSBuffer
, NULLHANDLE
); 
2178 #if !wxUSE_DC_CACHEING 
2179         ::GpiDestroyPS(hPSMask
); 
2180         ::GpiDestroyPS(hPSBuffer
); 
2181         ::DevCloseDC(hDCMask
); 
2182         ::DevCloseDC(hDCBuffer
); 
2183         ::GpiDeleteBitmap(hBufBitmap
); 
2187     else // no mask, just BitBlt() it 
2189         POINTL                          aPoint
[4] = { vXdest
, vYdest
 
2190                                                      ,vXdest 
+ vWidth
, vYdest 
+ vHeight
 
2192                                                      ,vXsrc 
+ vWidth
, vYsrc 
+ vHeight
 
2195         bSuccess 
= (::GpiBitBlt( m_hPS
 
2204             wxLogLastError(wxT("BitBlt")); 
2207     vCbnd
.lColor 
= (LONG
)vOldTextColor
; 
2208     ::GpiSetAttrs( m_hPS           
// presentation-space handle 
2209                   ,PRIM_CHAR       
// Char primitive. 
2210                   ,CBB_COLOR       
// sets color. 
2212                   ,&vCbnd          
// buffer for attributes. 
2214     ::GpiSetBackColor(m_hPS
, (LONG
)vOldBackground
); 
2218 void wxDC::DoGetSize( 
2223     LONG                            lArray
[CAPS_HEIGHT
]; 
2225     if(::DevQueryCaps( m_hDC
 
2231         *pnWidth  
= lArray
[CAPS_WIDTH
]; 
2232         *pnHeight 
= lArray
[CAPS_HEIGHT
]; 
2234 }; // end of wxDC::DoGetSize( 
2236 void wxDC::DoGetSizeMM( 
2241     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2243     if(::DevQueryCaps( m_hDC
 
2245                       ,CAPS_VERTICAL_RESOLUTION
 
2254         nWidth    
= lArray
[CAPS_WIDTH
]; 
2255         nHeight   
= lArray
[CAPS_HEIGHT
]; 
2256         nHorzRes  
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2257         nVertRes  
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2258         nWidth  
= (nHorzRes
/1000) * nWidth
; 
2259         nHeight 
= (nVertRes
/1000) * nHeight
; 
2261 }; // end of wxDC::DoGetSizeMM 
2263 wxSize 
wxDC::GetPPI() const 
2265     LONG                            lArray
[CAPS_VERTICAL_RESOLUTION
]; 
2269     if(::DevQueryCaps( m_hDC
 
2271                       ,CAPS_VERTICAL_RESOLUTION
 
2280         nPelWidth  
= lArray
[CAPS_WIDTH
]; 
2281         nPelHeight 
= lArray
[CAPS_HEIGHT
]; 
2282         nHorzRes   
= lArray
[CAPS_HORIZONTAL_RESOLUTION
]; // returns pel/meter 
2283         nVertRes   
= lArray
[CAPS_VERTICAL_RESOLUTION
];   // returns pel/meter 
2284         nWidth   
= (nHorzRes
/39.3) * nPelWidth
; 
2285         nHeight  
= (nVertRes
/39.3) * nPelHeight
; 
2287     return (wxSize(nWidth
,nHeight
)); 
2288 } // end of wxDC::GetPPI 
2290 void wxDC::SetLogicalScale( 
2295     m_logicalScaleX 
= dX
; 
2296     m_logicalScaleY 
= dY
; 
2297 }; // end of wxDC::SetLogicalScale 
2299 #if WXWIN_COMPATIBILITY 
2300 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
, 
2301                          float *descent
, float *externalLeading
, 
2302                          wxFont 
*theFont
, bool use16bit
) const 
2304     wxCoord x1
, y1
, descent1
, externalLeading1
; 
2305     GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
); 
2308         *descent 
= descent1
; 
2309     if (externalLeading
) 
2310         *externalLeading 
= externalLeading1
;