From: Robert Roebling Date: Wed, 13 Sep 2000 08:04:28 +0000 (+0000) Subject: First shot at wxBitmap based wxCanvas. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/33ebcd800ccc46703f8b5191d9860ba19418e4b0?ds=inline First shot at wxBitmap based wxCanvas. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8346 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/contrib/include/wx/canvas/canvas.h b/contrib/include/wx/canvas/canvas.h index d3a416e60e..eb435e6cd9 100644 --- a/contrib/include/wx/canvas/canvas.h +++ b/contrib/include/wx/canvas/canvas.h @@ -20,9 +20,13 @@ #include "wx/image.h" #include "wx/txtstrm.h" -class wxCanvas; +//---------------------------------------------------------------------------- +// decls +//---------------------------------------------------------------------------- + +#define IMAGE_CANVAS 0 -// WDR: class declarations +class wxCanvas; //---------------------------------------------------------------------------- // wxCanvasObject @@ -241,7 +245,11 @@ private: double m_height; wxImage m_image; +#if IMAGE_CANVAS wxImage m_tmp; +#else + wxBitmap m_tmp; +#endif }; //---------------------------------------------------------------------------- @@ -331,7 +339,12 @@ public: // ... and call this to tell all objets to recreate then virtual void Recreate(); +#if IMAGE_CANVAS inline wxImage *GetBuffer() { return &m_buffer; } +#else + inline wxBitmap *GetBuffer() { return &m_buffer; } + inline wxMemoryDC *GetDC() { return m_renderDC; } +#endif inline int GetBufferX() { return m_bufferX; } inline int GetBufferY() { return m_bufferY; } inline int GetBufferWidth() { return m_buffer.GetWidth(); } @@ -348,7 +361,12 @@ public: const wxRect* rect = (wxRect *) NULL ); private: +#if IMAGE_CANVAS wxImage m_buffer; +#else + wxBitmap m_buffer; + wxMemoryDC *m_renderDC; +#endif int m_bufferX; int m_bufferY; bool m_needUpdate; @@ -357,7 +375,6 @@ private: unsigned char m_green,m_red,m_blue; bool m_frozen; - bool m_requestNewBuffer; wxCanvasObject *m_lastMouse; wxCanvasObject *m_captureMouse; diff --git a/contrib/samples/canvas/test/test.cpp b/contrib/samples/canvas/test/test.cpp index 230cbb774a..4934995543 100644 --- a/contrib/samples/canvas/test/test.cpp +++ b/contrib/samples/canvas/test/test.cpp @@ -209,7 +209,7 @@ MyFrame::MyFrame() wxBitmap bitmap( smile_xpm ); wxImage image( bitmap ); - m_sm1 = new wxCanvasImage( image, 0,70,16,16 ); + m_sm1 = new wxCanvasImage( image, 0,70,32,32 ); m_canvas->Append( m_sm1 ); int i; @@ -241,13 +241,13 @@ MyFrame::MyFrame() // m_canvas->Append( new wxCanvasLine( 10,-1500e6,50,300000e6, 0,255,0 ) ); // m_canvas->Append( new wxCanvasLine( 10,-150000,50,300000, 0,255,0 ) ); +/* //make a group of wxCanvasObjects wxCanvasObjectGroup* group1 = new wxCanvasObjectGroup(); group1->Prepend( new wxCanvasLine( 10,-35,50,190,100,255,0 ) ); group1->Prepend( new wxCanvasImage( image, 4,38,32,32 ) ); group1->Prepend( new wxCanvasRect(20,-20,50,170,0,20,240 ) ); - //make another group of wxCanvasObjects wxCanvasObjectGroup* group2 = new wxCanvasObjectGroup(); group2->Prepend( new wxCanvasImage( image, 60,38,52,32 ) ); @@ -258,13 +258,12 @@ MyFrame::MyFrame() group1->Prepend( m_subref ); //now make two refrences to group1 into root group of the canvas -/* m_ref = new MywxCanvasObjectGroupRef(40,200, group1); m_canvas->Prepend( m_ref ); -*/ m_ref2 = new MywxCanvasObjectGroupRef(80,350, group1); m_canvas->Prepend( m_ref2 ); +*/ m_log = new wxTextCtrl( this, -1, "", wxPoint(0,0), wxSize(100,100), wxTE_MULTILINE ); wxLog *old_log = wxLog::SetActiveTarget( new wxLogTextCtrl( m_log ) ); diff --git a/contrib/src/canvas/canvas.cpp b/contrib/src/canvas/canvas.cpp index f2284c9ed7..3c6f3f58ee 100644 --- a/contrib/src/canvas/canvas.cpp +++ b/contrib/src/canvas/canvas.cpp @@ -284,12 +284,12 @@ bool wxCanvasObjectGroup::IsHit( int x, int y, int margin ) { if (obj->IsHit(x,y,margin)) { - return true; + return TRUE; } } node = node->Previous(); } - return false; + return FALSE; } wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin ) @@ -322,40 +322,39 @@ wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjec { m_x = x; m_y = y; - m_validbounds=false; - m_group=group; + m_validbounds = FALSE; + m_group = group; } void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas) { - m_owner=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; - } + 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_validbounds = FALSE; m_group->Recreate(); ExtendArea(m_group->GetXMin(),m_group->GetYMin()); ExtendArea(m_group->GetXMax(),m_group->GetYMax()); @@ -467,10 +466,12 @@ void wxCanvasRect::Recreate() 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(); +#if IMAGE_CANVAS + wxImage *image = m_owner->GetBuffer(); + int start_y = clip_y - buffer_y; int end_y = clip_y+clip_height - buffer_y; @@ -481,6 +482,14 @@ void wxCanvasRect::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_w 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 ); +#else + wxMemoryDC *dc = m_owner->GetDC(); + dc->SetPen( *wxTRANSPARENT_PEN ); + wxBrush brush( wxColour( m_red,m_green,m_blue), wxSOLID ); + dc->SetBrush( brush ); + + dc->DrawRectangle( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height ); +#endif } void wxCanvasRect::WriteSVG( wxTextOutputStream &stream ) @@ -528,21 +537,22 @@ void wxCanvasLine::Recreate() 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(); + 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 ); + +#if IMAGE_CANVAS + wxImage *image = m_owner->GetBuffer(); 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; @@ -597,6 +607,16 @@ void wxCanvasLine::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_w } } } +#else + wxMemoryDC *dc = m_owner->GetDC(); + dc->SetClippingRegion( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height ); + + wxPen pen( wxColour(m_red,m_green,m_blue), 0, wxSOLID ); + dc->SetPen( pen ); + dc->DrawLine( x1-buffer_x, y1-buffer_y, x2-buffer_x, y2-buffer_y ); + + dc->DestroyClippingRegion(); +#endif } void wxCanvasLine::WriteSVG( wxTextOutputStream &stream ) @@ -627,11 +647,28 @@ void wxCanvasImage::Recreate() m_owner->GetDeviceWidth( m_width ), m_owner->GetDeviceHeight( m_height ) ); +#if IMAGE_CANVAS 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 ); + } +#else + if ((m_area.width == m_image.GetWidth()) && + (m_area.width == m_image.GetWidth())) + { + m_tmp = m_image.ConvertToBitmap(); + } + else + { + wxImage tmp( m_image.Scale( m_area.width, m_area.height ) ); + m_tmp = tmp.ConvertToBitmap(); + } +#endif } void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) @@ -639,6 +676,7 @@ void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_ int buffer_x = m_owner->GetBufferX(); int buffer_y = m_owner->GetBufferY(); +#if IMAGE_CANVAS if ((clip_x == xabs + m_area.x) && (clip_y == yabs + m_area.y) && (clip_width == m_area.width) && @@ -656,6 +694,28 @@ void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_ wxImage sub_image( m_tmp.GetSubImage( rect ) ); m_owner->GetBuffer()->Paste( sub_image, clip_x-buffer_x, clip_y-buffer_y ); } +#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)) + { + dc->DrawBitmap( m_tmp, clip_x-buffer_x, clip_y-buffer_y, TRUE ); + } + else + { + // local coordinates + int start_x = clip_x - (xabs + m_area.x); + int start_y = clip_y - (yabs + m_area.y); + + // 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 ); + } +#endif } void wxCanvasImage::WriteSVG( wxTextOutputStream &stream ) @@ -763,6 +823,7 @@ void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_w { if (!m_alpha) return; +#if IMAGE_CANVAS wxImage *image = m_owner->GetBuffer(); int buffer_x = m_owner->GetBufferX(); int buffer_y = m_owner->GetBufferY(); @@ -801,6 +862,7 @@ void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_w image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 ); } } +#endif } void wxCanvasText::WriteSVG( wxTextOutputStream &stream ) @@ -884,7 +946,6 @@ wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id, m_lastMouse = (wxCanvasObject*)NULL; m_captureMouse = (wxCanvasObject*)NULL; m_frozen = TRUE; - m_requestNewBuffer = TRUE; //root group always at 0,0 m_root = new wxCanvasObjectGroup(); @@ -919,6 +980,7 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char if (m_frozen) return; +#if IMAGE_CANVAS unsigned char *data = m_buffer.GetData(); for (int y = 0; y < m_buffer.GetHeight(); y++) @@ -931,6 +993,15 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char data[0] = blue; data++; } +#else + wxMemoryDC dc; + dc.SelectObject( m_buffer ); + dc.SetPen( *wxTRANSPARENT_PEN ); + wxBrush brush( wxColour( red,green,blue), wxSOLID ); + dc.SetBrush( brush ); + dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() ); + dc.SelectObject( wxNullBitmap ); +#endif } void wxCanvas::SetCaptureMouse( wxCanvasObject *obj ) @@ -979,26 +1050,26 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit ) width -= m_bufferX-x; x = m_bufferX; } - if (width < 0) return; + if (width <= 0) return; if (y < m_bufferY) { height -= m_bufferY-y; y = m_bufferY; } - if (height < 0) return; + if (height <= 0) return; if (x+width > m_bufferX+m_buffer.GetWidth()) { width = m_bufferX+m_buffer.GetWidth() - x; } - if (width < 0) return; + if (width <= 0) return; if (y+height > m_bufferY+m_buffer.GetHeight()) { height = m_bufferY+m_buffer.GetHeight() - y; } - if (height < 0) return; + if (height <= 0) return; // update is within the buffer m_needUpdate = TRUE; @@ -1010,6 +1081,7 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit ) (wxObject*) new wxRect( x,y,width,height ) ); } +#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; @@ -1018,9 +1090,21 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit ) 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_root->Render(0,0, 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 ); + 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 ); + + dc.SelectObject( wxNullBitmap ); +#endif } void wxCanvas::BlitBuffer( wxDC &dc ) @@ -1034,8 +1118,9 @@ void wxCanvas::BlitBuffer( wxDC &dc ) sub_rect.x -= m_bufferX; sub_rect.y -= m_bufferY; - wxImage sub_image( m_buffer.GetSubImage( sub_rect ) ); +#if IMAGE_CANVAS + wxImage sub_image( m_buffer.GetSubImage( sub_rect ) ); #ifdef __WXGTK__ int bpp = wxDisplayDepth(); if (bpp > 8) @@ -1062,13 +1147,19 @@ void wxCanvas::BlitBuffer( wxDC &dc ) wxBitmap bitmap( sub_image.ConvertToBitmap() ); dc.DrawBitmap( bitmap, rect->x, rect->y ); } -#endif - -#ifndef __WXGTK__ +#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( sub_rect ) ); + dc.DrawBitmap( sub_bitmap, rect->x, rect->y ); + +#endif delete rect; m_updateRects.DeleteNode( node ); node = m_updateRects.First(); @@ -1208,6 +1299,7 @@ void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect ) // client area. Indeed, it is the client area. CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); +#if IMAGE_CANVAS unsigned char* data = m_buffer.GetData(); if (dy != 0) @@ -1271,6 +1363,10 @@ void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect ) Update( m_bufferX+m_buffer.GetWidth()+dx, m_bufferY, -dx, m_buffer.GetHeight(), FALSE ); } } +#else + // Update everything, TODO: scrolling + Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); +#endif wxWindow::ScrollWindow( dx, dy, rect ); } @@ -1408,7 +1504,11 @@ void wxCanvas::OnSize(wxSizeEvent &event) { int w,h; GetClientSize( &w, &h ); +#if IMAGE_CANVAS m_buffer = wxImage( w, h ); +#else + m_buffer = wxBitmap( w, h ); +#endif CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );