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. 
  84     return vCbnd
.lBackColor
; 
  90 , int                               nBackgroundColour
 
  96     rc 
=  QueryTextBkColor(hPS
); 
  98     vCbnd
.lBackColor 
= nBackgroundColour
; 
  99     ::GpiSetAttrs(hPS
,            // presentation-space handle 
 100                   PRIM_CHAR
,      // Char primitive. 
 101                   CBB_BACK_COLOR
, // sets color. 
 103                   &vCbnd          
// buffer for attributes. 
 110 , int                               nBackgroundMode
 
 113     if(nBackgroundMode 
== wxTRANSPARENT
) 
 118         // the background of the primitive takes  over whatever is underneath. 
 125 // =========================================================================== 
 127 // =========================================================================== 
 129 // --------------------------------------------------------------------------- 
 131 // --------------------------------------------------------------------------- 
 148     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     GetClipBox(GetHdc(), &rect);                \ 
 212     m_clipX1 = (wxCoord) XDEV2LOG(rect.left);   \ 
 213     m_clipY1 = (wxCoord) YDEV2LOG(rect.top);    \ 
 214     m_clipX2 = (wxCoord) XDEV2LOG(rect.right);  \ 
 215     m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \ 
 218 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
 
 219                                ,wxCoord width
, wxCoord height
 
 225 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
) 
 230 void wxDC::DestroyClippingRegion(void) 
 235 // --------------------------------------------------------------------------- 
 236 // query capabilities 
 237 // --------------------------------------------------------------------------- 
 239 bool wxDC::CanDrawBitmap() const 
 244 bool wxDC::CanGetTextExtent() const 
 246     // What sort of display is it? 
 247     int technology 
