]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/canvas/polygon.cpp
d7b159f683d8f012bbe86813fcfa83103a403b57
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Author:      Klaas Holwerda 
   5 // Copyright:   2000 (c) Klaas Holwerda 
   6 // Licence:     wxWindows Licence 
   7 ///////////////////////////////////////////////////////////////////////////// 
  10     #pragma implementation "polygon.cpp" 
  13 // For compilers that support precompilation, includes "wx/wx.h". 
  14 #include "wx/wxprec.h" 
  20 #include "wx/canvas/polygon.h" 
  21 #include "wx/canvas/liner.h" 
  23 void ConvertSplinedPolygon(wxList
* list
, double Aber
); 
  24 void ConvertSplinedPolyline(wxList
* list
,double Aber
); 
  25 void ConvertSplinedPolygon(int& n
, wxPoint2DDouble
* points
[], double Aber
); 
  26 static void GetLRO(const wxPoint2DDouble
& P
, const wxPoint2DDouble
& p1
, const wxPoint2DDouble
& p2
, int &LRO1
, int &LRO2
,const double marge
); 
  28 //---------------------------------------------------------------------------- 
  30 //---------------------------------------------------------------------------- 
  32 wxCanvasPolyline::wxCanvasPolyline( int n
,  wxPoint2DDouble points
[]) 
  42 wxCanvasPolyline::~wxCanvasPolyline() 
  47 void wxCanvasPolyline::SetPosXY( double x
, double y
) 
  49     double xo
=m_points
[0].m_x
; 
  50     double yo
=m_points
[0].m_y
; 
  52     for (i
=0; i 
< m_n
;i
++) 
  54         m_points
[i
].m_x 
+= (x
-xo
); 
  55         m_points
[i
].m_y 
+= (y
-yo
); 
  60 void wxCanvasPolyline::TransLate( double x
, double y 
) 
  63     for (i
=0; i 
< m_n
;i
++) 
  71 void wxCanvasPolyline::CalcBoundingBox() 
  73     m_bbox
.SetValid(FALSE
); 
  76     for (i
=0; i 
< m_n
;i
++) 
  78         m_bbox
.Expand( m_points
[i
].m_x
,m_points
[i
].m_y
); 
  81     //include the pen width also 
  82     m_bbox
.EnLarge(m_pen
.GetWidth()); 
  85 void wxCanvasPolyline::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
  87     if (!m_visible
) return; 
  90     int end_y 
= clip_y
+clip_height
; 
  93     int end_x 
= clip_x
+clip_width
; 
  97     wxPoint 
*cpoints 
= new wxPoint
[m_n
]; 
  99     for (i 
= 0; i 
< m_n
; i
++) 
 103         //transform to absolute 
 104         cworld
->TransformPoint( m_points
[i
].m_x
, m_points
[i
].m_y
, x1
, y1 
); 
 105         //transform to device 
 106         cpoints
[i
].x 
= m_admin
->LogicalToDeviceX(x1
); 
 107         cpoints
[i
].y 
= m_admin
->LogicalToDeviceY(y1
); 
 109     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 110     dc
->SetClippingRegion(start_x
,start_y
,end_x
-start_x
,end_y
-start_y
); 
 111     int pw
=m_pen
.GetWidth(); 
 112     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 114     dc
->DrawLines(m_n
, cpoints
, 0,0); 
 116     dc
->SetPen(wxNullPen
); 
 117     dc
->DestroyClippingRegion(); 
 122 void wxCanvasPolyline::WriteSVG( wxTextOutputStream 
&stream 
) 
 126 wxCanvasObject
* wxCanvasPolyline::IsHitWorld( double x
, double y
, double margin 
) 
 128     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 129         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 130         (y 
>= m_bbox
.GetMinY()-margin
) && 
 131         (y 
<= m_bbox
.GetMaxY()+margin
) 
 134         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
 135         if (PointOnPolyline(P
,m_pen
.GetWidth()/2+margin
)) 
 138             return (wxCanvasObject
*) NULL
; 
 140     return (wxCanvasObject
*) NULL
; 
 143 bool wxCanvasPolyline::PointOnPolyline(const wxPoint2DDouble
& P
, double margin
) 
 147     wxPoint2DDouble p1
,p2
; 
 151     for (i 
= 0; i 
< m_n
-1; i
++) 
 155         if (margin 
> sqrt(pow(p1
.m_x
-P
.m_x
,2)+pow(p1
.m_y
-P
.m_y
,2))) 
 160         else if (!((p1
.m_x 
== p2
.m_x
) && (p1
.m_y 
== p2
.m_y
))) 
 163             if (line1
.PointInLine(P
,distance
,margin
) == R_IN_AREA
) 
 174 //---------------------------------------------------------------------------- 
 176 //---------------------------------------------------------------------------- 
 178 wxCanvasPolygon::wxCanvasPolygon( int n
, wxPoint2DDouble points
[],bool splined
) 
 183     m_brush 
= *wxBLACK_BRUSH
; 
 184     m_pen 
= *wxTRANSPARENT_PEN
; 
 195         ConvertSplinedPolygon(m_n
, &m_points
, 10 ); 
 201 wxCanvasPolygon::~wxCanvasPolygon() 
 206 void wxCanvasPolygon::SetPosXY( double x
, double y
) 
 208     double xo
=m_points
[0].m_x
; 
 209     double yo
=m_points
[0].m_y
; 
 211     for (i
=0; i 
< m_n
;i
++) 
 213         m_points
[i
].m_x 
+= (x
-xo
); 
 214         m_points
[i
].m_y 
+= (y
-yo
); 
 219 void wxCanvasPolygon::TransLate( double x
, double y 
) 
 222     for (i
=0; i 
< m_n
;i
++) 
 224         m_points
