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" 
  27 #include "wx/dcprint.h" 
  32 #include "wx/os2/private.h" 
  34     IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
) 
  36 // --------------------------------------------------------------------------- 
  38 // --------------------------------------------------------------------------- 
  40 static const int VIEWPORT_EXTENT 
= 1000; 
  42 static const int MM_POINTS 
= 9; 
  43 static const int MM_METRIC 
= 10; 
  45 // usually this is defined in math.h 
  47     static const double M_PI 
= 3.14159265358979323846; 
  50 // --------------------------------------------------------------------------- 
  52 // --------------------------------------------------------------------------- 
  54 // convert degrees to radians 
  55 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  59 , int                               nForegroundColour
 
  64     vCbnd
.lColor 
=  nForegroundColour
; 
  65     ::GpiSetAttrs( hPS       
// presentation-space handle 
  66                   ,PRIM_CHAR 
// Char primitive. 
  67                   ,CBB_COLOR 
// sets color. 
  69                   ,&vCbnd    
// buffer for attributes. 
  80     ::GpiQueryAttrs( hPS            
// presentation-space handle 
  81                     ,PRIM_CHAR      
// Char primitive. 
  82                     ,CBB_BACK_COLOR 
// Background color. 
  83                     ,&vCbnd         
// buffer for attributes. 
  85     return vCbnd
.lBackColor
; 
  91 , int                               nBackgroundColour
 
  97     rc 
=  QueryTextBkColor(hPS
); 
  99     vCbnd
.lBackColor 
= nBackgroundColour
; 
 100     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 101                   PRIM_CHAR
,      // Char primitive. 
 102                   CBB_BACK_COLOR
, // sets color. 
 104                   &vCbnd          
// buffer for attributes. 
 111 , int                               nBackgroundMode
 
 114     if(nBackgroundMode 
== wxTRANSPARENT
) 
 119         // the background of the primitive takes  over whatever is underneath. 
 126 // =========================================================================== 
 128 // =========================================================================== 
 130 // --------------------------------------------------------------------------- 
 132 // --------------------------------------------------------------------------- 
 149     m_bIsPaintTime 
= FALSE
; // True at Paint Time 
 156 // This will select current objects out of the DC, 
 157 // which is what you have to do before deleting the 
 159 void wxDC::SelectOldObjects(WXHDC dc
) 
 165 //            ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap); 
 166             if (m_vSelectedBitmap
.Ok()) 
 168                 m_vSelectedBitmap
.SetSelectedInto(NULL
); 
 174 //            ::SelectObject((HDC) dc, (HPEN) m_oldPen); 
 179 //            ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush); 
 184 //            ::SelectObject((HDC) dc, (HFONT) m_oldFont); 
 189 //            ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE); 
 194     m_brush           
= wxNullBrush
; 
 196     m_palette         
= wxNullPalette
; 
 198     m_backgroundBrush 
= wxNullBrush
; 
 199     m_vSelectedBitmap 
= wxNullBitmap
; 
 202 // --------------------------------------------------------------------------- 
 204 // --------------------------------------------------------------------------- 
 206 #define DO_SET_CLIPPING_BOX()                    \ 
 210     ::GpiQueryClipBox(m_hPS, &rect);             \ 
 212     m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft);   \ 
 213     m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop);    \ 
 214     m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight);  \ 
 215     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \ 
 218 void wxDC::DoSetClippingRegion( 
 228     vRect
.xLeft   
= XLOG2DEV(x
); 
 229     vRect
.yTop    
= YLOG2DEV(y 
+ height
); 
 230     vRect
.xRight  
= XLOG2DEV(x 
+ width
); 
 231     vRect
.yBottom 
= YLOG2DEV(y
); 
 232     ::GpiIntersectClipRectangle(m_hPS
, &vRect
); 
 233     DO_SET_CLIPPING_BOX() 
 234 } // end of wxDC::DoSetClippingRegion 
 236 void wxDC::DoSetClippingRegionAsRegion( 
 237   const wxRegion
&                   rRegion
 
 240      wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region")); 
 244      ::GpiSetClipRegion( m_hPS
 
 245                         ,(HRGN
)rRegion
.GetHRGN() 
 248     DO_SET_CLIPPING_BOX() 
 249 } // end of wxDC::DoSetClippingRegionAsRegion 
 251 void wxDC::DestroyClippingRegion(void) 
 253     if (m_clipping 
&& m_hPS
) 
 258          // TODO: this should restore the previous clipped region 
 259          //       so that OnPaint processing works correctly, and 
 260          //       the update doesn't get destroyed after the first 
 261          //       DestroyClippingRegion 
 262          vRect
.xLeft   
= XLOG2DEV(0); 
 263          vRect
.yTop    
= YLOG2DEV(32000); 
 264          vRect
.xRight  
= XLOG2DEV(32000); 
 265          vRect
.yBottom 
= YLOG2DEV(0); 
 267          HRGN                       hRgn 
= ::GpiCreateRegion(m_hPS
, 1, &vRect
); 
 269          ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
); 
 272 } // end of wxDC::DestroyClippingRegion 
 274 // --------------------------------------------------------------------------- 
 275 // query capabilities 
 276 // --------------------------------------------------------------------------- 
 278 bool wxDC::CanDrawBitmap() const 
 283 bool wxDC::CanGetTextExtent() const 
 285     // What sort of display is it? 
 286     int technology 
