]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/canvas/canvas.cpp
Minor update to wxCanvas.
[wxWidgets.git] / contrib / src / canvas / canvas.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: canvas.cpp
3 // Author: Robert Roebling
4 // Created: XX/XX/XX
5 // Copyright: 2000 (c) Robert Roebling
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9 #ifdef __GNUG__
10 #pragma implementation "canvas.cpp"
11 #endif
12
13 // For compilers that support precompilation, includes "wx/wx.h".
14 #include "wx/wxprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #include "wx/canvas/canvas.h"
21
22 #ifdef __WXGTK__
23 #include <gtk/gtk.h>
24 #include <gdk/gdkrgb.h>
25 #include "wx/gtk/win_gtk.h"
26 #endif
27
28 #ifndef wxUSE_FREETYPE
29 #define wxUSE_FREETYPE 1
30 #endif
31
32 #if wxUSE_FREETYPE
33 #include <freetype/freetype.h>
34 #endif
35
36 //----------------------------------------------------------------------------
37 // globals
38 //----------------------------------------------------------------------------
39
40 #if wxUSE_FREETYPE
41 FT_Library g_freetypeLibrary;
42 #endif
43
44 //----------------------------------------------------------------------------
45 // wxCanvasObject
46 //----------------------------------------------------------------------------
47
48 wxCanvasObject::wxCanvasObject( int x, int y, int width, int height )
49 {
50 m_owner = NULL;
51 m_area.x = x;
52 m_area.y = y;
53 m_area.width = width;
54 m_area.height = height;
55 m_isControl = FALSE;
56 m_isVector = FALSE;
57 m_isImage = FALSE;
58 }
59
60 void wxCanvasObject::Move( int x, int y )
61 {
62 int old_x = m_area.x;
63 int old_y = m_area.y;
64
65 m_area.x = x;
66 m_area.y = y;
67
68 if (!m_isControl)
69 {
70 // TODO: sometimes faster to merge into 1 Update or
71 // to break up into four
72 m_owner->Update( old_x, old_y, m_area.width, m_area.height );
73 m_owner->Update( x, y, m_area.width, m_area.height );
74 }
75 }
76
77 bool wxCanvasObject::IsHit( int x, int y, int margin )
78 {
79 return ((x >= m_area.x-margin) &&
80 (x <= m_area.x+m_area.width+margin) &&
81 (y >= m_area.y-margin) &&
82 (y <= m_area.y+m_area.height+margin));
83 }
84
85 void wxCanvasObject::Render( int clip_x, int clip_y, int clip_width, int clip_height )
86 {
87 }
88
89 void wxCanvasObject::Rerender()
90 {
91 }
92
93 void wxCanvasObject::WriteSVG( wxTextOutputStream &stream )
94 {
95 }
96
97 //----------------------------------------------------------------------------
98 // wxCanvasRect
99 //----------------------------------------------------------------------------
100
101 wxCanvasRect::wxCanvasRect( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue )
102 : wxCanvasObject( x, y, w, h )
103 {
104 m_red = red;
105 m_green = green;
106 m_blue = blue;
107 }
108
109 void wxCanvasRect::Render( int clip_x, int clip_y, int clip_width, int clip_height )
110 {
111 wxImage *image = m_owner->GetBuffer();
112 // speed up later
113 for (int y = clip_y; y < clip_y+clip_height; y++)
114 for (int x = clip_x; x < clip_x+clip_width; x++)
115 image->SetRGB( x, y, m_red, m_green, m_blue );
116 }
117
118 void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
119 {
120 }
121
122 //----------------------------------------------------------------------------
123 // wxCanvasLine
124 //----------------------------------------------------------------------------
125
126 wxCanvasLine::wxCanvasLine( int x, int y, int w, int h, unsigned char red, unsigned char green, unsigned char blue )
127 : wxCanvasObject( x, y, w, h )
128 {
129 m_red = red;
130 m_green = green;
131 m_blue = blue;
132 }
133
134 void wxCanvasLine::Render( int clip_x, int clip_y, int clip_width, int clip_height )
135 {
136 wxImage *image = m_owner->GetBuffer();
137
138 if ((m_area.width == 0) && (m_area.height == 0))
139 {
140 image->SetRGB( m_area.x, m_area.y, m_red, m_green, m_blue );
141 }
142 else
143 {
144 int x1 = m_area.x;
145 int y1 = m_area.y;
146 int x2 = m_area.x+m_area.width;
147 int y2 = m_area.y+m_area.height;
148
149 wxInt32 d, ii, jj, di, ai, si, dj, aj, sj;
150 di = x1 - x2;
151 ai = abs(di) << 1;
152 si = (di < 0)? -1 : 1;
153 dj = y1 - y2;
154 aj = abs(dj) << 1;
155 sj = (dj < 0)? -1 : 1;
156
157 ii = x2;
158 jj = y2;
159
160 if (ai > aj)
161 {
162 // iterate over i
163 d = aj - (ai >> 1);
164
165 while (ii != x1)
166 {
167 if ((ii >= clip_x) && (ii <= clip_x+clip_width) &&
168 (jj >= clip_y) && (jj <= clip_y+clip_height))
169 {
170 image->SetRGB( ii, jj, m_red, m_blue, m_green );
171 }
172 if (d >= 0)
173 {
174 jj += sj;
175 d -= ai;
176 }
177 ii += si;
178 d += aj;
179 }
180 }
181 else
182 {
183 // iterate over j
184 d = ai - (aj >> 1);
185
186 while (jj != y1)
187 {
188 if ((ii >= clip_x) && (ii <= clip_x+clip_width) &&
189 (jj >= clip_y) && (jj <= clip_y+clip_height))
190 {
191 image->SetRGB( ii, jj, m_red, m_blue, m_green );
192 }
193 if (d >= 0)
194 {
195 ii += si;
196 d -= aj;
197 }
198 jj += sj;
199 d += ai;
200 }
201 }
202 }
203 }
204
205 void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
206 {
207 // no idea
208 }
209
210 //----------------------------------------------------------------------------
211 // wxCanvasImage
212 //----------------------------------------------------------------------------
213
214 wxCanvasImage::wxCanvasImage( const wxImage &image, int x, int y )
215 : wxCanvasObject( x, y, image.GetWidth(), image.GetHeight() )
216 {
217 m_image = image;
218 m_isImage = TRUE;
219 }
220
221 void wxCanvasImage::Render( int clip_x, int clip_y, int clip_width, int clip_height )
222 {
223 if ((clip_x == m_area.x) &&
224 (clip_y == m_area.y) &&
225 (clip_width == m_area.width) &&
226 (clip_height == m_area.height))
227 {
228 m_owner->GetBuffer()->Paste( m_image, clip_x, clip_y );
229 }
230 else
231 {
232 // local coordinates
233 int start_x = clip_x - m_area.x;
234 int start_y = clip_y - m_area.y;
235
236 wxRect rect( start_x, start_y, clip_width, clip_height );
237 wxImage sub_image( m_image.GetSubImage( rect ) );
238 m_owner->GetBuffer()->Paste( sub_image, clip_x, clip_y );
239 }
240 }
241
242 void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
243 {
244 // no idea
245 }
246
247 //----------------------------------------------------------------------------
248 // wxCanvasCtrl
249 //----------------------------------------------------------------------------
250
251 wxCanvasControl::wxCanvasControl( wxWindow *control )
252 : wxCanvasObject( -1, -1, -1, -1 )
253 {
254 m_isControl = TRUE;
255 m_control = control;
256 UpdateSize();
257 }
258
259 wxCanvasControl::~wxCanvasControl()
260 {
261 m_control->Destroy();
262 }
263
264 void wxCanvasControl::Move( int x, int y )
265 {
266 m_control->Move( x, y );
267 }
268
269 void wxCanvasControl::UpdateSize()
270 {
271 m_control->GetSize( &m_area.width, &m_area.height );
272 m_control->GetPosition( &m_area.x, &m_area.y );
273 }
274
275 //----------------------------------------------------------------------------
276 // wxCanvasText
277 //----------------------------------------------------------------------------
278
279 class wxFaceData
280 {
281 public:
282 #if wxUSE_FREETYPE
283 FT_Face m_face;
284 #else
285 void *m_dummy;
286 #endif
287 };
288
289 wxCanvasText::wxCanvasText( const wxString &text, int x, int y, const wxString &fontFile, int size )
290 : wxCanvasObject( x, y, -1, -1 )
291 {
292 m_text = text;
293 m_fontFileName = fontFile;
294 m_size = size;
295
296 m_red = 0;
297 m_green = 0;
298 m_blue = 0;
299
300 // test
301 m_area.width = 100;
302 m_area.height = m_size;
303 m_alpha = new unsigned char[100*m_size];
304 memset( m_alpha, 0, m_area.width*m_area.height );
305
306 #if wxUSE_FREETYPE
307 wxFaceData *data = new wxFaceData;
308 m_faceData = data;
309
310 int error = FT_New_Face( g_freetypeLibrary,
311 m_fontFileName,
312 0,
313 &(data->m_face) );
314
315 error = FT_Set_Char_Size( data->m_face,
316 0,
317 m_size*64,
318 96, // screen dpi
319 96 );
320 CreateBuffer();
321 #endif
322 }
323
324 wxCanvasText::~wxCanvasText()
325 {
326 #if wxUSE_FREETYPE
327 wxFaceData *data = (wxFaceData*) m_faceData;
328 delete data;
329 #endif
330
331 if (m_alpha) delete [] m_alpha;
332 }
333
334 void wxCanvasText::SetRGB( unsigned char red, unsigned char green, unsigned char blue )
335 {
336 m_red = red;
337 m_green = green;
338 m_blue = blue;
339 }
340
341 void wxCanvasText::SetFlag( int flag )
342 {
343 m_flag = flag;
344 }
345
346 void wxCanvasText::Render( int clip_x, int clip_y, int clip_width, int clip_height )
347 {
348 if (!m_alpha) return;
349
350 wxImage *image = m_owner->GetBuffer();
351
352 // local coordinates
353 int start_x = clip_x - m_area.x;
354 int end_x = clip_width + start_x;
355 int start_y = clip_y - m_area.y;
356 int end_y = clip_height + start_y;
357
358 for (int y = start_y; y < end_y; y++)
359 for (int x = start_x; x < end_x; x++)
360 {
361 int alpha = m_alpha[y*m_area.width + x];
362 if (alpha)
363 {
364 int image_x = m_area.x+x;
365 int image_y = m_area.y+y;
366 if (alpha == 255)
367 {
368 image->SetRGB( image_x, image_y, m_red, m_green, m_blue );
369 continue;
370 }
371 int red1 = (m_red * alpha) / 255;
372 int green1 = (m_green * alpha) / 255;
373 int blue1 = (m_blue * alpha) / 255;
374
375 alpha = 255-alpha;
376 int red2 = image->GetRed( image_x, image_y );
377 int green2 = image->GetGreen( image_x, image_y );
378 int blue2 = image->GetBlue( image_x, image_y );
379 red2 = (red2 * alpha) / 255;
380 green2 = (green2 * alpha) / 255;
381 blue2 = (blue2 * alpha) / 255;
382
383 image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
384 }
385 }
386 }
387
388 void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
389 {
390 }
391
392 void wxCanvasText::CreateBuffer()
393 {
394 #if wxUSE_FREETYPE
395 FT_Face face = ((wxFaceData*)m_faceData)->m_face;
396 FT_GlyphSlot slot = face->glyph;
397 int pen_x = 0;
398 int pen_y = m_size;
399
400 for (int n = 0; n < (int)m_text.Len(); n++)
401 {
402 FT_UInt index = FT_Get_Char_Index( face, m_text[n] );
403
404 int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
405 if (error) continue;
406
407 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
408 if (error) continue;
409
410 FT_Bitmap *bitmap = &slot->bitmap;
411 unsigned char* buffer = bitmap->buffer;
412 for (int y = 0; y < bitmap->rows; y++)
413 for (int x = 0; x < bitmap->width; x++)
414 {
415 unsigned char alpha = buffer[ y*bitmap->pitch + x ];
416 if (alpha == 0) continue;
417
418 int xx = pen_x + slot->bitmap_left + x;
419 int yy = pen_y - slot->bitmap_top + y;
420 m_alpha[ yy * m_area.width + xx ] = alpha;
421 }
422
423 pen_x += slot->advance.x >> 6;
424 pen_y += slot->advance.y >> 6;
425 }
426 #endif
427 }
428
429 //----------------------------------------------------------------------------
430 // wxCanvas
431 //----------------------------------------------------------------------------
432
433 IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
434
435 BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
436 EVT_CHAR( wxCanvas::OnChar )
437 EVT_PAINT( wxCanvas::OnPaint )
438 EVT_SIZE( wxCanvas::OnSize )
439 EVT_IDLE( wxCanvas::OnIdle )
440 EVT_MOUSE_EVENTS( wxCanvas::OnMouse )
441 EVT_SET_FOCUS( wxCanvas::OnSetFocus )
442 EVT_KILL_FOCUS( wxCanvas::OnKillFocus )
443 END_EVENT_TABLE()
444
445 wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id,
446 const wxPoint &position, const wxSize& size, long style ) :
447 wxScrolledWindow( parent, id, position, size, style )
448 {
449 m_needUpdate = FALSE;
450 m_objects.DeleteContents( TRUE );
451 m_red = 0;
452 m_green = 0;
453 m_blue = 0;
454 m_lastMouse = (wxCanvasObject*)NULL;
455 m_frozen = FALSE;
456 }
457
458 wxCanvas::~wxCanvas()
459 {
460 wxNode *node = m_updateRects.First();
461 while (node)
462 {
463 wxRect *rect = (wxRect*) node->Data();
464 delete rect;
465 m_updateRects.DeleteNode( node );
466 node = m_updateRects.First();
467 }
468 }
469
470 void wxCanvas::SetArea( int width, int height )
471 {
472 m_buffer = wxImage( width, height );
473 SetScrollbars( 10, 10, width/10, height/10 );
474 }
475
476 void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char blue )
477 {
478 m_red = red;
479 m_green = green;
480 m_blue = blue;
481
482 if (m_frozen) return;
483
484 unsigned char *data = m_buffer.GetData();
485
486 for (int y = 0; y < m_buffer.GetHeight(); y++)
487 for (int x = 0; x < m_buffer.GetWidth(); x++)
488 {
489 data[0] = red;
490 data++;
491 data[0] = green;
492 data++;
493 data[0] = blue;
494 data++;
495 }
496 }
497
498 void wxCanvas::Freeze()
499 {
500 m_frozen = TRUE;
501 }
502
503 void wxCanvas::Thaw()
504 {
505 wxNode *node = m_updateRects.First();
506 while (node)
507 {
508 wxRect *rect = (wxRect*) node->Data();
509 delete rect;
510 m_updateRects.DeleteNode( node );
511 node = m_updateRects.First();
512 }
513
514 m_frozen = FALSE;
515
516 Update( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
517 }
518
519 void wxCanvas::Update( int x, int y, int width, int height )
520 {
521 if (m_frozen) return;
522
523 // clip to buffer
524 if (x < 0)
525 {
526 width -= x;
527 x = 0;
528 }
529 if (width < 0) return;
530
531 if (y < 0)
532 {
533 height -= y;
534 y = 0;
535 }
536 if (height < 0) return;
537
538 if (x+width > m_buffer.GetWidth())
539 {
540 width = m_buffer.GetWidth() - x;
541 }
542 if (width < 0) return;
543
544 if (y+height > m_buffer.GetHeight())
545 {
546 height = m_buffer.GetHeight() - y;
547 }
548 if (height < 0) return;
549
550 // update is within the buffer
551 m_needUpdate = TRUE;
552
553 // has to be blitted to screen later
554 m_updateRects.Append(
555 (wxObject*) new wxRect( x,y,width,height ) );
556
557 // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
558 for (int yy = y; yy < y+height; yy++)
559 for (int xx = x; xx < x+width; xx++)
560 m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
561
562 // cycle through all objects
563 wxNode *node = m_objects.First();
564 while (node)
565 {
566 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
567
568 if (!obj->IsControl())
569 {
570 // If we have 10.000 objects, we will go through
571 // this 10.000 times for each update, so we have
572 // to optimise carefully.
573 int clip_x = obj->GetX();
574 int clip_width = obj->GetWidth();
575 if (clip_x < x)
576 {
577 clip_width -= x-clip_x;
578 clip_x = x;
579 }
580 if (clip_width > 0)
581 {
582 if (clip_x + clip_width > x + width)
583 clip_width = x+width-clip_x;
584
585 if (clip_width > 0)
586 {
587 int clip_y = obj->GetY();
588 int clip_height = obj->GetHeight();
589 if (clip_y < y)
590 {
591 clip_height -= y-clip_y;
592 clip_y = y;
593 }
594 if (clip_height > 0)
595 {
596 if (clip_y + clip_height > y + height)
597 clip_height = y+height-clip_y;
598
599 if (clip_height > 0)
600 obj->Render( clip_x, clip_y, clip_width, clip_height );
601 }
602 }
603 }
604 }
605
606 node = node->Next();
607 }
608 }
609
610 void wxCanvas::BlitBuffer( wxDC &dc )
611 {
612 wxNode *node = m_updateRects.First();
613 while (node)
614 {
615 wxRect *rect = (wxRect*) node->Data();
616 wxImage sub_image( m_buffer.GetSubImage( *rect ) );
617
618 // DirectDraw here, please
619
620 #ifdef __WXGTK__
621 int bpp = wxDisplayDepth();
622 if (bpp > 8)
623 {
624 // the init code is doubled in wxImage
625 static bool s_hasInitialized = FALSE;
626
627 if (!s_hasInitialized)
628 {
629 gdk_rgb_init();
630 s_hasInitialized = TRUE;
631 }
632
633 int x = rect->x;
634 int y = rect->y;
635 CalcScrolledPosition( x, y, &x, &y );
636
637 gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window,
638 m_wxwindow->style->black_gc,
639 x, y,
640 sub_image.GetWidth(), sub_image.GetHeight(),
641 GDK_RGB_DITHER_NONE,
642 sub_image.GetData(),
643 sub_image.GetWidth()*3 );
644 }
645 else
646 {
647 wxBitmap bitmap( sub_image.ConvertToBitmap() );
648 dc.DrawBitmap( bitmap, rect->x, rect->y );
649 }
650 #endif
651
652 #ifndef __WXGTK__
653 wxBitmap bitmap( sub_image.ConvertToBitmap() );
654 dc.DrawBitmap( bitmap, rect->x, rect->y );
655 #endif
656
657 delete rect;
658 m_updateRects.DeleteNode( node );
659 node = m_updateRects.First();
660 }
661
662 m_needUpdate = FALSE;
663 }
664
665 void wxCanvas::UpdateNow()
666 {
667 if (!m_needUpdate) return;
668
669 wxClientDC dc( this );
670 PrepareDC( dc );
671
672 BlitBuffer( dc );
673 }
674
675 void wxCanvas::Prepend( wxCanvasObject* obj )
676 {
677 m_objects.Insert( obj );
678
679 obj->SetOwner( this );
680
681 if (!obj->IsControl())
682 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
683 }
684
685 void wxCanvas::Append( wxCanvasObject* obj )
686 {
687 m_objects.Append( obj );
688
689 obj->SetOwner( this );
690
691 if (!obj->IsControl())
692 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
693 }
694
695 void wxCanvas::Insert( size_t before, wxCanvasObject* obj )
696 {
697 m_objects.Insert( before, obj );
698
699 obj->SetOwner( this );
700
701 if (!obj->IsControl())
702 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
703 }
704
705 void wxCanvas::Remove( wxCanvasObject* obj )
706 {
707 int x = obj->GetX();
708 int y = obj->GetY();
709 int w = obj->GetWidth();
710 int h = obj->GetHeight();
711 bool ic = obj->IsControl();
712
713 m_objects.DeleteObject( obj );
714
715 if (!ic)
716 Update( x, y, w, h );
717 }
718
719 void wxCanvas::OnPaint(wxPaintEvent &event)
720 {
721 wxPaintDC dc(this);
722 PrepareDC( dc );
723
724 m_needUpdate = TRUE;
725
726 wxRegionIterator it( GetUpdateRegion() );
727 while (it)
728 {
729 int x = it.GetX();
730 int y = it.GetY();
731 CalcUnscrolledPosition( x, y, &x, &y );
732
733 int w = it.GetWidth();
734 int h = it.GetHeight();
735
736 if (x+w > m_buffer.GetWidth())
737 w = m_buffer.GetWidth() - x;
738 if (y+h > m_buffer.GetHeight())
739 h = m_buffer.GetHeight() - y;
740
741 if ((w > 0) && (h > 0))
742 m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
743
744 it++;
745 }
746
747 BlitBuffer( dc );
748 }
749
750 void wxCanvas::OnMouse(wxMouseEvent &event)
751 {
752 // should we implement mouse capture ?
753
754 int x = event.GetX();
755 int y = event.GetY();
756 CalcUnscrolledPosition( x, y, &x, &y );
757
758 if (event.GetEventType() == wxEVT_MOTION)
759 {
760 wxNode *node = m_objects.First();
761 while (node)
762 {
763 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
764
765 if (!obj->IsControl())
766 {
767 if (obj->IsHit(x,y))
768 {
769 wxMouseEvent child_event( wxEVT_MOTION );
770 child_event.SetEventObject( obj );
771 child_event.m_x = x - obj->GetX();
772 child_event.m_y = y - obj->GetY();
773 child_event.m_leftDown = event.m_leftDown;
774 child_event.m_rightDown = event.m_rightDown;
775 child_event.m_middleDown = event.m_middleDown;
776 child_event.m_controlDown = event.m_controlDown;
777 child_event.m_shiftDown = event.m_shiftDown;
778 child_event.m_altDown = event.m_altDown;
779 child_event.m_metaDown = event.m_metaDown;
780
781 if ((obj != m_lastMouse) && (m_lastMouse != NULL))
782 {
783 child_event.SetEventType( wxEVT_LEAVE_WINDOW );
784 child_event.SetEventObject( m_lastMouse );
785 child_event.m_x = x - m_lastMouse->GetX();
786 child_event.m_y = y - m_lastMouse->GetY();
787 m_lastMouse->ProcessEvent( child_event );
788
789 m_lastMouse = obj;
790 child_event.SetEventType( wxEVT_ENTER_WINDOW );
791 child_event.SetEventObject( m_lastMouse );
792 child_event.m_x = x - m_lastMouse->GetX();
793 child_event.m_y = y - m_lastMouse->GetY();
794 m_lastMouse->ProcessEvent( child_event );
795
796 child_event.SetEventType( wxEVT_MOTION );
797 child_event.SetEventObject( obj );
798 }
799 obj->ProcessEvent( child_event );
800 return;
801 }
802 }
803 node = node->Next();
804 }
805 if (m_lastMouse)
806 {
807 wxMouseEvent child_event( wxEVT_LEAVE_WINDOW );
808 child_event.SetEventObject( m_lastMouse );
809 child_event.m_x = x - m_lastMouse->GetX();
810 child_event.m_y = y - m_lastMouse->GetY();
811 child_event.m_leftDown = event.m_leftDown;
812 child_event.m_rightDown = event.m_rightDown;
813 child_event.m_middleDown = event.m_middleDown;
814 child_event.m_controlDown = event.m_controlDown;
815 child_event.m_shiftDown = event.m_shiftDown;
816 child_event.m_altDown = event.m_altDown;
817 child_event.m_metaDown = event.m_metaDown;
818 m_lastMouse->ProcessEvent( child_event );
819
820 m_lastMouse = (wxCanvasObject*) NULL;
821 return;
822 }
823 }
824 event.Skip();
825 }
826
827 void wxCanvas::OnSize(wxSizeEvent &event)
828 {
829 event.Skip();
830 }
831
832 void wxCanvas::OnIdle(wxIdleEvent &event)
833 {
834 UpdateNow();
835 event.Skip();
836 }
837
838 void wxCanvas::OnSetFocus(wxFocusEvent &event)
839 {
840 }
841
842 void wxCanvas::OnKillFocus(wxFocusEvent &event)
843 {
844 }
845
846 void wxCanvas::OnChar(wxKeyEvent &event)
847 {
848 event.Skip();
849 }
850
851 //--------------------------------------------------------------------
852 // wxCanvasModule
853 //--------------------------------------------------------------------
854
855 class wxCanvasModule : public wxModule
856 {
857 public:
858 virtual bool OnInit();
859 virtual void OnExit();
860
861 private:
862 DECLARE_DYNAMIC_CLASS(wxCanvasModule)
863 };
864
865 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule)
866
867 bool wxCanvasModule::OnInit()
868 {
869 #if wxUSE_FREETYPE
870 int error = FT_Init_FreeType( &g_freetypeLibrary );
871 if (error) return FALSE;
872 #endif
873
874 return TRUE;
875 }
876
877 void wxCanvasModule::OnExit()
878 {
879 #if wxUSE_FREETYPE
880 FT_Done_FreeType( g_freetypeLibrary );
881 #endif
882 }