First shot at wxBitmap based wxCanvas.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8346 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2000-09-13 08:04:28 +00:00
parent bdb310a720
commit 33ebcd800c
3 changed files with 162 additions and 46 deletions

View File

@@ -20,9 +20,13 @@
#include "wx/image.h" #include "wx/image.h"
#include "wx/txtstrm.h" #include "wx/txtstrm.h"
class wxCanvas; //----------------------------------------------------------------------------
// decls
//----------------------------------------------------------------------------
// WDR: class declarations #define IMAGE_CANVAS 0
class wxCanvas;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// wxCanvasObject // wxCanvasObject
@@ -241,7 +245,11 @@ private:
double m_height; double m_height;
wxImage m_image; wxImage m_image;
#if IMAGE_CANVAS
wxImage m_tmp; wxImage m_tmp;
#else
wxBitmap m_tmp;
#endif
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -331,7 +339,12 @@ public:
// ... and call this to tell all objets to recreate then // ... and call this to tell all objets to recreate then
virtual void Recreate(); virtual void Recreate();
#if IMAGE_CANVAS
inline wxImage *GetBuffer() { return &m_buffer; } 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 GetBufferX() { return m_bufferX; }
inline int GetBufferY() { return m_bufferY; } inline int GetBufferY() { return m_bufferY; }
inline int GetBufferWidth() { return m_buffer.GetWidth(); } inline int GetBufferWidth() { return m_buffer.GetWidth(); }
@@ -348,7 +361,12 @@ public:
const wxRect* rect = (wxRect *) NULL ); const wxRect* rect = (wxRect *) NULL );
private: private:
#if IMAGE_CANVAS
wxImage m_buffer; wxImage m_buffer;
#else
wxBitmap m_buffer;
wxMemoryDC *m_renderDC;
#endif
int m_bufferX; int m_bufferX;
int m_bufferY; int m_bufferY;
bool m_needUpdate; bool m_needUpdate;
@@ -357,7 +375,6 @@ private:
unsigned char m_green,m_red,m_blue; unsigned char m_green,m_red,m_blue;
bool m_frozen; bool m_frozen;
bool m_requestNewBuffer;
wxCanvasObject *m_lastMouse; wxCanvasObject *m_lastMouse;
wxCanvasObject *m_captureMouse; wxCanvasObject *m_captureMouse;

View File

@@ -209,7 +209,7 @@ MyFrame::MyFrame()
wxBitmap bitmap( smile_xpm ); wxBitmap bitmap( smile_xpm );
wxImage image( bitmap ); 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 ); m_canvas->Append( m_sm1 );
int i; 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,-1500e6,50,300000e6, 0,255,0 ) );
// m_canvas->Append( new wxCanvasLine( 10,-150000,50,300000, 0,255,0 ) ); // m_canvas->Append( new wxCanvasLine( 10,-150000,50,300000, 0,255,0 ) );
/*
//make a group of wxCanvasObjects //make a group of wxCanvasObjects
wxCanvasObjectGroup* group1 = new wxCanvasObjectGroup(); wxCanvasObjectGroup* group1 = new wxCanvasObjectGroup();
group1->Prepend( new wxCanvasLine( 10,-35,50,190,100,255,0 ) ); group1->Prepend( new wxCanvasLine( 10,-35,50,190,100,255,0 ) );
group1->Prepend( new wxCanvasImage( image, 4,38,32,32 ) ); group1->Prepend( new wxCanvasImage( image, 4,38,32,32 ) );
group1->Prepend( new wxCanvasRect(20,-20,50,170,0,20,240 ) ); group1->Prepend( new wxCanvasRect(20,-20,50,170,0,20,240 ) );
//make another group of wxCanvasObjects //make another group of wxCanvasObjects
wxCanvasObjectGroup* group2 = new wxCanvasObjectGroup(); wxCanvasObjectGroup* group2 = new wxCanvasObjectGroup();
group2->Prepend( new wxCanvasImage( image, 60,38,52,32 ) ); group2->Prepend( new wxCanvasImage( image, 60,38,52,32 ) );
@@ -258,13 +258,12 @@ MyFrame::MyFrame()
group1->Prepend( m_subref ); group1->Prepend( m_subref );
//now make two refrences to group1 into root group of the canvas //now make two refrences to group1 into root group of the canvas
/*
m_ref = new MywxCanvasObjectGroupRef(40,200, group1); m_ref = new MywxCanvasObjectGroupRef(40,200, group1);
m_canvas->Prepend( m_ref ); m_canvas->Prepend( m_ref );
*/
m_ref2 = new MywxCanvasObjectGroupRef(80,350, group1); m_ref2 = new MywxCanvasObjectGroupRef(80,350, group1);
m_canvas->Prepend( m_ref2 ); m_canvas->Prepend( m_ref2 );
*/
m_log = new wxTextCtrl( this, -1, "", wxPoint(0,0), wxSize(100,100), wxTE_MULTILINE ); m_log = new wxTextCtrl( this, -1, "", wxPoint(0,0), wxSize(100,100), wxTE_MULTILINE );
wxLog *old_log = wxLog::SetActiveTarget( new wxLogTextCtrl( m_log ) ); wxLog *old_log = wxLog::SetActiveTarget( new wxLogTextCtrl( m_log ) );