= 0; // TODO:  ::GetDeviceCaps(GetHdc(), TECHNOLOGY); 
 288     // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER); 
 292 int wxDC::GetDepth() const 
 298 // --------------------------------------------------------------------------- 
 300 // --------------------------------------------------------------------------- 
 307 void wxDC::DoFloodFill( 
 310 , const wxColour
&                   rCol
 
 318     vPtlPos
.x 
= vX
;             // Loads x-coordinate 
 319     vPtlPos
.y 
= vY
;             // Loads y-coordinate 
 320     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 321     lColor 
= rCol
.GetPixel(); 
 322     lOptions 
= FF_BOUNDARY
; 
 323     if(wxFLOOD_SURFACE 
== nStyle
) 
 324         lOptions 
= FF_SURFACE
; 
 326     ::GpiFloodFill(m_hPS
, lOptions
, lColor
); 
 329 bool wxDC::DoGetPixel( 
 340     lColor 
= ::GpiSetPel(m_hPS
, &vPoint
); 
 341     pCol
->Set((unsigned long)lColor
); 
 348 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
) 
 353 void wxDC::DoDrawLine( 
 366     ::GpiMove(m_hPS
, &vPoint
[0]); 
 367     ::GpiLine(m_hPS
, &vPoint
[1]); 
 370 ////////////////////////////////////////////////////////////////////////////// 
 371 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1) 
 372 // and ending at (x2, y2). The current pen is used for the outline and the 
 373 // current brush for filling the shape. The arc is drawn in an anticlockwise 
 374 // direction from the start point to the end point. 
 375 ////////////////////////////////////////////////////////////////////////////// 
 376 void wxDC::DoDrawArc( 
 386      POINTL                         vPtlArc
[2]; // Structure for current position 
 395      ARCPARAMS                      vArcp
; // Structure for arc parameters 
 397     if((vX1 
== vXc 
&& vY1 
== vXc
) || (vX2 
== vXc 
&& vY2 
== vXc
)) 
 398         return; // Draw point ?? 
 399     dRadius 
= 0.5 * ( hypot( (double)(vY1 
- vYc
) 
 402                       hypot( (double)(vY2 
- vYc
) 
 407     dAngl1 
= atan2( (double)(vY1 
- vYc
) 
 410     dAngl2 
= atan2( (double)(vY2 
- vYc
) 
 417     // GpiPointArc can't draw full arc 
 419      if(dAngl2 
== dAngl1 
|| (vX1 
== vX2 
&& vY1 
== vY2
) ) 
 424         dAnglmid 
= (dAngl1 
+ dAngl2
)/2. + M_PI
; 
 425         vXm      
= vXc 
+ dRadius 
* cos(dAnglmid
); 
 426         vYm      
= vYc 
+ dRadius 
* sin(dAnglmid
); 
 441     dAnglmid 
= (dAngl1 
+ dAngl2
)/2.; 
 442     vXm      
= vXc 
+ dRadius 
* cos(dAnglmid
); 
 443     vYm      
= vYc 
+ dRadius 
* sin(dAnglmid
); 
 446     // Ellipse main axis (r,q), (p,s) with center at (0,0) */ 
 452     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 454     vPtlPos
.x 
= vX1
; // Loads x-coordinate 
 455     vPtlPos
.y 
= vY1
; // Loads y-coordinate 
 456     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 461     ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc 
 464 void wxDC::DoDrawCheckMark( 
 475     vPoint
[1].x 
= vX1 
+ vWidth
; 
 476     vPoint
[1].y 
= vY1 
+ vHeight
; 
 478     ::GpiMove(m_hPS
, &vPoint
[0]); 
 479     ::GpiBox( m_hPS       
// handle to a presentation space 
 480              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 481              ,&vPoint
[1]  // address of the corner 
 482              ,0L          // horizontal corner radius 
 483              ,0L          // vertical corner radius 
 485     if(vWidth 
> 4 && vHeight 
> 4) 
 489         vPoint
[0].x 
+= 2; vPoint
[0].y 
+= 2; 
 490         vPoint
[1].x 
-= 2; vPoint
[1].y 
-= 2; 
 491         ::GpiMove(m_hPS
, &vPoint
[0]); 
 492         ::GpiLine(m_hPS
, &vPoint
[1]); 
 494         vPoint
[0].x 
= vPoint
[1].x
; 
 496         ::GpiMove(m_hPS
, &vPoint
[0]); 
 497         ::GpiLine(m_hPS
, &vPoint
[1]); 
 501 void wxDC::DoDrawPoint( 
 510     ::GpiSetPel(m_hPS
, &vPoint
); 
 513 void wxDC::DoDrawPolygon( 
 521     ULONG                           ulCount 
= 1;    // Number of polygons. 
 522     POLYGON                         vPlgn
;          // polygon. 
 523     ULONG                           flOptions 
= 0L; // Drawing options. 
 525 ////////////////////////////////////////////////////////////////////////////// 
 526 // This contains fields of option bits... to draw boundary lines as well as 
 527 // the area interior. 
 529 // Drawing boundary lines: 
 530 //   POLYGON_NOBOUNDARY              Does not draw boundary lines. 
 531 //   POLYGON_BOUNDARY                Draws boundary lines (the default). 
 533 // Construction of the area interior: 
 534 //   POLYGON_ALTERNATE               Constructs interior in alternate mode 
 536 //   POLYGON_WINDING                 Constructs interior in winding mode. 
 537 ////////////////////////////////////////////////////////////////////////////// 
 539     ULONG                           flModel 
= 0L; // Drawing model. 
 541 ////////////////////////////////////////////////////////////////////////////// 
 543 //   POLYGON_INCL  Fill is inclusive of bottom right (the default). 
 544 //   POLYGON_EXCL  Fill is exclusive of bottom right. 
 545 //       This is provided to aid migration from other graphics models. 
 546 ////////////////////////////////////////////////////////////////////////////// 
 548     LONG                            lHits 
= 0L; // Correlation/error indicator. 
 551     int                             nIsTRANSPARENT 
= 0; 
 552     LONG                            lBorderColor 
= 0L; 
 555     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 556     lColor       
= m_brush
.GetColour().GetPixel(); 
 557     if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 561     vPlgn
.aPointl 
= (POINTL
*) calloc( n 
+ 1 
 563                                     ); // well, new will call malloc 
 565     for(i 
= 0; i 
< n
; i
++) 
 567         vPlgn
.aPointl
[i
].x 
= vPoints
[i
].x
; // +xoffset; 
 568         vPlgn
.aPointl
[i
].y 
= vPoints
[i
].y
; // +yoffset; 
 570     flModel 
= POLYGON_BOUNDARY
; 
 571     if(nFillStyle 
== wxWINDING_RULE
) 
 572         flModel 
|= POLYGON_WINDING
; 
 574         flModel 
|= POLYGON_ALTERNATE
; 
 579     ::GpiSetColor(m_hPS
, lBorderColor
); 
 580     ::GpiMove(m_hPS
, &vPoint
); 
 581     lHits 
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
); 
 585 void wxDC::DoDrawLines( 
 595     vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 596     vPoint
.y 
= vPoints
[0].y 
+ vYoffset
; 
 597     ::GpiMove(m_hPS
, &vPoint
); 
 599     LONG                            lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 601     ::GpiSetColor(m_hPS
, lBorderColor
); 
 602     for(i 
= 1; i 
< n
; i
++) 
 604         vPoint
.x 
= vPoints
[0].x 
+ vXoffset
; 
 605         vPoint
.y 
= vPoints
[0].y 
+ vYoffset
; 
 606         ::GpiLine(m_hPS
, &vPoint
); 
 610 void wxDC::DoDrawRectangle( 
 621     int                             nIsTRANSPARENT 
= 0; 
 625     vPoint
[1].x 
= vX 
+ vWidth
; 
 626     vPoint
[1].y 
= vY 
- vHeight
; 
 627     ::GpiMove(m_hPS
, &vPoint
[0]); 
 628     lColor       
= m_brush
.GetColour().GetPixel(); 
 629     lBorderColor 
= m_pen
.GetColour().GetPixel(); 
 630     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
 632     if(lColor 
== lBorderColor 
|| nIsTRANSPARENT
) 
 634         lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
 635         if(m_brush
.GetStyle() == wxTRANSPARENT
) 
 636             lControl 
= DRO_OUTLINE
; 
 638         ::GpiSetColor(m_hPS
, CLR_GREEN
); 
 639         ::GpiBox( m_hPS       
// handle to a presentation space 
 640                  ,lControl   
// draw the box outline ? or ? 
 641                  ,&vPoint
[1]  // address of the corner 
 642                  ,0L          // horizontal corner radius 
 643                  ,0L          // vertical corner radius 
 648         lControl 
= DRO_OUTLINE
; 
 671 void wxDC::DoDrawRoundedRectangle( 
 684     vPoint
[1].x 
= vX 
+ vWidth
; 
 685     vPoint
[1].y 
= vY 
+ vHeight
; 
 686     ::GpiMove(m_hPS
, &vPoint
[0]); 
 688     lControl 
= DRO_OUTLINEFILL
; //DRO_FILL; 
 689     if (m_brush
.GetStyle() == wxTRANSPARENT
) 
 690         lControl 
= DRO_OUTLINE
; 
 691     ::GpiBox( m_hPS         
// handle to a presentation space 
 692              ,DRO_OUTLINE   
// draw the box outline ? or ? 
 693              ,&vPoint
[1]    // address of the corner 
 694              ,(LONG
)dRadius 
// horizontal corner radius 
 695              ,(LONG
)dRadius 
// vertical corner radius 
 699 // Draw Ellipse within box (x,y) - (x+width, y+height) 
 700 void wxDC::DoDrawEllipse( 
 707     POINTL                          vPtlPos
; // Structure for current position 
 708     FIXED                           vFxMult
; // Multiplier for ellipse 
 709     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
 712     vArcp
.lQ 
= vHeight
/2; 
 715     ::GpiSetArcParams( m_hPS
 
 717                      ); // Sets parameters to default 
 718     vPtlPos
.x 
= vX 
+ vWidth
/2;  // Loads x-coordinate 
 719     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
 722              ); // Sets current position 
 723     vFxMult 
= MAKEFIXED(1, 0);             /* Sets multiplier            */ 
 726     // DRO_FILL, DRO_OTLINEFILL - where to get 
 731                 ); // Draws full arc with center at current position 
 734 void wxDC::DoDrawEllipticArc( 
 743     POINTL                          vPtlPos
; // Structure for current position 
 744     FIXED                           vFxMult
; // Multiplier for ellipse 
 745     ARCPARAMS                       vArcp
;   // Structure for arc parameters 
 747     FIXED                           vFSweepa
; // Start angle, sweep angle 
 752     dFractPart 
= modf(dSa
,&dIntPart
); 
 753     vFSa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
 754     dFractPart 
= modf(dEa 
- dSa
, &dIntPart
); 
 755     vFSweepa 
= MAKEFIXED((int)dIntPart
, (int)(dFractPart 
* 0xffff) ); 
 758     // Ellipse main axis (r,q), (p,s) with center at (0,0) 
 761     vArcp
.lQ 
= vHeight
/2; 
 764     ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default 
 765     vPtlPos
.x 
= vX 
+ vWidth
/2  * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate 
 766     vPtlPos
.y 
= vY 
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate 
 767     ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position 
 770     // May be not to the center ? 
 772     vPtlPos
.x 
= vX 
+ vWidth
/2 ; // Loads x-coordinate 
 773     vPtlPos
.y 
= vY 
+ vHeight
/2; // Loads y-coordinate 
 774     vFxMult 
= MAKEFIXED(1, 0);  // Sets multiplier 
 777     // DRO_FILL, DRO_OTLINEFILL - where to get 
 779     ::GpiPartialArc( m_hPS
 
 787 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
) 
 792 void wxDC::DoDrawBitmap( const wxBitmap 
&bmp
 
 793                         ,wxCoord x
, wxCoord y
 
 800 void wxDC::DoDrawText( 
 801   const wxString
&                   rsText
 
 812 void wxDC::DrawAnyText( 
 813   const wxString
&                   rsText
 
 818     int                             nOldBackground 
= 0; 
 823     // prepare for drawing the text 
 827     // Set text color attributes 
 829     if (m_textForegroundColour
.Ok()) 
 832                      ,(int)m_textForegroundColour
.GetPixel() 
 836     if (m_textBackgroundColour
.Ok()) 
 838         nOldBackground 
= SetTextBkColor( m_hPS
 
 839                                         ,(int)m_textBackgroundColour
.GetPixel() 
 848     lHits 
= ::GpiCharStringAt( m_hPS
 
 855         wxLogLastError(wxT("TextOut")); 
 859     // Restore the old parameters (text foreground colour may be left because 
 860     // it never is set to anything else, but background should remain 
 861     // transparent even if we just drew an opaque string) 
 863     if (m_textBackgroundColour
.Ok()) 
 864             SetTextBkColor( m_hPS
 
 872 void wxDC::DoDrawRotatedText( 
 873   const wxString
&                   rsText
 
 891         DoDrawText(text, x, y); 
 896         wxFillLogFont(&lf, &m_font); 
 898         // GDI wants the angle in tenth of degree 
 899         long angle10 = (long)(angle * 10); 
 900         lf.lfEscapement = angle10; 
 901         lf. lfOrientation = angle10; 
 903         HFONT hfont = ::CreateFontIndirect(&lf); 
 906             wxLogLastError("CreateFont"); 
 910             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
 912             DrawAnyText(text, x, y); 
 914             (void)::SelectObject(GetHdc(), hfontOld); 
 917         // call the bounding box by adding all four vertices of the rectangle 
 918         // containing the text to it (simpler and probably not slower than 
 919         // determining which of them is really topmost/leftmost/...) 
 921         GetTextExtent(text, &w, &h); 
 923         double rad = DegToRad(angle); 
 925         // "upper left" and "upper right" 
 926         CalcBoundingBox(x, y); 
 927         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
 928         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
 930         // "bottom left" and "bottom right" 
 931         x += (wxCoord)(h*sin(rad)); 
 932         y += (wxCoord)(h*cos(rad)); 
 933         CalcBoundingBox(x, y); 
 934         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
 939 // --------------------------------------------------------------------------- 
 941 // --------------------------------------------------------------------------- 
 943 void wxDC::SetPalette(const wxPalette
& palette
) 
 953     // Set the old object temporarily, in case the assignment deletes an object 
 954     // that's not yet selected out. 
 966     m_font
.SetPS(m_hPS
); // this will realize the font 
 970         HFONT                       hFont 
= m_font
.GetResourceHandle(); 
 971         if (hFont 
== (HFONT
) NULL
) 
 973             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
 976             m_hOldFont 
= (WXHFONT
) hFont
; 
 978 } // end of wxDC::SetFont 
 984     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1000             m_pen
.SetPS((HPS
)m_hOldPen
); 
1007         if (m_pen
.GetResourceHandle()) 
1011                 m_hOldPen 
= m_pen
.GetPS(); 
1017 void wxDC::SetBrush( 
1018   const wxBrush
&                    rBrush
 
1024 void wxDC::SetBackground(const wxBrush
& brush
) 
1029 void wxDC::SetBackgroundMode( 
1033     m_backgroundMode 
= nMode
; 
1036 void wxDC::SetLogicalFunction(int function
) 
1041 void wxDC::SetRop(WXHDC dc
) 
1043     if (!dc 
|| m_logicalFunction 
< 0) 
1047     // These may be wrong 
1048     switch (m_logicalFunction
) 
1050 // TODO: Figure this stuff out 
1051         //    case wxXOR: c_rop = R2_XORPEN; break; 
1052 //    case wxXOR: c_rop = R2_NOTXORPEN; break; 
1053 //    case wxINVERT: c_rop = R2_NOT; break; 
1054 //    case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break; 
1055 //    case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break; 
1056 //    case wxCLEAR: c_rop = R2_WHITE; break; 
1057 //    case wxSET: c_rop = R2_BLACK; break; 
1058 //    case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break; 
1059 //    case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break; 
1060 //    case wxAND: c_rop = R2_MASKPEN; break; 
1061 //    case wxOR: c_rop = R2_MERGEPEN; break; 
1062 //    case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break; 
1067 //      c_rop = R2_COPYPEN; 
1070 //    SetROP2((HDC) dc, c_rop); 
1073 bool wxDC::StartDoc(const wxString
& message
) 
1075     // We might be previewing, so return TRUE to let it continue. 
1083 void wxDC::StartPage() 
1087 void wxDC::EndPage() 
1091 // --------------------------------------------------------------------------- 
1093 // --------------------------------------------------------------------------- 
1095 wxCoord 
wxDC::GetCharHeight() const 
1097     FONTMETRICS                     vFM
; // metrics structure 
1099     ::GpiQueryFontMetrics( m_hPS
 
1100                           ,sizeof(FONTMETRICS
) 
1103     return YDEV2LOGREL(vFM
.lXHeight
); 
1106 wxCoord 
wxDC::GetCharWidth() const 
1108     FONTMETRICS                     vFM
; // metrics structure 
1110     ::GpiQueryFontMetrics( m_hPS
 
1111                           ,sizeof(FONTMETRICS
) 
1114     return XDEV2LOGREL(vFM
.lAveCharWidth
); 
1117 void wxDC::DoGetTextExtent( 
1118   const wxString
&                   rsString
 
1121 , wxCoord
*                          pvDescent
 
1122 , wxCoord
*                          pvExternalLeading
 
1126     POINTL                          avPoint
[TXTBOX_COUNT
]; 
1131     FONTMETRICS                     vFM
; // metrics structure 
1134     ERRORID                         vErrorCode
; // last error id code 
1135     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
1138         pFontToUse 
= (wxFont
*)&m_font
; 
1139     l 
= rsString
.length(); 
1140     pStr 
= (PCH
) rsString
.c_str(); 
1143     // In world coordinates. 
1145     bRc 
= ::GpiQueryTextBox( m_hPS
 
1148                             ,TXTBOX_COUNT 
// return maximum information 
1149                             ,avPoint      
// array of coordinates points 
1153        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
1156     vPtMin
.x 
= avPoint
[0].x
; 
1157     vPtMax
.x 
= avPoint
[0].x
; 
1158     vPtMin
.y 
= avPoint
[0].y
; 
1159     vPtMax
.y 
= avPoint
[0].y
; 
1160     for (i 
= 1; i 
< 4; i
++) 
1162         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
1163         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
1164         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
1165         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
1167     ::GpiQueryFontMetrics( m_hPS
 
1168                           ,sizeof(FONTMETRICS
) 
1173         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
1175         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
1177         *pvDescent 
= vFM
.lMaxDescender
; 
1178     if (pvExternalLeading
) 
1179         *pvExternalLeading 
= vFM
.lExternalLeading
; 
1182 void wxDC::SetMapMode( int mode 
) 
1187 void wxDC::SetUserScale(double x
, double y
) 
1192     SetMapMode(m_mappingMode
); 
1195 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
) 
1197     m_signX 
= xLeftRight 
? 1 : -1; 
1198     m_signY 
= yBottomUp 
? -1 : 1; 
1200     SetMapMode(m_mappingMode
); 
1203 void wxDC::SetSystemScale(double x
, double y
) 
1208     SetMapMode(m_mappingMode
); 
1211 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y 
) 
1216 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
1220     ::GpiQueryPageViewport( m_hPS
 
1227     ::GpiSetPageViewport( m_hPS
 
1232 // --------------------------------------------------------------------------- 
1233 // coordinates transformations 
1234 // --------------------------------------------------------------------------- 
1236 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
1238     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
1241 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
1243     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
)); 
1246 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
1248     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
1251 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
1253     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
)); 
1256 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
1258     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
1261 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
1263     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
); 
1266 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
1268     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
1271 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
1273     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
); 
1276 // --------------------------------------------------------------------------- 
1278 // --------------------------------------------------------------------------- 
1280 bool wxDC::DoBlit( wxCoord xdest
 
1295 void wxDC::DoGetSize( int* width
, int* height 
) const 
1300 void wxDC::DoGetSizeMM( int* width
, int* height 
) const 
1305 wxSize 
wxDC::GetPPI() const 
1310    return (wxSize(x
,y
)); 
1313 void wxDC::SetLogicalScale( double x
, double y 
) 
1318 #if WXWIN_COMPATIBILITY 
1319 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
, 
1320                          float *descent
, float *externalLeading
, 
1321                          wxFont 
*theFont
, bool use16bit
) const 
1323     wxCoord x1
, y1
, descent1
, externalLeading1
; 
1324     GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
); 
1327         *descent 
= descent1
; 
1328     if (externalLeading
) 
1329         *externalLeading 
= externalLeading1
; 
1333 // --------------------------------------------------------------------------- 
1334 // spline drawing code 
1335 // --------------------------------------------------------------------------- 
1339 class wxSpline
: public wxObject
 
1345     wxSpline(wxList 
*list
); 
1346     void DeletePoints(); 
1348     // Doesn't delete points 
1352 void wx_draw_open_spline(wxDC 
*dc
, wxSpline 
*spline
); 
1354 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
1355                          double a3
, double b3
, double a4
, double b4
); 
1356 void wx_clear_stack(); 
1357 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
1358                   double *y3
, double *x4
, double *y4
); 
1359 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
1360                     double x4
, double y4
); 
1361 static bool wx_spline_add_point(double x
, double y
); 
1362 static void wx_spline_draw_point_array(wxDC 
*dc
); 
1363 wxSpline 
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
); 
1365 void wxDC::DoDrawSpline(wxList 
*list
) 
1367     wxSpline 
spline(list
); 
1369     wx_draw_open_spline(this, &spline
); 
1372 wxList wx_spline_point_list
; 
1374 void wx_draw_open_spline(wxDC 
*dc
, wxSpline 
*spline
) 
1377     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
1378     double           x1
, y1
, x2
, y2
; 
1380     wxNode 
*node 
= spline
->points
->First(); 
1381     p 
= (wxPoint 
*)node
->Data(); 
1386     node 
= node
->Next(); 
1387     p 
= (wxPoint 
*)node
->Data(); 
1391     cx1 
= (double)((x1 
+ x2
) / 2); 
1392     cy1 
= (double)((y1 
+ y2
) / 2); 
1393     cx2 
= (double)((cx1 
+ x2
) / 2); 
1394     cy2 
= (double)((cy1 
+ y2
) / 2); 
1396     wx_spline_add_point(x1
, y1
); 
1398     while ((node 
= node
->Next()) != NULL
) 
1400         p 
= (wxPoint 
*)node
->Data(); 
1405         cx4 
= (double)(x1 
+ x2
) / 2; 
1406         cy4 
= (double)(y1 
+ y2
) / 2; 
1407         cx3 
= (double)(x1 
+ cx4
) / 2; 
1408         cy3 
= (double)(y1 
+ cy4
) / 2; 
1410         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
1414         cx2 
= (double)(cx1 
+ x2
) / 2; 
1415         cy2 
= (double)(cy1 
+ y2
) / 2; 
1418     wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
)); 
1419     wx_spline_add_point(x2
, y2
); 
1421     wx_spline_draw_point_array(dc
); 
1425 /********************* CURVES FOR SPLINES ***************************** 
1427   The following spline drawing routine is from 
1429     "An Algorithm for High-Speed Curve Generation" 
1430     by George Merrill Chaikin, 
1431     Computer Graphics and Image Processing, 3, Academic Press, 
1436         "On Chaikin's Algorithm" by R. F. Riesenfeld, 
1437         Computer Graphics and Image Processing, 4, Academic Press, 
1440 ***********************************************************************/ 
1442 #define     half(z1, z2)    ((z1+z2)/2.0) 
1445 /* iterative version */ 
1447 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
1450     register double  xmid
, ymid
; 
1451     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1454     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
1456     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
1457         xmid 
= (double)half(x2
, x3
); 
1458         ymid 
= (double)half(y2
, y3
); 
1459         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
1460             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
1461             wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
)); 
1462             wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
)); 
1464             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
1465                 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
1466             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
1467                 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
1473 /* utilities used by spline drawing routines */ 
1476 typedef struct wx_spline_stack_struct 
{ 
1477     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1481 #define         SPLINE_STACK_DEPTH             20 
1482 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
1483 static Stack   
*wx_stack_top
; 
1484 static int      wx_stack_count
; 
1486 void wx_clear_stack() 
1488     wx_stack_top 
= wx_spline_stack
; 
1492 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
1494     wx_stack_top
->x1 
= x1
; 
1495     wx_stack_top
->y1 
= y1
; 
1496     wx_stack_top
->x2 
= x2
; 
1497     wx_stack_top
->y2 
= y2
; 
1498     wx_stack_top
->x3 
= x3
; 
1499     wx_stack_top
->y3 
= y3
; 
1500     wx_stack_top
->x4 
= x4
; 
1501     wx_stack_top
->y4 
= y4
; 
1506 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
1507                   double *x3
, double *y3
, double *x4
, double *y4
) 
1509     if (wx_stack_count 
== 0) 
1513     *x1 
= wx_stack_top
->x1
; 
1514     *y1 
= wx_stack_top
->y1
; 
1515     *x2 
= wx_stack_top
->x2
; 
1516     *y2 
= wx_stack_top
->y2
; 
1517     *x3 
= wx_stack_top
->x3
; 
1518     *y3 
= wx_stack_top
->y3
; 
1519     *x4 
= wx_stack_top
->x4
; 
1520     *y4 
= wx_stack_top
->y4
; 
1524 static bool wx_spline_add_point(double x
, double y
) 
1526     wxPoint 
*point 
= new wxPoint
; 
1529     wx_spline_point_list
.Append((wxObject
*)point
); 
1533 static void wx_spline_draw_point_array(wxDC 
*dc
) 
1535     dc
->DrawLines(&wx_spline_point_list
, 0, 0); 
1536     wxNode 
*node 
= wx_spline_point_list
.First(); 
1539         wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
1542         node 
= wx_spline_point_list
.First(); 
1546 wxSpline::wxSpline(wxList 
*list
) 
1551 wxSpline::~wxSpline() 
1555 void wxSpline::DeletePoints() 
1557     for(wxNode 
*node 
= points
->First(); node
; node 
= points
->First()) 
1559         wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
1567 #endif // wxUSE_SPLINES