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 const double pi 
= 3.1415926535; 
  47 FT_Library g_freetypeLibrary
; 
  50 //---------------------------------------------------------------------------- 
  52 //---------------------------------------------------------------------------- 
  54 wxCanvasObject::wxCanvasObject() 
  56     // the default event handler is just this object 
  63     m_dragmode 
= DRAG_ONTOP
; 
  64 //  handy when debugging 
  65 //  m_dragmode = DRAG_RECTANGLE; 
  69 bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent
& event
) 
  71     return m_eventHandler
->ProcessEvent(event
); 
  74 void wxCanvasObject::PushEventHandler(wxEvtHandler 
*handler
) 
  76     handler
->SetNextHandler(GetEventHandler()); 
  77     m_eventHandler
=handler
; 
  80 wxEvtHandler 
*wxCanvasObject::PopEventHandler(bool deleteHandler
) 
  82     wxEvtHandler 
*handlerA 
= m_eventHandler
; 
  85         wxEvtHandler 
*handlerB 
= handlerA
->GetNextHandler(); 
  86         handlerA
->SetNextHandler((wxEvtHandler 
*)NULL
); 
  87         m_eventHandler
=handlerB
; 
  91             handlerA 
= (wxEvtHandler 
*)NULL
; 
  98 void wxCanvasObject::AppendEventHandler(wxEvtHandler 
*handler
) 
 100     GetEventHandler()->SetNextHandler(handler
); 
 103 wxEvtHandler 
*wxCanvasObject::RemoveLastEventHandler(bool deleteHandler
) 
 105     //always the first in the row 
 106     wxEvtHandler 
*handlerA 
= m_eventHandler
; 
 107     wxEvtHandler 
*handlerB
=handlerA
; 
 109     while ( handlerA
->GetNextHandler() ) 
 112         handlerA 
= handlerA
->GetNextHandler(); 
 115     handlerB
->SetNextHandler((wxEvtHandler 
*)NULL
); 
 121     return GetEventHandler(); 
 124 wxRect 
wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix
& cworld
) 
 126     wxBoundingBox tmp
=m_bbox
; 
 129     int x1 
= m_admin
->LogicalToDeviceX( tmp
.GetMinX() ); 
 130     int y1 
= m_admin
->LogicalToDeviceY( tmp
.GetMinY() ); 
 131     int x2 
= m_admin
->LogicalToDeviceX( tmp
.GetMaxX() ); 
 132     int y2 
= m_admin
->LogicalToDeviceY( tmp
.GetMaxY() ); 
 150     tmparea
.width 
= x2
-x1
;    // FIXME +1 ? 
 151     tmparea
.height 
= y2
-y1
;   // FIXME +1 ? 
 156 void wxCanvasObject::MoveAbsolute( double x
, double y 
) 
 158     //save old position of boundingbox 
 159     double oldx 
= GetXMin(); 
 160     double oldy 
= GetYMin(); 
 161     double w 
= m_bbox
.GetWidth(); 
 162     double h 
= m_bbox
.GetHeight(); 
 166     double newx
=GetXMin(); 
 167     double newy
=GetYMin(); 
 169     double leftu
,rightu
,bottomu
,topu 
; 
 170     leftu   
= wxMin (oldx
, newx 
) ; 
 171     rightu  
= wxMax (oldx 
+ w
, newx 
+ w
) ; 
 172     topu    
= wxMin (oldy
, newy
) ; 
 173     bottomu 
= wxMax (oldy 
+ h
, newy 
+ h
) ; 
 175     if ( rightu 
- leftu 
< 2*w 
&& bottomu 
- topu 
< 2*h 
) 
 177         m_admin
->Update( this,leftu
, topu
, rightu 
- leftu
, bottomu 
- topu
); 
 181         m_admin
->Update( this, oldx
, oldy
, w
, h 
); 
 182         m_admin
->Update( this, newx
, newy
, w
, h 
); 
 186 void wxCanvasObject::MoveRelative( double x
, double y 
) 
 188     //save old position of boundingbox 
 189     double oldx 
= GetXMin(); 
 190     double oldy 
= GetYMin(); 
 191     double w 
= m_bbox
.GetWidth(); 
 192     double h 
= m_bbox
.GetHeight(); 
 196     double newx
=GetXMin(); 
 197     double newy
=GetYMin(); 
 199     double leftu
,rightu
,bottomu
,topu 
; 
 200     leftu   
= wxMin (oldx
, newx 
) ; 
 201     rightu  
= wxMax (oldx 
+ w
, newx 
+ w
) ; 
 202     topu    
= wxMin (oldy
, newy
) ; 
 203     bottomu 
= wxMax (oldy 
+ h
, newy 
+ h
) ; 
 205     if ( rightu 
- leftu 
< 2*w 
&& bottomu 
- topu 
< 2*h 
) 
 207         m_admin
->Update( this,leftu
, topu
, rightu 
- leftu
, bottomu 
- topu
); 
 211         m_admin
->Update( this, oldx
, oldy
, w
, h 
); 
 212         m_admin
->Update( this, newx
, newy
, w
, h 
); 
 217 void wxCanvasObject::DragStart() 
 219     if (m_dragmode 
== DRAG_RECTANGLE
) 
 221         this->SetVisible(FALSE
); 
 222         wxTransformMatrix help
; 
 223         double x 
= GetXMin(); 
 224         double y 
= GetYMin(); 
 225         double w 
= m_bbox
.GetWidth(); 
 226         double h 
= m_bbox
.GetHeight(); 
 227         m_admin
->Update( this, x
, y
, w
, h 
); 
 228         m_admin
->UpdateNow(); 
 230         wxRect recold
=GetAbsoluteArea(help
); 
 231         wxClientDC 
dc(m_admin
->GetActive()); 
 232         dc
.SetPen(*wxBLACK_PEN
); 
 233         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 234         dc
.SetLogicalFunction(wxINVERT
); 
 235         dc
.DrawRectangle(recold
); 
 236         dc
.SetBrush(wxNullBrush
); 
 237         dc
.SetPen(wxNullPen
); 
 241         this->SetVisible(FALSE
); 
 242         wxTransformMatrix help
; 
 243         double x 
= GetXMin(); 
 244         double y 
= GetYMin(); 
 245         double w 
= m_bbox
.GetWidth(); 
 246         double h 
= m_bbox
.GetHeight(); 
 248         wxRect recnew
=GetAbsoluteArea(help
); 
 250          //redraw in buffer what should be there without this object 
 251         m_admin
->Update( this, x
, y
, w
, h 
); 
 252         m_admin
->GetActive()->Freeze(); 
 254         //save the drawing (without the object itself to a bitmap) 
 255         m_atnewpos 
= wxBitmap(recnew
.width
,recnew
.height
); 
 257         dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer()); 
 259         tmp
.SelectObject(m_atnewpos
); 
 260         tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 261         tmp
.SelectObject(wxNullBitmap
); 
 262         dcm
.SelectObject(wxNullBitmap
); 
 267 void wxCanvasObject::DragRelative( double x
, double y
) 
 269     if (m_dragmode 
== DRAG_RECTANGLE
) 
 271         wxTransformMatrix help
; 
 273         wxRect recold
=GetAbsoluteArea(help
); 
 277         wxRect recnew
=GetAbsoluteArea(help
); 
 279         wxClientDC 
dc(m_admin
->GetActive()); 
 280         dc
.SetPen(*wxBLACK_PEN
); 
 281         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 282         dc
.SetLogicalFunction(wxINVERT
); 
 283         dc
.DrawRectangle(recold
); 
 284         dc
.DrawRectangle(recnew
); 
 285         dc
.SetBrush(wxNullBrush
); 
 286         dc
.SetPen(wxNullPen
); 
 290         wxClientDC 
dc(m_admin
->GetActive()); 
 293         wxTransformMatrix help
; 
 294         wxRect recold
=GetAbsoluteArea(help
); 
 296         //restore what was there (without the object itself) 
 298         dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer()); 
 299         tmp
.SelectObject(m_atnewpos
); 
 300         dcm
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&tmp
,0,0,wxCOPY
,FALSE
); 
 304         wxRect recnew
=GetAbsoluteArea(help
); 
 306         //save the contents of the buffer at the new position 
 307         tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 308         tmp
.SelectObject(wxNullBitmap
); 
 310         //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew ); 
 312         this->SetVisible(TRUE
); 
 313         //redraw object into the buffer 
 314         m_admin
->GetActive()->SetDC(&dcm
); 
 315         Render(&help
,recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
); 
 317         //draw the union or seperate to the canvas 
 318         double leftu
,rightu
,bottomu
,topu 
; 
 319         leftu   
= wxMin (recold
.x
, recnew
.x 
) ; 
 320         rightu  
= wxMax (recold
.x 
+ recold
.width
, recnew
.x 
+ recnew
.width 
) ; 
 321         topu    
= wxMin (recold
.y
, recnew
.y
) ; 
 322         bottomu 
= wxMax (recold
.y 
+ recold
.height
, recnew
.y 
+ recnew
.height
) ; 
 324         if ( rightu 
- leftu 
< 2*recold
.width 
&& bottomu 
- topu 
< 2*recold
.height
) 
 326             dc
.Blit(leftu
,topu
,rightu 
- leftu
,bottomu 
- topu
,&dcm
,leftu
,topu
,wxCOPY
,FALSE
); 
 331             //first redraw what should be at the old position in the canvas 
 332             dc
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&dcm
,recold
.x
,recold
.y
,wxCOPY
,FALSE
); 
 333             //blit the new position of the object to the canvas 
 334             dc
.Blit(recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
); 
 336         dcm
.SelectObject(wxNullBitmap
); 
 337         this->SetVisible(FALSE
); 
 342 void wxCanvasObject::DragEnd() 
 344     m_atnewpos 
= wxBitmap(0,0); 
 345     m_admin
->GetActive()->Thaw(); 
 346     this->SetVisible(TRUE
); 
 347     double x 
= GetXMin(); 
 348     double y 
= GetYMin(); 
 349     double w 
