1 /////////////////////////////////////////////////////////////////////////////
3 // Author: Robert Roebling
5 // Copyright: 2000 (c) Robert Roebling
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
10 #pragma implementation "canvas.cpp"
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
20 #include "wx/canvas/canvas.h"
21 #include "wx/canvas/polygon.h"
22 #include "wx/canvas/liner.h"
26 #include <gdk/gdkrgb.h>
27 #include "wx/gtk/win_gtk.h"
30 #ifndef wxUSE_FREETYPE
31 #define wxUSE_FREETYPE 0
35 #include <freetype/freetype.h>
40 //----------------------------------------------------------------------------
42 //----------------------------------------------------------------------------
44 const double pi
= 3.1415926535;
47 FT_Library g_freetypeLibrary
;
50 //----------------------------------------------------------------------------
52 //----------------------------------------------------------------------------
54 wxCanvasObject::wxCanvasObject()
56 // the default event handler is just this object
63 m_dragmode
= DRAG_ONTOP
;
64 // handy when debugging
65 // m_dragmode = DRAG_RECTANGLE;
69 bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent
& event
)
71 return m_eventHandler
->ProcessEvent(event
);
74 void wxCanvasObject::PushEventHandler(wxEvtHandler
*handler
)
76 handler
->SetNextHandler(GetEventHandler());
77 m_eventHandler
=handler
;
80 wxEvtHandler
*wxCanvasObject::PopEventHandler(bool deleteHandler
)
82 wxEvtHandler
*handlerA
= m_eventHandler
;
85 wxEvtHandler
*handlerB
= handlerA
->GetNextHandler();
86 handlerA
->SetNextHandler((wxEvtHandler
*)NULL
);
87 m_eventHandler
=handlerB
;
91 handlerA
= (wxEvtHandler
*)NULL
;
98 void wxCanvasObject::AppendEventHandler(wxEvtHandler
*handler
)
100 GetEventHandler()->SetNextHandler(handler
);
103 wxEvtHandler
*wxCanvasObject::RemoveLastEventHandler(bool deleteHandler
)
105 //always the first in the row
106 wxEvtHandler
*handlerA
= m_eventHandler
;
107 wxEvtHandler
*handlerB
=handlerA
;
109 while ( handlerA
->GetNextHandler() )
112 handlerA
= handlerA
->GetNextHandler();
115 handlerB
->SetNextHandler((wxEvtHandler
*)NULL
);
121 return GetEventHandler();
124 wxRect
wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix
& cworld
)
127 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
;
153 tmparea
.height
= y2
-y1
;
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()
223 if (m_dragmode
== DRAG_RECTANGLE
)
225 this->SetVisible(FALSE
);
226 wxTransformMatrix help
;
227 double x
= GetXMin();
228 double y
= GetYMin();
229 double w
= m_bbox
.GetWidth();
230 double h
= m_bbox
.GetHeight();
231 m_admin
->Update( this, x
, y
, w
, h
);
232 m_admin
->UpdateNow();
234 wxRect recold
=GetAbsoluteArea(help
);
235 wxClientDC
dc(m_admin
->GetActive());
236 dc
.SetPen(*wxBLACK_PEN
);
237 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
238 dc
.SetLogicalFunction(wxINVERT
);
239 dc
.DrawRectangle(recold
);
240 dc
.SetBrush(wxNullBrush
);
241 dc
.SetPen(wxNullPen
);
245 this->SetVisible(FALSE
);
246 wxTransformMatrix help
;
247 double x
= GetXMin();
248 double y
= GetYMin();
249 double w
= m_bbox
.GetWidth();
250 double h
= m_bbox
.GetHeight();
252 wxRect recnew
=GetAbsoluteArea(help
);
254 //redraw in buffer what should be there without this object
255 m_admin
->Update( this, x
, y
, w
, h
);
256 m_admin
->GetActive()->Freeze();
258 //save the drawing (without the object itself to a bitmap)
259 m_atnewpos
= wxBitmap(recnew
.width
,recnew
.height
);
261 dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer());
263 tmp
.SelectObject(m_atnewpos
);
264 tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
);
265 tmp
.SelectObject(wxNullBitmap
);
266 dcm
.SelectObject(wxNullBitmap
);
272 void wxCanvasObject::DragRelative( double x
, double y
)
276 if (m_dragmode
== DRAG_RECTANGLE
)
278 wxTransformMatrix help
;
280 wxRect recold
=GetAbsoluteArea(help
);
284 wxRect recnew
=GetAbsoluteArea(help
);
286 wxClientDC
dc(m_admin
->GetActive());
287 dc
.SetPen(*wxBLACK_PEN
);
288 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
289 dc
.SetLogicalFunction(wxINVERT
);
290 dc
.DrawRectangle(recold
);
291 dc
.DrawRectangle(recnew
);
292 dc
.SetBrush(wxNullBrush
);
293 dc
.SetPen(wxNullPen
);
297 wxClientDC
dc(m_admin
->GetActive());
300 wxTransformMatrix help
;
301 wxRect recold
=GetAbsoluteArea(help
);
303 //restore what was there (without the object itself)
305 dcm
.SelectObject(*m_admin
->GetActive()->GetBuffer());
306 tmp
.SelectObject(m_atnewpos
);
307 dcm
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&tmp
,0,0,wxCOPY
,FALSE
);
311 wxRect recnew
=GetAbsoluteArea(help
);
313 //save the contents of the buffer at the new position
314 tmp
.Blit(0,0,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
);
315 tmp
.SelectObject(wxNullBitmap
);
317 //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew );
319 this->SetVisible(TRUE
);
320 //redraw object into the buffer
321 m_admin
->GetActive()->SetDC(&dcm
);
322 Render(&help
,recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
);
324 //draw the union or seperate to the canvas
325 double leftu
,rightu
,bottomu
,topu
;
326 leftu
= wxMin (recold
.x
, recnew
.x
) ;
327 rightu
= wxMax (recold
.x
+ recold
.width
, recnew
.x
+ recnew
.width
) ;
328 topu
= wxMin (recold
.y
, recnew
.y
) ;
329 bottomu
= wxMax (recold
.y
+ recold
.height
, recnew
.y
+ recnew
.height
) ;
331 if ( rightu
- leftu
< 2*recold
.width
&& bottomu
- topu
< 2*recold
.height
)
333 dc
.Blit(leftu
,topu
,rightu
- leftu
,bottomu
- topu
,&dcm
,leftu
,topu
,wxCOPY
,FALSE
);
338 //first redraw what should be at the old position in the canvas
339 dc
.Blit(recold
.x
,recold
.y
,recold
.width
,recold
.height
,&dcm
,recold
.x
,recold
.y
,wxCOPY
,FALSE
);
340 //blit the new position of the object to the canvas
341 dc
.Blit(recnew
.x
,recnew
.y
,recnew
.width
,recnew
.height
,&dcm
,recnew
.x
,recnew
.y
,wxCOPY
,FALSE
);
343 dcm
.SelectObject(wxNullBitmap
);
344 this->SetVisible(FALSE
);
350 void wxCanvasObject::DragEnd()
354 m_atnewpos
= wxBitmap(0,0);
355 m_admin
->GetActive()->Thaw();
356 this->SetVisible(TRUE
);
357 double x
= GetXMin();
358 double y
= GetYMin();
359 double w
= m_bbox
.GetWidth();
360 double h
= m_bbox
.GetHeight();
361 m_admin
->Update( this, x
, y
, w
, h
);
362 m_admin
->UpdateNow();
366 wxCanvasObject
* wxCanvasObject::IsHitWorld( double x
, double y
, double margin
)
368 if ((x
>= m_bbox
.GetMinX()-margin
) &&
369 (x
<= m_bbox
.GetMaxX()+margin
) &&
370 (y
>= m_bbox
.GetMinY()-margin
) &&
371 (y
<= m_bbox
.GetMaxY()+margin
))
376 return (wxCanvasObject
*) NULL
;
379 wxCanvasObject
* wxCanvasObject::Contains( wxCanvasObject
* obj
)
384 return (wxCanvasObject
*) NULL
;
387 void wxCanvasObject::CaptureMouse()
389 m_admin
->GetActive()->SetCaptureMouse( this );
392 void wxCanvasObject::ReleaseMouse()
394 m_admin
->GetActive()->SetCaptureMouse( NULL
);
397 bool wxCanvasObject::IsCapturedMouse()
399 return (m_admin
->GetActive()->GetCaptured() == this);
403 void wxCanvasObject::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
407 void wxCanvasObject::CalcBoundingBox()
411 void wxCanvasObject::WriteSVG( wxTextOutputStream
&stream
)
415 //----------------------------------------------------------------------------
416 // wxCanvasObjectGroup
417 //----------------------------------------------------------------------------
419 wxCanvasObjectGroup::wxCanvasObjectGroup(double x
, double y
)
421 lworld
.Translate(x
,y
);
422 //no objects make the bounding box the x,y and take care of it later
426 wxCanvasObjectGroup::~wxCanvasObjectGroup()
430 void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler
*handler
)
432 wxCanvasObject::PushEventHandler(handler
);
433 wxNode
*node
= m_objects
.First();
436 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
438 obj
->PushEventHandler(handler
);
444 wxEvtHandler
*wxCanvasObjectGroup::PopEventHandler(bool deleteHandler
)
446 wxNode
*node
= m_objects
.First();
449 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
451 obj
->PopEventHandler(deleteHandler
);
455 return wxCanvasObject::PopEventHandler(deleteHandler
);
458 void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler
*handler
)
460 wxCanvasObject::AppendEventHandler(handler
);
461 wxNode
*node
= m_objects
.First();
464 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
466 obj
->AppendEventHandler(handler
);
472 wxEvtHandler
*wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler
)
474 wxNode
*node
= m_objects
.First();
477 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
479 obj
->RemoveLastEventHandler(deleteHandler
);
483 return wxCanvasObject::RemoveLastEventHandler(deleteHandler
);
486 void wxCanvasObjectGroup::TransLate( double x
, double y
)
488 lworld
.Translate(x
,y
);
492 void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin
* admin
)
495 wxNode
*node
= m_objects
.First();
498 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
500 obj
->SetAdmin(admin
);
506 void wxCanvasObjectGroup::DeleteContents( bool flag
)
508 m_objects
.DeleteContents( flag
);
509 m_bbox
.SetValid(FALSE
);
513 void wxCanvasObjectGroup::Prepend( wxCanvasObject
* obj
)
515 m_objects
.Insert( obj
);
516 if (m_objects
.First())
518 m_bbox
.Expand(obj
->GetBbox());
522 m_bbox
.SetValid(FALSE
);
527 void wxCanvasObjectGroup::Append( wxCanvasObject
* obj
)
529 m_objects
.Append( obj
);
530 if (m_objects
.First())
532 m_bbox
.Expand(obj
->GetBbox());
536 m_bbox
.SetValid(FALSE
);
541 void wxCanvasObjectGroup::Insert( size_t before
, wxCanvasObject
* obj
)
543 m_objects
.Insert( before
, obj
);
544 m_bbox
.SetValid(FALSE
);
545 if (m_objects
.First())
547 m_bbox
.Expand(obj
->GetBbox());
551 m_bbox
.SetValid(FALSE
);
556 void wxCanvasObjectGroup::Remove( wxCanvasObject
* obj
)
558 m_objects
.DeleteObject( obj
);
559 m_bbox
.SetValid(FALSE
);
563 void wxCanvasObjectGroup::CalcBoundingBox()
565 m_bbox
.SetValid(FALSE
);
566 wxNode
*node
= m_objects
.First();
569 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
572 obj
->CalcBoundingBox();
577 m_bbox
.Expand( tmp
);
582 void wxCanvasObjectGroup::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height
)
584 if (!m_visible
) return;
586 wxTransformMatrix backup
= *cworld
;
589 wxNode
*node
= m_objects
.First();
595 wxRect absarea
=GetAbsoluteArea(*cworld
);
596 wxDC
*dc
= m_admin
->GetActive()->GetDC();
597 dc
->SetPen(*wxBLACK_PEN
);
598 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
599 dc
->DrawRectangle( absarea
.x
, absarea
.y
, absarea
.width
, absarea
.height
);
600 dc
->SetBrush(wxNullBrush
);
601 dc
->SetPen(wxNullPen
);
603 //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently
605 if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) &&
606 wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height )
612 // cycle through all objects
615 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
617 if (!obj
->IsControl() && obj
->GetVisible())
620 //get area at the absolute position
621 wxRect absareaobject
=obj
->GetAbsoluteArea(*cworld
);
623 // If we have 10.000 objects, we will go through
624 // this 10.000 times for each update, so we have
625 // to optimise carefully.
626 int clip_x
= absareaobject
.x
;
627 int clip_width
= absareaobject
.width
;
630 clip_width
-= x
-clip_x
;
635 if (clip_x
+ clip_width
> x
+ width
)
636 clip_width
= x
+width
-clip_x
;
640 int clip_y
= absareaobject
.y
;
641 int clip_height
= absareaobject
.height
;
644 clip_height
-= y
-clip_y
;
649 if (clip_y
+ clip_height
> y
+ height
)
650 clip_height
= y
+height
-clip_y
;
654 obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height
);
666 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream
&stream
)
670 wxCanvasObject
* wxCanvasObjectGroup::IsHitWorld( double x
, double y
, double margin
)
672 //KKKfirst check if within bbox
673 //will only work if they are always uptodate
674 //if (!m_bbox.PointInBox(x,y,margin))
675 // return (wxCanvasObject*) NULL;
677 wxTransformMatrix inverse
= lworld
;
680 inverse
.TransformPoint(x
,y
,xh
,yh
);
682 wxCanvasObject
*obj
=0;
683 wxNode
*node
= m_objects
.Last();
686 obj
=(wxCanvasObject
*) node
->Data();
688 if (!obj
->IsControl() )
690 if (obj
->IsHitWorld(x
,y
,margin
))
695 node
= node
->Previous();
698 return (wxCanvasObject
*) NULL
;
701 wxCanvasObject
* wxCanvasObjectGroup::Contains( wxCanvasObject
* obj
)
703 wxCanvasObject
* cobj
;
704 wxNode
*node
= m_objects
.First();
707 cobj
=(wxCanvasObject
*) node
->Data();
709 if (cobj
->Contains(obj
))
716 return (wxCanvasObject
*) NULL
;
719 int wxCanvasObjectGroup::IndexOf( wxCanvasObject
* obj
)
721 return m_objects
.IndexOf( obj
);
724 //----------------------------------------------------------------------------
726 //----------------------------------------------------------------------------
728 wxCanvasObjectRef::wxCanvasObjectRef(double x
, double y
, wxCanvasObject
* obj
)
731 lworld
.Translate(x
,y
);
734 m_bbox
.SetValid(FALSE
);
738 m_bbox
.Expand( tmp
);
741 void wxCanvasObjectRef::PushEventHandler(wxEvtHandler
*handler
)
743 wxCanvasObject::PushEventHandler(handler
);
744 m_obj
->PushEventHandler(handler
);
747 wxEvtHandler
*wxCanvasObjectRef::PopEventHandler(bool deleteHandler
)
749 m_obj
->PopEventHandler(deleteHandler
);
750 return wxCanvasObject::PopEventHandler(deleteHandler
);
753 void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler
*handler
)
755 wxCanvasObject::AppendEventHandler(handler
);
756 m_obj
->AppendEventHandler(handler
);
759 wxEvtHandler
*wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler
)
761 m_obj
->RemoveLastEventHandler(deleteHandler
);
762 return wxCanvasObject::RemoveLastEventHandler(deleteHandler
);
765 void wxCanvasObjectRef::TransLate( double x
, double y
)
767 lworld
.Translate(x
,y
);
771 wxCanvasObject
* wxCanvasObjectRef::Contains( wxCanvasObject
* obj
)
773 if (obj
== this || m_obj
->Contains(obj
))
776 return (wxCanvasObject
*) NULL
;
780 void wxCanvasObjectRef::SetRotation(double rotation
)
782 lworld
.SetRotation(rotation
);
786 void wxCanvasObjectRef::SetScale(double scalex
,double scaley
)
788 lworld
.Scale(scalex
,scaley
,lworld
.GetValue(2,0),lworld
.GetValue(2,1));
792 void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin
* admin
)
795 m_obj
->SetAdmin(admin
);
798 void wxCanvasObjectRef::CalcBoundingBox()
800 m_bbox
.SetValid(FALSE
);
801 m_obj
->CalcBoundingBox();
804 tmp
=m_obj
->GetBbox();
806 m_bbox
.Expand( tmp
);
809 void wxCanvasObjectRef::Render(wxTransformMatrix
* cworld
, int x
, int y
, int width
, int height
)
811 if (!m_visible
) return;
813 //get the absolute area (without the local matrix included)
814 //the boundingbox is relative to the parent.
815 wxRect absarea
=GetAbsoluteArea(*cworld
);
817 wxTransformMatrix backup
= *cworld
;
821 wxDC
*dc
= m_admin
->GetActive()->GetDC();
822 dc
->SetPen(*wxBLACK_PEN
);
823 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
824 dc
->DrawRectangle( absarea
.x
, absarea
.y
, absarea
.width
, absarea
.height
);
825 dc
->SetBrush(wxNullBrush
);
826 dc
->SetPen(wxNullPen
);
829 int clip_x
= absarea
.x
;
830 int clip_width
= absarea
.width
;
833 clip_width
-= x
-clip_x
;
838 if (clip_x
+ clip_width
> x
+ width
)
839 clip_width
= x
+width
-clip_x
;
843 int clip_y
= absarea
.y
;
844 int clip_height
= absarea
.height
;
847 clip_height
-= y
-clip_y
;
852 if (clip_y
+ clip_height
> y
+ height
)
853 clip_height
= y
+height
-clip_y
;
856 m_obj
->Render(cworld
, clip_x
, clip_y
, clip_width
, clip_height
);
864 void wxCanvasObjectRef::WriteSVG( wxTextOutputStream
&stream
)
868 wxCanvasObject
* wxCanvasObjectRef::IsHitWorld( double x
, double y
, double margin
)
870 //KKKfirst check if within bbox
871 //will only work if they are always uptodate
872 //if (!m_bbox.PointInBox(x,y,margin))
873 // return (wxCanvasObject*) NULL;
875 wxTransformMatrix inverse
= lworld
;
878 inverse
.TransformPoint(x
,y
,xh
,yh
);
880 if (m_obj
->IsHitWorld(xh
,yh
,margin
))
883 return (wxCanvasObject
*) NULL
;
888 //----------------------------------------------------------------------------
890 //----------------------------------------------------------------------------
892 wxCanvasRect::wxCanvasRect( double x
, double y
, double w
, double h
, double radius
)
901 m_brush
= *wxBLACK_BRUSH
;
902 m_pen
= *wxTRANSPARENT_PEN
;
906 void wxCanvasRect::TransLate( double x
, double y
)
913 void wxCanvasRect::CalcBoundingBox()
915 m_bbox
.SetMin( m_x
, m_y
);
916 m_bbox
.SetMax( m_x
+ m_width
,m_y
+ m_height
);
918 //include the pen width also
919 //KKK m_bbox.EnLarge(m_pen.GetWidth()+m_radius);
920 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
923 void wxCanvasRect::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
925 if (!m_visible
) return;
928 wxImage
*image
= m_admin
->GetActive()->GetBuffer();
930 int start_y
= clip_y
;
931 int end_y
= clip_y
+clip_height
;
933 int start_x
= clip_x
;
934 int end_x
= clip_x
+clip_width
;
937 for (int y
= start_y
; y
< end_y
; y
++)
938 for (int x
= start_x
; x
< end_x
; x
++)
940 int red
=m_brush
.GetColour().Red();
941 int green
=m_brush
.GetColour().Green();
942 int blue
=m_brush
.GetColour().Blue();
943 image
->SetRGB( x
, y
, red
, green
, blue
);
946 if (cworld
->GetRotation())
948 wxPoint
*cpoints
= new wxPoint
[4];
951 cworld
->TransformPoint( m_x
, m_y
, x
, y
);
952 cpoints
[0].x
= m_admin
->LogicalToDeviceX(x
);
953 cpoints
[0].y
= m_admin
->LogicalToDeviceY(y
);
954 cworld
->TransformPoint( m_x
, m_y
+ m_height
, x
, y
);
955 cpoints
[1].x
= m_admin
->LogicalToDeviceX(x
);
956 cpoints
[1].y
= m_admin
->LogicalToDeviceY(y
);
957 cworld
->TransformPoint( m_x
+ m_width
, m_y
+ m_height
, x
, y
);
958 cpoints
[2].x
= m_admin
->LogicalToDeviceX(x
);
959 cpoints
[2].y
= m_admin
->LogicalToDeviceY(y
);
960 cworld
->TransformPoint( m_x
+ m_width
, m_y
, x
, y
);
961 cpoints
[3].x
= m_admin
->LogicalToDeviceX(x
);
962 cpoints
[3].y
= m_admin
->LogicalToDeviceY(y
);
964 wxDC
*dc
= m_admin
->GetActive()->GetDC();
965 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
966 dc
->SetBrush(m_brush
);
967 int pw
=m_pen
.GetWidth();
968 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
970 dc
->DrawPolygon(4, cpoints
, 0,0,wxWINDING_RULE
);
972 dc
->SetBrush(wxNullBrush
);
973 dc
->SetPen(wxNullPen
);
974 dc
->DestroyClippingRegion();
979 wxDC
*dc
= m_admin
->GetActive()->GetDC();
980 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
981 dc
->SetBrush(m_brush
);
982 int pw
=m_pen
.GetWidth();
983 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
985 //yes the whole not only the clipping region, because we have a pen also
986 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
987 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
988 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
989 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
990 int r
= m_admin
->LogicalToDeviceYRel( m_radius
);
991 if (w
> 0 && w
< 1) w
=1;
992 if (w
< 0 && w
> -1) w
=-1;
993 if (h
> 0 && h
< 1) h
=1;
994 if (h
< 0 && h
> -1) h
=-1;
996 dc
->DrawRoundedRectangle( x
,y
,w
,h
,r
);
998 dc
->DrawRectangle( x
,y
,w
,h
);
999 dc
->SetBrush(wxNullBrush
);
1000 dc
->SetPen(wxNullPen
);
1001 dc
->DestroyClippingRegion();
1007 void wxCanvasRect::WriteSVG( wxTextOutputStream
&stream
)
1011 //----------------------------------------------------------------------------
1013 //----------------------------------------------------------------------------
1015 wxCanvasCircle::wxCanvasCircle( double x
, double y
, double radius
)
1022 m_brush
= *wxBLACK_BRUSH
;
1023 m_pen
= *wxTRANSPARENT_PEN
;
1027 void wxCanvasCircle::TransLate( double x
, double y
)
1034 void wxCanvasCircle::CalcBoundingBox()
1036 m_bbox
.SetMin( m_x
-m_radius
, m_y
-m_radius
);
1037 m_bbox
.SetMax( m_x
+m_radius
, m_y
+m_radius
);
1039 //include the pen width also
1040 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1043 void wxCanvasCircle::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1045 if (!m_visible
) return;
1049 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1050 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1051 dc
->SetBrush(m_brush
);
1052 int pw
=m_pen
.GetWidth();
1053 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1055 //yes the whole not only the clipping region, because we have a pen also
1056 //and rotation on a circle is not important so only a shift with cworld
1057 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1058 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1059 int radius
= m_admin
->LogicalToDeviceXRel( m_radius
);
1060 if (radius
< 1) radius
=1;
1061 dc
->DrawCircle( x
,y
,radius
);
1062 dc
->SetBrush(wxNullBrush
);
1063 dc
->SetPen(wxNullPen
);
1064 dc
->DestroyClippingRegion();
1069 void wxCanvasCircle::WriteSVG( wxTextOutputStream
&stream
)
1073 wxCanvasObject
* wxCanvasCircle::IsHitWorld( double x
, double y
, double margin
)
1075 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1076 (x
<= m_bbox
.GetMaxX()+margin
) &&
1077 (y
>= m_bbox
.GetMinY()-margin
) &&
1078 (y
<= m_bbox
.GetMaxY()+margin
)
1081 if (m_radius
+m_pen
.GetWidth()/2+margin
> sqrt(pow(m_x
-x
,2)+pow(m_y
-y
,2)))
1084 return (wxCanvasObject
*) NULL
;
1086 return (wxCanvasObject
*) NULL
;
1089 //----------------------------------------------------------------------------
1091 //----------------------------------------------------------------------------
1093 wxCanvasEllipse::wxCanvasEllipse( double x
, double y
, double width
, double height
)
1101 m_brush
= *wxBLACK_BRUSH
;
1102 m_pen
= *wxTRANSPARENT_PEN
;
1106 void wxCanvasEllipse::TransLate( double x
, double y
)
1113 void wxCanvasEllipse::CalcBoundingBox()
1115 m_bbox
.SetMin( m_x
, m_y
);
1116 m_bbox
.SetMax( m_x
+m_width
, m_y
+m_height
);
1118 //include the pen width also
1119 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1122 void wxCanvasEllipse::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1124 if (!m_visible
) return;
1128 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1129 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1130 dc
->SetBrush(m_brush
);
1131 int pw
=m_pen
.GetWidth();
1132 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1134 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1135 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1136 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1137 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1138 if (w
> 0 && w
< 1) w
=1;
1139 if (w
< 0 && w
> -1) w
=-1;
1140 if (h
> 0 && h
< 1) h
=1;
1141 if (h
< 0 && h
> -1) h
=-1;
1142 dc
->DrawEllipse( x
,y
,w
,h
);
1143 dc
->SetBrush(wxNullBrush
);
1144 dc
->SetPen(wxNullPen
);
1145 dc
->DestroyClippingRegion();
1150 void wxCanvasEllipse::WriteSVG( wxTextOutputStream
&stream
)
1154 wxCanvasObject
* wxCanvasEllipse::IsHitWorld( double x
, double y
, double margin
)
1156 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1157 (x
<= m_bbox
.GetMaxX()+margin
) &&
1158 (y
>= m_bbox
.GetMinY()-margin
) &&
1159 (y
<= m_bbox
.GetMaxY()+margin
)
1162 double a
=(m_width
+m_pen
.GetWidth())/2+margin
;
1163 double b
=(m_height
+m_pen
.GetWidth())/2+margin
;
1164 double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2);
1168 return (wxCanvasObject
*) NULL
;
1170 return (wxCanvasObject
*) NULL
;
1173 //----------------------------------------------------------------------------
1174 // wxCanvasEllipticArc
1175 //----------------------------------------------------------------------------
1177 wxCanvasEllipticArc::wxCanvasEllipticArc( double x
, double y
, double width
, double height
, double start
, double end
)
1187 m_brush
= *wxBLACK_BRUSH
;
1188 m_pen
= *wxTRANSPARENT_PEN
;
1192 void wxCanvasEllipticArc::TransLate( double x
, double y
)
1199 void wxCanvasEllipticArc::CalcBoundingBox()
1201 m_bbox
.SetMin( m_x
, m_y
);
1202 m_bbox
.SetMax( m_x
+m_width
, m_y
+m_height
);
1204 //include the pen width also
1205 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1208 void wxCanvasEllipticArc::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1210 if (!m_visible
) return;
1214 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1215 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1216 dc
->SetBrush(m_brush
);
1217 int pw
=m_pen
.GetWidth();
1218 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1220 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1221 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1222 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1223 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1224 if (w
> 0 && w
< 1) w
=1;
1225 if (w
< 0 && w
> -1) w
=-1;
1226 if (h
> 0 && h
< 1) h
=1;
1227 if (h
< 0 && h
> -1) h
=-1;
1228 if (m_admin
->GetActive()->GetYaxis())
1229 dc
->DrawEllipticArc( x
,y
,w
,h
,-m_end
,-m_start
);
1231 dc
->DrawEllipticArc( x
,y
,w
,h
,m_start
,m_end
);
1232 dc
->SetBrush(wxNullBrush
);
1233 dc
->SetPen(wxNullPen
);
1234 dc
->DestroyClippingRegion();
1239 void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream
&stream
)
1243 wxCanvasObject
* wxCanvasEllipticArc::IsHitWorld( double x
, double y
, double margin
)
1245 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1246 (x
<= m_bbox
.GetMaxX()+margin
) &&
1247 (y
>= m_bbox
.GetMinY()-margin
) &&
1248 (y
<= m_bbox
.GetMaxY()+margin
)
1251 double a
=(m_width
+m_pen
.GetWidth())/2+margin
;
1252 double b
=(m_height
+m_pen
.GetWidth())/2+margin
;
1253 double c
=pow((m_x
+m_width
/2-x
)/a
,2)+pow((m_y
+m_height
/2-y
)/b
,2);
1257 return (wxCanvasObject
*) NULL
;
1259 return (wxCanvasObject
*) NULL
;
1262 //----------------------------------------------------------------------------
1264 //----------------------------------------------------------------------------
1266 wxCanvasLine::wxCanvasLine( double x1
, double y1
, double x2
, double y2
)
1274 m_pen
= *wxBLACK_PEN
;
1278 void wxCanvasLine::TransLate( double x
, double y
)
1287 void wxCanvasLine::CalcBoundingBox()
1289 m_bbox
.SetMin( m_x1
, m_y1
);
1290 m_bbox
.SetMax( m_x2
, m_y2
);
1292 //include the pen width also
1293 m_bbox
.EnLarge(m_pen
.GetWidth()/2);
1296 void wxCanvasLine::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1298 if (!m_visible
) return;
1301 cworld
->TransformPoint( m_x1
, m_y1
, x1
, y1
);
1302 cworld
->TransformPoint( m_x2
, m_y2
, x2
, y2
);
1303 x1
= m_admin
->LogicalToDeviceX( x1
);
1304 y1
= m_admin
->LogicalToDeviceY( y1
);
1305 x2
= m_admin
->LogicalToDeviceX( x2
);
1306 y2
= m_admin
->LogicalToDeviceY( y2
);
1310 tmparea
.x
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX());
1311 tmparea
.y
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY());
1312 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1313 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1314 wxImage
*image
= m_admin
->GetActive()->GetBuffer();
1315 if ((tmparea
.width
== 0) && (tmparea
.height
== 0))
1317 int red
=m_pen
.GetColour().Red();
1318 int green
=m_pen
.GetColour().Green();
1319 int blue
=m_pen
.GetColour().Blue();
1320 image
->SetRGB( tmparea
.x
, tmparea
.y
, red
, green
, blue
);
1324 int red
=m_pen
.GetColour().Red();
1325 int green
=m_pen
.GetColour().Green();
1326 int blue
=m_pen
.GetColour().Blue();
1327 wxInt32 d
, ii
, jj
, di
, ai
, si
, dj
, aj
, sj
;
1330 si
= (di
< 0)? -1 : 1;
1333 sj
= (dj
< 0)? -1 : 1;
1345 if ((ii
>= clip_x
) && (ii
< clip_x
+clip_width
) &&
1346 (jj
>= clip_y
) && (jj
< clip_y
+clip_height
))
1348 image
->SetRGB( ii
, jj
, red
, blue
, green
);
1366 if ((ii
>= clip_x
) && (ii
< clip_x
+clip_width
) &&
1367 (jj
>= clip_y
) && (jj
< clip_y
+clip_height
))
1369 image
->SetRGB( ii
, jj
, red
, blue
, green
);
1382 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1383 dc
->SetClippingRegion( clip_x
, clip_y
, clip_width
, clip_height
);
1384 int pw
=m_pen
.GetWidth();
1385 m_pen
.SetWidth(m_admin
->LogicalToDeviceXRel(pw
));
1386 dc
->SetPen( m_pen
);
1387 dc
->DrawLine( x1
, y1
, x2
, y2
);
1389 dc
->DestroyClippingRegion();
1394 void wxCanvasLine::WriteSVG( wxTextOutputStream
&stream
)
1399 wxCanvasObject
* wxCanvasLine::IsHitWorld( double x
, double y
, double margin
)
1401 if ((x
>= m_bbox
.GetMinX()-margin
) &&
1402 (x
<= m_bbox
.GetMaxX()+margin
) &&
1403 (y
>= m_bbox
.GetMinY()-margin
) &&
1404 (y
<= m_bbox
.GetMaxY()+margin
)
1407 wxLine
line1(m_x1
,m_y1
,m_x2
,m_y2
);
1408 wxPoint2DDouble P
=wxPoint2DDouble(x
,y
);
1410 if (line1
.PointInLine(P
,distance
,m_pen
.GetWidth()/2+margin
) == R_IN_AREA
)
1413 return (wxCanvasObject
*) NULL
;
1415 return (wxCanvasObject
*) NULL
;
1418 //----------------------------------------------------------------------------
1420 //----------------------------------------------------------------------------
1422 wxCanvasImage::wxCanvasImage( const wxImage
&image
, double x
, double y
, double w
, double h
)
1432 m_orgw
= m_image
.GetWidth();
1433 m_orgh
= m_image
.GetHeight();
1439 void wxCanvasImage::TransLate( double x
, double y
)
1446 void wxCanvasImage::CalcBoundingBox()
1448 m_bbox
.SetMin( m_x
, m_y
);
1449 m_bbox
.SetMax( m_x
+ m_width
, m_y
+ m_height
);
1452 void wxCanvasImage::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1454 if (!m_visible
) return;
1458 tmparea
.x
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetMinX());
1459 tmparea
.y
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetMinY());
1460 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1461 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1465 cworld
->TransformPoint( m_x
, m_y
, x
, y
);
1466 x
= m_admin
->LogicalToDeviceX(x
);
1467 y
= m_admin
->LogicalToDeviceY(y
);
1471 if ((clip_x
== xabs
+ tmparea
.x
) &&
1472 (clip_y
== yabs
+ tmparea
.y
) &&
1473 (clip_width
== tmparea
.width
) &&
1474 (clip_height
== tmparea
.height
))
1476 m_admin
->GetActive()->GetBuffer()->Paste( m_tmp
, clip_x
, clip_y
);
1480 // local coordinates
1481 int start_x
= clip_x
- (xabs
+ tmparea
.x
);
1482 int start_y
= clip_y
- (yabs
+ tmparea
.y
);
1484 wxRect
rect( start_x
, start_y
, clip_width
, clip_height
);
1485 wxImage
sub_image( m_tmp
.GetSubImage( rect
) );
1486 m_admin
->GetActive()->GetBuffer()->Paste( sub_image
, clip_x
, clip_y
);
1489 if ( m_orgw
*5 < m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1490 m_orgw
/5 > m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) ||
1491 m_orgh
*5 < m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) ||
1492 m_orgh
/5 > m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() )
1495 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1496 dc
->SetClippingRegion(clip_x
, clip_y
, clip_width
, clip_height
);
1497 dc
->SetBrush(*wxTRANSPARENT_BRUSH
);
1498 dc
->SetPen(*wxBLACK_PEN
);
1499 //yes the whole not only the clipping region, because we have a pen also
1500 int x
= m_admin
->LogicalToDeviceX(cworld
->GetValue(2,0) + m_x
);
1501 int y
= m_admin
->LogicalToDeviceY(cworld
->GetValue(2,1) + m_y
);
1502 int w
= m_admin
->LogicalToDeviceXRel( m_width
);
1503 int h
= m_admin
->LogicalToDeviceYRel( m_height
);
1506 dc
->DrawRectangle( x
,y
,w
,h
);
1507 dc
->SetBrush(wxNullBrush
);
1508 dc
->SetPen(wxNullPen
);
1509 dc
->DestroyClippingRegion();
1513 if ((m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() ) == m_image
.GetWidth()) &&
1514 (m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() ) == m_image
.GetHeight()))
1520 m_tmp
= m_image
.Scale( m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth()),
1521 m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight()) );
1525 // wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
1528 if (cworld
->GetRotation())
1530 bmp
=m_tmp
.Rotate(-cworld
->GetRotation()/180.0 * pi
,centr
, TRUE
, NULL
).ConvertToBitmap();
1534 bmp
= m_tmp
.ConvertToBitmap();
1537 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1540 if (cworld
->GetRotation()> 0)
1542 centr2
.x
= (int) (x
+m_height
*sin(-cworld
->GetRotation()/180.0 * pi
));
1548 centr2
.y
= (int) (y
-m_width
*sin(-cworld
->GetRotation()/180.0 * pi
));
1551 if (cworld
->GetRotation() != 0)
1553 //TODO clipping not right
1554 dc
->DrawBitmap(bmp
,centr2
,TRUE
);
1555 // dc->DrawPoint(centr2);
1556 // dc->DrawPoint(x,y);
1560 //TODO clipping not right
1561 // dc->DrawPoint(centr2);
1562 // dc->DrawPoint(x,y);
1564 if ((clip_x
== x
) &&
1566 (clip_width
== tmparea
.width
) &&
1567 (clip_height
== tmparea
.height
))
1569 dc
->DrawBitmap( m_tmp
, clip_x
, clip_y
, TRUE
);
1573 int start_x
= clip_x
- (int)x
;
1574 int start_y
= clip_y
- (int)y
;
1576 //dc->DrawBitmap( bmp, x, y, TRUE );
1578 dcm
.SelectObject(bmp
);
1579 dc
->Blit(clip_x
, clip_y
,clip_width
, clip_height
,&dcm
,start_x
,start_y
,wxCOPY
,TRUE
);
1580 dcm
.SelectObject(wxNullBitmap
);
1586 void wxCanvasImage::WriteSVG( wxTextOutputStream
&stream
)
1591 //----------------------------------------------------------------------------
1593 //----------------------------------------------------------------------------
1595 wxCanvasControl::wxCanvasControl( wxWindow
*control
)
1599 m_control
= control
;
1603 double wxCanvasControl::GetPosX()
1606 m_control
->GetPosition( &x
, &y
);
1607 return m_admin
->DeviceToLogicalX(x
);
1610 double wxCanvasControl::GetPosY()
1613 m_control
->GetPosition( &x
, &y
);
1614 return m_admin
->DeviceToLogicalY(y
);
1617 void wxCanvasControl::SetPosXY( double x
, double y
)
1619 int xd
= m_admin
->LogicalToDeviceX(x
);
1620 int yd
= m_admin
->LogicalToDeviceY(y
);
1621 m_control
->Move(xd
,yd
);
1625 void wxCanvasControl::TransLate( double x
, double y
)
1628 m_control
->GetPosition( &xdo
, &ydo
);
1629 int xd
= m_admin
->LogicalToDeviceX(x
)-xdo
;
1630 int yd
= m_admin
->LogicalToDeviceY(y
)-ydo
;
1631 m_control
->Move(xd
,yd
);
1635 wxCanvasControl::~wxCanvasControl()
1637 m_control
->Destroy();
1640 void wxCanvasControl::CalcBoundingBox()
1644 m_control
->GetSize( &tmparea
.width
, &tmparea
.height
);
1645 m_control
->GetPosition( &tmparea
.x
, &tmparea
.y
);
1647 m_bbox
.SetMin( tmparea
.x
, tmparea
.y
);
1648 m_bbox
.SetMax( tmparea
.x
+ tmparea
.width
, tmparea
.y
+ tmparea
.height
);
1652 void wxCanvasControl::MoveRelative( double x
, double y
)
1654 m_control
->Move( m_admin
->LogicalToDeviceX(x
), m_admin
->LogicalToDeviceX(y
) );
1657 //----------------------------------------------------------------------------
1659 //----------------------------------------------------------------------------
1671 wxCanvasText::wxCanvasText( const wxString
&text
, double x
, double y
, const wxString
&fontFile
, int size
)
1675 m_fontFileName
= fontFile
;
1688 wxFaceData
*data
= new wxFaceData
;
1691 int error
= FT_New_Face( g_freetypeLibrary
,
1696 error
= FT_Set_Char_Size( data
->m_face
,
1705 wxCanvasText::~wxCanvasText()
1708 wxFaceData
*data
= (wxFaceData
*) m_faceData
;
1712 if (m_alpha
) delete [] m_alpha
;
1715 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue
)
1722 void wxCanvasText::SetFlag( int flag
)
1727 void wxCanvasText::Render(wxTransformMatrix
* cworld
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
1729 if (!m_visible
) return;
1732 tmparea
.x
= m_admin
->LogicalToDeviceX( m_bbox
.GetMinX());
1733 tmparea
.y
= m_admin
->LogicalToDeviceY( m_bbox
.GetMinY());
1734 tmparea
.width
= m_admin
->LogicalToDeviceXRel( m_bbox
.GetWidth() );
1735 tmparea
.height
= m_admin
->LogicalToDeviceYRel( m_bbox
.GetHeight() );
1737 m_alpha
= new unsigned char[tmparea
.width
*tmparea
.height
];
1738 memset( m_alpha
, 0, tmparea
.width
*tmparea
.height
);
1740 if (!m_alpha
) return;
1743 FT_Face face
= ((wxFaceData
*)m_faceData
)->m_face
;
1744 FT_GlyphSlot slot
= face
->glyph
;
1748 for (int n
= 0; n
< (int)m_text
.Len(); n
++)
1750 FT_UInt index
= FT_Get_Char_Index( face
, m_text
[(unsigned int)n
] );
1752 int error
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT
);
1753 if (error
) continue;
1755 error
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal
);
1756 if (error
) continue;
1758 FT_Bitmap
*bitmap
= &slot
->bitmap
;
1759 unsigned char* buffer
= bitmap
->buffer
;
1760 for (int y
= 0; y
< bitmap
->rows
; y
++)
1761 for (int x
= 0; x
< bitmap
->width
; x
++)
1763 unsigned char alpha
= buffer
[ y
*bitmap
->pitch
+ x
];
1764 if (alpha
== 0) continue;
1766 int xx
= pen_x
+ slot
->bitmap_left
+ x
;
1767 int yy
= pen_y
- slot
->bitmap_top
+ y
;
1768 m_alpha
[ yy
* tmparea
.width
+ xx
] = alpha
;
1771 pen_x
+= slot
->advance
.x
>> 6;
1772 pen_y
+= slot
->advance
.y
>> 6;
1777 wxImage
*image
= m_admin
->GetActive()->GetBuffer();
1779 // local coordinates
1780 int start_x
= clip_x
- tmparea
.x
;
1781 int end_x
= clip_width
+ start_x
;
1782 int start_y
= clip_y
- tmparea
.y
;
1783 int end_y
= clip_height
+ start_y
;
1785 for (int y
= start_y
; y
< end_y
; y
++)
1786 for (int x
= start_x
; x
< end_x
; x
++)
1788 int alpha
= m_alpha
[y
*tmparea
.width
+ x
];
1791 int image_x
= tmparea
.x
+x
;
1792 int image_y
= tmparea
.y
+y
;
1795 image
->SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
1798 int red1
= (m_red
* alpha
) / 255;
1799 int green1
= (m_green
* alpha
) / 255;
1800 int blue1
= (m_blue
* alpha
) / 255;
1803 int red2
= image
->GetRed( image_x
, image_y
);
1804 int green2
= image
->GetGreen( image_x
, image_y
);
1805 int blue2
= image
->GetBlue( image_x
, image_y
);
1806 red2
= (red2
* alpha
) / 255;
1807 green2
= (green2
* alpha
) / 255;
1808 blue2
= (blue2
* alpha
) / 255;
1810 image
->SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
1814 wxBitmap
*bitmap
= m_admin
->GetActive()->GetBuffer();
1815 wxRect
sub_rect( clip_x
, clip_y
, clip_width
, clip_height
);
1816 wxBitmap
sub_bitmap( bitmap
->GetSubBitmap( sub_rect
) );
1818 wxImage
image( sub_bitmap
);
1820 // local coordinates
1821 int start_x
= clip_x
- tmparea
.x
;
1822 int end_x
= clip_width
+ start_x
;
1823 int start_y
= clip_y
- tmparea
.y
;
1824 int end_y
= clip_height
+ start_y
;
1826 for (int y
= start_y
; y
< end_y
; y
++)
1827 for (int x
= start_x
; x
< end_x
; x
++)
1829 int alpha
= m_alpha
[y
*tmparea
.width
+ x
];
1832 int image_x
= x
- start_x
;
1833 int image_y
= y
- start_y
;
1836 image
.SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
1839 int red1
= (m_red
* alpha
) / 255;
1840 int green1
= (m_green
* alpha
) / 255;
1841 int blue1
= (m_blue
* alpha
) / 255;
1844 int red2
= image
.GetRed( image_x
, image_y
);
1845 int green2
= image
.GetGreen( image_x
, image_y
);
1846 int blue2
= image
.GetBlue( image_x
, image_y
);
1847 red2
= (red2
* alpha
) / 255;
1848 green2
= (green2
* alpha
) / 255;
1849 blue2
= (blue2
* alpha
) / 255;
1851 image
.SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
1855 sub_bitmap
= image
.ConvertToBitmap();
1857 wxDC
*dc
= m_admin
->GetActive()->GetDC();
1858 dc
->DrawBitmap( sub_bitmap
, clip_x
, clip_y
);
1862 void wxCanvasText::WriteSVG( wxTextOutputStream
&stream
)
1866 void wxCanvasText::TransLate( double x
, double y
)
1873 void wxCanvasText::CalcBoundingBox()
1875 if (m_alpha
) delete [] m_alpha
;
1877 m_bbox
.SetMin( m_x
, m_y
);
1878 m_bbox
.SetMax( m_x
+ 100 , m_y
+ m_size
+ (m_size
/2));
1883 //----------------------------------------------------------------------------
1885 //----------------------------------------------------------------------------
1887 IMPLEMENT_CLASS(wxCanvas
,wxWindow
)
1889 BEGIN_EVENT_TABLE(wxCanvas
,wxWindow
)
1890 EVT_SCROLLWIN( wxCanvas::OnScroll
)
1891 EVT_CHAR( wxCanvas::OnChar
)
1892 EVT_PAINT( wxCanvas::OnPaint
)
1893 EVT_SIZE( wxCanvas::OnSize
)
1894 EVT_IDLE( wxCanvas::OnIdle
)
1895 EVT_MOUSE_EVENTS( wxCanvas::OnMouse
)
1896 EVT_SET_FOCUS( wxCanvas::OnSetFocus
)
1897 EVT_KILL_FOCUS( wxCanvas::OnKillFocus
)
1898 EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground
)
1901 wxCanvas::wxCanvas( wxCanvasAdmin
* admin
, wxWindow
*parent
, wxWindowID id
,
1902 const wxPoint
&position
, const wxSize
& size
, long style
) :
1903 wxWindow( parent
, id
, position
, size
, style
)
1906 m_admin
->Append(this);
1907 m_needUpdate
= FALSE
;
1908 m_background
= *wxWHITE
;
1909 m_lastMouse
= (wxCanvasObject
*)NULL
;
1910 m_captureMouse
= (wxCanvasObject
*)NULL
;
1919 wxCanvas::~wxCanvas()
1921 wxNode
*node
= m_updateRects
.First();
1924 wxRect
*rect
= (wxRect
*) node
->Data();
1926 m_updateRects
.DeleteNode( node
);
1927 node
= m_updateRects
.First();
1931 void wxCanvas::SetColour( const wxColour
& background
)
1933 m_background
=background
;
1934 SetBackgroundColour( m_background
);
1936 if (m_frozen
) return;
1939 unsigned char red
= background
.Red();
1940 unsigned char green
= background
.Green();
1941 unsigned char blue
= background
.Blue();
1943 unsigned char *data
= m_buffer
.GetData();
1945 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
1946 for (int x
= 0; x
< m_buffer
.GetWidth(); x
++)
1957 dc
.SelectObject( m_buffer
);
1958 dc
.SetPen( *wxTRANSPARENT_PEN
);
1959 wxBrush
brush( m_background
, wxSOLID
);
1960 dc
.SetBrush( brush
);
1961 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
1962 dc
.SelectObject( wxNullBitmap
);
1966 void wxCanvas::SetCaptureMouse( wxCanvasObject
*obj
)
1970 wxWindow::CaptureMouse();
1971 m_captureMouse
= obj
;
1975 wxWindow::ReleaseMouse();
1976 m_captureMouse
= NULL
;
1980 void wxCanvas::Freeze()
1985 void wxCanvas::Thaw()
1987 wxNode
*node
= m_updateRects
.First();
1990 wxRect
*rect
= (wxRect
*) node
->Data();
1992 m_updateRects
.DeleteNode( node
);
1993 node
= m_updateRects
.First();
1999 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
2002 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit
)
2004 m_admin
->SetActive(this);
2006 if (!m_root
) return;
2008 if (m_frozen
) return;
2016 if (width
<= 0) return;
2023 if (height
<= 0) return;
2025 if (x
+width
> m_buffer
.GetWidth())
2027 width
= m_buffer
.GetWidth() - x
;
2029 if (width
<= 0) return;
2031 if (y
+height
> m_buffer
.GetHeight())
2033 height
= m_buffer
.GetHeight() - y
;
2035 if (height
<= 0) return;
2037 // update is within the buffer
2038 m_needUpdate
= TRUE
;
2040 // has to be blitted to screen later
2043 m_updateRects
.Append(
2044 (wxObject
*) new wxRect( x
,y
,width
,height
) );
2047 wxTransformMatrix cworld
;
2050 // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
2052 int end_y
= y
+height
;
2054 int end_x
= x
+width
;
2055 int red
=m_background
.Red();
2056 int green
=m_background
.Green();
2057 int blue
=m_background
.Blue();
2058 for (int yy
= start_y
; yy
< end_y
; yy
++)
2059 for (int xx
= start_x
; xx
< end_x
; xx
++)
2060 m_buffer
.SetRGB( xx
, yy
, red
, green
, blue
);
2062 m_root
->Render(&cworld
, x
, y
, width
, height
);
2065 dc
.SelectObject( m_buffer
);
2067 dc
.SetPen( *wxTRANSPARENT_PEN
);
2068 wxBrush
brush( m_background
, wxSOLID
);
2069 dc
.SetBrush( brush
);
2071 if (width
!= m_buffer
.GetWidth() && height
!= m_buffer
.GetHeight())
2073 dc
.SetLogicalFunction(wxCOPY
);
2074 dc
.SetClippingRegion(x
,y
,width
,height
);
2075 dc
.DrawRectangle(x
-2,y
-2,width
+4,height
+4);
2076 dc
.DestroyClippingRegion();
2081 dc
.SetLogicalFunction(wxCOPY
);
2082 dc
.DrawRectangle(0,0,m_buffer
.GetWidth(),m_buffer
.GetHeight());
2084 dc
.SetBrush(wxNullBrush
);
2085 dc
.SetPen(wxNullPen
);
2089 m_root
->Render(&cworld
,x
, y
, width
, height
);
2092 dc
.SelectObject( wxNullBitmap
);
2096 void wxCanvas::BlitBuffer( wxDC
&dc
)
2098 wxNode
*node
= m_updateRects
.First();
2101 wxRect
*rect
= (wxRect
*) node
->Data();
2105 wxImage
sub_image( m_buffer
.GetSubImage( *rect
) );
2107 int bpp
= wxDisplayDepth();
2110 // the init code is doubled in wxImage
2111 static bool s_hasInitialized
= FALSE
;
2113 if (!s_hasInitialized
)
2116 s_hasInitialized
= TRUE
;
2119 gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow
)->bin_window
,
2120 m_wxwindow
->style
->black_gc
,
2121 sub_rect
.x
, sub_rect
.y
,
2122 sub_image
.GetWidth(), sub_image
.GetHeight(),
2123 GDK_RGB_DITHER_NONE
,
2124 sub_image
.GetData(),
2125 sub_image
.GetWidth()*3 );
2129 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
2130 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
2133 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
2134 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
2137 #else // IMAGE_CANVAS
2139 // Maybe clipping use SetClipping() is faster than
2140 // getting the subrect first and drawing it then?
2142 // wxBitmap sub_bitmap( m_buffer.GetSubBitmap( *rect ) );
2143 // dc.DrawBitmap( sub_bitmap, rect->x, rect->y );
2146 mdc
.SelectObject( m_buffer
);
2147 dc
.Blit (rect
->x
, rect
->y
, rect
->GetWidth(), rect
->GetHeight(),&mdc
, rect
->x
, rect
->y
);
2148 mdc
.SelectObject( wxNullBitmap
);
2152 m_updateRects
.DeleteNode( node
);
2153 node
= m_updateRects
.First();
2156 m_needUpdate
= FALSE
;
2159 void wxCanvas::UpdateNow()
2161 if (m_frozen
) return;
2163 if (!m_needUpdate
) return;
2165 wxClientDC
dc( this );
2171 void wxCanvas::OnPaint(wxPaintEvent
&event
)
2176 if (!m_buffer
.Ok()) return;
2178 if (m_frozen
) return;
2180 m_needUpdate
= TRUE
;
2182 wxRegionIterator
it( GetUpdateRegion() );
2188 int w
= it
.GetWidth();
2189 int h
= it
.GetHeight();
2191 if (x
+w
> m_buffer
.GetWidth())
2192 w
= m_buffer
.GetWidth() - x
;
2193 if (y
+h
> m_buffer
.GetHeight())
2194 h
= m_buffer
.GetHeight() - y
;
2196 if ((w
> 0) && (h
> 0))
2198 m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h
) );
2207 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
2209 // If any updates are pending, do them now since they will
2210 // expect the previous m_bufferX and m_bufferY as well as
2211 // the previous device origin values.
2212 wxClientDC
dc( this );
2213 dc
.SetDeviceOrigin( m_oldDeviceX
, m_oldDeviceY
);
2218 double dyv
=DeviceToLogicalYRel(dy
);
2219 m_virt_minY
=m_virt_minY
-dyv
;
2220 m_virt_maxY
=m_virt_maxY
-dyv
;
2224 double dxv
=DeviceToLogicalXRel(dx
);
2225 m_virt_minX
=m_virt_minX
-dxv
;
2226 m_virt_maxX
=m_virt_maxX
-dxv
;
2229 m_admin
->SetActive(this);
2230 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2233 unsigned char* data
= m_buffer
.GetData();
2239 unsigned char *source
= data
;
2240 unsigned char *dest
= data
+ (dy
* m_buffer
.GetWidth() * 3);
2241 size_t count
= (size_t) (m_buffer
.GetWidth() * 3 * (m_buffer
.GetHeight()-dy
));
2242 memmove( dest
, source
, count
);
2244 // We update the new buffer area, but there is no need to
2245 // blit (last param FALSE) since the ensuing paint event will
2247 Update( 0, 0, m_buffer
.GetWidth(), dy
, FALSE
);
2251 unsigned char *dest
= data
;
2252 unsigned char *source
= data
+ (-dy
* m_buffer
.GetWidth() * 3);
2253 size_t count
= (size_t) (m_buffer
.GetWidth() * 3 * (m_buffer
.GetHeight()+dy
));
2254 memmove( dest
, source
, count
);
2256 // We update the new buffer area, but there is no need to
2257 // blit (last param FALSE) since the ensuing paint event will
2259 Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), -dy
, FALSE
);
2267 unsigned char *source
= data
;
2268 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
2270 unsigned char *dest
= source
+ dx
*3;
2271 memmove( dest
, source
, (m_buffer
.GetWidth()-dx
) * 3 );
2272 source
+= m_buffer
.GetWidth()*3;
2275 // We update the new buffer area, but there is no need to
2276 // blit (last param FALSE) since the ensuing paint event will
2278 Update( 0,0, dx
, m_buffer
.GetHeight(), FALSE
);
2282 unsigned char *dest
= data
;
2283 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
2285 unsigned char *source
= dest
- dx
*3;
2286 memmove( dest
, source
, (m_buffer
.GetWidth()+dx
) * 3 );
2287 dest
+= m_buffer
.GetWidth()*3;
2290 // We update the new buffer area, but there is no need to
2291 // blit (last param FALSE) since the ensuing paint event will
2293 Update( m_buffer
.GetWidth()+dx
, 0, -dx
, m_buffer
.GetHeight(), FALSE
);
2300 if (dy
> 0 && dy
< m_buffer
.GetHeight())
2302 wxRect
rect( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight()-dy
);
2303 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2305 dcm
.SelectObject( m_buffer
);
2306 dcm
.DrawBitmap( sub_bitmap
, 0, dy
, TRUE
);
2307 dcm
.SelectObject( wxNullBitmap
);
2309 Update( 0, 0, m_buffer
.GetWidth(), dy
, TRUE
);
2311 else if (dy
< 0 && dy
> -m_buffer
.GetHeight())
2313 wxRect
rect( 0, -dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight()+dy
);
2314 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2316 dcm
.SelectObject( m_buffer
);
2317 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2318 dcm
.SelectObject( wxNullBitmap
);
2320 Update( 0, m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2323 Update( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2328 if (dx
> 0 && dx
< m_buffer
.GetWidth())
2330 wxRect
rect( 0, 0, m_buffer
.GetWidth()-dx
, m_buffer
.GetHeight());
2331 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2333 dcm
.SelectObject( m_buffer
);
2334 dcm
.DrawBitmap( sub_bitmap
, dx
, 0, TRUE
);
2335 dcm
.SelectObject( wxNullBitmap
);
2337 Update( 0, 0, dx
, m_buffer
.GetHeight(), TRUE
);
2339 else if (dx
< 0 && dx
> -m_buffer
.GetWidth())
2341 wxRect
rect( -dx
, 0, m_buffer
.GetWidth()+dx
, m_buffer
.GetHeight());
2342 wxBitmap
sub_bitmap( m_buffer
.GetSubBitmap( rect
) );
2344 dcm
.SelectObject( m_buffer
);
2345 dcm
.DrawBitmap( sub_bitmap
, 0, 0, TRUE
);
2346 dcm
.SelectObject( wxNullBitmap
);
2348 Update( m_buffer
.GetWidth()+dx
, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2351 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), TRUE
);
2354 wxWindow::ScrollWindow( dx
, dy
, rect
);
2356 //must be done now because quick repeated scrolling will prevent wxPaint
2357 //from doing it properly
2361 void wxCanvas::OnMouse(wxMouseEvent
&event
)
2363 m_admin
->SetActive(this);
2370 int x
= event
.GetX();
2371 int y
= event
.GetY();
2373 //to world coordinates to do hit test in world coordinates
2374 double xw
= DeviceToLogicalX( x
);
2375 double yw
= DeviceToLogicalY( y
);
2377 //make a select margin of 2 pixels, so also zero line thickness will be hit
2378 double margin
= DeviceToLogicalXRel( 2 );
2380 if (event
.GetEventType() == wxEVT_MOTION
)
2382 if (m_captureMouse
) //no matter what go to this one
2384 wxMouseEvent
child_event( wxEVT_MOTION
);
2385 child_event
.SetEventObject(m_captureMouse
);
2386 child_event
.m_x
= x
;
2387 child_event
.m_y
= y
;
2388 child_event
.m_leftDown
= event
.m_leftDown
;
2389 child_event
.m_rightDown
= event
.m_rightDown
;
2390 child_event
.m_middleDown
= event
.m_middleDown
;
2391 child_event
.m_controlDown
= event
.m_controlDown
;
2392 child_event
.m_shiftDown
= event
.m_shiftDown
;
2393 child_event
.m_altDown
= event
.m_altDown
;
2394 child_event
.m_metaDown
= event
.m_metaDown
;
2396 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2401 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2403 if (obj
&& !obj
->IsControl())
2405 wxMouseEvent
child_event( wxEVT_MOTION
);
2406 child_event
.SetEventObject( obj
);
2407 child_event
.m_x
= x
;
2408 child_event
.m_y
= y
;
2409 child_event
.m_leftDown
= event
.m_leftDown
;
2410 child_event
.m_rightDown
= event
.m_rightDown
;
2411 child_event
.m_middleDown
= event
.m_middleDown
;
2412 child_event
.m_controlDown
= event
.m_controlDown
;
2413 child_event
.m_shiftDown
= event
.m_shiftDown
;
2414 child_event
.m_altDown
= event
.m_altDown
;
2415 child_event
.m_metaDown
= event
.m_metaDown
;
2417 if ((obj
!= m_lastMouse
) && (m_lastMouse
!= NULL
))
2419 child_event
.SetEventType( wxEVT_LEAVE_WINDOW
);
2420 child_event
.SetEventObject( m_lastMouse
);
2421 child_event
.m_x
= x
;
2422 child_event
.m_y
= y
;
2423 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2426 child_event
.SetEventType( wxEVT_ENTER_WINDOW
);
2427 child_event
.SetEventObject( m_lastMouse
);
2428 child_event
.m_x
= x
;
2429 child_event
.m_y
= y
;
2430 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2432 child_event
.SetEventType( wxEVT_MOTION
);
2433 child_event
.SetEventObject( obj
);
2436 obj
->ProcessCanvasObjectEvent( child_event
);
2442 wxMouseEvent
child_event( wxEVT_LEAVE_WINDOW
);
2443 child_event
.SetEventObject( m_lastMouse
);
2444 child_event
.m_x
= x
;
2445 child_event
.m_y
= y
;
2446 child_event
.m_leftDown
= event
.m_leftDown
;
2447 child_event
.m_rightDown
= event
.m_rightDown
;
2448 child_event
.m_middleDown
= event
.m_middleDown
;
2449 child_event
.m_controlDown
= event
.m_controlDown
;
2450 child_event
.m_shiftDown
= event
.m_shiftDown
;
2451 child_event
.m_altDown
= event
.m_altDown
;
2452 child_event
.m_metaDown
= event
.m_metaDown
;
2453 m_lastMouse
->ProcessCanvasObjectEvent( child_event
);
2455 m_lastMouse
= (wxCanvasObject
*) NULL
;
2461 if (m_captureMouse
) //no matter what go to this one
2463 wxMouseEvent
child_event( event
.GetEventType() );
2464 child_event
.SetEventObject(m_captureMouse
);
2465 child_event
.m_x
= x
;
2466 child_event
.m_y
= y
;
2467 child_event
.m_leftDown
= event
.m_leftDown
;
2468 child_event
.m_rightDown
= event
.m_rightDown
;
2469 child_event
.m_middleDown
= event
.m_middleDown
;
2470 child_event
.m_controlDown
= event
.m_controlDown
;
2471 child_event
.m_shiftDown
= event
.m_shiftDown
;
2472 child_event
.m_altDown
= event
.m_altDown
;
2473 child_event
.m_metaDown
= event
.m_metaDown
;
2474 m_captureMouse
->ProcessCanvasObjectEvent( child_event
);
2478 wxCanvasObject
*obj
= m_root
->IsHitWorld(xw
,yw
,margin
);
2480 if (obj
&& !obj
->IsControl())
2482 wxMouseEvent
child_event( event
.GetEventType() );
2483 child_event
.SetEventObject( obj
);
2484 child_event
.m_x
= x
;
2485 child_event
.m_y
= y
;
2486 child_event
.m_leftDown
= event
.m_leftDown
;
2487 child_event
.m_rightDown
= event
.m_rightDown
;
2488 child_event
.m_middleDown
= event
.m_middleDown
;
2489 child_event
.m_controlDown
= event
.m_controlDown
;
2490 child_event
.m_shiftDown
= event
.m_shiftDown
;
2491 child_event
.m_altDown
= event
.m_altDown
;
2492 child_event
.m_metaDown
= event
.m_metaDown
;
2494 obj
->ProcessCanvasObjectEvent( child_event
);
2503 void wxCanvas::OnSize(wxSizeEvent
&event
)
2507 GetClientSize( &w
, &h
);
2510 m_buffer
= wxImage( w
, h
);
2513 m_buffer
= wxBitmap( w
, h
);
2514 dc
.SelectObject( m_buffer
);
2515 dc
.SetPen( *wxTRANSPARENT_PEN
);
2516 wxBrush
brush( m_background
, wxSOLID
);
2517 dc
.SetBrush( brush
);
2518 dc
.DrawRectangle( 0, 0, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
2519 dc
.SelectObject( wxNullBitmap
);
2523 wxNode
*node
= m_updateRects
.First();
2526 wxRect
*rect
= (wxRect
*) node
->Data();
2528 m_updateRects
.DeleteNode( node
);
2529 node
= m_updateRects
.First();
2534 m_admin
->SetActive(this);
2535 SetMappingScroll(m_virt_minX
,m_virt_minY
,m_virt_maxX
,m_virt_maxY
,FALSE
);
2537 Update( 0,0, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
2542 void wxCanvas::OnIdle(wxIdleEvent
&event
)
2544 m_admin
->SetActive(this);
2549 void wxCanvas::OnSetFocus(wxFocusEvent
&event
)
2551 m_admin
->SetActive(this);
2554 void wxCanvas::OnKillFocus(wxFocusEvent
&event
)
2559 void wxCanvas::OnEraseBackground(wxEraseEvent
&event
)
2565 // maps the virtual window (Real drawing to the window coordinates
2566 // also used for zooming
2567 void wxCanvas::SetMappingScroll( double vx1
, double vy1
, double vx2
, double vy2
, bool border
)
2570 GetClientSize(&dwxi
,&dwyi
);
2572 if (vx2
==vx1
) vx2
=vx1
+100000;
2573 if (vy2
==vy1
) vy2
=vy1
+100000;
2584 double dvx
= m_virt_maxX
- m_virt_minX
;
2585 double dvy
= m_virt_maxY
- m_virt_minY
;
2587 // calculate the scaling factor for the virtual window
2590 if ((dvy
/ dvx
) < (dwy
/ dwx
))
2592 dvy
= dvx
* (dwy
/ dwx
);
2593 // calculate the change in the coordinates
2594 temp_y
= (dvy
- (m_virt_maxY
- m_virt_minY
) )/ 2.0;
2598 dvx
= dvy
* (dwx
/ dwy
);
2599 // calculate the change in the coordinates
2600 temp_x
= (dvx
- (m_virt_maxX
- m_virt_minX
) )/ 2.0;
2603 // add or substract the change from the original coordinates
2604 m_virt_minX
=m_virt_minX
-temp_x
;
2605 m_virt_minY
=m_virt_minY
-temp_y
;
2607 m_virt_maxX
=m_virt_maxX
+temp_x
;
2608 m_virt_maxY
=m_virt_maxY
+temp_y
;
2610 // initialize the mapping_matrix used for mapping the
2611 // virtual windows to the drawing window
2613 // make mappingmatrix
2614 m_mapping_matrix
.Identity();
2617 // translate the drawing to 0,0
2619 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2621 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2625 // make a small white border around the drawing
2626 m_virt_minX
=m_virt_minX
- 0.05 * dvx
;
2627 m_virt_minY
=m_virt_minY
- 0.05 * dvy
;
2629 m_virt_maxX
=m_virt_maxX
+ 0.05 * dvx
;
2630 m_virt_maxY
=m_virt_maxY
+ 0.05 * dvy
;
2632 // translate the drawing to 0,0
2634 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_maxY
);
2636 m_mapping_matrix
.Translate(-m_virt_minX
,-m_virt_minY
);
2639 double scalefactor_x
= dwx
;
2640 scalefactor_x
/= (m_virt_maxX
- m_virt_minX
);
2642 double scalefactor_y
= dwy
;
2643 scalefactor_y
/= (m_virt_maxY
- m_virt_minY
);
2645 // scale the drawing so it fit's in the window
2646 m_mapping_matrix
.Scale(scalefactor_x
, scalefactor_y
, 0, 0);
2648 // because of coordinate change mirror over X
2649 // 0,0 in graphic computerscreens: upperleft corner
2650 // 0,0 in cartesian: lowerleft corner
2653 m_mapping_matrix
.Mirror();
2655 // make inverse of mapping matrix
2656 // this is to set coordinates in the statusbar
2657 // and the calculate screencoordinates to world coordinates used
2659 m_inverse_mapping
=m_mapping_matrix
;
2660 m_inverse_mapping
.Invert();
2663 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2666 GetClientSize(&dx2
,&dy2
);
2667 if ( dwxi
!= dx2
|| dwyi
!= dy2
) //scrollbar is/became empty
2668 SetScroll(m_virtm_minX
,m_virtm_minY
,m_virtm_maxX
,m_virtm_maxY
);
2672 void wxCanvas::SetScroll(double vx1
,double vy1
,double vx2
,double vy2
)
2679 double dvx
= m_virt_maxX
- m_virt_minX
;
2680 double dvy
= m_virt_maxY
- m_virt_minY
;
2681 double dmvx
= m_virtm_maxX
- m_virtm_minX
;
2682 double dmvy
= m_virtm_maxY
- m_virtm_minY
;
2684 SetScrollbar(wxHORIZONTAL
,(m_virt_minX
-m_virtm_minX
)/dmvx
*1000,dvx
/dmvx
*1000,1000,FALSE
);
2687 SetScrollbar(wxVERTICAL
,(m_virtm_maxY
-m_virt_maxY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2691 SetScrollbar(wxVERTICAL
,(m_virt_minY
-m_virtm_minY
)/dmvy
*1000,dvy
/dmvy
*1000,1000,FALSE
);
2697 // coordinates conversions
2698 // -----------------------
2699 double wxCanvas::DeviceToLogicalX(int x
) const
2701 return m_inverse_mapping
.GetValue(0,0) * x
+ m_inverse_mapping
.GetValue(2,0);
2704 double wxCanvas::DeviceToLogicalY(int y
) const
2706 return m_inverse_mapping
.GetValue(1,1) * y
+ m_inverse_mapping
.GetValue(2,1);
2709 double wxCanvas::DeviceToLogicalXRel(int x
) const
2711 return x
*m_inverse_mapping
.GetValue(0,0);
2714 double wxCanvas::DeviceToLogicalYRel(int y
) const
2716 return y
*m_inverse_mapping
.GetValue(1,1);
2719 int wxCanvas::LogicalToDeviceX(double x
) const
2721 return (int) (m_mapping_matrix
.GetValue(0,0) * x
+ m_mapping_matrix
.GetValue(2,0) + 0.5);
2724 int wxCanvas::LogicalToDeviceY(double y
) const
2726 return (int) (m_mapping_matrix
.GetValue(1,1) * y
+ m_mapping_matrix
.GetValue(2,1) + 0.5);
2729 int wxCanvas::LogicalToDeviceXRel(double x
) const
2731 return (int) (x
*m_mapping_matrix
.GetValue(0,0) + 0.5);
2734 int wxCanvas::LogicalToDeviceYRel(double y
) const
2736 return (int) (y
*m_mapping_matrix
.GetValue(1,1) + 0.5);
2741 // return the inverse mapping matrix for zooming or coordinates
2742 wxTransformMatrix
wxCanvas::GetInverseMappingMatrix()
2744 return m_inverse_mapping
;
2747 wxTransformMatrix
wxCanvas::GetMappingMatrix()
2749 return m_mapping_matrix
;
2753 // ----------------------------------------------------------------------------
2754 // scrolling behaviour
2755 // ----------------------------------------------------------------------------
2757 void wxCanvas::OnScroll(wxScrollWinEvent
& event
)
2759 if (event
.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE
)
2761 if (event
.GetOrientation()==wxHORIZONTAL
)
2763 double x
=m_virtm_minX
+event
.GetPosition()/1000.0*(m_virtm_maxX
-m_virtm_minX
);
2764 x
=LogicalToDeviceXRel(x
-m_virt_minX
);
2765 ScrollWindow(-x
, 0, (const wxRect
*) NULL
);
2769 double y
=m_virtm_minY
+event
.GetPosition()/1000.0*(m_virtm_maxY
-m_virtm_minY
);
2770 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2771 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2774 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEUP
)
2776 if (event
.GetOrientation()==wxHORIZONTAL
)
2778 double x
=GetBufferWidth();
2779 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2783 double y
=GetBufferHeight();
2784 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2787 else if (event
.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN
)
2789 if (event
.GetOrientation()==wxHORIZONTAL
)
2791 double x
=-GetBufferWidth();
2792 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2796 double y
=-GetBufferHeight();
2797 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2800 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEUP
)
2802 if (event
.GetOrientation()==wxHORIZONTAL
)
2804 int x
=GetBufferWidth()/10;
2805 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2809 int y
=GetBufferHeight()/10;
2810 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2813 else if (event
.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN
)
2815 if (event
.GetOrientation()==wxHORIZONTAL
)
2817 int x
=-GetBufferWidth()/10;
2818 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2822 int y
=-GetBufferHeight()/10;
2823 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2829 void wxCanvas::OnChar(wxKeyEvent
& event
)
2831 switch ( event
.KeyCode() )
2836 double y
=GetBufferHeight();
2837 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2843 double y
=-GetBufferHeight();
2844 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2849 double y
=m_virtm_minY
;
2850 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2851 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2856 double y
=m_virtm_minY
+(m_virtm_maxY
-m_virtm_minY
);
2857 y
=LogicalToDeviceYRel(y
-m_virt_minY
);
2858 ScrollWindow(0, -y
, (const wxRect
*) NULL
);
2864 if (!event
.ControlDown())
2865 y
=GetBufferHeight()/10;
2867 y
=GetBufferHeight();
2868 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2875 if (!event
.ControlDown())
2876 y
=-GetBufferHeight()/10;
2878 y
=-GetBufferHeight();
2879 ScrollWindow(0, y
, (const wxRect
*) NULL
);
2886 if (!event
.ControlDown())
2887 x
=GetBufferWidth()/10;
2890 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2896 if (!event
.ControlDown())
2897 x
=-GetBufferWidth()/10;
2899 x
=-GetBufferWidth();
2900 ScrollWindow(x
, 0, (const wxRect
*) NULL
);
2912 //--------------------------------------------------------------------
2914 //--------------------------------------------------------------------
2916 class wxCanvasModule
: public wxModule
2919 virtual bool OnInit();
2920 virtual void OnExit();
2923 DECLARE_DYNAMIC_CLASS(wxCanvasModule
)
2926 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
)
2928 bool wxCanvasModule::OnInit()
2931 int error
= FT_Init_FreeType( &g_freetypeLibrary
);
2932 if (error
) return FALSE
;
2938 void wxCanvasModule::OnExit()
2941 FT_Done_FreeType( g_freetypeLibrary
);
2946 wxCanvasAdmin::wxCanvasAdmin()
2951 wxCanvasAdmin::~wxCanvasAdmin()
2958 void wxCanvasAdmin::Append( wxCanvas
* canvas
)
2960 m_canvaslist
.Append( canvas
);
2963 void wxCanvasAdmin::Remove( wxCanvas
* canvas
)
2965 m_canvaslist
.DeleteObject( canvas
);
2968 void wxCanvasAdmin::Update(wxCanvasObject
* obj
, double x
, double y
, double width
, double height
)
2970 wxNode
*node
= m_canvaslist
.First();
2974 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
2976 if (m_active
== canvas
)
2978 int xi
= canvas
->LogicalToDeviceX( x
);
2979 int yi
= canvas
->LogicalToDeviceY( y
);
2980 int wi
= canvas
->LogicalToDeviceXRel( width
);
2981 int hi
= canvas
->LogicalToDeviceYRel( height
);
2982 //update a little more then is strictly needed,
2983 //to get rid of the 1 bit bugs
2984 if (canvas
->GetYaxis())
2985 canvas
->Update( xi
-2, yi
+hi
-2, wi
+4, -hi
+4);
2987 canvas
->Update( xi
-2, yi
-2, wi
+4, hi
+4);
2990 { wxCanvasObject
* topobj
=canvas
->GetRoot()->Contains(obj
);
2993 wxCanvas
* tcanvas
= m_active
;
2997 //KKK TODO somehow the next does not work for update i do not know why
2998 canvas->GetRoot()->CalcBoundingBox();
2999 int xi = topobj->GetX();
3000 int yi = topobj->GetY();
3001 int wi = topobj->GetWidth();
3002 int hi = topobj->GetHeight();
3004 canvas
->Update( 0,0, canvas
->GetBufferWidth(),canvas
->GetBufferHeight());
3009 node
= node
->Next();
3013 void wxCanvasAdmin::UpdateNow()
3015 wxNode
*node
= m_canvaslist
.First();
3018 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
3020 canvas
->UpdateNow();
3021 node
= node
->Next();
3025 // coordinates conversions
3026 // -----------------------
3027 double wxCanvasAdmin::DeviceToLogicalX(int x
) const
3029 return m_active
->DeviceToLogicalX(x
);
3032 double wxCanvasAdmin::DeviceToLogicalY(int y
) const
3034 return m_active
->DeviceToLogicalY(y
);
3037 double wxCanvasAdmin::DeviceToLogicalXRel(int x
) const
3039 return m_active
->DeviceToLogicalXRel(x
);
3042 double wxCanvasAdmin::DeviceToLogicalYRel(int y
) const
3044 return m_active
->DeviceToLogicalYRel(y
);
3047 int wxCanvasAdmin::LogicalToDeviceX(double x
) const
3049 return m_active
->LogicalToDeviceX(x
);
3052 int wxCanvasAdmin::LogicalToDeviceY(double y
) const
3054 return m_active
->LogicalToDeviceY(y
);
3057 int wxCanvasAdmin::LogicalToDeviceXRel(double x
) const
3059 return m_active
->LogicalToDeviceXRel(x
);
3062 int wxCanvasAdmin::LogicalToDeviceYRel(double y
) const
3064 return m_active
->LogicalToDeviceYRel(y
);
3067 void wxCanvasAdmin::SetActive(wxCanvas
* activate
)
3069 wxNode
*node
= m_canvaslist
.First();
3072 wxCanvas
*canvas
= (wxCanvas
*) node
->Data();
3074 if (activate
== canvas
)
3079 node
= node
->Next();