From: Robert Roebling Date: Mon, 4 Sep 2000 15:39:52 +0000 (+0000) Subject: Virtualized coordinate system for wxCanvas. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/4dbd4ee6042dd8da797a790e53abcfe32b27bb7b Virtualized coordinate system for wxCanvas. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8251 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/contrib/include/wx/canvas/canvas.h b/contrib/include/wx/canvas/canvas.h index b82b3da636..47f2fb563b 100644 --- a/contrib/include/wx/canvas/canvas.h +++ b/contrib/include/wx/canvas/canvas.h @@ -31,18 +31,25 @@ class wxCanvas; class wxCanvasObject: public wxEvtHandler { public: - wxCanvasObject( int x, int y, int width, int height ); + wxCanvasObject(); + + // Area occupied by object. Used for clipping, intersection, + // mouse enter etc. Screen coordinates + void SetArea( int x, int y, int width, int height ); + void SetArea( wxRect rect ); // These are for screen output only therefore use // int as coordinates. - virtual void Move( int x, int y ); virtual bool IsHit( int x, int y, int margin = 0 ); virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); + // use doubles later + virtual void Move( int x, int y ); + // Once we have world coordinates in doubles, this will get // called for every object if the world coordinate system // changes (zooming). - virtual void Rerender(); + virtual void Recreate(); // Later... virtual void WriteSVG( wxTextOutputStream &stream ); @@ -75,12 +82,20 @@ protected: class wxCanvasRect: public wxCanvasObject { public: - wxCanvasRect( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ); + wxCanvasRect( double x, double y, double w, double h, + unsigned char red, unsigned char green, unsigned char blue ); + + virtual void Recreate(); virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); virtual void WriteSVG( wxTextOutputStream &stream ); private: + double m_x; + double m_y; + double m_width; + double m_height; + unsigned char m_red; unsigned char m_green; unsigned char m_blue; @@ -93,12 +108,20 @@ private: class wxCanvasLine: public wxCanvasObject { public: - wxCanvasLine( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ); + wxCanvasLine( double x1, double y1, double x1, double y1, + unsigned char red, unsigned char green, unsigned char blue ); + + virtual void Recreate(); virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); virtual void WriteSVG( wxTextOutputStream &stream ); private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + unsigned char m_red; unsigned char m_green; unsigned char m_blue; @@ -111,13 +134,21 @@ private: class wxCanvasImage: public wxCanvasObject { public: - wxCanvasImage( const wxImage &image, int x, int y ); + wxCanvasImage( const wxImage &image, double x, double y, double w, double h ); + + virtual void Recreate(); virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); virtual void WriteSVG( wxTextOutputStream &stream ); private: + double m_x; + double m_y; + double m_width; + double m_height; + wxImage m_image; + wxImage m_tmp; }; //---------------------------------------------------------------------------- @@ -130,8 +161,9 @@ public: wxCanvasControl( wxWindow *control ); ~wxCanvasControl(); + virtual void Recreate(); + virtual void Move( int x, int y ); - void UpdateSize(); private: wxWindow *m_control; @@ -144,19 +176,22 @@ private: class wxCanvasText: public wxCanvasObject { public: - wxCanvasText( const wxString &text, int x, int y, const wxString &foneFile, int size ); + wxCanvasText( const wxString &text, double x, double y, const wxString &foneFile, int size ); ~wxCanvasText(); + void Recreate(); + virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height ); virtual void WriteSVG( wxTextOutputStream &stream ); - void CreateBuffer(); void SetRGB( unsigned char red, unsigned char green, unsigned char blue ); void SetFlag( int flag ); int GetFlag() { return m_flag; } private: wxString m_text; + double m_x; + double m_y; unsigned char *m_alpha; void *m_faceData; int m_flag; @@ -194,6 +229,18 @@ public: virtual void Insert( size_t before, wxCanvasObject* obj ); virtual void Remove( wxCanvasObject* obj ); + // override these to change your coordiate system ... + virtual int GetDeviceX( double x ); + virtual int GetDeviceY( double y ); + virtual int GetDeviceWidth( double width ); + virtual int GetDeviceHeight( double height ); + + // ... and call this to tell all objets to recreate then + virtual void Recreate(); + + void CaptureMouse( wxCanvasObject *obj ); + void ReleaseMouse(); + wxImage *GetBuffer() { return &m_buffer; } bool NeedUpdate() { return m_needUpdate; } bool IsFrozen() { return m_frozen; } @@ -208,6 +255,7 @@ private: unsigned char m_green,m_red,m_blue; bool m_frozen; wxCanvasObject *m_lastMouse; + wxCanvasObject *m_captureMouse; friend class wxCanvasObject; diff --git a/contrib/samples/canvas/test/test.cpp b/contrib/samples/canvas/test/test.cpp index 6f109d3f2c..a812ff6eb1 100644 --- a/contrib/samples/canvas/test/test.cpp +++ b/contrib/samples/canvas/test/test.cpp @@ -116,14 +116,14 @@ MyFrame::MyFrame() wxBitmap bitmap( smile_xpm ); wxImage image( bitmap ); - m_sm1 = new wxCanvasImage( image, 0, 70 ); + m_sm1 = new wxCanvasImage( image, 0,70,16,16 ); m_canvas->Append( m_sm1 ); int i; for (i = 10; i < 300; i+=10) m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) ); - m_sm2 = new wxCanvasImage( image, 0, 140 ); + m_sm2 = new wxCanvasImage( image, 0,140,24,24 ); m_canvas->Append( m_sm2 ); for (i = 15; i < 300; i+=10) @@ -135,13 +135,13 @@ MyFrame::MyFrame() m_canvas->Append( new wxCanvasText( "Hello", 180, 50, wxGetApp().GetFontPath() + "/times.ttf", 20 ) ); - m_sm3 = new wxCanvasImage( image, 0, 210 ); + m_sm3 = new wxCanvasImage( image, 0,210,32,32 ); m_canvas->Append( m_sm3 ); for (i = 10; i < 300; i+=10) - m_canvas->Append( new wxCanvasLine( 10,150,i,200, 0,255,0 ) ); + m_canvas->Append( new wxCanvasLine( 10,150,i,300, 0,255,0 ) ); - m_sm4 = new wxCanvasImage( image, 0, 270 ); + m_sm4 = new wxCanvasImage( image, 0,270,64,32 ); m_canvas->Append( m_sm4 ); m_canvas->Thaw(); diff --git a/contrib/src/canvas/canvas.cpp b/contrib/src/canvas/canvas.cpp index ead4b808b7..ddb3b06615 100644 --- a/contrib/src/canvas/canvas.cpp +++ b/contrib/src/canvas/canvas.cpp @@ -45,16 +45,32 @@ FT_Library g_freetypeLibrary; // wxCanvasObject //---------------------------------------------------------------------------- -wxCanvasObject::wxCanvasObject( int x, int y, int width, int height ) +wxCanvasObject::wxCanvasObject() { m_owner = NULL; + m_area.x = -1; + m_area.y = -1; + m_area.width = -1; + m_area.height = -1; + m_isControl = FALSE; + m_isVector = FALSE; + m_isImage = FALSE; +} + +void wxCanvasObject::SetArea( int x, int y, int width, int height ) +{ m_area.x = x; m_area.y = y; m_area.width = width; m_area.height = height; - m_isControl = FALSE; - m_isVector = FALSE; - m_isImage = FALSE; +} + +void wxCanvasObject::SetArea( wxRect rect ) +{ + m_area.x = rect.x; + m_area.y = rect.y; + m_area.width = rect.width; + m_area.height = rect.height; } void wxCanvasObject::Move( int x, int y ) @@ -86,7 +102,7 @@ void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_he { } -void wxCanvasObject::Rerender() +void wxCanvasObject::Recreate() { } @@ -98,14 +114,28 @@ void wxCanvasObject::WriteSVG( wxTextOutputStream &stream ) // wxCanvasRect //---------------------------------------------------------------------------- -wxCanvasRect::wxCanvasRect( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ) - : wxCanvasObject( x, y, w, h ) +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 clip_x, int clip_y, int clip_width, int clip_height ) { wxImage *image = m_owner->GetBuffer(); @@ -123,14 +153,41 @@ void wxCanvasRect::WriteSVG( wxTextOutputStream &stream ) // wxCanvasLine //---------------------------------------------------------------------------- -wxCanvasLine::wxCanvasLine( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue ) - : wxCanvasObject( x, y, w, h ) +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 clip_x, int clip_y, int clip_width, int clip_height ) { wxImage *image = m_owner->GetBuffer(); @@ -141,10 +198,10 @@ void wxCanvasLine::Render( int clip_x, int clip_y, int clip_width, int clip_heig } else { - int x1 = m_area.x; - int y1 = m_area.y; - int x2 = m_area.x+m_area.width; - int y2 = m_area.y+m_area.height; + 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 ); wxInt32 d, ii, jj, di, ai, si, dj, aj, sj; di = x1 - x2; @@ -211,13 +268,32 @@ void wxCanvasLine::WriteSVG( wxTextOutputStream &stream ) // wxCanvasImage //---------------------------------------------------------------------------- -wxCanvasImage::wxCanvasImage( const wxImage &image, int x, int y ) - : wxCanvasObject( x, y, image.GetWidth(), image.GetHeight() ) +wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w, double h ) + : wxCanvasObject() { + m_x = x; + m_y = y; + m_width = w; + m_height = h; + m_image = image; m_isImage = TRUE; } +void wxCanvasImage::Recreate() +{ + SetArea( m_owner->GetDeviceX( m_x ), + m_owner->GetDeviceY( m_y ), + m_owner->GetDeviceWidth( m_width ), + m_owner->GetDeviceHeight( m_height ) ); + + if ((m_area.width == m_image.GetWidth()) && + (m_area.width == m_image.GetWidth())) + m_tmp = m_image; + else + m_tmp = m_image.Scale( m_area.width, m_area.height ); +} + void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height ) { if ((clip_x == m_area.x) && @@ -225,7 +301,7 @@ void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_hei (clip_width == m_area.width) && (clip_height == m_area.height)) { - m_owner->GetBuffer()->Paste( m_image, clip_x, clip_y ); + m_owner->GetBuffer()->Paste( m_tmp, clip_x, clip_y ); } else { @@ -234,7 +310,7 @@ void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_hei int start_y = clip_y - m_area.y; wxRect rect( start_x, start_y, clip_width, clip_height ); - wxImage sub_image( m_image.GetSubImage( rect ) ); + wxImage sub_image( m_tmp.GetSubImage( rect ) ); m_owner->GetBuffer()->Paste( sub_image, clip_x, clip_y ); } } @@ -249,11 +325,10 @@ void wxCanvasImage::WriteSVG( wxTextOutputStream &stream ) //---------------------------------------------------------------------------- wxCanvasControl::wxCanvasControl( wxWindow *control ) - : wxCanvasObject( -1, -1, -1, -1 ) + : wxCanvasObject() { m_isControl = TRUE; m_control = control; - UpdateSize(); } wxCanvasControl::~wxCanvasControl() @@ -261,15 +336,15 @@ wxCanvasControl::~wxCanvasControl() m_control->Destroy(); } -void wxCanvasControl::Move( int x, int y ) +void wxCanvasControl::Recreate() { - m_control->Move( x, y ); + m_control->GetSize( &m_area.width, &m_area.height ); + m_control->GetPosition( &m_area.x, &m_area.y ); } -void wxCanvasControl::UpdateSize() +void wxCanvasControl::Move( int x, int y ) { - m_control->GetSize( &m_area.width, &m_area.height ); - m_control->GetPosition( &m_area.x, &m_area.y ); + m_control->Move( x, y ); } //---------------------------------------------------------------------------- @@ -286,8 +361,8 @@ public: #endif }; -wxCanvasText::wxCanvasText( const wxString &text, int x, int y, const wxString &fontFile, int size ) - : wxCanvasObject( x, y, -1, -1 ) +wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size ) + : wxCanvasObject() { m_text = text; m_fontFileName = fontFile; @@ -297,11 +372,10 @@ wxCanvasText::wxCanvasText( const wxString &text, int x, int y, const wxString & m_green = 0; m_blue = 0; - // test - m_area.width = 100; - m_area.height = m_size; - m_alpha = new unsigned char[100*m_size]; - memset( m_alpha, 0, m_area.width*m_area.height ); + m_alpha = NULL; + + m_x = x; + m_y = y; #if wxUSE_FREETYPE wxFaceData *data = new wxFaceData; @@ -317,7 +391,6 @@ wxCanvasText::wxCanvasText( const wxString &text, int x, int y, const wxString & m_size*64, 96, // screen dpi 96 ); - CreateBuffer(); #endif } @@ -389,8 +462,18 @@ void wxCanvasText::WriteSVG( wxTextOutputStream &stream ) { } -void wxCanvasText::CreateBuffer() +void wxCanvasText::Recreate() { + if (m_alpha) delete [] m_alpha; + + m_area.x = m_owner->GetDeviceX( m_x ); + m_area.y = m_owner->GetDeviceY( m_y ); + + m_area.width = 100; // TODO, calculate length + m_area.height = m_size; + m_alpha = new unsigned char[100*m_size]; + memset( m_alpha, 0, m_area.width*m_area.height ); + #if wxUSE_FREETYPE FT_Face face = ((wxFaceData*)m_faceData)->m_face; FT_GlyphSlot slot = face->glyph; @@ -452,6 +535,7 @@ wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id, m_green = 0; m_blue = 0; m_lastMouse = (wxCanvasObject*)NULL; + m_captureMouse = (wxCanvasObject*)NULL; m_frozen = FALSE; } @@ -495,6 +579,18 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char } } +void wxCanvas::CaptureMouse( wxCanvasObject *obj ) +{ + wxWindow::CaptureMouse(); + m_captureMouse = obj; +} + +void wxCanvas::ReleaseMouse() +{ + m_captureMouse = (wxCanvasObject*) NULL; + wxWindow::ReleaseMouse(); +} + void wxCanvas::Freeze() { m_frozen = TRUE; @@ -672,11 +768,45 @@ void wxCanvas::UpdateNow() 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() +{ + wxNode *node = m_objects.First(); + while (node) + { + wxCanvasObject *obj = (wxCanvasObject*) node->Data(); + + obj->Recreate(); + + node = node->Next(); + } +} + void wxCanvas::Prepend( wxCanvasObject* obj ) { m_objects.Insert( obj ); obj->SetOwner( this ); + obj->Recreate(); if (!obj->IsControl()) Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); @@ -687,6 +817,7 @@ void wxCanvas::Append( wxCanvasObject* obj ) m_objects.Append( obj ); obj->SetOwner( this ); + obj->Recreate(); if (!obj->IsControl()) Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); @@ -697,6 +828,7 @@ void wxCanvas::Insert( size_t before, wxCanvasObject* obj ) m_objects.Insert( before, obj ); obj->SetOwner( this ); + obj->Recreate(); if (!obj->IsControl()) Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); @@ -757,7 +889,7 @@ void wxCanvas::OnMouse(wxMouseEvent &event) if (event.GetEventType() == wxEVT_MOTION) { - wxNode *node = m_objects.First(); + wxNode *node = m_objects.Last(); while (node) { wxCanvasObject *obj = (wxCanvasObject*) node->Data(); @@ -800,7 +932,7 @@ void wxCanvas::OnMouse(wxMouseEvent &event) return; } } - node = node->Next(); + node = node->Previous(); } if (m_lastMouse) {