1 /////////////////////////////////////////////////////////////////////////////
3 // Author: Robert Roebling
5 // Copyright: 2000 (c) Robert Roebling
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
10 #pragma implementation "canvas.cpp"
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
20 #include "wx/canvas/canvas.h"
24 #include <gdk/gdkrgb.h>
25 #include "wx/gtk/win_gtk.h"
28 #ifndef wxUSE_FREETYPE
29 #define wxUSE_FREETYPE 1
33 #include <freetype/freetype.h>
36 //----------------------------------------------------------------------------
38 //----------------------------------------------------------------------------
41 FT_Library g_freetypeLibrary
;
44 //----------------------------------------------------------------------------
46 //----------------------------------------------------------------------------
48 wxCanvasObject::wxCanvasObject()
60 void wxCanvasObject::SetArea( int x
, int y
, int width
, int height
)
65 m_area
.height
= height
;
68 void wxCanvasObject::SetArea( wxRect rect
)
72 m_area
.width
= rect
.width
;
73 m_area
.height
= rect
.height
;
76 void wxCanvasObject::Move( int x
, int y
)
86 // TODO: sometimes faster to merge into 1 Update or
87 // to break up into four
88 m_owner
->Update( old_x
, old_y
, m_area
.width
, m_area
.height
);
89 m_owner
->Update( x
, y
, m_area
.width
, m_area
.height
);
93 bool wxCanvasObject::IsHit( int x
, int y
, int margin
)
95 return ((x
>= m_area
.x
-margin
) &&
96 (x
<= m_area
.x
+m_area
.width
+margin
) &&
97 (y
>= m_area
.y
-margin
) &&
98 (y
<= m_area
.y
+m_area
.height
+margin
));
101 void wxCanvasObject::CaptureMouse()
103 m_owner
->SetCaptureMouse( this );
106 void wxCanvasObject::ReleaseMouse()
108 m_owner
->SetCaptureMouse( NULL
);
111 bool wxCanvasObject::IsCapturedMouse()
113 return m_owner
->m_captureMouse
==this;
117 void wxCanvasObject::Render(int xabs
, int yabs
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
121 void wxCanvasObject::Recreate()
125 void wxCanvasObject::WriteSVG( wxTextOutputStream
&stream
)
129 //----------------------------------------------------------------------------
130 // wxCanvasObjectGroup
131 //----------------------------------------------------------------------------
133 wxCanvasObjectGroup::wxCanvasObjectGroup()
138 void wxCanvasObjectGroup::SetOwner(wxCanvas
* canvas
)
141 wxNode
*node
= m_objects
.First();
144 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
146 obj
->SetOwner(canvas
);
152 void wxCanvasObjectGroup::ExtendArea(int x
, int y
)
156 if ( x
< m_minx
) m_minx
= x
;
157 if ( y
< m_miny
) m_miny
= y
;
158 if ( x
> m_maxx
) m_maxx
= x
;
159 if ( y
> m_maxy
) m_maxy
= y
;
163 m_validbounds
= true;
174 void wxCanvasObjectGroup::DeleteContents( bool flag
)
176 m_objects
.DeleteContents( flag
);
181 void wxCanvasObjectGroup::Prepend( wxCanvasObject
* obj
)
183 m_objects
.Insert( obj
);
187 void wxCanvasObjectGroup::Append( wxCanvasObject
* obj
)
189 m_objects
.Append( obj
);
193 void wxCanvasObjectGroup::Insert( size_t before
, wxCanvasObject
* obj
)
195 m_objects
.Insert( before
, obj
);
199 void wxCanvasObjectGroup::Remove( wxCanvasObject
* obj
)
201 m_objects
.DeleteObject( obj
);
205 void wxCanvasObjectGroup::Recreate()
208 wxNode
*node
= m_objects
.First();
211 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
214 ExtendArea(obj
->GetX(),obj
->GetY());
215 ExtendArea(obj
->GetX()+obj
->GetWidth(),obj
->GetY()+obj
->GetHeight());
221 void wxCanvasObjectGroup::Render(int xabs
, int yabs
, int x
, int y
, int width
, int height
)
223 wxImage
*image
= m_owner
->GetBuffer();
224 // cycle through all objects
225 wxNode
*node
= m_objects
.First();
228 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
230 if (!obj
->IsControl())
232 // If we have 10.000 objects, we will go through
233 // this 10.000 times for each update, so we have
234 // to optimise carefully.
235 int clip_x
= xabs
+ obj
->GetX();
236 int clip_width
= obj
->GetWidth();
239 clip_width
-= x
-clip_x
;
244 if (clip_x
+ clip_width
> x
+ width
)
245 clip_width
= x
+width
-clip_x
;
249 int clip_y
= yabs
+ obj
->GetY();
250 int clip_height
= obj
->GetHeight();
253 clip_height
-= y
-clip_y
;
258 if (clip_y
+ clip_height
> y
+ height
)
259 clip_height
= y
+height
-clip_y
;
262 obj
->Render(xabs
,yabs
, clip_x
, clip_y
, clip_width
, clip_height
);
272 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream
&stream
)
276 bool wxCanvasObjectGroup::IsHit( int x
, int y
, int margin
)
278 wxNode
*node
= m_objects
.Last();
281 wxCanvasObject
*obj
= (wxCanvasObject
*) node
->Data();
283 if (!obj
->IsControl())
285 if (obj
->IsHit(x
,y
,margin
))
290 node
= node
->Previous();
295 wxCanvasObject
* wxCanvasObjectGroup::IsHitObject( int x
, int y
, int margin
)
297 wxCanvasObject
*obj
=0;
298 wxNode
*node
= m_objects
.Last();
301 obj
=(wxCanvasObject
*) node
->Data();
303 if (!obj
->IsControl())
305 if (obj
->IsHit(x
,y
,margin
))
310 node
= node
->Previous();
315 //----------------------------------------------------------------------------
316 // wxCanvasObjectGroupRef
317 //----------------------------------------------------------------------------
319 wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x
, double y
, wxCanvasObjectGroup
* group
)
328 void wxCanvasObjectGroupRef::SetOwner(wxCanvas
* canvas
)
331 m_group
->SetOwner(canvas
);
334 void wxCanvasObjectGroupRef::ExtendArea(int x
, int y
)
338 if ( x
< m_minx
) m_minx
= x
;
339 if ( y
< m_miny
) m_miny
= y
;
340 if ( x
> m_maxx
) m_maxx
= x
;
341 if ( y
> m_maxy
) m_maxy
= y
;
345 m_validbounds
= true;
355 void wxCanvasObjectGroupRef::Recreate()
359 ExtendArea(m_group
->GetXMin(),m_group
->GetYMin());
360 ExtendArea(m_group
->GetXMax(),m_group
->GetYMax());
362 //set the area in pixels relative to the parent
363 SetArea( m_owner
->GetDeviceX( m_x
+ m_minx
),
364 m_owner
->GetDeviceY( m_y
+ m_miny
),
365 m_owner
->GetDeviceWidth( m_maxx
-m_minx
),
366 m_owner
->GetDeviceHeight( m_maxy
-m_miny
) );
369 void wxCanvasObjectGroupRef::Render(int xabs
, int yabs
, int x
, int y
, int width
, int height
)
371 wxImage
*image
= m_owner
->GetBuffer();
372 xabs
+=m_owner
->GetDeviceX(GetPosX());
373 yabs
+=m_owner
->GetDeviceY(GetPosY());
375 int clip_x
= xabs
+ m_group
->GetXMin();
376 int clip_width
= m_group
->GetXMax()-m_group
->GetXMin();
379 clip_width
-= x
-clip_x
;
384 if (clip_x
+ clip_width
> x
+ width
)
385 clip_width
= x
+width
-clip_x
;
389 int clip_y
= yabs
+ m_group
->GetYMin();
390 int clip_height
= m_group
->GetYMax()-m_group
->GetYMin();
393 clip_height
-= y
-clip_y
;
398 if (clip_y
+ clip_height
> y
+ height
)
399 clip_height
= y
+height
-clip_y
;
402 m_group
->Render(xabs
,yabs
, clip_x
, clip_y
, clip_width
, clip_height
);
408 void wxCanvasObjectGroupRef::WriteSVG( wxTextOutputStream
&stream
)
412 bool wxCanvasObjectGroupRef::IsHit( int x
, int y
, int margin
)
414 return m_group
->IsHit(x
-GetPosX(),y
-GetPosY(),margin
);
417 wxCanvasObject
* wxCanvasObjectGroupRef::IsHitObject( int x
, int y
, int margin
)
419 return m_group
->IsHitObject(x
-GetPosX(),y
-GetPosY(),margin
);
422 void wxCanvasObjectGroupRef::Move( int x
, int y
)
432 // TODO: sometimes faster to merge into 1 Update or
433 // to break up into four
434 m_owner
->Update(m_area
.x
, m_area
.y
, m_area
.width
, m_area
.height
);
435 //calculate the new area in pixels relative to the parent
436 SetArea( m_owner
->GetDeviceX( m_x
+ m_minx
),
437 m_owner
->GetDeviceY( m_y
+ m_miny
),
438 m_owner
->GetDeviceWidth( m_maxx
-m_minx
),
439 m_owner
->GetDeviceHeight( m_maxy
-m_miny
) );
440 m_owner
->Update( m_area
.x
, m_area
.y
, m_area
.width
, m_area
.height
);
445 //----------------------------------------------------------------------------
447 //----------------------------------------------------------------------------
449 wxCanvasRect::wxCanvasRect( double x
, double y
, double w
, double h
,
450 unsigned char red
, unsigned char green
, unsigned char blue
)
463 void wxCanvasRect::Recreate()
465 SetArea( m_owner
->GetDeviceX( m_x
),
466 m_owner
->GetDeviceY( m_y
),
467 m_owner
->GetDeviceWidth( m_width
),
468 m_owner
->GetDeviceHeight( m_height
) );
471 void wxCanvasRect::Render(int xabs
, int yabs
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
473 wxImage
*image
= m_owner
->GetBuffer();
474 int buffer_x
= m_owner
->GetBufferX();
475 int buffer_y
= m_owner
->GetBufferY();
477 int start_y
= clip_y
- buffer_y
;
478 int end_y
= clip_y
+clip_height
- buffer_y
;
480 int start_x
= clip_x
- buffer_x
;
481 int end_x
= clip_x
+clip_width
- buffer_x
;
484 for (int y
= start_y
; y
< end_y
; y
++)
485 for (int x
= start_x
; x
< end_x
; x
++)
486 image
->SetRGB( x
, y
, m_red
, m_green
, m_blue
);
489 void wxCanvasRect::WriteSVG( wxTextOutputStream
&stream
)
493 //----------------------------------------------------------------------------
495 //----------------------------------------------------------------------------
497 wxCanvasLine::wxCanvasLine( double x1
, double y1
, double x2
, double y2
,
498 unsigned char red
, unsigned char green
, unsigned char blue
)
511 void wxCanvasLine::Recreate()
513 int x1
= m_owner
->GetDeviceX( m_x1
);
514 int y1
= m_owner
->GetDeviceY( m_y1
);
515 int x2
= m_owner
->GetDeviceX( m_x2
);
516 int y2
= m_owner
->GetDeviceY( m_y2
);
529 SetArea( x1
, y1
, x2
-x1
+1, y2
-y1
+1 );
532 void wxCanvasLine::Render(int xabs
, int yabs
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
534 wxImage
*image
= m_owner
->GetBuffer();
535 int buffer_x
= m_owner
->GetBufferX();
536 int buffer_y
= m_owner
->GetBufferY();
538 if ((m_area
.width
== 0) && (m_area
.height
== 0))
540 image
->SetRGB( m_area
.x
-buffer_x
, m_area
.y
-buffer_y
, m_red
, m_green
, m_blue
);
544 int x1
= xabs
+ m_owner
->GetDeviceX( m_x1
);
545 int y1
= yabs
+ m_owner
->GetDeviceY( m_y1
);
546 int x2
= xabs
+ m_owner
->GetDeviceX( m_x2
);
547 int y2
= yabs
+ m_owner
->GetDeviceY( m_y2
);
549 wxInt32 d
, ii
, jj
, di
, ai
, si
, dj
, aj
, sj
;
552 si
= (di
< 0)? -1 : 1;
555 sj
= (dj
< 0)? -1 : 1;
567 if ((ii
>= clip_x
) && (ii
< clip_x
+clip_width
) &&
568 (jj
>= clip_y
) && (jj
< clip_y
+clip_height
))
570 image
->SetRGB( ii
-buffer_x
, jj
-buffer_y
, m_red
, m_blue
, m_green
);
588 if ((ii
>= clip_x
) && (ii
< clip_x
+clip_width
) &&
589 (jj
>= clip_y
) && (jj
< clip_y
+clip_height
))
591 image
->SetRGB( ii
-buffer_x
, jj
-buffer_y
, m_red
, m_blue
, m_green
);
605 void wxCanvasLine::WriteSVG( wxTextOutputStream
&stream
)
610 //----------------------------------------------------------------------------
612 //----------------------------------------------------------------------------
614 wxCanvasImage::wxCanvasImage( const wxImage
&image
, double x
, double y
, double w
, double h
)
626 void wxCanvasImage::Recreate()
628 SetArea( m_owner
->GetDeviceX( m_x
),
629 m_owner
->GetDeviceY( m_y
),
630 m_owner
->GetDeviceWidth( m_width
),
631 m_owner
->GetDeviceHeight( m_height
) );
633 if ((m_area
.width
== m_image
.GetWidth()) &&
634 (m_area
.width
== m_image
.GetWidth()))
637 m_tmp
= m_image
.Scale( m_area
.width
, m_area
.height
);
640 void wxCanvasImage::Render(int xabs
, int yabs
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
642 int buffer_x
= m_owner
->GetBufferX();
643 int buffer_y
= m_owner
->GetBufferY();
645 if ((clip_x
== xabs
+ m_area
.x
) &&
646 (clip_y
== yabs
+ m_area
.y
) &&
647 (clip_width
== m_area
.width
) &&
648 (clip_height
== m_area
.height
))
650 m_owner
->GetBuffer()->Paste( m_tmp
, clip_x
-buffer_x
, clip_y
-buffer_y
);
655 int start_x
= clip_x
- (xabs
+ m_area
.x
);
656 int start_y
= clip_y
- (yabs
+ m_area
.y
);
658 wxRect
rect( start_x
, start_y
, clip_width
, clip_height
);
659 wxImage
sub_image( m_tmp
.GetSubImage( rect
) );
660 m_owner
->GetBuffer()->Paste( sub_image
, clip_x
-buffer_x
, clip_y
-buffer_y
);
664 void wxCanvasImage::WriteSVG( wxTextOutputStream
&stream
)
669 //----------------------------------------------------------------------------
671 //----------------------------------------------------------------------------
673 wxCanvasControl::wxCanvasControl( wxWindow
*control
)
680 wxCanvasControl::~wxCanvasControl()
682 m_control
->Destroy();
685 void wxCanvasControl::Recreate()
687 m_control
->GetSize( &m_area
.width
, &m_area
.height
);
688 m_control
->GetPosition( &m_area
.x
, &m_area
.y
);
691 void wxCanvasControl::Move( int x
, int y
)
693 m_control
->Move( x
, y
);
696 //----------------------------------------------------------------------------
698 //----------------------------------------------------------------------------
710 wxCanvasText::wxCanvasText( const wxString
&text
, double x
, double y
, const wxString
&fontFile
, int size
)
714 m_fontFileName
= fontFile
;
727 wxFaceData
*data
= new wxFaceData
;
730 int error
= FT_New_Face( g_freetypeLibrary
,
735 error
= FT_Set_Char_Size( data
->m_face
,
743 wxCanvasText::~wxCanvasText()
746 wxFaceData
*data
= (wxFaceData
*) m_faceData
;
750 if (m_alpha
) delete [] m_alpha
;
753 void wxCanvasText::SetRGB( unsigned char red
, unsigned char green
, unsigned char blue
)
760 void wxCanvasText::SetFlag( int flag
)
765 void wxCanvasText::Render(int xabs
, int yabs
, int clip_x
, int clip_y
, int clip_width
, int clip_height
)
767 if (!m_alpha
) return;
769 wxImage
*image
= m_owner
->GetBuffer();
770 int buffer_x
= m_owner
->GetBufferX();
771 int buffer_y
= m_owner
->GetBufferY();
774 int start_x
= clip_x
- m_area
.x
;
775 int end_x
= clip_width
+ start_x
;
776 int start_y
= clip_y
- m_area
.y
;
777 int end_y
= clip_height
+ start_y
;
779 for (int y
= start_y
; y
< end_y
; y
++)
780 for (int x
= start_x
; x
< end_x
; x
++)
782 int alpha
= m_alpha
[y
*m_area
.width
+ x
];
785 int image_x
= m_area
.x
+x
- buffer_x
;
786 int image_y
= m_area
.y
+y
- buffer_y
;
789 image
->SetRGB( image_x
, image_y
, m_red
, m_green
, m_blue
);
792 int red1
= (m_red
* alpha
) / 255;
793 int green1
= (m_green
* alpha
) / 255;
794 int blue1
= (m_blue
* alpha
) / 255;
797 int red2
= image
->GetRed( image_x
, image_y
);
798 int green2
= image
->GetGreen( image_x
, image_y
);
799 int blue2
= image
->GetBlue( image_x
, image_y
);
800 red2
= (red2
* alpha
) / 255;
801 green2
= (green2
* alpha
) / 255;
802 blue2
= (blue2
* alpha
) / 255;
804 image
->SetRGB( image_x
, image_y
, red1
+red2
, green1
+green2
, blue1
+blue2
);
809 void wxCanvasText::WriteSVG( wxTextOutputStream
&stream
)
813 void wxCanvasText::Recreate()
815 if (m_alpha
) delete [] m_alpha
;
817 m_area
.x
= m_owner
->GetDeviceX( m_x
);
818 m_area
.y
= m_owner
->GetDeviceY( m_y
);
820 m_area
.width
= 100; // TODO, calculate length
821 m_area
.height
= m_size
;
822 m_alpha
= new unsigned char[100*m_size
];
823 memset( m_alpha
, 0, m_area
.width
*m_area
.height
);
826 FT_Face face
= ((wxFaceData
*)m_faceData
)->m_face
;
827 FT_GlyphSlot slot
= face
->glyph
;
831 for (int n
= 0; n
< (int)m_text
.Len(); n
++)
833 FT_UInt index
= FT_Get_Char_Index( face
, m_text
[n
] );
835 int error
= FT_Load_Glyph( face
, index
, FT_LOAD_DEFAULT
);
838 error
= FT_Render_Glyph( face
->glyph
, ft_render_mode_normal
);
841 FT_Bitmap
*bitmap
= &slot
->bitmap
;
842 unsigned char* buffer
= bitmap
->buffer
;
843 for (int y
= 0; y
< bitmap
->rows
; y
++)
844 for (int x
= 0; x
< bitmap
->width
; x
++)
846 unsigned char alpha
= buffer
[ y
*bitmap
->pitch
+ x
];
847 if (alpha
== 0) continue;
849 int xx
= pen_x
+ slot
->bitmap_left
+ x
;
850 int yy
= pen_y
- slot
->bitmap_top
+ y
;
851 m_alpha
[ yy
* m_area
.width
+ xx
] = alpha
;
854 pen_x
+= slot
->advance
.x
>> 6;
855 pen_y
+= slot
->advance
.y
>> 6;
860 //----------------------------------------------------------------------------
862 //----------------------------------------------------------------------------
864 IMPLEMENT_CLASS(wxCanvas
,wxScrolledWindow
)
866 BEGIN_EVENT_TABLE(wxCanvas
,wxScrolledWindow
)
867 EVT_CHAR( wxCanvas::OnChar
)
868 EVT_PAINT( wxCanvas::OnPaint
)
869 EVT_SIZE( wxCanvas::OnSize
)
870 EVT_IDLE( wxCanvas::OnIdle
)
871 EVT_MOUSE_EVENTS( wxCanvas::OnMouse
)
872 EVT_SET_FOCUS( wxCanvas::OnSetFocus
)
873 EVT_KILL_FOCUS( wxCanvas::OnKillFocus
)
874 EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground
)
877 wxCanvas::wxCanvas( wxWindow
*parent
, wxWindowID id
,
878 const wxPoint
&position
, const wxSize
& size
, long style
) :
879 wxScrolledWindow( parent
, id
, position
, size
, style
)
883 m_needUpdate
= FALSE
;
887 m_lastMouse
= (wxCanvasObject
*)NULL
;
888 m_captureMouse
= (wxCanvasObject
*)NULL
;
890 m_requestNewBuffer
= TRUE
;
892 //root group always at 0,0
893 m_root
= new wxCanvasObjectGroup();
894 m_root
->DeleteContents( TRUE
);
895 m_root
->SetOwner(this);
898 wxCanvas::~wxCanvas()
900 wxNode
*node
= m_updateRects
.First();
903 wxRect
*rect
= (wxRect
*) node
->Data();
905 m_updateRects
.DeleteNode( node
);
906 node
= m_updateRects
.First();
910 void wxCanvas::SetArea( int width
, int height
)
912 SetScrollbars( 10, 10, width
/10, height
/10 );
915 void wxCanvas::SetColour( unsigned char red
, unsigned char green
, unsigned char blue
)
921 SetBackgroundColour( wxColour( red
, green
, blue
) );
923 if (m_frozen
) return;
925 unsigned char *data
= m_buffer
.GetData();
927 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
928 for (int x
= 0; x
< m_buffer
.GetWidth(); x
++)
939 void wxCanvas::SetCaptureMouse( wxCanvasObject
*obj
)
943 wxWindow::CaptureMouse();
944 m_captureMouse
= obj
;
948 wxWindow::ReleaseMouse();
949 m_captureMouse
= NULL
;
953 void wxCanvas::Freeze()
958 void wxCanvas::Thaw()
960 wxNode
*node
= m_updateRects
.First();
963 wxRect
*rect
= (wxRect
*) node
->Data();
965 m_updateRects
.DeleteNode( node
);
966 node
= m_updateRects
.First();
972 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight() );
975 void wxCanvas::Update( int x
, int y
, int width
, int height
, bool blit
)
977 if (m_frozen
) return;
982 width
-= m_bufferX
-x
;
985 if (width
< 0) return;
989 height
-= m_bufferY
-y
;
992 if (height
< 0) return;
994 if (x
+width
> m_bufferX
+m_buffer
.GetWidth())
996 width
= m_bufferX
+m_buffer
.GetWidth() - x
;
998 if (width
< 0) return;
1000 if (y
+height
> m_bufferY
+m_buffer
.GetHeight())
1002 height
= m_bufferY
+m_buffer
.GetHeight() - y
;
1004 if (height
< 0) return;
1006 // update is within the buffer
1007 m_needUpdate
= TRUE
;
1009 // has to be blitted to screen later
1012 m_updateRects
.Append(
1013 (wxObject
*) new wxRect( x
,y
,width
,height
) );
1016 // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
1017 int start_y
= y
- m_bufferY
;
1018 int end_y
= y
+height
- m_bufferY
;
1019 int start_x
= x
- m_bufferX
;
1020 int end_x
= x
+width
- m_bufferX
;
1021 for (int yy
= start_y
; yy
< end_y
; yy
++)
1022 for (int xx
= start_x
; xx
< end_x
; xx
++)
1023 m_buffer
.SetRGB( xx
, yy
, m_red
, m_green
, m_blue
);
1025 m_root
->Render(0,0, x
, y
, width
, height
);
1029 void wxCanvas::BlitBuffer( wxDC
&dc
)
1031 wxNode
*node
= m_updateRects
.First();
1034 wxRect
*rect
= (wxRect
*) node
->Data();
1036 wxRect
sub_rect( *rect
);
1037 sub_rect
.x
-= m_bufferX
;
1038 sub_rect
.y
-= m_bufferY
;
1040 wxImage
sub_image( m_buffer
.GetSubImage( sub_rect
) );
1043 int bpp
= wxDisplayDepth();
1046 // the init code is doubled in wxImage
1047 static bool s_hasInitialized
= FALSE
;
1049 if (!s_hasInitialized
)
1052 s_hasInitialized
= TRUE
;
1055 gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow
)->bin_window
,
1056 m_wxwindow
->style
->black_gc
,
1057 sub_rect
.x
, sub_rect
.y
,
1058 sub_image
.GetWidth(), sub_image
.GetHeight(),
1059 GDK_RGB_DITHER_NONE
,
1060 sub_image
.GetData(),
1061 sub_image
.GetWidth()*3 );
1065 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
1066 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
1071 wxBitmap
bitmap( sub_image
.ConvertToBitmap() );
1072 dc
.DrawBitmap( bitmap
, rect
->x
, rect
->y
);
1076 m_updateRects
.DeleteNode( node
);
1077 node
= m_updateRects
.First();
1080 m_needUpdate
= FALSE
;
1083 void wxCanvas::UpdateNow()
1085 if (m_frozen
) return;
1087 if (!m_needUpdate
) return;
1089 wxClientDC
dc( this );
1095 int wxCanvas::GetDeviceX( double x
)
1100 int wxCanvas::GetDeviceY( double y
)
1105 int wxCanvas::GetDeviceWidth( double width
)
1110 int wxCanvas::GetDeviceHeight( double height
)
1112 return (int) height
;
1115 void wxCanvas::Recreate()
1120 void wxCanvas::Prepend( wxCanvasObject
* obj
)
1122 m_root
->Prepend( obj
);
1123 obj
->SetOwner(this);
1127 if (!obj
->IsControl())
1128 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
1131 void wxCanvas::Append( wxCanvasObject
* obj
)
1133 m_root
->Append( obj
);
1134 obj
->SetOwner(this);
1138 if (!obj
->IsControl())
1139 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
1142 void wxCanvas::Insert( size_t before
, wxCanvasObject
* obj
)
1144 m_root
->Insert( before
, obj
);
1145 obj
->SetOwner(this);
1149 if (!obj
->IsControl())
1150 Update( obj
->GetX(), obj
->GetY(), obj
->GetWidth(), obj
->GetHeight() );
1153 void wxCanvas::Remove( wxCanvasObject
* obj
)
1155 int x
= obj
->GetX();
1156 int y
= obj
->GetY();
1157 int w
= obj
->GetWidth();
1158 int h
= obj
->GetHeight();
1159 bool ic
= obj
->IsControl();
1161 m_root
->Remove( obj
);
1164 Update( x
, y
, w
, h
);
1167 void wxCanvas::OnPaint(wxPaintEvent
&event
)
1172 if (!m_buffer
.Ok()) return;
1174 if (m_frozen
) return;
1176 m_needUpdate
= TRUE
;
1178 wxRegionIterator
it( GetUpdateRegion() );
1184 int w
= it
.GetWidth();
1185 int h
= it
.GetHeight();
1187 if (x
+w
> m_buffer
.GetWidth())
1188 w
= m_buffer
.GetWidth() - x
;
1189 if (y
+h
> m_buffer
.GetHeight())
1190 h
= m_buffer
.GetHeight() - y
;
1192 if ((w
> 0) && (h
> 0))
1194 CalcUnscrolledPosition( x
, y
, &x
, &y
);
1195 m_updateRects
.Append( (wxObject
*) new wxRect( x
, y
, w
, h
) );
1204 void wxCanvas::ScrollWindow( int dx
, int dy
, const wxRect
* rect
)
1206 // If any updates are pending, do them now since they will
1207 // expect the previous m_bufferX and m_bufferY values.
1210 // The buffer always starts at the top left corner of the
1211 // client area. Indeed, it is the client area.
1212 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
1214 unsigned char* data
= m_buffer
.GetData();
1220 unsigned char *source
= data
;
1221 unsigned char *dest
= data
+ (dy
* m_buffer
.GetWidth() * 3);
1222 size_t count
= (size_t) (m_buffer
.GetWidth() * 3 * (m_buffer
.GetHeight()-dy
));
1223 memmove( dest
, source
, count
);
1225 // We update the new buffer area, but there is no need to
1226 // blit (last param FALSE) since the ensuing paint event will
1228 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), dy
, FALSE
);
1232 unsigned char *dest
= data
;
1233 unsigned char *source
= data
+ (-dy
* m_buffer
.GetWidth() * 3);
1234 size_t count
= (size_t) (m_buffer
.GetWidth() * 3 * (m_buffer
.GetHeight()+dy
));
1235 memmove( dest
, source
, count
);
1237 // We update the new buffer area, but there is no need to
1238 // blit (last param FALSE) since the ensuing paint event will
1240 Update( m_bufferX
, m_bufferY
+m_buffer
.GetHeight()+dy
, m_buffer
.GetWidth(), -dy
, FALSE
);
1248 unsigned char *source
= data
;
1249 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
1251 unsigned char *dest
= source
+ dx
*3;
1252 memmove( dest
, source
, (m_buffer
.GetWidth()-dx
) * 3 );
1253 source
+= m_buffer
.GetWidth()*3;
1256 // We update the new buffer area, but there is no need to
1257 // blit (last param FALSE) since the ensuing paint event will
1259 Update( m_bufferX
, m_bufferY
, dx
, m_buffer
.GetHeight(), FALSE
);
1263 unsigned char *dest
= data
;
1264 for (int y
= 0; y
< m_buffer
.GetHeight(); y
++)
1266 unsigned char *source
= dest
- dx
*3;
1267 memmove( dest
, source
, (m_buffer
.GetWidth()+dx
) * 3 );
1268 dest
+= m_buffer
.GetWidth()*3;
1271 // We update the new buffer area, but there is no need to
1272 // blit (last param FALSE) since the ensuing paint event will
1274 Update( m_bufferX
+m_buffer
.GetWidth()+dx
, m_bufferY
, -dx
, m_buffer
.GetHeight(), FALSE
);
1278 wxWindow::ScrollWindow( dx
, dy
, rect
);
1281 void wxCanvas::OnMouse(wxMouseEvent
&event
)
1283 int x
= event
.GetX();
1284 int y
= event
.GetY();
1285 CalcUnscrolledPosition( x
, y
, &x
, &y
);
1287 if (event
.GetEventType() == wxEVT_MOTION
)
1289 if (m_captureMouse
) //no matter what go to this one
1291 wxMouseEvent
child_event( wxEVT_MOTION
);
1292 child_event
.SetEventObject(m_captureMouse
);
1293 child_event
.m_x
= x
- m_captureMouse
->GetX();
1294 child_event
.m_y
= y
- m_captureMouse
->GetY();
1295 child_event
.m_leftDown
= event
.m_leftDown
;
1296 child_event
.m_rightDown
= event
.m_rightDown
;
1297 child_event
.m_middleDown
= event
.m_middleDown
;
1298 child_event
.m_controlDown
= event
.m_controlDown
;
1299 child_event
.m_shiftDown
= event
.m_shiftDown
;
1300 child_event
.m_altDown
= event
.m_altDown
;
1301 child_event
.m_metaDown
= event
.m_metaDown
;
1302 m_captureMouse
->ProcessEvent( child_event
);
1306 wxCanvasObject
*obj
= m_root
->IsHitObject(x
,y
,0);
1308 if (obj
&& !obj
->IsControl())
1310 wxMouseEvent
child_event( wxEVT_MOTION
);
1311 child_event
.SetEventObject( obj
);
1312 child_event
.m_x
= x
- obj
->GetX();
1313 child_event
.m_y
= y
- obj
->GetY();
1314 child_event
.m_leftDown
= event
.m_leftDown
;
1315 child_event
.m_rightDown
= event
.m_rightDown
;
1316 child_event
.m_middleDown
= event
.m_middleDown
;
1317 child_event
.m_controlDown
= event
.m_controlDown
;
1318 child_event
.m_shiftDown
= event
.m_shiftDown
;
1319 child_event
.m_altDown
= event
.m_altDown
;
1320 child_event
.m_metaDown
= event
.m_metaDown
;
1322 if ((obj
!= m_lastMouse
) && (m_lastMouse
!= NULL
))
1324 child_event
.SetEventType( wxEVT_LEAVE_WINDOW
);
1325 child_event
.SetEventObject( m_lastMouse
);
1326 child_event
.m_x
= x
- m_lastMouse
->GetX();
1327 child_event
.m_y
= y
- m_lastMouse
->GetY();
1328 m_lastMouse
->ProcessEvent( child_event
);
1331 child_event
.SetEventType( wxEVT_ENTER_WINDOW
);
1332 child_event
.SetEventObject( m_lastMouse
);
1333 child_event
.m_x
= x
- m_lastMouse
->GetX();
1334 child_event
.m_y
= y
- m_lastMouse
->GetY();
1335 m_lastMouse
->ProcessEvent( child_event
);
1337 child_event
.SetEventType( wxEVT_MOTION
);
1338 child_event
.SetEventObject( obj
);
1340 obj
->ProcessEvent( child_event
);
1346 wxMouseEvent
child_event( wxEVT_LEAVE_WINDOW
);
1347 child_event
.SetEventObject( m_lastMouse
);
1348 child_event
.m_x
= x
- m_lastMouse
->GetX();
1349 child_event
.m_y
= y
- m_lastMouse
->GetY();
1350 child_event
.m_leftDown
= event
.m_leftDown
;
1351 child_event
.m_rightDown
= event
.m_rightDown
;
1352 child_event
.m_middleDown
= event
.m_middleDown
;
1353 child_event
.m_controlDown
= event
.m_controlDown
;
1354 child_event
.m_shiftDown
= event
.m_shiftDown
;
1355 child_event
.m_altDown
= event
.m_altDown
;
1356 child_event
.m_metaDown
= event
.m_metaDown
;
1357 m_lastMouse
->ProcessEvent( child_event
);
1359 m_lastMouse
= (wxCanvasObject
*) NULL
;
1367 void wxCanvas::OnSize(wxSizeEvent
&event
)
1370 GetClientSize( &w
, &h
);
1371 m_buffer
= wxImage( w
, h
);
1373 CalcUnscrolledPosition( 0, 0, &m_bufferX
, &m_bufferY
);
1375 wxNode
*node
= m_updateRects
.First();
1378 wxRect
*rect
= (wxRect
*) node
->Data();
1380 m_updateRects
.DeleteNode( node
);
1381 node
= m_updateRects
.First();
1386 Update( m_bufferX
, m_bufferY
, m_buffer
.GetWidth(), m_buffer
.GetHeight(), FALSE
);
1391 void wxCanvas::OnIdle(wxIdleEvent
&event
)
1397 void wxCanvas::OnSetFocus(wxFocusEvent
&event
)
1401 void wxCanvas::OnKillFocus(wxFocusEvent
&event
)
1405 void wxCanvas::OnChar(wxKeyEvent
&event
)
1410 void wxCanvas::OnEraseBackground(wxEraseEvent
&event
)
1414 //--------------------------------------------------------------------
1416 //--------------------------------------------------------------------
1418 class wxCanvasModule
: public wxModule
1421 virtual bool OnInit();
1422 virtual void OnExit();
1425 DECLARE_DYNAMIC_CLASS(wxCanvasModule
)
1428 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule
, wxModule
)
1430 bool wxCanvasModule::OnInit()
1433 int error
= FT_Init_FreeType( &g_freetypeLibrary
);
1434 if (error
) return FALSE
;
1440 void wxCanvasModule::OnExit()
1443 FT_Done_FreeType( g_freetypeLibrary
);