= 0; // TODO:  ::GetDeviceCaps(GetHdc(), TECHNOLOGY); 
 249     // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER); 
 253 int wxDC::GetDepth() const 
 259 // --------------------------------------------------------------------------- 
 261 // --------------------------------------------------------------------------- 
 268 void wxDC::DoFloodFill( wxCoord x
 
 277 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour 
*col
) const 
 283 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
) 
 288 void wxDC::DoDrawLine( 
 301     // ::GpiSetColor(m_hPS,CLR_RED); //DEbug 
 302     ::GpiMove(m_hPS
, &vPoint
[0]); 
 303     ::GpiLine(m_hPS
, &vPoint
[1]); 
 306 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
 
 307                      ,wxCoord x2
, wxCoord y2
 
 308                      ,wxCoord xc
, wxCoord yc
 
 314 void wxDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, 
 315                            wxCoord width
, wxCoord height
) 
 320 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
) 
 325 void wxDC::DoDrawPolygon(int n
, wxPoint points
[] 
 326                          ,wxCoord xoffset
, wxCoord yoffset
 
 333 void wxDC::DoDrawLines( int n
, wxPoint points
[] 
 334                        ,wxCoord xoffset
, wxCoord yoffset
 
 340 void wxDC::DoDrawRectangle( 
 351     vPoint
[1].x 
= vX 
+ Width
; 
 352     vPoint
[1].y 
= vY 
- Height
;      //mustdie !!! ?? 
 354     ::GpiMove(m_hPS
, &vPoint
[0]); 
 355     ::GpiBox( m_hPS       
// handle to a presentation space 
 356              ,DRO_OUTLINE 
// draw the box outline ? or ? 
 357              ,&vPoint
[1]  // address of the corner 
 358              ,0L          // horizontal corner radius 
 359              ,0L          // vertical corner radius 
 363 void wxDC::DoDrawRoundedRectangle( 
 375     vPoint
[1].x 
= vX 
+ vWidth
; 
 376     vPoint
[1].y 
= vY 
+ vHeight
;      //or -height aka mustdie !!! ?? 
 378     ::GpiMove(m_hPS
, &vPoint
[0]); 
 379     ::GpiBox( m_hPS        
// handle to a presentation space 
 380              ,DRO_OUTLINE  
// draw the box outline ? or ? 
 381              ,&vPoint
[1]   // address of the corner 
 382              ,(LONG
)radius 
// horizontal corner radius 
 383              ,(LONG
)radius 
// vertical corner radius 
 387 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 392 void wxDC::DoDrawEllipticArc( wxCoord x
 
 403 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
) 
 408 void wxDC::DoDrawBitmap( const wxBitmap 
&bmp
 
 409                         ,wxCoord x
, wxCoord y
 
 416 void wxDC::DoDrawText( 
 417   const wxString
&                   rsText
 
 428 void wxDC::DrawAnyText( 
 429   const wxString
&                   rsText
 
 434     int                             nOldBackground 
= 0; 
 439     // prepare for drawing the text 
 443     // Set text color attributes 
 445     if (m_textForegroundColour
.Ok()) 
 448                      ,(int)m_textForegroundColour
.GetPixel() 
 452     if (m_textBackgroundColour
.Ok()) 
 454         nOldBackground 
= SetTextBkColor( m_hPS
 
 455                                         ,(int)m_textBackgroundColour
.GetPixel() 
 464     lHits 
= ::GpiCharStringAt( m_hPS
 
 471         wxLogLastError(wxT("TextOut")); 
 475     // Restore the old parameters (text foreground colour may be left because 
 476     // it never is set to anything else, but background should remain 
 477     // transparent even if we just drew an opaque string) 
 479     if (m_textBackgroundColour
.Ok()) 
 480             SetTextBkColor( m_hPS
 
 488 void wxDC::DoDrawRotatedText( 
 489   const wxString
&                   rsText
 
 507         DoDrawText(text, x, y); 
 512         wxFillLogFont(&lf, &m_font); 
 514         // GDI wants the angle in tenth of degree 
 515         long angle10 = (long)(angle * 10); 
 516         lf.lfEscapement = angle10; 
 517         lf. lfOrientation = angle10; 
 519         HFONT hfont = ::CreateFontIndirect(&lf); 
 522             wxLogLastError("CreateFont"); 
 526             HFONT hfontOld = ::SelectObject(GetHdc(), hfont); 
 528             DrawAnyText(text, x, y); 
 530             (void)::SelectObject(GetHdc(), hfontOld); 
 533         // call the bounding box by adding all four vertices of the rectangle 
 534         // containing the text to it (simpler and probably not slower than 
 535         // determining which of them is really topmost/leftmost/...) 
 537         GetTextExtent(text, &w, &h); 
 539         double rad = DegToRad(angle); 
 541         // "upper left" and "upper right" 
 542         CalcBoundingBox(x, y); 
 543         CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); 
 544         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
 546         // "bottom left" and "bottom right" 
 547         x += (wxCoord)(h*sin(rad)); 
 548         y += (wxCoord)(h*cos(rad)); 
 549         CalcBoundingBox(x, y); 
 550         CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); 
 555 // --------------------------------------------------------------------------- 
 557 // --------------------------------------------------------------------------- 
 559 void wxDC::SetPalette(const wxPalette
& palette
) 
 569     // Set the old object temporarily, in case the assignment deletes an object 
 570     // that's not yet selected out. 
 574 //        ::SelectObject(GetHdc(), (HFONT) m_hOldFont); 
 583 //            ::SelectObject(GetHdc(), (HFONT) m_hOldFont); 
 587     if (m_font
.Ok() && m_font
.GetResourceHandle()) 
 589         HFONT                       hFont 
= (HFONT
)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle()); 
 590         if (hFont 
== (HFONT
) NULL
) 
 592             wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont.")); 
 595             m_hOldFont 
= (WXHFONT
) hFont
; 
 603     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 611     int                             nWidth 
= m_pen
.GetWidth(); 
 620                                        ( fabs((double) XLOG2DEVREL(width
)) + 
 621                                          fabs((double) YLOG2DEVREL(width
)) 
 625     wxColour                        vColor 
= m_pen
.GetColour(); 
 632 void wxDC::SetBrush(const wxBrush
& brush
) 
 637 void wxDC::SetBackground(const wxBrush
& brush
) 
 642 void wxDC::SetBackgroundMode( 
 646     m_backgroundMode 
= nMode
; 
 649 void wxDC::SetLogicalFunction(int function
) 
 654 void wxDC::SetRop(WXHDC dc
) 
 656     if (!dc 
|| m_logicalFunction 
< 0) 
 660     // These may be wrong 
 661     switch (m_logicalFunction
) 
 663 // TODO: Figure this stuff out 
 664         //    case wxXOR: c_rop = R2_XORPEN; break; 
 665 //    case wxXOR: c_rop = R2_NOTXORPEN; break; 
 666 //    case wxINVERT: c_rop = R2_NOT; break; 
 667 //    case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break; 
 668 //    case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break; 
 669 //    case wxCLEAR: c_rop = R2_WHITE; break; 
 670 //    case wxSET: c_rop = R2_BLACK; break; 
 671 //    case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break; 
 672 //    case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break; 
 673 //    case wxAND: c_rop = R2_MASKPEN; break; 
 674 //    case wxOR: c_rop = R2_MERGEPEN; break; 
 675 //    case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break; 
 680 //      c_rop = R2_COPYPEN; 
 683 //    SetROP2((HDC) dc, c_rop); 
 686 bool wxDC::StartDoc(const wxString
& message
) 
 688     // We might be previewing, so return TRUE to let it continue. 
 696 void wxDC::StartPage() 
 704 // --------------------------------------------------------------------------- 
 706 // --------------------------------------------------------------------------- 
 708 wxCoord 
wxDC::GetCharHeight() const 
 714 wxCoord 
wxDC::GetCharWidth() const 
 720 void wxDC::DoGetTextExtent( 
 721   const wxString
&                   rsString
 
 725 , wxCoord
*                          pvExternalLeading
 
 729     POINTL                          avPoint
[TXTBOX_COUNT
]; 
 734     FONTMETRICS                     vFM
; // metrics structure 
 737     ERRORID                         vErrorCode
; // last error id code 
 738     wxFont
*                         pFontToUse 
= (wxFont
*)pTheFont
; 
 741         pFontToUse 
= (wxFont
*)&m_font
; 
 742     l 
= rsString
.length(); 
 743     pStr 
= (PCH
) rsString
.c_str(); 
 746     // In world coordinates. 
 748     bRc 
= ::GpiQueryTextBox( m_hPS
 
 751                             ,TXTBOX_COUNT 
// return maximum information 
 752                             ,avPoint      
// array of coordinates points 
 756        vErrorCode 
= ::WinGetLastError(wxGetInstance()); 
 759     vPtMin
.x 
= avPoint
[0].x
; 
 760     vPtMax
.x 
= avPoint
[0].x
; 
 761     vPtMin
.y 
= avPoint
[0].y
; 
 762     vPtMax
.y 
= avPoint
[0].y
; 
 763     for (i 
= 1; i 
< 4; i
++) 
 765         if(vPtMin
.x 
> avPoint
[i
].x
) vPtMin
.x 
= avPoint
[i
].x
; 
 766         if(vPtMin
.y 
> avPoint
[i
].y
) vPtMin
.y 
= avPoint
[i
].y
; 
 767         if(vPtMax
.x 
< avPoint
[i
].x
) vPtMax
.x 
= avPoint
[i
].x
; 
 768         if(vPtMax
.y 
< avPoint
[i
].y
) vPtMax
.y 
= avPoint
[i
].y
; 
 770     ::GpiQueryFontMetrics( m_hPS
 
 776         *pvX 
= (wxCoord
)(vPtMax
.x 
- vPtMin
.x 
+ 1); 
 778         *pvY 
= (wxCoord
)(vPtMax
.y 
- vPtMin
.y 
+ 1); 
 780         *pvDescent 
= vFM
.lMaxDescender
; 
 782         *pvExternalLeading 
= vFM
.lExternalLeading
; 
 785 void wxDC::SetMapMode( int mode 
) 
 790 void wxDC::SetUserScale(double x
, double y
) 
 795     SetMapMode(m_mappingMode
); 
 798 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
) 
 800     m_signX 
= xLeftRight 
? 1 : -1; 
 801     m_signY 
= yBottomUp 
? -1 : 1; 
 803     SetMapMode(m_mappingMode
); 
 806 void wxDC::SetSystemScale(double x
, double y
) 
 811     SetMapMode(m_mappingMode
); 
 814 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y 
) 
 819 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
 824 // --------------------------------------------------------------------------- 
 825 // coordinates transformations 
 826 // --------------------------------------------------------------------------- 
 828 wxCoord 
wxDCBase::DeviceToLogicalX(wxCoord x
) const 
 830     return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
); 
 833 wxCoord 
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const 
 835     return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
)); 
 838 wxCoord 
wxDCBase::DeviceToLogicalY(wxCoord y
) const 
 840     return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
); 
 843 wxCoord 
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const 
 845     return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
)); 
 848 wxCoord 
wxDCBase::LogicalToDeviceX(wxCoord x
) const 
 850     return (wxCoord
) ((x 
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX 
+ m_deviceOriginX
); 
 853 wxCoord 
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const 
 855     return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
); 
 858 wxCoord 
wxDCBase::LogicalToDeviceY(wxCoord y
) const 
 860     return (wxCoord
) ((y 
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY 
+ m_deviceOriginY
); 
 863 wxCoord 
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const 
 865     return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
); 
 868 // --------------------------------------------------------------------------- 
 870 // --------------------------------------------------------------------------- 
 872 bool wxDC::DoBlit( wxCoord xdest
 
 887 void wxDC::DoGetSize( int* width
, int* height 
) const 
 892 void wxDC::DoGetSizeMM( int* width
, int* height 
) const 
 897 wxSize 
wxDC::GetPPI() const 
 902    return (wxSize(x
,y
)); 
 905 void wxDC::SetLogicalScale( double x
, double y 
) 
 910 #if WXWIN_COMPATIBILITY 
 911 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
, 
 912                          float *descent
, float *externalLeading
, 
 913                          wxFont 
*theFont
, bool use16bit
) const 
 915     wxCoord x1
, y1
, descent1
, externalLeading1
; 
 916     GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
); 
 921         *externalLeading 
= externalLeading1
; 
 925 // --------------------------------------------------------------------------- 
 926 // spline drawing code 
 927 // --------------------------------------------------------------------------- 
 931 class wxSpline
: public wxObject
 
 937     wxSpline(wxList 
*list
); 
 940     // Doesn't delete points 
 944 void wx_draw_open_spline(wxDC 
*dc
, wxSpline 
*spline
); 
 946 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
 947                          double a3
, double b3
, double a4
, double b4
); 
 948 void wx_clear_stack(); 
 949 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
 950                   double *y3
, double *x4
, double *y4
); 
 951 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
 952                     double x4
, double y4
); 
 953 static bool wx_spline_add_point(double x
, double y
); 
 954 static void wx_spline_draw_point_array(wxDC 
*dc
); 
 955 wxSpline 
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
); 
 957 void wxDC::DoDrawSpline(wxList 
*list
) 
 959     wxSpline 
spline(list
); 
 961     wx_draw_open_spline(this, &spline
); 
 964 wxList wx_spline_point_list
; 
 966 void wx_draw_open_spline(wxDC 
*dc
, wxSpline 
*spline
) 
 969     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
 970     double           x1
, y1
, x2
, y2
; 
 972     wxNode 
*node 
= spline
->points
->First(); 
 973     p 
= (wxPoint 
*)node
->Data(); 
 979     p 
= (wxPoint 
*)node
->Data(); 
 983     cx1 
= (double)((x1 
+ x2
) / 2); 
 984     cy1 
= (double)((y1 
+ y2
) / 2); 
 985     cx2 
= (double)((cx1 
+ x2
) / 2); 
 986     cy2 
= (double)((cy1 
+ y2
) / 2); 
 988     wx_spline_add_point(x1
, y1
); 
 990     while ((node 
= node
->Next()) != NULL
) 
 992         p 
= (wxPoint 
*)node
->Data(); 
 997         cx4 
= (double)(x1 
+ x2
) / 2; 
 998         cy4 
= (double)(y1 
+ y2
) / 2; 
 999         cx3 
= (double)(x1 
+ cx4
) / 2; 
1000         cy3 
= (double)(y1 
+ cy4
) / 2; 
1002         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
1006         cx2 
= (double)(cx1 
+ x2
) / 2; 
1007         cy2 
= (double)(cy1 
+ y2
) / 2; 
1010     wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
)); 
1011     wx_spline_add_point(x2
, y2
); 
1013     wx_spline_draw_point_array(dc
); 
1017 /********************* CURVES FOR SPLINES ***************************** 
1019   The following spline drawing routine is from 
1021     "An Algorithm for High-Speed Curve Generation" 
1022     by George Merrill Chaikin, 
1023     Computer Graphics and Image Processing, 3, Academic Press, 
1028         "On Chaikin's Algorithm" by R. F. Riesenfeld, 
1029         Computer Graphics and Image Processing, 4, Academic Press, 
1032 ***********************************************************************/ 
1034 #define     half(z1, z2)    ((z1+z2)/2.0) 
1037 /* iterative version */ 
1039 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
1042     register double  xmid
, ymid
; 
1043     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1046     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
1048     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
1049         xmid 
= (double)half(x2
, x3
); 
1050         ymid 
= (double)half(y2
, y3
); 
1051         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
1052             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
1053             wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
)); 
1054             wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
)); 
1056             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
1057                 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
1058             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
1059                 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
1065 /* utilities used by spline drawing routines */ 
1068 typedef struct wx_spline_stack_struct 
{ 
1069     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1073 #define         SPLINE_STACK_DEPTH             20 
1074 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
1075 static Stack   
*wx_stack_top
; 
1076 static int      wx_stack_count
; 
1078 void wx_clear_stack() 
1080     wx_stack_top 
= wx_spline_stack
; 
1084 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
1086     wx_stack_top
->x1 
= x1
; 
1087     wx_stack_top
->y1 
= y1
; 
1088     wx_stack_top
->x2 
= x2
; 
1089     wx_stack_top
->y2 
= y2
; 
1090     wx_stack_top
->x3 
= x3
; 
1091     wx_stack_top
->y3 
= y3
; 
1092     wx_stack_top
->x4 
= x4
; 
1093     wx_stack_top
->y4 
= y4
; 
1098 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
1099                   double *x3
, double *y3
, double *x4
, double *y4
) 
1101     if (wx_stack_count 
== 0) 
1105     *x1 
= wx_stack_top
->x1
; 
1106     *y1 
= wx_stack_top
->y1
; 
1107     *x2 
= wx_stack_top
->x2
; 
1108     *y2 
= wx_stack_top
->y2
; 
1109     *x3 
= wx_stack_top
->x3
; 
1110     *y3 
= wx_stack_top
->y3
; 
1111     *x4 
= wx_stack_top
->x4
; 
1112     *y4 
= wx_stack_top
->y4
; 
1116 static bool wx_spline_add_point(double x
, double y
) 
1118     wxPoint 
*point 
= new wxPoint
; 
1121     wx_spline_point_list
.Append((wxObject
*)point
); 
1125 static void wx_spline_draw_point_array(wxDC 
*dc
) 
1127     dc
->DrawLines(&wx_spline_point_list
, 0, 0); 
1128     wxNode 
*node 
= wx_spline_point_list
.First(); 
1131         wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
1134         node 
= wx_spline_point_list
.First(); 
1138 wxSpline::wxSpline(wxList 
*list
) 
1143 wxSpline::~wxSpline() 
1147 void wxSpline::DeletePoints() 
1149     for(wxNode 
*node 
= points
->First(); node
; node 
= points
->First()) 
1151         wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
1159 #endif // wxUSE_SPLINES