= m_bbox
.GetWidth(); 
 350     double h 
= m_bbox
.GetHeight(); 
 351     m_admin
->Update( this, x
, y
, w
, h 
); 
 352     m_admin
->UpdateNow(); 
 355 wxCanvasObject
* wxCanvasObject::IsHitWorld( double x
, double y
, double margin 
) 
 357     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
 358         (x 
<= m_bbox
.GetMaxX()+margin
) && 
 359         (y 
>= m_bbox
.GetMinY()-margin
) && 
 360         (y 
<= m_bbox
.GetMaxY()+margin
)) 
 365     return (wxCanvasObject
*) NULL
; 
 368 wxCanvasObject
* wxCanvasObject::Contains( wxCanvasObject
* obj 
) 
 373     return (wxCanvasObject
*) NULL
; 
 376 void wxCanvasObject::CaptureMouse() 
 378     m_admin
->GetActive()->SetCaptureMouse( this ); 
 381 void wxCanvasObject::ReleaseMouse() 
 383     m_admin
->GetActive()->SetCaptureMouse( NULL 
); 
 386 bool wxCanvasObject::IsCapturedMouse() 
 388     return (m_admin
->GetActive()->GetCaptured() == this); 
 392 void wxCanvasObject::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 396 void wxCanvasObject::CalcBoundingBox() 
 400 void wxCanvasObject::WriteSVG( wxTextOutputStream 
&stream 
) 
 404 //---------------------------------------------------------------------------- 
 405 // wxCanvasObjectGroup 
 406 //---------------------------------------------------------------------------- 
 408 wxCanvasObjectGroup::wxCanvasObjectGroup(double x
, double y
) 
 410     lworld
.Translate(x
,y
); 
 411     //no objects make the bounding box the x,y and take care of it later 
 415 wxCanvasObjectGroup::~wxCanvasObjectGroup() 
 419 void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler 
*handler
) 
 421     wxCanvasObject::PushEventHandler(handler
); 
 422     wxNode 
*node 
= m_objects
.First(); 
 425         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 427         obj
->PushEventHandler(handler
); 
 433 wxEvtHandler 
*wxCanvasObjectGroup::PopEventHandler(bool deleteHandler
) 
 435     wxNode 
*node 
= m_objects
.First(); 
 438         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 440         obj
->PopEventHandler(deleteHandler
); 
 444     return wxCanvasObject::PopEventHandler(deleteHandler
); 
 447 void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler 
*handler
) 
 449     wxCanvasObject::AppendEventHandler(handler
); 
 450     wxNode 
*node 
= m_objects
.First(); 
 453         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 455         obj
->AppendEventHandler(handler
); 
 461 wxEvtHandler 
*wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler
) 
 463     wxNode 
*node 
= m_objects
.First(); 
 466         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 468         obj
->RemoveLastEventHandler(deleteHandler
); 
 472     return wxCanvasObject::RemoveLastEventHandler(deleteHandler
); 
 475 void wxCanvasObjectGroup::TransLate( double x
, double y 
) 
 477     lworld
.Translate(x
,y
); 
 481 void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin
* admin
) 
 484     wxNode 
*node 
= m_objects
.First(); 
 487         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 489         obj
->SetAdmin(admin
); 
 495 void wxCanvasObjectGroup::DeleteContents( bool flag
) 
 497     m_objects
.DeleteContents( flag 
); 
 498     m_bbox
.SetValid(FALSE
); 
 502 void wxCanvasObjectGroup::Prepend( wxCanvasObject
* obj 
) 
 504     m_objects
.Insert( obj 
); 
 505     if (m_objects
.First()) 
 507         m_bbox
.Expand(obj
->GetBbox()); 
 511         m_bbox
.SetValid(FALSE
); 
 516 void wxCanvasObjectGroup::Append( wxCanvasObject
* obj 
) 
 518     m_objects
.Append( obj 
); 
 519     if (m_objects
.First()) 
 521         m_bbox
.Expand(obj
->GetBbox()); 
 525         m_bbox
.SetValid(FALSE
); 
 530 void wxCanvasObjectGroup::Insert( size_t before
, wxCanvasObject
* obj 
) 
 532     m_objects
.Insert( before
, obj 
); 
 533     m_bbox
.SetValid(FALSE
); 
 534     if (m_objects
.First()) 
 536         m_bbox
.Expand(obj
->GetBbox()); 
 540         m_bbox
.SetValid(FALSE
); 
 545 void wxCanvasObjectGroup::Remove( wxCanvasObject
* obj 
) 
 547     m_objects
.DeleteObject( obj 
); 
 548     m_bbox
.SetValid(FALSE
); 
 552 void wxCanvasObjectGroup::CalcBoundingBox() 
 554     m_bbox
.SetValid(FALSE
); 
 555     wxNode 
*node 
= m_objects
.First(); 
 558         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 561         obj
->CalcBoundingBox(); 
 566         m_bbox
.Expand( tmp 
); 
 571 void wxCanvasObjectGroup::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height 
) 
 573     if (!m_visible
) return; 
 575     wxTransformMatrix backup 
= *cworld
; 
 578     wxNode 
*node 
= m_objects
.First(); 
 584     wxRect absarea
=GetAbsoluteArea(*cworld
); 
 585     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 586     dc
->SetPen(*wxBLACK_PEN
); 
 587     dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
 588     dc
->DrawRectangle( absarea
.x 
, absarea
.y 
, absarea
.width 
, absarea
.height 
); 
 589     dc
->SetBrush(wxNullBrush
); 
 590     dc
->SetPen(wxNullPen
); 
 592     //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently 
 594     if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) && 
 595             wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height ) 
 601     // cycle through all objects 
 604         wxCanvasObject 
*obj 
= (wxCanvasObject
*) node
->Data(); 
 606         if (!obj
->IsControl() && obj
->GetVisible()) 
 609             //get area at the absolute position 
 610             wxRect absareaobject 
= obj
->GetAbsoluteArea(*cworld
); 
 612             // If we have 10.000 objects, we will go through 
 613             // this 10.000 times for each update, so we have 
 614             // to optimise carefully. 
 615             int clip_x 
= absareaobject
.x
; 
 616             int clip_width 
= absareaobject
.width
; 
 619                 clip_width 
-= x
-clip_x
; 
 624                 if (clip_x 
+ clip_width 
> x 
+ width
) 
 625                     clip_width 
= x
+width
-clip_x
; 
 629                     int clip_y 
= absareaobject
.y
; 
 630                     int clip_height 
= absareaobject
.height
; 
 633                         clip_height 
-= y
-clip_y
; 
 638                         if (clip_y 
+ clip_height 
> y 
+ height
) 
 639                             clip_height 
= y
+height
-clip_y
; 
 643                             obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height 
); 
 655 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream 
&stream 
) 
 659 wxCanvasObject
* wxCanvasObjectGroup::IsHitWorld( double x
, double y
, double margin 
) 
 661     //KKKfirst check if within bbox 
 662     //will only work if they are always uptodate 
 663     //if (!m_bbox.PointInBox(x,y,margin)) 
 664     //    return (wxCanvasObject*) NULL; 
 666     wxTransformMatrix inverse 
=  lworld
; 
 669     inverse
.TransformPoint(x
,y
,xh
,yh
); 
 671     wxCanvasObject 
*obj
=0; 
 672     wxNode 
*node 
= m_objects
.Last(); 
 675         obj
=(wxCanvasObject
*) node
->Data(); 
 677         if (!obj
->IsControl() ) 
 679             if (obj
->IsHitWorld(x
,y
,margin
)) 
 684         node 
= node
->Previous(); 
 687     return (wxCanvasObject
*) NULL
; 
 690 wxCanvasObject
* wxCanvasObjectGroup::Contains( wxCanvasObject
* obj 
) 
 692     wxCanvasObject
* cobj
; 
 693     wxNode 
*node 
= m_objects
.First(); 
 696         cobj
=(wxCanvasObject
*) node
->Data(); 
 698         if (cobj
->Contains(obj
)) 
 705     return (wxCanvasObject
*) NULL
; 
 708 int wxCanvasObjectGroup::IndexOf( wxCanvasObject
* obj 
) 
 710     return m_objects
.IndexOf( obj 
); 
 713 //---------------------------------------------------------------------------- 
 715 //---------------------------------------------------------------------------- 
 717 wxCanvasObjectRef::wxCanvasObjectRef(double x
, double y
, wxCanvasObject
* obj
) 
 720     lworld
.Translate(x
,y
); 
 723     m_bbox
.SetValid(FALSE
); 
 727     m_bbox
.Expand( tmp 
); 
 730 void wxCanvasObjectRef::PushEventHandler(wxEvtHandler 
*handler
) 
 732     wxCanvasObject::PushEventHandler(handler
); 
 733     m_obj
->PushEventHandler(handler
); 
 736 wxEvtHandler 
*wxCanvasObjectRef::PopEventHandler(bool deleteHandler
) 
 738     m_obj
->PopEventHandler(deleteHandler
); 
 739     return wxCanvasObject::PopEventHandler(deleteHandler
); 
 742 void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler 
*handler
) 
 744     wxCanvasObject::AppendEventHandler(handler
); 
 745     m_obj
->AppendEventHandler(handler
); 
 748 wxEvtHandler 
*wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler
) 
 750     m_obj
->RemoveLastEventHandler(deleteHandler
); 
 751     return wxCanvasObject::RemoveLastEventHandler(deleteHandler
); 
 754 void wxCanvasObjectRef::TransLate( double x
, double y 
) 
 756     lworld
.Translate(x
,y
); 
 760 wxCanvasObject
* wxCanvasObjectRef::Contains( wxCanvasObject
* obj 
) 
 762     if (obj 
== this || m_obj
->Contains(obj
)) 
 765     return (wxCanvasObject
*) NULL
; 
 769 void wxCanvasObjectRef::SetRotation(double rotation
) 
 771     lworld
.SetRotation(rotation
); 
 775 void wxCanvasObjectRef::SetScale(double scalex
,double scaley
) 
 777     lworld
