}
-void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasObject::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
{
}
{
}
+//----------------------------------------------------------------------------
+// wxCanvasObjectGroup
+//----------------------------------------------------------------------------
+
+wxCanvasObjectGroup::wxCanvasObjectGroup()
+{
+ m_validbounds = FALSE;
+}
+
+wxCanvasObjectGroup::~wxCanvasObjectGroup()
+{
+}
+
+void wxCanvasObjectGroup::SetOwner(wxCanvas* canvas)
+{
+ m_owner=canvas;
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->SetOwner(canvas);
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::ExtendArea(double x, double 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 wxCanvasObjectGroup::DeleteContents( bool flag)
+{
+ m_objects.DeleteContents( flag );
+ m_validbounds = FALSE;
+}
+
+void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
+{
+ m_objects.Insert( obj );
+ m_validbounds = FALSE;
+}
+
+void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
+{
+ m_objects.Append( obj );
+ m_validbounds = FALSE;
+}
+
+void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
+{
+ m_objects.Insert( before, obj );
+ m_validbounds = FALSE;
+}
+
+void wxCanvasObjectGroup::Remove( wxCanvasObject* obj )
+{
+ m_objects.DeleteObject( obj );
+ m_validbounds = FALSE;
+}
+
+void wxCanvasObjectGroup::Recreate()
+{
+ m_validbounds = FALSE;
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ obj->Recreate();
+ ExtendArea(obj->GetX(),obj->GetY());
+ ExtendArea(obj->GetX()+obj->GetWidth(),obj->GetY()+obj->GetHeight());
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::Render(int xabs, int yabs, int x, int y, int width, int height )
+{
+ // cycle through all objects
+ wxNode *node = m_objects.First();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ // 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 = xabs + 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 = yabs + 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(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ }
+ }
+ }
+ }
+
+ node = node->Next();
+ }
+}
+
+void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+bool wxCanvasObjectGroup::IsHit( int x, int y, int margin )
+{
+ wxNode *node = m_objects.Last();
+ while (node)
+ {
+ wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ if (obj->IsHit(x,y,margin))
+ {
+ return TRUE;
+ }
+ }
+ node = node->Previous();
+ }
+ return FALSE;
+}
+
+wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin )
+{
+ wxCanvasObject *obj=0;
+ wxNode *node = m_objects.Last();
+ while (node)
+ {
+ obj=(wxCanvasObject*) node->Data();
+
+ if (!obj->IsControl())
+ {
+ if (obj->IsHit(x,y,margin))
+ {
+ return obj;
+ }
+ }
+ node = node->Previous();
+ }
+
+ return (wxCanvasObject*) NULL;
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasObjectGroupRef
+//----------------------------------------------------------------------------
+
+wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjectGroup* group)
+ : wxCanvasObject()
+{
+ m_x = x;
+ m_y = y;
+ m_validbounds = FALSE;
+ m_group = group;
+}
+
+void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas)
+{
+ m_owner = canvas;
+ m_group->SetOwner(canvas);
+}
+
+void wxCanvasObjectGroupRef::ExtendArea(double x, double 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_group->Recreate();
+ ExtendArea(m_group->GetXMin(),m_group->GetYMin());
+ ExtendArea(m_group->GetXMax(),m_group->GetYMax());
+
+ //set the area in pixels relative to the parent
+ SetArea( m_owner->GetDeviceX( m_x + m_minx ),
+ m_owner->GetDeviceY( m_y + m_miny ),
+ m_owner->GetDeviceWidth( m_maxx-m_minx ),
+ m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+}
+
+void wxCanvasObjectGroupRef::Render(int xabs, int yabs, int x, int y, int width, int height )
+{
+ xabs += m_area.x;
+ yabs += m_area.y;
+
+ int clip_x = xabs + m_group->GetXMin();
+ int clip_width = m_group->GetXMax()-m_group->GetXMin();
+ 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 = yabs + m_group->GetYMin();
+ int clip_height = m_group->GetYMax()-m_group->GetYMin();
+ 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)
+ m_group->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
+ }
+ }
+ }
+}
+
+void wxCanvasObjectGroupRef::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+bool wxCanvasObjectGroupRef::IsHit( int x, int y, int margin )
+{
+ return m_group->IsHit(x-GetPosX(),y-GetPosY(),margin);
+}
+
+wxCanvasObject* wxCanvasObjectGroupRef::IsHitObject( int x, int y, int margin )
+{
+ return m_group->IsHitObject(x-GetPosX(),y-GetPosY(),margin);
+}
+
+void wxCanvasObjectGroupRef::Move( int x, int y )
+{
+ m_x = x;
+ m_y = y;
+
+ int old_area_x = m_area.x;
+ int old_area_y = m_area.y;
+
+ m_area.x=m_owner->GetDeviceX( m_x + m_minx );
+ m_area.y=m_owner->GetDeviceY( m_y + m_miny );
+
+ int leftu,rightu,bottomu,topu ;
+ leftu = wxMin (m_area.x, old_area_x ) ;
+ rightu = wxMax (old_area_x + m_area.width, m_area.x + m_area.width) ;
+ topu = wxMin (m_area.y,old_area_y) ;
+ bottomu = wxMax (old_area_y + m_area.height, m_area.y + m_area.height) ;
+
+ if ( rightu - leftu < 2*m_area.width && bottomu - topu < 2*m_area.height )
+ {
+ m_owner->Update(leftu,topu,rightu - leftu,bottomu - topu);
+ }
+ else
+ {
+ m_owner->Update(old_area_x, old_area_y, m_area.width, m_area.height );
+ m_owner->Update( m_area.x, m_area.y, m_area.width, m_area.height );
+ }
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolyline
+//----------------------------------------------------------------------------
+
+wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[])
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_pen = *wxBLACK_PEN;
+}
+
+wxCanvasPolyline::~wxCanvasPolyline()
+{
+ delete m_points;
+}
+
+void wxCanvasPolyline::ExtendArea(double x, double 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 wxCanvasPolyline::Recreate()
+{
+
+ m_validbounds=FALSE;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ ExtendArea(m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth());
+ ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2);
+
+ //set the area in pixels relative to the parent
+ SetArea( m_owner->GetDeviceX(m_minx ),
+ m_owner->GetDeviceY(m_miny ),
+ m_owner->GetDeviceWidth( m_maxx-m_minx ),
+ m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+}
+
+void wxCanvasPolyline::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_y = m_owner->GetBufferY();
+
+ int start_y = clip_y - buffer_y;
+ int end_y = clip_y+clip_height - buffer_y;
+
+ int start_x = clip_x - buffer_x;
+ int end_x = clip_x+clip_width - buffer_x;
+
+#if IMAGE_CANVAS
+#else
+ wxPoint *cpoints = new wxPoint[m_n];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs);
+ cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs);
+ }
+ wxMemoryDC *dc = m_owner->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetPen(m_pen);
+ dc->DrawLines(m_n, cpoints, 0,0);
+ delete [] cpoints;
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+#endif
+}
+
+void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+//----------------------------------------------------------------------------
+// wxCanvasPolygon
+//----------------------------------------------------------------------------
+
+wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[])
+ : wxCanvasObject()
+{
+ m_n = n;
+ m_points = points;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
+}
+
+wxCanvasPolygon::~wxCanvasPolygon()
+{
+ delete m_points;
+}
+
+void wxCanvasPolygon::ExtendArea(double x, double 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 wxCanvasPolygon::Recreate()
+{
+
+ m_validbounds=FALSE;
+ int i;
+ for (i=0; i < m_n;i++)
+ {
+ ExtendArea(m_points[i].m_x,m_points[i].m_y);
+ }
+
+ //include the pen width also
+ ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth());
+ ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2);
+
+ //set the area in pixels relative to the parent
+ SetArea( m_owner->GetDeviceX( m_minx ),
+ m_owner->GetDeviceY( m_miny ),
+ m_owner->GetDeviceWidth( m_maxx-m_minx ),
+ m_owner->GetDeviceHeight( m_maxy-m_miny ) );
+}
+
+void wxCanvasPolygon::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_y = m_owner->GetBufferY();
+
+ int start_y = clip_y - buffer_y;
+ int end_y = clip_y+clip_height - buffer_y;
+
+ int start_x = clip_x - buffer_x;
+ int end_x = clip_x+clip_width - buffer_x;
+
+#if IMAGE_CANVAS
+#else
+ wxPoint *cpoints = new wxPoint[m_n];
+ int i;
+ for (i = 0; i < m_n; i++)
+ {
+ cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs);
+ cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs);
+ }
+ wxMemoryDC *dc = m_owner->GetDC();
+ dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y);
+ dc->SetBrush(m_brush);
+ dc->SetPen(m_pen);
+ dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE);
+ delete [] cpoints;
+ dc->SetBrush(wxNullBrush);
+ dc->SetPen(wxNullPen);
+ dc->DestroyClippingRegion();
+#endif
+}
+
+void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream )
+{
+}
+
+
+
//----------------------------------------------------------------------------
// wxCanvasRect
//----------------------------------------------------------------------------
-wxCanvasRect::wxCanvasRect( double x, double y, double w, double h,
- unsigned char red, unsigned char green, unsigned char blue )
+wxCanvasRect::wxCanvasRect( double x, double y, double w, double h )
: wxCanvasObject()
{
m_x = x;
m_width = w;
m_height = h;
- m_red = red;
- m_green = green;
- m_blue = blue;
+ m_brush = *wxBLACK_BRUSH;
+ m_pen = *wxTRANSPARENT_PEN;
}
void wxCanvasRect::Recreate()
m_owner->GetDeviceHeight( m_height ) );
}
-void wxCanvasRect::Render( 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_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;
-
+
int start_x = clip_x - buffer_x;
int end_x = clip_x+clip_width - buffer_x;
-
+
// speed up later
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( m_pen );
+ dc->SetBrush( m_brush );
+ dc->DrawRectangle( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+#endif
}
void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
// wxCanvasLine
//----------------------------------------------------------------------------
-wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2,
- unsigned char red, unsigned char green, unsigned char blue )
+wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2 )
: wxCanvasObject()
{
m_x1 = x1;
m_x2 = x2;
m_y2 = y2;
- m_red = red;
- m_green = green;
- m_blue = blue;
+ m_pen = *wxBLACK_PEN;
}
void wxCanvasLine::Recreate()
SetArea( x1, y1, x2-x1+1, y2-y1+1 );
}
-void wxCanvasLine::Render( 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_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 = 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;
ai = abs(di) << 1;
}
}
}
+#else
+ wxMemoryDC *dc = m_owner->GetDC();
+ dc->SetClippingRegion( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+ dc->SetPen( m_pen );
+ dc->DrawLine( x1-buffer_x, y1-buffer_y, x2-buffer_x, y2-buffer_y );
+
+ dc->DestroyClippingRegion();
+#endif
}
void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
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 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_y = m_owner->GetBufferY();
-
- if ((clip_x == m_area.x) &&
- (clip_y == m_area.y) &&
+
+#if IMAGE_CANVAS
+ if ((clip_x == xabs + m_area.x) &&
+ (clip_y == yabs + m_area.y) &&
(clip_width == m_area.width) &&
(clip_height == m_area.height))
{
else
{
// local coordinates
- int start_x = clip_x - m_area.x;
- int start_y = clip_y - m_area.y;
+ int start_x = clip_x - (xabs + m_area.x);
+ int start_y = clip_y - (yabs + m_area.y);
wxRect rect( start_x, start_y, clip_width, clip_height );
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 )
m_fontFileName,
0,
&(data->m_face) );
-
+
error = FT_Set_Char_Size( data->m_face,
0,
m_size*64,
wxCanvasText::~wxCanvasText()
{
-#if wxUSE_FREETYPE
+#if wxUSE_FREETYPE
wxFaceData *data = (wxFaceData*) m_faceData;
delete data;
#endif
m_flag = flag;
}
-void wxCanvasText::Render( int clip_x, int clip_y, int clip_width, int clip_height )
+void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
{
if (!m_alpha) return;
-
- 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();
// local coordinates
int start_x = clip_x - m_area.x;
int end_x = clip_width + start_x;
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 x = start_x; x < end_x; x++)
{
red2 = (red2 * alpha) / 255;
green2 = (green2 * alpha) / 255;
blue2 = (blue2 * alpha) / 255;
-
+
image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
}
}
+#else
+ wxBitmap *bitmap = m_owner->GetBuffer();
+ wxRect sub_rect( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
+ wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) );
+
+ wxImage image( sub_bitmap );
+
+ // local coordinates
+ int start_x = clip_x - m_area.x;
+ int end_x = clip_width + start_x;
+ 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 x = start_x; x < end_x; x++)
+ {
+ int alpha = m_alpha[y*m_area.width + x];
+ if (alpha)
+ {
+ int image_x = x - start_x;
+ int image_y = y - start_y;
+ if (alpha == 255)
+ {
+ image.SetRGB( image_x, image_y, m_red, m_green, m_blue );
+ continue;
+ }
+ int red1 = (m_red * alpha) / 255;
+ int green1 = (m_green * alpha) / 255;
+ int blue1 = (m_blue * alpha) / 255;
+
+ alpha = 255-alpha;
+ int red2 = image.GetRed( image_x, image_y );
+ int green2 = image.GetGreen( image_x, image_y );
+ int blue2 = image.GetBlue( image_x, image_y );
+ red2 = (red2 * alpha) / 255;
+ green2 = (green2 * alpha) / 255;
+ blue2 = (blue2 * alpha) / 255;
+
+ image.SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
+ }
+ }
+
+ sub_bitmap = image.ConvertToBitmap();
+
+ wxMemoryDC *dc = m_owner->GetDC();
+ dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y );
+#endif
}
void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
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];
+ m_area.width = 100; // TODO calculate length
+ m_area.height = m_size + (m_size/2); // TODO space for sub-baseline (pgypq)
+ m_alpha = new unsigned char[m_area.width*m_area.height];
memset( m_alpha, 0, m_area.width*m_area.height );
-
-#if wxUSE_FREETYPE
+
+#if wxUSE_FREETYPE
FT_Face face = ((wxFaceData*)m_faceData)->m_face;
FT_GlyphSlot slot = face->glyph;
int pen_x = 0;
int pen_y = m_size;
-
+
for (int n = 0; n < (int)m_text.Len(); n++)
{
FT_UInt index = FT_Get_Char_Index( face, m_text[n] );
int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
if (error) continue;
-
+
error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
if (error) continue;
-
+
FT_Bitmap *bitmap = &slot->bitmap;
unsigned char* buffer = bitmap->buffer;
for (int y = 0; y < bitmap->rows; y++)
int yy = pen_y - slot->bitmap_top + y;
m_alpha[ yy * m_area.width + xx ] = alpha;
}
-
+
pen_x += slot->advance.x >> 6;
pen_y += slot->advance.y >> 6;
- }
+ }
#endif
}
m_bufferX = 0;
m_bufferY = 0;
m_needUpdate = FALSE;
- m_objects.DeleteContents( TRUE );
m_red = 0;
m_green = 0;
m_blue = 0;
m_lastMouse = (wxCanvasObject*)NULL;
m_captureMouse = (wxCanvasObject*)NULL;
m_frozen = TRUE;
- m_requestNewBuffer = TRUE;
+ m_oldDeviceX = 0;
+ m_oldDeviceY = 0;
+
+ //root group always at 0,0
+ m_root = new wxCanvasObjectGroup();
+ m_root->DeleteContents( TRUE );
+ m_root->SetOwner(this);
}
wxCanvas::~wxCanvas()
if (m_frozen) return;
+#if IMAGE_CANVAS
unsigned char *data = m_buffer.GetData();
for (int y = 0; y < m_buffer.GetHeight(); y++)
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 )
void wxCanvas::Update( int x, int y, int width, int height, bool blit )
{
- if (m_frozen) return;
+ CalcScrolledPosition( 0, 0, &m_oldDeviceX, &m_oldDeviceY );
+ if (m_frozen) return;
+
// clip to buffer
if (x < m_bufferX)
{
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;
(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;
for (int xx = start_x; xx < end_x; xx++)
m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
- // cycle through all objects
- wxNode *node = m_objects.First();
- while (node)
- {
- wxCanvasObject *obj = (wxCanvasObject*) node->Data();
-
- if (!obj->IsControl())
- {
- // 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;
+ 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 );
- if (clip_height > 0)
- obj->Render( clip_x, clip_y, clip_width, clip_height );
- }
- }
- }
- }
+ m_renderDC = &dc;
+ m_root->Render(0,0, x, y, width, height );
- node = node->Next();
- }
+ dc.SelectObject( wxNullBitmap );
+#endif
}
void wxCanvas::BlitBuffer( wxDC &dc )
wxRect sub_rect( *rect );
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)
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();
void wxCanvas::Recreate()
{
- wxNode *node = m_objects.First();
- while (node)
- {
- wxCanvasObject *obj = (wxCanvasObject*) node->Data();
-
- obj->Recreate();
-
- node = node->Next();
- }
+ m_root->Recreate();
}
void wxCanvas::Prepend( wxCanvasObject* obj )
{
- m_objects.Insert( obj );
+ m_root->Prepend( obj );
+ obj->SetOwner(this);
- obj->SetOwner( this );
- obj->Recreate();
+ m_root->Recreate();
if (!obj->IsControl())
Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
void wxCanvas::Append( wxCanvasObject* obj )
{
- m_objects.Append( obj );
+ m_root->Append( obj );
+ obj->SetOwner(this);
- obj->SetOwner( this );
- obj->Recreate();
+ m_root->Recreate();
if (!obj->IsControl())
Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
void wxCanvas::Insert( size_t before, wxCanvasObject* obj )
{
- m_objects.Insert( before, obj );
+ m_root->Insert( before, obj );
+ obj->SetOwner(this);
- obj->SetOwner( this );
- obj->Recreate();
+ m_root->Recreate();
if (!obj->IsControl())
Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
int h = obj->GetHeight();
bool ic = obj->IsControl();
- m_objects.DeleteObject( obj );
+ m_root->Remove( obj );
if (!ic)
Update( x, y, w, h );
if (!m_buffer.Ok()) return;
+ if (m_frozen) return;
+
m_needUpdate = TRUE;
wxRegionIterator it( GetUpdateRegion() );
void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
{
// If any updates are pending, do them now since they will
- // expect the previous m_bufferX and m_bufferY values.
- UpdateNow();
+ // expect the previous m_bufferX and m_bufferY as well as
+ // the previous device origin values.
+ wxClientDC dc( this );
+ dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
+ BlitBuffer( dc );
// The buffer always starts at the top left corner of the
// 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)
{
if (dy > 0)
unsigned char *dest = data + (dy * m_buffer.GetWidth() * 3);
size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()-dy));
memmove( dest, source, count );
-
+
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
unsigned char *source = data + (-dy * m_buffer.GetWidth() * 3);
size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()+dy));
memmove( dest, source, count );
-
+
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
Update( m_bufferX, m_bufferY+m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE );
}
}
-
+
if (dx != 0)
{
if (dx > 0)
memmove( dest, source, (m_buffer.GetWidth()-dx) * 3 );
source += m_buffer.GetWidth()*3;
}
-
+
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
memmove( dest, source, (m_buffer.GetWidth()+dx) * 3 );
dest += m_buffer.GetWidth()*3;
}
-
+
// We update the new buffer area, but there is no need to
// blit (last param FALSE) since the ensuing paint event will
// do that anyway.
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 );
}
child_event.m_shiftDown = event.m_shiftDown;
child_event.m_altDown = event.m_altDown;
child_event.m_metaDown = event.m_metaDown;
+
m_captureMouse->ProcessEvent( child_event );
+ return;
}
else
{
- wxNode *node = m_objects.Last();
- while (node)
- {
- wxCanvasObject *obj = (wxCanvasObject*) node->Data();
+ wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
- if (!obj->IsControl())
+ if (obj && !obj->IsControl())
+ {
+ wxMouseEvent child_event( wxEVT_MOTION );
+ child_event.SetEventObject( obj );
+ child_event.m_x = x - obj->GetX();
+ child_event.m_y = y - obj->GetY();
+ child_event.m_leftDown = event.m_leftDown;
+ child_event.m_rightDown = event.m_rightDown;
+ child_event.m_middleDown = event.m_middleDown;
+ child_event.m_controlDown = event.m_controlDown;
+ child_event.m_shiftDown = event.m_shiftDown;
+ child_event.m_altDown = event.m_altDown;
+ child_event.m_metaDown = event.m_metaDown;
+
+ if ((obj != m_lastMouse) && (m_lastMouse != NULL))
{
- if (obj->IsHit(x,y))
- {
- wxMouseEvent child_event( wxEVT_MOTION );
- child_event.SetEventObject( obj );
- child_event.m_x = x - obj->GetX();
- child_event.m_y = y - obj->GetY();
- child_event.m_leftDown = event.m_leftDown;
- child_event.m_rightDown = event.m_rightDown;
- child_event.m_middleDown = event.m_middleDown;
- child_event.m_controlDown = event.m_controlDown;
- child_event.m_shiftDown = event.m_shiftDown;
- child_event.m_altDown = event.m_altDown;
- child_event.m_metaDown = event.m_metaDown;
-
- if ((obj != m_lastMouse) && (m_lastMouse != NULL))
- {
- child_event.SetEventType( wxEVT_LEAVE_WINDOW );
- child_event.SetEventObject( m_lastMouse );
- child_event.m_x = x - m_lastMouse->GetX();
- child_event.m_y = y - m_lastMouse->GetY();
- m_lastMouse->ProcessEvent( child_event );
-
- m_lastMouse = obj;
- child_event.SetEventType( wxEVT_ENTER_WINDOW );
- child_event.SetEventObject( m_lastMouse );
- child_event.m_x = x - m_lastMouse->GetX();
- child_event.m_y = y - m_lastMouse->GetY();
- m_lastMouse->ProcessEvent( child_event );
-
- child_event.SetEventType( wxEVT_MOTION );
- child_event.SetEventObject( obj );
- }
- obj->ProcessEvent( child_event );
- return;
- }
+ child_event.SetEventType( wxEVT_LEAVE_WINDOW );
+ child_event.SetEventObject( m_lastMouse );
+ child_event.m_x = x - m_lastMouse->GetX();
+ child_event.m_y = y - m_lastMouse->GetY();
+ m_lastMouse->ProcessEvent( child_event );
+
+ m_lastMouse = obj;
+ child_event.SetEventType( wxEVT_ENTER_WINDOW );
+ child_event.SetEventObject( m_lastMouse );
+ child_event.m_x = x - m_lastMouse->GetX();
+ child_event.m_y = y - m_lastMouse->GetY();
+ m_lastMouse->ProcessEvent( child_event );
+
+ child_event.SetEventType( wxEVT_MOTION );
+ child_event.SetEventObject( obj );
}
- node = node->Previous();
+
+ obj->ProcessEvent( child_event );
+ return;
}
}
if (m_lastMouse)
return;
}
}
+ else
+ {
+ if (m_captureMouse) //no matter what go to this one
+ {
+ wxMouseEvent child_event( event.GetEventType() );
+ child_event.SetEventObject(m_captureMouse);
+ child_event.m_x = x - m_captureMouse->GetX();
+ child_event.m_y = y - m_captureMouse->GetY();
+ child_event.m_leftDown = event.m_leftDown;
+ child_event.m_rightDown = event.m_rightDown;
+ child_event.m_middleDown = event.m_middleDown;
+ child_event.m_controlDown = event.m_controlDown;
+ child_event.m_shiftDown = event.m_shiftDown;
+ child_event.m_altDown = event.m_altDown;
+ child_event.m_metaDown = event.m_metaDown;
+ m_captureMouse->ProcessEvent( child_event );
+ }
+ else
+ {
+ wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
+
+ if (obj && !obj->IsControl())
+ {
+ wxMouseEvent child_event( event.GetEventType() );
+ child_event.SetEventObject( obj );
+ child_event.m_x = x - obj->GetX();
+ child_event.m_y = y - obj->GetY();
+ child_event.m_leftDown = event.m_leftDown;
+ child_event.m_rightDown = event.m_rightDown;
+ child_event.m_middleDown = event.m_middleDown;
+ child_event.m_controlDown = event.m_controlDown;
+ child_event.m_shiftDown = event.m_shiftDown;
+ child_event.m_altDown = event.m_altDown;
+ child_event.m_metaDown = event.m_metaDown;
+
+ obj->ProcessEvent( child_event );
+ return;
+ }
+ }
+ }
+
event.Skip();
}
void wxCanvas::OnSize(wxSizeEvent &event)
{
- m_requestNewBuffer = TRUE;
- Freeze();
+ 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 );
+
+ wxNode *node = m_updateRects.First();
+ while (node)
+ {
+ wxRect *rect = (wxRect*) node->Data();
+ delete rect;
+ m_updateRects.DeleteNode( node );
+ node = m_updateRects.First();
+ }
+
+ m_frozen = FALSE;
+
+ Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
event.Skip();
}
void wxCanvas::OnIdle(wxIdleEvent &event)
{
- if (m_requestNewBuffer)
- {
- m_requestNewBuffer = FALSE;
-
- int w,h;
- GetClientSize( &w, &h );
- m_buffer = wxImage( w, h );
-
- CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
-
- Thaw();
- }
-
UpdateNow();
event.Skip();
}