]> git.saurik.com Git - wxWidgets.git/blobdiff - contrib/src/canvas/canvas.cpp
Added wxTB_NODIVIDER and wxTB_NOALIGN so native Windows toolbar can
[wxWidgets.git] / contrib / src / canvas / canvas.cpp
index f0b3983b5a2a9099b486a9a85072030d56473327..7a63dc03529c7e47fa479acb7a75afb2a18e444c 100644 (file)
@@ -17,9 +17,9 @@
     #pragma hdrstop
 #endif
 
-#include "canvas.h"
-#include "polygon.h"
-#include "liner.h"
+#include "wx/canvas/canvas.h"
+#include "wx/canvas/polygon.h"
+#include "wx/canvas/liner.h"
 
 #ifdef __WXGTK__
     #include <gtk/gtk.h>
@@ -50,6 +50,7 @@ FT_Library g_freetypeLibrary;
 //----------------------------------------------------------------------------
 // wxCanvasObject
 //----------------------------------------------------------------------------
+
 wxCanvasObject::wxCanvasObject()
 {
     // the default event handler is just this object
@@ -59,9 +60,9 @@ wxCanvasObject::wxCanvasObject()
     m_isVector = FALSE;
     m_isImage = FALSE;
     m_visible  = TRUE;
-    m_dragmode = DRAG_ONTOP;
+    m_dragmode = wxDRAG_ONTOP;
 //  handy when debugging
-//  m_dragmode = DRAG_RECTANGLE;
+//  m_dragmode = wxDRAG_RECTANGLE;
     m_dragable = TRUE;
 }
 
@@ -122,11 +123,9 @@ wxEvtHandler *wxCanvasObject::RemoveLastEventHandler(bool deleteHandler)
 
 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() );
@@ -148,8 +147,8 @@ wxRect wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix& cworld)
     wxRect tmparea;
     tmparea.x = x1;
     tmparea.y = y1;
-    tmparea.width = x2-x1;
-    tmparea.height = y2-y1;
+    tmparea.width = x2-x1;    // FIXME +1 ?
+    tmparea.height = y2-y1;   // FIXME +1 ?
 
     return tmparea;
 }
@@ -217,9 +216,7 @@ void wxCanvasObject::MoveRelative( double x, double y )
 
 void wxCanvasObject::DragStart()
 {
-#if IMAGE_CANVAS
-#else
-    if (m_dragmode == DRAG_RECTANGLE)
+    if (m_dragmode == wxDRAG_RECTANGLE)
     {
         this->SetVisible(FALSE);
         wxTransformMatrix help;
@@ -239,7 +236,7 @@ void wxCanvasObject::DragStart()
         dc.SetBrush(wxNullBrush);
         dc.SetPen(wxNullPen);
     }
-    else
+    else if (m_dragmode != wxDRAG_REDRAW)
     {
         this->SetVisible(FALSE);
         wxTransformMatrix help;
@@ -264,15 +261,12 @@ void wxCanvasObject::DragStart()
         tmp.SelectObject(wxNullBitmap);
         dcm.SelectObject(wxNullBitmap);
     }
-#endif
 }
 
 
 void wxCanvasObject::DragRelative( double x, double y)
 {
-#if IMAGE_CANVAS
-#else
-    if (m_dragmode == DRAG_RECTANGLE)
+    if (m_dragmode == wxDRAG_RECTANGLE)
     {
         wxTransformMatrix help;
 
@@ -291,7 +285,7 @@ void wxCanvasObject::DragRelative( double x, double y)
         dc.SetBrush(wxNullBrush);
         dc.SetPen(wxNullPen);
     }
-    else
+    else if (m_dragmode != wxDRAG_REDRAW)
     {
         wxClientDC dc(m_admin->GetActive());
         wxMemoryDC tmp;
@@ -342,14 +336,13 @@ void wxCanvasObject::DragRelative( double x, double y)
         dcm.SelectObject(wxNullBitmap);
         this->SetVisible(FALSE);
     }
-#endif
+    else
+        MoveRelative(x,y);
 }
 
 
 void wxCanvasObject::DragEnd()
 {
-#if IMAGE_CANVAS
-#else
     m_atnewpos = wxBitmap(0,0);
     m_admin->GetActive()->Thaw();
     this->SetVisible(TRUE);
@@ -359,7 +352,6 @@ void wxCanvasObject::DragEnd()
     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 )
@@ -367,9 +359,11 @@ 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)
-       )
+        (y <= m_bbox.GetMaxY()+margin))
+    {
         return this;
+    }
+    
     return (wxCanvasObject*) NULL;
 }
 
@@ -377,6 +371,7 @@ wxCanvasObject* wxCanvasObject::Contains( wxCanvasObject* obj )
 {
     if (obj == this)
         return this;
+        
     return (wxCanvasObject*) NULL;
 }
 