[i
].m_x 
+= x
; 
 225         m_points
[i
].m_y 
+= y
; 
 230 void wxCanvasPolygon::CalcBoundingBox() 
 233     m_bbox
.SetValid(FALSE
); 
 236     for (i
=0; i 
< m_n
;i
++) 
 238         m_bbox
.Expand( m_points
[i
].m_x
,m_points
[i
].m_y
); 
 241     //include the pen width also 
 242     m_bbox
.EnLarge(m_pen
.GetWidth()); 
 245 void wxCanvasPolygon::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 247     if (!m_visible
) return; 
 249     int start_y 
= clip_y
; 
 250     int end_y 
= clip_y
+clip_height
; 
 252     int start_x 
= clip_x
; 
 253     int end_x 
= clip_x
+clip_width
; 
 257     //one extra for drawlines in some cases 
 258     wxPoint 
*cpoints 
= new wxPoint
[m_n
+1]; 
 260     for (i 
= 0; i 
< m_n
; i
++) 
 264         cworld
->TransformPoint( m_points
[i
].m_x
, m_points
[i
].m_y
, x1
, y1 
); 
 265         cpoints
[i
].x 
= m_admin
->LogicalToDeviceX(x1
); 
 266         cpoints
[i
].y 
= m_admin
->LogicalToDeviceY(y1
); 
 270     cworld
->TransformPoint( m_points
[0].m_x
, m_points
[0].m_y
, x1
, y1 
); 
 271     cpoints
[m_n
].x 
= m_admin
->LogicalToDeviceX(x1
); 
 272     cpoints
[m_n
].y 
= m_admin
->LogicalToDeviceY(y1
); 
 274     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 275     dc
->SetClippingRegion(start_x
,start_y
,end_x
-start_x
,end_y
-start_y
); 
 276     dc
->SetBrush(m_brush
); 
 277     int pw
=m_pen
.GetWidth(); 
 278     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 279     if ( m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE 
&& m_transp
) 
 281         //draw a transparent polygon 
 282         //leaf the pen not transparent, which i prefer 
 283         dc
->SetPen( wxPen( *wxWHITE
,m_admin
->LogicalToDeviceXRel(pw
), wxSOLID
) ); 
 284         dc
->SetTextForeground(*wxBLACK
); 
 285         dc
->SetTextBackground(*wxWHITE
); 
 286         dc
->SetLogicalFunction(wxAND_INVERT
); 
 287         // BLACK OUT the opaque pixels and leave the rest as is 
 288         dc
->DrawPolygon(m_n
, cpoints
, 0,0,wxWINDING_RULE
); 
 289         // Set background and foreground colors for fill pattern 
 290         //the previous blacked out pixels are now merged with the layer color 
 291         //while the non blacked out pixels stay as they are. 
 292         dc
->SetTextForeground(*wxBLACK
); 
 293         //now define what will be the color of the fillpattern parts that are not transparent 
 294         dc
->SetTextBackground(m_textfg
); 
 295         dc
->SetLogicalFunction(wxOR
); 
 296         //don't understand how but the outline is also depending on logicalfunction 
 298         dc
->DrawPolygon(m_n
, cpoints
, 0,0,wxWINDING_RULE
); 
 302         int pw2
=m_gpen
.GetWidth(); 
 303         m_gpen
.SetWidth(m_admin
->LogicalToDeviceYRel(pw2
)); 
 304         FillPolygon(cworld
,clip_x
,clip_y
,clip_width
,clip_height 
); 
 305         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 308             dc
->DrawLines(m_n
+1, cpoints
, 0,0); 
 310         m_gpen
.SetWidth(pw2
); 
 315         dc
->DrawPolygon(m_n
, cpoints
, 0,0,wxWINDING_RULE
); 
 318     dc
->SetBrush(wxNullBrush
); 
 319     dc
->SetPen(wxNullPen
); 
 320     dc
->DestroyClippingRegion(); 
 325 void wxCanvasPolygon::WriteSVG( wxTextOutputStream 
&stream 
) 
 329 wxCanvasObject
* wxCanvasPolygon::IsHitWorld( double x
, double y
, double margin 
) 
 331     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 332         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 333         (y 
>= m_bbox
.GetMinY()-margin
) && 
 334         (y 
<= m_bbox
.GetMaxY()+margin
) 
 337         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
 338         INOUTPOLY io
=PointInPolygon(P
, m_pen
.GetWidth()/2+margin
); 
 339         if (io 
== OUTSIDE_POLY
) 
 340             return (wxCanvasObject
*) NULL
; 
 344     return (wxCanvasObject
*) NULL
; 
 347 INOUTPOLY 
wxCanvasPolygon::PointInPolygon(const wxPoint2DDouble
& P
, double marge
) 
 349     int     R_tot 
= 0, L_tot 
= 0; 
 351     double  px 
= P
.m_x
, py 
= P
.m_y
; 
 353     wxPoint2DDouble p1
,p2
; 
 355     //iterate across points until we are sure that the given point is in or out 
 357     for (i 
= 0; i 
< m_n
; i
++) 
 366         GetLRO(P
,p1
,p2
,p1_LRO
,p2_LRO
,marge
/10); 
 367         if (p1_LRO 
!= p2_LRO
) 
 370             if (p2_LRO 
== -1) { R 
= -p1_LRO
; L 
= 1; } 
 371             if (p2_LRO 
== 0) if (p1_LRO 
== 1) R 
= -1; else L 
= -1; 
 372             if (p2_LRO 
== 1) { R 
= 1; L 
= p1_LRO
; } 
 374             // calculate intersection point with line for px 
 377                 if ((p1
.m_y 
< (py 
+ marge
)) && (p1
.m_y 
> (py 
- marge
))) 
 380                     Y_intersect 
= p1
.m_y
; 
 382             else if (p2_LRO 
== 0) 
 384                 if ((p2
.m_y 
< (py 
+ marge
)) && (p2
.m_y 
> (py 
- marge
))) 
 387                     Y_intersect 
= p2
.m_y
; 
 389             else //both p2_LRO and p1_LRO not 0 
 391                 if ((p1
.m_y 
> (py 
+ marge
)) && (p2
.m_y 
> (py 
+ marge
))) 
 392                     Y_intersect 
= p1
.m_y
; //a save value to check later 
 393                 else if ((p1
.m_y 
< (py
- marge
)) && (p2
.m_y 
< (py 
- marge
))) 
 394                     Y_intersect 
= p1
.m_y
; //a save value to check later 
 395                 else //need to calculate intersection 
 397                     if (!((p1
.m_x 
== p2
.m_x
) && (p1
.m_y 
== p2
.m_y
))) 
 400                         line1
.CalculateLineParameters(); 
 401                         Y_intersect 
= line1
.Calculate_Y(px
); 
 407             if (Y_intersect 
> (py 
+ marge
)) 
 412             else if ((Y_intersect 
<= (py 
+ marge
)) && (Y_intersect 
>= (py 
- marge
))) 
 419     // geef het juiste resultaat terug 
 421         if (L_tot 
== 0) return OUTSIDE_POLY
; 
 424         if (L_tot 
== 0) return ON_POLY
; 
 425         else return INSIDE_POLY
; 
 428 //---------------------------------------------------------------------------- 
 430 //---------------------------------------------------------------------------- 
 432 wxCanvasPolylineL::wxCanvasPolylineL( wxList
* points
, bool spline 
) 
 436     m_pen 
= *wxBLACK_PEN
; 
 439         ConvertSplinedPolyline(m_lpoints
, 10); 
 443 wxCanvasPolylineL::~wxCanvasPolylineL() 
 445     m_lpoints
->DeleteContents(TRUE
); 
 449 double wxCanvasPolylineL::GetPosX() 
 451     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 452     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 456 double wxCanvasPolylineL::GetPosY() 
 458     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 459     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 463 void wxCanvasPolylineL::SetPosXY( double x
, double y 
) 
 465     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 466     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 467     double xo
=point
->m_x
; 
 468     double yo
=point
->m_y
; 
 471         point 
= (wxPoint2DDouble
*)node
->Data(); 
 472         point
->m_x 
= point
->m_x 
+ x
-xo
; 
 473         point
->m_y 
= point
->m_y 
+ y
-yo
; 
 474         node 
= node
->GetNext(); 
 479 void wxCanvasPolylineL::TransLate( double x
, double y 
) 
 481     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 484         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 487         node 
= node
->GetNext(); 
 492 void wxCanvasPolylineL::CalcBoundingBox() 
 494     m_bbox
.SetValid(FALSE
); 
 496     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 499         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 500         m_bbox
.Expand( point
->m_x
,point
->m_y
); 
 501         node 
= node
->GetNext(); 
 504     //include the pen width also 
 505     m_bbox
.EnLarge(m_pen
.GetWidth()); 
 508 void wxCanvasPolylineL::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 510     if (!m_visible
) return; 
 512     int start_y 
= clip_y
; 
 513     int end_y 
= clip_y
+clip_height
; 
 515     int start_x 
= clip_x
; 
 516     int end_x 
= clip_x
+clip_width
; 
 520     int n
=m_lpoints
->GetCount(); 
 521     wxPoint 
*cpoints 
= new wxPoint
[n
]; 
 523     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 527         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 530         //transform to absolute 
 531         cworld
->TransformPoint( point
->m_x
, point
->m_y
, x1
, y1 
); 
 532         //transform to device 
 533         cpoints
[i
].x 
= m_admin
->LogicalToDeviceX(x1
); 
 534         cpoints
[i
].y 
= m_admin
->LogicalToDeviceY(y1
); 
 536         node 
= node
->GetNext(); 
 540     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 541     dc
->SetClippingRegion(start_x
,start_y
,end_x
-start_x
,end_y
-start_y
); 
 542     int pw
=m_pen
.GetWidth(); 
 543     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 545     dc
->DrawLines(n
, cpoints
, 0,0); 
 547     dc
->SetPen(wxNullPen
); 
 548     dc
->DestroyClippingRegion(); 
 553 void wxCanvasPolylineL::WriteSVG( wxTextOutputStream 
&stream 
) 
 557 wxCanvasObject
* wxCanvasPolylineL::IsHitWorld( double x
, double y
, double margin 
) 
 559     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 560         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 561         (y 
>= m_bbox
.GetMinY()-margin
) && 
 562         (y 
<= m_bbox
.GetMaxY()+margin
) 
 565         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
 566         if (PointOnPolyline(P
,m_pen
.GetWidth()/2+margin
)) 
 569             return (wxCanvasObject
*) NULL
; 
 571     return (wxCanvasObject
*) NULL
; 
 574 bool wxCanvasPolylineL::PointOnPolyline(const wxPoint2DDouble
& P
, double margin
) 
 578     wxPoint2DDouble p1
,p2
; 
 580     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 581     p2 
= *(wxPoint2DDouble
*)node
->Data(); 
 582     while (node 
&& !result
) 
 585         node
=node
->GetNext(); 
 587         p2 
= *(wxPoint2DDouble
*)node
->Data(); 
 589         if (margin 
> sqrt(pow(p1
.m_x
-P
.m_x
,2)+pow(p1
.m_y
-P
.m_y
,2))) 
 591         else if (!((p1
.m_x 
== p2
.m_x
) && (p1
.m_y 
== p2
.m_y
))) 
 594             if (line1
.PointInLine(P
,distance
,margin
) == R_IN_AREA
) 
 602 //---------------------------------------------------------------------------- 
 604 //---------------------------------------------------------------------------- 
 606 wxCanvasPolygonL::wxCanvasPolygonL( wxList
* points
, bool spline 
) 
 610     m_brush 
= *wxBLACK_BRUSH
; 
 611     m_pen 
= *wxTRANSPARENT_PEN
; 
 618         ConvertSplinedPolyline(m_lpoints
, 10); 
 622 wxCanvasPolygonL::~wxCanvasPolygonL() 
 624     m_lpoints
->DeleteContents(TRUE
); 
 628 double wxCanvasPolygonL::GetPosX() 
 630     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 631     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 635 double wxCanvasPolygonL::GetPosY() 
 637     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 638     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 642 void wxCanvasPolygonL::SetPosXY( double x
, double y 
) 
 644     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 645     wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 646     double xo
=point
->m_x
; 
 647     double yo
=point
->m_y
; 
 650         point 
= (wxPoint2DDouble
*)node
->Data(); 
 651         point
->m_x 
= point
->m_x 
+ x
-xo
; 
 652         point
->m_y 
= point
->m_y 
+ y
-yo
; 
 653         node 
= node
->GetNext(); 
 658 void wxCanvasPolygonL::TransLate( double x
, double y 
) 
 660     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 663         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 666         node 
= node
->GetNext(); 
 671 void wxCanvasPolygonL::CalcBoundingBox() 
 674     m_bbox
.SetValid(FALSE
); 
 676     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 679         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 680         m_bbox
.Expand( point
->m_x
,point
->m_y
); 
 681         node 
= node
->GetNext(); 
 684     //include the pen width also 
 685     m_bbox
.EnLarge(m_pen
.GetWidth()); 
 688 void wxCanvasPolygonL::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 690     if (!m_visible
) return; 
 692     int start_y 
= clip_y
; 
 693     int end_y 
= clip_y
+clip_height
; 
 695     int start_x 
= clip_x
; 
 696     int end_x 
= clip_x
+clip_width
; 
 700     int n
=m_lpoints
->GetCount(); 
 701     wxPoint 
*cpoints 
= new wxPoint
[n
]; 
 703     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 707         wxPoint2DDouble
* point 
= (wxPoint2DDouble
*)node
->Data(); 
 710         //transform to absolute 
 711         cworld
->TransformPoint( point
->m_x
, point
->m_y
, x1
, y1 
); 
 712         //transform to device 
 713         cpoints
[i
].x 
= m_admin
->LogicalToDeviceX(x1
); 
 714         cpoints
[i
].y 
= m_admin
->LogicalToDeviceY(y1
); 
 716         node 
= node
->GetNext(); 
 719     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 720     dc
->SetClippingRegion(start_x
,start_y
,end_x
-start_x
,end_y
-start_y
); 
 721     dc
->SetBrush(m_brush
); 
 722     int pw
=m_pen
.GetWidth(); 
 723     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 724     if ( m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE 
&& m_transp
) 
 726         //draw a transparent polygon 
 727         //leaf the pen not transparent, which i prefer 
 728         dc
->SetPen( wxPen( *wxWHITE
,m_admin
->LogicalToDeviceXRel(pw
), wxSOLID
) ); 
 729         dc
->SetTextForeground(*wxBLACK
); 
 730         dc
->SetTextBackground(*wxWHITE
); 
 731         dc
->SetLogicalFunction(wxAND_INVERT
); 
 732         // BLACK OUT the opaque pixels and leave the rest as is 
 733         dc
->DrawPolygon(n
, cpoints
, 0,0,wxWINDING_RULE
); 
 734         // Set background and foreground colors for fill pattern 
 735         //the previous blacked out pixels are now merged with the layer color 
 736         //while the non blacked out pixels stay as they are. 
 737         dc
->SetTextForeground(*wxBLACK
); 
 738         //now define what will be the color of the fillpattern parts that are not transparent 
 739         dc
->SetTextBackground(m_textfg
); 
 740         dc
->SetLogicalFunction(wxOR
); 
 741         //don't understand how but the outline is also depending on logicalfunction 
 743         dc
->DrawPolygon(n
, cpoints
, 0,0,wxWINDING_RULE
); 
 744         dc
->SetLogicalFunction(wxCOPY
); 
 749         dc
->SetTextForeground(m_textfg
); 
 750         dc
->SetTextBackground(m_textbg
); 
 751         dc
->DrawPolygon(n
, cpoints
, 0,0,wxWINDING_RULE
); 
 754     dc
->SetBrush(wxNullBrush
); 
 755     dc
->SetPen(wxNullPen
); 
 756     dc
->DestroyClippingRegion(); 
 761 void wxCanvasPolygonL::WriteSVG( wxTextOutputStream 
&stream 
) 
 765 static void GetLRO(const wxPoint2DDouble
& P
, const wxPoint2DDouble
& p1
, const wxPoint2DDouble
& p2
, int &LRO1
, int &LRO2
,const double marge
) 
 767     if (p1
.m_x 
> (P
.m_x 
+ marge
)) LRO1 
= -1;        // beginnode is right of P 
 769         if (p1
.m_x 
< (P
.m_x 
- marge
)) LRO1 
= 1;     // beginnode is left of P 
 770         else LRO1 
