1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Author:      Robert Roebling 
   5 // Copyright:   2000 (c) Robert Roebling 
   6 // Licence:     wxWindows Licence 
   7 ///////////////////////////////////////////////////////////////////////////// 
  10     #pragma implementation "canvas.cpp" 
  13 // For compilers that support precompilation, includes "wx/wx.h". 
  14 #include "wx/wxprec.h" 
  20 #include "wx/canvas/canvas.h" 
  21 #include "wx/canvas/polygon.h" 
  22 #include "wx/canvas/liner.h" 
  26     #include <gdk/gdkrgb.h> 
  27     #include "wx/gtk/win_gtk.h" 
  30 #ifndef wxUSE_FREETYPE 
  31     #define wxUSE_FREETYPE 0 
  35     #include <freetype/freetype.h> 
  40 //---------------------------------------------------------------------------- 
  42 //---------------------------------------------------------------------------- 
  44 static const double pi 
= 3.1415926535; 
  47 FT_Library g_freetypeLibrary
; 
  50 //---------------------------------------------------------------------------- 
  52 //---------------------------------------------------------------------------- 
  54 IMPLEMENT_CLASS(wxCanvasObject
, wxEvtHandler
) 
  56 wxCanvasObject::wxCanvasObject() 
  58     // the default event handler is just this object 
  65     m_dragmode 
= wxDRAG_ONTOP
; 
  66 //  handy when debugging 
  67 //  m_dragmode = wxDRAG_RECTANGLE; 
  71 bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent
& event
) 
  73     return m_eventHandler
->ProcessEvent(event
); 
  76 void wxCanvasObject::PushEventHandler(wxEvtHandler 
*handler
) 
  78     handler
->SetNextHandler(GetEventHandler()); 
  79     m_eventHandler
=handler
; 
  82 wxEvtHandler 
*wxCanvasObject::PopEventHandler(bool deleteHandler
) 
  84     wxEvtHandler 
*handlerA 
= m_eventHandler
; 
  87         wxEvtHandler 
*handlerB 
= handlerA
->GetNextHandler(); 
  88         handlerA
->SetNextHandler((wxEvtHandler 
*)NULL
); 
  89         m_eventHandler
=handlerB
; 
  93             handlerA 
= (wxEvtHandler 
*)NULL
; 
 100 void wxCanvasObject::AppendEventHandler(wxEvtHandler 
*handler
) 
 102     GetEventHandler()->SetNextHandler(handler
); 
 105 wxEvtHandler 
*wxCanvasObject::RemoveLastEventHandler(bool deleteHandler
) 
 107     //always the first in the row 
 108     wxEvtHandler 
*handlerA 
= m_eventHandler
; 
 109     wxEvtHandler 
*handlerB
=handlerA
; 
 111     while ( handlerA
->GetNextHandler() ) 
 114         handlerA 
= handlerA
->GetNextHandler(); 
 117     handlerB
->SetNextHandler((wxEvtHandler 
*)NULL
); 
 123     return GetEventHandler(); 
 126 wxRect 
wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix
& cworld
) 
 128     wxBoundingBox tmp
=m_bbox
; 
 131     int x1 
= m_admin
->LogicalToDeviceX( tmp
.GetMinX() ); 
 132     int y1 
= m_admin
->LogicalToDeviceY( tmp
.GetMinY() ); 
 133     int x2 
= m_admin
->LogicalToDeviceX( tmp
.GetMaxX() ); 
 134     int y2 
= m_admin
->LogicalToDeviceY( tmp
.GetMaxY() ); 
 152     tmparea
.width 
= x2
-x1
;    // FIXME +1 ? 
 153     tmparea
.height 
= y2
-y1
;   // FIXME +1 ? 
 158 void wxCanvasObject::MoveAbsolute( double x
, double y 
) 
 160     //save old position of boundingbox 
 161     double oldx 
= GetXMin(); 
 162     double oldy 
= GetYMin(); 
 163     double w 
= m_bbox
.GetWidth(); 
 164     double h 
= m_bbox
.GetHeight(); 
 168     double newx
=GetXMin(); 
 169     double newy
=GetYMin(); 
 171     double leftu
,rightu
,bottomu
,topu 
; 
 172     leftu   
= wxMin (oldx
, newx 
) ; 
 173     rightu  
= wxMax (oldx 
+ w
, newx 
+ w
) ; 
 174     topu    
= wxMin (oldy
, newy
) ; 
 175     bottomu 
= wxMax (oldy 
+ h
, newy 
+ h
) ; 
 177     if ( rightu 
- leftu 
< 2*w 
&& bottomu 
- topu 
< 2*h 
) 
 179         m_admin
->Update( this,leftu
, topu
, rightu 
- leftu
, bottomu 
- topu
); 
 183         m_admin
->Update( this, oldx
, oldy
, w
, h 
); 
 184         m_admin
->Update( this, newx
, newy
, w
, h 
); 
 188 void wxCanvasObject::MoveRelative( double x
, double y 
) 
 190     //save old position of boundingbox 
 191     double oldx 
= GetXMin(); 
 192     double oldy 
= GetYMin(); 
 193     double w 
= m_bbox
.GetWidth(); 
 194     double h 
= m_bbox
.GetHeight(); 
 198     double newx
=GetXMin(); 
 199     double newy
=GetYMin(); 
 201     double leftu
,rightu
,bottomu
,topu 
; 
 202     leftu   
= wxMin (oldx
, newx 
) ; 
 203     rightu  
= wxMax (oldx 
+ w
, newx 
+ w
) ; 
 204     topu    
= wxMin (oldy
, newy
) ; 
 205     bottomu 
= wxMax (oldy 
+ h
, newy 
+ h
) ; 
 207     if ( rightu 
- leftu 
< 2*w 
&& bottomu 
- topu 
< 2*h 
) 
 209         m_admin
->Update( this,leftu
, topu
, rightu 
- leftu
, bottomu 
- topu
); 
 213         m_admin
->Update( this, oldx
, oldy
, w
, h 
); 
 214         m_admin
->Update( this, newx
, newy
, w
, h 
); 
 219 void wxCanvasObject::DragStart() 
 221     if (m_dragmode 
== wxDRAG_RECTANGLE
) 
 223         this->SetVisible(FALSE
); 
 224         wxTransformMatrix help
; 
 225         double x 
= GetXMin(); 
 226         double y 
= GetYMin(); 
 227         double w 
= m_bbox
.GetWidth(); 
 228         double h 
= m_bbox
.GetHeight(); 
 229         m_admin
->Update( this, x
, y
, w
, h 
); 
 230         m_admin
->UpdateNow(); 
 232         wxRect recold
=GetAbsoluteArea(help
); 
 233         wxClientDC 
dc(m_admin
->GetActive()); 
 234         dc
.SetPen(*wxBLACK_PEN
); 
 235         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 236         dc
.SetLogicalFunction(wxINVERT
); 
 237         dc
.DrawRectangle(recold
); 
 238         dc
.SetBrush(wxNullBrush
); 
 239         dc
.SetPen(wxNullPen
); 
 241     else if (m_dragmode 
!= wxDRAG_REDRAW
) 
 243         this->SetVisible(FALSE
); 
 244         wxTransformMatrix help
; 
 245         double x 
= GetXMin(); 
 246         double y 
= GetYMin(); 
 247         double w 
= m_bbox
.GetWidth(); 
 248         double h 
= m_bbox
.GetHeight(); 
 250         wxRect recnew
=GetAbsoluteArea(help
); 
 252          //redraw in buffer what should be there without this object 
 253         m_admin
->Update( this, x
, y
, w
, h 
); 
 254         m_admin
->GetActive()->Freeze(); 
 256         //save the drawing (without the object itself to a bitmap) 
 257         m_atnewpos 
= wxBitmap(recnew
.width
,recnew
.height
); 
 259         dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer()); 
 261         tmp
.SelectObject(m_atnewpos
); 
 262         tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 263         tmp
.SelectObject(wxNullBitmap
); 
 264         dcm
.SelectObject(wxNullBitmap
); 
 269 void wxCanvasObject::DragRelative( double x
, double y
) 
 271     if (m_dragmode 
== wxDRAG_RECTANGLE
) 
 273         wxTransformMatrix help
; 
 275         wxRect recold
=GetAbsoluteArea(help
); 
 279         wxRect recnew
=GetAbsoluteArea(help
); 
 281         wxClientDC 
dc(m_admin
->GetActive()); 
 282         dc
.SetPen(*wxBLACK_PEN
); 
 283         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 284         dc
.SetLogicalFunction(wxINVERT
); 
 285         dc
.DrawRectangle(recold
); 
 286         dc
.DrawRectangle(recnew
); 
 287         dc
.SetBrush(wxNullBrush
); 
 288         dc
.SetPen(wxNullPen
); 
 290     else if (m_dragmode 
!= wxDRAG_REDRAW
) 
 292         wxClientDC 
dc(m_admin
->GetActive()); 
 295         wxTransformMatrix help
; 
 296         wxRect recold
=GetAbsoluteArea(help
); 
 298         //restore what was there (without the object itself) 
 300         dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer()); 
 301         tmp
.SelectObject(m_atnewpos
); 
 302         dcm
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&tmp
,0,0,wxCOPY
,FALSE
); 
 306         wxRect recnew
=GetAbsoluteArea(help
); 
 308         //save the contents of the buffer at the new position 
 309         tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 310         tmp
.SelectObject(wxNullBitmap
); 
 312         //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew ); 
 314         this->SetVisible(TRUE
); 
 315         //redraw object into the buffer 
 316         m_admin
->GetActive()->SetDC(&dcm
); 
 317         Render(&help
,recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
); 
 319         //draw the union or seperate to the canvas 
 320         double leftu
,rightu
,bottomu
,topu 
; 
 321         leftu   
= wxMin (recold
.x
, recnew
.x 
) ; 
 322         rightu  
= wxMax (recold
.x 
+ recold
.width
, recnew
.x 
+ recnew
.width 
) ; 
 323         topu    