@@ -392,7 +387,7 @@ void wxCanvasObject::ReleaseMouse()
 
 bool wxCanvasObject::IsCapturedMouse()
 {
-    return m_admin->GetActive()->GetCaptured()==this;
+    return (m_admin->GetActive()->GetCaptured() == this);
 }
 
 
@@ -510,7 +505,9 @@ void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
 {
     m_objects.Insert( obj );
     if (m_objects.First())
+    {
         m_bbox.Expand(obj->GetBbox());
+    }
     else
     {
         m_bbox.SetValid(FALSE);
@@ -522,7 +519,9 @@ void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
 {
     m_objects.Append( obj );
     if (m_objects.First())
+    {
         m_bbox.Expand(obj->GetBbox());
+    }
     else
     {
         m_bbox.SetValid(FALSE);
@@ -535,7 +534,9 @@ void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
     m_objects.Insert( before, obj );
     m_bbox.SetValid(FALSE);
     if (m_objects.First())
+    {
         m_bbox.Expand(obj->GetBbox());
+    }
     else
     {
         m_bbox.SetValid(FALSE);
@@ -608,8 +609,8 @@ void wxCanvasObjectGroup::Render(wxTransformMatrix* cworld, int x, int y, int wi
         {
 
             //get area at the absolute position
-            wxRect absareaobject=obj->GetAbsoluteArea(*cworld);
-
+            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.
@@ -657,7 +658,7 @@ void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
 {
 }
 
-wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double margin  )
+wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double margin )
 {
     //KKKfirst check if within bbox
     //will only work if they are always uptodate
@@ -677,7 +678,7 @@ wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double marg
 
         if (!obj->IsControl() )
         {
-            if (obj->IsHitWorld(x,y,margin))
+            if (obj->IsHitWorld(xh,yh,margin))
             {
                 return obj;
             }
@@ -711,8 +712,6 @@ int wxCanvasObjectGroup::IndexOf( wxCanvasObject* obj )
     return m_objects.IndexOf( obj );
 }
 
-
-
 //----------------------------------------------------------------------------
 // wxCanvasObjectRef
 //----------------------------------------------------------------------------
@@ -720,7 +719,7 @@ int wxCanvasObjectGroup::IndexOf( wxCanvasObject* obj )
 wxCanvasObjectRef::wxCanvasObjectRef(double x, double y, wxCanvasObject* obj)
    : wxCanvasObject()
 {
-     lworld.Translate(x,y);
+    lworld.Translate(x,y);
     m_obj = obj;
 
     m_bbox.SetValid(FALSE);
@@ -916,25 +915,6 @@ void wxCanvasRect::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
 {
     if (!m_visible) return;
 
-#if IMAGE_CANVAS
-    wxImage *image = m_admin->GetActive()->GetBuffer();
-
-    int start_y = clip_y;
-    int end_y = clip_y+clip_height;
-
-    int start_x = clip_x;
-    int end_x = clip_x+clip_width;
-
-    // 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
     if (cworld->GetRotation())
     {
         wxPoint *cpoints = new wxPoint[4];
@@ -993,7 +973,6 @@ void wxCanvasRect::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
         dc->DestroyClippingRegion();
         m_pen.SetWidth(pw);
     }
-#endif
 }
 
 void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
@@ -1036,8 +1015,6 @@ void wxCanvasCircle::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, i
 {
     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);
@@ -1055,7 +1032,6 @@ void wxCanvasCircle::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, i
     dc->SetPen(wxNullPen);
     dc->DestroyClippingRegion();
     m_pen.SetWidth(pw);
-#endif
 }
 
 void wxCanvasCircle::WriteSVG( wxTextOutputStream &stream )
@@ -1115,8 +1091,6 @@ void wxCanvasEllipse::Render(wxTransformMatrix* cworld, int clip_x, int clip_y,
 {
     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);
@@ -1136,7 +1110,6 @@ void wxCanvasEllipse::Render(wxTransformMatrix* cworld, int clip_x, int clip_y,
     dc->SetPen(wxNullPen);
     dc->DestroyClippingRegion();
     m_pen.SetWidth(pw);
-#endif
 }
 
 void wxCanvasEllipse::WriteSVG( wxTextOutputStream &stream )
@@ -1201,8 +1174,6 @@ void wxCanvasEllipticArc::Render(wxTransformMatrix* cworld, int clip_x, int clip
 {
     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);
@@ -1225,7 +1196,6 @@ void wxCanvasEllipticArc::Render(wxTransformMatrix* cworld, int clip_x, int clip
     dc->SetPen(wxNullPen);
     dc->DestroyClippingRegion();
     m_pen.SetWidth(pw);
-#endif
 }
 
 void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream &stream )
@@ -1297,80 +1267,6 @@ void wxCanvasLine::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
     x2 = m_admin->LogicalToDeviceX( x2 );
     y2 = m_admin->LogicalToDeviceY( y2 );
 
-#if IMAGE_CANVAS
-    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))
-    {
-        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;
-        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, jj, red, blue, 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, jj, red, blue, green );
-                }
-                if (d >= 0)
-                {
-                    ii += si;
-                    d  -= aj;
-                }
-                jj += sj;
-                d  += ai;
-            }
-        }
-    }
-#else
     wxDC *dc = m_admin->GetActive()->GetDC();
     dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
     int pw=m_pen.GetWidth();
@@ -1380,7 +1276,6 @@ void wxCanvasLine::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
 
     dc->DestroyClippingRegion();
     m_pen.SetWidth(pw);
-#endif
 }
 
 void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
