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(xh
,yh
,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::SetPosXY( double x
, double y
)
1331 void wxCanvasImage::TransLate( double x
, double y
)
1338 void wxCanvasImage::CalcBoundingBox()
1340 m_bbox
.SetMin( m_x
, m_y
);
1341 m_bbox
.SetMax( m_x
+ m_width
, m_y
+ m_height
);
1344 void wxCanvasImage::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1346 if (!m_visible
) return;
1350 tmparea
.x
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX());
1351 tmparea
.y
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY());
1352 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1353 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1357 cworld
->TransformPoint( m_x
, m_y
, x
, y
);
1358 x
= m_admin
->LogicalToDeviceX(x
);
1359 y
= m_admin
->LogicalToDeviceY(y
);
1363 if ( m_orgw
*5 < m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1364 m_orgw
/5 > m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1365 m_orgh
*5 < m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) ||
1366 m_orgh
/5 > m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() )
1369 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1370 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1371 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
1372 dc
->SetPen(*wxBLACK_PEN
);
1373 //yes the whole not only the clipping region, because we have a pen also
1374 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1375 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1376 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1377 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1380 dc
->DrawRectangle( x
,y
,w
,h
);
1381 dc
->SetBrush(wxNullBrush
);
1382 dc
->SetPen(wxNullPen
);
1383 dc
->DestroyClippingRegion();
1388 bool is_cashed
= FALSE
;
1390 if (m_cImage
.Ok() && (m_cW
== m_bbox
.GetWidth()) && (m_cH
== m_bbox
.GetHeight()))
1398 if ((m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) == m_image
.GetWidth()) &&
1399 (m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) == m_image
.GetHeight()))
1405 tmp
= m_image
.Scale( m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()),
1406 m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight()) );
1409 // create cached image
1411 m_cW
= tmp
.GetWidth();
1412 m_cH
= tmp
.GetHeight();
1415 // wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
1420 if (m_cBitmap
.Ok() && is_cashed
&& (m_cR
== cworld
->GetRotation()))
1426 if (cworld
->GetRotation())
1427 tmp
= tmp
.Rotate(-cworld
->GetRotation()/180.0 * pi
, centr
, TRUE
, NULL
);
1429 bmp
= tmp
.ConvertToBitmap();
1431 // create cached bitmap
1433 m_cR
= cworld
->GetRotation();
1436 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1439 if (cworld
->GetRotation()> 0)
1441 centr2
.x
= (int) (x
+m_height
*sin(-cworld
->GetRotation()/180.0 * pi
));
1447 centr2
.y
= (int) (y
-m_width
*sin(-cworld
->GetRotation()/180.0 * pi
));
1450 if (cworld
->GetRotation() != 0)
1452 //TODO clipping not right
1453 dc
->DrawBitmap(bmp
,centr2
,TRUE
);
1454 // dc->DrawPoint(centr2);
1455 // dc->DrawPoint(x,y);
1459 dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height
);
1460 dc
->DrawBitmap( bmp
, x
, y
, TRUE
);
1461 dc
->DestroyClippingRegion();
1465 void wxCanvasImage::WriteSVG( wxTextOutputStream
&stream
)
1470 //----------------------------------------------------------------------------
1472 //----------------------------------------------------------------------------
1474 wxCanvasControl::wxCanvasControl( wxWindow
*control
)
1478 m_control
= control
;
1482 double wxCanvasControl::GetPosX()
1485 m_control
->GetPosition( &x
, &y
);
1486 return m_admin
->DeviceToLogicalX(x
);
1489 double wxCanvasControl::GetPosY()
1492 m_control
->GetPosition( &x
, &y
);
1493 return m_admin
->DeviceToLogicalY(y
);
1496 void wxCanvasControl::SetPosXY( double x
, double y
)
1498 int xd
= m_admin
->LogicalToDeviceX(x
);
1499 int yd
= m_admin
->LogicalToDeviceY(y
);
1500 m_control
->Move(xd
,yd
);
1504 void wxCanvasControl::TransLate( double x
, double y
)
1507 m_control
->GetPosition( &xdo
, &ydo
);
1508 int xd
= m_admin
->LogicalToDeviceX(x
)-xdo
;
1509 int yd
= m_admin
->LogicalToDeviceY(y
)-ydo
;
1510 m_control
->Move(xd
,yd
);
1514 wxCanvasControl::~wxCanvasControl()
1516 m_control
->Destroy();
1519 void wxCanvasControl::CalcBoundingBox()
1523 m_control
->GetSize( &tmparea
.width
, &tmparea
.height
);
1524 m_control
->GetPosition( &tmparea
.x
, &tmparea
.y
);
1526 m_bbox
.SetMin( tmparea
.x
, tmparea
.y
);
1527 m_bbox
.SetMax( tmparea
.x
+ tmparea
.width
, tmparea
.y
+ tmparea
.height
);
1531 void wxCanvasControl::MoveRelative( double x
, double y
)
1533 m_control
->Move( m_admin
->LogicalToDeviceX(x
), m_admin
->LogicalToDeviceX(y
) );
1536 //----------------------------------------------------------------------------
1538 //----------------------------------------------------------------------------
1550 wxCanvasText::wxCanvasText( const wxString
&text
, double x
, double y
, const wxString
&fontFile
, int size
)
1554 m_fontFileName
= fontFile
;
1567 wxFaceData
*data
= new wxFaceData
;
1570 int error
= FT_New_Face( g_freetypeLibrary
,
1575 error
= FT_Set_Char_Size( data
->m_face
,
1584 wxCanvasText::~wxCanvasText()
1587 wxFaceData
*data
= (wxFaceData
*) m_faceData
;
1591 if (m_alpha
) delete [] m_alpha
;
1594 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue
)
1601 void wxCanvasText::SetFlag( int flag
)
1606 void wxCanvasText::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1608 if (!m_visible
) return;
1611 tmparea
.x
= m_admin
->LogicalToDeviceX( m_bbox
.GetMinX());
1612 tmparea
.y
= m_admin
->LogicalToDeviceY( m_bbox
.GetMinY());
1613 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1614 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1616 m_alpha
= new unsigned char[tmparea
.width
*tmparea
.height
];
1617 memset( m_alpha
, 0, tmparea
.width
*tmparea
.height
);
1619 if (!m_alpha
) return;
1622 FT_Face face
= ((wxFaceData
*)m_faceData
)->m_face
;
1623 FT_GlyphSlot slot
= face
->glyph
;
1627 for (int n
= 0; n
< (int)m_text
.Len(); n
++)
1629 FT_UInt index
= FT_Get_Char_Index( face
, m_text
[(unsigned int)n
] );
1631 int error
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT
);
1632 if (error
) continue;
1634 error
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal
);
1635 if (error
) continue;
1637 FT_Bitmap
*bitmap
= &slot
->bitmap
;
1638 unsigned char* buffer
= bitmap
->buffer
;
1639 for (int y
= 0; y
< bitmap
->rows
; y
++)
1640 for (int x
= 0; x
< bitmap
->width
; x
++)
1642 unsigned char alpha
= buffer
[ y
*bitmap
->pitch
+ x
];
1643 if (alpha
== 0) continue;
1645 int xx
= pen_x
+ slot
->bitmap_left
+ x
;
1646 int yy
= pen_y
- slot
->bitmap_top
+ y
;
1647 m_alpha
[ yy
* tmparea
.width
+ xx
] = alpha
;
1650 pen_x
+= slot
->advance
.x
>> 6;
1651 pen_y
+= slot
->advance
.y
>> 6;
1655 wxBitmap
*bitmap
= m_admin
->GetActive()->GetBuffer();
1656 wxRect
sub_rect( clip_x
, clip_y
, clip_width
, clip_height
);
1657 wxBitmap
sub_bitmap( bitmap
->GetSubBitmap( sub_rect
) );
1659 wxImage
image( sub_bitmap
);
1661 // local coordinates
1662 int start_x
= clip_x
- tmparea
.x
;
1663 int end_x
= clip_width
+ start_x
;
1664 int start_y
= clip_y
- tmparea
.y
;
1665 int end_y
= clip_height
+ start_y
;
1667 for (int y
= start_y
; y
< end_y
; y
++)
1668 for (int x
= start_x
; x
< end_x
; x
++)
1670 int alpha
= m_alpha
[y
*tmparea
.width
+ x
];
1673 int image_x
= x
- start_x
;
1674 int image_y
= y
- start_y
;
1677 image
.SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
1680 int red1
= (m_red
* alpha
) / 255;
1681 int green1
= (m_green
* alpha
) / 255;
1682 int blue1
= (m_blue
* alpha
) / 255;
1685 int red2
= image
.GetRed( image_x
, image_y
);
1686 int green2
= image
.GetGreen( image_x
, image_y
);
1687 int blue2
= image
.GetBlue( image_x
, image_y
);
1688 red2
= (red2
* alpha
) / 255;
1689 green2
= (green2
* alpha
) / 255;
1690 blue2
= (blue2
* alpha
) / 255;
1692 image
.SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
1696 sub_bitmap
= image
.ConvertToBitmap();
1698 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1699 dc
->DrawBitmap( sub_bitmap
, clip_x
, clip_y
);
1702 void wxCanvasText::WriteSVG( wxTextOutputStream
&stream
)
1706 void wxCanvasText::TransLate( double x
, double y
)
1713 void wxCanvasText::CalcBoundingBox()
1715 if (m_alpha
) delete [] m_alpha
;
1717 m_bbox
.SetMin( m_x
, m_y
);
1718 m_bbox
.SetMax( m_x
+ 100 , m_y
+ m_size
+ (m_size
/2));
1723 //----------------------------------------------------------------------------
1725 //----------------------------------------------------------------------------
1727 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
)
1729 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
)
1730 EVT_PAINT( wxCanvas::OnPaint
)
1731 EVT_IDLE( wxCanvas::OnIdle
)
1732 EVT_SIZE( wxCanvas::OnSize
)
1733 EVT_MOUSE_EVENTS( wxCanvas::OnMouse
)
1734 EVT_SET_FOCUS( wxCanvas::OnSetFocus
)
1735 EVT_KILL_FOCUS( wxCanvas::OnKillFocus
)
1736 EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground
)
1739 wxCanvas::wxCanvas( wxCanvasAdmin
* admin
, wxWindow
*parent
, wxWindowID id
,
1740 const wxPoint
&position
, const wxSize
& size
, long style
) :
1741 wxScrolledWindow( parent
, id
, position
, size
, style
)
1743 // These are unused in wxVectorCanvas
1748 m_admin
->Append( this );
1750 m_needUpdate
= FALSE
;
1751 m_background
= *wxWHITE
;
1752 m_lastMouse
= (wxCanvasObject
*)NULL
;
1753 m_captureMouse
= (wxCanvasObject
*)NULL
;
1757 m_root
= (wxCanvasObjectGroup
*)NULL
;
1760 wxCanvas::~wxCanvas()
1762 wxNode
*node
= m_updateRects
.First();
1765 wxRect
*rect
= (wxRect
*) node
->Data();
1767 m_updateRects
.DeleteNode( node
);
1768 node
= m_updateRects
.First();
1772 double wxCanvas::GetMinX() const
1777 double wxCanvas::GetMinY() const
1782 double wxCanvas::GetMaxX() const
1785 GetVirtualSize( &width
, NULL
);
1789 double wxCanvas::GetMaxY() const
1792 GetVirtualSize( NULL
, &height
);
1796 void wxCanvas::SetColour( const wxColour
& background
)
1798 m_background
= background
;
1799 SetBackgroundColour( m_background
);
1801 if (m_frozen
) return;
1804 dc
.SelectObject( m_buffer
);
1805 dc
.SetPen( *wxTRANSPARENT_PEN
);
1806 wxBrush
brush( m_background
, wxSOLID
);
1807 dc
.SetBrush( brush
);
1808 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
1809 dc
.SelectObject( wxNullBitmap
);
1812 void wxCanvas::SetCaptureMouse( wxCanvasObject
*obj
)
1816 wxWindow::CaptureMouse();
1817 m_captureMouse
= obj
;
1821 wxWindow::ReleaseMouse();
1822 m_captureMouse
= NULL
;
1826 void wxCanvas::Freeze()
1831 void wxCanvas::Thaw()
1833 wxNode
*node
= m_updateRects
.First();
1836 wxRect
*rect
= (wxRect
*) node
->Data();
1838 m_updateRects
.DeleteNode( node
);
1839 node
= m_updateRects
.First();
1845 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
1848 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit
)
1850 CalcScrolledPosition( 0, 0, &m_oldDeviceX
, &m_oldDeviceY
);
1852 m_admin
->SetActive(this);
1854 if (!m_root
) return;
1856 if (m_frozen
) return;
1861 width
-= m_bufferX
-x
;
1864 if (width
<= 0) return;
1868 height
-= m_bufferY
-y
;
1871 if (height
<= 0) return;
1873 if (x
+width
> m_bufferX
+m_buffer
.GetWidth())
1875 width
= m_bufferX
+m_buffer
.GetWidth() - x
;
1877 if (width
<= 0) return;
1879 if (y
+height
> m_bufferY
+m_buffer
.GetHeight())
1881 height
= m_bufferY
+m_buffer
.GetHeight() - y
;
1883 if (height
<= 0) return;
1885 // update is within the buffer
1886 m_needUpdate
= TRUE
;
1888 // has to be blitted to screen later
1891 m_updateRects
.Append(
1892 (wxObject
*) new wxRect( x
,y
,width
,height
) );
1895 wxTransformMatrix cworld
;
1898 dc
.SelectObject( m_buffer
);
1900 dc
.SetPen( *wxTRANSPARENT_PEN
);
1901 wxBrush
brush( m_background
, wxSOLID
);
1902 dc
.SetBrush( brush
);
1903 dc
.SetLogicalFunction(wxCOPY
);
1906 if (width
!= m_buffer
.GetWidth() && height
!= m_buffer
.GetHeight())
1908 dc
.SetClippingRegion(x
,y
,width
,height
);
1909 dc
.DrawRectangle(x
-2,y
-2,width
+4,height
+4);
1910 dc
.DestroyClippingRegion();
1915 dc
.DrawRectangle(0,0,m_buffer
.GetWidth(),m_buffer
.GetHeight());
1918 // No idea, what the code up there does.
1919 dc
.DrawRectangle( x
-m_bufferX
, y
-m_bufferY
, width
, height
);
1922 dc
.SetBrush(wxNullBrush
);
1923 dc
.SetPen(wxNullPen
);
1925 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
1928 m_root
->Render( &cworld
, x
, y
, width
, height
);
1931 dc
.SelectObject( wxNullBitmap
);
1934 void wxCanvas::BlitBuffer( wxDC
&dc
)
1936 wxNode
*node
= m_updateRects
.First();
1939 wxRect
*rect
= (wxRect
*) node
->Data();
1942 mdc
.SelectObject( m_buffer
);
1948 rect
->x
- m_bufferX
,
1949 rect
->y
- m_bufferY
);
1950 mdc
.SelectObject( wxNullBitmap
);
1953 m_updateRects
.DeleteNode( node
);
1954 node
= m_updateRects
.First();
1957 m_needUpdate
= FALSE
;
1960 void wxCanvas::UpdateNow()
1962 if (m_frozen
) return;
1964 if (!m_needUpdate
) return;
1966 wxClientDC
dc( this );
1972 void wxCanvas::OnSize(wxSizeEvent
&event
)
1975 GetClientSize( &w
, &h
);
1976 m_buffer
= wxBitmap( w
, h
);
1978 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
1980 wxNode
*node
= m_updateRects
.First();
1983 wxRect
*rect
= (wxRect
*) node
->Data();
1985 m_updateRects
.DeleteNode( node
);
1986 node
= m_updateRects
.First();
1991 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
1996 void wxCanvas::OnPaint(wxPaintEvent
&event
)
2001 if (!m_buffer
.Ok()) return;
2003 if (m_frozen
) return;
2005 m_needUpdate
= TRUE
;
2007 wxRegionIterator
it( GetUpdateRegion() );
2013 int w
= it
.GetWidth();
2014 int h
= it
.GetHeight();
2016 if (x
+w
> m_buffer
.GetWidth())
2017 w
= m_buffer
.GetWidth() - x
;
2018 if (y
+h
> m_buffer
.GetHeight())
2019 h
= m_buffer
.GetHeight() - y
;
2021 if ((w
> 0) && (h
> 0))
2025 m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h
) );
2034 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
2036 // If any updates are pending, do them now since they will
2037 // expect the previous m_bufferX and m_bufferY as well as
2038 // the previous device origin values.
2039 wxClientDC
dc( this );
2040 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
2043 // The buffer always starts at the top left corner of the
2044 // client area. Indeed, it is the client area.
2045 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
2047 // Update everything.
2048 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
2050 // Scroll, actually.
2051 wxWindow::ScrollWindow( dx
, dy
, rect
);
2054 void wxCanvas::OnMouse(wxMouseEvent
&event
)
2056 m_admin
->SetActive(this);
2063 int x
= event
.GetX();
2064 int y
= event
.GetY();
2066 //to world coordinates to do hit test in world coordinates
2067 double xw
= DeviceToLogicalX( x
);
2068 double yw
= DeviceToLogicalY( y
);
2070 //make a select margin of 2 pixels, so also zero line thickness will be hit
2071 double margin
= DeviceToLogicalXRel( 2 );
2073 if (event
.GetEventType() == wxEVT_MOTION
)
2075 if (m_captureMouse
) //no matter what go to this one
2077 wxMouseEvent
child_event( wxEVT_MOTION
);
2078 child_event
.SetEventObject(m_captureMouse
);
2079 child_event
.m_x
= x
;
2080 child_event
.m_y
= y
;
2081 child_event
.m_leftDown
= event
.m_leftDown
;
2082 child_event
.m_rightDown
= event
.m_rightDown
;
2083 child_event
.m_middleDown
= event
.m_middleDown
;
2084 child_event
.m_controlDown
= event
.m_controlDown
;
2085 child_event
.m_shiftDown
= event
.m_shiftDown
;
2086 child_event
.m_altDown
= event
.m_altDown
;
2087 child_event
.m_metaDown
= event
.m_metaDown
;
2089 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2094 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2096 if (obj
&& !obj
->IsControl())
2098 wxMouseEvent
child_event( wxEVT_MOTION
);
2099 child_event
.SetEventObject( obj
);
2100 child_event
.m_x
= x
;
2101 child_event
.m_y
= y
;
2102 child_event
.m_leftDown
= event
.m_leftDown
;
2103 child_event
.m_rightDown
= event
.m_rightDown
;
2104 child_event
.m_middleDown
= event
.m_middleDown
;
2105 child_event
.m_controlDown
= event
.m_controlDown
;
2106 child_event
.m_shiftDown
= event
.m_shiftDown
;
2107 child_event
.m_altDown
= event
.m_altDown
;
2108 child_event
.m_metaDown
= event
.m_metaDown
;
2110 if ((obj
!= m_lastMouse
) && (m_lastMouse
!= NULL
))
2112 child_event
.SetEventType( wxEVT_LEAVE_WINDOW
);
2113 child_event
.SetEventObject( m_lastMouse
);
2114 child_event
.m_x
= x
;
2115 child_event
.m_y
= y
;
2116 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2119 child_event
.SetEventType( wxEVT_ENTER_WINDOW
);
2120 child_event
.SetEventObject( m_lastMouse
);
2121 child_event
.m_x
= x
;
2122 child_event
.m_y
= y
;
2123 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2125 child_event
.SetEventType( wxEVT_MOTION
);
2126 child_event
.SetEventObject( obj
);
2129 obj
->ProcessCanvasObjectEvent( child_event
);
2135 wxMouseEvent
child_event( wxEVT_LEAVE_WINDOW
);
2136 child_event
.SetEventObject( m_lastMouse
);
2137 child_event
.m_x
= x
;
2138 child_event
.m_y
= y
;
2139 child_event
.m_leftDown
= event
.m_leftDown
;
2140 child_event
.m_rightDown
= event
.m_rightDown
;
2141 child_event
.m_middleDown
= event
.m_middleDown
;
2142 child_event
.m_controlDown
= event
.m_controlDown
;
2143 child_event
.m_shiftDown
= event
.m_shiftDown
;
2144 child_event
.m_altDown
= event
.m_altDown
;
2145 child_event
.m_metaDown
= event
.m_metaDown
;
2146 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2148 m_lastMouse
= (wxCanvasObject
*) NULL
;
2154 if (m_captureMouse
) //no matter what go to this one
2156 wxMouseEvent
child_event( event
.GetEventType() );
2157 child_event
.SetEventObject(m_captureMouse
);
2158 child_event
.m_x
= x
;
2159 child_event
.m_y
= y
;
2160 child_event
.m_leftDown
= event
.m_leftDown
;
2161 child_event
.m_rightDown
= event
.m_rightDown
;
2162 child_event
.m_middleDown
= event
.m_middleDown
;
2163 child_event
.m_controlDown
= event
.m_controlDown
;
2164 child_event
.m_shiftDown
= event
.m_shiftDown
;
2165 child_event
.m_altDown
= event
.m_altDown
;
2166 child_event
.m_metaDown
= event
.m_metaDown
;
2167 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2171 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2173 if (obj
&& !obj
->IsControl())
2175 wxMouseEvent
child_event( event
.GetEventType() );
2176 child_event
.SetEventObject( obj
);
2177 child_event
.m_x
= x
;
2178 child_event
.m_y
= y
;
2179 child_event
.m_leftDown
= event
.m_leftDown
;
2180 child_event
.m_rightDown
= event
.m_rightDown
;
2181 child_event
.m_middleDown
= event
.m_middleDown
;
2182 child_event
.m_controlDown
= event
.m_controlDown
;
2183 child_event
.m_shiftDown
= event
.m_shiftDown
;
2184 child_event
.m_altDown
= event
.m_altDown
;
2185 child_event
.m_metaDown
= event
.m_metaDown
;
2187 obj
->ProcessCanvasObjectEvent( child_event
);
2196 void wxCanvas::OnIdle(wxIdleEvent
&event
)
2198 m_admin
->SetActive(this);
2203 void wxCanvas::OnSetFocus(wxFocusEvent
&event
)
2205 m_admin
->SetActive(this);
2208 void wxCanvas::OnKillFocus(wxFocusEvent
&event
)
2213 void wxCanvas::OnEraseBackground(wxEraseEvent
&event
)
2217 // coordinates conversions
2218 // -----------------------
2219 double wxCanvas::DeviceToLogicalX(int x
) const
2224 double wxCanvas::DeviceToLogicalY(int y
) const
2229 double wxCanvas::DeviceToLogicalXRel(int x
) const
2234 double wxCanvas::DeviceToLogicalYRel(int y
) const
2239 int wxCanvas::LogicalToDeviceX(double x
) const
2241 return (int)(x
+ 0.5);
2244 int wxCanvas::LogicalToDeviceY(double y
) const
2246 return (int)(y
+ 0.5);
2249 int wxCanvas::LogicalToDeviceXRel(double x
) const
2251 return (int)(x
+ 0.5);
2254 int wxCanvas::LogicalToDeviceYRel(double y
) const
2256 return (int)(y
+ 0.5);
2259 //----------------------------------------------------------------------------
2261 //----------------------------------------------------------------------------
2263 IMPLEMENT_CLASS(wxVectorCanvas
,wxCanvas
)
2265 BEGIN_EVENT_TABLE(wxVectorCanvas
,wxCanvas
)
2266 EVT_SCROLLWIN( wxVectorCanvas::OnScroll
)
2267 EVT_CHAR( wxVectorCanvas::OnChar
)
2268 EVT_SIZE( wxVectorCanvas::OnSize
)
2271 wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin
* admin
, wxWindow
*parent
, wxWindowID id
,
2272 const wxPoint
&position
, const wxSize
& size
, long style
) :
2273 wxCanvas( admin
, parent
, id
, position
, size
, style
)
2279 double wxVectorCanvas::GetMinX() const
2284 double wxVectorCanvas::GetMinY() const
2289 double wxVectorCanvas::GetMaxX() const
2294 double wxVectorCanvas::GetMaxY() const
2299 void wxVectorCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
2301 // If any updates are pending, do them now since they will
2302 // expect the previous m_bufferX and m_bufferY as well as
2303 // the previous device origin values.
2304 wxClientDC
dc( this );
2305 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
2310 double dyv
=DeviceToLogicalYRel(dy
);
2311 m_virt_minY
=m_virt_minY
-dyv
;
2312 m_virt_maxY
=m_virt_maxY
-dyv
;
2316 double dxv
=DeviceToLogicalXRel(dx
);
2317 m_virt_minX
=m_virt_minX
-dxv
;
2318 m_virt_maxX
=m_virt_maxX
-dxv
;
2321 m_admin
->SetActive(this);
2322 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2327 if (dy
> 0 && dy
< m_buffer
.GetHeight())
2329 wxRect
rect( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight()-dy
);
2330 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2332 dcm
.SelectObject( m_buffer
);
2333 dcm
.DrawBitmap( sub_bitmap
, 0, dy
, TRUE
);
2334 dcm
.SelectObject( wxNullBitmap
);
2336 Update( 0, 0, m_buffer
.GetWidth(), dy
, TRUE
);
2338 else if (dy
< 0 && dy
> -m_buffer
.GetHeight())
2340 wxRect
rect( 0, -dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight()+dy
);
2341 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2343 dcm
.SelectObject( m_buffer
);
2344 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2345 dcm
.SelectObject( wxNullBitmap
);
2347 Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2350 Update( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2355 if (dx
> 0 && dx
< m_buffer
.GetWidth())
2357 wxRect
rect( 0, 0, m_buffer
.GetWidth()-dx
, m_buffer
.GetHeight());
2358 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2360 dcm
.SelectObject( m_buffer
);
2361 dcm
.DrawBitmap( sub_bitmap
, dx
, 0, TRUE
);
2362 dcm
.SelectObject( wxNullBitmap
);
2364 Update( 0, 0, dx
, m_buffer
.GetHeight(), TRUE
);
2366 else if (dx
< 0 && dx
> -m_buffer
.GetWidth())
2368 wxRect
rect( -dx
, 0, m_buffer
.GetWidth()+dx
, m_buffer
.GetHeight());
2369 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2371 dcm
.SelectObject( m_buffer
);
2372 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2373 dcm
.SelectObject( wxNullBitmap
);
2375 Update( m_buffer
.GetWidth()+dx
, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2378 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2381 wxWindow::ScrollWindow( dx
, dy
, rect
);
2383 //must be done now because quick repeated scrolling will prevent wxPaint
2384 //from doing it properly
2388 void wxVectorCanvas::OnSize(wxSizeEvent
&event
)
2392 GetClientSize( &w
, &h
);
2395 m_buffer
= wxBitmap( w
, h
);
2396 dc
.SelectObject( m_buffer
);
2397 dc
.SetPen( *wxTRANSPARENT_PEN
);
2398 wxBrush
brush( m_background
, wxSOLID
);
2399 dc
.SetBrush( brush
);
2400 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
2401 dc
.SelectObject( wxNullBitmap
);
2403 wxNode
*node
= m_updateRects
.First();
2406 wxRect
*rect
= (wxRect
*) node
->Data();
2408 m_updateRects
.DeleteNode( node
);
2409 node
= m_updateRects
.First();
2414 m_admin
->SetActive(this);
2415 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2417 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
2422 // maps the virtual window (Real drawing to the window coordinates
2423 // also used for zooming
2424 void wxVectorCanvas::SetMappingScroll( double vx1
, double vy1
, double vx2
, double vy2
, bool border
)
2427 GetClientSize(&dwxi
,&dwyi
);
2429 if (vx2
==vx1
) vx2
=vx1
+100000;
2430 if (vy2
==vy1
) vy2
=vy1
+100000;
2441 double dvx
= m_virt_maxX
- m_virt_minX
;
2442 double dvy
= m_virt_maxY
- m_virt_minY
;
2444 // calculate the scaling factor for the virtual window
2447 if ((dvy
/ dvx
) < (dwy
/ dwx
))
2449 dvy
= dvx
* (dwy
/ dwx
);
2450 // calculate the change in the coordinates
2451 temp_y
= (dvy
- (m_virt_maxY
- m_virt_minY
) )/ 2.0;
2455 dvx
= dvy
* (dwx
/ dwy
);
2456 // calculate the change in the coordinates
2457 temp_x
= (dvx
- (m_virt_maxX
- m_virt_minX
) )/ 2.0;
2460 // add or substract the change from the original coordinates
2461 m_virt_minX
=m_virt_minX
-temp_x
;
2462 m_virt_minY
=m_virt_minY
-temp_y
;
2464 m_virt_maxX
=m_virt_maxX
+temp_x
;
2465 m_virt_maxY
=m_virt_maxY
+temp_y
;
2467 // initialize the mapping_matrix used for mapping the
2468 // virtual windows to the drawing window
2470 // make mappingmatrix
2471 m_mapping_matrix
.Identity();
2474 // translate the drawing to 0,0
2476 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2478 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2482 // make a small white border around the drawing
2483 m_virt_minX
=m_virt_minX
- 0.05 * dvx
;
2484 m_virt_minY
=m_virt_minY
- 0.05 * dvy
;
2486 m_virt_maxX
=m_virt_maxX
+ 0.05 * dvx
;
2487 m_virt_maxY
=m_virt_maxY
+ 0.05 * dvy
;
2489 // translate the drawing to 0,0
2491 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2493 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2496 double scalefactor_x
= dwx
;
2497 scalefactor_x
/= (m_virt_maxX
- m_virt_minX
);
2499 double scalefactor_y
= dwy
;
2500 scalefactor_y
/= (m_virt_maxY
- m_virt_minY
);
2502 // scale the drawing so it fit's in the window
2503 m_mapping_matrix
.Scale(scalefactor_x
, scalefactor_y
, 0, 0);
2505 // because of coordinate change mirror over X
2506 // 0,0 in graphic computerscreens: upperleft corner
2507 // 0,0 in cartesian: lowerleft corner
2510 m_mapping_matrix
.Mirror();
2512 // make inverse of mapping matrix
2513 // this is to set coordinates in the statusbar
2514 // and the calculate screencoordinates to world coordinates used
2516 m_inverse_mapping
=m_mapping_matrix
;
2517 m_inverse_mapping
.Invert();
2520 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2523 GetClientSize(&dx2
,&dy2
);
2524 if ( dwxi
!= dx2
|| dwyi
!= dy2
) //scrollbar is/became empty
2525 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2529 void wxVectorCanvas::SetScroll(double vx1
,double vy1
,double vx2
,double vy2
)
2536 double dvx
= m_virt_maxX
- m_virt_minX
;
2537 double dvy
= m_virt_maxY
- m_virt_minY
;
2538 double dmvx
= m_virtm_maxX
- m_virtm_minX
;
2539 double dmvy
= m_virtm_maxY
- m_virtm_minY
;
2541 SetScrollbar(wxHORIZONTAL
,(m_virt_minX
-m_virtm_minX
)/dmvx
*1000,dvx
/dmvx
*1000,1000,FALSE
);
2544 SetScrollbar(wxVERTICAL
,(m_virtm_maxY
-m_virt_maxY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2548 SetScrollbar(wxVERTICAL
,(m_virt_minY
-m_virtm_minY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2554 // coordinates conversions
2555 // -----------------------
2556 double wxVectorCanvas::DeviceToLogicalX(int x
) const
2558 return m_inverse_mapping
.GetValue(0,0) * x
+ m_inverse_mapping
.GetValue(2,0);
2561 double wxVectorCanvas::DeviceToLogicalY(int y
) const
2563 return m_inverse_mapping
.GetValue(1,1) * y
+ m_inverse_mapping
.GetValue(2,1);
2566 double wxVectorCanvas::DeviceToLogicalXRel(int x
) const
2568 return x
*m_inverse_mapping
.GetValue(0,0);
2571 double wxVectorCanvas::DeviceToLogicalYRel(int y
) const
2573 return y
*m_inverse_mapping
.GetValue(1,1);
2576 int wxVectorCanvas::LogicalToDeviceX(double x
) const
2578 return (int) (m_mapping_matrix
.GetValue(0,0) * x
+ m_mapping_matrix
.GetValue(2,0) + 0.5);
2581 int wxVectorCanvas::LogicalToDeviceY(double y
) const
2583 return (int) (m_mapping_matrix
.GetValue(1,1) * y
+ m_mapping_matrix
.GetValue(2,1) + 0.5);
2586 int wxVectorCanvas::LogicalToDeviceXRel(double x
) const
2588 return (int) (x
*m_mapping_matrix
.GetValue(0,0) + 0.5);
2591 int wxVectorCanvas::LogicalToDeviceYRel(double y
) const
2593 return (int) (y
*m_mapping_matrix
.GetValue(1,1) + 0.5);
2597 // return the inverse mapping matrix for zooming or coordinates
2598 wxTransformMatrix
wxVectorCanvas::GetInverseMappingMatrix()
2600 return m_inverse_mapping
;
2603 wxTransformMatrix
wxVectorCanvas::GetMappingMatrix()
2605 return m_mapping_matrix
;
2609 // ----------------------------------------------------------------------------
2610 // scrolling behaviour
2611 // ----------------------------------------------------------------------------
2613 void wxVectorCanvas::OnScroll(wxScrollWinEvent
& event
)
2615 if (event
.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE
)
2617 if (event
.GetOrientation()==wxHORIZONTAL
)
2619 double x
=m_virtm_minX
+event
.GetPosition()/1000.0*(m_virtm_maxX
-m_virtm_minX
);
2620 x
=LogicalToDeviceXRel(x
-m_virt_minX
);
2621 ScrollWindow(-x
, 0, (const wxRect
*) NULL
);
2625 double y
=m_virtm_minY
+event
.GetPosition()/1000.0*(m_virtm_maxY
-m_virtm_minY
);
2626 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2627 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2630 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEUP
)
2632 if (event
.GetOrientation()==wxHORIZONTAL
)
2634 double x
=GetBufferWidth();
2635 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2639 double y
=GetBufferHeight();
2640 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2643 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN
)
2645 if (event
.GetOrientation()==wxHORIZONTAL
)
2647 double x
=-GetBufferWidth();
2648 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2652 double y
=-GetBufferHeight();
2653 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2656 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEUP
)
2658 if (event
.GetOrientation()==wxHORIZONTAL
)
2660 int x
=GetBufferWidth()/10;
2661 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2665 int y
=GetBufferHeight()/10;
2666 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2669 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN
)
2671 if (event
.GetOrientation()==wxHORIZONTAL
)
2673 int x
=-GetBufferWidth()/10;
2674 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2678 int y
=-GetBufferHeight()/10;
2679 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2685 void wxVectorCanvas::OnChar(wxKeyEvent
& event
)
2687 switch ( event
.KeyCode() )
2692 double y
=GetBufferHeight();
2693 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2699 double y
=-GetBufferHeight();
2700 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2705 double y
=m_virtm_minY
;
2706 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2707 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2712 double y
=m_virtm_minY
+(m_virtm_maxY
-m_virtm_minY
);
2713 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2714 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2720 if (!event
.ControlDown())
2721 y
=GetBufferHeight()/10;
2723 y
=GetBufferHeight();
2724 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2731 if (!event
.ControlDown())
2732 y
=-GetBufferHeight()/10;
2734 y
=-GetBufferHeight();
2735 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2742 if (!event
.ControlDown())
2743 x
=GetBufferWidth()/10;
2746 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2752 if (!event
.ControlDown())
2753 x
=-GetBufferWidth()/10;
2755 x
=-GetBufferWidth();
2756 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2766 //----------------------------------------------------------------------------
2768 //----------------------------------------------------------------------------
2770 wxCanvasAdmin::wxCanvasAdmin()
2775 wxCanvasAdmin::~wxCanvasAdmin()
2780 void wxCanvasAdmin::Append( wxCanvas
* canvas
)
2782 m_canvaslist
.Append( canvas
);
2785 void wxCanvasAdmin::Remove( wxCanvas
* canvas
)
2787 m_canvaslist
.DeleteObject( canvas
);
2790 void wxCanvasAdmin::Update(wxCanvasObject
* obj
, double x
, double y
, double width
, double height
)
2792 wxNode
*node
= m_canvaslist
.First();
2796 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2798 if (m_active
== canvas
)
2800 int xi
= canvas
->LogicalToDeviceX( x
);
2801 int yi
= canvas
->LogicalToDeviceY( y
);
2802 int wi
= canvas
->LogicalToDeviceXRel( width
);
2803 int hi
= canvas
->LogicalToDeviceYRel( height
);
2804 //update a little more then is strictly needed,
2805 //to get rid of the 1 bit bugs
2806 if (canvas
->GetYaxis())
2807 canvas
->Update( xi
-2, yi
+hi
-2, wi
+4, -hi
+4);
2809 canvas
->Update( xi
-2, yi
-2, wi
+4, hi
+4);
2812 { wxCanvasObject
* topobj
=canvas
->GetRoot()->Contains(obj
);
2815 wxCanvas
* tcanvas
= m_active
;
2819 //KKK TODO somehow the next does not work for update i do not know why
2820 canvas->GetRoot()->CalcBoundingBox();
2821 int xi = topobj->GetX();
2822 int yi = topobj->GetY();
2823 int wi = topobj->GetWidth();
2824 int hi = topobj->GetHeight();
2826 canvas
->Update( 0,0, canvas
->GetBufferWidth(),canvas
->GetBufferHeight());
2831 node
= node
->Next();
2835 void wxCanvasAdmin::UpdateNow()
2837 wxNode
*node
= m_canvaslist
.First();
2840 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2842 canvas
->UpdateNow();
2843 node
= node
->Next();
2847 // coordinates conversions
2848 // -----------------------
2849 double wxCanvasAdmin::DeviceToLogicalX(int x
) const
2851 return m_active
->DeviceToLogicalX(x
);
2854 double wxCanvasAdmin::DeviceToLogicalY(int y
) const
2856 return m_active
->DeviceToLogicalY(y
);
2859 double wxCanvasAdmin::DeviceToLogicalXRel(int x
) const
2861 return m_active
->DeviceToLogicalXRel(x
);
2864 double wxCanvasAdmin::DeviceToLogicalYRel(int y
) const
2866 return m_active
->DeviceToLogicalYRel(y
);
2869 int wxCanvasAdmin::LogicalToDeviceX(double x
) const
2871 return m_active
->LogicalToDeviceX(x
);
2874 int wxCanvasAdmin::LogicalToDeviceY(double y
) const
2876 return m_active
->LogicalToDeviceY(y
);
2879 int wxCanvasAdmin::LogicalToDeviceXRel(double x
) const
2881 return m_active
->LogicalToDeviceXRel(x
);
2884 int wxCanvasAdmin::LogicalToDeviceYRel(double y
) const
2886 return m_active
->LogicalToDeviceYRel(y
);
2889 void wxCanvasAdmin::SetActive(wxCanvas
* activate
)
2891 wxNode
*node
= m_canvaslist
.First();
2894 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2896 if (activate
== canvas
)
2901 node
= node
->Next();
2904 //--------------------------------------------------------------------
2906 //--------------------------------------------------------------------
2908 class wxCanvasModule
: public wxModule
2911 virtual bool OnInit();
2912 virtual void OnExit();
2915 DECLARE_DYNAMIC_CLASS(wxCanvasModule
)
2918 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
)
2920 bool wxCanvasModule::OnInit()
2923 int error
= FT_Init_FreeType( &g_freetypeLibrary
);
2924 if (error
) return FALSE
;
2930 void wxCanvasModule::OnExit()
2933 FT_Done_FreeType( g_freetypeLibrary
);