= wxMin (recold
.y
, recnew
.y
) ; 
 324         bottomu 
= wxMax (recold
.y 
+ recold
.height
, recnew
.y 
+ recnew
.height
) ; 
 326         if ( rightu 
- leftu 
< 2*recold
.width 
&& bottomu 
- topu 
< 2*recold
.height
) 
 328             dc
.Blit(leftu
,topu
,rightu 
- leftu
,bottomu 
- topu
,&dcm
,leftu
,topu
,wxCOPY
,FALSE
); 
 333             //first redraw what should be at the old position in the canvas 
 334             dc
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&dcm
,recold
.x
,recold
.y
,wxCOPY
,FALSE
); 
 335             //blit the new position of the object to the canvas 
 336             dc
.Blit(recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 338         dcm
.SelectObject(wxNullBitmap
); 
 339         this->SetVisible(FALSE
); 
 346 void wxCanvasObject::DragEnd() 
 348     m_atnewpos 
= wxBitmap(0,0); 
 349     m_admin
->GetActive()->Thaw(); 
 350     this->SetVisible(TRUE
); 
 351     double x 
= GetXMin(); 
 352     double y 
= GetYMin(); 
 353     double w 
= m_bbox
.GetWidth(); 
 354     double h 
= m_bbox
.GetHeight(); 
 355     m_admin
->Update( this, x
, y
, w
, h 
); 
 356     m_admin
->UpdateNow(); 
 359 wxCanvasObject
* wxCanvasObject::IsHitWorld( double x
, double y
, double margin 
) 
 361     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 362         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 363         (y 
>= m_bbox
.GetMinY()-margin
) && 
 364         (y 
<= m_bbox
.GetMaxY()+margin
)) 
 369     return (wxCanvasObject
*) NULL
; 
 372 wxCanvasObject
* wxCanvasObject::Contains( wxCanvasObject
* obj 
) 
 377     return (wxCanvasObject
*) NULL
; 
 380 void wxCanvasObject::CaptureMouse() 
 382     m_admin
->GetActive()->SetCaptureMouse( this ); 
 385 void wxCanvasObject::ReleaseMouse() 
 387     m_admin
->GetActive()->SetCaptureMouse( NULL 
); 
 390 bool wxCanvasObject::IsCapturedMouse() 
 392     return (m_admin
->GetActive()->GetCaptured() == this); 
 396 void wxCanvasObject::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 400 void wxCanvasObject::CalcBoundingBox() 
 404 void wxCanvasObject::WriteSVG( wxTextOutputStream 
&stream 
) 
 408 //---------------------------------------------------------------------------- 
 409 // wxCanvasObjectGroup 
 410 //---------------------------------------------------------------------------- 
 412 IMPLEMENT_CLASS(wxCanvasObjectGroup
, wxCanvasObject
) 
 414 wxCanvasObjectGroup::wxCanvasObjectGroup(double x
, double y
) 
 416     lworld
.Translate(x
,y
); 
 417     //no objects make the bounding box the x,y and take care of it later 
 421 wxCanvasObjectGroup::~wxCanvasObjectGroup() 
 425 void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler 
*handler
) 
 427     wxCanvasObject::PushEventHandler(handler
); 
 428     wxNode 
*node 
= m_objects
.First(); 
 431         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 433         obj
->PushEventHandler(handler
); 
 439 wxEvtHandler 
*wxCanvasObjectGroup::PopEventHandler(bool deleteHandler
) 
 441     wxNode 
*node 
= m_objects
.First(); 
 444         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 446         obj
->PopEventHandler(deleteHandler
); 
 450     return wxCanvasObject::PopEventHandler(deleteHandler
); 
 453 void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler 
*handler
) 
 455     wxCanvasObject::AppendEventHandler(handler
); 
 456     wxNode 
*node 
= m_objects
.First(); 
 459         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 461         obj
->AppendEventHandler(handler
); 
 467 wxEvtHandler 
*wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler
) 
 469     wxNode 
*node 
= m_objects
.First(); 
 472         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 474         obj
->RemoveLastEventHandler(deleteHandler
); 
 478     return wxCanvasObject::RemoveLastEventHandler(deleteHandler
); 
 481 void wxCanvasObjectGroup::TransLate( double x
, double y 
) 
 483     lworld
.Translate(x
,y
); 
 487 void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin
* admin
) 
 490     wxNode 
*node 
= m_objects
.First(); 
 493         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 495         obj
->SetAdmin(admin
); 
 501 void wxCanvasObjectGroup::DeleteContents( bool flag
) 
 503     m_objects
.DeleteContents( flag 
); 
 504     m_bbox
.SetValid(FALSE
); 
 508 void wxCanvasObjectGroup::Prepend( wxCanvasObject
* obj 
) 
 510     m_objects
.Insert( obj 
); 
 511     if (m_objects
.First()) 
 513         m_bbox
.Expand(obj
->GetBbox()); 
 517         m_bbox
.SetValid(FALSE
); 
 522 void wxCanvasObjectGroup::Append( wxCanvasObject
* obj 
) 
 524     m_objects
.Append( obj 
); 
 525     if (m_objects
.First()) 
 527         m_bbox
.Expand(obj
->GetBbox()); 
 531         m_bbox
.SetValid(FALSE
); 
 536 void wxCanvasObjectGroup::Insert( size_t before
, wxCanvasObject
* obj 
) 
 538     m_objects
.Insert( before
, obj 
); 
 539     m_bbox
.SetValid(FALSE
); 
 540     if (m_objects
.First()) 
 542         m_bbox
.Expand(obj
->GetBbox()); 
 546         m_bbox
.SetValid(FALSE
); 
 551 void wxCanvasObjectGroup::Remove( wxCanvasObject
* obj 
) 
 553     m_objects
.DeleteObject( obj 
); 
 554     m_bbox
.SetValid(FALSE
); 
 558 void wxCanvasObjectGroup::CalcBoundingBox() 
 560     m_bbox
.SetValid(FALSE
); 
 561     wxNode 
*node 
= m_objects
.First(); 
 564         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 567         obj
->CalcBoundingBox(); 
 572         m_bbox
.Expand( tmp 
); 
 577 void wxCanvasObjectGroup::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height 
) 
 579     if (!m_visible
) return; 
 581     wxTransformMatrix backup 
= *cworld
; 
 584     wxNode 
*node 
= m_objects
.First(); 
 590     wxRect absarea
=GetAbsoluteArea(*cworld
); 
 591     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 592     dc
->SetPen(*wxBLACK_PEN
); 
 593     dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
 594     dc
->DrawRectangle( absarea
.x 
, absarea
.y 
, absarea
.width 
, absarea
.height 
); 
 595     dc
->SetBrush(wxNullBrush
); 
 596     dc
->SetPen(wxNullPen
); 
 598     //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently 
 600     if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) && 
 601             wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height ) 
 607     // cycle through all objects 
 610         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 612         if (!obj
->IsControl() && obj
->GetVisible()) 
 615             //get area at the absolute position 
 616             wxRect absareaobject 
= obj
->GetAbsoluteArea(*cworld
); 
 618             // If we have 10.000 objects, we will go through 
 619             // this 10.000 times for each update, so we have 
 620             // to optimise carefully. 
 621             int clip_x 
= absareaobject
.x
; 
 622             int clip_width 
= absareaobject
.width
; 
 625                 clip_width 
-= x
-clip_x
; 
 630                 if (clip_x 
+ clip_width 
> x 
+ width
) 
 631                     clip_width 
= x
+width
-clip_x
; 
 635                     int clip_y 
= absareaobject
.y
; 
 636                     int clip_height 
= absareaobject
.height
; 
 639                         clip_height 
-= y
-clip_y
; 
 644                         if (clip_y 
+ clip_height 
> y 
+ height
) 
 645                             clip_height 
= y
+height
-clip_y
; 
 649                             obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height 
); 
 661 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream 
&stream 
) 
 665 wxCanvasObject
* wxCanvasObjectGroup::IsHitWorld( double x
, double y
, double margin 
) 
 667     //KKKfirst check if within bbox 
 668     //will only work if they are always uptodate 
 669     //if (!m_bbox.PointInBox(x,y,margin)) 
 670     //    return (wxCanvasObject*) NULL; 
 672     wxTransformMatrix inverse 
=  lworld
; 
 675     inverse
.TransformPoint(x
,y
,xh
,yh
); 
 677     wxCanvasObject 
*obj
=0; 
 678     wxNode 
*node 
= m_objects
.Last(); 
 681         obj
=(wxCanvasObject
*) node
->Data(); 
 683         if (!obj
->IsControl() ) 
 685             if (obj
->IsHitWorld(xh
,yh
,margin
)) 
 690         node 
= node
->Previous(); 
 693     return (wxCanvasObject
*) NULL
; 
 696 wxCanvasObject
* wxCanvasObjectGroup::Contains( wxCanvasObject
* obj 
) 
 698     wxCanvasObject
* cobj
; 
 699     wxNode 
*node 
= m_objects
.First(); 
 702         cobj
=(wxCanvasObject
*) node
->Data(); 
 704         if (cobj
->Contains(obj
)) 
 711     return (wxCanvasObject
*) NULL
; 
 714 int wxCanvasObjectGroup::IndexOf( wxCanvasObject
* obj 
) 
 716     return m_objects
.IndexOf( obj 
); 
 719 //---------------------------------------------------------------------------- 
 721 //---------------------------------------------------------------------------- 
 723 IMPLEMENT_CLASS(wxCanvasObjectRef
, wxCanvasObject
) 
 725 wxCanvasObjectRef::wxCanvasObjectRef(double x
, double y
, wxCanvasObject
* obj
) 
 728     lworld
.Translate(x
,y
); 
 731     m_bbox
.SetValid(FALSE
); 
 735     m_bbox
.Expand( tmp 
); 
 738 void wxCanvasObjectRef::PushEventHandler(wxEvtHandler 
*handler
) 
 740     wxCanvasObject::PushEventHandler(handler
); 
 741     m_obj
->PushEventHandler(handler
); 
 744 wxEvtHandler 
*wxCanvasObjectRef::PopEventHandler(bool deleteHandler
) 
 746     m_obj
->PopEventHandler(deleteHandler
); 
 747     return wxCanvasObject::PopEventHandler(deleteHandler
); 
 750 void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler 
*handler
) 
 752     wxCanvasObject::AppendEventHandler(handler
); 
 753     m_obj
->AppendEventHandler(handler
); 
 756 wxEvtHandler 
*wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler
) 
 758     m_obj
->RemoveLastEventHandler(deleteHandler
); 
 759     return wxCanvasObject::RemoveLastEventHandler(deleteHandler
); 
 762 void wxCanvasObjectRef::TransLate( double x
, double y 
) 
 764     lworld
.Translate(x
,y
); 
 768 wxCanvasObject
* wxCanvasObjectRef::Contains( wxCanvasObject
* obj 
) 
 770     if (obj 
== this || m_obj
->Contains(obj
)) 
 773     return (wxCanvasObject
*) NULL
; 
 777 void wxCanvasObjectRef::SetRotation(double rotation
) 
 779     lworld
.SetRotation(rotation
); 
 783 void wxCanvasObjectRef::SetScale(double scalex
,double scaley
) 
 785     lworld
.Scale(scalex
,scaley
,lworld
.GetValue(2,0),lworld
.GetValue(2,1)); 
 789 void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin
* admin
) 
 792     m_obj
->SetAdmin(admin
); 
 795 void wxCanvasObjectRef::CalcBoundingBox() 
 797     m_bbox
.SetValid(FALSE
); 
 798     m_obj
->CalcBoundingBox(); 
 801     tmp
=m_obj
->GetBbox(); 
 803     m_bbox
.Expand( tmp 
); 
 806 void wxCanvasObjectRef::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height 
) 
 808     if (!m_visible
) return; 
 810     //get the absolute area (without the local matrix included) 
 811     //the boundingbox is relative to the parent. 
 812     wxRect absarea
=GetAbsoluteArea(*cworld
); 
 814     wxTransformMatrix backup 
= *cworld
; 
 818     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 819     dc
->SetPen(*wxBLACK_PEN
); 
 820     dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
 821     dc
->DrawRectangle( absarea
.x 
, absarea
.y 
, absarea
.width 
, absarea
.height 
); 
 822     dc
->SetBrush(wxNullBrush
); 
 823     dc
->SetPen(wxNullPen
); 
 826     int clip_x 
= absarea
.x
; 
 827     int clip_width 
= absarea
.width
; 
 830         clip_width 
-= x
-clip_x
; 
 835         if (clip_x 
+ clip_width 
> x 
+ width
) 
 836             clip_width 
= x
+width
-clip_x
; 
 840             int clip_y 
= absarea
.y
; 
 841             int clip_height 
= absarea
.height
; 
 844                 clip_height 
-= y
-clip_y
; 
 849                 if (clip_y 
+ clip_height 
> y 
+ height
) 
 850                     clip_height 
= y
+height
-clip_y
; 
 853                     m_obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height 
); 
 861 void wxCanvasObjectRef::WriteSVG( wxTextOutputStream 
&stream 
) 
 865 wxCanvasObject
* wxCanvasObjectRef::IsHitWorld( double x
, double y
, double margin 
) 
 867     //KKKfirst check if within bbox 
 868     //will only work if they are always uptodate 
 869     //if (!m_bbox.PointInBox(x,y,margin)) 
 870     //    return (wxCanvasObject*) NULL; 
 872     wxTransformMatrix inverse 
=  lworld
; 
 875     inverse
.TransformPoint(x
,y
,xh
,yh
); 
 877     if (m_obj
->IsHitWorld(xh
,yh
,margin
)) 
 880     return (wxCanvasObject
*) NULL
; 
 885 //---------------------------------------------------------------------------- 
 887 //---------------------------------------------------------------------------- 
 889 IMPLEMENT_CLASS(wxCanvasRect
, wxCanvasObject
) 
 891 wxCanvasRect::wxCanvasRect( double x
, double y
, double w
, double h 
, double radius 
) 
 900     m_brush 
= *wxBLACK_BRUSH
; 
 901     m_pen 
= *wxTRANSPARENT_PEN
; 
 905 void wxCanvasRect::TransLate( double x
, double y 
) 
 912 void wxCanvasRect::CalcBoundingBox() 
 914     m_bbox
.SetMin( m_x 
, m_y
); 
 915     m_bbox
.SetMax( m_x 
+ m_width 
,m_y 
+ m_height 
); 
 917     //include the pen width also 
 918 //KKK    m_bbox.EnLarge(m_pen.GetWidth()+m_radius); 
 919     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
 922 void wxCanvasRect::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 924     if (!m_visible
) return; 
 926     if (cworld
->GetRotation()) 
 928         wxPoint 
*cpoints 
= new wxPoint
[4]; 
 931         cworld
->TransformPoint( m_x
, m_y
, x
, y 
); 
 932         cpoints
[0].x 
= m_admin
->LogicalToDeviceX(x
); 
 933         cpoints
[0].y 
= m_admin
->LogicalToDeviceY(y
); 
 934         cworld
->TransformPoint( m_x 
, m_y 
+ m_height
, x
, y 
); 
 935         cpoints
[1].x 
= m_admin
->LogicalToDeviceX(x
); 
 936         cpoints
[1].y 
= m_admin
->LogicalToDeviceY(y
); 
 937         cworld
->TransformPoint( m_x 
+ m_width
, m_y 
+ m_height
, x
, y 
); 
 938         cpoints
[2].x 
= m_admin
->LogicalToDeviceX(x
); 
 939         cpoints
[2].y 
= m_admin
->LogicalToDeviceY(y
); 
 940         cworld
->TransformPoint( m_x 
+ m_width
, m_y 
, x
, y 
); 
 941         cpoints
[3].x 
= m_admin
->LogicalToDeviceX(x
); 
 942         cpoints
[3].y 
= m_admin
->LogicalToDeviceY(y
); 
 944         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 945         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
 946         dc
->SetBrush(m_brush
); 
 947         int pw
=m_pen
.GetWidth(); 
 948         m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 950         dc
->DrawPolygon(4, cpoints
, 0,0,wxWINDING_RULE
); 
 952         dc
->SetBrush(wxNullBrush
); 
 953         dc
->SetPen(wxNullPen
); 
 954         dc
->DestroyClippingRegion(); 
 959         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 960         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
 961         dc
->SetBrush(m_brush
); 
 962         int pw
=m_pen
.GetWidth(); 
 963         m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 965         //yes the whole not only the clipping region, because we have a pen also 
 966         int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
 967         int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
 968         int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
 969         int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
 970         int r 
= m_admin
->LogicalToDeviceYRel( m_radius 
); 
 971         if (w 
> 0 && w 
< 1) w
=1; 
 972         if (w 
< 0 && w 
> -1) w
=-1; 
 973         if (h 
> 0 && h 
< 1) h
=1; 
 974         if (h 
< 0 && h 
> -1) h
=-1; 
 976             dc
->DrawRoundedRectangle( x
,y
,w
,h
,r
); 
 978             dc
->DrawRectangle( x
,y
,w
,h
); 
 979         dc
->SetBrush(wxNullBrush
); 
 980         dc
->SetPen(wxNullPen
); 
 981         dc