View File

@@ -284,12 +284,12 @@ bool wxCanvasObjectGroup::IsHit( int x, int y, int margin )
{ {
if (obj->IsHit(x,y,margin)) if (obj->IsHit(x,y,margin))
{ {
return true; return TRUE;
} }
} }
node = node->Previous(); node = node->Previous();
} }
return false; return FALSE;
} }
wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin ) wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin )
@@ -322,7 +322,7 @@ wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjec
{ {
m_x = x; m_x = x;
m_y = y; m_y = y;
m_validbounds=false; m_validbounds = FALSE;
m_group = group; m_group = group;
} }
@@ -343,19 +343,18 @@ void wxCanvasObjectGroupRef::ExtendArea(int x, int y)
} }
else else
{ {
m_validbounds = true; m_validbounds = TRUE;
m_minx = x; m_minx = x;
m_miny = y; m_miny = y;
m_maxx = x; m_maxx = x;
m_maxy = y; m_maxy = y;
} }
} }
void wxCanvasObjectGroupRef::Recreate() void wxCanvasObjectGroupRef::Recreate()
{ {
m_validbounds=false; m_validbounds = FALSE;
m_group->Recreate(); m_group->Recreate();
ExtendArea(m_group->GetXMin(),m_group->GetYMin()); ExtendArea(m_group->GetXMin(),m_group->GetYMin());
ExtendArea(m_group->GetXMax(),m_group->GetYMax()); 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 ) 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_x = m_owner->GetBufferX();
int buffer_y = m_owner->GetBufferY(); int buffer_y = m_owner->GetBufferY();
#if IMAGE_CANVAS
wxImage *image = m_owner->GetBuffer();
int start_y = clip_y - buffer_y; int start_y = clip_y - buffer_y;
int end_y = clip_y+clip_height - 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 y = start_y; y < end_y; y++)
for (int x = start_x; x < end_x; x++) for (int x = start_x; x < end_x; x++)
image->SetRGB( x, y, m_red, m_green, m_blue ); 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 ) 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 ) 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_x = m_owner->GetBufferX();
int buffer_y = m_owner->GetBufferY(); 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)) 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 ); image->SetRGB( m_area.x-buffer_x, m_area.y-buffer_y, m_red, m_green, m_blue );
} }
else 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; wxInt32 d, ii, jj, di, ai, si, dj, aj, sj;
di = x1 - x2; di = x1 - x2;
ai = abs(di) << 1; 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 ) void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
@@ -627,18 +647,36 @@ void wxCanvasImage::Recreate()
m_owner->GetDeviceWidth( m_width ), m_owner->GetDeviceWidth( m_width ),
m_owner->GetDeviceHeight( m_height ) ); m_owner->GetDeviceHeight( m_height ) );
#if IMAGE_CANVAS
if ((m_area.width == m_image.GetWidth()) && if ((m_area.width == m_image.GetWidth()) &&
(m_area.width == m_image.GetWidth())) (m_area.width == m_image.GetWidth()))
{
m_tmp = m_image; m_tmp = m_image;
}
else else
{
m_tmp = m_image.Scale( m_area.width, m_area.height ); 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 ) 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_x = m_owner->GetBufferX();
int buffer_y = m_owner->GetBufferY(); int buffer_y = m_owner->GetBufferY();
#if IMAGE_CANVAS
if ((clip_x == xabs + m_area.x) && if ((clip_x == xabs + m_area.x) &&
(clip_y == yabs + m_area.y) && (clip_y == yabs + m_area.y) &&
(clip_width == m_area.width) && (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 ) ); wxImage sub_image( m_tmp.GetSubImage( rect ) );
m_owner->GetBuffer()->Paste( sub_image, clip_x-buffer_x, clip_y-buffer_y ); 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 ) 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 (!m_alpha) return;
#if IMAGE_CANVAS
wxImage *image = m_owner->GetBuffer(); wxImage *image = m_owner->GetBuffer();
int buffer_x = m_owner->GetBufferX(); int buffer_x = m_owner->GetBufferX();
int buffer_y = m_owner->GetBufferY(); 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 ); image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
} }
} }
#endif
} }
void wxCanvasText::WriteSVG( wxTextOutputStream &stream ) void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
@@ -884,7 +946,6 @@ wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id,
m_lastMouse = (wxCanvasObject*)NULL; m_lastMouse = (wxCanvasObject*)NULL;
m_captureMouse = (wxCanvasObject*)NULL; m_captureMouse = (wxCanvasObject*)NULL;
m_frozen = TRUE; m_frozen = TRUE;
m_requestNewBuffer = TRUE;
//root group always at 0,0 //root group always at 0,0
m_root = new wxCanvasObjectGroup(); m_root = new wxCanvasObjectGroup();
@@ -919,6 +980,7 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char
if (m_frozen) return; if (m_frozen) return;
#if IMAGE_CANVAS
unsigned char *data = m_buffer.GetData(); unsigned char *data = m_buffer.GetData();
for (int y = 0; y < m_buffer.GetHeight(); y++) 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[0] = blue;
data++; 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 ) 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; width -= m_bufferX-x;
x = m_bufferX; x = m_bufferX;
} }
if (width < 0) return; if (width <= 0) return;
if (y < m_bufferY) if (y < m_bufferY)
{ {
height -= m_bufferY-y; height -= m_bufferY-y;
y = m_bufferY; y = m_bufferY;
} }
if (height < 0) return; if (height <= 0) return;
if (x+width > m_bufferX+m_buffer.GetWidth()) if (x+width > m_bufferX+m_buffer.GetWidth())
{ {
width = m_bufferX+m_buffer.GetWidth() - x; width = m_bufferX+m_buffer.GetWidth() - x;
} }
if (width < 0) return; if (width <= 0) return;
if (y+height > m_bufferY+m_buffer.GetHeight()) if (y+height > m_bufferY+m_buffer.GetHeight())
{ {
height = m_bufferY+m_buffer.GetHeight() - y; height = m_bufferY+m_buffer.GetHeight() - y;
} }
if (height < 0) return; if (height <= 0) return;
// update is within the buffer // update is within the buffer
m_needUpdate = TRUE; 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 ) ); (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) // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
int start_y = y - m_bufferY; int start_y = y - m_bufferY;
int end_y = y+height - m_bufferY; int end_y = y+height - m_bufferY;
@@ -1020,7 +1092,19 @@ void wxCanvas::Update( int x, int y, int width, int height, bool blit )
m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue ); m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
m_root->Render(0,0, x, y, width, height ); 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 ) void wxCanvas::BlitBuffer( wxDC &dc )
@@ -1034,8 +1118,9 @@ void wxCanvas::BlitBuffer( wxDC &dc )
sub_rect.x -= m_bufferX; sub_rect.x -= m_bufferX;
sub_rect.y -= m_bufferY; 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__ #ifdef __WXGTK__
int bpp = wxDisplayDepth(); int bpp = wxDisplayDepth();
if (bpp > 8) if (bpp > 8)
@@ -1062,13 +1147,19 @@ void wxCanvas::BlitBuffer( wxDC &dc )
wxBitmap bitmap( sub_image.ConvertToBitmap() ); wxBitmap bitmap( sub_image.ConvertToBitmap() );
dc.DrawBitmap( bitmap, rect->x, rect->y ); dc.DrawBitmap( bitmap, rect->x, rect->y );
} }
#endif #else
#ifndef __WXGTK__
wxBitmap bitmap( sub_image.ConvertToBitmap() ); wxBitmap bitmap( sub_image.ConvertToBitmap() );
dc.DrawBitmap( bitmap, rect->x, rect->y ); dc.DrawBitmap( bitmap, rect->x, rect->y );
#endif #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; delete rect;
m_updateRects.DeleteNode( node ); m_updateRects.DeleteNode( node );
node = m_updateRects.First(); 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. // client area. Indeed, it is the client area.
CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
#if IMAGE_CANVAS
unsigned char* data = m_buffer.GetData(); unsigned char* data = m_buffer.GetData();
if (dy != 0) 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 ); 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 ); wxWindow::ScrollWindow( dx, dy, rect );
} }
@@ -1408,7 +1504,11 @@ void wxCanvas::OnSize(wxSizeEvent &event)
{ {
int w,h; int w,h;
GetClientSize( &w, &h ); GetClientSize( &w, &h );
#if IMAGE_CANVAS
m_buffer = wxImage( w, h ); m_buffer = wxImage( w, h );
#else
m_buffer = wxBitmap( w, h );
#endif
CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );