+ m_validbounds=false;
+}
+
+void wxCanvasObjectGroup::SetOwner(wxCanvas* canvas)
+{
+ m_owner=canvas;
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->SetOwner(canvas);
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::ExtendArea(int x, int 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;
+ }
+
+}
+
+
+void wxCanvasObjectGroup::DeleteContents( bool flag)
+{
+ m_objects.DeleteContents( flag );
+ m_validbounds=false;
+}
+
+
+void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
+{
+ m_objects.Insert( obj );
+ m_validbounds=false;
+}
+
+void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
+{
+ m_objects.Append( obj );
+ m_validbounds=false;
+}
+
+void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
+{
+ m_objects.Insert( before, obj );
+ m_validbounds=false;
+}
+
+void wxCanvasObjectGroup::Remove( wxCanvasObject* obj )
+{
+ m_objects.DeleteObject( obj );
+ m_validbounds=false;
+}
+
+void wxCanvasObjectGroup::Recreate()
+{
+ m_validbounds=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());
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::Render(int xabs, int yabs, int x, int y, int width, int height )
+{
+ wxImage *image = m_owner->GetBuffer();
+ // cycle through all objects
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ // 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();
+ if (clip_x < x)
+ {
+ clip_width -= x-clip_x;
+ clip_x = x;
+ }
+ if (clip_width > 0)
+ {
+ if (clip_x + clip_width > x + width)
+ clip_width = x+width-clip_x;
+
+ if (clip_width > 0)
+ {
+ int clip_y = yabs + obj->GetY();
+ int clip_height = obj->GetHeight();
+ if (clip_y < y)
+ {
+ clip_height -= y-clip_y;
+ clip_y = y;
+ }
+ if (clip_height > 0)
+ {
+ if (clip_y + clip_height > y + height)
+ clip_height = y+height-clip_y;
+
+ if (clip_height > 0)
+ obj->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ }
+ }
+ }
+ }
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+bool wxCanvasObjectGroup::IsHit( int x, int y, int margin )
+{
+ wxNode *node = m_objects.Last();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ if (obj->IsHit(x,y,margin))
+ {
+ return true;
+ }
+ }
+ node = node->Previous();
+ }
+ return false;
+}
+
+wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin )
+{
+ wxCanvasObject *obj=0;
+ wxNode *node = m_objects.Last();
+ while (node)
+ {
+ obj=(wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ if (obj->IsHit(x,y,margin))
+ {
+ return obj;
+ }
+ }
+ node = node->Previous();
+ }
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasObjectGroupRef
+//----------------------------------------------------------------------------
+
+wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjectGroup* group)
+ : wxCanvasObject()
+{
+ m_x = x;
+ m_y = y;
+ m_validbounds=false;
+ m_group=group;
+}
+
+void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas)
+{
+ m_owner=canvas;
+ m_group->SetOwner(canvas);
+}
+
+void wxCanvasObjectGroupRef::ExtendArea(int x, int 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;
+ }
+
+}
+
+void wxCanvasObjectGroupRef::Recreate()
+{
+ m_validbounds=false;
+ m_group->Recreate();
+ ExtendArea(m_group->GetXMin(),m_group->GetYMin());
+ ExtendArea(m_group->GetXMax(),m_group->GetYMax());
+
+ //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 ) );
+}
+
+void wxCanvasObjectGroupRef::Render(int xabs, int yabs, int x, int y, int width, int height )
+{
+ wxImage *image = m_owner->GetBuffer();
+ xabs+=m_owner->GetDeviceX(GetPosX());
+ yabs+=m_owner->GetDeviceY(GetPosY());
+
+ int clip_x = xabs + m_group->GetXMin();
+ int clip_width = m_group->GetXMax()-m_group->GetXMin();
+ if (clip_x < x)
+ {
+ clip_width -= x-clip_x;
+ clip_x = x;
+ }
+ if (clip_width > 0)
+ {
+ if (clip_x + clip_width > x + width)
+ clip_width = x+width-clip_x;
+
+ if (clip_width > 0)
+ {
+ int clip_y = yabs + m_group->GetYMin();
+ int clip_height = m_group->GetYMax()-m_group->GetYMin();
+ if (clip_y < y)
+ {
+ clip_height -= y-clip_y;
+ clip_y = y;
+ }
+ if (clip_height > 0)
+ {
+ if (clip_y + clip_height > y + height)
+ clip_height = y+height-clip_y;
+
+ if (clip_height > 0)
+ m_group->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ }
+ }
+ }
+}
+
+void wxCanvasObjectGroupRef::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+bool wxCanvasObjectGroupRef::IsHit( int x, int y, int margin )
+{
+ return m_group->IsHit(x-GetPosX(),y-GetPosY(),margin);
+}
+
+wxCanvasObject* wxCanvasObjectGroupRef::IsHitObject( int x, int y, int margin )
+{
+ return m_group->IsHitObject(x-GetPosX(),y-GetPosY(),margin);
+}
+
+void wxCanvasObjectGroupRef::Move( int x, int y )
+{
+ int old_x = m_x;
+ int old_y = m_y;
+
+ m_x = x;
+ m_y = y;
+
+ if (!m_isControl)
+ {
+ // TODO: sometimes faster to merge into 1 Update or
+ // to break up into four
+ m_owner->Update(m_area.x, m_area.y, m_area.width, m_area.height );
+ //calculate the new 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 ) );
+ m_owner->Update( m_area.x, m_area.y, m_area.width, m_area.height );
+ }
+}
+
+
+//----------------------------------------------------------------------------
+// wxCanvasRect
+//----------------------------------------------------------------------------
+
+wxCanvasRect::wxCanvasRect( double x, double y, double w, double h,
+ unsigned char red, unsigned char green, unsigned char blue )
+ : wxCanvasObject()
+{
+ m_x = x;
+ m_y = y;
+ m_width = w;
+ m_height = h;
+
+ m_red = red;
+ m_green = green;
+ m_blue = blue;
+}
+
+void wxCanvasRect::Recreate()
+{
+ SetArea( m_owner->GetDeviceX( m_x ),
+ m_owner->GetDeviceY( m_y ),
+ m_owner->GetDeviceWidth( m_width ),
+ m_owner->GetDeviceHeight( m_height ) );
+}
+
+void wxCanvasRect::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ wxImage *image = m_owner->GetBuffer();
+ int buffer_x = m_owner->GetBufferX();
+ int buffer_y = m_owner->GetBufferY();
+
+ int start_y = clip_y - buffer_y;
+ int end_y = clip_y+clip_height - buffer_y;
+
+ int start_x = clip_x - buffer_x;
+ int end_x = clip_x+clip_width - buffer_x;
+
+ // 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 );
+}
+
+void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasLine
+//----------------------------------------------------------------------------
+
+wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2,
+ unsigned char red, unsigned char green, unsigned char blue )
+ : wxCanvasObject()
+{
+ m_x1 = x1;
+ m_y1 = y1;
+ m_x2 = x2;
+ m_y2 = y2;
+
+ m_red = red;
+ m_green = green;
+ m_blue = blue;
+}
+
+void wxCanvasLine::Recreate()
+{
+ 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 );
+}
+
+void wxCanvasLine::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
+{
+ wxImage *image = m_owner->GetBuffer();
+ int buffer_x = m_owner->GetBufferX();
+ int buffer_y = m_owner->GetBufferY();
+
+ if ((m_area.width == 0) && (m_area.height == 0))
+ {
+ image->SetRGB( m_area.x-buffer_x, m_area.y-buffer_y, m_red, m_green, m_blue );
+ }
+ else
+ {
+ 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 );
+
+ wxInt32 d, ii, jj, di, ai, si, dj, aj, sj;
+ di = x1 - x2;
+ ai = abs(di) << 1;
+ si = (di < 0)? -1 : 1;
+ dj = y1 - y2;
+ aj = abs(dj) << 1;
+ sj = (dj < 0)? -1 : 1;
+
+ ii = x2;
+ jj = y2;
+
+ if (ai > aj)
+ {
+ // iterate over i
+ d = aj - (ai >> 1);
+
+ while (ii != x1)
+ {
+ 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 );
+ }
+ if (d >= 0)
+ {
+ jj += sj;
+ d -= ai;
+ }
+ ii += si;
+ d += aj;
+ }
+ }
+ else
+ {
+ // iterate over j
+ d = ai - (aj >> 1);
+
+ while (jj != y1)
+ {
+ 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 );
+ }
+ if (d >= 0)
+ {
+ ii += si;
+ d -= aj;
+ }
+ jj += sj;
+ d += ai;
+ }
+ }
+ }
+}
+
+void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
+{
+ // no idea