->DestroyClippingRegion(); 
 986 void wxCanvasRect::WriteSVG( wxTextOutputStream 
&stream 
) 
 990 //---------------------------------------------------------------------------- 
 992 //---------------------------------------------------------------------------- 
 994 wxCanvasCircle::wxCanvasCircle( double x
, double y
, double radius 
) 
1001     m_brush 
= *wxBLACK_BRUSH
; 
1002     m_pen 
= *wxTRANSPARENT_PEN
; 
1006 void wxCanvasCircle::TransLate( double x
, double y 
) 
1013 void wxCanvasCircle::CalcBoundingBox() 
1015     m_bbox
.SetMin( m_x
-m_radius 
, m_y
-m_radius 
); 
1016     m_bbox
.SetMax( m_x
+m_radius 
, m_y
+m_radius 
); 
1018     //include the pen width also 
1019     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1022 void wxCanvasCircle::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1024     if (!m_visible
) return; 
1026     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1027     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1028     dc
->SetBrush(m_brush
); 
1029     int pw
=m_pen
.GetWidth(); 
1030     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1032     //yes the whole not only the clipping region, because we have a pen also 
1033     //and rotation on a circle is not important so only a shift with cworld 
1034     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1035     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1036     int radius 
= m_admin
->LogicalToDeviceXRel( m_radius 
); 
1037     if (radius 
< 1) radius
=1; 
1038     dc
->DrawCircle( x
,y
,radius
); 
1039     dc
->SetBrush(wxNullBrush
); 
1040     dc
->SetPen(wxNullPen
); 
1041     dc
->DestroyClippingRegion(); 
1045 void wxCanvasCircle::WriteSVG( wxTextOutputStream 
&stream 
) 
1049 wxCanvasObject
* wxCanvasCircle::IsHitWorld( double x
, double y
, double margin 
) 
1051     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1052         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1053         (y 
>= m_bbox
.GetMinY()-margin
) && 
1054         (y 
<= m_bbox
.GetMaxY()+margin
) 
1057         if (m_radius
+m_pen
.GetWidth()/2+margin 
> sqrt(pow(m_x
-x
,2)+pow(m_y
-y
,2))) 
1060             return (wxCanvasObject
*) NULL
; 
1062     return (wxCanvasObject
*) NULL
; 
1065 //---------------------------------------------------------------------------- 
1067 //---------------------------------------------------------------------------- 
1069 wxCanvasEllipse::wxCanvasEllipse( double x
, double y
, double width
, double height 
) 
1077     m_brush 
= *wxBLACK_BRUSH
; 
1078     m_pen 
= *wxTRANSPARENT_PEN
; 
1082 void wxCanvasEllipse::TransLate( double x
, double y 
) 
1089 void wxCanvasEllipse::CalcBoundingBox() 
1091     m_bbox
.SetMin( m_x
, m_y 
); 
1092     m_bbox
.SetMax( m_x
+m_width 
, m_y
+m_height 
); 
1094     //include the pen width also 
1095     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1098 void wxCanvasEllipse::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1100     if (!m_visible
) return; 
1102     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1103     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1104     dc
->SetBrush(m_brush
); 
1105     int pw
=m_pen
.GetWidth(); 
1106     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1108     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1109     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1110     int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1111     int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1112     if (w 
> 0 && w 
< 1) w
=1; 
1113     if (w 
< 0 && w 
> -1) w
=-1; 
1114     if (h 
> 0 && h 
< 1) h
=1; 
1115     if (h 
< 0 && h 
> -1) h
=-1; 
1116     dc
->DrawEllipse( x
,y
,w
,h
); 
1117     dc
->SetBrush(wxNullBrush
); 
1118     dc
->SetPen(wxNullPen
); 
1119     dc
->DestroyClippingRegion(); 
1123 void wxCanvasEllipse::WriteSVG( wxTextOutputStream 
&stream 
) 
1127 wxCanvasObject
* wxCanvasEllipse::IsHitWorld( double x
, double y
, double margin 
) 
1129     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1130         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1131         (y 
>= m_bbox
.GetMinY()-margin
) && 
1132         (y 
<= m_bbox
.GetMaxY()+margin
) 
1135         double a
=(m_width
+m_pen
.GetWidth())/2+margin 
; 
1136         double b
=(m_height
+m_pen
.GetWidth())/2+margin
; 
1137         double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2); 
1141             return (wxCanvasObject
*) NULL
; 
1143     return (wxCanvasObject
*) NULL
; 
1146 //---------------------------------------------------------------------------- 
1147 // wxCanvasEllipticArc 
1148 //---------------------------------------------------------------------------- 
1150 wxCanvasEllipticArc::wxCanvasEllipticArc( double x
, double y
, double width
, double height
, double start
, double end 
) 
1160     m_brush 
= *wxBLACK_BRUSH
; 
1161     m_pen 
= *wxTRANSPARENT_PEN
; 
1165 void wxCanvasEllipticArc::TransLate( double x
, double y 
) 
1172 void wxCanvasEllipticArc::CalcBoundingBox() 
1174     m_bbox
.SetMin( m_x
, m_y 
); 
1175     m_bbox
.SetMax( m_x
+m_width 
, m_y
+m_height 
); 
1177     //include the pen width also 
1178     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1181 void wxCanvasEllipticArc::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1183     if (!m_visible
) return; 
1185     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1186     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1187     dc
->SetBrush(m_brush
); 
1188     int pw
=m_pen
.GetWidth(); 
1189     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1191     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1192     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1193     int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1194     int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1195     if (w 
> 0 && w 
< 1) w
=1; 
1196     if (w 
< 0 && w 
> -1) w
=-1; 
1197     if (h 
> 0 && h 
< 1) h
=1; 
1198     if (h 
< 0 && h 
> -1) h
=-1; 
1199     if (m_admin
->GetActive()->GetYaxis()) 
1200         dc
->DrawEllipticArc( x
,y
,w
,h
,-m_end
,-m_start
); 
1202         dc
->DrawEllipticArc( x
,y
,w
,h
,m_start
,m_end
); 
1203     dc
->SetBrush(wxNullBrush
); 
1204     dc
->SetPen(wxNullPen
); 
1205     dc
->DestroyClippingRegion(); 
1209 void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream 
&stream 
) 
1213 wxCanvasObject
* wxCanvasEllipticArc::IsHitWorld( double x
, double y
, double margin 
) 
1215     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1216         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1217         (y 
>= m_bbox
.GetMinY()-margin
) && 
1218         (y 
<= m_bbox
.GetMaxY()+margin
) 
1221         double a
=(m_width
+m_pen
.GetWidth())/2+margin 
; 
1222         double b
=(m_height
+m_pen
.GetWidth())/2+margin
; 
1223         double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2); 
1227             return (wxCanvasObject
*) NULL
; 
1229     return (wxCanvasObject
*) NULL
; 
1232 //---------------------------------------------------------------------------- 
1234 //---------------------------------------------------------------------------- 
1236 wxCanvasLine::wxCanvasLine( double x1
, double y1
, double x2
, double y2 
) 
1244     m_pen 
= *wxBLACK_PEN
; 
1248 void wxCanvasLine::TransLate( double x
, double y 
) 
1257 void wxCanvasLine::CalcBoundingBox() 
1259     m_bbox
.SetMin( m_x1 
, m_y1
); 
1260     m_bbox
.SetMax( m_x2 
, m_y2
); 
1262     //include the pen width also 
1263     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1266 void wxCanvasLine::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1268     if (!m_visible
) return; 
1271     cworld
->TransformPoint( m_x1
, m_y1
, x1
, y1 
); 
1272     cworld
->TransformPoint( m_x2
, m_y2
, x2
, y2 
); 
1273     x1 
= m_admin
->LogicalToDeviceX( x1 
); 
1274     y1 
= m_admin
->LogicalToDeviceY( y1 
); 
1275     x2 
= m_admin
->LogicalToDeviceX( x2 
); 
1276     y2 
= m_admin
->LogicalToDeviceY( y2 
); 
1278     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1279     dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height 
); 
1280     int pw
=m_pen
.GetWidth(); 
1281     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1282     dc
->SetPen( m_pen 
); 
1283     dc
->DrawLine( x1
, y1
, x2
, y2 
); 
1285     dc
->DestroyClippingRegion(); 
1289 void wxCanvasLine::WriteSVG( wxTextOutputStream 
&stream 
) 
1294 wxCanvasObject
* wxCanvasLine::IsHitWorld( double x
, double y
, double margin 
) 
1296     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1297         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1298         (y 
>= m_bbox
.GetMinY()-margin
) && 
1299         (y 
<= m_bbox
.GetMaxY()+margin
) 
1302         wxLine 
line1(m_x1
,m_y1
,m_x2
,m_y2
); 
1303         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
1305         if (line1
.PointInLine(P
,distance
,m_pen
.GetWidth()/2+margin
) == R_IN_AREA
) 
1308             return (wxCanvasObject
*) NULL
; 
1310     return (wxCanvasObject
*) NULL
; 
1313 //---------------------------------------------------------------------------- 
1315 //---------------------------------------------------------------------------- 
1317 wxCanvasImage::wxCanvasImage( const wxImage 
&image
, double x
, double y
, double w
, double h 
) 
1327     m_orgw 
= m_image
.GetWidth(); 
1328     m_orgh 
= m_image
.GetHeight(); 
1334 void wxCanvasImage::SetPosXY( double x
, double y
) 
1341 void wxCanvasImage::TransLate( double x
, double y 
) 
1348 void wxCanvasImage::CalcBoundingBox() 
1350     m_bbox
.SetMin( m_x
, m_y 
); 
1351     m_bbox
.SetMax( m_x 
+ m_width
, m_y 
+ m_height 
); 
1354 void wxCanvasImage::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1356     if (!m_visible
) return; 
1360     tmparea
.x 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX()); 
1361     tmparea
.y 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY()); 
1362     tmparea
.width 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ); 
1363     tmparea
.height 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ); 
1367     cworld
->TransformPoint( m_x
, m_y
, x
, y 
); 
1368     x 
= m_admin
->LogicalToDeviceX(x
); 
1369     y 
= m_admin
->LogicalToDeviceY(y
); 
1373     if (  m_orgw
*5 < m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()  ) || 
1374           m_orgw
/5 > m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()  ) || 
1375           m_orgh
*5 < m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) || 
1376           m_orgh
/5 > m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) 
1379         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1380         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1381         dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
1382         dc
->SetPen(*wxBLACK_PEN
); 
1383         //yes the whole not only the clipping region, because we have a pen also 
1384         int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1385         int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1386         int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1387         int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1390         dc
->DrawRectangle( x
,y
,w
,h
); 
1391         dc
->SetBrush(wxNullBrush
); 
1392         dc
->SetPen(wxNullPen
); 
1393         dc
->DestroyClippingRegion(); 
1398     bool is_cashed 
= FALSE
; 
1400     if (m_cImage
.Ok() && (m_cW 
== m_bbox
.GetWidth()) && (m_cH 
== m_bbox
.GetHeight())) 
1408         if ((m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) == m_image
.GetWidth()) && 
1409             (m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) == m_image
.GetHeight())) 
1415             tmp 
= m_image
.Scale( m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()), 
1416                                  m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight()) ); 
1419         // create cached image 
1421         m_cW 
= tmp
.GetWidth(); 
1422         m_cH 
= tmp
.GetHeight(); 
1425 //    wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y)); 
1430     if (m_cBitmap
.Ok() && is_cashed 
&& (m_cR 
== cworld
->GetRotation())) 
1436         if (cworld
->GetRotation()) 
1437             tmp 
= tmp
.Rotate(-cworld
->GetRotation()/180.0 * pi
, centr
, TRUE
, NULL 
); 
1439         bmp 
= wxBitmap(tmp
); 
1441         // create cached bitmap 
1443         m_cR 
= cworld
->GetRotation(); 
1446     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1449     if (cworld
->GetRotation()> 0) 
1451         centr2
.x
= (int) (x
+m_height
*sin(-cworld
->GetRotation()/180.0 * pi
)); 
1457         centr2
.y
= (int) (y
-m_width
*sin(-cworld
->GetRotation()/180.0 * pi
)); 
1460     if (cworld
->GetRotation() != 0) 
1462         //TODO clipping not right 
1463             dc
->DrawBitmap(bmp
,centr2
,TRUE 
); 
1464 //        dc->DrawPoint(centr2); 
1465 //        dc->DrawPoint(x,y); 
1469         dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height 
); 
1470         dc
->DrawBitmap( bmp
, x
, y
, TRUE 
); 
1471         dc
->DestroyClippingRegion(); 
1475 void wxCanvasImage::WriteSVG( wxTextOutputStream 
&stream 
) 
1480 //---------------------------------------------------------------------------- 
1482 //---------------------------------------------------------------------------- 
1484 wxCanvasControl::wxCanvasControl( wxWindow 
*control 
) 
1488     m_control 
= control
; 
1492 double wxCanvasControl::GetPosX() 
1495     m_control
->GetPosition( &x
, &y 
); 
1496     return m_admin
->DeviceToLogicalX(x
); 
1499 double wxCanvasControl::GetPosY() 
1502     m_control
->GetPosition( &x
, &y 
); 
1503     return m_admin
->DeviceToLogicalY(y
); 
1506 void wxCanvasControl::SetPosXY( double x
, double y
) 
1508     int xd 
= m_admin
->LogicalToDeviceX(x
); 
1509     int yd 
= m_admin
->LogicalToDeviceY(y
); 
1510     m_control
->Move(xd
,yd
); 
1514 void wxCanvasControl::TransLate( double x
, double y 
) 
1517     m_control
->GetPosition( &xdo
, &ydo 
); 
1518     int xd 
= m_admin
->LogicalToDeviceX(x
)-xdo
; 
1519     int yd 
= m_admin
->LogicalToDeviceY(y
)-ydo
; 
1520     m_control
->Move(xd
,yd
); 
1524 wxCanvasControl::~wxCanvasControl() 
1526     m_control
->Destroy(); 
1529 void wxCanvasControl::CalcBoundingBox() 
1533     m_control
->GetSize( &tmparea
.width
, &tmparea
.height 
); 
1534     m_control
->GetPosition( &tmparea
.x
, &tmparea
.y 
); 
1536     m_bbox
.SetMin( tmparea
.x 
, tmparea
.y
); 
1537     m_bbox
.SetMax( tmparea
.x 
+ tmparea
.width 
, tmparea
.y 
+ tmparea
.height
); 
1541 void wxCanvasControl::MoveRelative( double x
, double y 
) 
1543     m_control
->Move( m_admin
->LogicalToDeviceX(x
),  m_admin
->LogicalToDeviceX(y
) ); 
1546 //---------------------------------------------------------------------------- 
1548 //---------------------------------------------------------------------------- 
1560 wxCanvasText::wxCanvasText( const wxString 
&text
, double x
, double y
, const wxString 
&fontFile
, int size 
) 
1564     m_fontFileName 
= fontFile
; 
1577     wxFaceData 
*data 
= new wxFaceData
; 
1580     int error 
= FT_New_Face( g_freetypeLibrary
, 
1585     error 
= FT_Set_Char_Size( data
->m_face
, 
1594 wxCanvasText::~wxCanvasText() 
1597     wxFaceData 
*data 
= (wxFaceData
*) m_faceData
; 
1601     if (m_alpha
) delete [] m_alpha
; 
1604 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue 
) 
1611 void wxCanvasText::SetFlag( int flag 
) 
1616 void wxCanvasText::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1618     if (!m_visible
) return; 
1621     tmparea
.x 
= m_admin
->LogicalToDeviceX( m_bbox
.GetMinX()); 
1622     tmparea
.y 
= m_admin
->LogicalToDeviceY( m_bbox
.GetMinY()); 
1623     tmparea
.width 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ); 
1624     tmparea
.height 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ); 
1626     m_alpha 
= new unsigned char[tmparea
.width
*tmparea
.height
]; 
1627     memset( m_alpha
, 0, tmparea
.width
*tmparea
.height 
); 
1629     if (!m_alpha
) return; 
1632     FT_Face face 
= ((wxFaceData
*)m_faceData
)->m_face
; 
1633     FT_GlyphSlot slot 
= face
->glyph
; 
1637     for (int n 
= 0; n 
< (int)m_text
.Len(); n
++) 
1639         FT_UInt index 
= FT_Get_Char_Index( face
, m_text
[(unsigned int)n
] ); 
1641         int error 
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT 
); 
1642         if (error
) continue; 
1644         error 
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal 
); 
1645         if (error
) continue; 
1647         FT_Bitmap 
*bitmap 
= &slot
->bitmap
; 
1648         unsigned char* buffer 
= bitmap
->buffer
; 
1649         for (int y 
= 0; y 
< bitmap
->rows
; y
++) 
1650             for (int x 
= 0; x 
< bitmap
->width
; x
++) 
1652                 unsigned char alpha 
= buffer
[ y
*bitmap
->pitch 
+ x 
]; 
1653                 if (alpha 
== 0) continue; 
1655                 int xx 
= pen_x 
+ slot
->bitmap_left 
+ x
; 
1656                 int yy 
= pen_y 
- slot
->bitmap_top 
+ y
; 
1657                 m_alpha
[ yy 
* tmparea
.width 
+ xx 
] = alpha
; 
1660         pen_x 
+= slot
->advance
.x 
>> 6; 
1661         pen_y 
+= slot
->advance
.y 
>> 6; 
1665     wxBitmap 
*bitmap 
= m_admin
->GetActive()->GetBuffer(); 
1666     wxRect 
sub_rect( clip_x
, clip_y
, clip_width
, clip_height 
); 
1667     wxBitmap 
sub_bitmap( bitmap
->GetSubBitmap( sub_rect 
) ); 
1669     wxImage 
image( sub_bitmap
.ConvertToImage() ); 
1671     // local coordinates 
1672     int start_x 
= clip_x 
- tmparea
.x
; 
1673     int end_x 
= clip_width 
+ start_x
; 
1674     int start_y 
= clip_y 
- tmparea
.y
; 
1675     int end_y 
= clip_height 
+ start_y
; 
1677     for (int y 
= start_y
; y 
< end_y
; y
++) 
1678         for (int x 
= start_x
; x 
< end_x
; x
++) 
1680             int alpha 
= m_alpha
[y
*tmparea
.width 
+ x
]; 
1683                 int image_x 
= x 
- start_x
; 
1684                 int image_y 
= y 
- start_y
; 
1687                     image
.SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue 
); 
1690                 int red1 
= (m_red 
* alpha
) / 255; 
1691                 int green1 
= (m_green 
* alpha
) / 255; 
1692                 int blue1 
= (m_blue 
* alpha
) / 255; 
1695                 int red2 
= image
.GetRed( image_x
, image_y 
); 
1696                 int green2 
= image
.GetGreen( image_x
, image_y 
); 
1697                 int blue2 
= image
.GetBlue( image_x
, image_y 
); 
1698                 red2 
= (red2 
* alpha
) / 255; 
1699                 green2 
= (green2 
* alpha
) / 255; 
1700                 blue2 
= (blue2 
* alpha
) / 255; 
1702                 image
.SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2 
); 
1706    sub_bitmap 
= wxBitmap(image
); 
1708    wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1709    dc
->DrawBitmap( sub_bitmap
, clip_x
, clip_y 
); 
1712 void wxCanvasText::WriteSVG( wxTextOutputStream 
&stream 
) 
1716 void wxCanvasText::TransLate( double x
, double y 
) 
1723 void wxCanvasText::CalcBoundingBox() 
1725     if (m_alpha
) delete [] m_alpha
; 
1727     m_bbox
.SetMin( m_x 
, m_y
); 
1728     m_bbox
.SetMax( m_x 
+ 100 , m_y 
+ m_size 
+ (m_size
/2)); 
1733 //---------------------------------------------------------------------------- 
1735 //---------------------------------------------------------------------------- 
1737 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
) 
1739 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
) 
1740     EVT_PAINT( wxCanvas::OnPaint 
) 
1741     EVT_IDLE( wxCanvas::OnIdle 
) 
1742     EVT_SIZE( wxCanvas::OnSize 
) 
1743     EVT_MOUSE_EVENTS( wxCanvas::OnMouse 
) 
1744     EVT_SET_FOCUS( wxCanvas::OnSetFocus 
) 
1745     EVT_KILL_FOCUS( wxCanvas::OnKillFocus 
) 
1746     EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground 
) 
1749 wxCanvas::wxCanvas( wxCanvasAdmin
* admin
, wxWindow 
*parent
, wxWindowID id
, 
1750     const wxPoint 
&position
, const wxSize
& size
, long style 
) : 
1751     wxScrolledWindow( parent
, id
, position
, size
, style 
) 
1753     // These are unused in wxVectorCanvas 
1758     m_admin
->Append( this ); 
1760     m_needUpdate 
= FALSE
; 
1761     m_background 
= *wxWHITE
; 
1762     m_lastMouse 
= (wxCanvasObject
*)NULL
; 
1763     m_captureMouse 
= (wxCanvasObject
*)NULL
; 
1767     m_root 
= (wxCanvasObjectGroup
*)NULL
; 
1770 wxCanvas::~wxCanvas() 
1772     wxNode 
*node 
= m_updateRects
.First(); 
1775         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1777         m_updateRects
.DeleteNode( node 
); 
1778         node 
= m_updateRects
.First(); 
1782 double wxCanvas::GetMinX() const 
1787 double wxCanvas::GetMinY() const 
1792 double wxCanvas::GetMaxX() const 
1795    GetVirtualSize( &width
, NULL 
); 
1799 double wxCanvas::GetMaxY() const 
1802    GetVirtualSize( NULL
, &height 
); 
1806 void wxCanvas::SetColour( const wxColour
& background 
) 
1808     m_background 
= background
; 
1809     SetBackgroundColour( m_background 
); 
1811     if (m_frozen
) return; 
1814     dc
.SelectObject( m_buffer 
); 
1815     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1816     wxBrush 
brush( m_background
, wxSOLID 
); 
1817     dc
.SetBrush( brush 
); 
1818     dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
1819     dc
.SelectObject( wxNullBitmap 
); 
1822 void wxCanvas::SetCaptureMouse( wxCanvasObject 
*obj 
) 
1826         wxWindow::CaptureMouse(); 
1827         m_captureMouse 
= obj
; 
1831         wxWindow::ReleaseMouse(); 
1832         m_captureMouse 
= NULL
; 
1836 void wxCanvas::Freeze() 
1841 void wxCanvas::Thaw() 
1843     wxNode 
*node 
= m_updateRects
.First(); 
1846         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1848         m_updateRects
.DeleteNode( node 
); 
1849         node 
= m_updateRects
.First(); 
1855         Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
1858 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit 
) 
1860     CalcScrolledPosition( 0, 0, &m_oldDeviceX
, &m_oldDeviceY 
); 
1862     m_admin
->SetActive(this); 
1864     if (!m_root
) return; 
1866     if (m_frozen
) return; 
1871         width 
-= m_bufferX
-x
; 
1874     if (width 
<= 0) return; 
1878         height 
-= m_bufferY
-y
; 
1881     if (height 
<= 0) return; 
1883     if (x
+width 
> m_bufferX
+m_buffer
.GetWidth()) 
1885         width 
= m_bufferX
+m_buffer
.GetWidth() - x
; 
1887     if (width 
<= 0) return; 
1889     if (y
+height 
> m_bufferY
+m_buffer
.GetHeight()) 
1891         height 
= m_bufferY
+m_buffer
.GetHeight() - y
; 
1893     if (height 
<= 0) return; 
1895     // update is within the buffer 
1896     m_needUpdate 
= TRUE
; 
1898     // has to be blitted to screen later 
1901         m_updateRects
.Append( 
1902             (wxObject
*) new wxRect( x
,y
,width
,height 
) ); 
1905     wxTransformMatrix cworld
; 
1908     dc
.SelectObject( m_buffer 
); 
1910     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1911     wxBrush 
brush( m_background
, wxSOLID 
); 
1912     dc
.SetBrush( brush 
); 
1913     dc
.SetLogicalFunction(wxCOPY
); 
1916     if (width 
!= m_buffer
.GetWidth() && height 
!= m_buffer
.GetHeight()) 
1918         dc
.SetClippingRegion(x
,y
,width
,height
); 
1919         dc
.DrawRectangle(x
-2,y
-2,width
+4,height
+4); 
1920         dc
.DestroyClippingRegion(); 
1925         dc
.DrawRectangle(0,0,m_buffer
.GetWidth(),m_buffer
.GetHeight()); 
1928     // No idea, what the code up there does. 
1929     dc
.DrawRectangle( x
-m_bufferX
, y
-m_bufferY
, width
, height 
); 
1932     dc
.SetBrush(wxNullBrush
); 
1933     dc
.SetPen(wxNullPen
); 
1935     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
1938     m_root
->Render( &cworld
, x
, y
, width
, height 
); 
1941     dc
.SelectObject( wxNullBitmap 
); 
1944 void wxCanvas::BlitBuffer( wxDC 
&dc 
) 
1946     wxNode 
*node 
= m_updateRects
.First(); 
1949         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1952         mdc
.SelectObject( m_buffer 
); 
1958                  rect
->x 
- m_bufferX
, 
1959                  rect
->y 
- m_bufferY 
);  
1960         mdc
.SelectObject( wxNullBitmap 
); 
1963         m_updateRects
.DeleteNode( node 
); 
1964         node 
= m_updateRects
.First(); 
1967     m_needUpdate 
= FALSE
; 
1970 void wxCanvas::UpdateNow() 
1972     if (m_frozen
) return; 
1974     if (!m_needUpdate
) return; 
1976     wxClientDC 
dc( this ); 
1982 void wxCanvas::OnSize(wxSizeEvent 
&event
) 
1985     GetClientSize( &w
, &h 
); 
1986     m_buffer 
= wxBitmap( w
, h 
); 
1988     CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY 
); 
1990     wxNode 
*node 
= m_updateRects
.First(); 
1993         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1995         m_updateRects
.DeleteNode( node 
); 
1996         node 
= m_updateRects
.First(); 
2001     Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
2006 void wxCanvas::OnPaint(wxPaintEvent 
&event
) 
2011     if (!m_buffer
.Ok()) return; 
2013     if (m_frozen
) return; 
2015     m_needUpdate 
= TRUE
; 
2017     wxRegionIterator 
it( GetUpdateRegion() ); 
2023         int w 
= it
.GetWidth(); 
2024         int h 
= it
.GetHeight(); 
2026         if (x
+w 
> m_buffer
.GetWidth()) 
2027             w 
= m_buffer
.GetWidth() - x
; 
2028         if (y
+h 
> m_buffer
.GetHeight()) 
2029             h 
= m_buffer
.GetHeight() - y
; 
2031         if ((w 
> 0) && (h 
> 0)) 
2035             m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h 
) ); 
2044 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect 
) 
2046     // If any updates are pending, do them now since they will 
2047     // expect the previous m_bufferX and m_bufferY as well as 
2048     // the previous device origin values. 
2049     wxClientDC 
dc( this ); 
2050     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
2053     // The buffer always starts at the top left corner of the 
2054     // client area. Indeed, it is the client area. 
2055     CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY 
); 
2057     // Update everything. 
2058     Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
2060     // Scroll, actually. 
2061     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
2064 void wxCanvas::OnMouse(wxMouseEvent 
&event
) 
2066     m_admin
->SetActive(this); 
2073     int x 
= event
.GetX(); 
2074     int y 
= event
.GetY(); 
2076     //to world coordinates to do hit test in world coordinates 
2077     double xw 
= DeviceToLogicalX( x 
); 
2078     double yw 
= DeviceToLogicalY( y 
); 
2080     //make a select margin of 2 pixels, so also zero line thickness will be hit 
2081     double margin 
= DeviceToLogicalXRel( 2 ); 
2083     if (event
.GetEventType() == wxEVT_MOTION
) 
2085         if (m_captureMouse
) //no matter what go to this one 
2087             wxMouseEvent 
child_event( wxEVT_MOTION 
); 
2088             child_event
.SetEventObject(m_captureMouse
); 
2089             child_event
.m_x 
= x
; 
2090             child_event
.m_y 
= y
; 
2091             child_event
.m_leftDown 
= event
.m_leftDown
; 
2092             child_event
.m_rightDown 
= event
.m_rightDown
; 
2093             child_event
.m_middleDown 
= event
.m_middleDown
; 
2094             child_event
.m_controlDown 
= event
.m_controlDown
; 
2095             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2096             child_event
.m_altDown 
= event
.m_altDown
; 
2097             child_event
.m_metaDown 
= event
.m_metaDown
; 
2099             m_captureMouse
->ProcessCanvasObjectEvent( child_event 
); 
2104             wxCanvasObject 
*obj 
= m_root
->IsHitWorld(xw
,yw
,margin
); 
2106             if (obj 
&& !obj
->IsControl()) 
2108                 wxMouseEvent 
child_event( wxEVT_MOTION 
); 
2109                 child_event
.SetEventObject( obj 
); 
2110                 child_event
.m_x 
= x
; 
2111                 child_event
.m_y 
= y
; 
2112                 child_event
.m_leftDown 
= event
.m_leftDown
; 
2113                 child_event
.m_rightDown 
= event
.m_rightDown
; 
2114                 child_event
.m_middleDown 
= event
.m_middleDown
; 
2115                 child_event
.m_controlDown 
= event
.m_controlDown
; 
2116                 child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2117                 child_event
.m_altDown 
= event
.m_altDown
; 
2118                 child_event
.m_metaDown 
= event
.m_metaDown
; 
2120                 if ((obj 
!= m_lastMouse
) && (m_lastMouse 
!= NULL
)) 
2122                     child_event
.SetEventType( wxEVT_LEAVE_WINDOW 
); 
2123                     child_event
.SetEventObject( m_lastMouse 
); 
2124                     child_event
.m_x 
= x
; 
2125                     child_event
.m_y 
= y
; 
2126                     m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2129                     child_event
.SetEventType( wxEVT_ENTER_WINDOW 
); 
2130                     child_event
.SetEventObject( m_lastMouse 
); 
2131                     child_event
.m_x 
= x
; 
2132                     child_event
.m_y 
= y
; 
2133                     m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2135                     child_event
.SetEventType( wxEVT_MOTION 
); 
2136                     child_event
.SetEventObject( obj 
); 
2139                 obj
->ProcessCanvasObjectEvent( child_event 
); 
2145             wxMouseEvent 
child_event( wxEVT_LEAVE_WINDOW 
); 
2146             child_event
.SetEventObject( m_lastMouse 
); 
2147             child_event
.m_x 
= x
; 
2148             child_event
.m_y 
= y
; 
2149             child_event
.m_leftDown 
= event
.m_leftDown
; 
2150             child_event
.m_rightDown 
= event
.m_rightDown
; 
2151             child_event
.m_middleDown 
= event
.m_middleDown
; 
2152             child_event
.m_controlDown 
= event
.m_controlDown
; 
2153             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2154             child_event
.m_altDown 
= event
.m_altDown
; 
2155             child_event
.m_metaDown 
= event
.m_metaDown
; 
2156             m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2158             m_lastMouse 
= (wxCanvasObject
*) NULL
; 
2164         if (m_captureMouse
) //no matter what go to this one 
2166             wxMouseEvent 
child_event( event
.GetEventType() ); 
2167             child_event
.SetEventObject(m_captureMouse
); 
2168             child_event
.m_x 
= x
; 
2169             child_event
.m_y 
= y
; 
2170             child_event
.m_leftDown 
= event
.m_leftDown
; 
2171             child_event
.m_rightDown 
= event
.m_rightDown
; 
2172             child_event
.m_middleDown 
= event
.m_middleDown
; 
2173             child_event
.m_controlDown 
= event
.m_controlDown
; 
2174             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2175             child_event
.m_altDown 
= event
.m_altDown
; 
2176             child_event
.m_metaDown 
= event
.m_metaDown
; 
2177             m_captureMouse
->ProcessCanvasObjectEvent( child_event 
); 
2181             wxCanvasObject 
*obj 
= m_root
->IsHitWorld(xw
,yw
,margin
); 
2183             if (obj 
&& !obj
->IsControl()) 
2185                 wxMouseEvent 
child_event( event
.GetEventType() ); 
2186                 child_event
.SetEventObject( obj 
); 
2187                 child_event
.m_x 
= x
; 
2188                 child_event
.m_y 
= y
; 
2189                 child_event
.m_leftDown 
= event
.m_leftDown
; 
2190                 child_event
.m_rightDown 
= event
.m_rightDown
; 
2191                 child_event
.m_middleDown 
= event
.m_middleDown
; 
2192                 child_event
.m_controlDown 
= event
.m_controlDown
; 
2193                 child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2194                 child_event
.m_altDown 
= event
.m_altDown
; 
2195                 child_event
.m_metaDown 
= event
.m_metaDown
; 
2197                 obj
->ProcessCanvasObjectEvent( child_event 
); 
2206 void wxCanvas::OnIdle(wxIdleEvent 
&event
) 
2208     m_admin
->SetActive(this); 
2213 void wxCanvas::OnSetFocus(wxFocusEvent 
&event
) 
2215     m_admin
->SetActive(this); 
2218 void wxCanvas::OnKillFocus(wxFocusEvent 
&event
) 
2223 void wxCanvas::OnEraseBackground(wxEraseEvent 
&event
) 
2227 // coordinates conversions 
2228 // ----------------------- 
2229 double wxCanvas::DeviceToLogicalX(int x
) const 
2234 double wxCanvas::DeviceToLogicalY(int y
) const 
2239 double wxCanvas::DeviceToLogicalXRel(int x
) const 
2244 double wxCanvas::DeviceToLogicalYRel(int y
) const 
2249 int wxCanvas::LogicalToDeviceX(double x
) const 
2251     return (int)(x 
+ 0.5); 
2254 int wxCanvas::LogicalToDeviceY(double y
) const 
2256     return (int)(y 
+ 0.5); 
2259 int wxCanvas::LogicalToDeviceXRel(double x
) const 
2261     return (int)(x 
+ 0.5); 
2264 int wxCanvas::LogicalToDeviceYRel(double y
) const 
2266     return (int)(y 
+ 0.5); 
2269 //---------------------------------------------------------------------------- 
2271 //---------------------------------------------------------------------------- 
2273 IMPLEMENT_CLASS(wxVectorCanvas
,wxCanvas
) 
2275 BEGIN_EVENT_TABLE(wxVectorCanvas
,wxCanvas
) 
2276     EVT_SCROLLWIN( wxVectorCanvas::OnScroll 
) 
2277     EVT_CHAR( wxVectorCanvas::OnChar 
) 
2278     EVT_SIZE( wxVectorCanvas::OnSize 
) 
2281 wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin
* admin
, wxWindow 
*parent
, wxWindowID id
, 
2282     const wxPoint 
&position
, const wxSize
& size
, long style 
) : 
2283     wxCanvas( admin
, parent
, id
, position
, size
, style 
) 
2289 double wxVectorCanvas::GetMinX() const 
2294 double wxVectorCanvas::GetMinY() const 
2299 double wxVectorCanvas::GetMaxX() const 
2304 double wxVectorCanvas::GetMaxY() const 
2309 void wxVectorCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect 
) 
2311     // If any updates are pending, do them now since they will 
2312     // expect the previous m_bufferX and m_bufferY as well as 
2313     // the previous device origin values. 
2314     wxClientDC 
dc( this ); 
2315     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
2320         double dyv
=DeviceToLogicalYRel(dy
); 
2321         m_virt_minY
=m_virt_minY
-dyv
; 
2322         m_virt_maxY
=m_virt_maxY
-dyv
; 
2326         double dxv
=DeviceToLogicalXRel(dx
); 
2327         m_virt_minX
=m_virt_minX
-dxv
; 
2328         m_virt_maxX
=m_virt_maxX
-dxv
; 
2331     m_admin
->SetActive(this); 
2332     SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
); 
2337         if (dy 
> 0 && dy 
< m_buffer
.GetHeight()) 
2339             wxRect 
rect( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight()-dy
); 
2340             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2342             dcm
.SelectObject( m_buffer 
); 
2343             dcm
.DrawBitmap( sub_bitmap
, 0, dy
, TRUE 
); 
2344             dcm
.SelectObject( wxNullBitmap 
); 
2346             Update( 0, 0, m_buffer
.GetWidth(), dy
, TRUE 
); 
2348         else  if (dy 
< 0 && dy 
> -m_buffer
.GetHeight()) 
2350             wxRect 
rect( 0, -dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight()+dy
); 
2351             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2353             dcm
.SelectObject( m_buffer 
); 
2354             dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE 
); 
2355             dcm
.SelectObject( wxNullBitmap 
); 
2357             Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2360             Update( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2365         if (dx 
> 0 && dx 
< m_buffer
.GetWidth()) 
2367             wxRect 
rect( 0, 0, m_buffer
.GetWidth()-dx
, m_buffer
.GetHeight()); 
2368             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2370             dcm
.SelectObject( m_buffer 
); 
2371             dcm
.DrawBitmap( sub_bitmap
, dx
, 0, TRUE 
); 
2372             dcm
.SelectObject( wxNullBitmap 
); 
2374             Update( 0, 0, dx
, m_buffer
.GetHeight(), TRUE 
); 
2376         else if (dx 
< 0 && dx 
> -m_buffer
.GetWidth()) 
2378             wxRect 
rect( -dx
, 0, m_buffer
.GetWidth()+dx
, m_buffer
.GetHeight()); 
2379             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2381             dcm
.SelectObject( m_buffer 
); 
2382             dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE 
); 
2383             dcm
.SelectObject( wxNullBitmap 
); 
2385             Update( m_buffer
.GetWidth()+dx
, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2388             Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2391     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
2393     //must be done now because quick repeated scrolling will prevent wxPaint 
2394     //from doing it properly 
2398 void wxVectorCanvas::OnSize(wxSizeEvent 
&event
) 
2402     GetClientSize( &w
, &h 
); 
2405     m_buffer 
= wxBitmap( w
, h 
); 
2406     dc
.SelectObject( m_buffer 
); 
2407     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
2408     wxBrush 
brush( m_background 
, wxSOLID 
); 
2409     dc
.SetBrush( brush 
); 
2410     dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
2411     dc
.SelectObject( wxNullBitmap 
); 
2413     wxNode 
*node 
= m_updateRects
.First(); 
2416         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
2418         m_updateRects
.DeleteNode( node 
); 
2419         node 
= m_updateRects
.First(); 
2424     m_admin
->SetActive(this); 
2425     SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
); 
2427     Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
2432 // maps the virtual window (Real drawing to the window coordinates 
2433 // also used for zooming 
2434 void wxVectorCanvas::SetMappingScroll( double vx1
,    double vy1
, double vx2
, double vy2
, bool border
) 
2437     GetClientSize(&dwxi
,&dwyi
); 
2439     if (vx2
==vx1
) vx2
=vx1
+100000; 
2440     if (vy2
==vy1
) vy2
=vy1
+100000; 
2451     double dvx 
= m_virt_maxX 
- m_virt_minX
; 
2452     double dvy 
= m_virt_maxY 
- m_virt_minY
; 
2454     // calculate the scaling factor for the virtual window 
2457     if ((dvy 
/ dvx
) < (dwy 
/ dwx
)) 
2459         dvy 
= dvx 
* (dwy 
/ dwx
); 
2460         // calculate the change in the coordinates 
2461         temp_y 
= (dvy 
- (m_virt_maxY 
- m_virt_minY
) )/ 2.0; 
2465         dvx 
= dvy 
* (dwx 
/ dwy
); 
2466         // calculate the change in the coordinates 
2467         temp_x 
= (dvx 
- (m_virt_maxX 
- m_virt_minX
) )/ 2.0; 
2470     // add or substract the change from the original coordinates 
2471     m_virt_minX
=m_virt_minX
-temp_x
; 
2472     m_virt_minY
=m_virt_minY
-temp_y
; 
2474     m_virt_maxX
=m_virt_maxX
+temp_x
; 
2475     m_virt_maxY
=m_virt_maxY
+temp_y
; 
2477     // initialize the mapping_matrix used for mapping the 
2478     // virtual windows to the drawing window 
2480      // make mappingmatrix 
2481     m_mapping_matrix
.Identity(); 
2484         // translate the drawing to 0,0 
2486             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
); 
2488             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
); 
2492         // make a small white border around the drawing 
2493         m_virt_minX
=m_virt_minX
- 0.05 * dvx
; 
2494         m_virt_minY
=m_virt_minY
- 0.05 * dvy
; 
2496         m_virt_maxX
=m_virt_maxX
+ 0.05 * dvx
; 
2497         m_virt_maxY
=m_virt_maxY
+ 0.05 * dvy
; 
2499         // translate the drawing to 0,0 
2501             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
); 
2503             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
); 
2506     double scalefactor_x 
= dwx
; 
2507     scalefactor_x 
/= (m_virt_maxX 
- m_virt_minX
); 
2509     double scalefactor_y 
= dwy
; 
2510     scalefactor_y 
/= (m_virt_maxY 
- m_virt_minY
); 
2512     // scale the drawing so it fit's in the window 
2513     m_mapping_matrix
.Scale(scalefactor_x
, scalefactor_y
, 0, 0); 
2515     // because of coordinate change mirror over X 
2516     // 0,0 in graphic computerscreens: upperleft corner 
2517     // 0,0 in cartesian: lowerleft corner 
2520         m_mapping_matrix
.Mirror(); 
2522     // make inverse of mapping matrix 
2523     // this is to set coordinates in the statusbar 
2524     // and the calculate screencoordinates to world coordinates used 
2526     m_inverse_mapping
=m_mapping_matrix
; 
2527     m_inverse_mapping
.Invert(); 
2530         SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
); 
2533     GetClientSize(&dx2
,&dy2
); 
2534     if ( dwxi 
!= dx2 
|| dwyi  
!= dy2
) //scrollbar is/became empty 
2535         SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
); 
2539 void wxVectorCanvas::SetScroll(double vx1
,double vy1
,double vx2
,double vy2
) 
2546     double dvx 
= m_virt_maxX 
- m_virt_minX
; 
2547     double dvy 
= m_virt_maxY 
- m_virt_minY
; 
2548     double dmvx 
= m_virtm_maxX 
- m_virtm_minX
; 
2549     double dmvy 
= m_virtm_maxY 
- m_virtm_minY
; 
2551     SetScrollbar(wxHORIZONTAL
,(m_virt_minX
-m_virtm_minX
)/dmvx 
*1000,dvx
/dmvx 
*1000,1000,FALSE
); 
2554         SetScrollbar(wxVERTICAL
,(m_virtm_maxY
-m_virt_maxY
)/dmvy 
*1000,dvy
/dmvy 
*1000,1000,FALSE
); 
2558         SetScrollbar(wxVERTICAL
,(m_virt_minY
-m_virtm_minY
)/dmvy 
*1000,dvy
/dmvy 
*1000,1000,FALSE
); 
2564 // coordinates conversions 
2565 // ----------------------- 
2566 double wxVectorCanvas::DeviceToLogicalX(int x
) const 
2568     return m_inverse_mapping
.GetValue(0,0) * x 
+ m_inverse_mapping
.GetValue(2,0); 
2571 double wxVectorCanvas::DeviceToLogicalY(int y
) const 
2573     return m_inverse_mapping
.GetValue(1,1) * y 
+ m_inverse_mapping
.GetValue(2,1); 
2576 double wxVectorCanvas::DeviceToLogicalXRel(int x
) const 
2578     return x
*m_inverse_mapping
.GetValue(0,0); 
2581 double wxVectorCanvas::DeviceToLogicalYRel(int y
) const 
2583     return y
*m_inverse_mapping
.GetValue(1,1); 
2586 int wxVectorCanvas::LogicalToDeviceX(double x
) const 
2588     return (int) (m_mapping_matrix
.GetValue(0,0) * x 
+ m_mapping_matrix
.GetValue(2,0) + 0.5); 
2591 int wxVectorCanvas::LogicalToDeviceY(double y
) const 
2593     return (int) (m_mapping_matrix
.GetValue(1,1) * y 
+ m_mapping_matrix
.GetValue(2,1) + 0.5); 
2596 int wxVectorCanvas::LogicalToDeviceXRel(double x
) const 
2598     return (int) (x
*m_mapping_matrix
.GetValue(0,0) + 0.5); 
2601 int wxVectorCanvas::LogicalToDeviceYRel(double y
) const 
2603     return (int) (y
*m_mapping_matrix
.GetValue(1,1) + 0.5); 
2607 // return the inverse mapping matrix for zooming or coordinates 
2608 wxTransformMatrix 
wxVectorCanvas::GetInverseMappingMatrix() 
2610     return m_inverse_mapping
; 
2613 wxTransformMatrix 
wxVectorCanvas::GetMappingMatrix() 
2615     return m_mapping_matrix
; 
2619 // ---------------------------------------------------------------------------- 
2620 // scrolling behaviour 
2621 // ---------------------------------------------------------------------------- 
2623 void wxVectorCanvas::OnScroll(wxScrollWinEvent
& event
) 
2625     if (event
.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE
) 
2627         if (event
.GetOrientation()==wxHORIZONTAL
) 
2629           double x
=m_virtm_minX
+event
.GetPosition()/1000.0*(m_virtm_maxX
-m_virtm_minX
); 
2630           x
=LogicalToDeviceXRel(x
-m_virt_minX
); 
2631           ScrollWindow(-x
, 0, (const wxRect 
*) NULL
); 
2635           double y
=m_virtm_minY
+event
.GetPosition()/1000.0*(m_virtm_maxY
-m_virtm_minY
); 
2636           y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2637           ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2640     else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEUP
) 
2642         if (event
.GetOrientation()==wxHORIZONTAL
) 
2644           double x
=GetBufferWidth(); 
2645           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2649           double y
=GetBufferHeight(); 
2650           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2653     else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN
) 
2655         if (event
.GetOrientation()==wxHORIZONTAL
) 
2657           double x
=-GetBufferWidth(); 
2658           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2662           double y
=-GetBufferHeight(); 
2663           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2666     else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEUP
) 
2668         if (event
.GetOrientation()==wxHORIZONTAL
) 
2670           int x
=GetBufferWidth()/10; 
2671           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2675           int y
=GetBufferHeight()/10; 
2676           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2679     else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN
) 
2681         if (event
.GetOrientation()==wxHORIZONTAL
) 
2683           int x
=-GetBufferWidth()/10; 
2684           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2688           int y
=-GetBufferHeight()/10; 
2689           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2695 void wxVectorCanvas::OnChar(wxKeyEvent
& event
) 
2697     switch ( event
.KeyCode() ) 
2702               double y
=GetBufferHeight(); 
2703               ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2709               double y
=-GetBufferHeight(); 
2710               ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2715                 double y
=m_virtm_minY
; 
2716                 y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2717                 ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2722                 double y
=m_virtm_minY
+(m_virtm_maxY
-m_virtm_minY
); 
2723                 y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2724                 ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2730                 if  (!event
.ControlDown()) 
2731                     y
=GetBufferHeight()/10; 
2733                     y
=GetBufferHeight(); 
2734                 ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2741                 if  (!event
.ControlDown()) 
2742                     y
=-GetBufferHeight()/10; 
2744                     y
=-GetBufferHeight(); 
2745                 ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2752                 if  (!event
.ControlDown()) 
2753                     x
=GetBufferWidth()/10; 
2756                 ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2762                 if  (!event
.ControlDown()) 
2763                     x
=-GetBufferWidth()/10; 
2765                     x
=-GetBufferWidth(); 
2766                 ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2776 //---------------------------------------------------------------------------- 
2778 //---------------------------------------------------------------------------- 
2780 wxCanvasAdmin::wxCanvasAdmin() 
2785 wxCanvasAdmin::~wxCanvasAdmin() 
2790 void wxCanvasAdmin::Append( wxCanvas
* canvas 
) 
2792     m_canvaslist
.Append( canvas 
); 
2795 void wxCanvasAdmin::Remove( wxCanvas
* canvas 
) 
2797     m_canvaslist
.DeleteObject( canvas 
); 
2800 void wxCanvasAdmin::Update(wxCanvasObject
* obj
, double x
, double y
, double width
, double height
) 
2802     wxNode 
*node 
= m_canvaslist
.First(); 
2806         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2808         if (m_active 
== canvas
) 
2810             int xi 
= canvas
->LogicalToDeviceX( x
); 
2811             int yi 
= canvas
->LogicalToDeviceY( y
); 
2812             int wi 
= canvas
->LogicalToDeviceXRel( width 
); 
2813             int hi 
= canvas
->LogicalToDeviceYRel( height
); 
2814             //update a little more then is strictly needed, 
2815             //to get rid of the 1 bit bugs 
2816             if (canvas
->GetYaxis()) 
2817                 canvas
->Update( xi
-2, yi
+hi
-2, wi
+4, -hi
+4); 
2819                 canvas
->Update( xi
-2, yi
-2, wi
+4, hi
+4); 
2822         {   wxCanvasObject
* topobj
=canvas
->GetRoot()->Contains(obj
); 
2825                 wxCanvas
* tcanvas 
= m_active
; 
2829                 //KKK TODO somehow the next does not work for update i do not know why 
2830                 canvas->GetRoot()->CalcBoundingBox(); 
2831                 int xi = topobj->GetX(); 
2832                 int yi = topobj->GetY(); 
2833                 int wi = topobj->GetWidth(); 
2834                 int hi = topobj->GetHeight(); 
2836                 canvas
->Update( 0,0, canvas
->GetBufferWidth(),canvas
->GetBufferHeight()); 
2841         node 
= node
->Next(); 
2845 void wxCanvasAdmin::UpdateNow() 
2847     wxNode 
*node 
= m_canvaslist
.First(); 
2850         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2852         canvas
->UpdateNow(); 
2853         node 
= node
->Next(); 
2857 // coordinates conversions 
2858 // ----------------------- 
2859 double wxCanvasAdmin::DeviceToLogicalX(int x
) const 
2861     return m_active
->DeviceToLogicalX(x
); 
2864 double wxCanvasAdmin::DeviceToLogicalY(int y
) const 
2866     return m_active
->DeviceToLogicalY(y
); 
2869 double wxCanvasAdmin::DeviceToLogicalXRel(int x
) const 
2871     return m_active
->DeviceToLogicalXRel(x
); 
2874 double wxCanvasAdmin::DeviceToLogicalYRel(int y
) const 
2876     return m_active
->DeviceToLogicalYRel(y
); 
2879 int wxCanvasAdmin::LogicalToDeviceX(double x
) const 
2881     return m_active
->LogicalToDeviceX(x
); 
2884 int wxCanvasAdmin::LogicalToDeviceY(double y
) const 
2886     return m_active
->LogicalToDeviceY(y
); 
2889 int wxCanvasAdmin::LogicalToDeviceXRel(double x
) const 
2891     return m_active
->LogicalToDeviceXRel(x
); 
2894 int wxCanvasAdmin::LogicalToDeviceYRel(double y
) const 
2896     return m_active
->LogicalToDeviceYRel(y
); 
2899 void wxCanvasAdmin::SetActive(wxCanvas
* activate
) 
2901     wxNode 
*node 
= m_canvaslist
.First(); 
2904         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2906         if (activate 
== canvas
) 
2911         node 
= node
->Next(); 
2914 //-------------------------------------------------------------------- 
2916 //-------------------------------------------------------------------- 
2918 class wxCanvasModule 
: public wxModule
 
2921     virtual bool OnInit(); 
2922     virtual void OnExit(); 
2925     DECLARE_DYNAMIC_CLASS(wxCanvasModule
) 
2928 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
) 
2930 bool wxCanvasModule::OnInit() 
2933     int error 
= FT_Init_FreeType( &g_freetypeLibrary 
); 
2934     if (error
) return FALSE
; 
2940 void wxCanvasModule::OnExit() 
2943     FT_Done_FreeType( g_freetypeLibrary 
);