@@ -1421,12 +1316,17 @@ wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w
 
     m_image = image;
 
-    m_orgw=m_image.GetWidth();
-    m_orgh=m_image.GetHeight();
+    m_orgw = m_image.GetWidth();
+    m_orgh = m_image.GetHeight();
 
     m_isImage = TRUE;
-    m_visible = FALSE;
-//KKK    m_visible=TRUE;
+    CalcBoundingBox();
+}
+
+void wxCanvasImage::SetPosXY( double x, double y)
+{
+    m_x = x;
+    m_y = y;
     CalcBoundingBox();
 }
 
@@ -1439,14 +1339,14 @@ void wxCanvasImage::TransLate( double x, double y )
 
 void wxCanvasImage::CalcBoundingBox()
 {
-    m_bbox.SetMin( m_x , m_y);
-    m_bbox.SetMax( m_x + m_width , m_y + m_height);
+    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());
@@ -1461,25 +1361,7 @@ void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, in
     y = m_admin->LogicalToDeviceY(y);
 
 
-#if IMAGE_CANVAS
-    if ((clip_x == xabs + tmparea.x) &&
-        (clip_y == yabs + tmparea.y) &&
-        (clip_width == tmparea.width) &&
-        (clip_height == tmparea.height))
-    {
-        m_admin->GetActive()->GetBuffer()->Paste( m_tmp, clip_x, clip_y );
-    }
-    else
-    {
-        // 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
+    // What is this???
     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() ) ||
@@ -1503,29 +1385,54 @@ void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, in
         dc->DestroyClippingRegion();
         return;
     }
+    
+    wxImage tmp;
+    bool is_cashed = FALSE;
 
-    if ((m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) == m_image.GetWidth()) &&
-        (m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) == m_image.GetHeight()))
+    if (m_cImage.Ok() && (m_cW == m_bbox.GetWidth()) && (m_cH == m_bbox.GetHeight()))
     {
-        m_tmp = m_image;
+        // use cached image
+        tmp = m_cImage;
+        is_cashed = TRUE;
     }
     else
     {
-        m_tmp = m_image.Scale( m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()),
-                               m_admin->LogicalToDeviceYRel( m_bbox.GetHeight()) );
+        if ((m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) == m_image.GetWidth()) &&
+            (m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) == m_image.GetHeight()))
+        {
+            tmp = m_image;
+        }
+        else
+        {
+            tmp = m_image.Scale( m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()),
+                                 m_admin->LogicalToDeviceYRel( m_bbox.GetHeight()) );
+        }
+        
+        // create cached image
+        m_cImage = tmp;
+        m_cW = tmp.GetWidth();
+        m_cH = tmp.GetHeight();
     }
 
-    wxBitmap bmp;
 //    wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
     wxPoint centr(0,0);
 
-    if (cworld->GetRotation())
+    wxBitmap bmp;
+    
+    if (m_cBitmap.Ok() && is_cashed && (m_cR == cworld->GetRotation()))
     {
-        bmp=m_tmp.Rotate(-cworld->GetRotation()/180.0 * pi,centr, TRUE,  NULL).ConvertToBitmap();
+        bmp = m_cBitmap;
     }
     else
     {
-        bmp = m_tmp.ConvertToBitmap();
+        if (cworld->GetRotation())
+            tmp = tmp.Rotate(-cworld->GetRotation()/180.0 * pi, centr, TRUE, NULL );
+            
+        bmp = tmp.ConvertToBitmap();
+        
+        // create cached bitmap
+        m_cBitmap = bmp;
+        m_cR = cworld->GetRotation();
     }
 
     wxDC *dc = m_admin->GetActive()->GetDC();
@@ -1551,30 +1458,10 @@ void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, in
     }
     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);
-        }
+        dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
+        dc->DrawBitmap( bmp, x, y, TRUE );
+        dc->DestroyClippingRegion();
     }
-#endif
 }
 
 void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
@@ -1767,44 +1654,6 @@ void wxCanvasText::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
     }
 #endif
 
