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