#pragma hdrstop
#endif
-#include "wx/canvas/canvas.h"
+#include "canvas.h"
+#include "polygon.h"
+#include "liner.h"
#ifdef __WXGTK__
#include <gtk/gtk.h>
#endif
#ifndef wxUSE_FREETYPE
- #define wxUSE_FREETYPE 1
+ #define wxUSE_FREETYPE 0
#endif
#if wxUSE_FREETYPE
#include <freetype/freetype.h>
#endif
+//#define CANVASDEBUG
+
//----------------------------------------------------------------------------
// globals
//----------------------------------------------------------------------------
+const double pi = 3.1415926535;
+
#if wxUSE_FREETYPE
FT_Library g_freetypeLibrary;
#endif
//----------------------------------------------------------------------------
// wxCanvasObject
//----------------------------------------------------------------------------
-
wxCanvasObject::wxCanvasObject()
{
- m_owner = NULL;
- m_area.x = -1;
- m_area.y = -1;
- m_area.width = -1;
- m_area.height = -1;
+ // the default event handler is just this object
+ m_eventHandler=this;
+ m_admin = NULL;
m_isControl = FALSE;
m_isVector = FALSE;
m_isImage = FALSE;
+ m_visible = TRUE;
+ m_dragmode = DRAG_ONTOP;
+// handy when debugging
+// m_dragmode = DRAG_RECTANGLE;
+ m_dragable = TRUE;
+}
+
+bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent& event)
+{
+ return m_eventHandler->ProcessEvent(event);
+}
+
+void wxCanvasObject::PushEventHandler(wxEvtHandler *handler)
+{
+ handler->SetNextHandler(GetEventHandler());
+ m_eventHandler=handler;
+}
+
+wxEvtHandler *wxCanvasObject::PopEventHandler(bool deleteHandler)
+{
+ wxEvtHandler *handlerA = m_eventHandler;
+ if ( handlerA )
+ {
+ wxEvtHandler *handlerB = handlerA->GetNextHandler();
+ handlerA->SetNextHandler((wxEvtHandler *)NULL);
+ m_eventHandler=handlerB;
+ if ( deleteHandler )
+ {
+ delete handlerA;
+ handlerA = (wxEvtHandler *)NULL;
+ }
+ }
+
+ return handlerA;
+}
+
+void wxCanvasObject::AppendEventHandler(wxEvtHandler *handler)
+{
+ GetEventHandler()->SetNextHandler(handler);
+}
+
+wxEvtHandler *wxCanvasObject::RemoveLastEventHandler(bool deleteHandler)
+{
+ //always the first in the row
+ wxEvtHandler *handlerA = m_eventHandler;
+ wxEvtHandler *handlerB=handlerA;
+ //goto the end
+ while ( handlerA->GetNextHandler() )
+ {
+ handlerB = handlerA;
+ handlerA = handlerA->GetNextHandler();
+ }
+
+ handlerB->SetNextHandler((wxEvtHandler *)NULL);
+ if ( deleteHandler )
+ {
+ delete handlerA;
+ }
+
+ return GetEventHandler();
+}
+
+wxRect wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix& cworld)
+{
+
+ wxBoundingBox tmp=m_bbox;
+ tmp.MapBbox(cworld);
+
+
+ int x1 = m_admin->LogicalToDeviceX( tmp.GetMinX() );
+ int y1 = m_admin->LogicalToDeviceY( tmp.GetMinY() );
+ int x2 = m_admin->LogicalToDeviceX( tmp.GetMaxX() );
+ int y2 = m_admin->LogicalToDeviceY( tmp.GetMaxY() );
+
+ if (x1 > x2)
+ {
+ int tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+ if (y1 > y2)
+ {
+ int tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+
+ wxRect tmparea;
+ tmparea.x = x1;
+ tmparea.y = y1;
+ tmparea.width = x2-x1;
+ tmparea.height = y2-y1;
+
+ return tmparea;
+}
+
+void wxCanvasObject::MoveAbsolute( double x, double y )
+{
+ //save old position of boundingbox
+ double oldx = GetXMin();
+ double oldy = GetYMin();
+ double w = m_bbox.GetWidth();
+ double h = m_bbox.GetHeight();
+
+ SetPosXY(x,y);
+
+ double newx=GetXMin();
+ double newy=GetYMin();
+
+ double leftu,rightu,bottomu,topu ;
+ leftu = wxMin (oldx, newx ) ;
+ rightu = wxMax (oldx + w, newx + w) ;
+ topu = wxMin (oldy, newy) ;
+ bottomu = wxMax (oldy + h, newy + h) ;
+
+ if ( rightu - leftu < 2*w && bottomu - topu < 2*h )
+ {
+ m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu);
+ }
+ else
+ {
+ m_admin->Update( this, oldx, oldy, w, h );
+ m_admin->Update( this, newx, newy, w, h );
+ }
}
-void wxCanvasObject::SetArea( int x, int y, int width, int height )
+void wxCanvasObject::MoveRelative( double x, double y )
{
- m_area.x = x;
- m_area.y = y;
- m_area.width = width;
- m_area.height = height;
+ //save old position of boundingbox
+ double oldx = GetXMin();
+ double oldy = GetYMin();
+ double w = m_bbox.GetWidth();
+ double h = m_bbox.GetHeight();
+
+ TransLate(x,y);
+
+ double newx=GetXMin();
+ double newy=GetYMin();
+
+ double leftu,rightu,bottomu,topu ;
+ leftu = wxMin (oldx, newx ) ;
+ rightu = wxMax (oldx + w, newx + w) ;
+ topu = wxMin (oldy, newy) ;
+ bottomu = wxMax (oldy + h, newy + h) ;
+
+ if ( rightu - leftu < 2*w && bottomu - topu < 2*h )
+ {
+ m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu);
+ }
+ else
+ {
+ m_admin->Update( this, oldx, oldy, w, h );
+ m_admin->Update( this, newx, newy, w, h );
+ }
}
-void wxCanvasObject::SetArea( wxRect rect )
+
+void wxCanvasObject::DragStart()
{
- m_area.x = rect.x;
- m_area.y = rect.y;
- m_area.width = rect.width;
- m_area.height = rect.height;
+#if IMAGE_CANVAS
+#else
+ if (m_dragmode == DRAG_RECTANGLE)
+ {
+ this->SetVisible(FALSE);
+ wxTransformMatrix help;
+ double x = GetXMin();
+ double y = GetYMin();
+ double w = m_bbox.GetWidth();
+ double h = m_bbox.GetHeight();
+ m_admin->Update( this, x, y, w, h );
+ m_admin->UpdateNow();
+
+ wxRect recold=GetAbsoluteArea(help);
+ wxClientDC dc(m_admin->GetActive());
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ dc.SetLogicalFunction(wxINVERT);
+ dc.DrawRectangle(recold);
+ dc.SetBrush(wxNullBrush);
+ dc.SetPen(wxNullPen);
+ }
+ else
+ {
+ this->SetVisible(FALSE);
+ wxTransformMatrix help;
+ double x = GetXMin();
+ double y = GetYMin();
+ double w = m_bbox.GetWidth();
+ double h = m_bbox.GetHeight();
+
+ wxRect recnew=GetAbsoluteArea(help);
+
+ //redraw in buffer what should be there without this object
+ m_admin->Update( this, x, y, w, h );
+ m_admin->GetActive()->Freeze();
+
+ //save the drawing (without the object itself to a bitmap)
+ m_atnewpos = wxBitmap(recnew.width,recnew.height);
+ wxMemoryDC dcm;
+ dcm.SelectObject(*m_admin->GetActive()->GetBuffer());
+ wxMemoryDC tmp;
+ tmp.SelectObject(m_atnewpos);
+ tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
+ tmp.SelectObject(wxNullBitmap);
+ dcm.SelectObject(wxNullBitmap);
+ }
+#endif
}
-void wxCanvasObject::Move( int x, int y )
+
+void wxCanvasObject::DragRelative( double x, double y)
{
- int old_x = m_area.x;
- int old_y = m_area.y;
+#if IMAGE_CANVAS
+#else
+ if (m_dragmode == DRAG_RECTANGLE)
+ {
+ wxTransformMatrix help;
- m_area.x = x;
- m_area.y = y;
+ wxRect recold=GetAbsoluteArea(help);
- if (!m_isControl)
+ TransLate(x,y);
+
+ wxRect recnew=GetAbsoluteArea(help);
+
+ wxClientDC dc(m_admin->GetActive());
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ dc.SetLogicalFunction(wxINVERT);
+ dc.DrawRectangle(recold);
+ dc.DrawRectangle(recnew);
+ dc.SetBrush(wxNullBrush);
+ dc.SetPen(wxNullPen);
+ }
+ else
{
- // TODO: sometimes faster to merge into 1 Update or
- // to break up into four
- m_owner->Update( old_x, old_y, m_area.width, m_area.height );
- m_owner->Update( x, y, m_area.width, m_area.height );
+ wxClientDC dc(m_admin->GetActive());
+ wxMemoryDC tmp;
+
+ wxTransformMatrix help;
+ wxRect recold=GetAbsoluteArea(help);
+
+ //restore what was there (without the object itself)
+ wxMemoryDC dcm;
+ dcm.SelectObject(*m_admin->GetActive()->GetBuffer());
+ tmp.SelectObject(m_atnewpos);
+ dcm.Blit(recold.x,recold.y,recold.width,recold.height,&tmp,0,0,wxCOPY,FALSE);
+
+ TransLate(x,y);
+
+ wxRect recnew=GetAbsoluteArea(help);
+
+ //save the contents of the buffer at the new position
+ tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
+ tmp.SelectObject(wxNullBitmap);
+
+ //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew );
+
+ this->SetVisible(TRUE);
+ //redraw object into the buffer
+ m_admin->GetActive()->SetDC(&dcm);
+ Render(&help,recnew.x,recnew.y,recnew.width,recnew.height);
+
+ //draw the union or seperate to the canvas
+ double leftu,rightu,bottomu,topu ;
+ leftu = wxMin (recold.x, recnew.x ) ;
+ rightu = wxMax (recold.x + recold.width, recnew.x + recnew.width ) ;
+ topu = wxMin (recold.y, recnew.y) ;
+ bottomu = wxMax (recold.y + recold.height, recnew.y + recnew.height) ;
+
+ if ( rightu - leftu < 2*recold.width && bottomu - topu < 2*recold.height)
+ {
+ dc.Blit(leftu,topu,rightu - leftu,bottomu - topu,&dcm,leftu,topu,wxCOPY,FALSE);
+ }
+ else
+ {
+ //do them seperate
+ //first redraw what should be at the old position in the canvas
+ dc.Blit(recold.x,recold.y,recold.width,recold.height,&dcm,recold.x,recold.y,wxCOPY,FALSE);
+ //blit the new position of the object to the canvas
+ dc.Blit(recnew.x,recnew.y,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
+ }
+ dcm.SelectObject(wxNullBitmap);
+ this->SetVisible(FALSE);
}
+#endif
+}
+
+
+void wxCanvasObject::DragEnd()
+{
+#if IMAGE_CANVAS
+#else
+ m_atnewpos = wxBitmap(0,0);
+ m_admin->GetActive()->Thaw();
+ this->SetVisible(TRUE);
+ double x = GetXMin();
+ double y = GetYMin();
+ double w = m_bbox.GetWidth();
+ double h = m_bbox.GetHeight();
+ m_admin->Update( this, x, y, w, h );
+ m_admin->UpdateNow();
+#endif
+}
+
+wxCanvasObject* wxCanvasObject::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ return this;
+ return (wxCanvasObject*) NULL;
}
-bool wxCanvasObject::IsHit( int x, int y, int margin )
+wxCanvasObject* wxCanvasObject::Contains( wxCanvasObject* obj )
{
- return ((x >= m_area.x-margin) &&
- (x <= m_area.x+m_area.width+margin) &&
- (y >= m_area.y-margin) &&
- (y <= m_area.y+m_area.height+margin));
+ if (obj == this)
+ return this;
+ return (wxCanvasObject*) NULL;
}
void wxCanvasObject::CaptureMouse()
{
- m_owner->SetCaptureMouse( this );
+ m_admin->GetActive()->SetCaptureMouse( this );
}
void wxCanvasObject::ReleaseMouse()
{
- m_owner->SetCaptureMouse( NULL );
+ m_admin->GetActive()->SetCaptureMouse( NULL );
}
bool wxCanvasObject::IsCapturedMouse()
{
- return m_owner->m_captureMouse==this;
+ return m_admin->GetActive()->GetCaptured()==this;
}
-void wxCanvasObject::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasObject::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
{
}
-void wxCanvasObject::Recreate()
+void wxCanvasObject::CalcBoundingBox()
{
}
// wxCanvasObjectGroup
//----------------------------------------------------------------------------
-wxCanvasObjectGroup::wxCanvasObjectGroup()
+wxCanvasObjectGroup::wxCanvasObjectGroup(double x, double y)
{
- m_validbounds = FALSE;
+ lworld.Translate(x,y);
+ //no objects make the bounding box the x,y and take care of it later
+ m_bbox.Expand(x,y);
}
wxCanvasObjectGroup::~wxCanvasObjectGroup()
{
}
-void wxCanvasObjectGroup::SetOwner(wxCanvas* canvas)
+void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler *handler)
{
- m_owner=canvas;
+ wxCanvasObject::PushEventHandler(handler);
wxNode *node = m_objects.First();
while (node)
{
wxCanvasObject *obj = (wxCanvasObject*) node->Data();
- obj->SetOwner(canvas);
+ obj->PushEventHandler(handler);
node = node->Next();
}
}
-void wxCanvasObjectGroup::ExtendArea(double x, double y)
+wxEvtHandler *wxCanvasObjectGroup::PopEventHandler(bool deleteHandler)
{
- if (m_validbounds)
+ wxNode *node = m_objects.First();
+ while (node)
{
- if (x < m_minx) m_minx = x;
- if (y < m_miny) m_miny = y;
- if (x > m_maxx) m_maxx = x;
- if (y > m_maxy) m_maxy = y;
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->PopEventHandler(deleteHandler);
+
+ node = node->Next();
}
- else
+ return wxCanvasObject::PopEventHandler(deleteHandler);
+}
+
+void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler *handler)
+{
+ wxCanvasObject::AppendEventHandler(handler);
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->AppendEventHandler(handler);
+
+ node = node->Next();
+ }
+}
+
+wxEvtHandler *wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler)
+{
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->RemoveLastEventHandler(deleteHandler);
+
+ node = node->Next();
+ }
+ return wxCanvasObject::RemoveLastEventHandler(deleteHandler);
+}
+
+void wxCanvasObjectGroup::TransLate( double x, double y )
+{
+ lworld.Translate(x,y);
+ CalcBoundingBox();
+}
+
+void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin* admin)
+{
+ m_admin=admin;
+ wxNode *node = m_objects.First();
+ while (node)
{
- m_validbounds = TRUE;
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->SetAdmin(admin);
- m_minx = x;
- m_miny = y;
- m_maxx = x;
- m_maxy = y;
+ node = node->Next();
}
}
void wxCanvasObjectGroup::DeleteContents( bool flag)
{
m_objects.DeleteContents( flag );
- m_validbounds = FALSE;
+ m_bbox.SetValid(FALSE);
+ CalcBoundingBox();
}
void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
{
m_objects.Insert( obj );
- m_validbounds = FALSE;
+ if (m_objects.First())
+ m_bbox.Expand(obj->GetBbox());
+ else
+ {
+ m_bbox.SetValid(FALSE);
+ CalcBoundingBox();
+ }
}
void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
{
m_objects.Append( obj );
- m_validbounds = FALSE;
+ if (m_objects.First())
+ m_bbox.Expand(obj->GetBbox());
+ else
+ {
+ m_bbox.SetValid(FALSE);
+ CalcBoundingBox();
+ }
}
void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
{
m_objects.Insert( before, obj );
- m_validbounds = FALSE;
+ m_bbox.SetValid(FALSE);
+ if (m_objects.First())
+ m_bbox.Expand(obj->GetBbox());
+ else
+ {
+ m_bbox.SetValid(FALSE);
+ CalcBoundingBox();
+ }
}
void wxCanvasObjectGroup::Remove( wxCanvasObject* obj )
{
m_objects.DeleteObject( obj );
- m_validbounds = FALSE;
+ m_bbox.SetValid(FALSE);
+ CalcBoundingBox();
}
-void wxCanvasObjectGroup::Recreate()
+void wxCanvasObjectGroup::CalcBoundingBox()
{
- m_validbounds = FALSE;
+ m_bbox.SetValid(FALSE);
wxNode *node = m_objects.First();
while (node)
{
wxCanvasObject *obj = (wxCanvasObject*) node->Data();
- obj->Recreate();
- ExtendArea(obj->GetX(),obj->GetY());
- ExtendArea(obj->GetX()+obj->GetWidth(),obj->GetY()+obj->GetHeight());
+ obj->CalcBoundingBox();
+ wxBoundingBox tmp;
+ tmp=obj->GetBbox();
+ tmp.MapBbox(lworld);
+
+ m_bbox.Expand( tmp );
node = node->Next();
}
}
-void wxCanvasObjectGroup::Render(int xabs, int yabs, int x, int y, int width, int height )
+void wxCanvasObjectGroup::Render(wxTransformMatrix* cworld, int x, int y, int width, int height )
{
- // cycle through all objects
+ if (!m_visible) return;
+
+ wxTransformMatrix backup = *cworld;
+ *cworld *= lworld;
+
wxNode *node = m_objects.First();
+
+ if (!node) return;
+
+
+#ifdef CANVASDEBUG
+ wxRect absarea=GetAbsoluteArea(*cworld);
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetPen(*wxBLACK_PEN);
+ dc->SetBrush(*wxTRANSPARENT_BRUSH);
+ dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height );
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+#endif
+ //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently
+ /*
+ if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) &&
+ wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height )
+ )
+ )
+ return;
+ */
+
+ // cycle through all objects
while (node)
{
wxCanvasObject *obj = (wxCanvasObject*) node->Data();
- if (!obj->IsControl())
+ if (!obj->IsControl() && obj->GetVisible())
{
+
+ //get area at the absolute position
+ wxRect absareaobject=obj->GetAbsoluteArea(*cworld);
+
// If we have 10.000 objects, we will go through
// this 10.000 times for each update, so we have
// to optimise carefully.
- int clip_x = xabs + obj->GetX();
- int clip_width = obj->GetWidth();
+ int clip_x = absareaobject.x;
+ int clip_width = absareaobject.width;
if (clip_x < x)
{
clip_width -= x-clip_x;
if (clip_width > 0)
{
- int clip_y = yabs + obj->GetY();
- int clip_height = obj->GetHeight();
+ int clip_y = absareaobject.y;
+ int clip_height = absareaobject.height;
if (clip_y < y)
{
clip_height -= y-clip_y;
clip_height = y+height-clip_y;
if (clip_height > 0)
- obj->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ {
+ obj->Render(cworld, clip_x, clip_y, clip_width, clip_height );
+ }
}
}
}
node = node->Next();
}
+ *cworld = backup;
}
void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
{
}
-bool wxCanvasObjectGroup::IsHit( int x, int y, int margin )
+wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double margin )
{
+ //KKKfirst check if within bbox
+ //will only work if they are always uptodate
+ //if (!m_bbox.PointInBox(x,y,margin))
+ // return (wxCanvasObject*) NULL;
+
+ wxTransformMatrix inverse = lworld;
+ double xh,yh;
+ inverse.Invert();
+ inverse.TransformPoint(x,y,xh,yh);
+
+ wxCanvasObject *obj=0;
wxNode *node = m_objects.Last();
while (node)
{
- wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+ obj=(wxCanvasObject*) node->Data();
- if (!obj->IsControl())
+ if (!obj->IsControl() )
{
- if (obj->IsHit(x,y,margin))
+ if (obj->IsHitWorld(x,y,margin))
{
- return TRUE;
+ return obj;
}
}
node = node->Previous();
}
- return FALSE;
+
+ return (wxCanvasObject*) NULL;
}
-wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin )
+wxCanvasObject* wxCanvasObjectGroup::Contains( wxCanvasObject* obj )
{
- wxCanvasObject *obj=0;
- wxNode *node = m_objects.Last();
+ wxCanvasObject* cobj;
+ wxNode *node = m_objects.First();
while (node)
{
- obj=(wxCanvasObject*) node->Data();
+ cobj=(wxCanvasObject*) node->Data();
- if (!obj->IsControl())
+ if (cobj->Contains(obj))
{
- if (obj->IsHit(x,y,margin))
- {
- return obj;
- }
+ return obj;
}
- node = node->Previous();
+ node = node->Next();
}
return (wxCanvasObject*) NULL;
}
+int wxCanvasObjectGroup::IndexOf( wxCanvasObject* obj )
+{
+ return m_objects.IndexOf( obj );
+}
+
+
+
//----------------------------------------------------------------------------
-// wxCanvasObjectGroupRef
+// wxCanvasObjectRef
//----------------------------------------------------------------------------
-wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjectGroup* group)
+wxCanvasObjectRef::wxCanvasObjectRef(double x, double y, wxCanvasObject* obj)
: wxCanvasObject()
{
- m_x = x;
- m_y = y;
- m_validbounds = FALSE;
- m_group = group;
+ lworld.Translate(x,y);
+ m_obj = obj;
+
+ m_bbox.SetValid(FALSE);
+ wxBoundingBox tmp;
+ tmp=obj->GetBbox();
+ tmp.MapBbox(lworld);
+ m_bbox.Expand( tmp );
}
-void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas)
+void wxCanvasObjectRef::PushEventHandler(wxEvtHandler *handler)
{
- m_owner = canvas;
- m_group->SetOwner(canvas);
+ wxCanvasObject::PushEventHandler(handler);
+ m_obj->PushEventHandler(handler);
}
-void wxCanvasObjectGroupRef::ExtendArea(double x, double y)
+wxEvtHandler *wxCanvasObjectRef::PopEventHandler(bool deleteHandler)
{
- if (m_validbounds)
- {
- if (x < m_minx) m_minx = x;
- if (y < m_miny) m_miny = y;
- if (x > m_maxx) m_maxx = x;
- if (y > m_maxy) m_maxy = y;
- }
- else
- {
- m_validbounds = TRUE;
+ m_obj->PopEventHandler(deleteHandler);
+ return wxCanvasObject::PopEventHandler(deleteHandler);
+}
- m_minx = x;
- m_miny = y;
- m_maxx = x;
- m_maxy = y;
- }
+void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler *handler)
+{
+ wxCanvasObject::AppendEventHandler(handler);
+ m_obj->AppendEventHandler(handler);
+}
+
+wxEvtHandler *wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler)
+{
+ m_obj->RemoveLastEventHandler(deleteHandler);
+ return wxCanvasObject::RemoveLastEventHandler(deleteHandler);
+}
+
+void wxCanvasObjectRef::TransLate( double x, double y )
+{
+ lworld.Translate(x,y);
+ CalcBoundingBox();
+}
+
+wxCanvasObject* wxCanvasObjectRef::Contains( wxCanvasObject* obj )
+{
+ if (obj == this || m_obj->Contains(obj))
+ return this;
+
+ return (wxCanvasObject*) NULL;
+}
+
+
+void wxCanvasObjectRef::SetRotation(double rotation)
+{
+ lworld.SetRotation(rotation);
+ CalcBoundingBox();
+}
+
+void wxCanvasObjectRef::SetScale(double scalex,double scaley)
+{
+ lworld.Scale(scalex,scaley,lworld.GetValue(2,0),lworld.GetValue(2,1));
+ CalcBoundingBox();
}
-void wxCanvasObjectGroupRef::Recreate()
+void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin* admin)
{
- m_validbounds = FALSE;
- m_group->Recreate();
- ExtendArea(m_group->GetXMin(),m_group->GetYMin());
- ExtendArea(m_group->GetXMax(),m_group->GetYMax());
+ m_admin = admin;
+ m_obj->SetAdmin(admin);
+}
+
+void wxCanvasObjectRef::CalcBoundingBox()
+{
+ m_bbox.SetValid(FALSE);
+ m_obj->CalcBoundingBox();
- //set the area in pixels relative to the parent
- SetArea( m_owner->GetDeviceX( m_x + m_minx ),
- m_owner->GetDeviceY( m_y + m_miny ),
- m_owner->GetDeviceWidth( m_maxx-m_minx ),
- m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+ wxBoundingBox tmp;
+ tmp=m_obj->GetBbox();
+ tmp.MapBbox(lworld);
+ m_bbox.Expand( tmp );
}
-void wxCanvasObjectGroupRef::Render(int xabs, int yabs, int x, int y, int width, int height )
+void wxCanvasObjectRef::Render(wxTransformMatrix* cworld, int x, int y, int width, int height )
{
- xabs += m_area.x;
- yabs += m_area.y;
+ if (!m_visible) return;
+
+ //get the absolute area (without the local matrix included)
+ //the boundingbox is relative to the parent.
+ wxRect absarea=GetAbsoluteArea(*cworld);
- int clip_x = xabs + m_group->GetXMin();
- int clip_width = m_group->GetXMax()-m_group->GetXMin();
+ wxTransformMatrix backup = *cworld;
+ *cworld *= lworld;
+
+#ifdef CANVASDEBUG
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetPen(*wxBLACK_PEN);
+ dc->SetBrush(*wxTRANSPARENT_BRUSH);
+ dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height );
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+#endif
+
+ int clip_x = absarea.x;
+ int clip_width = absarea.width;
if (clip_x < x)
{
clip_width -= x-clip_x;
if (clip_width > 0)
{
- int clip_y = yabs + m_group->GetYMin();
- int clip_height = m_group->GetYMax()-m_group->GetYMin();
+ int clip_y = absarea.y;
+ int clip_height = absarea.height;
if (clip_y < y)
{
clip_height -= y-clip_y;
clip_height = y+height-clip_y;
if (clip_height > 0)
- m_group->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ m_obj->Render(cworld, clip_x, clip_y, clip_width, clip_height );
}
}
}
-}
-void wxCanvasObjectGroupRef::WriteSVG( wxTextOutputStream &stream )
-{
+ *cworld = backup;
}
-bool wxCanvasObjectGroupRef::IsHit( int x, int y, int margin )
+void wxCanvasObjectRef::WriteSVG( wxTextOutputStream &stream )
{
- return m_group->IsHit(x-GetPosX(),y-GetPosY(),margin);
}
-wxCanvasObject* wxCanvasObjectGroupRef::IsHitObject( int x, int y, int margin )
+wxCanvasObject* wxCanvasObjectRef::IsHitWorld( double x, double y, double margin )
{
- return m_group->IsHitObject(x-GetPosX(),y-GetPosY(),margin);
-}
+ //KKKfirst check if within bbox
+ //will only work if they are always uptodate
+ //if (!m_bbox.PointInBox(x,y,margin))
+ // return (wxCanvasObject*) NULL;
-void wxCanvasObjectGroupRef::Move( int x, int y )
-{
- m_x = x;
- m_y = y;
+ wxTransformMatrix inverse = lworld;
+ double xh,yh;
+ inverse.Invert();
+ inverse.TransformPoint(x,y,xh,yh);
- int old_area_x = m_area.x;
- int old_area_y = m_area.y;
+ if (m_obj->IsHitWorld(xh,yh,margin))
+ return this;
- m_area.x=m_owner->GetDeviceX( m_x + m_minx );
- m_area.y=m_owner->GetDeviceY( m_y + m_miny );
+ return (wxCanvasObject*) NULL;
+}
- int leftu,rightu,bottomu,topu ;
- leftu = wxMin (m_area.x, old_area_x ) ;
- rightu = wxMax (old_area_x + m_area.width, m_area.x + m_area.width) ;
- topu = wxMin (m_area.y,old_area_y) ;
- bottomu = wxMax (old_area_y + m_area.height, m_area.y + m_area.height) ;
- if ( rightu - leftu < 2*m_area.width && bottomu - topu < 2*m_area.height )
- {
- m_owner->Update(leftu,topu,rightu - leftu,bottomu - topu);
- }
- else
- {
- m_owner->Update(old_area_x, old_area_y, m_area.width, m_area.height );
- m_owner->Update( m_area.x, m_area.y, m_area.width, m_area.height );
- }
-}
//----------------------------------------------------------------------------
-// wxCanvasPolyline
+// wxCanvasRect
//----------------------------------------------------------------------------
-wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[])
+wxCanvasRect::wxCanvasRect( double x, double y, double w, double h , double radius )
: wxCanvasObject()
{
- m_n = n;
- m_points = points;
- m_pen = *wxBLACK_PEN;
-}
-
-wxCanvasPolyline::~wxCanvasPolyline()
-{
- delete m_points;
+ m_x = x;
+ m_y = y;
+ m_width = w;
+ m_height = h;
+ m_radius = radius;
+
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ CalcBoundingBox();
}
-void wxCanvasPolyline::ExtendArea(double x, double y)
+void wxCanvasRect::TransLate( double x, double y )
{
- if (m_validbounds)
- {
- if (x < m_minx) m_minx = x;
- if (y < m_miny) m_miny = y;
- if (x > m_maxx) m_maxx = x;
- if (y > m_maxy) m_maxy = y;
- }
- else
- {
- m_validbounds = TRUE;
-
- m_minx = x;
- m_miny = y;
- m_maxx = x;
- m_maxy = y;
- }
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
}
-void wxCanvasPolyline::Recreate()
+void wxCanvasRect::CalcBoundingBox()
{
-
- m_validbounds=FALSE;
- int i;
- for (i=0; i < m_n;i++)
- {
- ExtendArea(m_points[i].m_x,m_points[i].m_y);
- }
+ m_bbox.SetMin( m_x , m_y);
+ m_bbox.SetMax( m_x + m_width ,m_y + m_height );
//include the pen width also
- ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth());
- ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2);
-
- //set the area in pixels relative to the parent
- SetArea( m_owner->GetDeviceX(m_minx ),
- m_owner->GetDeviceY(m_miny ),
- m_owner->GetDeviceWidth( m_maxx-m_minx ),
- m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+//KKK m_bbox.EnLarge(m_pen.GetWidth()+m_radius);
+ m_bbox.EnLarge(m_pen.GetWidth()/2);
}
-void wxCanvasPolyline::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasRect::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
{
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
+ if (!m_visible) return;
+
+#if IMAGE_CANVAS
+ wxImage *image = m_admin->GetActive()->GetBuffer();
- int start_y = clip_y - buffer_y;
- int end_y = clip_y+clip_height - buffer_y;
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
- int start_x = clip_x - buffer_x;
- int end_x = clip_x+clip_width - buffer_x;
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
-#if IMAGE_CANVAS
+ // speed up later
+ for (int y = start_y; y < end_y; y++)
+ for (int x = start_x; x < end_x; x++)
+ {
+ int red=m_brush.GetColour().Red();
+ int green=m_brush.GetColour().Green();
+ int blue=m_brush.GetColour().Blue();
+ image->SetRGB( x, y, red, green, blue );
+ }
#else
- wxPoint *cpoints = new wxPoint[m_n];
- int i;
- for (i = 0; i < m_n; i++)
+ if (cworld->GetRotation())
{
- cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs);
- cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs);
+ wxPoint *cpoints = new wxPoint[4];
+ double x;
+ double y;
+ cworld->TransformPoint( m_x, m_y, x, y );
+ cpoints[0].x = m_admin->LogicalToDeviceX(x);
+ cpoints[0].y = m_admin->LogicalToDeviceY(y);
+ cworld->TransformPoint( m_x , m_y + m_height, x, y );
+ cpoints[1].x = m_admin->LogicalToDeviceX(x);
+ cpoints[1].y = m_admin->LogicalToDeviceY(y);
+ cworld->TransformPoint( m_x + m_width, m_y + m_height, x, y );
+ cpoints[2].x = m_admin->LogicalToDeviceX(x);
+ cpoints[2].y = m_admin->LogicalToDeviceY(y);
+ cworld->TransformPoint( m_x + m_width, m_y , x, y );
+ cpoints[3].x = m_admin->LogicalToDeviceX(x);
+ cpoints[3].y = m_admin->LogicalToDeviceY(y);
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(4, cpoints, 0,0,wxWINDING_RULE);
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+ }
+ else
+ {
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ //yes the whole not only the clipping region, because we have a pen also
+ int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
+ int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
+ int w = m_admin->LogicalToDeviceXRel( m_width );
+ int h = m_admin->LogicalToDeviceYRel( m_height );
+ int r = m_admin->LogicalToDeviceYRel( m_radius );
+ if (w > 0 && w < 1) w=1;
+ if (w < 0 && w > -1) w=-1;
+ if (h > 0 && h < 1) h=1;
+ if (h < 0 && h > -1) h=-1;
+ if (m_radius)
+ dc->DrawRoundedRectangle( x,y,w,h,r);
+ else
+ dc->DrawRectangle( x,y,w,h);
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
}
- wxMemoryDC *dc = m_owner->GetDC();
- dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
- dc->SetPen(m_pen);
- dc->DrawLines(m_n, cpoints, 0,0);
- delete [] cpoints;
- dc->SetPen(wxNullPen);
- dc->DestroyClippingRegion();
#endif
}
-void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream )
+void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
{
}
//----------------------------------------------------------------------------
-// wxCanvasPolygon
+// wxCanvasCircle
//----------------------------------------------------------------------------
-wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[])
+wxCanvasCircle::wxCanvasCircle( double x, double y, double radius )
: wxCanvasObject()
{
- m_n = n;
- m_points = points;
+ m_x = x;
+ m_y = y;
+ m_radius = radius;
+
m_brush = *wxBLACK_BRUSH;
m_pen = *wxTRANSPARENT_PEN;
+ CalcBoundingBox();
}
-wxCanvasPolygon::~wxCanvasPolygon()
+void wxCanvasCircle::TransLate( double x, double y )
{
- delete m_points;
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
}
-void wxCanvasPolygon::ExtendArea(double x, double y)
+void wxCanvasCircle::CalcBoundingBox()
{
- if (m_validbounds)
- {
- if (x < m_minx) m_minx = x;
- if (y < m_miny) m_miny = y;
- if (x > m_maxx) m_maxx = x;
- if (y > m_maxy) m_maxy = y;
- }
- else
- {
- m_validbounds = TRUE;
+ m_bbox.SetMin( m_x-m_radius , m_y-m_radius );
+ m_bbox.SetMax( m_x+m_radius , m_y+m_radius );
- m_minx = x;
- m_miny = y;
- m_maxx = x;
- m_maxy = y;
- }
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth()/2);
+}
+
+void wxCanvasCircle::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+#if IMAGE_CANVAS
+#else
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ //yes the whole not only the clipping region, because we have a pen also
+ //and rotation on a circle is not important so only a shift with cworld
+ int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
+ int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
+ int radius = m_admin->LogicalToDeviceXRel( m_radius );
+ if (radius < 1) radius=1;
+ dc->DrawCircle( x,y,radius);
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
}
-void wxCanvasPolygon::Recreate()
+void wxCanvasCircle::WriteSVG( wxTextOutputStream &stream )
{
+}
- m_validbounds=FALSE;
- int i;
- for (i=0; i < m_n;i++)
+wxCanvasObject* wxCanvasCircle::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
{
- ExtendArea(m_points[i].m_x,m_points[i].m_y);
+ if (m_radius+m_pen.GetWidth()/2+margin > sqrt(pow(m_x-x,2)+pow(m_y-y,2)))
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
}
+ return (wxCanvasObject*) NULL;
+}
- //include the pen width also
- ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth());
- ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2);
+//----------------------------------------------------------------------------
+// wxCanvasEllipse
+//----------------------------------------------------------------------------
+
+wxCanvasEllipse::wxCanvasEllipse( double x, double y, double width, double height )
+ : wxCanvasObject()
+{
+ m_x = x;
+ m_y = y;
+ m_width = width;
+ m_height = height;
+
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ CalcBoundingBox();
+}
- //set the area in pixels relative to the parent
- SetArea( m_owner->GetDeviceX( m_minx ),
- m_owner->GetDeviceY( m_miny ),
- m_owner->GetDeviceWidth( m_maxx-m_minx ),
- m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+void wxCanvasEllipse::TransLate( double x, double y )
+{
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
}
-void wxCanvasPolygon::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasEllipse::CalcBoundingBox()
{
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
+ m_bbox.SetMin( m_x, m_y );
+ m_bbox.SetMax( m_x+m_width , m_y+m_height );
- int start_y = clip_y - buffer_y;
- int end_y = clip_y+clip_height - buffer_y;
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth()/2);
+}
- int start_x = clip_x - buffer_x;
- int end_x = clip_x+clip_width - buffer_x;
+void wxCanvasEllipse::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
#if IMAGE_CANVAS
#else
- wxPoint *cpoints = new wxPoint[m_n];
- int i;
- for (i = 0; i < m_n; i++)
- {
- cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs);
- cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs);
- }
- wxMemoryDC *dc = m_owner->GetDC();
- dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
dc->SetPen(m_pen);
- dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
- delete [] cpoints;
+ int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
+ int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
+ int w = m_admin->LogicalToDeviceXRel( m_width );
+ int h = m_admin->LogicalToDeviceYRel( m_height );
+ if (w > 0 && w < 1) w=1;
+ if (w < 0 && w > -1) w=-1;
+ if (h > 0 && h < 1) h=1;
+ if (h < 0 && h > -1) h=-1;
+ dc->DrawEllipse( x,y,w,h);
dc->SetBrush(wxNullBrush);
dc->SetPen(wxNullPen);
dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
#endif
}
-void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream )
+void wxCanvasEllipse::WriteSVG( wxTextOutputStream &stream )
{
}
-
+wxCanvasObject* wxCanvasEllipse::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ double a=(m_width+m_pen.GetWidth())/2+margin ;
+ double b=(m_height+m_pen.GetWidth())/2+margin;
+ double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2);
+ if ( 1 > c)
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
//----------------------------------------------------------------------------
-// wxCanvasRect
+// wxCanvasEllipticArc
//----------------------------------------------------------------------------
-wxCanvasRect::wxCanvasRect( double x, double y, double w, double h )
+wxCanvasEllipticArc::wxCanvasEllipticArc( double x, double y, double width, double height, double start, double end )
: wxCanvasObject()
{
m_x = x;
m_y = y;
- m_width = w;
- m_height = h;
+ m_width = width;
+ m_height = height;
+ m_start = start;
+ m_end = end;
m_brush = *wxBLACK_BRUSH;
m_pen = *wxTRANSPARENT_PEN;
+ CalcBoundingBox();
}
-void wxCanvasRect::Recreate()
+void wxCanvasEllipticArc::TransLate( double x, double y )
{
- SetArea( m_owner->GetDeviceX( m_x ),
- m_owner->GetDeviceY( m_y ),
- m_owner->GetDeviceWidth( m_width ),
- m_owner->GetDeviceHeight( m_height ) );
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
}
-void wxCanvasRect::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasEllipticArc::CalcBoundingBox()
{
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
+ m_bbox.SetMin( m_x, m_y );
+ m_bbox.SetMax( m_x+m_width , m_y+m_height );
-#if IMAGE_CANVAS
- wxImage *image = m_owner->GetBuffer();
-
- int start_y = clip_y - buffer_y;
- int end_y = clip_y+clip_height - buffer_y;
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth()/2);
+}
- int start_x = clip_x - buffer_x;
- int end_x = clip_x+clip_width - buffer_x;
+void wxCanvasEllipticArc::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
- // speed up later
- for (int y = start_y; y < end_y; y++)
- for (int x = start_x; x < end_x; x++)
- image->SetRGB( x, y, m_red, m_green, m_blue );
+#if IMAGE_CANVAS
#else
- wxMemoryDC *dc = m_owner->GetDC();
- dc->SetPen( m_pen );
- dc->SetBrush( m_brush );
- dc->DrawRectangle( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
+ int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
+ int w = m_admin->LogicalToDeviceXRel( m_width );
+ int h = m_admin->LogicalToDeviceYRel( m_height );
+ if (w > 0 && w < 1) w=1;
+ if (w < 0 && w > -1) w=-1;
+ if (h > 0 && h < 1) h=1;
+ if (h < 0 && h > -1) h=-1;
+ if (m_admin->GetActive()->GetYaxis())
+ dc->DrawEllipticArc( x,y,w,h,-m_end,-m_start);
+ else
+ dc->DrawEllipticArc( x,y,w,h,m_start,m_end);
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
#endif
}
-void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
+void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasEllipticArc::IsHitWorld( double x, double y, double margin )
{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ double a=(m_width+m_pen.GetWidth())/2+margin ;
+ double b=(m_height+m_pen.GetWidth())/2+margin;
+ double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2);
+ if ( 1 > c)
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
}
//----------------------------------------------------------------------------
m_y2 = y2;
m_pen = *wxBLACK_PEN;
+ CalcBoundingBox();
}
-void wxCanvasLine::Recreate()
+void wxCanvasLine::TransLate( double x, double y )
{
- int x1 = m_owner->GetDeviceX( m_x1 );
- int y1 = m_owner->GetDeviceY( m_y1 );
- int x2 = m_owner->GetDeviceX( m_x2 );
- int y2 = m_owner->GetDeviceY( m_y2 );
- if (x1 > x2)
- {
- int tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y1 > y2)
- {
- int tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- SetArea( x1, y1, x2-x1+1, y2-y1+1 );
+ m_x1 += x;
+ m_y1 += y;
+ m_x2 += x;
+ m_y2 += y;
+ CalcBoundingBox();
+}
+
+void wxCanvasLine::CalcBoundingBox()
+{
+ m_bbox.SetMin( m_x1 , m_y1);
+ m_bbox.SetMax( m_x2 , m_y2);
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth()/2);
}
-void wxCanvasLine::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasLine::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
{
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
+ if (!m_visible) return;
- int x1 = xabs + m_owner->GetDeviceX( m_x1 );
- int y1 = yabs + m_owner->GetDeviceY( m_y1 );
- int x2 = xabs + m_owner->GetDeviceX( m_x2 );
- int y2 = yabs + m_owner->GetDeviceY( m_y2 );
+ double x1,y1,x2,y2;
+ cworld->TransformPoint( m_x1, m_y1, x1, y1 );
+ cworld->TransformPoint( m_x2, m_y2, x2, y2 );
+ x1 = m_admin->LogicalToDeviceX( x1 );
+ y1 = m_admin->LogicalToDeviceY( y1 );
+ x2 = m_admin->LogicalToDeviceX( x2 );
+ y2 = m_admin->LogicalToDeviceY( y2 );
#if IMAGE_CANVAS
- wxImage *image = m_owner->GetBuffer();
- if ((m_area.width == 0) && (m_area.height == 0))
+ wxRect tmparea;
+ tmparea.x = m_admin->LogicalToDeviceXRel( m_bbox.GetMinX());
+ tmparea.y = m_admin->LogicalToDeviceYRel( m_bbox.GetMinY());
+ tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() );
+ tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() );
+ wxImage *image = m_admin->GetActive()->GetBuffer();
+ if ((tmparea.width == 0) && (tmparea.height == 0))
{
- image->SetRGB( m_area.x-buffer_x, m_area.y-buffer_y, m_red, m_green, m_blue );
+ int red=m_pen.GetColour().Red();
+ int green=m_pen.GetColour().Green();
+ int blue=m_pen.GetColour().Blue();
+ image->SetRGB( tmparea.x, tmparea.y, red, green, blue );
}
else
{
+ int red=m_pen.GetColour().Red();
+ int green=m_pen.GetColour().Green();
+ int blue=m_pen.GetColour().Blue();
wxInt32 d, ii, jj, di, ai, si, dj, aj, sj;
di = x1 - x2;
ai = abs(di) << 1;
if ((ii >= clip_x) && (ii < clip_x+clip_width) &&
(jj >= clip_y) && (jj < clip_y+clip_height))
{
- image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green );
+ image->SetRGB( ii, jj, red, blue, green );
}
if (d >= 0)
{
if ((ii >= clip_x) && (ii < clip_x+clip_width) &&
(jj >= clip_y) && (jj < clip_y+clip_height))
{
- image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green );
+ image->SetRGB( ii, jj, red, blue, green );
}
if (d >= 0)
{
}
}
#else
- wxMemoryDC *dc = m_owner->GetDC();
- dc->SetClippingRegion( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
dc->SetPen( m_pen );
- dc->DrawLine( x1-buffer_x, y1-buffer_y, x2-buffer_x, y2-buffer_y );
+ dc->DrawLine( x1, y1, x2, y2 );
dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
#endif
}
// no idea
}
+wxCanvasObject* wxCanvasLine::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxLine line1(m_x1,m_y1,m_x2,m_y2);
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ double distance;
+ if (line1.PointInLine(P,distance,m_pen.GetWidth()/2+margin) == R_IN_AREA)
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
//----------------------------------------------------------------------------
// wxCanvasImage
//----------------------------------------------------------------------------
m_height = h;
m_image = image;
+
+ m_orgw=m_image.GetWidth();
+ m_orgh=m_image.GetHeight();
+
m_isImage = TRUE;
+ m_visible = FALSE;
+//KKK m_visible=TRUE;
+ CalcBoundingBox();
}
-void wxCanvasImage::Recreate()
+void wxCanvasImage::TransLate( double x, double y )
{
- SetArea( m_owner->GetDeviceX( m_x ),
- m_owner->GetDeviceY( m_y ),
- m_owner->GetDeviceWidth( m_width ),
- m_owner->GetDeviceHeight( m_height ) );
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
+}
+
+void wxCanvasImage::CalcBoundingBox()
+{
+ m_bbox.SetMin( m_x , m_y);
+ m_bbox.SetMax( m_x + m_width , m_y + m_height);
+}
+
+void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ wxRect tmparea;
+
+ tmparea.x = m_admin->LogicalToDeviceXRel( m_bbox.GetMinX());
+ tmparea.y = m_admin->LogicalToDeviceYRel( m_bbox.GetMinY());
+ tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() );
+ tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() );
+
+ double x;
+ double y;
+ cworld->TransformPoint( m_x, m_y, x, y );
+ x = m_admin->LogicalToDeviceX(x);
+ y = m_admin->LogicalToDeviceY(y);
+
#if IMAGE_CANVAS
- if ((m_area.width == m_image.GetWidth()) &&
- (m_area.width == m_image.GetWidth()))
+ if ((clip_x == xabs + tmparea.x) &&
+ (clip_y == yabs + tmparea.y) &&
+ (clip_width == tmparea.width) &&
+ (clip_height == tmparea.height))
{
- m_tmp = m_image;
+ m_admin->GetActive()->GetBuffer()->Paste( m_tmp, clip_x, clip_y );
}
else
{
- m_tmp = m_image.Scale( m_area.width, m_area.height );
+ // local coordinates
+ int start_x = clip_x - (xabs + tmparea.x);
+ int start_y = clip_y - (yabs + tmparea.y);
+
+ wxRect rect( start_x, start_y, clip_width, clip_height );
+ wxImage sub_image( m_tmp.GetSubImage( rect ) );
+ m_admin->GetActive()->GetBuffer()->Paste( sub_image, clip_x, clip_y );
}
#else
- if ((m_area.width == m_image.GetWidth()) &&
- (m_area.width == m_image.GetWidth()))
+ if ( m_orgw*5 < m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) ||
+ m_orgw/5 > m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) ||
+ m_orgh*5 < m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) ||
+ m_orgh/5 > m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() )
+ )
+ {
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
+ dc->SetBrush(*wxTRANSPARENT_BRUSH);
+ dc->SetPen(*wxBLACK_PEN);
+ //yes the whole not only the clipping region, because we have a pen also
+ int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
+ int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
+ int w = m_admin->LogicalToDeviceXRel( m_width );
+ int h = m_admin->LogicalToDeviceYRel( m_height );
+ if (w < 1) w=1;
+ if (h < 1) h=1;
+ dc->DrawRectangle( x,y,w,h);
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ return;
+ }
+
+ if ((m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) == m_image.GetWidth()) &&
+ (m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) == m_image.GetHeight()))
{
- m_tmp = m_image.ConvertToBitmap();
+ m_tmp = m_image;
}
else
{
- wxImage tmp( m_image.Scale( m_area.width, m_area.height ) );
- m_tmp = tmp.ConvertToBitmap();
+ m_tmp = m_image.Scale( m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()),
+ m_admin->LogicalToDeviceYRel( m_bbox.GetHeight()) );
}
-#endif
-}
-void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
-{
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
+ wxBitmap bmp;
+// wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
+ wxPoint centr(0,0);
-#if IMAGE_CANVAS
- if ((clip_x == xabs + m_area.x) &&
- (clip_y == yabs + m_area.y) &&
- (clip_width == m_area.width) &&
- (clip_height == m_area.height))
+ if (cworld->GetRotation())
{
- m_owner->GetBuffer()->Paste( m_tmp, clip_x-buffer_x, clip_y-buffer_y );
+ bmp=m_tmp.Rotate(-cworld->GetRotation()/180.0 * pi,centr, TRUE, NULL).ConvertToBitmap();
}
else
{
- // local coordinates
- int start_x = clip_x - (xabs + m_area.x);
- int start_y = clip_y - (yabs + m_area.y);
-
- wxRect rect( start_x, start_y, clip_width, clip_height );
- wxImage sub_image( m_tmp.GetSubImage( rect ) );
- m_owner->GetBuffer()->Paste( sub_image, clip_x-buffer_x, clip_y-buffer_y );
+ bmp = m_tmp.ConvertToBitmap();
}
-#else
- wxMemoryDC *dc = m_owner->GetDC();
- if ((clip_x == xabs + m_area.x) &&
- (clip_y == yabs + m_area.y) &&
- (clip_width == m_area.width) &&
- (clip_height == m_area.height))
+ wxDC *dc = m_admin->GetActive()->GetDC();
+
+ wxPoint centr2;
+ if (cworld->GetRotation()> 0)
{
- dc->DrawBitmap( m_tmp, clip_x-buffer_x, clip_y-buffer_y, TRUE );
+ centr2.x= (int) (x+m_height*sin(-cworld->GetRotation()/180.0 * pi));
+ centr2.y= (int) y;
}
else
{
- // local coordinates
- int start_x = clip_x - (xabs + m_area.x);
- int start_y = clip_y - (yabs + m_area.y);
+ centr2.x= (int) x;
+ centr2.y= (int) (y-m_width*sin(-cworld->GetRotation()/180.0 * pi));
+ }
- // Clipping region faster ?
- wxRect rect( start_x, start_y, clip_width, clip_height );
- wxBitmap sub_bitmap( m_tmp.GetSubBitmap( rect ) );
- dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y, TRUE );
+ if (cworld->GetRotation() != 0)
+ {
+ //TODO clipping not right
+ dc->DrawBitmap(bmp,centr2,TRUE );
+// dc->DrawPoint(centr2);
+// dc->DrawPoint(x,y);
+ }
+ else
+ {
+ //TODO clipping not right
+// dc->DrawPoint(centr2);
+// dc->DrawPoint(x,y);
+
+ if ((clip_x == x) &&
+ (clip_y == y) &&
+ (clip_width == tmparea.width) &&
+ (clip_height == tmparea.height))
+ {
+ dc->DrawBitmap( m_tmp, clip_x, clip_y, TRUE );
+ }
+ else
+ {
+ int start_x = clip_x - (int)x;
+ int start_y = clip_y - (int)y;
+
+ //dc->DrawBitmap( bmp, x, y, TRUE );
+ wxMemoryDC dcm;
+ dcm.SelectObject(bmp);
+ dc->Blit(clip_x, clip_y,clip_width, clip_height,&dcm,start_x,start_y,wxCOPY,TRUE);
+ dcm.SelectObject(wxNullBitmap);
+ }
}
#endif
}
{
m_isControl = TRUE;
m_control = control;
+ CalcBoundingBox();
+}
+
+double wxCanvasControl::GetPosX()
+{
+ int x,y ;
+ m_control->GetPosition( &x, &y );
+ return m_admin->DeviceToLogicalX(x);
+}
+
+double wxCanvasControl::GetPosY()
+{
+ int x,y ;
+ m_control->GetPosition( &x, &y );
+ return m_admin->DeviceToLogicalY(y);
+}
+
+void wxCanvasControl::SetPosXY( double x, double y)
+{
+ int xd = m_admin->LogicalToDeviceX(x);
+ int yd = m_admin->LogicalToDeviceY(y);
+ m_control->Move(xd,yd);
+}
+
+
+void wxCanvasControl::TransLate( double x, double y )
+{
+ int xdo,ydo;
+ m_control->GetPosition( &xdo, &ydo );
+ int xd = m_admin->LogicalToDeviceX(x)-xdo;
+ int yd = m_admin->LogicalToDeviceY(y)-ydo;
+ m_control->Move(xd,yd);
+ CalcBoundingBox();
}
wxCanvasControl::~wxCanvasControl()
m_control->Destroy();
}
-void wxCanvasControl::Recreate()
+void wxCanvasControl::CalcBoundingBox()
{
- m_control->GetSize( &m_area.width, &m_area.height );
- m_control->GetPosition( &m_area.x, &m_area.y );
+ wxRect tmparea;
+
+ m_control->GetSize( &tmparea.width, &tmparea.height );
+ m_control->GetPosition( &tmparea.x, &tmparea.y );
+
+ m_bbox.SetMin( tmparea.x , tmparea.y);
+ m_bbox.SetMax( tmparea.x + tmparea.width , tmparea.y + tmparea.height);
+
}
-void wxCanvasControl::Move( int x, int y )
+void wxCanvasControl::MoveRelative( double x, double y )
{
- m_control->Move( x, y );
+ m_control->Move( m_admin->LogicalToDeviceX(x), m_admin->LogicalToDeviceX(y) );
}
//----------------------------------------------------------------------------
96, // screen dpi
96 );
#endif
+ CalcBoundingBox();
}
wxCanvasText::~wxCanvasText()
m_flag = flag;
}
-void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasText::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
{
+ if (!m_visible) return;
+
+ wxRect tmparea;
+ tmparea.x = m_admin->LogicalToDeviceX( m_bbox.GetMinX());
+ tmparea.y = m_admin->LogicalToDeviceY( m_bbox.GetMinY());
+ tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() );
+ tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() );
+
+ m_alpha = new unsigned char[tmparea.width*tmparea.height];
+ memset( m_alpha, 0, tmparea.width*tmparea.height );
+
if (!m_alpha) return;
- int buffer_x = m_owner->GetBufferX();
- int buffer_y = m_owner->GetBufferY();
-
+#if wxUSE_FREETYPE
+ FT_Face face = ((wxFaceData*)m_faceData)->m_face;
+ FT_GlyphSlot slot = face->glyph;
+ int pen_x = 0;
+ int pen_y = m_size;
+
+ for (int n = 0; n < (int)m_text.Len(); n++)
+ {
+ FT_UInt index = FT_Get_Char_Index( face, m_text[(unsigned int)n] );
+
+ int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
+ if (error) continue;
+
+ error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
+ if (error) continue;
+
+ FT_Bitmap *bitmap = &slot->bitmap;
+ unsigned char* buffer = bitmap->buffer;
+ for (int y = 0; y < bitmap->rows; y++)
+ for (int x = 0; x < bitmap->width; x++)
+ {
+ unsigned char alpha = buffer[ y*bitmap->pitch + x ];
+ if (alpha == 0) continue;
+
+ int xx = pen_x + slot->bitmap_left + x;
+ int yy = pen_y - slot->bitmap_top + y;
+ m_alpha[ yy * tmparea.width + xx ] = alpha;
+ }
+
+ pen_x += slot->advance.x >> 6;
+ pen_y += slot->advance.y >> 6;
+ }
+#endif
+
#if IMAGE_CANVAS
- wxImage *image = m_owner->GetBuffer();
+ wxImage *image = m_admin->GetActive()->GetBuffer();
// local coordinates
- int start_x = clip_x - m_area.x;
+ int start_x = clip_x - tmparea.x;
int end_x = clip_width + start_x;
- int start_y = clip_y - m_area.y;
+ int start_y = clip_y - tmparea.y;
int end_y = clip_height + start_y;
for (int y = start_y; y < end_y; y++)
for (int x = start_x; x < end_x; x++)
{
- int alpha = m_alpha[y*m_area.width + x];
+ int alpha = m_alpha[y*tmparea.width + x];
if (alpha)
{
- int image_x = m_area.x+x - buffer_x;
- int image_y = m_area.y+y - buffer_y;
+ int image_x = tmparea.x+x;
+ int image_y = tmparea.y+y;
if (alpha == 255)
{
image->SetRGB( image_x, image_y, m_red, m_green, m_blue );
}
}
#else
- wxBitmap *bitmap = m_owner->GetBuffer();
- wxRect sub_rect( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+ wxBitmap *bitmap = m_admin->GetActive()->GetBuffer();
+ wxRect sub_rect( clip_x, clip_y, clip_width, clip_height );
wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) );
-
+
wxImage image( sub_bitmap );
// local coordinates
- int start_x = clip_x - m_area.x;
+ int start_x = clip_x - tmparea.x;
int end_x = clip_width + start_x;
- int start_y = clip_y - m_area.y;
+ int start_y = clip_y - tmparea.y;
int end_y = clip_height + start_y;
for (int y = start_y; y < end_y; y++)
for (int x = start_x; x < end_x; x++)
{
- int alpha = m_alpha[y*m_area.width + x];
+ int alpha = m_alpha[y*tmparea.width + x];
if (alpha)
{
int image_x = x - start_x;
image.SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
}
}
-
+
sub_bitmap = image.ConvertToBitmap();
-
- wxMemoryDC *dc = m_owner->GetDC();
- dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y );
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->DrawBitmap( sub_bitmap, clip_x, clip_y );
#endif
}
{
}
-void wxCanvasText::Recreate()
+void wxCanvasText::TransLate( double x, double y )
{
- if (m_alpha) delete [] m_alpha;
+ m_x += x;
+ m_y += y;
+ CalcBoundingBox();
+}
- m_area.x = m_owner->GetDeviceX( m_x );
- m_area.y = m_owner->GetDeviceY( m_y );
+void wxCanvasText::CalcBoundingBox()
+{
+ if (m_alpha) delete [] m_alpha;
- m_area.width = 100; // TODO calculate length
- m_area.height = m_size + (m_size/2); // TODO space for sub-baseline (pgypq)
- m_alpha = new unsigned char[m_area.width*m_area.height];
- memset( m_alpha, 0, m_area.width*m_area.height );
+ m_bbox.SetMin( m_x , m_y);
+ m_bbox.SetMax( m_x + 100 , m_y + m_size + (m_size/2));
-#if wxUSE_FREETYPE
- FT_Face face = ((wxFaceData*)m_faceData)->m_face;
- FT_GlyphSlot slot = face->glyph;
- int pen_x = 0;
- int pen_y = m_size;
- for (int n = 0; n < (int)m_text.Len(); n++)
- {
- FT_UInt index = FT_Get_Char_Index( face, m_text[n] );
+}
- int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
- if (error) continue;
+//----------------------------------------------------------------------------
+// wxCanvas
+//----------------------------------------------------------------------------
- error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
- if (error) continue;
+IMPLEMENT_CLASS(wxCanvas,wxWindow)
- FT_Bitmap *bitmap = &slot->bitmap;
- unsigned char* buffer = bitmap->buffer;
- for (int y = 0; y < bitmap->rows; y++)
- for (int x = 0; x < bitmap->width; x++)
- {
- unsigned char alpha = buffer[ y*bitmap->pitch + x ];
- if (alpha == 0) continue;
-
- int xx = pen_x + slot->bitmap_left + x;
- int yy = pen_y - slot->bitmap_top + y;
- m_alpha[ yy * m_area.width + xx ] = alpha;
- }
-
- pen_x += slot->advance.x >> 6;
- pen_y += slot->advance.y >> 6;
- }
-#endif
-}
-
-//----------------------------------------------------------------------------
-// wxCanvas
-//----------------------------------------------------------------------------
-
-IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
-
-BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
+BEGIN_EVENT_TABLE(wxCanvas,wxWindow)
+ EVT_SCROLLWIN( wxCanvas::OnScroll )
EVT_CHAR( wxCanvas::OnChar )
EVT_PAINT( wxCanvas::OnPaint )
EVT_SIZE( wxCanvas::OnSize )
EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground )
END_EVENT_TABLE()
-wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id,
+wxCanvas::wxCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id,
const wxPoint &position, const wxSize& size, long style ) :
- wxScrolledWindow( parent, id, position, size, style )
+ wxWindow( parent, id, position, size, style )
{
- m_bufferX = 0;
- m_bufferY = 0;
+ m_admin = admin;
+ m_admin->Append(this);
m_needUpdate = FALSE;
- m_red = 0;
- m_green = 0;
- m_blue = 0;
+ m_background = *wxWHITE;
m_lastMouse = (wxCanvasObject*)NULL;
m_captureMouse = (wxCanvasObject*)NULL;
m_frozen = TRUE;
m_oldDeviceX = 0;
m_oldDeviceY = 0;
-
- //root group always at 0,0
- m_root = new wxCanvasObjectGroup();
- m_root->DeleteContents( TRUE );
- m_root->SetOwner(this);
+ m_scrolled=FALSE;
+ m_root=0;
+ m_yaxis=FALSE;
}
wxCanvas::~wxCanvas()
}
}
-void wxCanvas::SetArea( int width, int height )
-{
- SetScrollbars( 10, 10, width/10, height/10 );
-}
-
-void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char blue )
+void wxCanvas::SetColour( const wxColour& background )
{
- m_red = red;
- m_green = green;
- m_blue = blue;
-
- SetBackgroundColour( wxColour( red, green, blue ) );
+ m_background=background;
+ SetBackgroundColour( m_background );
if (m_frozen) return;
#if IMAGE_CANVAS
+ unsigned char red = background.Red();
+ unsigned char green = background.Green();
+ unsigned char blue = background.Blue();
+
unsigned char *data = m_buffer.GetData();
for (int y = 0; y < m_buffer.GetHeight(); y++)
wxMemoryDC dc;
dc.SelectObject( m_buffer );
dc.SetPen( *wxTRANSPARENT_PEN );
- wxBrush brush( wxColour( red,green,blue), wxSOLID );
+ wxBrush brush( m_background, wxSOLID );
dc.SetBrush( brush );
dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
dc.SelectObject( wxNullBitmap );
m_frozen = FALSE;
if (m_buffer.Ok())
- Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight() );
+ Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight() );
}
void wxCanvas::Update( int x, int y, int width, int height, bool blit )
{
- CalcScrolledPosition( 0, 0, &m_oldDeviceX, &m_oldDeviceY );
-
+ m_admin->SetActive(this);
+
+ if (!m_root) return;
+
if (m_frozen) return;
// clip to buffer
- if (x < m_bufferX)
+ if (x < 0)
{
- width -= m_bufferX-x;
- x = m_bufferX;
+ width -= -x;
+ x = 0;
}
if (width <= 0) return;
- if (y < m_bufferY)
+ if (y < 0)
{
- height -= m_bufferY-y;
- y = m_bufferY;
+ height -= -y;
+ y = 0;
}
if (height <= 0) return;
- if (x+width > m_bufferX+m_buffer.GetWidth())
+ if (x+width > m_buffer.GetWidth())
{
- width = m_bufferX+m_buffer.GetWidth() - x;
+ width = m_buffer.GetWidth() - x;
}
if (width <= 0) return;
- if (y+height > m_bufferY+m_buffer.GetHeight())
+ if (y+height > m_buffer.GetHeight())
{
- height = m_bufferY+m_buffer.GetHeight() - y;
+ height = m_buffer.GetHeight() - y;
}
if (height <= 0) return;
(wxObject*) new wxRect( x,y,width,height ) );
}
+ wxTransformMatrix cworld;
+
#if IMAGE_CANVAS
// speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
- int start_y = y - m_bufferY;
- int end_y = y+height - m_bufferY;
- int start_x = x - m_bufferX;
- int end_x = x+width - m_bufferX;
+ int start_y = y;
+ int end_y = y+height;
+ int start_x = x;
+ int end_x = x+width;
+ int red=m_background.Red();
+ int green=m_background.Green();
+ int blue=m_background.Blue();
for (int yy = start_y; yy < end_y; yy++)
for (int xx = start_x; xx < end_x; xx++)
- m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
+ m_buffer.SetRGB( xx, yy, red, green, blue );
- m_root->Render(0,0, x, y, width, height );
+ m_root->Render(&cworld, x, y, width, height );
#else
wxMemoryDC dc;
dc.SelectObject( m_buffer );
+
dc.SetPen( *wxTRANSPARENT_PEN );
- wxBrush brush( wxColour( m_red,m_green,m_blue), wxSOLID );
+ wxBrush brush( m_background , wxSOLID );
dc.SetBrush( brush );
- dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height );
- m_renderDC = &dc;
- m_root->Render(0,0, x, y, width, height );
+ if (width != m_buffer.GetWidth() && height != m_buffer.GetHeight())
+ {
+ dc.SetLogicalFunction(wxCOPY);
+ dc.SetClippingRegion(x,y,width,height);
+ dc.DrawRectangle(x-2,y-2,width+4,height+4);
+ dc.DestroyClippingRegion();
+ }
+ else
+ {
+ dc.Clear();
+ dc.SetLogicalFunction(wxCOPY);
+ dc.DrawRectangle(0,0,m_buffer.GetWidth(),m_buffer.GetHeight());
+ }
+ dc.SetBrush(wxNullBrush);
+ dc.SetPen(wxNullPen);
+
+ m_renderDC=&dc;
+
+ m_root->Render(&cworld,x, y, width, height );
+ m_renderDC=0;
dc.SelectObject( wxNullBitmap );
#endif
}
{
wxRect *rect = (wxRect*) node->Data();
- wxRect sub_rect( *rect );
- sub_rect.x -= m_bufferX;
- sub_rect.y -= m_bufferY;
-
#if IMAGE_CANVAS
- wxImage sub_image( m_buffer.GetSubImage( sub_rect ) );
+ wxImage sub_image( m_buffer.GetSubImage( *rect ) );
#ifdef __WXGTK__
int bpp = wxDisplayDepth();
if (bpp > 8)
// Maybe clipping use SetClipping() is faster than
// getting the subrect first and drawing it then?
- wxBitmap sub_bitmap( m_buffer.GetSubBitmap( sub_rect ) );
- dc.DrawBitmap( sub_bitmap, rect->x, rect->y );
+
+// wxBitmap sub_bitmap( m_buffer.GetSubBitmap( *rect ) );
+// dc.DrawBitmap( sub_bitmap, rect->x, rect->y );
+
+ wxMemoryDC mdc;
+ mdc.SelectObject( m_buffer );
+ dc.Blit (rect->x, rect->y , rect->GetWidth(), rect->GetHeight(),&mdc, rect->x, rect->y );
+ mdc.SelectObject( wxNullBitmap );
#endif
delete rect;
BlitBuffer( dc );
}
-int wxCanvas::GetDeviceX( double x )
-{
- return (int) x;
-}
-
-int wxCanvas::GetDeviceY( double y )
-{
- return (int) y;
-}
-
-int wxCanvas::GetDeviceWidth( double width )
-{
- return (int) width;
-}
-
-int wxCanvas::GetDeviceHeight( double height )
-{
- return (int) height;
-}
-
-void wxCanvas::Recreate()
-{
- m_root->Recreate();
-}
-
-void wxCanvas::Prepend( wxCanvasObject* obj )
-{
- m_root->Prepend( obj );
- obj->SetOwner(this);
-
- m_root->Recreate();
-
- if (!obj->IsControl())
- Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
-}
-
-void wxCanvas::Append( wxCanvasObject* obj )
-{
- m_root->Append( obj );
- obj->SetOwner(this);
-
- m_root->Recreate();
-
- if (!obj->IsControl())
- Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
-}
-
-void wxCanvas::Insert( size_t before, wxCanvasObject* obj )
-{
- m_root->Insert( before, obj );
- obj->SetOwner(this);
-
- m_root->Recreate();
-
- if (!obj->IsControl())
- Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
-}
-
-void wxCanvas::Remove( wxCanvasObject* obj )
-{
- int x = obj->GetX();
- int y = obj->GetY();
- int w = obj->GetWidth();
- int h = obj->GetHeight();
- bool ic = obj->IsControl();
-
- m_root->Remove( obj );
-
- if (!ic)
- Update( x, y, w, h );
-}
-
void wxCanvas::OnPaint(wxPaintEvent &event)
{
wxPaintDC dc(this);
if ((w > 0) && (h > 0))
{
- CalcUnscrolledPosition( x, y, &x, &y );
m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
}
{
// If any updates are pending, do them now since they will
// expect the previous m_bufferX and m_bufferY as well as
- // the previous device origin values.
+ // the previous device origin values.
wxClientDC dc( this );
dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
BlitBuffer( dc );
- // The buffer always starts at the top left corner of the
- // client area. Indeed, it is the client area.
- CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
+ if (dy != 0)
+ {
+ double dyv=DeviceToLogicalYRel(dy);
+ m_virt_minY=m_virt_minY-dyv;
+ m_virt_maxY=m_virt_maxY-dyv;
+ }
+ if (dx != 0)
+ {
+ double dxv=DeviceToLogicalXRel(dx);
+ m_virt_minX=m_virt_minX-dxv;
+ m_virt_maxX=m_virt_maxX-dxv;
+ }
+
+ m_admin->SetActive(this);
+ SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE);
#if IMAGE_CANVAS
unsigned char* data = m_buffer.GetData();
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
- Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), dy, FALSE );
+ Update( 0, 0, m_buffer.GetWidth(), dy, FALSE );
}
else
{
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
- Update( m_bufferX, m_bufferY+m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE );
+ Update( 0, m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE );
}
}
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
- Update( m_bufferX, m_bufferY, dx, m_buffer.GetHeight(), FALSE );
+ Update( 0,0, dx, m_buffer.GetHeight(), FALSE );
}
else
{
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
- Update( m_bufferX+m_buffer.GetWidth()+dx, m_bufferY, -dx, m_buffer.GetHeight(), FALSE );
+ Update( m_buffer.GetWidth()+dx, 0, -dx, m_buffer.GetHeight(), FALSE );
}
}
#else
- // Update everything, TODO: scrolling
- Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
-#endif
+ if (dy != 0)
+ {
+ if (dy > 0 && dy < m_buffer.GetHeight())
+ {
+ wxRect rect( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight()-dy);
+ wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
+ wxMemoryDC dcm;
+ dcm.SelectObject( m_buffer );
+ dcm.DrawBitmap( sub_bitmap, 0, dy, TRUE );
+ dcm.SelectObject( wxNullBitmap );
+
+ Update( 0, 0, m_buffer.GetWidth(), dy, TRUE );
+ }
+ else if (dy < 0 && dy > -m_buffer.GetHeight())
+ {
+ wxRect rect( 0, -dy, m_buffer.GetWidth(), m_buffer.GetHeight()+dy);
+ wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
+ wxMemoryDC dcm;
+ dcm.SelectObject( m_buffer );
+ dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE );
+ dcm.SelectObject( wxNullBitmap );
+
+ Update( 0, m_buffer.GetHeight()+dy, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
+ }
+ else
+ Update( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
+ }
+
+ if (dx != 0)
+ {
+ if (dx > 0 && dx < m_buffer.GetWidth())
+ {
+ wxRect rect( 0, 0, m_buffer.GetWidth()-dx, m_buffer.GetHeight());
+ wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
+ wxMemoryDC dcm;
+ dcm.SelectObject( m_buffer );
+ dcm.DrawBitmap( sub_bitmap, dx, 0, TRUE );
+ dcm.SelectObject( wxNullBitmap );
+
+ Update( 0, 0, dx, m_buffer.GetHeight(), TRUE );
+ }
+ else if (dx < 0 && dx > -m_buffer.GetWidth())
+ {
+ wxRect rect( -dx, 0, m_buffer.GetWidth()+dx, m_buffer.GetHeight());
+ wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
+ wxMemoryDC dcm;
+ dcm.SelectObject( m_buffer );
+ dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE );
+ dcm.SelectObject( wxNullBitmap );
+
+ Update( m_buffer.GetWidth()+dx, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
+ }
+ else
+ Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
+ }
+#endif
wxWindow::ScrollWindow( dx, dy, rect );
+
+ //must be done now because quick repeated scrolling will prevent wxPaint
+ //from doing it properly
+ UpdateNow();
}
void wxCanvas::OnMouse(wxMouseEvent &event)
{
+ m_admin->SetActive(this);
+ if (!m_root)
+ {
+ event.Skip();
+ return;
+ }
+
int x = event.GetX();
int y = event.GetY();
- CalcUnscrolledPosition( x, y, &x, &y );
+
+ //to world coordinates to do hit test in world coordinates
+ double xw = DeviceToLogicalX( x );
+ double yw = DeviceToLogicalY( y );
+
+ //make a select margin of 2 pixels, so also zero line thickness will be hit
+ double margin = DeviceToLogicalXRel( 2 );
if (event.GetEventType() == wxEVT_MOTION)
{
{
wxMouseEvent child_event( wxEVT_MOTION );
child_event.SetEventObject(m_captureMouse);
- child_event.m_x = x - m_captureMouse->GetX();
- child_event.m_y = y - m_captureMouse->GetY();
+ child_event.m_x = x;
+ child_event.m_y = y;
child_event.m_leftDown = event.m_leftDown;
child_event.m_rightDown = event.m_rightDown;
child_event.m_middleDown = event.m_middleDown;
child_event.m_shiftDown = event.m_shiftDown;
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
-
- m_captureMouse->ProcessEvent( child_event );
+
+ m_captureMouse->ProcessCanvasObjectEvent( child_event );
return;
}
else
{
- wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
+ wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin);
if (obj && !obj->IsControl())
{
wxMouseEvent child_event( wxEVT_MOTION );
child_event.SetEventObject( obj );
- child_event.m_x = x - obj->GetX();
- child_event.m_y = y - obj->GetY();
+ child_event.m_x = x;
+ child_event.m_y = y;
child_event.m_leftDown = event.m_leftDown;
child_event.m_rightDown = event.m_rightDown;
child_event.m_middleDown = event.m_middleDown;
{
child_event.SetEventType( wxEVT_LEAVE_WINDOW );
child_event.SetEventObject( m_lastMouse );
- child_event.m_x = x - m_lastMouse->GetX();
- child_event.m_y = y - m_lastMouse->GetY();
- m_lastMouse->ProcessEvent( child_event );
+ child_event.m_x = x;
+ child_event.m_y = y;
+ m_lastMouse->ProcessCanvasObjectEvent( child_event );
m_lastMouse = obj;
child_event.SetEventType( wxEVT_ENTER_WINDOW );
child_event.SetEventObject( m_lastMouse );
- child_event.m_x = x - m_lastMouse->GetX();
- child_event.m_y = y - m_lastMouse->GetY();
- m_lastMouse->ProcessEvent( child_event );
+ child_event.m_x = x;
+ child_event.m_y = y;
+ m_lastMouse->ProcessCanvasObjectEvent( child_event );
child_event.SetEventType( wxEVT_MOTION );
child_event.SetEventObject( obj );
}
-
- obj->ProcessEvent( child_event );
+
+ obj->ProcessCanvasObjectEvent( child_event );
return;
}
}
{
wxMouseEvent child_event( wxEVT_LEAVE_WINDOW );
child_event.SetEventObject( m_lastMouse );
- child_event.m_x = x - m_lastMouse->GetX();
- child_event.m_y = y - m_lastMouse->GetY();
+ child_event.m_x = x;
+ child_event.m_y = y;
child_event.m_leftDown = event.m_leftDown;
child_event.m_rightDown = event.m_rightDown;
child_event.m_middleDown = event.m_middleDown;
child_event.m_shiftDown = event.m_shiftDown;
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
- m_lastMouse->ProcessEvent( child_event );
+ m_lastMouse->ProcessCanvasObjectEvent( child_event );
m_lastMouse = (wxCanvasObject*) NULL;
return;
{
wxMouseEvent child_event( event.GetEventType() );
child_event.SetEventObject(m_captureMouse);
- child_event.m_x = x - m_captureMouse->GetX();
- child_event.m_y = y - m_captureMouse->GetY();
+ child_event.m_x = x;
+ child_event.m_y = y;
child_event.m_leftDown = event.m_leftDown;
child_event.m_rightDown = event.m_rightDown;
child_event.m_middleDown = event.m_middleDown;
child_event.m_shiftDown = event.m_shiftDown;
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
- m_captureMouse->ProcessEvent( child_event );
+ m_captureMouse->ProcessCanvasObjectEvent( child_event );
}
else
{
- wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
+ wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin);
if (obj && !obj->IsControl())
{
wxMouseEvent child_event( event.GetEventType() );
child_event.SetEventObject( obj );
- child_event.m_x = x - obj->GetX();
- child_event.m_y = y - obj->GetY();
+ child_event.m_x = x;
+ child_event.m_y = y;
child_event.m_leftDown = event.m_leftDown;
child_event.m_rightDown = event.m_rightDown;
child_event.m_middleDown = event.m_middleDown;
child_event.m_shiftDown = event.m_shiftDown;
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
-
- obj->ProcessEvent( child_event );
+
+ obj->ProcessCanvasObjectEvent( child_event );
return;
}
}
void wxCanvas::OnSize(wxSizeEvent &event)
{
int w,h;
+
GetClientSize( &w, &h );
+
#if IMAGE_CANVAS
m_buffer = wxImage( w, h );
#else
+ wxMemoryDC dc;
m_buffer = wxBitmap( w, h );
-#endif
+ dc.SelectObject( m_buffer );
+ dc.SetPen( *wxTRANSPARENT_PEN );
+ wxBrush brush( m_background , wxSOLID );
+ dc.SetBrush( brush );
+ dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
+ dc.SelectObject( wxNullBitmap );
- CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
+#endif
wxNode *node = m_updateRects.First();
while (node)
m_frozen = FALSE;
- Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
+ m_admin->SetActive(this);
+ SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE);
+
+ Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
event.Skip();
}
void wxCanvas::OnIdle(wxIdleEvent &event)
{
+ m_admin->SetActive(this);
UpdateNow();
event.Skip();
}
void wxCanvas::OnSetFocus(wxFocusEvent &event)
{
+ m_admin->SetActive(this);
}
void wxCanvas::OnKillFocus(wxFocusEvent &event)
{
}
-void wxCanvas::OnChar(wxKeyEvent &event)
+
+void wxCanvas::OnEraseBackground(wxEraseEvent &event)
{
- event.Skip();
}
-void wxCanvas::OnEraseBackground(wxEraseEvent &event)
+
+
+// maps the virtual window (Real drawing to the window coordinates
+// also used for zooming
+void wxCanvas::SetMappingScroll( double vx1, double vy1, double vx2, double vy2, bool border)
+{
+ int dwxi,dwyi;
+ GetClientSize(&dwxi,&dwyi);
+
+ if (vx2==vx1) vx2=vx1+100000;
+ if (vy2==vy1) vy2=vy1+100000;
+ m_virt_minX=vx1;
+ m_virt_minY=vy1;
+ m_virt_maxX=vx2;
+ m_virt_maxY=vy2;
+
+ double dwx=dwxi;
+ double dwy=dwyi;
+ if (dwx==0) dwx=1;
+ if (dwy==0) dwy=1;
+
+ double dvx = m_virt_maxX - m_virt_minX;
+ double dvy = m_virt_maxY - m_virt_minY;
+
+ // calculate the scaling factor for the virtual window
+ double temp_x=0;
+ double temp_y=0;
+ if ((dvy / dvx) < (dwy / dwx))
+ {
+ dvy = dvx * (dwy / dwx);
+ // calculate the change in the coordinates
+ temp_y = (dvy - (m_virt_maxY - m_virt_minY) )/ 2.0;
+ }
+ else
+ {
+ dvx = dvy * (dwx / dwy);
+ // calculate the change in the coordinates
+ temp_x = (dvx - (m_virt_maxX - m_virt_minX) )/ 2.0;
+ }
+
+ // add or substract the change from the original coordinates
+ m_virt_minX=m_virt_minX-temp_x;
+ m_virt_minY=m_virt_minY-temp_y;
+
+ m_virt_maxX=m_virt_maxX+temp_x;
+ m_virt_maxY=m_virt_maxY+temp_y;
+
+ // initialize the mapping_matrix used for mapping the
+ // virtual windows to the drawing window
+
+ // make mappingmatrix
+ m_mapping_matrix.Identity();
+ if (!border)
+ // translate the drawing to 0,0
+ if (m_yaxis)
+ m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY);
+ else
+ m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY);
+ else
+ {
+ // make a small white border around the drawing
+ m_virt_minX=m_virt_minX- 0.05 * dvx;
+ m_virt_minY=m_virt_minY- 0.05 * dvy;
+
+ m_virt_maxX=m_virt_maxX+ 0.05 * dvx;
+ m_virt_maxY=m_virt_maxY+ 0.05 * dvy;
+
+ // translate the drawing to 0,0
+ if (m_yaxis)
+ m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY);
+ else
+ m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY);
+ }
+
+ double scalefactor_x = dwx;
+ scalefactor_x /= (m_virt_maxX - m_virt_minX);
+
+ double scalefactor_y = dwy;
+ scalefactor_y /= (m_virt_maxY - m_virt_minY);
+
+ // scale the drawing so it fit's in the window
+ m_mapping_matrix.Scale(scalefactor_x, scalefactor_y, 0, 0);
+
+ // because of coordinate change mirror over X
+ // 0,0 in graphic computerscreens: upperleft corner
+ // 0,0 in cartesian: lowerleft corner
+ if (m_yaxis)
+ {
+ m_mapping_matrix.Mirror();
+ }
+ // make inverse of mapping matrix
+ // this is to set coordinates in the statusbar
+ // and the calculate screencoordinates to world coordinates used
+ // in zooming
+ m_inverse_mapping=m_mapping_matrix;
+ m_inverse_mapping.Invert();
+
+ if (m_scrolled)
+ SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY);
+
+ int dx2,dy2;
+ GetClientSize(&dx2,&dy2);
+ if ( dwxi != dx2 || dwyi != dy2) //scrollbar is/became empty
+ SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY);
+}
+
+
+void wxCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2)
+{
+ m_virtm_minX=vx1;
+ m_virtm_minY=vy1;
+ m_virtm_maxX=vx2;
+ m_virtm_maxY=vy2;
+
+ double dvx = m_virt_maxX - m_virt_minX;
+ double dvy = m_virt_maxY - m_virt_minY;
+ double dmvx = m_virtm_maxX - m_virtm_minX;
+ double dmvy = m_virtm_maxY - m_virtm_minY;
+
+ SetScrollbar(wxHORIZONTAL,(m_virt_minX-m_virtm_minX)/dmvx *1000,dvx/dmvx *1000,1000,true);
+ if (m_yaxis)
+ {
+ SetScrollbar(wxVERTICAL,(m_virtm_maxY-m_virt_maxY)/dmvy *1000,dvy/dmvy *1000,1000,true);
+ }
+ else
+ {
+ SetScrollbar(wxVERTICAL,(m_virt_minY-m_virtm_minY)/dmvy *1000,dvy/dmvy *1000,1000,true);
+ }
+
+ m_scrolled=true;
+}
+
+// coordinates conversions
+// -----------------------
+double wxCanvas::DeviceToLogicalX(int x) const
{
+ return m_inverse_mapping.GetValue(0,0) * x + m_inverse_mapping.GetValue(2,0);
}
+double wxCanvas::DeviceToLogicalY(int y) const
+{
+ return m_inverse_mapping.GetValue(1,1) * y + m_inverse_mapping.GetValue(2,1);
+}
+
+double wxCanvas::DeviceToLogicalXRel(int x) const
+{
+ return x*m_inverse_mapping.GetValue(0,0);
+}
+
+double wxCanvas::DeviceToLogicalYRel(int y) const
+{
+ return y*m_inverse_mapping.GetValue(1,1);
+}
+
+int wxCanvas::LogicalToDeviceX(double x) const
+{
+ return (int) (m_mapping_matrix.GetValue(0,0) * x + m_mapping_matrix.GetValue(2,0) + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceY(double y) const
+{
+ return (int) (m_mapping_matrix.GetValue(1,1) * y + m_mapping_matrix.GetValue(2,1) + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceXRel(double x) const
+{
+ return (int) (x*m_mapping_matrix.GetValue(0,0) + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceYRel(double y) const
+{
+ return (int) (y*m_mapping_matrix.GetValue(1,1) + 0.5);
+}
+
+
+
+// return the inverse mapping matrix for zooming or coordinates
+wxTransformMatrix wxCanvas::GetInverseMappingMatrix()
+{
+ return m_inverse_mapping;
+}
+
+wxTransformMatrix wxCanvas::GetMappingMatrix()
+{
+ return m_mapping_matrix;
+}
+
+
+// ----------------------------------------------------------------------------
+// scrolling behaviour
+// ----------------------------------------------------------------------------
+
+void wxCanvas::OnScroll(wxScrollWinEvent& event)
+{
+ if (event.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE)
+ {
+ if (event.GetOrientation()==wxHORIZONTAL)
+ {
+ double x=m_virtm_minX+event.GetPosition()/1000.0*(m_virtm_maxX-m_virtm_minX);
+ x=LogicalToDeviceXRel(x-m_virt_minX);
+ ScrollWindow(-x, 0, (const wxRect *) NULL);
+ }
+ else
+ {
+ double y=m_virtm_minY+event.GetPosition()/1000.0*(m_virtm_maxY-m_virtm_minY);
+ y=LogicalToDeviceYRel(y-m_virt_minY);
+ ScrollWindow(0, -y, (const wxRect *) NULL);
+ }
+ }
+ else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEUP)
+ {
+ if (event.GetOrientation()==wxHORIZONTAL)
+ {
+ double x=GetBufferWidth();
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ else
+ {
+ double y=GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ }
+ else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN)
+ {
+ if (event.GetOrientation()==wxHORIZONTAL)
+ {
+ double x=-GetBufferWidth();
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ else
+ {
+ double y=-GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ }
+ else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEUP)
+ {
+ if (event.GetOrientation()==wxHORIZONTAL)
+ {
+ int x=GetBufferWidth()/10;
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ else
+ {
+ int y=GetBufferHeight()/10;
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ }
+ else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN)
+ {
+ if (event.GetOrientation()==wxHORIZONTAL)
+ {
+ int x=-GetBufferWidth()/10;
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ else
+ {
+ int y=-GetBufferHeight()/10;
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ }
+
+}
+
+void wxCanvas::OnChar(wxKeyEvent& event)
+{
+ switch ( event.KeyCode() )
+ {
+ case WXK_PAGEUP:
+ case WXK_PRIOR:
+ {
+ double y=GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ break;
+ case WXK_PAGEDOWN:
+ case WXK_NEXT:
+ {
+ double y=-GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ break;
+ case WXK_HOME:
+ {
+ double y=m_virtm_minY;
+ y=LogicalToDeviceYRel(y-m_virt_minY);
+ ScrollWindow(0, -y, (const wxRect *) NULL);
+ }
+ break;
+ case WXK_END:
+ {
+ double y=m_virtm_minY+(m_virtm_maxY-m_virtm_minY);
+ y=LogicalToDeviceYRel(y-m_virt_minY);
+ ScrollWindow(0, -y, (const wxRect *) NULL);
+ }
+ break;
+ case WXK_UP:
+ {
+ int y;
+ if (!event.ControlDown())
+ y=GetBufferHeight()/10;
+ else
+ y=GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ break;
+
+ case WXK_DOWN:
+ {
+ int y;
+ if (!event.ControlDown())
+ y=-GetBufferHeight()/10;
+ else
+ y=-GetBufferHeight();
+ ScrollWindow(0, y, (const wxRect *) NULL);
+ }
+ break;
+
+ case WXK_LEFT:
+ {
+ int x;
+ if (!event.ControlDown())
+ x=GetBufferWidth()/10;
+ else
+ x=GetBufferWidth();
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ break;
+ case WXK_RIGHT:
+ {
+ int x;
+ if (!event.ControlDown())
+ x=-GetBufferWidth()/10;
+ else
+ x=-GetBufferWidth();
+ ScrollWindow(x, 0, (const wxRect *) NULL);
+ }
+ break;
+ default:
+ // not for us
+ event.Skip();
+ }
+}
+
+
+
+
//--------------------------------------------------------------------
// wxCanvasModule
//--------------------------------------------------------------------
FT_Done_FreeType( g_freetypeLibrary );
#endif
}
+
+
+wxCanvasAdmin::wxCanvasAdmin()
+{
+
+}
+
+wxCanvasAdmin::~wxCanvasAdmin()
+{
+
+
+}
+
+
+void wxCanvasAdmin::Append( wxCanvas* canvas )
+{
+ m_canvaslist.Append( canvas );
+}
+
+void wxCanvasAdmin::Remove( wxCanvas* canvas )
+{
+ m_canvaslist.DeleteObject( canvas );
+}
+
+void wxCanvasAdmin::Update(wxCanvasObject* obj, double x, double y, double width, double height)
+{
+ wxNode *node = m_canvaslist.First();
+ while (node)
+ {
+
+ wxCanvas *canvas = (wxCanvas*) node->Data();
+
+ if (m_active == canvas)
+ {
+ int xi = canvas->LogicalToDeviceX( x);
+ int yi = canvas->LogicalToDeviceY( y);
+ int wi = canvas->LogicalToDeviceXRel( width );
+ int hi = canvas->LogicalToDeviceYRel( height);
+ //update a little more then is strictly needed,
+ //to get rid of the 1 bit bugs
+ if (canvas->GetYaxis())
+ canvas->Update( xi-2, yi+hi-2, wi+4, -hi+4);
+ else
+ canvas->Update( xi-2, yi-2, wi+4, hi+4);
+ }
+ else
+ { wxCanvasObject* topobj=canvas->GetRoot()->Contains(obj);
+ if (topobj)
+ {
+ wxCanvas* tcanvas = m_active;
+ SetActive(canvas);
+
+ /*
+ //KKK TODO somehow the next does not work for update i do not know why
+ canvas->GetRoot()->CalcBoundingBox();
+ int xi = topobj->GetX();
+ int yi = topobj->GetY();
+ int wi = topobj->GetWidth();
+ int hi = topobj->GetHeight();
+ */
+ canvas->Update( 0,0, canvas->GetBufferWidth(),canvas->GetBufferHeight());
+ SetActive(tcanvas);
+ }
+ }
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasAdmin::UpdateNow()
+{
+ wxNode *node = m_canvaslist.First();
+ while (node)
+ {
+ wxCanvas *canvas = (wxCanvas*) node->Data();
+
+ canvas->UpdateNow();
+ node = node->Next();
+ }
+}
+
+// coordinates conversions
+// -----------------------
+double wxCanvasAdmin::DeviceToLogicalX(int x) const
+{
+ return m_active->DeviceToLogicalX(x);
+}
+
+double wxCanvasAdmin::DeviceToLogicalY(int y) const
+{
+ return m_active->DeviceToLogicalY(y);
+}
+
+double wxCanvasAdmin::DeviceToLogicalXRel(int x) const
+{
+ return m_active->DeviceToLogicalXRel(x);
+}
+
+double wxCanvasAdmin::DeviceToLogicalYRel(int y) const
+{
+ return m_active->DeviceToLogicalYRel(y);
+}
+
+int wxCanvasAdmin::LogicalToDeviceX(double x) const
+{
+ return m_active->LogicalToDeviceX(x);
+}
+
+int wxCanvasAdmin::LogicalToDeviceY(double y) const
+{
+ return m_active->LogicalToDeviceY(y);
+}
+
+int wxCanvasAdmin::LogicalToDeviceXRel(double x) const
+{
+ return m_active->LogicalToDeviceXRel(x);
+}
+
+int wxCanvasAdmin::LogicalToDeviceYRel(double y) const
+{
+ return m_active->LogicalToDeviceYRel(y);
+}
+
+void wxCanvasAdmin::SetActive(wxCanvas* activate)
+{
+ wxNode *node = m_canvaslist.First();
+ while (node)
+ {
+ wxCanvas *canvas = (wxCanvas*) node->Data();
+
+ if (activate == canvas)
+ {
+ m_active=canvas;
+ break;
+ }
+ node = node->Next();
+ }
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: polygon.cpp
+// Author: Klaas Holwerda
+// Created: XX/XX/XX
+// Copyright: 2000 (c) Klaas Holwerda
+// Licence: wxWindows Licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+ #pragma implementation "polygon.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "polygon.h"
+#include "liner.h"
+
+void ConvertSplinedPolygon(wxList* list, double Aber);
+void ConvertSplinedPolyline(wxList* list,double Aber);
+void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber);
+static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge);
+
+//----------------------------------------------------------------------------
+// wxCanvasPolyline
+//----------------------------------------------------------------------------
+
+wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[])
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_pen = *wxBLACK_PEN;
+
+ CalcBoundingBox();
+}
+
+wxCanvasPolyline::~wxCanvasPolyline()
+{
+ delete m_points;
+}
+
+void wxCanvasPolyline::SetPosXY( double x, double y)
+{
+ double xo=m_points[0].m_x;
+ double yo=m_points[0].m_y;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += (x-xo);
+ m_points[i].m_y += (y-yo);
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolyline::TransLate( double x, double y )
+{
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += x;
+ m_points[i].m_y += y;
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolyline::CalcBoundingBox()
+{
+ m_bbox.SetValid(FALSE);
+
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolyline::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ wxPoint *cpoints = new wxPoint[m_n];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+ }
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ dc->DrawLines(m_n, cpoints, 0,0);
+ delete [] cpoints;
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolyline::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+bool wxCanvasPolyline::PointOnPolyline(const wxPoint2DDouble& P, double margin)
+{
+ bool result = FALSE;
+ double distance;
+ wxPoint2DDouble p1,p2;
+
+ p2=m_points[0];
+ int i;
+ for (i = 0; i < m_n-1; i++)
+ {
+ p1=p2;
+ p2=m_points[i+1];
+ if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
+ {
+ result=TRUE;
+ break;
+ }
+ else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
+ {
+ result=TRUE;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolygon
+//----------------------------------------------------------------------------
+
+wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[],bool splined)
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ m_textfg=*wxBLACK;
+ m_textbg=*wxWHITE;
+ m_transp=FALSE;
+ m_gpen=*wxBLACK_PEN;
+ m_gdistance=0;
+ m_gradient=FALSE;
+ m_spline = splined;
+
+ if (m_spline)
+ {
+ ConvertSplinedPolygon(m_n, &m_points, 10 );
+ }
+
+ CalcBoundingBox();
+}
+
+wxCanvasPolygon::~wxCanvasPolygon()
+{
+ delete m_points;
+}
+
+void wxCanvasPolygon::SetPosXY( double x, double y)
+{
+ double xo=m_points[0].m_x;
+ double yo=m_points[0].m_y;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += (x-xo);
+ m_points[i].m_y += (y-yo);
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygon::TransLate( double x, double y )
+{
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_points[i].m_x += x;
+ m_points[i].m_y += y;
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygon::CalcBoundingBox()
+{
+
+ m_bbox.SetValid(FALSE);
+
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ m_bbox.Expand( m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolygon::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ //one extra for drawlines in some cases
+ wxPoint *cpoints = new wxPoint[m_n+1];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ double x1;
+ double y1;
+ cworld->TransformPoint( m_points[i].m_x, m_points[i].m_y, x1, y1 );
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+ }
+ double x1;
+ double y1;
+ cworld->TransformPoint( m_points[0].m_x, m_points[0].m_y, x1, y1 );
+ cpoints[m_n].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[m_n].y = m_admin->LogicalToDeviceY(y1);
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
+ {
+ //draw a transparent polygon
+ //leaf the pen not transparent, which i prefer
+ dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
+ dc->SetTextForeground(*wxBLACK);
+ dc->SetTextBackground(*wxWHITE);
+ dc->SetLogicalFunction(wxAND_INVERT);
+ // BLACK OUT the opaque pixels and leave the rest as is
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ // Set background and foreground colors for fill pattern
+ //the previous blacked out pixels are now merged with the layer color
+ //while the non blacked out pixels stay as they are.
+ dc->SetTextForeground(*wxBLACK);
+ //now define what will be the color of the fillpattern parts that are not transparent
+ dc->SetTextBackground(m_textfg);
+ dc->SetLogicalFunction(wxOR);
+ //don't understand how but the outline is also depending on logicalfunction
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ else if (m_gradient)
+ {
+ int pw2=m_gpen.GetWidth();
+ m_gpen.SetWidth(m_admin->LogicalToDeviceYRel(pw2));
+ FillPolygon(cworld,clip_x,clip_y,clip_width,clip_height );
+ if (m_pen.GetStyle() != wxTRANSPARENT)
+ {
+ dc->SetPen(m_pen);
+ dc->DrawLines(m_n+1, cpoints, 0,0);
+ }
+ m_gpen.SetWidth(pw2);
+ }
+ else
+ {
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolygon::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ INOUTPOLY io=PointInPolygon(P, m_pen.GetWidth()/2+margin);
+ if (io == OUTSIDE_POLY)
+ return (wxCanvasObject*) NULL;
+ else
+ return this;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+INOUTPOLY wxCanvasPolygon::PointInPolygon(const wxPoint2DDouble& P, double marge)
+{
+ int R_tot = 0, L_tot = 0;
+ int p1_LRO, p2_LRO;
+ double px = P.m_x, py = P.m_y;
+ double Y_intersect;
+ wxPoint2DDouble p1,p2;
+
+ //iterate across points until we are sure that the given point is in or out
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ p1 = m_points[i];
+ if (i == m_n-1)
+ p2 = m_points[0];
+ else
+ p2 = m_points[i+1];
+
+ //more accurate
+ GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
+ if (p1_LRO != p2_LRO)
+ {
+ int L = 0, R = 0;
+ if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
+ if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
+ if (p2_LRO == 1) { R = 1; L = p1_LRO; }
+
+ // calculate intersection point with line for px
+ if (p1_LRO == 0)
+ {
+ if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p1.m_y;
+ }
+ else if (p2_LRO == 0)
+ {
+ if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p2.m_y;
+ }
+ else //both p2_LRO and p1_LRO not 0
+ {
+ if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else //need to calculate intersection
+ {
+ if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ line1.CalculateLineParameters();
+ Y_intersect = line1.Calculate_Y(px);
+ }
+ else
+ continue;
+ }
+ }
+ if (Y_intersect > (py + marge))
+ {
+ R_tot += R;
+ L_tot += L;
+ }
+ else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
+ {
+ return ON_POLY;
+ }
+ }
+ }
+
+ // geef het juiste resultaat terug
+ if (R_tot == 0)
+ if (L_tot == 0) return OUTSIDE_POLY;
+ else return ON_POLY;
+ else
+ if (L_tot == 0) return ON_POLY;
+ else return INSIDE_POLY;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolylineL
+//----------------------------------------------------------------------------
+
+wxCanvasPolylineL::wxCanvasPolylineL( wxList* points, bool spline )
+ : wxCanvasObject()
+{
+ m_lpoints = points;
+ m_pen = *wxBLACK_PEN;
+ m_spline=spline;
+ if (m_spline)
+ ConvertSplinedPolyline(m_lpoints, 10);
+ CalcBoundingBox();
+}
+
+wxCanvasPolylineL::~wxCanvasPolylineL()
+{
+ m_lpoints->DeleteContents(TRUE);
+ delete m_lpoints;
+}
+
+double wxCanvasPolylineL::GetPosX()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_x;
+}
+
+double wxCanvasPolylineL::GetPosY()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_y;
+}
+
+void wxCanvasPolylineL::SetPosXY( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double xo=point->m_x;
+ double yo=point->m_y;
+ while (node)
+ {
+ point = (wxPoint2DDouble*)node->Data();
+ point->m_x = point->m_x + x-xo;
+ point->m_y = point->m_y + y-yo;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolylineL::TransLate( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ point->m_x += x;
+ point->m_y += y;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolylineL::CalcBoundingBox()
+{
+ m_bbox.SetValid(FALSE);
+
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ m_bbox.Expand( point->m_x,point->m_y);
+ node = node->GetNext();
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolylineL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ int n=m_lpoints->GetCount();
+ wxPoint *cpoints = new wxPoint[n];
+
+ wxNode *node = m_lpoints->GetFirst();
+ int i=0;
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+
+ node = node->GetNext();
+ i++;
+ }
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ dc->SetPen(m_pen);
+ dc->DrawLines(n, cpoints, 0,0);
+ delete [] cpoints;
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolylineL::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+wxCanvasObject* wxCanvasPolylineL::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ if (PointOnPolyline(P,m_pen.GetWidth()/2+margin))
+ return this;
+ else
+ return (wxCanvasObject*) NULL;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+bool wxCanvasPolylineL::PointOnPolyline(const wxPoint2DDouble& P, double margin)
+{
+ bool result = FALSE;
+ double distance;
+ wxPoint2DDouble p1,p2;
+
+ wxNode *node = m_lpoints->GetFirst();
+ p2 = *(wxPoint2DDouble*)node->Data();
+ while (node && !result)
+ {
+ p1=p2;
+ node=node->GetNext();
+ if (!node) break;
+ p2 = *(wxPoint2DDouble*)node->Data();
+
+ if (margin > sqrt(pow(p1.m_x-P.m_x,2)+pow(p1.m_y-P.m_y,2)))
+ result=TRUE;
+ else if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ if (line1.PointInLine(P,distance,margin) == R_IN_AREA)
+ result=TRUE;
+ }
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolygon
+//----------------------------------------------------------------------------
+
+wxCanvasPolygonL::wxCanvasPolygonL( wxList* points, bool spline )
+ : wxCanvasObject()
+{
+ m_lpoints = points;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+ m_spline=spline;
+ m_textfg=*wxBLACK;
+ m_textbg=*wxWHITE;
+ m_transp=FALSE;
+
+ if (m_spline)
+ ConvertSplinedPolyline(m_lpoints, 10);
+ CalcBoundingBox();
+}
+
+wxCanvasPolygonL::~wxCanvasPolygonL()
+{
+ m_lpoints->DeleteContents(TRUE);
+ delete m_lpoints;
+}
+
+double wxCanvasPolygonL::GetPosX()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_x;
+}
+
+double wxCanvasPolygonL::GetPosY()
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ return point->m_y;
+}
+
+void wxCanvasPolygonL::SetPosXY( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double xo=point->m_x;
+ double yo=point->m_y;
+ while (node)
+ {
+ point = (wxPoint2DDouble*)node->Data();
+ point->m_x = point->m_x + x-xo;
+ point->m_y = point->m_y + y-yo;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygonL::TransLate( double x, double y )
+{
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ point->m_x += x;
+ point->m_y += y;
+ node = node->GetNext();
+ }
+ CalcBoundingBox();
+}
+
+void wxCanvasPolygonL::CalcBoundingBox()
+{
+
+ m_bbox.SetValid(FALSE);
+
+ wxNode *node = m_lpoints->GetFirst();
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ m_bbox.Expand( point->m_x,point->m_y);
+ node = node->GetNext();
+ }
+
+ //include the pen width also
+ m_bbox.EnLarge(m_pen.GetWidth());
+}
+
+void wxCanvasPolygonL::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ if (!m_visible) return;
+
+ int start_y = clip_y;
+ int end_y = clip_y+clip_height;
+
+ int start_x = clip_x;
+ int end_x = clip_x+clip_width;
+
+#if IMAGE_CANVAS
+#else
+ int n=m_lpoints->GetCount();
+ wxPoint *cpoints = new wxPoint[n];
+
+ wxNode *node = m_lpoints->GetFirst();
+ int i=0;
+ while (node)
+ {
+ wxPoint2DDouble* point = (wxPoint2DDouble*)node->Data();
+ double x1;
+ double y1;
+ //transform to absolute
+ cworld->TransformPoint( point->m_x, point->m_y, x1, y1 );
+ //transform to device
+ cpoints[i].x = m_admin->LogicalToDeviceX(x1);
+ cpoints[i].y = m_admin->LogicalToDeviceY(y1);
+
+ node = node->GetNext();
+ i++;
+ }
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetBrush(m_brush);
+ int pw=m_pen.GetWidth();
+ m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
+ if ( m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE && m_transp)
+ {
+ //draw a transparent polygon
+ //leaf the pen not transparent, which i prefer
+ dc->SetPen( wxPen( *wxWHITE,m_admin->LogicalToDeviceXRel(pw), wxSOLID) );
+ dc->SetTextForeground(*wxBLACK);
+ dc->SetTextBackground(*wxWHITE);
+ dc->SetLogicalFunction(wxAND_INVERT);
+ // BLACK OUT the opaque pixels and leave the rest as is
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ // Set background and foreground colors for fill pattern
+ //the previous blacked out pixels are now merged with the layer color
+ //while the non blacked out pixels stay as they are.
+ dc->SetTextForeground(*wxBLACK);
+ //now define what will be the color of the fillpattern parts that are not transparent
+ dc->SetTextBackground(m_textfg);
+ dc->SetLogicalFunction(wxOR);
+ //don't understand how but the outline is also depending on logicalfunction
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ dc->SetLogicalFunction(wxCOPY);
+ }
+ else
+ {
+ dc->SetPen(m_pen);
+ dc->SetTextForeground(m_textfg);
+ dc->SetTextBackground(m_textbg);
+ dc->DrawPolygon(n, cpoints, 0,0,wxWINDING_RULE);
+ }
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+ m_pen.SetWidth(pw);
+#endif
+}
+
+void wxCanvasPolygonL::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+static void GetLRO(const wxPoint2DDouble& P, const wxPoint2DDouble& p1, const wxPoint2DDouble& p2, int &LRO1, int &LRO2,const double marge)
+{
+ if (p1.m_x > (P.m_x + marge)) LRO1 = -1; // beginnode is right of P
+ else
+ if (p1.m_x < (P.m_x - marge)) LRO1 = 1; // beginnode is left of P
+ else LRO1 = 0; // beginnode is on vertical line through P
+
+ if (p2.m_x > (P.m_x + marge)) LRO2 = -1; // endnode is right of P
+ else
+ if (p2.m_x < (P.m_x - marge)) LRO2 = 1; // endnode is left of P
+ else LRO2 = 0; // endnode is on vertical line through P
+}
+
+wxCanvasObject* wxCanvasPolygonL::IsHitWorld( double x, double y, double margin )
+{
+ if ((x >= m_bbox.GetMinX()-margin) &&
+ (x <= m_bbox.GetMaxX()+margin) &&
+ (y >= m_bbox.GetMinY()-margin) &&
+ (y <= m_bbox.GetMaxY()+margin)
+ )
+ {
+ wxPoint2DDouble P=wxPoint2DDouble(x,y);
+ INOUTPOLY io=PointInPolygon(P,m_pen.GetWidth()/2 + margin);
+ if (io == OUTSIDE_POLY)
+ return (wxCanvasObject*) NULL;
+ else
+ return this;
+ }
+ return (wxCanvasObject*) NULL;
+}
+
+INOUTPOLY wxCanvasPolygonL::PointInPolygon(const wxPoint2DDouble& P, double marge)
+{
+ int R_tot = 0, L_tot = 0;
+ int p1_LRO, p2_LRO;
+ double px = P.m_x, py = P.m_y;
+ double Y_intersect;
+ wxPoint2DDouble p1,p2;
+
+ //iterate across points until we are sure that the given point is in or out
+ wxNode *node = m_lpoints->GetFirst();
+
+ while (node)
+ {
+ p1 = *(wxPoint2DDouble*)node->Data();
+ if (m_lpoints->GetLast() == node)
+ {
+ p2 = *(wxPoint2DDouble*)m_lpoints->GetFirst();
+ }
+ else
+ {
+ p2 = *(wxPoint2DDouble*)node->GetNext()->Data();
+ }
+
+ //more accurate
+ GetLRO(P,p1,p2,p1_LRO,p2_LRO,marge/10);
+ if (p1_LRO != p2_LRO)
+ {
+ int L = 0, R = 0;
+ if (p2_LRO == -1) { R = -p1_LRO; L = 1; }
+ if (p2_LRO == 0) if (p1_LRO == 1) R = -1; else L = -1;
+ if (p2_LRO == 1) { R = 1; L = p1_LRO; }
+
+ // calculate intersection point with line for px
+ if (p1_LRO == 0)
+ {
+ if ((p1.m_y < (py + marge)) && (p1.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p1.m_y;
+ }
+ else if (p2_LRO == 0)
+ {
+ if ((p2.m_y < (py + marge)) && (p2.m_y > (py - marge)))
+ return ON_POLY;
+ else
+ Y_intersect = p2.m_y;
+ }
+ else //both p2_LRO and p1_LRO not 0
+ {
+ if ((p1.m_y > (py + marge)) && (p2.m_y > (py + marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else if ((p1.m_y < (py- marge)) && (p2.m_y < (py - marge)))
+ Y_intersect = p1.m_y; //a save value to check later
+ else //need to calculate intersection
+ {
+ if (!((p1.m_x == p2.m_x) && (p1.m_y == p2.m_y)))
+ {
+ wxLine line1(p1,p2);
+ line1.CalculateLineParameters();
+ Y_intersect = line1.Calculate_Y(px);
+ }
+ else
+ continue;
+ }
+ }
+ if (Y_intersect > (py + marge))
+ {
+ R_tot += R;
+ L_tot += L;
+ }
+ else if ((Y_intersect <= (py + marge)) && (Y_intersect >= (py - marge)))
+ {
+ return ON_POLY;
+ }
+ }
+ node=node->Next();
+ }
+
+ // geef het juiste resultaat terug
+ if (R_tot == 0)
+ if (L_tot == 0) return OUTSIDE_POLY;
+ else return ON_POLY;
+ else
+ if (L_tot == 0) return ON_POLY;
+ else return INSIDE_POLY;
+}
+
+// ---------------------------------------------------------------------------
+// spline drawing code
+// ---------------------------------------------------------------------------
+
+static void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2,
+ double a3, double b3, double a4, double b4,double aber);
+static void gds_clear_stack();
+static int gds_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
+ double *y3, double *x4, double *y4);
+static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
+ double x4, double y4);
+
+void ConvertSplinedPolygon(int& n, wxPoint2DDouble* points[], double Aber)
+{
+ wxList h;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ h.Append((wxObject*) new wxPoint2DDouble((*points)[i].m_x, (*points)[i].m_y));
+ }
+ delete *points;
+
+ ConvertSplinedPolygon(&h, Aber);
+
+ n=h.GetCount();
+ *points = new wxPoint2DDouble[n];
+ wxNode* node=h.GetFirst();
+ for (i = 0; i < n; i++)
+ {
+ wxNode* hh= node;
+ node = node->GetNext();
+ (*points)[i].m_x=((wxPoint2DDouble*) hh->GetData())->m_x;
+ (*points)[i].m_y=((wxPoint2DDouble*) hh->GetData())->m_y;
+ delete (wxPoint2DDouble*) hh->GetData();
+ h.DeleteNode(hh);
+ }
+}
+
+void ConvertSplinedPolygon(wxList* list, double Aber)
+{
+ wxPoint2DDouble* point;
+ double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ double x1, y1, x2, y2;
+
+ if (list->GetCount() <2)
+ return;
+
+ wxNode* iter=list->GetLast();
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ iter=list->GetFirst();
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ point = new wxPoint2DDouble(x2,y2);
+ list->Append((wxObject*)point);
+
+ cx1 = (x1 + x2) / 2.0;
+ cy1 = (y1 + y2) / 2.0;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+
+ delete (wxPoint2DDouble*) iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ point = new wxPoint2DDouble(x1,y1);
+ list->Append((wxObject*)point);
+
+ int i=1;
+ int count=list->GetCount();
+ while (i < count)
+ {
+ x1 = x2;
+ y1 = y2;
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx4 = (x1 + x2) / 2.0;
+ cy4 = (y1 + y2) / 2.0;
+ cx3 = (x1 + cx4) / 2.0;
+ cy3 = (y1 + cy4) / 2.0;
+
+ gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
+
+ cx1 = cx4;
+ cy1 = cy4;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ i++;
+ }
+
+ iter=list->GetFirst();
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+}
+
+void ConvertSplinedPolyline(wxList* list,double Aber)
+{
+ double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ double x1, y1, x2, y2;
+
+
+ if (list->GetCount() <2)
+ return;
+
+
+
+ wxNode* iter=list->GetFirst();
+
+ x1 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y1 = ((wxPoint2DDouble*)iter->Data())->m_y;
+
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx1 = (x1 + x2) / 2.0;
+ cy1 = (y1 + y2) / 2.0;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+
+ wxPoint2DDouble* point = new wxPoint2DDouble(x1,y1);
+ list->Append((wxObject*)point);
+
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+
+ int i=1;
+ int count=list->GetCount();
+ while (i < count)
+ {
+ x1 = x2;
+ y1 = y2;
+ x2 = ((wxPoint2DDouble*)iter->Data())->m_x;
+ y2 = ((wxPoint2DDouble*)iter->Data())->m_y;
+ cx4 = (x1 + x2) / 2.0;
+ cy4 = (y1 + y2) / 2.0;
+ cx3 = (x1 + cx4) / 2.0;
+ cy3 = (y1 + cy4) / 2.0;
+
+ gds_quadratic_spline(list,cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4,Aber);
+
+ cx1 = cx4;
+ cy1 = cy4;
+ cx2 = (cx1 + x2) / 2.0;
+ cy2 = (cy1 + y2) / 2.0;
+ delete (wxPoint2DDouble*)iter->Data();
+ delete iter;
+ iter=list->GetFirst();
+ i++;
+ }
+
+ point = new wxPoint2DDouble(cx1,cy1);
+ list->Append((wxObject*)point);
+
+ point = new wxPoint2DDouble(x2,y2);
+ list->Append((wxObject*)point);
+}
+
+/********************* CURVES FOR SPLINES *****************************
+
+ The following spline drawing routine is from
+
+ "An Algorithm for High-Speed Curve Generation"
+ by George Merrill Chaikin,
+ Computer Graphics and Image Processing, 3, Academic Press,
+ 1974, 346-349.
+
+ and
+
+ "On Chaikin's Algorithm" by R. F. Riesenfeld,
+ Computer Graphics and Image Processing, 4, Academic Press,
+ 1975, 304-310.
+
+***********************************************************************/
+
+#define half(z1, z2) ((z1+z2)/2.0)
+#define THRESHOLD 5
+
+/* iterative version */
+
+void gds_quadratic_spline(wxList *org,double a1, double b1, double a2, double b2, double a3, double b3, double a4,
+ double b4,double Aber)
+{
+ register double xmid, ymid;
+ double x1, y1, x2, y2, x3, y3, x4, y4;
+ wxPoint2DDouble* point;
+
+ gds_clear_stack();
+ gds_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
+
+ while (gds_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4))
+ {
+ xmid = half(x2, x3);
+ ymid = half(y2, y3);
+ if (fabs(x1 - xmid) < Aber && fabs(y1 - ymid) < Aber &&
+ fabs(xmid - x4) < Aber && fabs(ymid - y4) < Aber)
+ {
+ point = new wxPoint2DDouble(x1,y1);
+ org->Append((wxObject*)point);
+ point = new wxPoint2DDouble(xmid,ymid);
+ org->Append((wxObject*)point);
+ } else {
+ gds_spline_push(xmid, ymid, half(xmid, x3), half(ymid, y3),
+ half(x3, x4), half(y3, y4), x4, y4);
+ gds_spline_push(x1, y1, half(x1, x2), half(y1, y2),
+ half(x2, xmid), half(y2, ymid), xmid, ymid);
+ }
+ }
+}
+
+
+/* utilities used by spline drawing routines */
+
+
+typedef struct gds_spline_stack_struct {
+ double x1, y1, x2, y2, x3, y3, x4, y4;
+}
+Stack;
+
+#define SPLINE_STACK_DEPTH 20
+static Stack gds_spline_stack[SPLINE_STACK_DEPTH];
+static Stack *gds_stack_top;
+static int gds_stack_count;
+
+static void gds_clear_stack()
+{
+ gds_stack_top = gds_spline_stack;
+ gds_stack_count = 0;
+}
+
+static void gds_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
+{
+ gds_stack_top->x1 = x1;
+ gds_stack_top->y1 = y1;
+ gds_stack_top->x2 = x2;
+ gds_stack_top->y2 = y2;
+ gds_stack_top->x3 = x3;
+ gds_stack_top->y3 = y3;
+ gds_stack_top->x4 = x4;
+ gds_stack_top->y4 = y4;
+ gds_stack_top++;
+ gds_stack_count++;
+}
+
+int gds_spline_pop(double *x1, double *y1, double *x2, double *y2,
+ double *x3, double *y3, double *x4, double *y4)
+{
+ if (gds_stack_count == 0)
+ return (0);
+ gds_stack_top--;
+ gds_stack_count--;
+ *x1 = gds_stack_top->x1;
+ *y1 = gds_stack_top->y1;
+ *x2 = gds_stack_top->x2;
+ *y2 = gds_stack_top->y2;
+ *x3 = gds_stack_top->x3;
+ *y3 = gds_stack_top->y3;
+ *x4 = gds_stack_top->x4;
+ *y4 = gds_stack_top->y4;
+ return (1);
+}
+
+void wxAET::CalculateLineParameters( const wxPoint2DDouble& p1 , const wxPoint2DDouble& p2 )
+{
+ double A = p2.m_y - p1.m_y; //A (y2-y1)
+ if (A == 0)
+ {
+ m_horizontal=TRUE;
+ m_BdivA=0;
+ m_CdivA=0;
+ }
+ else
+ {
+ m_horizontal=FALSE;
+ m_BdivA= (p1.m_x - p2.m_x)/A; //B (x1-x2)
+ //normalize
+ m_CdivA= ((p2.m_x*p1.m_y) - (p1.m_x*p2.m_y)) /A ;
+ }
+}
+
+void wxAET::CalculateXs( double y )
+{
+ m_xs= -m_BdivA * y - m_CdivA;
+}
+
+//use by polygon filling
+//moves the scanline up
+//index is the index of the point where the search begins
+//direction is +1 or -1 and indicates if the segment ascends or decends
+bool wxCanvasPolygon::MoveUp( double horline, int& index, int direction)
+{
+ int walk = (index + direction + m_n) % m_n;
+ while ( m_points[walk].m_y < horline )
+ {
+ if (m_points[walk].m_y < m_points[index].m_y )
+ return FALSE;
+ else
+ {
+ //modify index
+ index=walk;
+ walk = (index + direction + m_n) % m_n;
+ }
+ }
+ return TRUE;
+}
+
+//a crictical point is a point between a decending and a ascending segment
+//collect those points for filling later
+void wxCanvasPolygon::DetectCriticalPoints()
+{
+ //candidate for critical point
+ //true if Y is getting lower, unchanged i Y is unchanged
+ //and if Y becomes higher and candidate was true: it is a critical point
+ bool candidate = FALSE;
+ int i,j;
+
+ for ( i=0; i < m_n; i++)
+ {
+ //j next point
+ j= (i+1) % m_n;
+
+ //check if Y is smaller
+ if (m_points[i].m_y > m_points[j].m_y)
+ //we have a candidate
+ candidate=TRUE;
+ else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
+ { //this is a critical point put in list
+ bool inserted=FALSE;
+ wxNode *node = m_CRlist.GetFirst();
+ while (node)
+ {
+ //sorted on smallest Y value
+ int* ind=(int*) node->GetData();
+ if (m_points[*ind].m_y > m_points[i].m_y)
+ {
+ m_CRlist.Insert(node,(wxObject*) new int(i));
+ inserted = TRUE;
+ break;
+ }
+ node = node->GetNext();
+ }
+ if (!inserted)
+ m_CRlist.Append((wxObject*) new int(i));
+ candidate = FALSE;
+ }
+ }
+ if (candidate)
+ {
+ for ( i=0; i < m_n; i++)
+ {
+ //j next point
+ j= (i+1) % m_n;
+
+ //check if Y is smaller
+ if (m_points[i].m_y > m_points[j].m_y)
+ //we have a candidate
+ candidate=TRUE;
+ else if ( (m_points[i].m_y < m_points[j].m_y) && candidate)
+ { //this is a critical point put in list
+ bool inserted=FALSE;
+ wxNode *node = m_CRlist.GetFirst();
+ while (node)
+ {
+ //sorted on smallest Y value
+ int* ind=(int*) node->GetData();
+ if (m_points[*ind].m_y > m_points[i].m_y)
+ {
+ m_CRlist.Insert(node,(wxObject*) new int(i));
+ inserted = TRUE;
+ break;
+ }
+ node = node->GetNext();
+ }
+ if (!inserted)
+ m_CRlist.Append((wxObject*) new int(i));
+ candidate = FALSE;
+ }
+ }
+ }
+}
+
+
+void wxCanvasPolygon::FillPolygon(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+#if IMAGE_CANVAS
+#else
+ int index;
+ //how much is on pixel in world coordinates
+
+ double scalefactor;
+ if (m_gdistance)
+ scalefactor=m_gdistance;
+ else
+ //abs here needed if yaxis is going up (always scan in world coordinates UP)
+ scalefactor=fabs(m_admin->DeviceToLogicalYRel(1)); //1 pixel height
+
+ wxDC *dc = m_admin->GetActive()->GetDC();
+ dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
+ wxPen gradientpen=m_gpen;
+
+ int dred = m_textbg.Red()-m_textfg.Red();
+ int dgreen = m_textbg.Green()-m_textfg.Green();
+ int dblue = m_textbg.Blue()-m_textfg.Blue();
+
+ //total number of lines to go from m_textbg to m_textfg
+ //gives the following number of steps for the gradient color
+ int stepcol = (int) (m_bbox.GetHeight()/scalefactor);
+
+ DetectCriticalPoints();
+
+ double min;
+ double max;
+ if (cworld->IsIdentity())
+ {
+ //TODO do something with clipping region (inverse transform?)
+ //the next does not work, i don't know why
+ //min = wxMin (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
+ //max = wxMax (m_admin->DeviceToLogicalY(clip_y),m_admin->DeviceToLogicalY(clip_y+clip_height));
+ min= m_bbox.GetMinY();
+ max= m_bbox.GetMaxY();
+ }
+ else
+ {
+ min= m_bbox.GetMinY();
+ max= m_bbox.GetMaxY();
+ }
+
+ int curcol = (int)( (min - m_bbox.GetMinY())/scalefactor );
+
+ double i;
+ for ( i = min; i < max; i+=scalefactor)
+ {
+ wxNode *node = m_AETlist.GetFirst();
+ int count= m_AETlist.GetCount();
+ while (count > 0)
+ {
+ wxAET* ele = ((wxAET*)node->GetData());
+ index= ele->m_index;
+ int direction = ele->m_direction;
+ if (!MoveUp(i,index,direction))
+ {
+ wxNode* h = node;
+ //remove this node
+ node = node->GetNext();
+ m_AETlist.DeleteNode(h);
+ }
+ else
+ {
+ if (ele->m_index != index)
+ {
+ ele->m_index=index;
+ int h = (index + direction + m_n) % m_n;
+ ele->CalculateLineParameters(m_points[h],m_points[index]);
+ }
+ if (ele->m_horizontal)
+ ele->m_xs=m_points[index].m_x;
+ else
+ ele->CalculateXs(i);
+ node = node->GetNext();
+ }
+ count--;
+ }
+
+ node = m_CRlist.GetFirst();
+ while (m_CRlist.GetCount() && m_points[*((int*)node->GetData())].m_y <=i )
+ {
+ int DI;
+ for ( DI = -1; DI <=1 ; DI+=2)
+ {
+ index=*((int*)node->GetData());
+ if (MoveUp(i,index,DI))
+ {
+ wxAET* ele = new wxAET();
+ ele->m_index=index;
+ ele->m_direction=DI;
+ int h = (index + DI + m_n) % m_n;
+ ele->CalculateLineParameters(m_points[h],m_points[index]);
+ if (ele->m_horizontal)
+ ele->m_xs=m_points[index].m_x;
+ else
+ ele->CalculateXs(i);
+
+ //insert in sorted order od m_xs
+ bool inserted=FALSE;
+ wxNode *node2 = m_AETlist.GetFirst();
+ while (node2)
+ {
+ //sorted on smallest xs value
+ if (ele->m_xs < ((wxAET*)node2->GetData())->m_xs)
+ {
+ m_AETlist.Insert(node2,(wxObject*) ele);
+ inserted = TRUE;
+ break;
+ }
+ node2 = node2->GetNext();
+ }
+ if (!inserted)
+ m_AETlist.Append((wxObject*)ele);
+ }
+ }
+
+ wxNode* h= node;
+ node = node->GetNext();
+ m_CRlist.DeleteNode(h);
+ }
+
+ curcol++;
+ wxColour gradcol(m_textbg.Red()+dred*curcol/stepcol,
+ m_textbg.Green()+dgreen*curcol/stepcol,
+ m_textbg.Blue()+dblue*curcol/stepcol);
+ gradientpen.SetColour(gradcol);
+
+ //m_AETlist must be sorted in m_xs at this moment
+ //now draw all the line parts on one horizontal scanline (Winding Rule)
+ int out= 0;
+ node = m_AETlist.GetFirst();
+ while (node)
+ {
+ wxAET* ele = ((wxAET*)node->GetData());
+ out+=ele->m_direction;
+ if (out != 0)
+ {
+ double x1=ele->m_xs;
+ node = node->GetNext();
+ ele = ((wxAET*)node->GetData());
+ double x2=ele->m_xs;
+ dc->SetPen( gradientpen );
+ double wx1,wy1,wx2,wy2;
+ cworld->TransformPoint( x1, i, wx1, wy1 );
+ cworld->TransformPoint( x2, i, wx2, wy2 );
+ int dx1,dy1,dx2,dy2;
+ dx1 = m_admin->LogicalToDeviceX( wx1 );
+ dy1 = m_admin->LogicalToDeviceY( wy1 );
+ dx2 = m_admin->LogicalToDeviceX( wx2 );
+ dy2 = m_admin->LogicalToDeviceY( wy2 );
+
+ //TODO KKK need real line clipping here since line can be rotated.
+ if (0 && cworld->IsIdentity())
+ {
+ if (dx1 < clip_x) dx1=clip_x;
+ if (dx2 > clip_x + clip_width) dx2=clip_x + clip_width;
+ if ((dy1 > clip_y) && dy1 < clip_y + clip_height)
+ dc->DrawLine( dx1, dy1, dx2, dy2 );
+ }
+ else
+ {
+ dc->DrawLine( dx1, dy1, dx2, dy2 );
+ }
+
+ }
+ else
+ node = node->GetNext();
+ }
+ }
+
+ dc->DestroyClippingRegion();
+#endif
+}
+
+
+
+
+