-#if IMAGE_CANVAS
-    wxImage *image = m_admin->GetActive()->GetBuffer();
-
-    // local coordinates
-    int start_x = clip_x - tmparea.x;
-    int end_x = clip_width + start_x;
-    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*tmparea.width + x];
-            if (alpha)
-            {
-                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 );
-                    continue;
-                }
-                int red1 = (m_red * alpha) / 255;
-                int green1 = (m_green * alpha) / 255;
-                int blue1 = (m_blue * alpha) / 255;
-
-                alpha = 255-alpha;
-                int red2 = image->GetRed( image_x, image_y );
-                int green2 = image->GetGreen( image_x, image_y );
-                int blue2 = image->GetBlue( image_x, image_y );
-                red2 = (red2 * alpha) / 255;
-                green2 = (green2 * alpha) / 255;
-                blue2 = (blue2 * alpha) / 255;
-
-                image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
-            }
-        }
-#else
     wxBitmap *bitmap = m_admin->GetActive()->GetBuffer();
     wxRect sub_rect( clip_x, clip_y, clip_width, clip_height );
     wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) );
@@ -1850,7 +1699,6 @@ void wxCanvasText::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int
 
    wxDC *dc = m_admin->GetActive()->GetDC();
    dc->DrawBitmap( sub_bitmap, clip_x, clip_y );
-#endif
 }
 
 void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
@@ -1878,14 +1726,12 @@ void wxCanvasText::CalcBoundingBox()
 // wxCanvas
 //----------------------------------------------------------------------------
 
-IMPLEMENT_CLASS(wxCanvas,wxWindow)
+IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
 
-BEGIN_EVENT_TABLE(wxCanvas,wxWindow)
-    EVT_SCROLLWIN( wxCanvas::OnScroll )
-    EVT_CHAR( wxCanvas::OnChar )
+BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
     EVT_PAINT( wxCanvas::OnPaint )
-    EVT_SIZE( wxCanvas::OnSize )
     EVT_IDLE( wxCanvas::OnIdle )
+    EVT_SIZE( wxCanvas::OnSize )
     EVT_MOUSE_EVENTS( wxCanvas::OnMouse )
     EVT_SET_FOCUS( wxCanvas::OnSetFocus )
     EVT_KILL_FOCUS( wxCanvas::OnKillFocus )
@@ -1894,20 +1740,23 @@ END_EVENT_TABLE()
 
 wxCanvas::wxCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id,
     const wxPoint &position, const wxSize& size, long style ) :
-    wxWindow( parent, id, position, size, style )
+    wxScrolledWindow( parent, id, position, size, style )
 {
+    // These are unused in wxVectorCanvas
+    m_bufferX = 0;
+    m_bufferY = 0;
+    
     m_admin = admin;
-    m_admin->Append(this);
+    m_admin->Append( this );
+    
     m_needUpdate = FALSE;
     m_background = *wxWHITE;
     m_lastMouse = (wxCanvasObject*)NULL;
     m_captureMouse = (wxCanvasObject*)NULL;
-    m_frozen = TRUE;
+    m_frozen = FALSE;
     m_oldDeviceX = 0;
     m_oldDeviceY = 0;
-    m_scrolled=FALSE;
-    m_root=0;
-    m_yaxis=FALSE;
+    m_root = (wxCanvasObjectGroup*)NULL;
 }
 
 wxCanvas::~wxCanvas()
@@ -1922,31 +1771,37 @@ wxCanvas::~wxCanvas()
     }
 }
 
+double wxCanvas::GetMinX() const
+{
+    return 0.0;
+}
+
+double wxCanvas::GetMinY() const
+{
+    return 0.0;
+}
+
+double wxCanvas::GetMaxX() const
+{
+   int width;
+   GetVirtualSize( &width, NULL );
+   return width;
+}
+
+double wxCanvas::GetMaxY() const
+{
+   int height;
+   GetVirtualSize( NULL, &height );
+   return height;
+}
+
 void wxCanvas::SetColour( const wxColour& background )
 {
-    m_background=background;
+    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++)
-        for (int x = 0; x < m_buffer.GetWidth(); x++)
-        {
-            data[0] = red;
-            data++;
-            data[0] = green;
-            data++;
-            data[0] = blue;
-            data++;
-        }
-#else
     wxMemoryDC dc;
     dc.SelectObject( m_buffer );
     dc.SetPen( *wxTRANSPARENT_PEN );
@@ -1954,7 +1809,6 @@ void wxCanvas::SetColour( const wxColour& background )
     dc.SetBrush( brush );
     dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
     dc.SelectObject( wxNullBitmap );
-#endif
 }
 
 void wxCanvas::SetCaptureMouse( wxCanvasObject *obj )