= 0;                              // beginnode is on vertical line through P 
 772     if (p2
.m_x 
> (P
.m_x 
+ marge
)) LRO2 
= -1;        // endnode is right of P 
 774         if (p2
.m_x 
< (P
.m_x 
- marge
)) LRO2 
= 1;     // endnode is left of P 
 775         else LRO2 
= 0;                              // endnode is on vertical line through P 
 778 wxCanvasObject
* wxCanvasPolygonL::IsHitWorld( double x
, double y
, double margin 
) 
 780     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 781         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 782         (y 
>= m_bbox
.GetMinY()-margin
) && 
 783         (y 
<= m_bbox
.GetMaxY()+margin
) 
 786         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
 787         INOUTPOLY io
=PointInPolygon(P
,m_pen
.GetWidth()/2 + margin
); 
 788         if (io 
== OUTSIDE_POLY
) 
 789             return (wxCanvasObject
*) NULL
; 
 793     return (wxCanvasObject
*) NULL
; 
 796 INOUTPOLY 
wxCanvasPolygonL::PointInPolygon(const wxPoint2DDouble
& P
, double marge
) 
 798     int     R_tot 
= 0, L_tot 
= 0; 
 800     double  px 
= P
.m_x
, py 
= P
.m_y
; 
 802     wxPoint2DDouble p1
,p2
; 
 804     //iterate across points until we are sure that the given point is in or out 
 805     wxNode 
*node 
= m_lpoints
->GetFirst(); 
 809         p1 
= *(wxPoint2DDouble
*)node
->Data(); 
 810         if (m_lpoints
->GetLast() == node
) 
 812             p2 
= *(wxPoint2DDouble
*)m_lpoints
->GetFirst(); 
 816             p2 
= *(wxPoint2DDouble
*)node
->GetNext()->Data(); 
 820         GetLRO(P
,p1
,p2
,p1_LRO
,p2_LRO
,marge
/10); 
 821         if (p1_LRO 
!= p2_LRO
) 
 824             if (p2_LRO 
== -1) { R 
= -p1_LRO
; L 
= 1; } 
 825             if (p2_LRO 
== 0) if (p1_LRO 
== 1) R 
= -1; else L 
= -1; 
 826             if (p2_LRO 
== 1) { R 
= 1; L 
= p1_LRO
; } 
 828             // calculate intersection point with line for px 
 831                 if ((p1
.m_y 
< (py 
+ marge
)) && (p1
.m_y 
> (py 
- marge
))) 
 834                     Y_intersect 
= p1
.m_y
; 
 836             else if (p2_LRO 
== 0) 
 838                 if ((p2
.m_y 
< (py 
+ marge
)) && (p2
.m_y 
> (py 
- marge
))) 
 841                     Y_intersect 
= p2
.m_y
; 
 843             else //both p2_LRO and p1_LRO not 0 
 845                 if ((p1
.m_y 
> (py 
+ marge
)) && (p2
.m_y 
> (py 
+ marge
))) 
 846                     Y_intersect 
= p1
.m_y
; //a save value to check later 
 847                 else if ((p1
.m_y 
< (py
- marge
)) && (p2
.m_y 
< (py 
- marge
))) 
 848                     Y_intersect 
= p1
.m_y
; //a save value to check later 
 849                 else //need to calculate intersection 
 851                     if (!((p1
.m_x 
== p2
.m_x
) && (p1
.m_y 
== p2
.m_y
))) 
 854                         line1
.CalculateLineParameters(); 
 855                         Y_intersect 
= line1
.Calculate_Y(px
); 
 861             if (Y_intersect 
> (py 
+ marge
)) 
 866             else if ((Y_intersect 
<= (py 
+ marge
)) && (Y_intersect 
>= (py 
- marge
))) 
 874     // geef het juiste resultaat terug 
 876         if (L_tot 
== 0) return OUTSIDE_POLY
; 
 879         if (L_tot 
== 0) return ON_POLY
; 
 880         else return INSIDE_POLY
; 
 883 // --------------------------------------------------------------------------- 
 884 // spline drawing code 
 885 // --------------------------------------------------------------------------- 
 887 static void gds_quadratic_spline(wxList 
*org
,double a1
, double b1
, double a2
, double b2
, 
 888                          double a3
, double b3
, double a4
, double b4
,double aber
); 
 889 static void gds_clear_stack(); 
 890 static int gds_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
 891                   double *y3
, double *x4
, double *y4
); 
 892 static void gds_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
 893                     double x4
, double y4
); 
 895 void ConvertSplinedPolygon(int& n
, wxPoint2DDouble
* points
[], double Aber
) 
 899     for (i 
= 0; i 
< n
; i
++) 
 901         h
.Append((wxObject
*) new wxPoint2DDouble((*points
)[i
].m_x
, (*points
)[i
].m_y
)); 
 905     ConvertSplinedPolygon(&h
, Aber
); 
 908     *points 
= new wxPoint2DDouble
[n
]; 
 909     wxNode
* node
=h
.GetFirst(); 
 910     for (i 
= 0; i 
< n
; i
++) 
 913         node 
= node
->GetNext(); 
 914         (*points
)[i
].m_x
=((wxPoint2DDouble
*) hh
->GetData())->m_x
; 
 915         (*points
)[i
].m_y
=((wxPoint2DDouble
*) hh
->GetData())->m_y
; 
 916         delete (wxPoint2DDouble
*) hh
->GetData(); 
 921 void ConvertSplinedPolygon(wxList
* list
, double Aber
) 
 923     wxPoint2DDouble
* point
; 
 924     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
 925     double           x1
, y1
, x2
, y2
; 
 927     if (list
->GetCount() <2) 
 930     wxNode
* iter
=list
->GetLast(); 
 931     x1 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
 932     y1 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
 934     iter
