Various improvements and addition to wxCanvas

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8226 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2000-09-01 10:25:39 +00:00
parent 6a86a6c893
commit 2154485967
3 changed files with 152 additions and 40 deletions

View File

@@ -58,6 +58,24 @@ protected:
friend class wxCanvas; friend class wxCanvas;
}; };
//----------------------------------------------------------------------------
// wxCanvasRect
//----------------------------------------------------------------------------
class wxCanvasRect: public wxCanvasObject
{
public:
wxCanvasRect( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue );
virtual void Render( int clip_x, int clip_y, int clip_width, int clip_height );
virtual void WriteSVG( wxTextOutputStream &stream );
private:
unsigned char m_red;
unsigned char m_green;
unsigned char m_blue;
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// wxCanvasImage // wxCanvasImage
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@@ -44,7 +44,8 @@ public:
void OnTimer( wxTimerEvent &event ); void OnTimer( wxTimerEvent &event );
wxCanvas *m_canvas; wxCanvas *m_canvas;
wxCanvasObject *m_co; wxCanvasObject *m_sm1;
wxCanvasObject *m_sm2;
wxTimer *m_timer; wxTimer *m_timer;
private: private:
@@ -102,10 +103,19 @@ MyFrame::MyFrame()
wxBitmap bitmap( smile_xpm ); wxBitmap bitmap( smile_xpm );
wxImage image( bitmap ); wxImage image( bitmap );
m_co = new wxCanvasImage( image, 10, 50 );
m_canvas->Append( m_co );
m_canvas->Append( new wxCanvasImage( image, 40, 50 ) ); m_sm1 = new wxCanvasImage( image, 0, 70 );
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_canvas->Append( m_sm2 );
for (i = 15; i < 300; i+=10)
m_canvas->Append( new wxCanvasRect( i,50,3,140, 255,0,0 ) );
wxButton *button = new wxButton( m_canvas, -1, "Hello", wxPoint(80,50) ); wxButton *button = new wxButton( m_canvas, -1, "Hello", wxPoint(80,50) );
m_canvas->Append( new wxCanvasControl( button ) ); m_canvas->Append( new wxCanvasControl( button ) );
@@ -128,7 +138,8 @@ void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
void MyFrame::OnTimer( wxTimerEvent &WXUNUSED(event) ) void MyFrame::OnTimer( wxTimerEvent &WXUNUSED(event) )
{ {
m_co->Move( m_co->GetX()+1, m_co->GetY() ); m_sm1->Move( m_sm1->GetX()+1, m_sm1->GetY() );
m_sm2->Move( m_sm2->GetX()+1, m_sm2->GetY() );
wxWakeUpIdle(); wxWakeUpIdle();
} }

View File

@@ -80,6 +80,31 @@ void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_he
{ {
} }
//----------------------------------------------------------------------------
// 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 )
{
m_red = red;
m_green = green;
m_blue = blue;
}
void wxCanvasRect::Render( int clip_x, int clip_y, int clip_width, int clip_height )
{
wxImage *image = m_owner->GetBuffer();
// speed up later
for (int y = clip_y; y < clip_y+clip_height; y++)
for (int x = clip_x; x < clip_x+clip_width; x++)
image->SetRGB( x, y, m_red, m_green, m_blue );
}
void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
{
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// wxCanvasImage // wxCanvasImage
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -93,26 +118,22 @@ wxCanvasImage::wxCanvasImage( const wxImage &image, int x, int y )
void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height ) void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height )
{ {
int start_x = wxMax( 0, clip_x-m_area.x ); if ((clip_x == m_area.x) &&
int end_x = wxMin( m_area.width, clip_width+clip_x-m_area.x ); (clip_y == m_area.y) &&
int start_y = wxMax( 0, clip_y-m_area.y ); (clip_width == m_area.width) &&
int end_y = wxMin( m_area.height, clip_height+clip_y-m_area.y ); (clip_height == m_area.height))
if (end_x < start_x) return;
if (end_y < start_y) return;
if ((start_x == 0) &&
(start_y == 0) &&
(end_x == m_area.width) &&
(end_y == m_area.height))
{ {
m_owner->GetBuffer()->Paste( m_image, m_area.x, m_area.y ); m_owner->GetBuffer()->Paste( m_image, clip_x, clip_y );
} }
else else
{ {
wxRect rect( start_x, start_y, end_x-start_x, end_y-start_y ); // local coordinates
int start_x = clip_x - m_area.x;
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_image.GetSubImage( rect ) );
m_owner->GetBuffer()->Paste( sub_image, m_area.x+start_x, m_area.y+start_y ); m_owner->GetBuffer()->Paste( sub_image, clip_x, clip_y );
} }
} }
@@ -128,6 +149,7 @@ void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
wxCanvasControl::wxCanvasControl( wxWindow *control ) wxCanvasControl::wxCanvasControl( wxWindow *control )
: wxCanvasObject( -1, -1, -1, -1 ) : wxCanvasObject( -1, -1, -1, -1 )
{ {
m_isControl = TRUE;
m_control = control; m_control = control;
UpdateSize(); UpdateSize();
} }
@@ -225,10 +247,11 @@ void wxCanvasText::Render( int clip_x, int clip_y, int clip_width, int clip_heig
wxImage *image = m_owner->GetBuffer(); wxImage *image = m_owner->GetBuffer();
int start_x = wxMax( 0, clip_x-m_area.x ); // local coordinates
int end_x = wxMin( m_area.width, clip_width+clip_x-m_area.x ); int start_x = clip_x - m_area.x;
int start_y = wxMax( 0, clip_y-m_area.y ); int end_x = clip_width + start_x;
int end_y = wxMin( m_area.height, clip_height+clip_y-m_area.y ); int start_y = clip_y - m_area.y;
int end_y = clip_height + start_y;
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++)
@@ -368,29 +391,87 @@ void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char
void wxCanvas::Update( int x, int y, int width, int height ) void wxCanvas::Update( int x, int y, int width, int height )
{ {
// clip to buffer
if (x < 0)
{
width -= x;
x = 0;
}
if (width < 0) return;
if (y < 0)
{
height -= y;
y = 0;
}
if (height < 0) return;
if (x+width > m_buffer.GetWidth())
{
width = m_buffer.GetWidth() - x;
}
if (width < 0) return;
if (y+height > m_buffer.GetHeight())
{
height = m_buffer.GetHeight() - y;
}
if (height < 0) return;
// update is within the buffer
m_needUpdate = TRUE; m_needUpdate = TRUE;
// has to be blitted to screen later
m_updateRects.Append( m_updateRects.Append(
(wxObject*) new wxRect( x,y,width,height ) ); (wxObject*) new wxRect( x,y,width,height ) );
// speed up with direct access, maybe add wxImage::Clear(x,y,w,h) // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
int xx,yy,ww,hh; for (int yy = y; yy < y+height; yy++)
for (yy = y; yy < y+height; yy++) for (int xx = x; xx < x+width; xx++)
for (xx = x; xx < x+width; xx++)
m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue ); m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
// cycle through all objects
wxNode *node = m_objects.First(); wxNode *node = m_objects.First();
while (node) while (node)
{ {
wxCanvasObject *obj = (wxCanvasObject*) node->Data(); wxCanvasObject *obj = (wxCanvasObject*) node->Data();
xx = obj->GetX();
yy = obj->GetY();
ww = obj->GetWidth();
hh = obj->GetHeight();
if (!obj->IsControl()) // calc intersection ! if (!obj->IsControl())
{ {
obj->Render( x, y, width, height ); // If we have 10.000 objects, we will go through
// this 10.000 times for each update, so we have
// to optimise carefully.
int clip_x = obj->GetX();
int clip_width = obj->GetWidth();
if (clip_x < x)
{
clip_width -= x-clip_x;
clip_x = x;
}
if (clip_width > 0)
{
if (clip_x + clip_width > x + width)
clip_width = x+width-clip_x;
if (clip_width > 0)
{
int clip_y = obj->GetY();
int clip_height = obj->GetHeight();
if (clip_y < y)
{
clip_height -= y-clip_y;
clip_y = y;
}
if (clip_height > 0)
{
if (clip_y + clip_height > y + height)
clip_height = y+height-clip_y;
if (clip_height > 0)
obj->Render( clip_x, clip_y, clip_width, clip_height );
}
}
}
} }
node = node->Next(); node = node->Next();
@@ -522,11 +603,13 @@ void wxCanvas::OnPaint(wxPaintEvent &event)
int w = it.GetWidth(); int w = it.GetWidth();
int h = it.GetHeight(); int h = it.GetHeight();
if (x + w > m_buffer.GetWidth())
w = m_buffer.GetWidth()-x;
if (y + h > m_buffer.GetHeight())
h = m_buffer.GetHeight()-y;
if (x+w > m_buffer.GetWidth())
w = m_buffer.GetWidth() - x;
if (y+h > m_buffer.GetHeight())
h = m_buffer.GetHeight() - y;
if ((w > 0) && (h > 0))
m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) ); m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
it++; it++;