@@ -1990,11 +1844,13 @@ void wxCanvas::Thaw()
     m_frozen = FALSE;
 
     if (m_buffer.Ok())
-        Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight() );
+        Update( m_bufferX, m_bufferY, 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;
@@ -2002,29 +1858,29 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit )
     if (m_frozen) return;
 
     // clip to buffer
-    if (x < 0)
+    if (x < m_bufferX)
     {
-        width -= -x;
-        x = 0;
+        width -= m_bufferX-x;
+        x = m_bufferX;
     }
     if (width <= 0) return;
 
-    if (y < 0)
+    if (y < m_bufferY)
     {
-        height -= -y;
-        y = 0;
+        height -= m_bufferY-y;
+        y = m_bufferY;
     }
     if (height <= 0) return;
 
-    if (x+width > m_buffer.GetWidth())
+    if (x+width > m_bufferX+m_buffer.GetWidth())
     {
-        width = m_buffer.GetWidth() - x;
+        width = m_bufferX+m_buffer.GetWidth() - x;
     }
     if (width <= 0) return;
 
-    if (y+height > m_buffer.GetHeight())
+    if (y+height > m_bufferY+m_buffer.GetHeight())
     {
-        height = m_buffer.GetHeight() - y;
+        height = m_bufferY+m_buffer.GetHeight() - y;
     }
     if (height <= 0) return;
 
@@ -2040,31 +1896,17 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit )
 
     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;
-    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, red, green, blue );
-
-    m_root->Render(&cworld, x, y, width, height );
-#else
     wxMemoryDC dc;
     dc.SelectObject( m_buffer );
 
     dc.SetPen( *wxTRANSPARENT_PEN );
-    wxBrush brush( m_background , wxSOLID );
+    wxBrush brush( m_background, wxSOLID );
     dc.SetBrush( brush );
+    dc.SetLogicalFunction(wxCOPY);
 
+#if 0
     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();
@@ -2072,19 +1914,23 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit )
     else
     {
         dc.Clear();
-        dc.SetLogicalFunction(wxCOPY);
         dc.DrawRectangle(0,0,m_buffer.GetWidth(),m_buffer.GetHeight());
     }
+#else
+    // No idea, what the code up there does.
+    dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height );
+#endif    
+   
     dc.SetBrush(wxNullBrush);
     dc.SetPen(wxNullPen);
 
-    m_renderDC=&dc;
+    dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
+    m_renderDC = &dc;
 
-    m_root->Render(&cworld,x, y, width, height );
+    m_root->Render( &cworld, x, y, width, height );
 
-    m_renderDC=0;
+    m_renderDC = NULL;
     dc.SelectObject( wxNullBitmap );
-#endif
 }
 
 void wxCanvas::BlitBuffer( wxDC &dc )
@@ -2093,55 +1939,18 @@ void wxCanvas::BlitBuffer( wxDC &dc )
     while (node)
     {
         wxRect *rect = (wxRect*) node->Data();
-
-#if IMAGE_CANVAS
-
-        wxImage sub_image( m_buffer.GetSubImage( *rect ) );
-#ifdef __WXGTK__
-        int bpp = wxDisplayDepth();
-        if (bpp > 8)
-        {
-            // the init code is doubled in wxImage
-            static bool s_hasInitialized = FALSE;
-
-            if (!s_hasInitialized)
-            {
-                gdk_rgb_init();
-                s_hasInitialized = TRUE;
-            }
-
-            gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window,
-                            m_wxwindow->style->black_gc,
-                            sub_rect.x, sub_rect.y,
-                            sub_image.GetWidth(), sub_image.GetHeight(),
-                            GDK_RGB_DITHER_NONE,
-                            sub_image.GetData(),
-                            sub_image.GetWidth()*3 );
-        }
-        else
-        {
-            wxBitmap bitmap( sub_image.ConvertToBitmap() );
-            dc.DrawBitmap( bitmap, rect->x, rect->y );
-        }
-#else
-        wxBitmap bitmap( sub_image.ConvertToBitmap() );
-        dc.DrawBitmap( bitmap, rect->x, rect->y );
-#endif
-
-#else  // IMAGE_CANVAS
-
-        // Maybe clipping use SetClipping() is faster than
-        // getting the subrect first and drawing it then?
-
-//        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 );
+        dc.Blit( rect->x,
+                 rect->y,
+                 rect->width,
+                 rect->height,
+                 &mdc,
+                 rect->x - m_bufferX,
+                 rect->y - m_bufferY ); 
         mdc.SelectObject( wxNullBitmap );
 
-#endif
         delete rect;
         m_updateRects.DeleteNode( node );
         node = m_updateRects.First();
@@ -2162,6 +1971,30 @@ void wxCanvas::UpdateNow()
     BlitBuffer( dc );
 }
 
+void wxCanvas::OnSize(wxSizeEvent &event)
+{
+    int w,h;
+    GetClientSize( &w, &h );
+    m_buffer = wxBitmap( w, h );
+
+    CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
+
+    wxNode *node = m_updateRects.First();
+    while (node)
+    {
+        wxRect *rect = (wxRect*) node->Data();
+        delete rect;
+        m_updateRects.DeleteNode( node );
+        node = m_updateRects.First();
+    }
+
+    m_frozen = FALSE;
+
+    Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
+
+    event.Skip();
+}
+
 void wxCanvas::OnPaint(wxPaintEvent &event)
 {
     wxPaintDC dc(this);
@@ -2189,6 +2022,8 @@ void wxCanvas::OnPaint(wxPaintEvent &event)
 
         if ((w > 0) && (h > 0))
         {
+            x += m_bufferX;
+            y += m_bufferY;
             m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
         }
 
@@ -2207,188 +2042,54 @@ void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
     dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
     BlitBuffer( dc );
 
-    if (dy != 0)
-    {
-        double dyv=DeviceToLogicalYRel(dy);
-        m_virt_minY=m_virt_minY-dyv;
-        m_virt_maxY=m_virt_maxY-dyv;
-    }
-    if (dx != 0)
+    // 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 );
+    
+    // Update everything.
+    Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
+
+    // Scroll, actually.
+    wxWindow::ScrollWindow( dx, dy, rect );
+}
+
+void wxCanvas::OnMouse(wxMouseEvent &event)
+{
+    m_admin->SetActive(this);
+    if (!m_root)
     {
-        double dxv=DeviceToLogicalXRel(dx);
-        m_virt_minX=m_virt_minX-dxv;
-        m_virt_maxX=m_virt_maxX-dxv;
+        event.Skip();
+        return;
     }
 
-    m_admin->SetActive(this);
-    SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE);
+    int x = event.GetX();
+    int y = event.GetY();
 
-#if IMAGE_CANVAS
-    unsigned char* data = m_buffer.GetData();
+    //to world coordinates to do hit test in world coordinates
+    double xw = DeviceToLogicalX( x );
+    double yw = DeviceToLogicalY( y );
 
