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:
@@ -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
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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++;
|
||||||
|
Reference in New Issue
Block a user