.Scale(scalex
,scaley
,lworld
.GetValue(2,0),lworld
.GetValue(2,1)); 
 781 void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin
* admin
) 
 784     m_obj
->SetAdmin(admin
); 
 787 void wxCanvasObjectRef::CalcBoundingBox() 
 789     m_bbox
.SetValid(FALSE
); 
 790     m_obj
->CalcBoundingBox(); 
 793     tmp
=m_obj
->GetBbox(); 
 795     m_bbox
.Expand( tmp 
); 
 798 void wxCanvasObjectRef::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height 
) 
 800     if (!m_visible
) return; 
 802     //get the absolute area (without the local matrix included) 
 803     //the boundingbox is relative to the parent. 
 804     wxRect absarea
=GetAbsoluteArea(*cworld
); 
 806     wxTransformMatrix backup 
= *cworld
; 
 810     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 811     dc
->SetPen(*wxBLACK_PEN
); 
 812     dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
 813     dc
->DrawRectangle( absarea
.x 
, absarea
.y 
, absarea
.width 
, absarea
.height 
); 
 814     dc
->SetBrush(wxNullBrush
); 
 815     dc
->SetPen(wxNullPen
); 
 818     int clip_x 
= absarea
.x
; 
 819     int clip_width 
= absarea
.width
; 
 822         clip_width 
-= x
-clip_x
; 
 827         if (clip_x 
+ clip_width 
> x 
+ width
) 
 828             clip_width 
= x
+width
-clip_x
; 
 832             int clip_y 
= absarea
.y
; 
 833             int clip_height 
= absarea
.height
; 
 836                 clip_height 
-= y
-clip_y
; 
 841                 if (clip_y 
+ clip_height 
> y 
+ height
) 
 842                     clip_height 
= y
+height
-clip_y
; 
 845                     m_obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height 
); 
 853 void wxCanvasObjectRef::WriteSVG( wxTextOutputStream 
&stream 
) 
 857 wxCanvasObject
* wxCanvasObjectRef::IsHitWorld( double x
, double y
, double margin 
) 
 859     //KKKfirst check if within bbox 
 860     //will only work if they are always uptodate 
 861     //if (!m_bbox.PointInBox(x,y,margin)) 
 862     //    return (wxCanvasObject*) NULL; 
 864     wxTransformMatrix inverse 
=  lworld
; 
 867     inverse
.TransformPoint(x
,y
,xh
,yh
); 
 869     if (m_obj
->IsHitWorld(xh
,yh
,margin
)) 
 872     return (wxCanvasObject
*) NULL
; 
 877 //---------------------------------------------------------------------------- 
 879 //---------------------------------------------------------------------------- 
 881 wxCanvasRect::wxCanvasRect( double x
, double y
, double w
, double h 
, double radius 
) 
 890     m_brush 
= *wxBLACK_BRUSH
; 
 891     m_pen 
= *wxTRANSPARENT_PEN
; 
 895 void wxCanvasRect::TransLate( double x
, double y 
) 
 902 void wxCanvasRect::CalcBoundingBox() 
 904     m_bbox
.SetMin( m_x 
, m_y
); 
 905     m_bbox
.SetMax( m_x 
+ m_width 
,m_y 
+ m_height 
); 
 907     //include the pen width also 
 908 //KKK    m_bbox.EnLarge(m_pen.GetWidth()+m_radius); 
 909     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
 912 void wxCanvasRect::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
 914     if (!m_visible
) return; 
 916     if (cworld
->GetRotation()) 
 918         wxPoint 
*cpoints 
= new wxPoint
[4]; 
 921         cworld
->TransformPoint( m_x
, m_y
, x
, y 
); 
 922         cpoints
[0].x 
= m_admin
->LogicalToDeviceX(x
); 
 923         cpoints
[0].y 
= m_admin
->LogicalToDeviceY(y
); 
 924         cworld
->TransformPoint( m_x 
, m_y 
+ m_height
, x
, y 
); 
 925         cpoints
[1].x 
= m_admin
->LogicalToDeviceX(x
); 
 926         cpoints
[1].y 
= m_admin
->LogicalToDeviceY(y
); 
 927         cworld
->TransformPoint( m_x 
+ m_width
, m_y 
+ m_height
, x
, y 
); 
 928         cpoints
[2].x 
= m_admin
->LogicalToDeviceX(x
); 
 929         cpoints
[2].y 
= m_admin
->LogicalToDeviceY(y
); 
 930         cworld
->TransformPoint( m_x 
+ m_width
, m_y 
, x
, y 
); 
 931         cpoints
[3].x 
= m_admin
->LogicalToDeviceX(x
); 
 932         cpoints
[3].y 
= m_admin
->LogicalToDeviceY(y
); 
 934         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 935         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
 936         dc
->SetBrush(m_brush
); 
 937         int pw
=m_pen
.GetWidth(); 
 938         m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 940         dc
->DrawPolygon(4, cpoints
, 0,0,wxWINDING_RULE
); 
 942         dc
->SetBrush(wxNullBrush
); 
 943         dc
->SetPen(wxNullPen
); 
 944         dc
->DestroyClippingRegion(); 
 949         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
 950         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
 951         dc
->SetBrush(m_brush
); 
 952         int pw
=m_pen
.GetWidth(); 
 953         m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
 955         //yes the whole not only the clipping region, because we have a pen also 
 956         int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
 957         int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
 958         int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
 959         int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
 960         int r 
= m_admin
->LogicalToDeviceYRel( m_radius 
); 
 961         if (w 
> 0 && w 
< 1) w
=1; 
 962         if (w 
< 0 && w 
> -1) w
=-1; 
 963         if (h 
> 0 && h 
< 1) h
=1; 
 964         if (h 
< 0 && h 
> -1) h
=-1; 
 966             dc
->DrawRoundedRectangle( x
,y
,w
,h
,r
); 
 968             dc
->DrawRectangle( x
,y
,w
,h
); 
 969         dc
->SetBrush(wxNullBrush
); 
 970         dc
->SetPen(wxNullPen
); 
 971         dc
->DestroyClippingRegion(); 
 976 void wxCanvasRect::WriteSVG( wxTextOutputStream 
&stream 
) 
 980 //---------------------------------------------------------------------------- 
 982 //---------------------------------------------------------------------------- 
 984 wxCanvasCircle::wxCanvasCircle( double x
, double y
, double radius 
) 
 991     m_brush 
= *wxBLACK_BRUSH
; 
 992     m_pen 