-    if (dy != 0)
+    //make a select margin of 2 pixels, so also zero line thickness will be hit
+    double margin = DeviceToLogicalXRel( 2 );
+
+    if (event.GetEventType() == wxEVT_MOTION)
     {
-        if (dy > 0)
+        if (m_captureMouse) //no matter what go to this one
         {
-            unsigned char *source = data;
-            unsigned char *dest = data + (dy * m_buffer.GetWidth() * 3);
-            size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()-dy));
-            memmove( dest, source, count );
-
-            // 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( 0, 0, m_buffer.GetWidth(), dy, FALSE );
-        }
-        else
-        {
-            unsigned char *dest = data;
-            unsigned char *source = data + (-dy * m_buffer.GetWidth() * 3);
-            size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()+dy));
-            memmove( dest, source, count );
-
-            // 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( 0, m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE );
-        }
-    }
-
-    if (dx != 0)
-    {
-        if (dx > 0)
-        {
-            unsigned char *source = data;
-            for (int y = 0; y < m_buffer.GetHeight(); y++)
-            {
-                unsigned char *dest = source + dx*3;
-                memmove( dest, source, (m_buffer.GetWidth()-dx) * 3 );
-                source += m_buffer.GetWidth()*3;
-            }
-
-            // 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( 0,0, dx, m_buffer.GetHeight(), FALSE );
-        }
-        else
-        {
-            unsigned char *dest = data;
-            for (int y = 0; y < m_buffer.GetHeight(); y++)
-            {
-                unsigned char *source = dest - dx*3;
-                memmove( dest, source, (m_buffer.GetWidth()+dx) * 3 );
-                dest += m_buffer.GetWidth()*3;
-            }
-
-            // 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_buffer.GetWidth()+dx, 0, -dx, m_buffer.GetHeight(), FALSE );
-        }
-    }
-#else
-
-    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();
-
-    //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)
-    {
-        if (m_captureMouse) //no matter what go to this one
-        {
-            wxMouseEvent child_event( wxEVT_MOTION );
-            child_event.SetEventObject(m_captureMouse);
-            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_controlDown = event.m_controlDown;
-            child_event.m_shiftDown = event.m_shiftDown;
-            child_event.m_altDown = event.m_altDown;
-            child_event.m_metaDown = event.m_metaDown;
-
-            m_captureMouse->ProcessCanvasObjectEvent( child_event );
-            return;
+            wxMouseEvent child_event( wxEVT_MOTION );
+            child_event.SetEventObject(m_captureMouse);
+            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_controlDown = event.m_controlDown;
+            child_event.m_shiftDown = event.m_shiftDown;
+            child_event.m_altDown = event.m_altDown;
+            child_event.m_metaDown = event.m_metaDown;
+
+            m_captureMouse->ProcessCanvasObjectEvent( child_event );
+            return;
         }
         else
         {
@@ -2494,15 +2195,204 @@ void wxCanvas::OnMouse(wxMouseEvent &event)
     event.Skip();
 }
 
-void wxCanvas::OnSize(wxSizeEvent &event)
+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::OnEraseBackground(wxEraseEvent &event)
+{
+}
+
+// coordinates conversions
+// -----------------------
+double wxCanvas::DeviceToLogicalX(int x) const
+{
+    return (double)(x);
+}
+
+double wxCanvas::DeviceToLogicalY(int y) const
+{
+    return (double)(y);
+}
+
+double wxCanvas::DeviceToLogicalXRel(int x) const
+{
+    return (double)x;
+}
+
+double wxCanvas::DeviceToLogicalYRel(int y) const
+{
+    return (double)y;
+}
+
+int wxCanvas::LogicalToDeviceX(double x) const
+{
+    return (int)(x + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceY(double y) const
+{
+    return (int)(y + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceXRel(double x) const
+{
+    return (int)(x + 0.5);
+}
+
+int wxCanvas::LogicalToDeviceYRel(double y) const
+{
+    return (int)(y + 0.5);
+}
+
+//----------------------------------------------------------------------------
+// wxVectorCanvas
+//----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxVectorCanvas,wxCanvas)
+
+BEGIN_EVENT_TABLE(wxVectorCanvas,wxCanvas)
+    EVT_SCROLLWIN( wxVectorCanvas::OnScroll )
+    EVT_CHAR( wxVectorCanvas::OnChar )
+    EVT_SIZE( wxVectorCanvas::OnSize )
+END_EVENT_TABLE()
+
+wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id,
+    const wxPoint &position, const wxSize& size, long style ) :
+    wxCanvas( admin, parent, id, position, size, style )
+{
+    m_scrolled = FALSE;
+    m_yaxis = FALSE;
+}
+
+double wxVectorCanvas::GetMinX() const
+{
+    return m_virt_minX;
+}
+
+double wxVectorCanvas::GetMinY() const
+{
+    return m_virt_minY;
+}
+
+double wxVectorCanvas::GetMaxX() const
+{
+   return m_virt_maxX;
+}
+
+double wxVectorCanvas::GetMaxY() const
+{
+    return m_virt_maxY;
+}
+
+void wxVectorCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
+{
+    // 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.
+    wxClientDC dc( this );
+    dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
+    BlitBuffer( dc );
+
+    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 (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 );
+    }
+    
+    wxWindow::ScrollWindow( dx, dy, rect );
+
+    //must be done now because quick repeated scrolling will prevent wxPaint
+    //from doing it properly
+    UpdateNow();
+}
+
+void wxVectorCanvas::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 );
     dc.SelectObject( m_buffer );
@@ -2512,8 +2402,6 @@ void wxCanvas::OnSize(wxSizeEvent &event)
     dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
     dc.SelectObject( wxNullBitmap );
 
-#endif
-
     wxNode *node = m_updateRects.First();
     while (node)
     {
@@ -2530,35 +2418,12 @@ void wxCanvas::OnSize(wxSizeEvent &event)
 
     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::OnEraseBackground(wxEraseEvent &event)
-{
+//    event.Skip();
 }
 
-
-
 // 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)
+void wxVectorCanvas::SetMappingScroll( double vx1,    double vy1, double vx2, double vy2, bool border)
 {
     int dwxi,dwyi;
     GetClientSize(&dwxi,&dwyi);
@@ -2607,11 +2472,13 @@ void wxCanvas::SetMappingScroll( double vx1,    double vy1, double vx2, double v
      // 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
@@ -2661,7 +2528,7 @@ void wxCanvas::SetMappingScroll( double vx1,    double vy1, double vx2, double v
 }
 
 
-void wxCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2)
+void wxVectorCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2)
 {
     m_virtm_minX=vx1;
     m_virtm_minY=vy1;
@@ -2673,70 +2540,69 @@ void wxCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2)
     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);
+    SetScrollbar(wxHORIZONTAL,(m_virt_minX-m_virtm_minX)/dmvx *1000,dvx/dmvx *1000,1000,FALSE);
     if (m_yaxis)
     {
-        SetScrollbar(wxVERTICAL,(m_virtm_maxY-m_virt_maxY)/dmvy *1000,dvy/dmvy *1000,1000,true);
+        SetScrollbar(wxVERTICAL,(m_virtm_maxY-m_virt_maxY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE);
     }
     else
     {
-        SetScrollbar(wxVERTICAL,(m_virt_minY-m_virtm_minY)/dmvy *1000,dvy/dmvy *1000,1000,true);
+        SetScrollbar(wxVERTICAL,(m_virt_minY-m_virtm_minY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE);
     }
 
-    m_scrolled=true;
+    m_scrolled=TRUE;
 }
 
 // coordinates conversions
 // -----------------------
-double wxCanvas::DeviceToLogicalX(int x) const
+double wxVectorCanvas::DeviceToLogicalX(int x) const
 {
     return m_inverse_mapping.GetValue(0,0) * x + m_inverse_mapping.GetValue(2,0);
 }
 
-double wxCanvas::DeviceToLogicalY(int y) const
+double wxVectorCanvas::DeviceToLogicalY(int y) const
 {
     return m_inverse_mapping.GetValue(1,1) * y + m_inverse_mapping.GetValue(2,1);
 }
 
-double wxCanvas::DeviceToLogicalXRel(int x) const
+double wxVectorCanvas::DeviceToLogicalXRel(int x) const
 {
     return x*m_inverse_mapping.GetValue(0,0);
 }
 
-double wxCanvas::DeviceToLogicalYRel(int y) const
+double wxVectorCanvas::DeviceToLogicalYRel(int y) const
 {
     return y*m_inverse_mapping.GetValue(1,1);
 }
 
-int wxCanvas::LogicalToDeviceX(double x) const
+int wxVectorCanvas::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
+int wxVectorCanvas::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
+int wxVectorCanvas::LogicalToDeviceXRel(double x) const
 {
     return (int) (x*m_mapping_matrix.GetValue(0,0) + 0.5);
 }
 
-int wxCanvas::LogicalToDeviceYRel(double y) const
+int wxVectorCanvas::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()
+wxTransformMatrix wxVectorCanvas::GetInverseMappingMatrix()
 {
     return m_inverse_mapping;
 }
 
-wxTransformMatrix wxCanvas::GetMappingMatrix()
+wxTransformMatrix wxVectorCanvas::GetMappingMatrix()
 {
     return m_mapping_matrix;
 }
@@ -2746,7 +2612,7 @@ wxTransformMatrix wxCanvas::GetMappingMatrix()
 // scrolling behaviour
 // ----------------------------------------------------------------------------
 
-void wxCanvas::OnScroll(wxScrollWinEvent& event)
+void wxVectorCanvas::OnScroll(wxScrollWinEvent& event)
 {
     if (event.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE)
     {
@@ -2818,7 +2684,7 @@ void wxCanvas::OnScroll(wxScrollWinEvent& event)
 
 }
 
-void wxCanvas::OnChar(wxKeyEvent& event)
+void wxVectorCanvas::OnChar(wxKeyEvent& event)
 {
     switch ( event.KeyCode() )
     {
@@ -2899,41 +2765,9 @@ void wxCanvas::OnChar(wxKeyEvent& event)
 }
 
 
-
-
-//--------------------------------------------------------------------
-// wxCanvasModule
-//--------------------------------------------------------------------
-
-class wxCanvasModule : public wxModule
-{
-public:
-    virtual bool OnInit();
-    virtual void OnExit();
-
-private:
-    DECLARE_DYNAMIC_CLASS(wxCanvasModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule)
-
-bool wxCanvasModule::OnInit()
-{
-#if wxUSE_FREETYPE
-    int error = FT_Init_FreeType( &g_freetypeLibrary );
-    if (error) return FALSE;
-#endif
-
-    return TRUE;
-}
-
-void wxCanvasModule::OnExit()
-{
-#if wxUSE_FREETYPE
-    FT_Done_FreeType( g_freetypeLibrary );
-#endif
-}
-
+//----------------------------------------------------------------------------
+// wxCanvasAdmin
+//----------------------------------------------------------------------------
 
 wxCanvasAdmin::wxCanvasAdmin()
 {
@@ -2942,8 +2776,6 @@ wxCanvasAdmin::wxCanvasAdmin()
 
 wxCanvasAdmin::~wxCanvasAdmin()
 {
-
-
 }
 
 
@@ -3071,5 +2903,39 @@ void wxCanvasAdmin::SetActive(wxCanvas* activate)
         node = node->Next();
     }
 }
+//--------------------------------------------------------------------
+// wxCanvasModule
+//--------------------------------------------------------------------
+
+class wxCanvasModule : public wxModule
+{
+public:
+    virtual bool OnInit();
+    virtual void OnExit();
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxCanvasModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule)
+
+bool wxCanvasModule::OnInit()
+{
+#if wxUSE_FREETYPE
+    int error = FT_Init_FreeType( &g_freetypeLibrary );
+    if (error) return FALSE;
+#endif
+
+    return TRUE;
+}
+
+void wxCanvasModule::OnExit()
+{
+#if wxUSE_FREETYPE
+    FT_Done_FreeType( g_freetypeLibrary );
+#endif
+}
+
+