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