= *wxTRANSPARENT_PEN
; 
 996 void wxCanvasCircle::TransLate( double x
, double y 
) 
1003 void wxCanvasCircle::CalcBoundingBox() 
1005     m_bbox
.SetMin( m_x
-m_radius 
, m_y
-m_radius 
); 
1006     m_bbox
.SetMax( m_x
+m_radius 
, m_y
+m_radius 
); 
1008     //include the pen width also 
1009     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1012 void wxCanvasCircle::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1014     if (!m_visible
) return; 
1016     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1017     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1018     dc
->SetBrush(m_brush
); 
1019     int pw
=m_pen
.GetWidth(); 
1020     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1022     //yes the whole not only the clipping region, because we have a pen also 
1023     //and rotation on a circle is not important so only a shift with cworld 
1024     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1025     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1026     int radius 
= m_admin
->LogicalToDeviceXRel( m_radius 
); 
1027     if (radius 
< 1) radius
=1; 
1028     dc
->DrawCircle( x
,y
,radius
); 
1029     dc
->SetBrush(wxNullBrush
); 
1030     dc
->SetPen(wxNullPen
); 
1031     dc
->DestroyClippingRegion(); 
1035 void wxCanvasCircle::WriteSVG( wxTextOutputStream 
&stream 
) 
1039 wxCanvasObject
* wxCanvasCircle::IsHitWorld( double x
, double y
, double margin 
) 
1041     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1042         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1043         (y 
>= m_bbox
.GetMinY()-margin
) && 
1044         (y 
<= m_bbox
.GetMaxY()+margin
) 
1047         if (m_radius
+m_pen
.GetWidth()/2+margin 
> sqrt(pow(m_x
-x
,2)+pow(m_y
-y
,2))) 
1050             return (wxCanvasObject
*) NULL
; 
1052     return (wxCanvasObject
*) NULL
; 
1055 //---------------------------------------------------------------------------- 
1057 //---------------------------------------------------------------------------- 
1059 wxCanvasEllipse::wxCanvasEllipse( double x
, double y
, double width
, double height 
) 
1067     m_brush 
= *wxBLACK_BRUSH
; 
1068     m_pen 
= *wxTRANSPARENT_PEN
; 
1072 void wxCanvasEllipse::TransLate( double x
, double y 
) 
1079 void wxCanvasEllipse::CalcBoundingBox() 
1081     m_bbox
.SetMin( m_x
, m_y 
); 
1082     m_bbox
.SetMax( m_x
+m_width 
, m_y
+m_height 
); 
1084     //include the pen width also 
1085     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1088 void wxCanvasEllipse::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1090     if (!m_visible
) return; 
1092     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1093     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1094     dc
->SetBrush(m_brush
); 
1095     int pw
=m_pen
.GetWidth(); 
1096     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1098     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1099     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1100     int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1101     int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1102     if (w 
> 0 && w 
< 1) w
=1; 
1103     if (w 
< 0 && w 
> -1) w
=-1; 
1104     if (h 
> 0 && h 
< 1) h
=1; 
1105     if (h 
< 0 && h 
> -1) h
=-1; 
1106     dc
->DrawEllipse( x
,y
,w
,h
); 
1107     dc
->SetBrush(wxNullBrush
); 
1108     dc
->SetPen(wxNullPen
); 
1109     dc
->DestroyClippingRegion(); 
1113 void wxCanvasEllipse::WriteSVG( wxTextOutputStream 
&stream 
) 
1117 wxCanvasObject
* wxCanvasEllipse::IsHitWorld( double x
, double y
, double margin 
) 
1119     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1120         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1121         (y 
>= m_bbox
.GetMinY()-margin
) && 
1122         (y 
<= m_bbox
.GetMaxY()+margin
) 
1125         double a
=(m_width
+m_pen
.GetWidth())/2+margin 
; 
1126         double b
=(m_height
+m_pen
.GetWidth())/2+margin
; 
1127         double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2); 
1131             return (wxCanvasObject
*) NULL
; 
1133     return (wxCanvasObject
*) NULL
; 
1136 //---------------------------------------------------------------------------- 
1137 // wxCanvasEllipticArc 
1138 //---------------------------------------------------------------------------- 
1140 wxCanvasEllipticArc::wxCanvasEllipticArc( double x
, double y
, double width
, double height
, double start
, double end 
) 
1150     m_brush 
= *wxBLACK_BRUSH
; 
1151     m_pen 
= *wxTRANSPARENT_PEN
; 
1155 void wxCanvasEllipticArc::TransLate( double x
, double y 
) 
1162 void wxCanvasEllipticArc::CalcBoundingBox() 
1164     m_bbox
.SetMin( m_x
, m_y 
); 
1165     m_bbox
.SetMax( m_x
+m_width 
, m_y
+m_height 
); 
1167     //include the pen width also 
1168     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1171 void wxCanvasEllipticArc::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1173     if (!m_visible
) return; 
1175     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1176     dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1177     dc
->SetBrush(m_brush
); 
1178     int pw
=m_pen
.GetWidth(); 
1179     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1181     int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1182     int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1183     int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1184     int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1185     if (w 
> 0 && w 
< 1) w
=1; 
1186     if (w 
< 0 && w 
> -1) w
=-1; 
1187     if (h 
> 0 && h 
< 1) h
=1; 
1188     if (h 
< 0 && h 
> -1) h
=-1; 
1189     if (m_admin
->GetActive()->GetYaxis()) 
1190         dc
->DrawEllipticArc( x
,y
,w
,h
,-m_end
,-m_start
); 
1192         dc
->DrawEllipticArc( x
,y
,w
,h
,m_start
,m_end
); 
1193     dc
->SetBrush(wxNullBrush
); 
1194     dc
->SetPen(wxNullPen
); 
1195     dc
->DestroyClippingRegion(); 
1199 void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream 
&stream 
) 
1203 wxCanvasObject
* wxCanvasEllipticArc::IsHitWorld( double x
, double y
, double margin 
) 
1205     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1206         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1207         (y 
>= m_bbox
.GetMinY()-margin
) && 
1208         (y 
<= m_bbox
.GetMaxY()+margin
) 
1211         double a
=(m_width
+m_pen
.GetWidth())/2+margin 
; 
1212         double b
=(m_height
+m_pen
.GetWidth())/2+margin
; 
1213         double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2); 
1217             return (wxCanvasObject
*) NULL
; 
1219     return (wxCanvasObject
*) NULL
; 
1222 //---------------------------------------------------------------------------- 
1224 //---------------------------------------------------------------------------- 
1226 wxCanvasLine::wxCanvasLine( double x1
, double y1
, double x2
, double y2 
) 
1234     m_pen 
= *wxBLACK_PEN
; 
1238 void wxCanvasLine::TransLate( double x
, double y 
) 
1247 void wxCanvasLine::CalcBoundingBox() 
1249     m_bbox
.SetMin( m_x1 
, m_y1
); 
1250     m_bbox
.SetMax( m_x2 
, m_y2
); 
1252     //include the pen width also 
1253     m_bbox
.EnLarge(m_pen
.GetWidth()/2); 
1256 void wxCanvasLine::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1258     if (!m_visible
) return; 
1261     cworld
->TransformPoint( m_x1
, m_y1
, x1
, y1 
); 
1262     cworld
->TransformPoint( m_x2
, m_y2
, x2
, y2 
); 
1263     x1 
= m_admin
->LogicalToDeviceX( x1 
); 
1264     y1 
= m_admin
->LogicalToDeviceY( y1 
); 
1265     x2 
= m_admin
->LogicalToDeviceX( x2 
); 
1266     y2 
= m_admin
->LogicalToDeviceY( y2 
); 
1268     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1269     dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height 
); 
1270     int pw
=m_pen
.GetWidth(); 
1271     m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
)); 
1272     dc
->SetPen( m_pen 
); 
1273     dc
->DrawLine( x1
, y1
, x2
, y2 
); 
1275     dc
->DestroyClippingRegion(); 
1279 void wxCanvasLine::WriteSVG( wxTextOutputStream 
&stream 
) 
1284 wxCanvasObject
* wxCanvasLine::IsHitWorld( double x
, double y
, double margin 
) 
1286     if ((x 
>= m_bbox
.GetMinX()-margin
) && 
1287         (x 
<= m_bbox
.GetMaxX()+margin
) && 
1288         (y 
>= m_bbox
.GetMinY()-margin
) && 
1289         (y 
<= m_bbox
.GetMaxY()+margin
) 
1292         wxLine 
line1(m_x1
,m_y1
,m_x2
,m_y2
); 
1293         wxPoint2DDouble P
=wxPoint2DDouble(x
,y
); 
1295         if (line1
.PointInLine(P
,distance
,m_pen
.GetWidth()/2+margin
) == R_IN_AREA
) 
1298             return (wxCanvasObject
*) NULL
; 
1300     return (wxCanvasObject
*) NULL
; 
1303 //---------------------------------------------------------------------------- 
1305 //---------------------------------------------------------------------------- 
1307 wxCanvasImage::wxCanvasImage( const wxImage 
&image
, double x
, double y
, double w
, double h 
) 
1317     m_orgw 
= m_image
.GetWidth(); 
1318     m_orgh 
= m_image
.GetHeight(); 
1324 void wxCanvasImage::TransLate( double x
, double y 
) 
1331 void wxCanvasImage::CalcBoundingBox() 
1333     m_bbox
.SetMin( m_x
, m_y 
); 
1334     m_bbox
.SetMax( m_x 
+ m_width
, m_y 
+ m_height 
); 
1337 void wxCanvasImage::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1339     if (!m_visible
) return; 
1343     tmparea
.x 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX()); 
1344     tmparea
.y 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY()); 
1345     tmparea
.width 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ); 
1346     tmparea
.height 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ); 
1350     cworld
->TransformPoint( m_x
, m_y
, x
, y 
); 
1351     x 
= m_admin
->LogicalToDeviceX(x
); 
1352     y 
= m_admin
->LogicalToDeviceY(y
); 
1355     if (  m_orgw
*5 < m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()  ) || 
1356           m_orgw
/5 > m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()  ) || 
1357           m_orgh
*5 < m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) || 
1358           m_orgh
/5 > m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) 
1361         wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1362         dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
); 
1363         dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
1364         dc
->SetPen(*wxBLACK_PEN
); 
1365         //yes the whole not only the clipping region, because we have a pen also 
1366         int x 
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x 
); 
1367         int y 
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y 
); 
1368         int w 
= m_admin
->LogicalToDeviceXRel( m_width 
); 
1369         int h 
= m_admin
->LogicalToDeviceYRel( m_height 
); 
1372         dc
->DrawRectangle( x
,y
,w
,h
); 
1373         dc
->SetBrush(wxNullBrush
); 
1374         dc
->SetPen(wxNullPen
); 
1375         dc
->DestroyClippingRegion(); 
1379     if ((m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) == m_image
.GetWidth()) && 
1380         (m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) == m_image
.GetHeight())) 
1386         m_tmp 
= m_image
.Scale( m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()), 
1387                                m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight()) ); 
1391 //    wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y)); 
1394     if (cworld
->GetRotation()) 
1396         bmp
=m_tmp
.Rotate(-cworld
->GetRotation()/180.0 * pi
,centr
, TRUE
,  NULL
).ConvertToBitmap(); 
1400         bmp 
= m_tmp
.ConvertToBitmap(); 
1403     wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1406     if (cworld
->GetRotation()> 0) 
1408         centr2
.x
= (int) (x
+m_height
*sin(-cworld
->GetRotation()/180.0 * pi
)); 
1414         centr2
.y
= (int) (y
-m_width
*sin(-cworld
->GetRotation()/180.0 * pi
)); 
1417     if (cworld
->GetRotation() != 0) 
1419         //TODO clipping not right 
1420             dc
->DrawBitmap(bmp
,centr2
,TRUE 
); 
1421 //        dc->DrawPoint(centr2); 
1422 //        dc->DrawPoint(x,y); 
1426         //TODO clipping not right 
1427 //        dc->DrawPoint(centr2); 
1428 //        dc->DrawPoint(x,y); 
1430         if ((clip_x 
== x
) && 
1432             (clip_width 
== tmparea
.width
) && 
1433             (clip_height 
== tmparea
.height
)) 
1435             dc
->DrawBitmap( m_tmp
, clip_x
, clip_y
, TRUE 
); 
1439             int start_x 
= clip_x 
- (int)x
; 
1440             int start_y 
= clip_y 
- (int)y
; 
1442             //dc->DrawBitmap( bmp, x, y, TRUE ); 
1444             dcm
.SelectObject(bmp
); 
1445             dc
->Blit(clip_x
, clip_y
,clip_width
, clip_height
,&dcm
,start_x
,start_y
,wxCOPY
,TRUE
); 
1446             dcm
.SelectObject(wxNullBitmap
); 
1451 void wxCanvasImage::WriteSVG( wxTextOutputStream 
&stream 
) 
1456 //---------------------------------------------------------------------------- 
1458 //---------------------------------------------------------------------------- 
1460 wxCanvasControl::wxCanvasControl( wxWindow 
*control 
) 
1464     m_control 
= control
; 
1468 double wxCanvasControl::GetPosX() 
1471     m_control
->GetPosition( &x
, &y 
); 
1472     return m_admin
->DeviceToLogicalX(x
); 
1475 double wxCanvasControl::GetPosY() 
1478     m_control
->GetPosition( &x
, &y 
); 
1479     return m_admin
->DeviceToLogicalY(y
); 
1482 void wxCanvasControl::SetPosXY( double x
, double y
) 
1484     int xd 
= m_admin
->LogicalToDeviceX(x
); 
1485     int yd 
= m_admin
->LogicalToDeviceY(y
); 
1486     m_control
->Move(xd
,yd
); 
1490 void wxCanvasControl::TransLate( double x
, double y 
) 
1493     m_control
->GetPosition( &xdo
, &ydo 
); 
1494     int xd 
= m_admin
->LogicalToDeviceX(x
)-xdo
; 
1495     int yd 
= m_admin
->LogicalToDeviceY(y
)-ydo
; 
1496     m_control
->Move(xd
,yd
); 
1500 wxCanvasControl::~wxCanvasControl() 
1502     m_control
->Destroy(); 
1505 void wxCanvasControl::CalcBoundingBox() 
1509     m_control
->GetSize( &tmparea
.width
, &tmparea
.height 
); 
1510     m_control
->GetPosition( &tmparea
.x
, &tmparea
.y 
); 
1512     m_bbox
.SetMin( tmparea
.x 
, tmparea
.y
); 
1513     m_bbox
.SetMax( tmparea
.x 
+ tmparea
.width 
, tmparea
.y 
+ tmparea
.height
); 
1517 void wxCanvasControl::MoveRelative( double x
, double y 
) 
1519     m_control
->Move( m_admin
->LogicalToDeviceX(x
),  m_admin
->LogicalToDeviceX(y
) ); 
1522 //---------------------------------------------------------------------------- 
1524 //---------------------------------------------------------------------------- 
1536 wxCanvasText::wxCanvasText( const wxString 
&text
, double x
, double y
, const wxString 
&fontFile
, int size 
) 
1540     m_fontFileName 
= fontFile
; 
1553     wxFaceData 
*data 
= new wxFaceData
; 
1556     int error 
= FT_New_Face( g_freetypeLibrary
, 
1561     error 
= FT_Set_Char_Size( data
->m_face
, 
1570 wxCanvasText::~wxCanvasText() 
1573     wxFaceData 
*data 
= (wxFaceData
*) m_faceData
; 
1577     if (m_alpha
) delete [] m_alpha
; 
1580 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue 
) 
1587 void wxCanvasText::SetFlag( int flag 
) 
1592 void wxCanvasText::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height 
) 
1594     if (!m_visible
) return; 
1597     tmparea
.x 
= m_admin
->LogicalToDeviceX( m_bbox
.GetMinX()); 
1598     tmparea
.y 
= m_admin
->LogicalToDeviceY( m_bbox
.GetMinY()); 
1599     tmparea
.width 
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ); 
1600     tmparea
.height 
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ); 
1602     m_alpha 
= new unsigned char[tmparea
.width
*tmparea
.height
]; 
1603     memset( m_alpha
, 0, tmparea
.width
*tmparea
.height 
); 
1605     if (!m_alpha
) return; 
1608     FT_Face face 
= ((wxFaceData
*)m_faceData
)->m_face
; 
1609     FT_GlyphSlot slot 
= face
->glyph
; 
1613     for (int n 
= 0; n 
< (int)m_text
.Len(); n
++) 
1615         FT_UInt index 
= FT_Get_Char_Index( face
, m_text
[(unsigned int)n
] ); 
1617         int error 
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT 
); 
1618         if (error
) continue; 
1620         error 
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal 
); 
1621         if (error
) continue; 
1623         FT_Bitmap 
*bitmap 
= &slot
->bitmap
; 
1624         unsigned char* buffer 
= bitmap
->buffer
; 
1625         for (int y 
= 0; y 
< bitmap
->rows
; y
++) 
1626             for (int x 
= 0; x 
< bitmap
->width
; x
++) 
1628                 unsigned char alpha 
= buffer
[ y
*bitmap
->pitch 
+ x 
]; 
1629                 if (alpha 
== 0) continue; 
1631                 int xx 
= pen_x 
+ slot
->bitmap_left 
+ x
; 
1632                 int yy 
= pen_y 
- slot
->bitmap_top 
+ y
; 
1633                 m_alpha
[ yy 
* tmparea
.width 
+ xx 
] = alpha
; 
1636         pen_x 
+= slot
->advance
.x 
>> 6; 
1637         pen_y 
+= slot
->advance
.y 
>> 6; 
1641     wxBitmap 
*bitmap 
= m_admin
->GetActive()->GetBuffer(); 
1642     wxRect 
sub_rect( clip_x
, clip_y
, clip_width
, clip_height 
); 
1643     wxBitmap 
sub_bitmap( bitmap
->GetSubBitmap( sub_rect 
) ); 
1645     wxImage 
image( sub_bitmap 
); 
1647     // local coordinates 
1648     int start_x 
= clip_x 
- tmparea
.x
; 
1649     int end_x 
= clip_width 
+ start_x
; 
1650     int start_y 
= clip_y 
- tmparea
.y
; 
1651     int end_y 
= clip_height 
+ start_y
; 
1653     for (int y 
= start_y
; y 
< end_y
; y
++) 
1654         for (int x 
= start_x
; x 
< end_x
; x
++) 
1656             int alpha 
= m_alpha
[y
*tmparea
.width 
+ x
]; 
1659                 int image_x 
= x 
- start_x
; 
1660                 int image_y 
= y 
- start_y
; 
1663                     image
.SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue 
); 
1666                 int red1 
= (m_red 
* alpha
) / 255; 
1667                 int green1 
= (m_green 
* alpha
) / 255; 
1668                 int blue1 
= (m_blue 
* alpha
) / 255; 
1671                 int red2 
= image
.GetRed( image_x
, image_y 
); 
1672                 int green2 
= image
.GetGreen( image_x
, image_y 
); 
1673                 int blue2 
= image
.GetBlue( image_x
, image_y 
); 
1674                 red2 
= (red2 
* alpha
) / 255; 
1675                 green2 
= (green2 
* alpha
) / 255; 
1676                 blue2 
= (blue2 
* alpha
) / 255; 
1678                 image
.SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2 
); 
1682    sub_bitmap 
= image
.ConvertToBitmap(); 
1684    wxDC 
*dc 
= m_admin
->GetActive()->GetDC(); 
1685    dc
->DrawBitmap( sub_bitmap
, clip_x
, clip_y 
); 
1688 void wxCanvasText::WriteSVG( wxTextOutputStream 
&stream 
) 
1692 void wxCanvasText::TransLate( double x
, double y 
) 
1699 void wxCanvasText::CalcBoundingBox() 
1701     if (m_alpha
) delete [] m_alpha
; 
1703     m_bbox
.SetMin( m_x 
, m_y
); 
1704     m_bbox
.SetMax( m_x 
+ 100 , m_y 
+ m_size 
+ (m_size
/2)); 
1709 //---------------------------------------------------------------------------- 
1711 //---------------------------------------------------------------------------- 
1713 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
) 
1715 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
) 
1716     EVT_PAINT( wxCanvas::OnPaint 
) 
1717     EVT_IDLE( wxCanvas::OnIdle 
) 
1718     EVT_SIZE( wxCanvas::OnSize 
) 
1719     EVT_MOUSE_EVENTS( wxCanvas::OnMouse 
) 
1720     EVT_SET_FOCUS( wxCanvas::OnSetFocus 
) 
1721     EVT_KILL_FOCUS( wxCanvas::OnKillFocus 
) 
1722     EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground 
) 
1725 wxCanvas::wxCanvas( wxCanvasAdmin
* admin
, wxWindow 
*parent
, wxWindowID id
, 
1726     const wxPoint 
&position
, const wxSize
& size
, long style 
) : 
1727     wxScrolledWindow( parent
, id
, position
, size
, style 
) 
1729     // These are unused in wxVectorCanvas 
1734     m_admin
->Append( this ); 
1736     m_needUpdate 
= FALSE
; 
1737     m_background 
= *wxWHITE
; 
1738     m_lastMouse 
= (wxCanvasObject
*)NULL
; 
1739     m_captureMouse 
= (wxCanvasObject
*)NULL
; 
1743     m_root 
= (wxCanvasObjectGroup
*)NULL
; 
1746 wxCanvas::~wxCanvas() 
1748     wxNode 
*node 
= m_updateRects
.First(); 
1751         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1753         m_updateRects
.DeleteNode( node 
); 
1754         node 
= m_updateRects
.First(); 
1758 double wxCanvas::GetMinX() const 
1763 double wxCanvas::GetMinY() const 
1768 double wxCanvas::GetMaxX() const 
1771    GetVirtualSize( &width
, NULL 
); 
1775 double wxCanvas::GetMaxY() const 
1778    GetVirtualSize( NULL
, &height 
); 
1782 void wxCanvas::SetColour( const wxColour
& background 
) 
1784     m_background 
= background
; 
1785     SetBackgroundColour( m_background 
); 
1787     if (m_frozen
) return; 
1790     dc
.SelectObject( m_buffer 
); 
1791     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1792     wxBrush 
brush( m_background
, wxSOLID 
); 
1793     dc
.SetBrush( brush 
); 
1794     dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
1795     dc
.SelectObject( wxNullBitmap 
); 
1798 void wxCanvas::SetCaptureMouse( wxCanvasObject 
*obj 
) 
1802         wxWindow::CaptureMouse(); 
1803         m_captureMouse 
= obj
; 
1807         wxWindow::ReleaseMouse(); 
1808         m_captureMouse 
= NULL
; 
1812 void wxCanvas::Freeze() 
1817 void wxCanvas::Thaw() 
1819     wxNode 
*node 
= m_updateRects
.First(); 
1822         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1824         m_updateRects
.DeleteNode( node 
); 
1825         node 
= m_updateRects
.First(); 
1831         Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
1834 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit 
) 
1836     CalcScrolledPosition( 0, 0, &m_oldDeviceX
, &m_oldDeviceY 
); 
1838     m_admin
->SetActive(this); 
1840     if (!m_root
) return; 
1842     if (m_frozen
) return; 
1847         width 
-= m_bufferX
-x
; 
1850     if (width 
<= 0) return; 
1854         height 
-= m_bufferY
-y
; 
1857     if (height 
<= 0) return; 
1859     if (x
+width 
> m_bufferX
+m_buffer
.GetWidth()) 
1861         width 
= m_bufferX
+m_buffer
.GetWidth() - x
; 
1863     if (width 
<= 0) return; 
1865     if (y
+height 
> m_bufferY
+m_buffer
.GetHeight()) 
1867         height 
= m_bufferY
+m_buffer
.GetHeight() - y
; 
1869     if (height 
<= 0) return; 
1871     // update is within the buffer 
1872     m_needUpdate 
= TRUE
; 
1874     // has to be blitted to screen later 
1877         m_updateRects
.Append( 
1878             (wxObject
*) new wxRect( x
,y
,width
,height 
) ); 
1881     wxTransformMatrix cworld
; 
1884     dc
.SelectObject( m_buffer 
); 
1886     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1887     wxBrush 
brush( m_background
, wxSOLID 
); 
1888     dc
.SetBrush( brush 
); 
1889     dc
.SetLogicalFunction(wxCOPY
); 
1892     if (width 
!= m_buffer
.GetWidth() && height 
!= m_buffer
.GetHeight()) 
1894         dc
.SetClippingRegion(x
,y
,width
,height
); 
1895         dc
.DrawRectangle(x
-2,y
-2,width
+4,height
+4); 
1896         dc
.DestroyClippingRegion(); 
1901         dc
.DrawRectangle(0,0,m_buffer
.GetWidth(),m_buffer
.GetHeight()); 
1904     // No idea, what the code up there does. 
1905     dc
.DrawRectangle( x
-m_bufferX
, y
-m_bufferY
, width
, height 
); 
1908     dc
.SetBrush(wxNullBrush
); 
1909     dc
.SetPen(wxNullPen
); 
1911     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
1914     m_root
->Render( &cworld
, x
, y
, width
, height 
); 
1917     dc
.SelectObject( wxNullBitmap 
); 
1920 void wxCanvas::BlitBuffer( wxDC 
&dc 
) 
1922     wxNode 
*node 
= m_updateRects
.First(); 
1925         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1928         mdc
.SelectObject( m_buffer 
); 
1934                  rect
->x 
- m_bufferX
, 
1935                  rect
->y 
- m_bufferY 
);  
1936         mdc
.SelectObject( wxNullBitmap 
); 
1939         m_updateRects
.DeleteNode( node 
); 
1940         node 
= m_updateRects
.First(); 
1943     m_needUpdate 
= FALSE
; 
1946 void wxCanvas::UpdateNow() 
1948     if (m_frozen
) return; 
1950     if (!m_needUpdate
) return; 
1952     wxClientDC 
dc( this ); 
1958 void wxCanvas::OnSize(wxSizeEvent 
&event
) 
1961     GetClientSize( &w
, &h 
); 
1962     m_buffer 
= wxBitmap( w
, h 
); 
1964     CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY 
); 
1966     wxNode 
*node 
= m_updateRects
.First(); 
1969         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
1971         m_updateRects
.DeleteNode( node 
); 
1972         node 
= m_updateRects
.First(); 
1977     Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
1982 void wxCanvas::OnPaint(wxPaintEvent 
&event
) 
1987     if (!m_buffer
.Ok()) return; 
1989     if (m_frozen
) return; 
1991     m_needUpdate 
= TRUE
; 
1993     wxRegionIterator 
it( GetUpdateRegion() ); 
1999         int w 
= it
.GetWidth(); 
2000         int h 
= it
.GetHeight(); 
2002         if (x
+w 
> m_buffer
.GetWidth()) 
2003             w 
= m_buffer
.GetWidth() - x
; 
2004         if (y
+h 
> m_buffer
.GetHeight()) 
2005             h 
= m_buffer
.GetHeight() - y
; 
2007         if ((w 
> 0) && (h 
> 0)) 
2011             m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h 
) ); 
2020 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect 
) 
2022     // If any updates are pending, do them now since they will 
2023     // expect the previous m_bufferX and m_bufferY as well as 
2024     // the previous device origin values. 
2025     wxClientDC 
dc( this ); 
2026     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
2029     // The buffer always starts at the top left corner of the 
2030     // client area. Indeed, it is the client area. 
2031     CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY 
); 
2033     // Update everything. 
2034     Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
2036     // Scroll, actually. 
2037     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
2040 void wxCanvas::OnMouse(wxMouseEvent 
&event
) 
2042     m_admin
->SetActive(this); 
2049     int x 
= event
.GetX(); 
2050     int y 
= event
.GetY(); 
2052     //to world coordinates to do hit test in world coordinates 
2053     double xw 
= DeviceToLogicalX( x 
); 
2054     double yw 
= DeviceToLogicalY( y 
); 
2056     //make a select margin of 2 pixels, so also zero line thickness will be hit 
2057     double margin 
= DeviceToLogicalXRel( 2 ); 
2059     if (event
.GetEventType() == wxEVT_MOTION
) 
2061         if (m_captureMouse
) //no matter what go to this one 
2063             wxMouseEvent 
child_event( wxEVT_MOTION 
); 
2064             child_event
.SetEventObject(m_captureMouse
); 
2065             child_event
.m_x 
= x
; 
2066             child_event
.m_y 
= y
; 
2067             child_event
.m_leftDown 
= event
.m_leftDown
; 
2068             child_event
.m_rightDown 
= event
.m_rightDown
; 
2069             child_event
.m_middleDown 
= event
.m_middleDown
; 
2070             child_event
.m_controlDown 
= event
.m_controlDown
; 
2071             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2072             child_event
.m_altDown 
= event
.m_altDown
; 
2073             child_event
.m_metaDown 
= event
.m_metaDown
; 
2075             m_captureMouse
->ProcessCanvasObjectEvent( child_event 
); 
2080             wxCanvasObject 
*obj 
= m_root
->IsHitWorld(xw
,yw
,margin
); 
2082             if (obj 
&& !obj
->IsControl()) 
2084                 wxMouseEvent 
child_event( wxEVT_MOTION 
); 
2085                 child_event
.SetEventObject( obj 
); 
2086                 child_event
.m_x 
= x
; 
2087                 child_event
.m_y 
= y
; 
2088                 child_event
.m_leftDown 
= event
.m_leftDown
; 
2089                 child_event
.m_rightDown 
= event
.m_rightDown
; 
2090                 child_event
.m_middleDown 
= event
.m_middleDown
; 
2091                 child_event
.m_controlDown 
= event
.m_controlDown
; 
2092                 child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2093                 child_event
.m_altDown 
= event
.m_altDown
; 
2094                 child_event
.m_metaDown 
= event
.m_metaDown
; 
2096                 if ((obj 
!= m_lastMouse
) && (m_lastMouse 
!= NULL
)) 
2098                     child_event
.SetEventType( wxEVT_LEAVE_WINDOW 
); 
2099                     child_event
.SetEventObject( m_lastMouse 
); 
2100                     child_event
.m_x 
= x
; 
2101                     child_event
.m_y 
= y
; 
2102                     m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2105                     child_event
.SetEventType( wxEVT_ENTER_WINDOW 
); 
2106                     child_event
.SetEventObject( m_lastMouse 
); 
2107                     child_event
.m_x 
= x
; 
2108                     child_event
.m_y 
= y
; 
2109                     m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2111                     child_event
.SetEventType( wxEVT_MOTION 
); 
2112                     child_event
.SetEventObject( obj 
); 
2115                 obj
->ProcessCanvasObjectEvent( child_event 
); 
2121             wxMouseEvent 
child_event( wxEVT_LEAVE_WINDOW 
); 
2122             child_event
.SetEventObject( m_lastMouse 
); 
2123             child_event
.m_x 
= x
; 
2124             child_event
.m_y 
= y
; 
2125             child_event
.m_leftDown 
= event
.m_leftDown
; 
2126             child_event
.m_rightDown 
= event
.m_rightDown
; 
2127             child_event
.m_middleDown 
= event
.m_middleDown
; 
2128             child_event
.m_controlDown 
= event
.m_controlDown
; 
2129             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2130             child_event
.m_altDown 
= event
.m_altDown
; 
2131             child_event
.m_metaDown 
= event
.m_metaDown
; 
2132             m_lastMouse
->ProcessCanvasObjectEvent( child_event 
); 
2134             m_lastMouse 
= (wxCanvasObject
*) NULL
; 
2140         if (m_captureMouse
) //no matter what go to this one 
2142             wxMouseEvent 
child_event( event
.GetEventType() ); 
2143             child_event
.SetEventObject(m_captureMouse
); 
2144             child_event
.m_x 
= x
; 
2145             child_event
.m_y 
= y
; 
2146             child_event
.m_leftDown 
= event
.m_leftDown
; 
2147             child_event
.m_rightDown 
= event
.m_rightDown
; 
2148             child_event
.m_middleDown 
= event
.m_middleDown
; 
2149             child_event
.m_controlDown 
= event
.m_controlDown
; 
2150             child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2151             child_event
.m_altDown 
= event
.m_altDown
; 
2152             child_event
.m_metaDown 
= event
.m_metaDown
; 
2153             m_captureMouse
->ProcessCanvasObjectEvent( child_event 
); 
2157             wxCanvasObject 
*obj 
= m_root
->IsHitWorld(xw
,yw
,margin
); 
2159             if (obj 
&& !obj
->IsControl()) 
2161                 wxMouseEvent 
child_event( event
.GetEventType() ); 
2162                 child_event
.SetEventObject( obj 
); 
2163                 child_event
.m_x 
= x
; 
2164                 child_event
.m_y 
= y
; 
2165                 child_event
.m_leftDown 
= event
.m_leftDown
; 
2166                 child_event
.m_rightDown 
= event
.m_rightDown
; 
2167                 child_event
.m_middleDown 
= event
.m_middleDown
; 
2168                 child_event
.m_controlDown 
= event
.m_controlDown
; 
2169                 child_event
.m_shiftDown 
= event
.m_shiftDown
; 
2170                 child_event
.m_altDown 
= event
.m_altDown
; 
2171                 child_event
.m_metaDown 
= event
.m_metaDown
; 
2173                 obj
->ProcessCanvasObjectEvent( child_event 
); 
2182 void wxCanvas::OnIdle(wxIdleEvent 
&event
) 
2184     m_admin
->SetActive(this); 
2189 void wxCanvas::OnSetFocus(wxFocusEvent 
&event
) 
2191     m_admin
->SetActive(this); 
2194 void wxCanvas::OnKillFocus(wxFocusEvent 
&event
) 
2199 void wxCanvas::OnEraseBackground(wxEraseEvent 
&event
) 
2203 // coordinates conversions 
2204 // ----------------------- 
2205 double wxCanvas::DeviceToLogicalX(int x
) const 
2210 double wxCanvas::DeviceToLogicalY(int y
) const 
2215 double wxCanvas::DeviceToLogicalXRel(int x
) const 
2220 double wxCanvas::DeviceToLogicalYRel(int y
) const 
2225 int wxCanvas::LogicalToDeviceX(double x
) const 
2227     return (int)(x 
+ 0.5); 
2230 int wxCanvas::LogicalToDeviceY(double y
) const 
2232     return (int)(y 
+ 0.5); 
2235 int wxCanvas::LogicalToDeviceXRel(double x
) const 
2237     return (int)(x 
+ 0.5); 
2240 int wxCanvas::LogicalToDeviceYRel(double y
) const 
2242     return (int)(y 
+ 0.5); 
2245 //---------------------------------------------------------------------------- 
2247 //---------------------------------------------------------------------------- 
2249 IMPLEMENT_CLASS(wxVectorCanvas
,wxCanvas
) 
2251 BEGIN_EVENT_TABLE(wxVectorCanvas
,wxCanvas
) 
2252     EVT_SCROLLWIN( wxVectorCanvas::OnScroll 
) 
2253     EVT_CHAR( wxVectorCanvas::OnChar 
) 
2254     EVT_SIZE( wxVectorCanvas::OnSize 
) 
2257 wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin
* admin
, wxWindow 
*parent
, wxWindowID id
, 
2258     const wxPoint 
&position
, const wxSize
& size
, long style 
) : 
2259     wxCanvas( admin
, parent
, id
, position
, size
, style 
) 
2265 double wxVectorCanvas::GetMinX() const 
2270 double wxVectorCanvas::GetMinY() const 
2275 double wxVectorCanvas::GetMaxX() const 
2280 double wxVectorCanvas::GetMaxY() const 
2285 void wxVectorCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect 
) 
2287     // If any updates are pending, do them now since they will 
2288     // expect the previous m_bufferX and m_bufferY as well as 
2289     // the previous device origin values. 
2290     wxClientDC 
dc( this ); 
2291     dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY 
); 
2296         double dyv
=DeviceToLogicalYRel(dy
); 
2297         m_virt_minY
=m_virt_minY
-dyv
; 
2298         m_virt_maxY
=m_virt_maxY
-dyv
; 
2302         double dxv
=DeviceToLogicalXRel(dx
); 
2303         m_virt_minX
=m_virt_minX
-dxv
; 
2304         m_virt_maxX
=m_virt_maxX
-dxv
; 
2307     m_admin
->SetActive(this); 
2308     SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
); 
2313         if (dy 
> 0 && dy 
< m_buffer
.GetHeight()) 
2315             wxRect 
rect( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight()-dy
); 
2316             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2318             dcm
.SelectObject( m_buffer 
); 
2319             dcm
.DrawBitmap( sub_bitmap
, 0, dy
, TRUE 
); 
2320             dcm
.SelectObject( wxNullBitmap 
); 
2322             Update( 0, 0, m_buffer
.GetWidth(), dy
, TRUE 
); 
2324         else  if (dy 
< 0 && dy 
> -m_buffer
.GetHeight()) 
2326             wxRect 
rect( 0, -dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight()+dy
); 
2327             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2329             dcm
.SelectObject( m_buffer 
); 
2330             dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE 
); 
2331             dcm
.SelectObject( wxNullBitmap 
); 
2333             Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2336             Update( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2341         if (dx 
> 0 && dx 
< m_buffer
.GetWidth()) 
2343             wxRect 
rect( 0, 0, m_buffer
.GetWidth()-dx
, m_buffer
.GetHeight()); 
2344             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2346             dcm
.SelectObject( m_buffer 
); 
2347             dcm
.DrawBitmap( sub_bitmap
, dx
, 0, TRUE 
); 
2348             dcm
.SelectObject( wxNullBitmap 
); 
2350             Update( 0, 0, dx
, m_buffer
.GetHeight(), TRUE 
); 
2352         else if (dx 
< 0 && dx 
> -m_buffer
.GetWidth()) 
2354             wxRect 
rect( -dx
, 0, m_buffer
.GetWidth()+dx
, m_buffer
.GetHeight()); 
2355             wxBitmap 
sub_bitmap( m_buffer
.GetSubBitmap( rect 
) ); 
2357             dcm
.SelectObject( m_buffer 
); 
2358             dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE 
); 
2359             dcm
.SelectObject( wxNullBitmap 
); 
2361             Update( m_buffer
.GetWidth()+dx
, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2364             Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE 
); 
2367     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
2369     //must be done now because quick repeated scrolling will prevent wxPaint 
2370     //from doing it properly 
2374 void wxVectorCanvas::OnSize(wxSizeEvent 
&event
) 
2378     GetClientSize( &w
, &h 
); 
2381     m_buffer 
= wxBitmap( w
, h 
); 
2382     dc
.SelectObject( m_buffer 
); 
2383     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
2384     wxBrush 
brush( m_background 
, wxSOLID 
); 
2385     dc
.SetBrush( brush 
); 
2386     dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() ); 
2387     dc
.SelectObject( wxNullBitmap 
); 
2389     wxNode 
*node 
= m_updateRects
.First(); 
2392         wxRect 
*rect 
= (wxRect
*) node
->Data(); 
2394         m_updateRects
.DeleteNode( node 
); 
2395         node 
= m_updateRects
.First(); 
2400     m_admin
->SetActive(this); 
2401     SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
); 
2403     Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE 
); 
2408 // maps the virtual window (Real drawing to the window coordinates 
2409 // also used for zooming 
2410 void wxVectorCanvas::SetMappingScroll( double vx1
,    double vy1
, double vx2
, double vy2
, bool border
) 
2413     GetClientSize(&dwxi
,&dwyi
); 
2415     if (vx2
==vx1
) vx2
=vx1
+100000; 
2416     if (vy2
==vy1
) vy2
=vy1
+100000; 
2427     double dvx 
= m_virt_maxX 
- m_virt_minX
; 
2428     double dvy 
= m_virt_maxY 
- m_virt_minY
; 
2430     // calculate the scaling factor for the virtual window 
2433     if ((dvy 
/ dvx
) < (dwy 
/ dwx
)) 
2435         dvy 
= dvx 
* (dwy 
/ dwx
); 
2436         // calculate the change in the coordinates 
2437         temp_y 
= (dvy 
- (m_virt_maxY 
- m_virt_minY
) )/ 2.0; 
2441         dvx 
= dvy 
* (dwx 
/ dwy
); 
2442         // calculate the change in the coordinates 
2443         temp_x 
= (dvx 
- (m_virt_maxX 
- m_virt_minX
) )/ 2.0; 
2446     // add or substract the change from the original coordinates 
2447     m_virt_minX
=m_virt_minX
-temp_x
; 
2448     m_virt_minY
=m_virt_minY
-temp_y
; 
2450     m_virt_maxX
=m_virt_maxX
+temp_x
; 
2451     m_virt_maxY
=m_virt_maxY
+temp_y
; 
2453     // initialize the mapping_matrix used for mapping the 
2454     // virtual windows to the drawing window 
2456      // make mappingmatrix 
2457     m_mapping_matrix
.Identity(); 
2460         // translate the drawing to 0,0 
2462             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
); 
2464             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
); 
2468         // make a small white border around the drawing 
2469         m_virt_minX
=m_virt_minX
- 0.05 * dvx
; 
2470         m_virt_minY
=m_virt_minY
- 0.05 * dvy
; 
2472         m_virt_maxX
=m_virt_maxX
+ 0.05 * dvx
; 
2473         m_virt_maxY
=m_virt_maxY
+ 0.05 * dvy
; 
2475         // translate the drawing to 0,0 
2477             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
); 
2479             m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
); 
2482     double scalefactor_x 
= dwx
; 
2483     scalefactor_x 
/= (m_virt_maxX 
- m_virt_minX
); 
2485     double scalefactor_y 
= dwy
; 
2486     scalefactor_y 
/= (m_virt_maxY 
- m_virt_minY
); 
2488     // scale the drawing so it fit's in the window 
2489     m_mapping_matrix
.Scale(scalefactor_x
, scalefactor_y
, 0, 0); 
2491     // because of coordinate change mirror over X 
2492     // 0,0 in graphic computerscreens: upperleft corner 
2493     // 0,0 in cartesian: lowerleft corner 
2496         m_mapping_matrix
.Mirror(); 
2498     // make inverse of mapping matrix 
2499     // this is to set coordinates in the statusbar 
2500     // and the calculate screencoordinates to world coordinates used 
2502     m_inverse_mapping
=m_mapping_matrix
; 
2503     m_inverse_mapping
.Invert(); 
2506         SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
); 
2509     GetClientSize(&dx2
,&dy2
); 
2510     if ( dwxi 
!= dx2 
|| dwyi  
!= dy2
) //scrollbar is/became empty 
2511         SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
); 
2515 void wxVectorCanvas::SetScroll(double vx1
,double vy1
,double vx2
,double vy2
) 
2522     double dvx 
= m_virt_maxX 
- m_virt_minX
; 
2523     double dvy 
= m_virt_maxY 
- m_virt_minY
; 
2524     double dmvx 
= m_virtm_maxX 
- m_virtm_minX
; 
2525     double dmvy 
= m_virtm_maxY 
- m_virtm_minY
; 
2527     SetScrollbar(wxHORIZONTAL
,(m_virt_minX
-m_virtm_minX
)/dmvx 
*1000,dvx
/dmvx 
*1000,1000,FALSE
); 
2530         SetScrollbar(wxVERTICAL
,(m_virtm_maxY
-m_virt_maxY
)/dmvy 
*1000,dvy
/dmvy 
*1000,1000,FALSE
); 
2534         SetScrollbar(wxVERTICAL
,(m_virt_minY
-m_virtm_minY
)/dmvy 
*1000,dvy
/dmvy 
*1000,1000,FALSE
); 
2540 // coordinates conversions 
2541 // ----------------------- 
2542 double wxVectorCanvas::DeviceToLogicalX(int x
) const 
2544     return m_inverse_mapping
.GetValue(0,0) * x 
+ m_inverse_mapping
.GetValue(2,0); 
2547 double wxVectorCanvas::DeviceToLogicalY(int y
) const 
2549     return m_inverse_mapping
.GetValue(1,1) * y 
+ m_inverse_mapping
.GetValue(2,1); 
2552 double wxVectorCanvas::DeviceToLogicalXRel(int x
) const 
2554     return x
*m_inverse_mapping
.GetValue(0,0); 
2557 double wxVectorCanvas::DeviceToLogicalYRel(int y
) const 
2559     return y
*m_inverse_mapping
.GetValue(1,1); 
2562 int wxVectorCanvas::LogicalToDeviceX(double x
) const 
2564     return (int) (m_mapping_matrix
.GetValue(0,0) * x 
+ m_mapping_matrix
.GetValue(2,0) + 0.5); 
2567 int wxVectorCanvas::LogicalToDeviceY(double y
) const 
2569     return (int) (m_mapping_matrix
.GetValue(1,1) * y 
+ m_mapping_matrix
.GetValue(2,1) + 0.5); 
2572 int wxVectorCanvas::LogicalToDeviceXRel(double x
) const 
2574     return (int) (x
*m_mapping_matrix
.GetValue(0,0) + 0.5); 
2577 int wxVectorCanvas::LogicalToDeviceYRel(double y
) const 
2579     return (int) (y
*m_mapping_matrix
.GetValue(1,1) + 0.5); 
2583 // return the inverse mapping matrix for zooming or coordinates 
2584 wxTransformMatrix 
wxVectorCanvas::GetInverseMappingMatrix() 
2586     return m_inverse_mapping
; 
2589 wxTransformMatrix 
wxVectorCanvas::GetMappingMatrix() 
2591     return m_mapping_matrix
; 
2595 // ---------------------------------------------------------------------------- 
2596 // scrolling behaviour 
2597 // ---------------------------------------------------------------------------- 
2599 void wxVectorCanvas::OnScroll(wxScrollWinEvent
& event
) 
2601     if (event
.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE
) 
2603         if (event
.GetOrientation()==wxHORIZONTAL
) 
2605           double x
=m_virtm_minX
+event
.GetPosition()/1000.0*(m_virtm_maxX
-m_virtm_minX
); 
2606           x
=LogicalToDeviceXRel(x
-m_virt_minX
); 
2607           ScrollWindow(-x
, 0, (const wxRect 
*) NULL
); 
2611           double y
=m_virtm_minY
+event
.GetPosition()/1000.0*(m_virtm_maxY
-m_virtm_minY
); 
2612           y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2613           ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2616     else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEUP
) 
2618         if (event
.GetOrientation()==wxHORIZONTAL
) 
2620           double x
=GetBufferWidth(); 
2621           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2625           double y
=GetBufferHeight(); 
2626           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2629     else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN
) 
2631         if (event
.GetOrientation()==wxHORIZONTAL
) 
2633           double x
=-GetBufferWidth(); 
2634           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2638           double y
=-GetBufferHeight(); 
2639           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2642     else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEUP
) 
2644         if (event
.GetOrientation()==wxHORIZONTAL
) 
2646           int x
=GetBufferWidth()/10; 
2647           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2651           int y
=GetBufferHeight()/10; 
2652           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2655     else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN
) 
2657         if (event
.GetOrientation()==wxHORIZONTAL
) 
2659           int x
=-GetBufferWidth()/10; 
2660           ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2664           int y
=-GetBufferHeight()/10; 
2665           ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2671 void wxVectorCanvas::OnChar(wxKeyEvent
& event
) 
2673     switch ( event
.KeyCode() ) 
2678               double y
=GetBufferHeight(); 
2679               ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2685               double y
=-GetBufferHeight(); 
2686               ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2691                 double y
=m_virtm_minY
; 
2692                 y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2693                 ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2698                 double y
=m_virtm_minY
+(m_virtm_maxY
-m_virtm_minY
); 
2699                 y
=LogicalToDeviceYRel(y
-m_virt_minY
); 
2700                 ScrollWindow(0, -y
, (const wxRect 
*) NULL
); 
2706                 if  (!event
.ControlDown()) 
2707                     y
=GetBufferHeight()/10; 
2709                     y
=GetBufferHeight(); 
2710                 ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2717                 if  (!event
.ControlDown()) 
2718                     y
=-GetBufferHeight()/10; 
2720                     y
=-GetBufferHeight(); 
2721                 ScrollWindow(0, y
, (const wxRect 
*) NULL
); 
2728                 if  (!event
.ControlDown()) 
2729                     x
=GetBufferWidth()/10; 
2732                 ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2738                 if  (!event
.ControlDown()) 
2739                     x
=-GetBufferWidth()/10; 
2741                     x
=-GetBufferWidth(); 
2742                 ScrollWindow(x
, 0, (const wxRect 
*) NULL
); 
2752 //---------------------------------------------------------------------------- 
2754 //---------------------------------------------------------------------------- 
2756 wxCanvasAdmin::wxCanvasAdmin() 
2761 wxCanvasAdmin::~wxCanvasAdmin() 
2766 void wxCanvasAdmin::Append( wxCanvas
* canvas 
) 
2768     m_canvaslist
.Append( canvas 
); 
2771 void wxCanvasAdmin::Remove( wxCanvas
* canvas 
) 
2773     m_canvaslist
.DeleteObject( canvas 
); 
2776 void wxCanvasAdmin::Update(wxCanvasObject
* obj
, double x
, double y
, double width
, double height
) 
2778     wxNode 
*node 
= m_canvaslist
.First(); 
2782         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2784         if (m_active 
== canvas
) 
2786             int xi 
= canvas
->LogicalToDeviceX( x
); 
2787             int yi 
= canvas
->LogicalToDeviceY( y
); 
2788             int wi 
= canvas
->LogicalToDeviceXRel( width 
); 
2789             int hi 
= canvas
->LogicalToDeviceYRel( height
); 
2790             //update a little more then is strictly needed, 
2791             //to get rid of the 1 bit bugs 
2792             if (canvas
->GetYaxis()) 
2793                 canvas
->Update( xi
-2, yi
+hi
-2, wi
+4, -hi
+4); 
2795                 canvas
->Update( xi
-2, yi
-2, wi
+4, hi
+4); 
2798         {   wxCanvasObject
* topobj
=canvas
->GetRoot()->Contains(obj
); 
2801                 wxCanvas
* tcanvas 
= m_active
; 
2805                 //KKK TODO somehow the next does not work for update i do not know why 
2806                 canvas->GetRoot()->CalcBoundingBox(); 
2807                 int xi = topobj->GetX(); 
2808                 int yi = topobj->GetY(); 
2809                 int wi = topobj->GetWidth(); 
2810                 int hi = topobj->GetHeight(); 
2812                 canvas
->Update( 0,0, canvas
->GetBufferWidth(),canvas
->GetBufferHeight()); 
2817         node 
= node
->Next(); 
2821 void wxCanvasAdmin::UpdateNow() 
2823     wxNode 
*node 
= m_canvaslist
.First(); 
2826         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2828         canvas
->UpdateNow(); 
2829         node 
= node
->Next(); 
2833 // coordinates conversions 
2834 // ----------------------- 
2835 double wxCanvasAdmin::DeviceToLogicalX(int x
) const 
2837     return m_active
->DeviceToLogicalX(x
); 
2840 double wxCanvasAdmin::DeviceToLogicalY(int y
) const 
2842     return m_active
->DeviceToLogicalY(y
); 
2845 double wxCanvasAdmin::DeviceToLogicalXRel(int x
) const 
2847     return m_active
->DeviceToLogicalXRel(x
); 
2850 double wxCanvasAdmin::DeviceToLogicalYRel(int y
) const 
2852     return m_active
->DeviceToLogicalYRel(y
); 
2855 int wxCanvasAdmin::LogicalToDeviceX(double x
) const 
2857     return m_active
->LogicalToDeviceX(x
); 
2860 int wxCanvasAdmin::LogicalToDeviceY(double y
) const 
2862     return m_active
->LogicalToDeviceY(y
); 
2865 int wxCanvasAdmin::LogicalToDeviceXRel(double x
) const 
2867     return m_active
->LogicalToDeviceXRel(x
); 
2870 int wxCanvasAdmin::LogicalToDeviceYRel(double y
) const 
2872     return m_active
->LogicalToDeviceYRel(y
); 
2875 void wxCanvasAdmin::SetActive(wxCanvas
* activate
) 
2877     wxNode 
*node 
= m_canvaslist
.First(); 
2880         wxCanvas 
*canvas 
= (wxCanvas
*) node
->Data(); 
2882         if (activate 
== canvas
) 
2887         node 
= node
->Next(); 
2890 //-------------------------------------------------------------------- 
2892 //-------------------------------------------------------------------- 
2894 class wxCanvasModule 
: public wxModule
 
2897     virtual bool OnInit(); 
2898     virtual void OnExit(); 
2901     DECLARE_DYNAMIC_CLASS(wxCanvasModule
) 
2904 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
) 
2906 bool wxCanvasModule::OnInit() 
2909     int error 
= FT_Init_FreeType( &g_freetypeLibrary 
); 
2910     if (error
) return FALSE
; 
2916 void wxCanvasModule::OnExit() 
2919     FT_Done_FreeType( g_freetypeLibrary 
);