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
= wxDRAG_ONTOP
;
64 // handy when debugging
65 // m_dragmode = wxDRAG_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
== wxDRAG_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
);
239 else if (m_dragmode
!= wxDRAG_REDRAW
)
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
== wxDRAG_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
);
288 else if (m_dragmode
!= wxDRAG_REDRAW
)
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
);
344 void wxCanvasObject::DragEnd()
346 m_atnewpos
= wxBitmap(0,0);
347 m_admin
->GetActive()->Thaw();
348 this->SetVisible(TRUE
);
349 double x
= GetXMin();
350 double y
= GetYMin();
351 double w
= m_bbox
.GetWidth();
352 double h
= m_bbox
.GetHeight();
353 m_admin
->Update( this, x
, y
, w
, h
);
354 m_admin
->UpdateNow();
357 wxCanvasObject
* wxCanvasObject::IsHitWorld( double x
, double y
, double margin
)
359 if ((x
>= m_bbox
.GetMinX()-margin
) &&
360 (x
<= m_bbox
.GetMaxX()+margin
) &&
361 (y
>= m_bbox
.GetMinY()-margin
) &&
362 (y
<= m_bbox
.GetMaxY()+margin
))
367 return (wxCanvasObject
*) NULL
;
370 wxCanvasObject
* wxCanvasObject::Contains( wxCanvasObject
* obj
)
375 return (wxCanvasObject
*) NULL
;
378 void wxCanvasObject::CaptureMouse()
380 m_admin
->GetActive()->SetCaptureMouse( this );
383 void wxCanvasObject::ReleaseMouse()
385 m_admin
->GetActive()->SetCaptureMouse( NULL
);
388 bool wxCanvasObject::IsCapturedMouse()
390 return (m_admin
->GetActive()->GetCaptured() == this);
394 void wxCanvasObject::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
398 void wxCanvasObject::CalcBoundingBox()
402 void wxCanvasObject::WriteSVG( wxTextOutputStream
&stream
)
406 //----------------------------------------------------------------------------
407 // wxCanvasObjectGroup
408 //----------------------------------------------------------------------------
410 wxCanvasObjectGroup::wxCanvasObjectGroup(double x
, double y
)
412 lworld
.Translate(x
,y
);
413 //no objects make the bounding box the x,y and take care of it later
417 wxCanvasObjectGroup::~wxCanvasObjectGroup()
421 void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler
*handler
)
423 wxCanvasObject::PushEventHandler(handler
);
424 wxNode
*node
= m_objects
.First();
427 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
429 obj
->PushEventHandler(handler
);
435 wxEvtHandler
*wxCanvasObjectGroup::PopEventHandler(bool deleteHandler
)
437 wxNode
*node
= m_objects
.First();
440 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
442 obj
->PopEventHandler(deleteHandler
);
446 return wxCanvasObject::PopEventHandler(deleteHandler
);
449 void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler
*handler
)
451 wxCanvasObject::AppendEventHandler(handler
);
452 wxNode
*node
= m_objects
.First();
455 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
457 obj
->AppendEventHandler(handler
);
463 wxEvtHandler
*wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler
)
465 wxNode
*node
= m_objects
.First();
468 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
470 obj
->RemoveLastEventHandler(deleteHandler
);
474 return wxCanvasObject::RemoveLastEventHandler(deleteHandler
);
477 void wxCanvasObjectGroup::TransLate( double x
, double y
)
479 lworld
.Translate(x
,y
);
483 void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin
* admin
)
486 wxNode
*node
= m_objects
.First();
489 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
491 obj
->SetAdmin(admin
);
497 void wxCanvasObjectGroup::DeleteContents( bool flag
)
499 m_objects
.DeleteContents( flag
);
500 m_bbox
.SetValid(FALSE
);
504 void wxCanvasObjectGroup::Prepend( wxCanvasObject
* obj
)
506 m_objects
.Insert( obj
);
507 if (m_objects
.First())
509 m_bbox
.Expand(obj
->GetBbox());
513 m_bbox
.SetValid(FALSE
);
518 void wxCanvasObjectGroup::Append( wxCanvasObject
* obj
)
520 m_objects
.Append( obj
);
521 if (m_objects
.First())
523 m_bbox
.Expand(obj
->GetBbox());
527 m_bbox
.SetValid(FALSE
);
532 void wxCanvasObjectGroup::Insert( size_t before
, wxCanvasObject
* obj
)
534 m_objects
.Insert( before
, obj
);
535 m_bbox
.SetValid(FALSE
);
536 if (m_objects
.First())
538 m_bbox
.Expand(obj
->GetBbox());
542 m_bbox
.SetValid(FALSE
);
547 void wxCanvasObjectGroup::Remove( wxCanvasObject
* obj
)
549 m_objects
.DeleteObject( obj
);
550 m_bbox
.SetValid(FALSE
);
554 void wxCanvasObjectGroup::CalcBoundingBox()
556 m_bbox
.SetValid(FALSE
);
557 wxNode
*node
= m_objects
.First();
560 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
563 obj
->CalcBoundingBox();
568 m_bbox
.Expand( tmp
);
573 void wxCanvasObjectGroup::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height
)
575 if (!m_visible
) return;
577 wxTransformMatrix backup
= *cworld
;
580 wxNode
*node
= m_objects
.First();
586 wxRect absarea
=GetAbsoluteArea(*cworld
);
587 wxDC
*dc
= m_admin
->GetActive()->GetDC();
588 dc
->SetPen(*wxBLACK_PEN
);
589 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
590 dc
->DrawRectangle( absarea
.x
, absarea
.y
, absarea
.width
, absarea
.height
);
591 dc
->SetBrush(wxNullBrush
);
592 dc
->SetPen(wxNullPen
);
594 //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently
596 if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) &&
597 wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height )
603 // cycle through all objects
606 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
608 if (!obj
->IsControl() && obj
->GetVisible())
611 //get area at the absolute position
612 wxRect absareaobject
= obj
->GetAbsoluteArea(*cworld
);
614 // If we have 10.000 objects, we will go through
615 // this 10.000 times for each update, so we have
616 // to optimise carefully.
617 int clip_x
= absareaobject
.x
;
618 int clip_width
= absareaobject
.width
;
621 clip_width
-= x
-clip_x
;
626 if (clip_x
+ clip_width
> x
+ width
)
627 clip_width
= x
+width
-clip_x
;
631 int clip_y
= absareaobject
.y
;
632 int clip_height
= absareaobject
.height
;
635 clip_height
-= y
-clip_y
;
640 if (clip_y
+ clip_height
> y
+ height
)
641 clip_height
= y
+height
-clip_y
;
645 obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height
);
657 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream
&stream
)
661 wxCanvasObject
* wxCanvasObjectGroup::IsHitWorld( double x
, double y
, double margin
)
663 //KKKfirst check if within bbox
664 //will only work if they are always uptodate
665 //if (!m_bbox.PointInBox(x,y,margin))
666 // return (wxCanvasObject*) NULL;
668 wxTransformMatrix inverse
= lworld
;
671 inverse
.TransformPoint(x
,y
,xh
,yh
);
673 wxCanvasObject
*obj
=0;
674 wxNode
*node
= m_objects
.Last();
677 obj
=(wxCanvasObject
*) node
->Data();
679 if (!obj
->IsControl() )
681 if (obj
->IsHitWorld(xh
,yh
,margin
))
686 node
= node
->Previous();
689 return (wxCanvasObject
*) NULL
;
692 wxCanvasObject
* wxCanvasObjectGroup::Contains( wxCanvasObject
* obj
)
694 wxCanvasObject
* cobj
;
695 wxNode
*node
= m_objects
.First();
698 cobj
=(wxCanvasObject
*) node
->Data();
700 if (cobj
->Contains(obj
))
707 return (wxCanvasObject
*) NULL
;
710 int wxCanvasObjectGroup::IndexOf( wxCanvasObject
* obj
)
712 return m_objects
.IndexOf( obj
);
715 //----------------------------------------------------------------------------
717 //----------------------------------------------------------------------------
719 wxCanvasObjectRef::wxCanvasObjectRef(double x
, double y
, wxCanvasObject
* obj
)
722 lworld
.Translate(x
,y
);
725 m_bbox
.SetValid(FALSE
);
729 m_bbox
.Expand( tmp
);
732 void wxCanvasObjectRef::PushEventHandler(wxEvtHandler
*handler
)
734 wxCanvasObject::PushEventHandler(handler
);
735 m_obj
->PushEventHandler(handler
);
738 wxEvtHandler
*wxCanvasObjectRef::PopEventHandler(bool deleteHandler
)
740 m_obj
->PopEventHandler(deleteHandler
);
741 return wxCanvasObject::PopEventHandler(deleteHandler
);
744 void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler
*handler
)
746 wxCanvasObject::AppendEventHandler(handler
);
747 m_obj
->AppendEventHandler(handler
);
750 wxEvtHandler
*wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler
)
752 m_obj
->RemoveLastEventHandler(deleteHandler
);
753 return wxCanvasObject::RemoveLastEventHandler(deleteHandler
);
756 void wxCanvasObjectRef::TransLate( double x
, double y
)
758 lworld
.Translate(x
,y
);
762 wxCanvasObject
* wxCanvasObjectRef::Contains( wxCanvasObject
* obj
)
764 if (obj
== this || m_obj
->Contains(obj
))
767 return (wxCanvasObject
*) NULL
;
771 void wxCanvasObjectRef::SetRotation(double rotation
)
773 lworld
.SetRotation(rotation
);
777 void wxCanvasObjectRef::SetScale(double scalex
,double scaley
)
779 lworld
.Scale(scalex
,scaley
,lworld
.GetValue(2,0),lworld
.GetValue(2,1));
783 void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin
* admin
)
786 m_obj
->SetAdmin(admin
);
789 void wxCanvasObjectRef::CalcBoundingBox()
791 m_bbox
.SetValid(FALSE
);
792 m_obj
->CalcBoundingBox();
795 tmp
=m_obj
->GetBbox();
797 m_bbox
.Expand( tmp
);
800 void wxCanvasObjectRef::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height
)
802 if (!m_visible
) return;
804 //get the absolute area (without the local matrix included)
805 //the boundingbox is relative to the parent.
806 wxRect absarea
=GetAbsoluteArea(*cworld
);
808 wxTransformMatrix backup
= *cworld
;
812 wxDC
*dc
= m_admin
->GetActive()->GetDC();
813 dc
->SetPen(*wxBLACK_PEN
);
814 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
815 dc
->DrawRectangle( absarea
.x
, absarea
.y
, absarea
.width
, absarea
.height
);
816 dc
->SetBrush(wxNullBrush
);
817 dc
->SetPen(wxNullPen
);
820 int clip_x
= absarea
.x
;
821 int clip_width
= absarea
.width
;
824 clip_width
-= x
-clip_x
;
829 if (clip_x
+ clip_width
> x
+ width
)
830 clip_width
= x
+width
-clip_x
;
834 int clip_y
= absarea
.y
;
835 int clip_height
= absarea
.height
;
838 clip_height
-= y
-clip_y
;
843 if (clip_y
+ clip_height
> y
+ height
)
844 clip_height
= y
+height
-clip_y
;
847 m_obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height
);
855 void wxCanvasObjectRef::WriteSVG( wxTextOutputStream
&stream
)
859 wxCanvasObject
* wxCanvasObjectRef::IsHitWorld( double x
, double y
, double margin
)
861 //KKKfirst check if within bbox
862 //will only work if they are always uptodate
863 //if (!m_bbox.PointInBox(x,y,margin))
864 // return (wxCanvasObject*) NULL;
866 wxTransformMatrix inverse
= lworld
;
869 inverse
.TransformPoint(x
,y
,xh
,yh
);
871 if (m_obj
->IsHitWorld(xh
,yh
,margin
))
874 return (wxCanvasObject
*) NULL
;
879 //----------------------------------------------------------------------------
881 //----------------------------------------------------------------------------
883 wxCanvasRect::wxCanvasRect( double x
, double y
, double w
, double h
, double radius
)
892 m_brush
= *wxBLACK_BRUSH
;
893 m_pen
= *wxTRANSPARENT_PEN
;
897 void wxCanvasRect::TransLate( double x
, double y
)
904 void wxCanvasRect::CalcBoundingBox()
906 m_bbox
.SetMin( m_x
, m_y
);
907 m_bbox
.SetMax( m_x
+ m_width
,m_y
+ m_height
);
909 //include the pen width also
910 //KKK m_bbox.EnLarge(m_pen.GetWidth()+m_radius);
911 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
914 void wxCanvasRect::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
916 if (!m_visible
) return;
918 if (cworld
->GetRotation())
920 wxPoint
*cpoints
= new wxPoint
[4];
923 cworld
->TransformPoint( m_x
, m_y
, x
, y
);
924 cpoints
[0].x
= m_admin
->LogicalToDeviceX(x
);
925 cpoints
[0].y
= m_admin
->LogicalToDeviceY(y
);
926 cworld
->TransformPoint( m_x
, m_y
+ m_height
, x
, y
);
927 cpoints
[1].x
= m_admin
->LogicalToDeviceX(x
);
928 cpoints
[1].y
= m_admin
->LogicalToDeviceY(y
);
929 cworld
->TransformPoint( m_x
+ m_width
, m_y
+ m_height
, x
, y
);
930 cpoints
[2].x
= m_admin
->LogicalToDeviceX(x
);
931 cpoints
[2].y
= m_admin
->LogicalToDeviceY(y
);
932 cworld
->TransformPoint( m_x
+ m_width
, m_y
, x
, y
);
933 cpoints
[3].x
= m_admin
->LogicalToDeviceX(x
);
934 cpoints
[3].y
= m_admin
->LogicalToDeviceY(y
);
936 wxDC
*dc
= m_admin
->GetActive()->GetDC();
937 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
938 dc
->SetBrush(m_brush
);
939 int pw
=m_pen
.GetWidth();
940 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
942 dc
->DrawPolygon(4, cpoints
, 0,0,wxWINDING_RULE
);
944 dc
->SetBrush(wxNullBrush
);
945 dc
->SetPen(wxNullPen
);
946 dc
->DestroyClippingRegion();
951 wxDC
*dc
= m_admin
->GetActive()->GetDC();
952 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
953 dc
->SetBrush(m_brush
);
954 int pw
=m_pen
.GetWidth();
955 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
957 //yes the whole not only the clipping region, because we have a pen also
958 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
959 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
960 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
961 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
962 int r
= m_admin
->LogicalToDeviceYRel( m_radius
);
963 if (w
> 0 && w
< 1) w
=1;
964 if (w
< 0 && w
> -1) w
=-1;
965 if (h
> 0 && h
< 1) h
=1;
966 if (h
< 0 && h
> -1) h
=-1;
968 dc
->DrawRoundedRectangle( x
,y
,w
,h
,r
);
970 dc
->DrawRectangle( x
,y
,w
,h
);
971 dc
->SetBrush(wxNullBrush
);
972 dc
->SetPen(wxNullPen
);
973 dc
->DestroyClippingRegion();
978 void wxCanvasRect::WriteSVG( wxTextOutputStream
&stream
)
982 //----------------------------------------------------------------------------
984 //----------------------------------------------------------------------------
986 wxCanvasCircle::wxCanvasCircle( double x
, double y
, double radius
)
993 m_brush
= *wxBLACK_BRUSH
;
994 m_pen
= *wxTRANSPARENT_PEN
;
998 void wxCanvasCircle::TransLate( double x
, double y
)
1005 void wxCanvasCircle::CalcBoundingBox()
1007 m_bbox
.SetMin( m_x
-m_radius
, m_y
-m_radius
);
1008 m_bbox
.SetMax( m_x
+m_radius
, m_y
+m_radius
);
1010 //include the pen width also
1011 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1014 void wxCanvasCircle::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1016 if (!m_visible
) return;
1018 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1019 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1020 dc
->SetBrush(m_brush
);
1021 int pw
=m_pen
.GetWidth();
1022 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1024 //yes the whole not only the clipping region, because we have a pen also
1025 //and rotation on a circle is not important so only a shift with cworld
1026 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1027 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1028 int radius
= m_admin
->LogicalToDeviceXRel( m_radius
);
1029 if (radius
< 1) radius
=1;
1030 dc
->DrawCircle( x
,y
,radius
);
1031 dc
->SetBrush(wxNullBrush
);
1032 dc
->SetPen(wxNullPen
);
1033 dc
->DestroyClippingRegion();
1037 void wxCanvasCircle::WriteSVG( wxTextOutputStream
&stream
)
1041 wxCanvasObject
* wxCanvasCircle::IsHitWorld( double x
, double y
, double margin
)
1043 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1044 (x
<= m_bbox
.GetMaxX()+margin
) &&
1045 (y
>= m_bbox
.GetMinY()-margin
) &&
1046 (y
<= m_bbox
.GetMaxY()+margin
)
1049 if (m_radius
+m_pen
.GetWidth()/2+margin
> sqrt(pow(m_x
-x
,2)+pow(m_y
-y
,2)))
1052 return (wxCanvasObject
*) NULL
;
1054 return (wxCanvasObject
*) NULL
;
1057 //----------------------------------------------------------------------------
1059 //----------------------------------------------------------------------------
1061 wxCanvasEllipse::wxCanvasEllipse( double x
, double y
, double width
, double height
)
1069 m_brush
= *wxBLACK_BRUSH
;
1070 m_pen
= *wxTRANSPARENT_PEN
;
1074 void wxCanvasEllipse::TransLate( double x
, double y
)
1081 void wxCanvasEllipse::CalcBoundingBox()
1083 m_bbox
.SetMin( m_x
, m_y
);
1084 m_bbox
.SetMax( m_x
+m_width
, m_y
+m_height
);
1086 //include the pen width also
1087 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1090 void wxCanvasEllipse::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1092 if (!m_visible
) return;
1094 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1095 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1096 dc
->SetBrush(m_brush
);
1097 int pw
=m_pen
.GetWidth();
1098 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1100 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1101 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1102 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1103 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1104 if (w
> 0 && w
< 1) w
=1;
1105 if (w
< 0 && w
> -1) w
=-1;
1106 if (h
> 0 && h
< 1) h
=1;
1107 if (h
< 0 && h
> -1) h
=-1;
1108 dc
->DrawEllipse( x
,y
,w
,h
);
1109 dc
->SetBrush(wxNullBrush
);
1110 dc
->SetPen(wxNullPen
);
1111 dc
->DestroyClippingRegion();
1115 void wxCanvasEllipse::WriteSVG( wxTextOutputStream
&stream
)
1119 wxCanvasObject
* wxCanvasEllipse::IsHitWorld( double x
, double y
, double margin
)
1121 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1122 (x
<= m_bbox
.GetMaxX()+margin
) &&
1123 (y
>= m_bbox
.GetMinY()-margin
) &&
1124 (y
<= m_bbox
.GetMaxY()+margin
)
1127 double a
=(m_width
+m_pen
.GetWidth())/2+margin
;
1128 double b
=(m_height
+m_pen
.GetWidth())/2+margin
;
1129 double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2);
1133 return (wxCanvasObject
*) NULL
;
1135 return (wxCanvasObject
*) NULL
;
1138 //----------------------------------------------------------------------------
1139 // wxCanvasEllipticArc
1140 //----------------------------------------------------------------------------
1142 wxCanvasEllipticArc::wxCanvasEllipticArc( double x
, double y
, double width
, double height
, double start
, double end
)
1152 m_brush
= *wxBLACK_BRUSH
;
1153 m_pen
= *wxTRANSPARENT_PEN
;
1157 void wxCanvasEllipticArc::TransLate( double x
, double y
)
1164 void wxCanvasEllipticArc::CalcBoundingBox()
1166 m_bbox
.SetMin( m_x
, m_y
);
1167 m_bbox
.SetMax( m_x
+m_width
, m_y
+m_height
);
1169 //include the pen width also
1170 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1173 void wxCanvasEllipticArc::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1175 if (!m_visible
) return;
1177 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1178 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1179 dc
->SetBrush(m_brush
);
1180 int pw
=m_pen
.GetWidth();
1181 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1183 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1184 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1185 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1186 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1187 if (w
> 0 && w
< 1) w
=1;
1188 if (w
< 0 && w
> -1) w
=-1;
1189 if (h
> 0 && h
< 1) h
=1;
1190 if (h
< 0 && h
> -1) h
=-1;
1191 if (m_admin
->GetActive()->GetYaxis())
1192 dc
->DrawEllipticArc( x
,y
,w
,h
,-m_end
,-m_start
);
1194 dc
->DrawEllipticArc( x
,y
,w
,h
,m_start
,m_end
);
1195 dc
->SetBrush(wxNullBrush
);
1196 dc
->SetPen(wxNullPen
);
1197 dc
->DestroyClippingRegion();
1201 void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream
&stream
)
1205 wxCanvasObject
* wxCanvasEllipticArc::IsHitWorld( double x
, double y
, double margin
)
1207 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1208 (x
<= m_bbox
.GetMaxX()+margin
) &&
1209 (y
>= m_bbox
.GetMinY()-margin
) &&
1210 (y
<= m_bbox
.GetMaxY()+margin
)
1213 double a
=(m_width
+m_pen
.GetWidth())/2+margin
;
1214 double b
=(m_height
+m_pen
.GetWidth())/2+margin
;
1215 double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2);
1219 return (wxCanvasObject
*) NULL
;
1221 return (wxCanvasObject
*) NULL
;
1224 //----------------------------------------------------------------------------
1226 //----------------------------------------------------------------------------
1228 wxCanvasLine::wxCanvasLine( double x1
, double y1
, double x2
, double y2
)
1236 m_pen
= *wxBLACK_PEN
;
1240 void wxCanvasLine::TransLate( double x
, double y
)
1249 void wxCanvasLine::CalcBoundingBox()
1251 m_bbox
.SetMin( m_x1
, m_y1
);
1252 m_bbox
.SetMax( m_x2
, m_y2
);
1254 //include the pen width also
1255 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1258 void wxCanvasLine::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1260 if (!m_visible
) return;
1263 cworld
->TransformPoint( m_x1
, m_y1
, x1
, y1
);
1264 cworld
->TransformPoint( m_x2
, m_y2
, x2
, y2
);
1265 x1
= m_admin
->LogicalToDeviceX( x1
);
1266 y1
= m_admin
->LogicalToDeviceY( y1
);
1267 x2
= m_admin
->LogicalToDeviceX( x2
);
1268 y2
= m_admin
->LogicalToDeviceY( y2
);
1270 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1271 dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height
);
1272 int pw
=m_pen
.GetWidth();
1273 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1274 dc
->SetPen( m_pen
);
1275 dc
->DrawLine( x1
, y1
, x2
, y2
);
1277 dc
->DestroyClippingRegion();
1281 void wxCanvasLine::WriteSVG( wxTextOutputStream
&stream
)
1286 wxCanvasObject
* wxCanvasLine::IsHitWorld( double x
, double y
, double margin
)
1288 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1289 (x
<= m_bbox
.GetMaxX()+margin
) &&
1290 (y
>= m_bbox
.GetMinY()-margin
) &&
1291 (y
<= m_bbox
.GetMaxY()+margin
)
1294 wxLine
line1(m_x1
,m_y1
,m_x2
,m_y2
);
1295 wxPoint2DDouble P
=wxPoint2DDouble(x
,y
);
1297 if (line1
.PointInLine(P
,distance
,m_pen
.GetWidth()/2+margin
) == R_IN_AREA
)
1300 return (wxCanvasObject
*) NULL
;
1302 return (wxCanvasObject
*) NULL
;
1305 //----------------------------------------------------------------------------
1307 //----------------------------------------------------------------------------
1309 wxCanvasImage::wxCanvasImage( const wxImage
&image
, double x
, double y
, double w
, double h
)
1319 m_orgw
= m_image
.GetWidth();
1320 m_orgh
= m_image
.GetHeight();
1326 void wxCanvasImage::SetPosXY( double x
, double y
)
1333 void wxCanvasImage::TransLate( double x
, double y
)
1340 void wxCanvasImage::CalcBoundingBox()
1342 m_bbox
.SetMin( m_x
, m_y
);
1343 m_bbox
.SetMax( m_x
+ m_width
, m_y
+ m_height
);
1346 void wxCanvasImage::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1348 if (!m_visible
) return;
1352 tmparea
.x
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX());
1353 tmparea
.y
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY());
1354 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1355 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1359 cworld
->TransformPoint( m_x
, m_y
, x
, y
);
1360 x
= m_admin
->LogicalToDeviceX(x
);
1361 y
= m_admin
->LogicalToDeviceY(y
);
1365 if ( m_orgw
*5 < m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1366 m_orgw
/5 > m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1367 m_orgh
*5 < m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) ||
1368 m_orgh
/5 > m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() )
1371 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1372 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1373 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
1374 dc
->SetPen(*wxBLACK_PEN
);
1375 //yes the whole not only the clipping region, because we have a pen also
1376 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1377 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1378 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1379 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1382 dc
->DrawRectangle( x
,y
,w
,h
);
1383 dc
->SetBrush(wxNullBrush
);
1384 dc
->SetPen(wxNullPen
);
1385 dc
->DestroyClippingRegion();
1390 bool is_cashed
= FALSE
;
1392 if (m_cImage
.Ok() && (m_cW
== m_bbox
.GetWidth()) && (m_cH
== m_bbox
.GetHeight()))
1400 if ((m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) == m_image
.GetWidth()) &&
1401 (m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) == m_image
.GetHeight()))
1407 tmp
= m_image
.Scale( m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()),
1408 m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight()) );
1411 // create cached image
1413 m_cW
= tmp
.GetWidth();
1414 m_cH
= tmp
.GetHeight();
1417 // wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
1422 if (m_cBitmap
.Ok() && is_cashed
&& (m_cR
== cworld
->GetRotation()))
1428 if (cworld
->GetRotation())
1429 tmp
= tmp
.Rotate(-cworld
->GetRotation()/180.0 * pi
, centr
, TRUE
, NULL
);
1431 bmp
= tmp
.ConvertToBitmap();
1433 // create cached bitmap
1435 m_cR
= cworld
->GetRotation();
1438 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1441 if (cworld
->GetRotation()> 0)
1443 centr2
.x
= (int) (x
+m_height
*sin(-cworld
->GetRotation()/180.0 * pi
));
1449 centr2
.y
= (int) (y
-m_width
*sin(-cworld
->GetRotation()/180.0 * pi
));
1452 if (cworld
->GetRotation() != 0)
1454 //TODO clipping not right
1455 dc
->DrawBitmap(bmp
,centr2
,TRUE
);
1456 // dc->DrawPoint(centr2);
1457 // dc->DrawPoint(x,y);
1461 dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height
);
1462 dc
->DrawBitmap( bmp
, x
, y
, TRUE
);
1463 dc
->DestroyClippingRegion();
1467 void wxCanvasImage::WriteSVG( wxTextOutputStream
&stream
)
1472 //----------------------------------------------------------------------------
1474 //----------------------------------------------------------------------------
1476 wxCanvasControl::wxCanvasControl( wxWindow
*control
)
1480 m_control
= control
;
1484 double wxCanvasControl::GetPosX()
1487 m_control
->GetPosition( &x
, &y
);
1488 return m_admin
->DeviceToLogicalX(x
);
1491 double wxCanvasControl::GetPosY()
1494 m_control
->GetPosition( &x
, &y
);
1495 return m_admin
->DeviceToLogicalY(y
);
1498 void wxCanvasControl::SetPosXY( double x
, double y
)
1500 int xd
= m_admin
->LogicalToDeviceX(x
);
1501 int yd
= m_admin
->LogicalToDeviceY(y
);
1502 m_control
->Move(xd
,yd
);
1506 void wxCanvasControl::TransLate( double x
, double y
)
1509 m_control
->GetPosition( &xdo
, &ydo
);
1510 int xd
= m_admin
->LogicalToDeviceX(x
)-xdo
;
1511 int yd
= m_admin
->LogicalToDeviceY(y
)-ydo
;
1512 m_control
->Move(xd
,yd
);
1516 wxCanvasControl::~wxCanvasControl()
1518 m_control
->Destroy();
1521 void wxCanvasControl::CalcBoundingBox()
1525 m_control
->GetSize( &tmparea
.width
, &tmparea
.height
);
1526 m_control
->GetPosition( &tmparea
.x
, &tmparea
.y
);
1528 m_bbox
.SetMin( tmparea
.x
, tmparea
.y
);
1529 m_bbox
.SetMax( tmparea
.x
+ tmparea
.width
, tmparea
.y
+ tmparea
.height
);
1533 void wxCanvasControl::MoveRelative( double x
, double y
)
1535 m_control
->Move( m_admin
->LogicalToDeviceX(x
), m_admin
->LogicalToDeviceX(y
) );
1538 //----------------------------------------------------------------------------
1540 //----------------------------------------------------------------------------
1552 wxCanvasText::wxCanvasText( const wxString
&text
, double x
, double y
, const wxString
&fontFile
, int size
)
1556 m_fontFileName
= fontFile
;
1569 wxFaceData
*data
= new wxFaceData
;
1572 int error
= FT_New_Face( g_freetypeLibrary
,
1577 error
= FT_Set_Char_Size( data
->m_face
,
1586 wxCanvasText::~wxCanvasText()
1589 wxFaceData
*data
= (wxFaceData
*) m_faceData
;
1593 if (m_alpha
) delete [] m_alpha
;
1596 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue
)
1603 void wxCanvasText::SetFlag( int flag
)
1608 void wxCanvasText::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1610 if (!m_visible
) return;
1613 tmparea
.x
= m_admin
->LogicalToDeviceX( m_bbox
.GetMinX());
1614 tmparea
.y
= m_admin
->LogicalToDeviceY( m_bbox
.GetMinY());
1615 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1616 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1618 m_alpha
= new unsigned char[tmparea
.width
*tmparea
.height
];
1619 memset( m_alpha
, 0, tmparea
.width
*tmparea
.height
);
1621 if (!m_alpha
) return;
1624 FT_Face face
= ((wxFaceData
*)m_faceData
)->m_face
;
1625 FT_GlyphSlot slot
= face
->glyph
;
1629 for (int n
= 0; n
< (int)m_text
.Len(); n
++)
1631 FT_UInt index
= FT_Get_Char_Index( face
, m_text
[(unsigned int)n
] );
1633 int error
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT
);
1634 if (error
) continue;
1636 error
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal
);
1637 if (error
) continue;
1639 FT_Bitmap
*bitmap
= &slot
->bitmap
;
1640 unsigned char* buffer
= bitmap
->buffer
;
1641 for (int y
= 0; y
< bitmap
->rows
; y
++)
1642 for (int x
= 0; x
< bitmap
->width
; x
++)
1644 unsigned char alpha
= buffer
[ y
*bitmap
->pitch
+ x
];
1645 if (alpha
== 0) continue;
1647 int xx
= pen_x
+ slot
->bitmap_left
+ x
;
1648 int yy
= pen_y
- slot
->bitmap_top
+ y
;
1649 m_alpha
[ yy
* tmparea
.width
+ xx
] = alpha
;
1652 pen_x
+= slot
->advance
.x
>> 6;
1653 pen_y
+= slot
->advance
.y
>> 6;
1657 wxBitmap
*bitmap
= m_admin
->GetActive()->GetBuffer();
1658 wxRect
sub_rect( clip_x
, clip_y
, clip_width
, clip_height
);
1659 wxBitmap
sub_bitmap( bitmap
->GetSubBitmap( sub_rect
) );
1661 wxImage
image( sub_bitmap
);
1663 // local coordinates
1664 int start_x
= clip_x
- tmparea
.x
;
1665 int end_x
= clip_width
+ start_x
;
1666 int start_y
= clip_y
- tmparea
.y
;
1667 int end_y
= clip_height
+ start_y
;
1669 for (int y
= start_y
; y
< end_y
; y
++)
1670 for (int x
= start_x
; x
< end_x
; x
++)
1672 int alpha
= m_alpha
[y
*tmparea
.width
+ x
];
1675 int image_x
= x
- start_x
;
1676 int image_y
= y
- start_y
;
1679 image
.SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
1682 int red1
= (m_red
* alpha
) / 255;
1683 int green1
= (m_green
* alpha
) / 255;
1684 int blue1
= (m_blue
* alpha
) / 255;
1687 int red2
= image
.GetRed( image_x
, image_y
);
1688 int green2
= image
.GetGreen( image_x
, image_y
);
1689 int blue2
= image
.GetBlue( image_x
, image_y
);
1690 red2
= (red2
* alpha
) / 255;
1691 green2
= (green2
* alpha
) / 255;
1692 blue2
= (blue2
* alpha
) / 255;
1694 image
.SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
1698 sub_bitmap
= image
.ConvertToBitmap();
1700 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1701 dc
->DrawBitmap( sub_bitmap
, clip_x
, clip_y
);
1704 void wxCanvasText::WriteSVG( wxTextOutputStream
&stream
)
1708 void wxCanvasText::TransLate( double x
, double y
)
1715 void wxCanvasText::CalcBoundingBox()
1717 if (m_alpha
) delete [] m_alpha
;
1719 m_bbox
.SetMin( m_x
, m_y
);
1720 m_bbox
.SetMax( m_x
+ 100 , m_y
+ m_size
+ (m_size
/2));
1725 //----------------------------------------------------------------------------
1727 //----------------------------------------------------------------------------
1729 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
)
1731 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
)
1732 EVT_PAINT( wxCanvas::OnPaint
)
1733 EVT_IDLE( wxCanvas::OnIdle
)
1734 EVT_SIZE( wxCanvas::OnSize
)
1735 EVT_MOUSE_EVENTS( wxCanvas::OnMouse
)
1736 EVT_SET_FOCUS( wxCanvas::OnSetFocus
)
1737 EVT_KILL_FOCUS( wxCanvas::OnKillFocus
)
1738 EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground
)
1741 wxCanvas::wxCanvas( wxCanvasAdmin
* admin
, wxWindow
*parent
, wxWindowID id
,
1742 const wxPoint
&position
, const wxSize
& size
, long style
) :
1743 wxScrolledWindow( parent
, id
, position
, size
, style
)
1745 // These are unused in wxVectorCanvas
1750 m_admin
->Append( this );
1752 m_needUpdate
= FALSE
;
1753 m_background
= *wxWHITE
;
1754 m_lastMouse
= (wxCanvasObject
*)NULL
;
1755 m_captureMouse
= (wxCanvasObject
*)NULL
;
1759 m_root
= (wxCanvasObjectGroup
*)NULL
;
1762 wxCanvas::~wxCanvas()
1764 wxNode
*node
= m_updateRects
.First();
1767 wxRect
*rect
= (wxRect
*) node
->Data();
1769 m_updateRects
.DeleteNode( node
);
1770 node
= m_updateRects
.First();
1774 double wxCanvas::GetMinX() const
1779 double wxCanvas::GetMinY() const
1784 double wxCanvas::GetMaxX() const
1787 GetVirtualSize( &width
, NULL
);
1791 double wxCanvas::GetMaxY() const
1794 GetVirtualSize( NULL
, &height
);
1798 void wxCanvas::SetColour( const wxColour
& background
)
1800 m_background
= background
;
1801 SetBackgroundColour( m_background
);
1803 if (m_frozen
) return;
1806 dc
.SelectObject( m_buffer
);
1807 dc
.SetPen( *wxTRANSPARENT_PEN
);
1808 wxBrush
brush( m_background
, wxSOLID
);
1809 dc
.SetBrush( brush
);
1810 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
1811 dc
.SelectObject( wxNullBitmap
);
1814 void wxCanvas::SetCaptureMouse( wxCanvasObject
*obj
)
1818 wxWindow::CaptureMouse();
1819 m_captureMouse
= obj
;
1823 wxWindow::ReleaseMouse();
1824 m_captureMouse
= NULL
;
1828 void wxCanvas::Freeze()
1833 void wxCanvas::Thaw()
1835 wxNode
*node
= m_updateRects
.First();
1838 wxRect
*rect
= (wxRect
*) node
->Data();
1840 m_updateRects
.DeleteNode( node
);
1841 node
= m_updateRects
.First();
1847 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
1850 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit
)
1852 CalcScrolledPosition( 0, 0, &m_oldDeviceX
, &m_oldDeviceY
);
1854 m_admin
->SetActive(this);
1856 if (!m_root
) return;
1858 if (m_frozen
) return;
1863 width
-= m_bufferX
-x
;
1866 if (width
<= 0) return;
1870 height
-= m_bufferY
-y
;
1873 if (height
<= 0) return;
1875 if (x
+width
> m_bufferX
+m_buffer
.GetWidth())
1877 width
= m_bufferX
+m_buffer
.GetWidth() - x
;
1879 if (width
<= 0) return;
1881 if (y
+height
> m_bufferY
+m_buffer
.GetHeight())
1883 height
= m_bufferY
+m_buffer
.GetHeight() - y
;
1885 if (height
<= 0) return;
1887 // update is within the buffer
1888 m_needUpdate
= TRUE
;
1890 // has to be blitted to screen later
1893 m_updateRects
.Append(
1894 (wxObject
*) new wxRect( x
,y
,width
,height
) );
1897 wxTransformMatrix cworld
;
1900 dc
.SelectObject( m_buffer
);
1902 dc
.SetPen( *wxTRANSPARENT_PEN
);
1903 wxBrush
brush( m_background
, wxSOLID
);
1904 dc
.SetBrush( brush
);
1905 dc
.SetLogicalFunction(wxCOPY
);
1908 if (width
!= m_buffer
.GetWidth() && height
!= m_buffer
.GetHeight())
1910 dc
.SetClippingRegion(x
,y
,width
,height
);
1911 dc
.DrawRectangle(x
-2,y
-2,width
+4,height
+4);
1912 dc
.DestroyClippingRegion();
1917 dc
.DrawRectangle(0,0,m_buffer
.GetWidth(),m_buffer
.GetHeight());
1920 // No idea, what the code up there does.
1921 dc
.DrawRectangle( x
-m_bufferX
, y
-m_bufferY
, width
, height
);
1924 dc
.SetBrush(wxNullBrush
);
1925 dc
.SetPen(wxNullPen
);
1927 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
1930 m_root
->Render( &cworld
, x
, y
, width
, height
);
1933 dc
.SelectObject( wxNullBitmap
);
1936 void wxCanvas::BlitBuffer( wxDC
&dc
)
1938 wxNode
*node
= m_updateRects
.First();
1941 wxRect
*rect
= (wxRect
*) node
->Data();
1944 mdc
.SelectObject( m_buffer
);
1950 rect
->x
- m_bufferX
,
1951 rect
->y
- m_bufferY
);
1952 mdc
.SelectObject( wxNullBitmap
);
1955 m_updateRects
.DeleteNode( node
);
1956 node
= m_updateRects
.First();
1959 m_needUpdate
= FALSE
;
1962 void wxCanvas::UpdateNow()
1964 if (m_frozen
) return;
1966 if (!m_needUpdate
) return;
1968 wxClientDC
dc( this );
1974 void wxCanvas::OnSize(wxSizeEvent
&event
)
1977 GetClientSize( &w
, &h
);
1978 m_buffer
= wxBitmap( w
, h
);
1980 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
1982 wxNode
*node
= m_updateRects
.First();
1985 wxRect
*rect
= (wxRect
*) node
->Data();
1987 m_updateRects
.DeleteNode( node
);
1988 node
= m_updateRects
.First();
1993 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
1998 void wxCanvas::OnPaint(wxPaintEvent
&event
)
2003 if (!m_buffer
.Ok()) return;
2005 if (m_frozen
) return;
2007 m_needUpdate
= TRUE
;
2009 wxRegionIterator
it( GetUpdateRegion() );
2015 int w
= it
.GetWidth();
2016 int h
= it
.GetHeight();
2018 if (x
+w
> m_buffer
.GetWidth())
2019 w
= m_buffer
.GetWidth() - x
;
2020 if (y
+h
> m_buffer
.GetHeight())
2021 h
= m_buffer
.GetHeight() - y
;
2023 if ((w
> 0) && (h
> 0))
2027 m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h
) );
2036 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
2038 // If any updates are pending, do them now since they will
2039 // expect the previous m_bufferX and m_bufferY as well as
2040 // the previous device origin values.
2041 wxClientDC
dc( this );
2042 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
2045 // The buffer always starts at the top left corner of the
2046 // client area. Indeed, it is the client area.
2047 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
2049 // Update everything.
2050 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
2052 // Scroll, actually.
2053 wxWindow::ScrollWindow( dx
, dy
, rect
);
2056 void wxCanvas::OnMouse(wxMouseEvent
&event
)
2058 m_admin
->SetActive(this);
2065 int x
= event
.GetX();
2066 int y
= event
.GetY();
2068 //to world coordinates to do hit test in world coordinates
2069 double xw
= DeviceToLogicalX( x
);
2070 double yw
= DeviceToLogicalY( y
);
2072 //make a select margin of 2 pixels, so also zero line thickness will be hit
2073 double margin
= DeviceToLogicalXRel( 2 );
2075 if (event
.GetEventType() == wxEVT_MOTION
)
2077 if (m_captureMouse
) //no matter what go to this one
2079 wxMouseEvent
child_event( wxEVT_MOTION
);
2080 child_event
.SetEventObject(m_captureMouse
);
2081 child_event
.m_x
= x
;
2082 child_event
.m_y
= y
;
2083 child_event
.m_leftDown
= event
.m_leftDown
;
2084 child_event
.m_rightDown
= event
.m_rightDown
;
2085 child_event
.m_middleDown
= event
.m_middleDown
;
2086 child_event
.m_controlDown
= event
.m_controlDown
;
2087 child_event
.m_shiftDown
= event
.m_shiftDown
;
2088 child_event
.m_altDown
= event
.m_altDown
;
2089 child_event
.m_metaDown
= event
.m_metaDown
;
2091 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2096 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2098 if (obj
&& !obj
->IsControl())
2100 wxMouseEvent
child_event( wxEVT_MOTION
);
2101 child_event
.SetEventObject( obj
);
2102 child_event
.m_x
= x
;
2103 child_event
.m_y
= y
;
2104 child_event
.m_leftDown
= event
.m_leftDown
;
2105 child_event
.m_rightDown
= event
.m_rightDown
;
2106 child_event
.m_middleDown
= event
.m_middleDown
;
2107 child_event
.m_controlDown
= event
.m_controlDown
;
2108 child_event
.m_shiftDown
= event
.m_shiftDown
;
2109 child_event
.m_altDown
= event
.m_altDown
;
2110 child_event
.m_metaDown
= event
.m_metaDown
;
2112 if ((obj
!= m_lastMouse
) && (m_lastMouse
!= NULL
))
2114 child_event
.SetEventType( wxEVT_LEAVE_WINDOW
);
2115 child_event
.SetEventObject( m_lastMouse
);
2116 child_event
.m_x
= x
;
2117 child_event
.m_y
= y
;
2118 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2121 child_event
.SetEventType( wxEVT_ENTER_WINDOW
);
2122 child_event
.SetEventObject( m_lastMouse
);
2123 child_event
.m_x
= x
;
2124 child_event
.m_y
= y
;
2125 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2127 child_event
.SetEventType( wxEVT_MOTION
);
2128 child_event
.SetEventObject( obj
);
2131 obj
->ProcessCanvasObjectEvent( child_event
);
2137 wxMouseEvent
child_event( wxEVT_LEAVE_WINDOW
);
2138 child_event
.SetEventObject( m_lastMouse
);
2139 child_event
.m_x
= x
;
2140 child_event
.m_y
= y
;
2141 child_event
.m_leftDown
= event
.m_leftDown
;
2142 child_event
.m_rightDown
= event
.m_rightDown
;
2143 child_event
.m_middleDown
= event
.m_middleDown
;
2144 child_event
.m_controlDown
= event
.m_controlDown
;
2145 child_event
.m_shiftDown
= event
.m_shiftDown
;
2146 child_event
.m_altDown
= event
.m_altDown
;
2147 child_event
.m_metaDown
= event
.m_metaDown
;
2148 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2150 m_lastMouse
= (wxCanvasObject
*) NULL
;
2156 if (m_captureMouse
) //no matter what go to this one
2158 wxMouseEvent
child_event( event
.GetEventType() );
2159 child_event
.SetEventObject(m_captureMouse
);
2160 child_event
.m_x
= x
;
2161 child_event
.m_y
= y
;
2162 child_event
.m_leftDown
= event
.m_leftDown
;
2163 child_event
.m_rightDown
= event
.m_rightDown
;
2164 child_event
.m_middleDown
= event
.m_middleDown
;
2165 child_event
.m_controlDown
= event
.m_controlDown
;
2166 child_event
.m_shiftDown
= event
.m_shiftDown
;
2167 child_event
.m_altDown
= event
.m_altDown
;
2168 child_event
.m_metaDown
= event
.m_metaDown
;
2169 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2173 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2175 if (obj
&& !obj
->IsControl())
2177 wxMouseEvent
child_event( event
.GetEventType() );
2178 child_event
.SetEventObject( obj
);
2179 child_event
.m_x
= x
;
2180 child_event
.m_y
= y
;
2181 child_event
.m_leftDown
= event
.m_leftDown
;
2182 child_event
.m_rightDown
= event
.m_rightDown
;
2183 child_event
.m_middleDown
= event
.m_middleDown
;
2184 child_event
.m_controlDown
= event
.m_controlDown
;
2185 child_event
.m_shiftDown
= event
.m_shiftDown
;
2186 child_event
.m_altDown
= event
.m_altDown
;
2187 child_event
.m_metaDown
= event
.m_metaDown
;
2189 obj
->ProcessCanvasObjectEvent( child_event
);
2198 void wxCanvas::OnIdle(wxIdleEvent
&event
)
2200 m_admin
->SetActive(this);
2205 void wxCanvas::OnSetFocus(wxFocusEvent
&event
)
2207 m_admin
->SetActive(this);
2210 void wxCanvas::OnKillFocus(wxFocusEvent
&event
)
2215 void wxCanvas::OnEraseBackground(wxEraseEvent
&event
)
2219 // coordinates conversions
2220 // -----------------------
2221 double wxCanvas::DeviceToLogicalX(int x
) const
2226 double wxCanvas::DeviceToLogicalY(int y
) const
2231 double wxCanvas::DeviceToLogicalXRel(int x
) const
2236 double wxCanvas::DeviceToLogicalYRel(int y
) const
2241 int wxCanvas::LogicalToDeviceX(double x
) const
2243 return (int)(x
+ 0.5);
2246 int wxCanvas::LogicalToDeviceY(double y
) const
2248 return (int)(y
+ 0.5);
2251 int wxCanvas::LogicalToDeviceXRel(double x
) const
2253 return (int)(x
+ 0.5);
2256 int wxCanvas::LogicalToDeviceYRel(double y
) const
2258 return (int)(y
+ 0.5);
2261 //----------------------------------------------------------------------------
2263 //----------------------------------------------------------------------------
2265 IMPLEMENT_CLASS(wxVectorCanvas
,wxCanvas
)
2267 BEGIN_EVENT_TABLE(wxVectorCanvas
,wxCanvas
)
2268 EVT_SCROLLWIN( wxVectorCanvas::OnScroll
)
2269 EVT_CHAR( wxVectorCanvas::OnChar
)
2270 EVT_SIZE( wxVectorCanvas::OnSize
)
2273 wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin
* admin
, wxWindow
*parent
, wxWindowID id
,
2274 const wxPoint
&position
, const wxSize
& size
, long style
) :
2275 wxCanvas( admin
, parent
, id
, position
, size
, style
)
2281 double wxVectorCanvas::GetMinX() const
2286 double wxVectorCanvas::GetMinY() const
2291 double wxVectorCanvas::GetMaxX() const
2296 double wxVectorCanvas::GetMaxY() const
2301 void wxVectorCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
2303 // If any updates are pending, do them now since they will
2304 // expect the previous m_bufferX and m_bufferY as well as
2305 // the previous device origin values.
2306 wxClientDC
dc( this );
2307 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
2312 double dyv
=DeviceToLogicalYRel(dy
);
2313 m_virt_minY
=m_virt_minY
-dyv
;
2314 m_virt_maxY
=m_virt_maxY
-dyv
;
2318 double dxv
=DeviceToLogicalXRel(dx
);
2319 m_virt_minX
=m_virt_minX
-dxv
;
2320 m_virt_maxX
=m_virt_maxX
-dxv
;
2323 m_admin
->SetActive(this);
2324 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2329 if (dy
> 0 && dy
< m_buffer
.GetHeight())
2331 wxRect
rect( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight()-dy
);
2332 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2334 dcm
.SelectObject( m_buffer
);
2335 dcm
.DrawBitmap( sub_bitmap
, 0, dy
, TRUE
);
2336 dcm
.SelectObject( wxNullBitmap
);
2338 Update( 0, 0, m_buffer
.GetWidth(), dy
, TRUE
);
2340 else if (dy
< 0 && dy
> -m_buffer
.GetHeight())
2342 wxRect
rect( 0, -dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight()+dy
);
2343 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2345 dcm
.SelectObject( m_buffer
);
2346 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2347 dcm
.SelectObject( wxNullBitmap
);
2349 Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2352 Update( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2357 if (dx
> 0 && dx
< m_buffer
.GetWidth())
2359 wxRect
rect( 0, 0, m_buffer
.GetWidth()-dx
, m_buffer
.GetHeight());
2360 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2362 dcm
.SelectObject( m_buffer
);
2363 dcm
.DrawBitmap( sub_bitmap
, dx
, 0, TRUE
);
2364 dcm
.SelectObject( wxNullBitmap
);
2366 Update( 0, 0, dx
, m_buffer
.GetHeight(), TRUE
);
2368 else if (dx
< 0 && dx
> -m_buffer
.GetWidth())
2370 wxRect
rect( -dx
, 0, m_buffer
.GetWidth()+dx
, m_buffer
.GetHeight());
2371 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2373 dcm
.SelectObject( m_buffer
);
2374 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2375 dcm
.SelectObject( wxNullBitmap
);
2377 Update( m_buffer
.GetWidth()+dx
, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2380 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2383 wxWindow::ScrollWindow( dx
, dy
, rect
);
2385 //must be done now because quick repeated scrolling will prevent wxPaint
2386 //from doing it properly
2390 void wxVectorCanvas::OnSize(wxSizeEvent
&event
)
2394 GetClientSize( &w
, &h
);
2397 m_buffer
= wxBitmap( w
, h
);
2398 dc
.SelectObject( m_buffer
);
2399 dc
.SetPen( *wxTRANSPARENT_PEN
);
2400 wxBrush
brush( m_background
, wxSOLID
);
2401 dc
.SetBrush( brush
);
2402 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
2403 dc
.SelectObject( wxNullBitmap
);
2405 wxNode
*node
= m_updateRects
.First();
2408 wxRect
*rect
= (wxRect
*) node
->Data();
2410 m_updateRects
.DeleteNode( node
);
2411 node
= m_updateRects
.First();
2416 m_admin
->SetActive(this);
2417 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2419 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
2424 // maps the virtual window (Real drawing to the window coordinates
2425 // also used for zooming
2426 void wxVectorCanvas::SetMappingScroll( double vx1
, double vy1
, double vx2
, double vy2
, bool border
)
2429 GetClientSize(&dwxi
,&dwyi
);
2431 if (vx2
==vx1
) vx2
=vx1
+100000;
2432 if (vy2
==vy1
) vy2
=vy1
+100000;
2443 double dvx
= m_virt_maxX
- m_virt_minX
;
2444 double dvy
= m_virt_maxY
- m_virt_minY
;
2446 // calculate the scaling factor for the virtual window
2449 if ((dvy
/ dvx
) < (dwy
/ dwx
))
2451 dvy
= dvx
* (dwy
/ dwx
);
2452 // calculate the change in the coordinates
2453 temp_y
= (dvy
- (m_virt_maxY
- m_virt_minY
) )/ 2.0;
2457 dvx
= dvy
* (dwx
/ dwy
);
2458 // calculate the change in the coordinates
2459 temp_x
= (dvx
- (m_virt_maxX
- m_virt_minX
) )/ 2.0;
2462 // add or substract the change from the original coordinates
2463 m_virt_minX
=m_virt_minX
-temp_x
;
2464 m_virt_minY
=m_virt_minY
-temp_y
;
2466 m_virt_maxX
=m_virt_maxX
+temp_x
;
2467 m_virt_maxY
=m_virt_maxY
+temp_y
;
2469 // initialize the mapping_matrix used for mapping the
2470 // virtual windows to the drawing window
2472 // make mappingmatrix
2473 m_mapping_matrix
.Identity();
2476 // translate the drawing to 0,0
2478 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2480 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2484 // make a small white border around the drawing
2485 m_virt_minX
=m_virt_minX
- 0.05 * dvx
;
2486 m_virt_minY
=m_virt_minY
- 0.05 * dvy
;
2488 m_virt_maxX
=m_virt_maxX
+ 0.05 * dvx
;
2489 m_virt_maxY
=m_virt_maxY
+ 0.05 * dvy
;
2491 // translate the drawing to 0,0
2493 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2495 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2498 double scalefactor_x
= dwx
;
2499 scalefactor_x
/= (m_virt_maxX
- m_virt_minX
);
2501 double scalefactor_y
= dwy
;
2502 scalefactor_y
/= (m_virt_maxY
- m_virt_minY
);
2504 // scale the drawing so it fit's in the window
2505 m_mapping_matrix
.Scale(scalefactor_x
, scalefactor_y
, 0, 0);
2507 // because of coordinate change mirror over X
2508 // 0,0 in graphic computerscreens: upperleft corner
2509 // 0,0 in cartesian: lowerleft corner
2512 m_mapping_matrix
.Mirror();
2514 // make inverse of mapping matrix
2515 // this is to set coordinates in the statusbar
2516 // and the calculate screencoordinates to world coordinates used
2518 m_inverse_mapping
=m_mapping_matrix
;
2519 m_inverse_mapping
.Invert();
2522 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2525 GetClientSize(&dx2
,&dy2
);
2526 if ( dwxi
!= dx2
|| dwyi
!= dy2
) //scrollbar is/became empty
2527 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2531 void wxVectorCanvas::SetScroll(double vx1
,double vy1
,double vx2
,double vy2
)
2538 double dvx
= m_virt_maxX
- m_virt_minX
;
2539 double dvy
= m_virt_maxY
- m_virt_minY
;
2540 double dmvx
= m_virtm_maxX
- m_virtm_minX
;
2541 double dmvy
= m_virtm_maxY
- m_virtm_minY
;
2543 SetScrollbar(wxHORIZONTAL
,(m_virt_minX
-m_virtm_minX
)/dmvx
*1000,dvx
/dmvx
*1000,1000,FALSE
);
2546 SetScrollbar(wxVERTICAL
,(m_virtm_maxY
-m_virt_maxY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2550 SetScrollbar(wxVERTICAL
,(m_virt_minY
-m_virtm_minY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2556 // coordinates conversions
2557 // -----------------------
2558 double wxVectorCanvas::DeviceToLogicalX(int x
) const
2560 return m_inverse_mapping
.GetValue(0,0) * x
+ m_inverse_mapping
.GetValue(2,0);
2563 double wxVectorCanvas::DeviceToLogicalY(int y
) const
2565 return m_inverse_mapping
.GetValue(1,1) * y
+ m_inverse_mapping
.GetValue(2,1);
2568 double wxVectorCanvas::DeviceToLogicalXRel(int x
) const
2570 return x
*m_inverse_mapping
.GetValue(0,0);
2573 double wxVectorCanvas::DeviceToLogicalYRel(int y
) const
2575 return y
*m_inverse_mapping
.GetValue(1,1);
2578 int wxVectorCanvas::LogicalToDeviceX(double x
) const
2580 return (int) (m_mapping_matrix
.GetValue(0,0) * x
+ m_mapping_matrix
.GetValue(2,0) + 0.5);
2583 int wxVectorCanvas::LogicalToDeviceY(double y
) const
2585 return (int) (m_mapping_matrix
.GetValue(1,1) * y
+ m_mapping_matrix
.GetValue(2,1) + 0.5);
2588 int wxVectorCanvas::LogicalToDeviceXRel(double x
) const
2590 return (int) (x
*m_mapping_matrix
.GetValue(0,0) + 0.5);
2593 int wxVectorCanvas::LogicalToDeviceYRel(double y
) const
2595 return (int) (y
*m_mapping_matrix
.GetValue(1,1) + 0.5);
2599 // return the inverse mapping matrix for zooming or coordinates
2600 wxTransformMatrix
wxVectorCanvas::GetInverseMappingMatrix()
2602 return m_inverse_mapping
;
2605 wxTransformMatrix
wxVectorCanvas::GetMappingMatrix()
2607 return m_mapping_matrix
;
2611 // ----------------------------------------------------------------------------
2612 // scrolling behaviour
2613 // ----------------------------------------------------------------------------
2615 void wxVectorCanvas::OnScroll(wxScrollWinEvent
& event
)
2617 if (event
.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE
)
2619 if (event
.GetOrientation()==wxHORIZONTAL
)
2621 double x
=m_virtm_minX
+event
.GetPosition()/1000.0*(m_virtm_maxX
-m_virtm_minX
);
2622 x
=LogicalToDeviceXRel(x
-m_virt_minX
);
2623 ScrollWindow(-x
, 0, (const wxRect
*) NULL
);
2627 double y
=m_virtm_minY
+event
.GetPosition()/1000.0*(m_virtm_maxY
-m_virtm_minY
);
2628 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2629 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2632 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEUP
)
2634 if (event
.GetOrientation()==wxHORIZONTAL
)
2636 double x
=GetBufferWidth();
2637 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2641 double y
=GetBufferHeight();
2642 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2645 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN
)
2647 if (event
.GetOrientation()==wxHORIZONTAL
)
2649 double x
=-GetBufferWidth();
2650 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2654 double y
=-GetBufferHeight();
2655 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2658 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEUP
)
2660 if (event
.GetOrientation()==wxHORIZONTAL
)
2662 int x
=GetBufferWidth()/10;
2663 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2667 int y
=GetBufferHeight()/10;
2668 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2671 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN
)
2673 if (event
.GetOrientation()==wxHORIZONTAL
)
2675 int x
=-GetBufferWidth()/10;
2676 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2680 int y
=-GetBufferHeight()/10;
2681 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2687 void wxVectorCanvas::OnChar(wxKeyEvent
& event
)
2689 switch ( event
.KeyCode() )
2694 double y
=GetBufferHeight();
2695 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2701 double y
=-GetBufferHeight();
2702 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2707 double y
=m_virtm_minY
;
2708 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2709 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2714 double y
=m_virtm_minY
+(m_virtm_maxY
-m_virtm_minY
);
2715 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2716 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2722 if (!event
.ControlDown())
2723 y
=GetBufferHeight()/10;
2725 y
=GetBufferHeight();
2726 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2733 if (!event
.ControlDown())
2734 y
=-GetBufferHeight()/10;
2736 y
=-GetBufferHeight();
2737 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2744 if (!event
.ControlDown())
2745 x
=GetBufferWidth()/10;
2748 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2754 if (!event
.ControlDown())
2755 x
=-GetBufferWidth()/10;
2757 x
=-GetBufferWidth();
2758 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2768 //----------------------------------------------------------------------------
2770 //----------------------------------------------------------------------------
2772 wxCanvasAdmin::wxCanvasAdmin()
2777 wxCanvasAdmin::~wxCanvasAdmin()
2782 void wxCanvasAdmin::Append( wxCanvas
* canvas
)
2784 m_canvaslist
.Append( canvas
);
2787 void wxCanvasAdmin::Remove( wxCanvas
* canvas
)
2789 m_canvaslist
.DeleteObject( canvas
);
2792 void wxCanvasAdmin::Update(wxCanvasObject
* obj
, double x
, double y
, double width
, double height
)
2794 wxNode
*node
= m_canvaslist
.First();
2798 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2800 if (m_active
== canvas
)
2802 int xi
= canvas
->LogicalToDeviceX( x
);
2803 int yi
= canvas
->LogicalToDeviceY( y
);
2804 int wi
= canvas
->LogicalToDeviceXRel( width
);
2805 int hi
= canvas
->LogicalToDeviceYRel( height
);
2806 //update a little more then is strictly needed,
2807 //to get rid of the 1 bit bugs
2808 if (canvas
->GetYaxis())
2809 canvas
->Update( xi
-2, yi
+hi
-2, wi
+4, -hi
+4);
2811 canvas
->Update( xi
-2, yi
-2, wi
+4, hi
+4);
2814 { wxCanvasObject
* topobj
=canvas
->GetRoot()->Contains(obj
);
2817 wxCanvas
* tcanvas
= m_active
;
2821 //KKK TODO somehow the next does not work for update i do not know why
2822 canvas->GetRoot()->CalcBoundingBox();
2823 int xi = topobj->GetX();
2824 int yi = topobj->GetY();
2825 int wi = topobj->GetWidth();
2826 int hi = topobj->GetHeight();
2828 canvas
->Update( 0,0, canvas
->GetBufferWidth(),canvas
->GetBufferHeight());
2833 node
= node
->Next();
2837 void wxCanvasAdmin::UpdateNow()
2839 wxNode
*node
= m_canvaslist
.First();
2842 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2844 canvas
->UpdateNow();
2845 node
= node
->Next();
2849 // coordinates conversions
2850 // -----------------------
2851 double wxCanvasAdmin::DeviceToLogicalX(int x
) const
2853 return m_active
->DeviceToLogicalX(x
);
2856 double wxCanvasAdmin::DeviceToLogicalY(int y
) const
2858 return m_active
->DeviceToLogicalY(y
);
2861 double wxCanvasAdmin::DeviceToLogicalXRel(int x
) const
2863 return m_active
->DeviceToLogicalXRel(x
);
2866 double wxCanvasAdmin::DeviceToLogicalYRel(int y
) const
2868 return m_active
->DeviceToLogicalYRel(y
);
2871 int wxCanvasAdmin::LogicalToDeviceX(double x
) const
2873 return m_active
->LogicalToDeviceX(x
);
2876 int wxCanvasAdmin::LogicalToDeviceY(double y
) const
2878 return m_active
->LogicalToDeviceY(y
);
2881 int wxCanvasAdmin::LogicalToDeviceXRel(double x
) const
2883 return m_active
->LogicalToDeviceXRel(x
);
2886 int wxCanvasAdmin::LogicalToDeviceYRel(double y
) const
2888 return m_active
->LogicalToDeviceYRel(y
);
2891 void wxCanvasAdmin::SetActive(wxCanvas
* activate
)
2893 wxNode
*node
= m_canvaslist
.First();
2896 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2898 if (activate
== canvas
)
2903 node
= node
->Next();
2906 //--------------------------------------------------------------------
2908 //--------------------------------------------------------------------
2910 class wxCanvasModule
: public wxModule
2913 virtual bool OnInit();
2914 virtual void OnExit();
2917 DECLARE_DYNAMIC_CLASS(wxCanvasModule
)
2920 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
)
2922 bool wxCanvasModule::OnInit()
2925 int error
= FT_Init_FreeType( &g_freetypeLibrary
);
2926 if (error
) return FALSE
;
2932 void wxCanvasModule::OnExit()
2935 FT_Done_FreeType( g_freetypeLibrary
);