=list
->GetFirst(); 
 935     x2 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
 936     y2 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
 938     point 
= new wxPoint2DDouble(x2
,y2
); 
 939     list
->Append((wxObject
*)point
); 
 941     cx1 
= (x1 
+ x2
) / 2.0; 
 942     cy1 
= (y1 
+ y2
) / 2.0; 
 943     cx2 
= (cx1 
+ x2
) / 2.0; 
 944     cy2 
= (cy1 
+ y2
) / 2.0; 
 946     delete (wxPoint2DDouble
*) iter
->Data(); 
 948     iter
=list
->GetFirst(); 
 949     x1 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
 950     y1 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
 951     point 
= new wxPoint2DDouble(x1
,y1
); 
 952     list
->Append((wxObject
*)point
); 
 955     int count
=list
->GetCount(); 
 960         x2 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
 961         y2 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
 962         cx4 
= (x1 
+ x2
) / 2.0; 
 963         cy4 
= (y1 
+ y2
) / 2.0; 
 964         cx3 
= (x1 
+ cx4
) / 2.0; 
 965         cy3 
= (y1 
+ cy4
) / 2.0; 
 967         gds_quadratic_spline(list
,cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
,Aber
); 
 971         cx2 
= (cx1 
+ x2
) / 2.0; 
 972         cy2 
= (cy1 
+ y2
) / 2.0; 
 973         delete (wxPoint2DDouble
*)iter
->Data(); 
 975         iter
=list
->GetFirst(); 
 979     iter
=list
->GetFirst(); 
 980     delete (wxPoint2DDouble
*)iter
->Data(); 
 984 void ConvertSplinedPolyline(wxList
* list
,double Aber
) 
 986     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
 987     double           x1
, y1
, x2
, y2
; 
 990     if (list
->GetCount() <2) 
 995     wxNode
* iter
=list
->GetFirst(); 
 997     x1 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
 998     y1 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
