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
);