1000     delete (wxPoint2DDouble
*)iter
->Data(); 
1002     iter
=list
->GetFirst(); 
1003     x2 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
1004     y2 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
1005     cx1 
= (x1 
+ x2
) / 2.0; 
1006     cy1 
= (y1 
+ y2
) / 2.0; 
1007     cx2 
= (cx1 
+ x2
) / 2.0; 
1008     cy2 
= (cy1 
+ y2
) / 2.0; 
1010     wxPoint2DDouble
* point 
= new wxPoint2DDouble(x1
,y1
); 
1011     list
->Append((wxObject
*)point
); 
1013     delete (wxPoint2DDouble
*)iter
->Data(); 
1015     iter
=list
->GetFirst(); 
1018     int count
=list
->GetCount(); 
1023         x2 
= ((wxPoint2DDouble
*)iter
->Data())->m_x
; 
1024         y2 
= ((wxPoint2DDouble
*)iter
->Data())->m_y
; 
1025         cx4 
= (x1 
+ x2
) / 2.0; 
1026         cy4 
= (y1 
+ y2
) / 2.0; 
1027         cx3 
= (x1 
+ cx4
) / 2.0; 
1028         cy3 
= (y1 
+ cy4
) / 2.0; 
1030         gds_quadratic_spline(list
,cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
,Aber
); 
1034         cx2 
= (cx1 
+ x2
) / 2.0; 
1035         cy2 
= (cy1 
+ y2
) / 2.0; 
1036         delete (wxPoint2DDouble
*)iter
->Data(); 
1038         iter
=list
->GetFirst(); 
1042     point 
= new wxPoint2DDouble(cx1
,cy1
); 
1043     list
->Append((wxObject
*)point
); 
1045     point 
= new wxPoint2DDouble(x2
,y2
); 
1046     list
->Append((wxObject
*)point
); 
1049 /********************* CURVES FOR SPLINES ***************************** 
1051   The following spline drawing routine is from 
1053     "An Algorithm for High-Speed Curve Generation" 
1054     by George Merrill Chaikin, 
1055     Computer Graphics and Image Processing, 3, Academic Press, 
1060         "On Chaikin's Algorithm" by R. F. Riesenfeld, 
1061         Computer Graphics and Image Processing, 4, Academic Press, 
1064 ***********************************************************************/ 
1066 #define     half(z1, z2)    ((z1+z2)/2.0) 
1069 /* iterative version */ 
1071 void gds_quadratic_spline(wxList 
*org
,double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
1072                          double b4
,double Aber
) 
1074     register double  xmid
, ymid
; 
1075     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1076     wxPoint2DDouble
* point
; 
1079     gds_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
1081     while (gds_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) 
1083         xmid 
= half(x2
, x3
); 
1084         ymid 
= half(y2
, y3
); 
1085         if (fabs(x1 
- xmid
) < Aber 
&& fabs(y1 
- ymid
) < Aber 
&& 
1086             fabs(xmid 
- x4
) < Aber 
&& fabs(ymid 
- y4
) < Aber
) 
1088             point 
= new wxPoint2DDouble(x1
,y1
); 
1089             org
->Append((wxObject
*)point
); 
1090             point 
= new wxPoint2DDouble(xmid
,ymid
); 
1091             org
->Append((wxObject
*)point
); 
1093             gds_spline_push(xmid
, ymid
, half(xmid
, x3
), half(ymid
, y3
), 
1094                 half(x3
, x4
), half(y3
, y4
), x4
, y4
); 
1095             gds_spline_push(x1
, y1
, half(x1
, x2
), half(y1
, y2
), 
1096                 half(x2
, xmid
), half(y2
, ymid
), xmid
, ymid
); 
1102 /* utilities used by spline drawing routines */ 
1105 typedef struct gds_spline_stack_struct 
{ 
1106     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1110 #define         SPLINE_STACK_DEPTH             20 
1111 static Stack    gds_spline_stack
[SPLINE_STACK_DEPTH
]; 
1112 static Stack   
*gds_stack_top
; 
1113 static int      gds_stack_count
; 
1115 static void gds_clear_stack() 
1117     gds_stack_top 
= gds_spline_stack
; 
1118     gds_stack_count 
= 0; 
1121 static void gds_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
1123     gds_stack_top
->x1 
= x1
; 
1124     gds_stack_top
->y1 
= y1
; 
1125     gds_stack_top
->x2 
= x2
; 
1126     gds_stack_top
->y2 
= y2
; 
1127     gds_stack_top
->x3 
= x3
; 
1128     gds_stack_top
->y3 
= y3
; 
1129     gds_stack_top
->x4 
= x4
; 
1130     gds_stack_top
->y4 
= y4
; 
1135 int gds_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
1136                   double *x3
, double *y3
, double *x4
, double *y4
) 
1138     if (gds_stack_count 
== 0) 
1142     *x1 
= gds_stack_top
->x1
; 
1143     *y1 
= gds_stack_top
->y1
; 
1144     *x2 
= gds_stack_top
->x2
; 
1145     *y2 
= gds_stack_top
->y2
; 
1146     *x3 
= gds_stack_top
->x3
; 
1147     *y3 
= gds_stack_top
->y3
; 
1148     *x4 
= gds_stack_top
->x4
; 
1149     *y4 
= gds_stack_top
->y4
; 
1153 void wxAET::CalculateLineParameters( const wxPoint2DDouble
& p1 
, const wxPoint2DDouble
& p2 
) 
1155     double A 
= p2
.m_y 
- p1
.m_y
; //A (y2-y1) 
1165         m_BdivA
= (p1
.m_x 
- p2
.m_x
)/A
; //B (x1-x2) 
1167         m_CdivA
= ((p2
.m_x
*p1
.m_y
) - (p1
.m_x
*p2
.m_y
)) /A 
; 
1171 void wxAET::CalculateXs( double y 
) 
1173     m_xs
= -m_BdivA 
* y 
- m_CdivA
; 
1176 //use by polygon filling 
1177 //moves the scanline up 
1178 //index is the index of the point where the search begins 
1179 //direction is +1 or -1 and indicates if the segment ascends or decends 
1180 bool wxCanvasPolygon::MoveUp( double horline
, int& index
, int direction
) 
1182     int walk 
= (index 
+ direction 
+ m_n
) % m_n
; 
1183     while ( m_points
[walk
].m_y 
< horline 
) 
1185         if (m_points
[walk
].m_y 
< m_points
[index
].m_y 
) 
1191             walk 
= (index 
+ direction 
+ m_n
) % m_n
; 
1197 //a crictical point is a point between a decending and a ascending segment 
1198 //collect those points for filling later 
1199 void wxCanvasPolygon::DetectCriticalPoints() 
1201     //candidate for critical point 
1202     //true if Y is getting lower, unchanged i Y is unchanged 
1203     //and if Y becomes higher and candidate was true: it is a critical point 
1204     bool candidate 
= FALSE
; 
1207     for ( i
=0; i 
< m_n
; i
++) 
1212         //check if Y is smaller 
1213         if (m_points
[i
].m_y 
> m_points
[j
].m_y
) 
1214             //we have a candidate 
1216         else if ( (m_points
[i
].m_y 
< m_points
[j
].m_y
) && candidate
) 
1217         {   //this is a critical point put in list 
1218             bool inserted
=FALSE
; 
1219             wxNode 
*node 
= m_CRlist
.GetFirst(); 
1222                 //sorted on smallest Y value 
1223                 int* ind
=(int*) node
->GetData(); 
1224                 if (m_points
[*ind
].m_y 
> m_points
[i
].m_y
) 
1226                     m_CRlist
.Insert(node
,(wxObject
*) new int(i
)); 
1230                 node 
= node
->GetNext(); 
1233                 m_CRlist
.Append((wxObject
*) new int(i
)); 
1239         for ( i
=0; i 
< m_n
; i
++) 
1244             //check if Y is smaller 
1245             if (m_points
[i
].m_y 
> m_points
[j
].m_y
) 
1246                 //we have a candidate 
1248             else if ( (m_points
[i
].m_y 
< m_points
[j
].m_y
) && candidate
) 
1249             {   //this is a critical point put in list 
1250                 bool inserted
=FALSE
; 
1251                 wxNode 
*node 
= m_CRlist
.GetFirst(); 
1254                     //sorted on smallest Y value 
1255                     int* ind
=(int*) node
->GetData(); 
1256                     if (m_points
[*ind
].m_y 
> m_points
[i
].m_y
) 
1258                         m_CRlist
.Insert(node
,(wxObject
*) new int(i
)); 
1262                     node 
= node
->GetNext(); 
1265                     m_CRlist
.Append((wxObject
*) new int(i
)); 
1273 void wxCanvasPolygon::FillPolygon(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1278     //how much is on pixel in world coordinates 
1282         scalefactor
=m_gdistance
; 
1284         //abs here needed if yaxis is going up (always scan in world coordinates UP) 
1285         scalefactor
=fabs(m_admin
->DeviceToLogicalYRel(1)); //1 pixel height 
1287     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1288     dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height 
); 
1289     wxPen  gradientpen
=m_gpen
; 
1291     int dred 
= m_textbg
.Red()-m_textfg
.Red(); 
1292     int dgreen 
= m_textbg
.Green()-m_textfg
.Green(); 
1293     int dblue 
= m_textbg
.Blue()-m_textfg
.Blue(); 
1295     //total number of lines to go from m_textbg to m_textfg 
1296     //gives the following number of steps for the gradient color 
1297     int stepcol 
= (int) (m_bbox
.GetHeight()/scalefactor
); 
1299     DetectCriticalPoints(); 
1303     if (cworld
->IsIdentity()) 
1305         //TODO do something with clipping region (inverse transform?) 
1306         //the next does not work, i don't know why 
1307         //min = wxMin (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height)); 
1308         //max = wxMax (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height)); 
1309         min
= m_bbox
.GetMinY(); 
1310         max
= m_bbox
.GetMaxY(); 
1314         min
= m_bbox
.GetMinY(); 
1315         max
= m_bbox
.GetMaxY(); 
1318     int curcol 
= (int)( (min 
- m_bbox
.GetMinY())/scalefactor 
); 
1321     for ( i 
= min
; i 
< max
; i
+=scalefactor
) 
1323         wxNode 
*node 
= m_AETlist
.GetFirst(); 
1324         int count
= m_AETlist
.GetCount(); 
1327             wxAET
* ele 
= ((wxAET
*)node
->GetData()); 
1328             index
= ele
->m_index
; 
1329             int direction 
= ele
->m_direction
; 
1330             if (!MoveUp(i
,index
,direction
)) 
1334                 node 
= node
->GetNext(); 
1335                 m_AETlist
.DeleteNode(h
); 
1339                 if (ele
->m_index 
!= index
) 
1342                    int h 
= (index 
+ direction 
+ m_n
) % m_n
; 
1343                    ele
->CalculateLineParameters(m_points
[h
],m_points
[index
]); 
1345                 if (ele
->m_horizontal
) 
1346                    ele
->m_xs
=m_points
[index
].m_x
; 
1348                    ele
->CalculateXs(i
); 
1349                 node 
= node
->GetNext(); 
1354         node 
= m_CRlist
.GetFirst(); 
1355         while (m_CRlist
.GetCount() && m_points
[*((int*)node
->GetData())].m_y 
<=i 
) 
1358             for ( DI 
= -1; DI 
<=1 ; DI
+=2) 
1360                 index
=*((int*)node
->GetData()); 
1361                 if (MoveUp(i
,index
,DI
)) 
1363                     wxAET
* ele 
= new wxAET(); 
1365                     ele
->m_direction
=DI
; 
1366                     int h 
= (index 
+ DI 
+ m_n
) % m_n
; 
1367                     ele
->CalculateLineParameters(m_points
[h
],m_points
[index
]); 
1368                     if (ele
->m_horizontal
) 
1369                         ele
->m_xs
=m_points
[index
].m_x
; 
1371                         ele
->CalculateXs(i
); 
1373                     //insert in sorted order od m_xs 
1374                     bool inserted
=FALSE
; 
1375                     wxNode 
*node2 
= m_AETlist
.GetFirst(); 
1378                         //sorted on smallest xs value 
1379                         if (ele
->m_xs 
< ((wxAET
*)node2
->GetData())->m_xs
) 
1381                             m_AETlist
.Insert(node2
,(wxObject
*) ele
); 
1385                         node2 
= node2
->GetNext(); 
1388                         m_AETlist
.Append((wxObject
*)ele
); 
1393             node 
= node
->GetNext(); 
1394             m_CRlist
.DeleteNode(h
); 
1398         wxColour 
gradcol(m_textbg
.Red()+dred
*curcol
/stepcol
, 
1399                          m_textbg
.Green()+dgreen
*curcol
/stepcol
, 
1400                          m_textbg
.Blue()+dblue
*curcol
/stepcol
); 
1401         gradientpen
.SetColour(gradcol
); 
1403         //m_AETlist must be sorted in m_xs at this moment 
1404         //now draw all the line parts on one horizontal scanline (Winding Rule) 
1406         node 
= m_AETlist
.GetFirst(); 
1409             wxAET
* ele 
= ((wxAET
*)node
->GetData()); 
1410             out
+=ele
->m_direction
; 
1413                 double x1
=ele
->m_xs
; 
1414                 node 
= node
->GetNext(); 
1415                 ele 
= ((wxAET
*)node
->GetData()); 
1416                 double x2
=ele
->m_xs
; 
1417                 dc
->SetPen( gradientpen 
); 
1418                 double wx1
,wy1
,wx2
,wy2
; 
1419                 cworld
->TransformPoint( x1
, i
, wx1
, wy1 
); 
1420                 cworld
->TransformPoint( x2
, i
, wx2
, wy2 
); 
1421                 int dx1
,dy1
,dx2
,dy2
; 
1422                 dx1 
= m_admin
->LogicalToDeviceX( wx1 
); 
1423                 dy1 
= m_admin
->LogicalToDeviceY( wy1 
); 
1424                 dx2 
= m_admin
->LogicalToDeviceX( wx2 
); 
1425                 dy2 
= m_admin
->LogicalToDeviceY( wy2 
); 
1427                 //TODO KKK need real line clipping here since line can be rotated. 
1428                 if (0 && cworld
->IsIdentity()) 
1430                     if (dx1 
< clip_x
) dx1
=clip_x
; 
1431                     if (dx2 
> clip_x 
+ clip_width
) dx2
=clip_x 
+ clip_width
; 
1432                     if ((dy1 
>  clip_y
) && dy1 
< clip_y 
+ clip_height
) 
1433                         dc
->DrawLine( dx1
, dy1
, dx2
, dy2 
); 
1437                     dc
->DrawLine( dx1
, dy1
, dx2
, dy2 
); 
1442                 node 
= node
->GetNext(); 
1446     dc
->DestroyClippingRegion();