]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/canvas/canvas.cpp
3c6f3f58eebf7a1e9ff5bced313ce1ce3a547d48
[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 xabs, int yabs, 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 // wxCanvasObjectGroup
131 //----------------------------------------------------------------------------
132
133 wxCanvasObjectGroup::wxCanvasObjectGroup()
134 {
135 m_validbounds = FALSE;
136 }
137
138 wxCanvasObjectGroup::~wxCanvasObjectGroup()
139 {
140 }
141
142 void wxCanvasObjectGroup::SetOwner(wxCanvas* canvas)
143 {
144 m_owner=canvas;
145 wxNode *node = m_objects.First();
146 while (node)
147 {
148 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
149
150 obj->SetOwner(canvas);
151
152 node = node->Next();
153 }
154 }
155
156 void wxCanvasObjectGroup::ExtendArea(int x, int y)
157 {
158 if (m_validbounds)
159 {
160 if (x < m_minx) m_minx = x;
161 if (y < m_miny) m_miny = y;
162 if (x > m_maxx) m_maxx = x;
163 if (y > m_maxy) m_maxy = y;
164 }
165 else
166 {
167 m_validbounds = TRUE;
168
169 m_minx = x;
170 m_miny = y;
171 m_maxx = x;
172 m_maxy = y;
173 }
174 }
175
176 void wxCanvasObjectGroup::DeleteContents( bool flag)
177 {
178 m_objects.DeleteContents( flag );
179 m_validbounds = FALSE;
180 }
181
182 void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
183 {
184 m_objects.Insert( obj );
185 m_validbounds = FALSE;
186 }
187
188 void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
189 {
190 m_objects.Append( obj );
191 m_validbounds = FALSE;
192 }
193
194 void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
195 {
196 m_objects.Insert( before, obj );
197 m_validbounds = FALSE;
198 }
199
200 void wxCanvasObjectGroup::Remove( wxCanvasObject* obj )
201 {
202 m_objects.DeleteObject( obj );
203 m_validbounds = FALSE;
204 }
205
206 void wxCanvasObjectGroup::Recreate()
207 {
208 m_validbounds = FALSE;
209 wxNode *node = m_objects.First();
210 while (node)
211 {
212 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
213
214 obj->Recreate();
215 ExtendArea(obj->GetX(),obj->GetY());
216 ExtendArea(obj->GetX()+obj->GetWidth(),obj->GetY()+obj->GetHeight());
217
218 node = node->Next();
219 }
220 }
221
222 void wxCanvasObjectGroup::Render(int xabs, int yabs, int x, int y, int width, int height )
223 {
224 // cycle through all objects
225 wxNode *node = m_objects.First();
226 while (node)
227 {
228 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
229
230 if (!obj->IsControl())
231 {
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();
237 if (clip_x < x)
238 {
239 clip_width -= x-clip_x;
240 clip_x = x;
241 }
242 if (clip_width > 0)
243 {
244 if (clip_x + clip_width > x + width)
245 clip_width = x+width-clip_x;
246
247 if (clip_width > 0)
248 {
249 int clip_y = yabs + obj->GetY();
250 int clip_height = obj->GetHeight();
251 if (clip_y < y)
252 {
253 clip_height -= y-clip_y;
254 clip_y = y;
255 }
256 if (clip_height > 0)
257 {
258 if (clip_y + clip_height > y + height)
259 clip_height = y+height-clip_y;
260
261 if (clip_height > 0)
262 obj->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
263 }
264 }
265 }
266 }
267
268 node = node->Next();
269 }
270 }
271
272 void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
273 {
274 }
275
276 bool wxCanvasObjectGroup::IsHit( int x, int y, int margin )
277 {
278 wxNode *node = m_objects.Last();
279 while (node)
280 {
281 wxCanvasObject *obj = (wxCanvasObject*) node->Data();
282
283 if (!obj->IsControl())
284 {
285 if (obj->IsHit(x,y,margin))
286 {
287 return TRUE;
288 }
289 }
290 node = node->Previous();
291 }
292 return FALSE;
293 }
294
295 wxCanvasObject* wxCanvasObjectGroup::IsHitObject( int x, int y, int margin )
296 {
297 wxCanvasObject *obj=0;
298 wxNode *node = m_objects.Last();
299 while (node)
300 {
301 obj=(wxCanvasObject*) node->Data();
302
303 if (!obj->IsControl())
304 {
305 if (obj->IsHit(x,y,margin))
306 {
307 return obj;
308 }
309 }
310 node = node->Previous();
311 }
312
313 return (wxCanvasObject*) NULL;
314 }
315
316 //----------------------------------------------------------------------------
317 // wxCanvasObjectGroupRef
318 //----------------------------------------------------------------------------
319
320 wxCanvasObjectGroupRef::wxCanvasObjectGroupRef(double x, double y, wxCanvasObjectGroup* group)
321 : wxCanvasObject()
322 {
323 m_x = x;
324 m_y = y;
325 m_validbounds = FALSE;
326 m_group = group;
327 }
328
329 void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas)
330 {
331 m_owner = canvas;
332 m_group->SetOwner(canvas);
333 }
334
335 void wxCanvasObjectGroupRef::ExtendArea(int x, int y)
336 {
337 if (m_validbounds)
338 {
339 if (x < m_minx) m_minx = x;
340 if (y < m_miny) m_miny = y;
341 if (x > m_maxx) m_maxx = x;
342 if (y > m_maxy) m_maxy = y;
343 }
344 else
345 {
346 m_validbounds = TRUE;
347
348 m_minx = x;
349 m_miny = y;
350 m_maxx = x;
351 m_maxy = y;
352 }
353 }
354
355 void wxCanvasObjectGroupRef::Recreate()
356 {
357 m_validbounds = FALSE;
358 m_group->Recreate();
359 ExtendArea(m_group->GetXMin(),m_group->GetYMin());
360 ExtendArea(m_group->GetXMax(),m_group->GetYMax());
361
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 ) );
367 }
368
369 void wxCanvasObjectGroupRef::Render(int xabs, int yabs, int x, int y, int width, int height )
370 {
371 xabs += m_owner->GetDeviceX(GetPosX());
372 yabs += m_owner->GetDeviceY(GetPosY());
373
374 int clip_x = xabs + m_group->GetXMin();
375 int clip_width = m_group->GetXMax()-m_group->GetXMin();
376 if (clip_x < x)
377 {
378 clip_width -= x-clip_x;
379 clip_x = x;
380 }
381 if (clip_width > 0)
382 {
383 if (clip_x + clip_width > x + width)
384 clip_width = x+width-clip_x;
385
386 if (clip_width > 0)
387 {
388 int clip_y = yabs + m_group->GetYMin();
389 int clip_height = m_group->GetYMax()-m_group->GetYMin();
390 if (clip_y < y)
391 {
392 clip_height -= y-clip_y;
393 clip_y = y;
394 }
395 if (clip_height > 0)
396 {
397 if (clip_y + clip_height > y + height)
398 clip_height = y+height-clip_y;
399
400 if (clip_height > 0)
401 m_group->Render(xabs,yabs, clip_x, clip_y, clip_width, clip_height );
402 }
403 }
404 }
405 }
406
407 void wxCanvasObjectGroupRef::WriteSVG( wxTextOutputStream &stream )
408 {
409 }
410
411 bool wxCanvasObjectGroupRef::IsHit( int x, int y, int margin )
412 {
413 return m_group->IsHit(x-GetPosX(),y-GetPosY(),margin);
414 }
415
416 wxCanvasObject* wxCanvasObjectGroupRef::IsHitObject( int x, int y, int margin )
417 {
418 return m_group->IsHitObject(x-GetPosX(),y-GetPosY(),margin);
419 }
420
421 void wxCanvasObjectGroupRef::Move( int x, int y )
422 {
423 m_x = x;
424 m_y = y;
425
426 if (!m_isControl)
427 {
428 // TODO: sometimes faster to merge into 1 Update or
429 // to break up into four
430 m_owner->Update(m_area.x, m_area.y, m_area.width, m_area.height );
431 //calculate the new area in pixels relative to the parent
432 SetArea( m_owner->GetDeviceX( m_x + m_minx ),
433 m_owner->GetDeviceY( m_y + m_miny ),
434 m_owner->GetDeviceWidth( m_maxx-m_minx ),
435 m_owner->GetDeviceHeight( m_maxy-m_miny ) );
436 m_owner->Update( m_area.x, m_area.y, m_area.width, m_area.height );
437 }
438 }
439
440
441 //----------------------------------------------------------------------------
442 // wxCanvasRect
443 //----------------------------------------------------------------------------
444
445 wxCanvasRect::wxCanvasRect( double x, double y, double w, double h,
446 unsigned char red, unsigned char green, unsigned char blue )
447 : wxCanvasObject()
448 {
449 m_x = x;
450 m_y = y;
451 m_width = w;
452 m_height = h;
453
454 m_red = red;
455 m_green = green;
456 m_blue = blue;
457 }
458
459 void wxCanvasRect::Recreate()
460 {
461 SetArea( m_owner->GetDeviceX( m_x ),
462 m_owner->GetDeviceY( m_y ),
463 m_owner->GetDeviceWidth( m_width ),
464 m_owner->GetDeviceHeight( m_height ) );
465 }
466
467 void wxCanvasRect::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
468 {
469 int buffer_x = m_owner->GetBufferX();
470 int buffer_y = m_owner->GetBufferY();
471
472 #if IMAGE_CANVAS
473 wxImage *image = m_owner->GetBuffer();
474
475 int start_y = clip_y - buffer_y;
476 int end_y = clip_y+clip_height - buffer_y;
477
478 int start_x = clip_x - buffer_x;
479 int end_x = clip_x+clip_width - buffer_x;
480
481 // speed up later
482 for (int y = start_y; y < end_y; y++)
483 for (int x = start_x; x < end_x; x++)
484 image->SetRGB( x, y, m_red, m_green, m_blue );
485 #else
486 wxMemoryDC *dc = m_owner->GetDC();
487 dc->SetPen( *wxTRANSPARENT_PEN );
488 wxBrush brush( wxColour( m_red,m_green,m_blue), wxSOLID );
489 dc->SetBrush( brush );
490
491 dc->DrawRectangle( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
492 #endif
493 }
494
495 void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
496 {
497 }
498
499 //----------------------------------------------------------------------------
500 // wxCanvasLine
501 //----------------------------------------------------------------------------
502
503 wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2,
504 unsigned char red, unsigned char green, unsigned char blue )
505 : wxCanvasObject()
506 {
507 m_x1 = x1;
508 m_y1 = y1;
509 m_x2 = x2;
510 m_y2 = y2;
511
512 m_red = red;
513 m_green = green;
514 m_blue = blue;
515 }
516
517 void wxCanvasLine::Recreate()
518 {
519 int x1 = m_owner->GetDeviceX( m_x1 );
520 int y1 = m_owner->GetDeviceY( m_y1 );
521 int x2 = m_owner->GetDeviceX( m_x2 );
522 int y2 = m_owner->GetDeviceY( m_y2 );
523 if (x1 > x2)
524 {
525 int tmp = x1;
526 x1 = x2;
527 x2 = tmp;
528 }
529 if (y1 > y2)
530 {
531 int tmp = y1;
532 y1 = y2;
533 y2 = tmp;
534 }
535 SetArea( x1, y1, x2-x1+1, y2-y1+1 );
536 }
537
538 void wxCanvasLine::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
539 {
540 int buffer_x = m_owner->GetBufferX();
541 int buffer_y = m_owner->GetBufferY();
542
543 int x1 = xabs + m_owner->GetDeviceX( m_x1 );
544 int y1 = yabs + m_owner->GetDeviceY( m_y1 );
545 int x2 = xabs + m_owner->GetDeviceX( m_x2 );
546 int y2 = yabs + m_owner->GetDeviceY( m_y2 );
547
548 #if IMAGE_CANVAS
549 wxImage *image = m_owner->GetBuffer();
550 if ((m_area.width == 0) && (m_area.height == 0))
551 {
552 image->SetRGB( m_area.x-buffer_x, m_area.y-buffer_y, m_red, m_green, m_blue );
553 }
554 else
555 {
556 wxInt32 d, ii, jj, di, ai, si, dj, aj, sj;
557 di = x1 - x2;
558 ai = abs(di) << 1;
559 si = (di < 0)? -1 : 1;
560 dj = y1 - y2;
561 aj = abs(dj) << 1;
562 sj = (dj < 0)? -1 : 1;
563
564 ii = x2;
565 jj = y2;
566
567 if (ai > aj)
568 {
569 // iterate over i
570 d = aj - (ai >> 1);
571
572 while (ii != x1)
573 {
574 if ((ii >= clip_x) && (ii < clip_x+clip_width) &&
575 (jj >= clip_y) && (jj < clip_y+clip_height))
576 {
577 image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green );
578 }
579 if (d >= 0)
580 {
581 jj += sj;
582 d -= ai;
583 }
584 ii += si;
585 d += aj;
586 }
587 }
588 else
589 {
590 // iterate over j
591 d = ai - (aj >> 1);
592
593 while (jj != y1)
594 {
595 if ((ii >= clip_x) && (ii < clip_x+clip_width) &&
596 (jj >= clip_y) && (jj < clip_y+clip_height))
597 {
598 image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green );
599 }
600 if (d >= 0)
601 {
602 ii += si;
603 d -= aj;
604 }
605 jj += sj;
606 d += ai;
607 }
608 }
609 }
610 #else
611 wxMemoryDC *dc = m_owner->GetDC();
612 dc->SetClippingRegion( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height );
613
614 wxPen pen( wxColour(m_red,m_green,m_blue), 0, wxSOLID );
615 dc->SetPen( pen );
616 dc->DrawLine( x1-buffer_x, y1-buffer_y, x2-buffer_x, y2-buffer_y );
617
618 dc->DestroyClippingRegion();
619 #endif
620 }
621
622 void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
623 {
624 // no idea
625 }
626
627 //----------------------------------------------------------------------------
628 // wxCanvasImage
629 //----------------------------------------------------------------------------
630
631 wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w, double h )
632 : wxCanvasObject()
633 {
634 m_x = x;
635 m_y = y;
636 m_width = w;
637 m_height = h;
638
639 m_image = image;
640 m_isImage = TRUE;
641 }
642
643 void wxCanvasImage::Recreate()
644 {
645 SetArea( m_owner->GetDeviceX( m_x ),
646 m_owner->GetDeviceY( m_y ),
647 m_owner->GetDeviceWidth( m_width ),
648 m_owner->GetDeviceHeight( m_height ) );
649
650 #if IMAGE_CANVAS
651 if ((m_area.width == m_image.GetWidth()) &&
652 (m_area.width == m_image.GetWidth()))
653 {
654 m_tmp = m_image;
655 }
656 else
657 {
658 m_tmp = m_image.Scale( m_area.width, m_area.height );
659 }
660 #else
661 if ((m_area.width == m_image.GetWidth()) &&
662 (m_area.width == m_image.GetWidth()))
663 {
664 m_tmp = m_image.ConvertToBitmap();
665 }
666 else
667 {
668 wxImage tmp( m_image.Scale( m_area.width, m_area.height ) );
669 m_tmp = tmp.ConvertToBitmap();
670 }
671 #endif
672 }
673
674 void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
675 {
676 int buffer_x = m_owner->GetBufferX();
677 int buffer_y = m_owner->GetBufferY();
678
679 #if IMAGE_CANVAS
680 if ((clip_x == xabs + m_area.x) &&
681 (clip_y == yabs + m_area.y) &&
682 (clip_width == m_area.width) &&
683 (clip_height == m_area.height))
684 {
685 m_owner->GetBuffer()->Paste( m_tmp, clip_x-buffer_x, clip_y-buffer_y );
686 }
687 else
688 {
689 // local coordinates
690 int start_x = clip_x - (xabs + m_area.x);
691 int start_y = clip_y - (yabs + m_area.y);
692
693 wxRect rect( start_x, start_y, clip_width, clip_height );
694 wxImage sub_image( m_tmp.GetSubImage( rect ) );
695 m_owner->GetBuffer()->Paste( sub_image, clip_x-buffer_x, clip_y-buffer_y );
696 }
697 #else
698 wxMemoryDC *dc = m_owner->GetDC();
699
700 if ((clip_x == xabs + m_area.x) &&
701 (clip_y == yabs + m_area.y) &&
702 (clip_width == m_area.width) &&
703 (clip_height == m_area.height))
704 {
705 dc->DrawBitmap( m_tmp, clip_x-buffer_x, clip_y-buffer_y, TRUE );
706 }
707 else
708 {
709 // local coordinates
710 int start_x = clip_x - (xabs + m_area.x);
711 int start_y = clip_y - (yabs + m_area.y);
712
713 // Clipping region faster ?
714 wxRect rect( start_x, start_y, clip_width, clip_height );
715 wxBitmap sub_bitmap( m_tmp.GetSubBitmap( rect ) );
716 dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y, TRUE );
717 }
718 #endif
719 }
720
721 void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
722 {
723 // no idea
724 }
725
726 //----------------------------------------------------------------------------
727 // wxCanvasCtrl
728 //----------------------------------------------------------------------------
729
730 wxCanvasControl::wxCanvasControl( wxWindow *control )
731 : wxCanvasObject()
732 {
733 m_isControl = TRUE;
734 m_control = control;
735 }
736
737 wxCanvasControl::~wxCanvasControl()
738 {
739 m_control->Destroy();
740 }
741
742 void wxCanvasControl::Recreate()
743 {
744 m_control->GetSize( &m_area.width, &m_area.height );
745 m_control->GetPosition( &m_area.x, &m_area.y );
746 }
747
748 void wxCanvasControl::Move( int x, int y )
749 {
750 m_control->Move( x, y );
751 }
752
753 //----------------------------------------------------------------------------
754 // wxCanvasText
755 //----------------------------------------------------------------------------
756
757 class wxFaceData
758 {
759 public:
760 #if wxUSE_FREETYPE
761 FT_Face m_face;
762 #else
763 void *m_dummy;
764 #endif
765 };
766
767 wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size )
768 : wxCanvasObject()
769 {
770 m_text = text;
771 m_fontFileName = fontFile;
772 m_size = size;
773
774 m_red = 0;
775 m_green = 0;
776 m_blue = 0;
777
778 m_alpha = NULL;
779
780 m_x = x;
781 m_y = y;
782
783 #if wxUSE_FREETYPE
784 wxFaceData *data = new wxFaceData;
785 m_faceData = data;
786
787 int error = FT_New_Face( g_freetypeLibrary,
788 m_fontFileName,
789 0,
790 &(data->m_face) );
791
792 error = FT_Set_Char_Size( data->m_face,
793 0,
794 m_size*64,
795 96, // screen dpi
796 96 );
797 #endif
798 }
799
800 wxCanvasText::~wxCanvasText()
801 {
802 #if wxUSE_FREETYPE
803 wxFaceData *data = (wxFaceData*) m_faceData;
804 delete data;
805 #endif
806
807 if (m_alpha) delete [] m_alpha;
808 }
809
810 void wxCanvasText::SetRGB( unsigned char red, unsigned char green, unsigned char blue )
811 {
812 m_red = red;
813 m_green = green;
814 m_blue = blue;
815 }
816
817 void wxCanvasText::SetFlag( int flag )
818 {
819 m_flag = flag;
820 }
821
822 void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height )
823 {
824 if (!m_alpha) return;
825
826 #if IMAGE_CANVAS
827 wxImage *image = m_owner->GetBuffer();
828 int buffer_x = m_owner->GetBufferX();
829 int buffer_y = m_owner->GetBufferY();
830
831 // local coordinates
832 int start_x = clip_x - m_area.x;
833 int end_x = clip_width + start_x;
834 int start_y = clip_y - m_area.y;
835 int end_y = clip_height + start_y;
836
837 for (int y = start_y; y < end_y; y++)
838 for (int x = start_x; x < end_x; x++)
839 {
840 int alpha = m_alpha[y*m_area.width + x];
841 if (alpha)
842 {
843 int image_x = m_area.x+x - buffer_x;
844 int image_y = m_area.y+y - buffer_y;
845 if (alpha == 255)
846 {
847 image->SetRGB( image_x, image_y, m_red, m_green, m_blue );
848 continue;
849 }
850 int red1 = (m_red * alpha) / 255;
851 int green1 = (m_green * alpha) / 255;
852 int blue1 = (m_blue * alpha) / 255;
853
854 alpha = 255-alpha;
855 int red2 = image->GetRed( image_x, image_y );
856 int green2 = image->GetGreen( image_x, image_y );
857 int blue2 = image->GetBlue( image_x, image_y );
858 red2 = (red2 * alpha) / 255;
859 green2 = (green2 * alpha) / 255;
860 blue2 = (blue2 * alpha) / 255;
861
862 image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
863 }
864 }
865 #endif
866 }
867
868 void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
869 {
870 }
871
872 void wxCanvasText::Recreate()
873 {
874 if (m_alpha) delete [] m_alpha;
875
876 m_area.x = m_owner->GetDeviceX( m_x );
877 m_area.y = m_owner->GetDeviceY( m_y );
878
879 m_area.width = 100; // TODO, calculate length
880 m_area.height = m_size;
881 m_alpha = new unsigned char[100*m_size];
882 memset( m_alpha, 0, m_area.width*m_area.height );
883
884 #if wxUSE_FREETYPE
885 FT_Face face = ((wxFaceData*)m_faceData)->m_face;
886 FT_GlyphSlot slot = face->glyph;
887 int pen_x = 0;
888 int pen_y = m_size;
889
890 for (int n = 0; n < (int)m_text.Len(); n++)
891 {
892 FT_UInt index = FT_Get_Char_Index( face, m_text[n] );
893
894 int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
895 if (error) continue;
896
897 error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
898 if (error) continue;
899
900 FT_Bitmap *bitmap = &slot->bitmap;
901 unsigned char* buffer = bitmap->buffer;
902 for (int y = 0; y < bitmap->rows; y++)
903 for (int x = 0; x < bitmap->width; x++)
904 {
905 unsigned char alpha = buffer[ y*bitmap->pitch + x ];
906 if (alpha == 0) continue;
907
908 int xx = pen_x + slot->bitmap_left + x;
909 int yy = pen_y - slot->bitmap_top + y;
910 m_alpha[ yy * m_area.width + xx ] = alpha;
911 }
912
913 pen_x += slot->advance.x >> 6;
914 pen_y += slot->advance.y >> 6;
915 }
916 #endif
917 }
918
919 //----------------------------------------------------------------------------
920 // wxCanvas
921 //----------------------------------------------------------------------------
922
923 IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
924
925 BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
926 EVT_CHAR( wxCanvas::OnChar )
927 EVT_PAINT( wxCanvas::OnPaint )
928 EVT_SIZE( wxCanvas::OnSize )
929 EVT_IDLE( wxCanvas::OnIdle )
930 EVT_MOUSE_EVENTS( wxCanvas::OnMouse )
931 EVT_SET_FOCUS( wxCanvas::OnSetFocus )
932 EVT_KILL_FOCUS( wxCanvas::OnKillFocus )
933 EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground )
934 END_EVENT_TABLE()
935
936 wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id,
937 const wxPoint &position, const wxSize& size, long style ) :
938 wxScrolledWindow( parent, id, position, size, style )
939 {
940 m_bufferX = 0;
941 m_bufferY = 0;
942 m_needUpdate = FALSE;
943 m_red = 0;
944 m_green = 0;
945 m_blue = 0;
946 m_lastMouse = (wxCanvasObject*)NULL;
947 m_captureMouse = (wxCanvasObject*)NULL;
948 m_frozen = TRUE;
949
950 //root group always at 0,0
951 m_root = new wxCanvasObjectGroup();
952 m_root->DeleteContents( TRUE );
953 m_root->SetOwner(this);
954 }
955
956 wxCanvas::~wxCanvas()
957 {
958 wxNode *node = m_updateRects.First();
959 while (node)
960 {
961 wxRect *rect = (wxRect*) node->Data();
962 delete rect;
963 m_updateRects.DeleteNode( node );
964 node = m_updateRects.First();
965 }
966 }
967
968 void wxCanvas::SetArea( int width, int height )
969 {
970 SetScrollbars( 10, 10, width/10, height/10 );
971 }
972
973 void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char blue )
974 {
975 m_red = red;
976 m_green = green;
977 m_blue = blue;
978
979 SetBackgroundColour( wxColour( red, green, blue ) );
980
981 if (m_frozen) return;
982
983 #if IMAGE_CANVAS
984 unsigned char *data = m_buffer.GetData();
985
986 for (int y = 0; y < m_buffer.GetHeight(); y++)
987 for (int x = 0; x < m_buffer.GetWidth(); x++)
988 {
989 data[0] = red;
990 data++;
991 data[0] = green;
992 data++;
993 data[0] = blue;
994 data++;
995 }
996 #else
997 wxMemoryDC dc;
998 dc.SelectObject( m_buffer );
999 dc.SetPen( *wxTRANSPARENT_PEN );
1000 wxBrush brush( wxColour( red,green,blue), wxSOLID );
1001 dc.SetBrush( brush );
1002 dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
1003 dc.SelectObject( wxNullBitmap );
1004 #endif
1005 }
1006
1007 void wxCanvas::SetCaptureMouse( wxCanvasObject *obj )
1008 {
1009 if (obj)
1010 {
1011 wxWindow::CaptureMouse();
1012 m_captureMouse = obj;
1013 }
1014 else
1015 {
1016 wxWindow::ReleaseMouse();
1017 m_captureMouse = NULL;
1018 }
1019 }
1020
1021 void wxCanvas::Freeze()
1022 {
1023 m_frozen = TRUE;
1024 }
1025
1026 void wxCanvas::Thaw()
1027 {
1028 wxNode *node = m_updateRects.First();
1029 while (node)
1030 {
1031 wxRect *rect = (wxRect*) node->Data();
1032 delete rect;
1033 m_updateRects.DeleteNode( node );
1034 node = m_updateRects.First();
1035 }
1036
1037 m_frozen = FALSE;
1038
1039 if (m_buffer.Ok())
1040 Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight() );
1041 }
1042
1043 void wxCanvas::Update( int x, int y, int width, int height, bool blit )
1044 {
1045 if (m_frozen) return;
1046
1047 // clip to buffer
1048 if (x < m_bufferX)
1049 {
1050 width -= m_bufferX-x;
1051 x = m_bufferX;
1052 }
1053 if (width <= 0) return;
1054
1055 if (y < m_bufferY)
1056 {
1057 height -= m_bufferY-y;
1058 y = m_bufferY;
1059 }
1060 if (height <= 0) return;
1061
1062 if (x+width > m_bufferX+m_buffer.GetWidth())
1063 {
1064 width = m_bufferX+m_buffer.GetWidth() - x;
1065 }
1066 if (width <= 0) return;
1067
1068 if (y+height > m_bufferY+m_buffer.GetHeight())
1069 {
1070 height = m_bufferY+m_buffer.GetHeight() - y;
1071 }
1072 if (height <= 0) return;
1073
1074 // update is within the buffer
1075 m_needUpdate = TRUE;
1076
1077 // has to be blitted to screen later
1078 if (blit)
1079 {
1080 m_updateRects.Append(
1081 (wxObject*) new wxRect( x,y,width,height ) );
1082 }
1083
1084 #if IMAGE_CANVAS
1085 // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b)
1086 int start_y = y - m_bufferY;
1087 int end_y = y+height - m_bufferY;
1088 int start_x = x - m_bufferX;
1089 int end_x = x+width - m_bufferX;
1090 for (int yy = start_y; yy < end_y; yy++)
1091 for (int xx = start_x; xx < end_x; xx++)
1092 m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue );
1093
1094 m_root->Render(0,0, x, y, width, height );
1095 #else
1096 wxMemoryDC dc;
1097 dc.SelectObject( m_buffer );
1098 dc.SetPen( *wxTRANSPARENT_PEN );
1099 wxBrush brush( wxColour( m_red,m_green,m_blue), wxSOLID );
1100 dc.SetBrush( brush );
1101 dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height );
1102
1103 m_renderDC = &dc;
1104 m_root->Render(0,0, x, y, width, height );
1105
1106 dc.SelectObject( wxNullBitmap );
1107 #endif
1108 }
1109
1110 void wxCanvas::BlitBuffer( wxDC &dc )
1111 {
1112 wxNode *node = m_updateRects.First();
1113 while (node)
1114 {
1115 wxRect *rect = (wxRect*) node->Data();
1116
1117 wxRect sub_rect( *rect );
1118 sub_rect.x -= m_bufferX;
1119 sub_rect.y -= m_bufferY;
1120
1121 #if IMAGE_CANVAS
1122
1123 wxImage sub_image( m_buffer.GetSubImage( sub_rect ) );
1124 #ifdef __WXGTK__
1125 int bpp = wxDisplayDepth();
1126 if (bpp > 8)
1127 {
1128 // the init code is doubled in wxImage
1129 static bool s_hasInitialized = FALSE;
1130
1131 if (!s_hasInitialized)
1132 {
1133 gdk_rgb_init();
1134 s_hasInitialized = TRUE;
1135 }
1136
1137 gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window,
1138 m_wxwindow->style->black_gc,
1139 sub_rect.x, sub_rect.y,
1140 sub_image.GetWidth(), sub_image.GetHeight(),
1141 GDK_RGB_DITHER_NONE,
1142 sub_image.GetData(),
1143 sub_image.GetWidth()*3 );
1144 }
1145 else
1146 {
1147 wxBitmap bitmap( sub_image.ConvertToBitmap() );
1148 dc.DrawBitmap( bitmap, rect->x, rect->y );
1149 }
1150 #else
1151 wxBitmap bitmap( sub_image.ConvertToBitmap() );
1152 dc.DrawBitmap( bitmap, rect->x, rect->y );
1153 #endif
1154
1155 #else // IMAGE_CANVAS
1156
1157 // Maybe clipping use SetClipping() is faster than
1158 // getting the subrect first and drawing it then?
1159 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( sub_rect ) );
1160 dc.DrawBitmap( sub_bitmap, rect->x, rect->y );
1161
1162 #endif
1163 delete rect;
1164 m_updateRects.DeleteNode( node );
1165 node = m_updateRects.First();
1166 }
1167
1168 m_needUpdate = FALSE;
1169 }
1170
1171 void wxCanvas::UpdateNow()
1172 {
1173 if (m_frozen) return;
1174
1175 if (!m_needUpdate) return;
1176
1177 wxClientDC dc( this );
1178 PrepareDC( dc );
1179
1180 BlitBuffer( dc );
1181 }
1182
1183 int wxCanvas::GetDeviceX( double x )
1184 {
1185 return (int) x;
1186 }
1187
1188 int wxCanvas::GetDeviceY( double y )
1189 {
1190 return (int) y;
1191 }
1192
1193 int wxCanvas::GetDeviceWidth( double width )
1194 {
1195 return (int) width;
1196 }
1197
1198 int wxCanvas::GetDeviceHeight( double height )
1199 {
1200 return (int) height;
1201 }
1202
1203 void wxCanvas::Recreate()
1204 {
1205 m_root->Recreate();
1206 }
1207
1208 void wxCanvas::Prepend( wxCanvasObject* obj )
1209 {
1210 m_root->Prepend( obj );
1211 obj->SetOwner(this);
1212
1213 m_root->Recreate();
1214
1215 if (!obj->IsControl())
1216 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
1217 }
1218
1219 void wxCanvas::Append( wxCanvasObject* obj )
1220 {
1221 m_root->Append( obj );
1222 obj->SetOwner(this);
1223
1224 m_root->Recreate();
1225
1226 if (!obj->IsControl())
1227 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
1228 }
1229
1230 void wxCanvas::Insert( size_t before, wxCanvasObject* obj )
1231 {
1232 m_root->Insert( before, obj );
1233 obj->SetOwner(this);
1234
1235 m_root->Recreate();
1236
1237 if (!obj->IsControl())
1238 Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() );
1239 }
1240
1241 void wxCanvas::Remove( wxCanvasObject* obj )
1242 {
1243 int x = obj->GetX();
1244 int y = obj->GetY();
1245 int w = obj->GetWidth();
1246 int h = obj->GetHeight();
1247 bool ic = obj->IsControl();
1248
1249 m_root->Remove( obj );
1250
1251 if (!ic)
1252 Update( x, y, w, h );
1253 }
1254
1255 void wxCanvas::OnPaint(wxPaintEvent &event)
1256 {
1257 wxPaintDC dc(this);
1258 PrepareDC( dc );
1259
1260 if (!m_buffer.Ok()) return;
1261
1262 if (m_frozen) return;
1263
1264 m_needUpdate = TRUE;
1265
1266 wxRegionIterator it( GetUpdateRegion() );
1267 while (it)
1268 {
1269 int x = it.GetX();
1270 int y = it.GetY();
1271
1272 int w = it.GetWidth();
1273 int h = it.GetHeight();
1274
1275 if (x+w > m_buffer.GetWidth())
1276 w = m_buffer.GetWidth() - x;
1277 if (y+h > m_buffer.GetHeight())
1278 h = m_buffer.GetHeight() - y;
1279
1280 if ((w > 0) && (h > 0))
1281 {
1282 CalcUnscrolledPosition( x, y, &x, &y );
1283 m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
1284 }
1285
1286 it++;
1287 }
1288
1289 BlitBuffer( dc );
1290 }
1291
1292 void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
1293 {
1294 // If any updates are pending, do them now since they will
1295 // expect the previous m_bufferX and m_bufferY values.
1296 UpdateNow();
1297
1298 // The buffer always starts at the top left corner of the
1299 // client area. Indeed, it is the client area.
1300 CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
1301
1302 #if IMAGE_CANVAS
1303 unsigned char* data = m_buffer.GetData();
1304
1305 if (dy != 0)
1306 {
1307 if (dy > 0)
1308 {
1309 unsigned char *source = data;
1310 unsigned char *dest = data + (dy * m_buffer.GetWidth() * 3);
1311 size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()-dy));
1312 memmove( dest, source, count );
1313
1314 // We update the new buffer area, but there is no need to
1315 // blit (last param FALSE) since the ensuing paint event will
1316 // do that anyway.
1317 Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), dy, FALSE );
1318 }
1319 else
1320 {
1321 unsigned char *dest = data;
1322 unsigned char *source = data + (-dy * m_buffer.GetWidth() * 3);
1323 size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()+dy));
1324 memmove( dest, source, count );
1325
1326 // We update the new buffer area, but there is no need to
1327 // blit (last param FALSE) since the ensuing paint event will
1328 // do that anyway.
1329 Update( m_bufferX, m_bufferY+m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE );
1330 }
1331 }
1332
1333 if (dx != 0)
1334 {
1335 if (dx > 0)
1336 {
1337 unsigned char *source = data;
1338 for (int y = 0; y < m_buffer.GetHeight(); y++)
1339 {
1340 unsigned char *dest = source + dx*3;
1341 memmove( dest, source, (m_buffer.GetWidth()-dx) * 3 );
1342 source += m_buffer.GetWidth()*3;
1343 }
1344
1345 // We update the new buffer area, but there is no need to
1346 // blit (last param FALSE) since the ensuing paint event will
1347 // do that anyway.
1348 Update( m_bufferX, m_bufferY, dx, m_buffer.GetHeight(), FALSE );
1349 }
1350 else
1351 {
1352 unsigned char *dest = data;
1353 for (int y = 0; y < m_buffer.GetHeight(); y++)
1354 {
1355 unsigned char *source = dest - dx*3;
1356 memmove( dest, source, (m_buffer.GetWidth()+dx) * 3 );
1357 dest += m_buffer.GetWidth()*3;
1358 }
1359
1360 // We update the new buffer area, but there is no need to
1361 // blit (last param FALSE) since the ensuing paint event will
1362 // do that anyway.
1363 Update( m_bufferX+m_buffer.GetWidth()+dx, m_bufferY, -dx, m_buffer.GetHeight(), FALSE );
1364 }
1365 }
1366 #else
1367 // Update everything, TODO: scrolling
1368 Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
1369 #endif
1370
1371 wxWindow::ScrollWindow( dx, dy, rect );
1372 }
1373
1374 void wxCanvas::OnMouse(wxMouseEvent &event)
1375 {
1376 int x = event.GetX();
1377 int y = event.GetY();
1378 CalcUnscrolledPosition( x, y, &x, &y );
1379
1380 if (event.GetEventType() == wxEVT_MOTION)
1381 {
1382 if (m_captureMouse) //no matter what go to this one
1383 {
1384 wxMouseEvent child_event( wxEVT_MOTION );
1385 child_event.SetEventObject(m_captureMouse);
1386 child_event.m_x = x - m_captureMouse->GetX();
1387 child_event.m_y = y - m_captureMouse->GetY();
1388 child_event.m_leftDown = event.m_leftDown;
1389 child_event.m_rightDown = event.m_rightDown;
1390 child_event.m_middleDown = event.m_middleDown;
1391 child_event.m_controlDown = event.m_controlDown;
1392 child_event.m_shiftDown = event.m_shiftDown;
1393 child_event.m_altDown = event.m_altDown;
1394 child_event.m_metaDown = event.m_metaDown;
1395
1396 m_captureMouse->ProcessEvent( child_event );
1397 return;
1398 }
1399 else
1400 {
1401 wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
1402
1403 if (obj && !obj->IsControl())
1404 {
1405 wxMouseEvent child_event( wxEVT_MOTION );
1406 child_event.SetEventObject( obj );
1407 child_event.m_x = x - obj->GetX();
1408 child_event.m_y = y - obj->GetY();
1409 child_event.m_leftDown = event.m_leftDown;
1410 child_event.m_rightDown = event.m_rightDown;
1411 child_event.m_middleDown = event.m_middleDown;
1412 child_event.m_controlDown = event.m_controlDown;
1413 child_event.m_shiftDown = event.m_shiftDown;
1414 child_event.m_altDown = event.m_altDown;
1415 child_event.m_metaDown = event.m_metaDown;
1416
1417 if ((obj != m_lastMouse) && (m_lastMouse != NULL))
1418 {
1419 child_event.SetEventType( wxEVT_LEAVE_WINDOW );
1420 child_event.SetEventObject( m_lastMouse );
1421 child_event.m_x = x - m_lastMouse->GetX();
1422 child_event.m_y = y - m_lastMouse->GetY();
1423 m_lastMouse->ProcessEvent( child_event );
1424
1425 m_lastMouse = obj;
1426 child_event.SetEventType( wxEVT_ENTER_WINDOW );
1427 child_event.SetEventObject( m_lastMouse );
1428 child_event.m_x = x - m_lastMouse->GetX();
1429 child_event.m_y = y - m_lastMouse->GetY();
1430 m_lastMouse->ProcessEvent( child_event );
1431
1432 child_event.SetEventType( wxEVT_MOTION );
1433 child_event.SetEventObject( obj );
1434 }
1435
1436 obj->ProcessEvent( child_event );
1437 return;
1438 }
1439 }
1440 if (m_lastMouse)
1441 {
1442 wxMouseEvent child_event( wxEVT_LEAVE_WINDOW );
1443 child_event.SetEventObject( m_lastMouse );
1444 child_event.m_x = x - m_lastMouse->GetX();
1445 child_event.m_y = y - m_lastMouse->GetY();
1446 child_event.m_leftDown = event.m_leftDown;
1447 child_event.m_rightDown = event.m_rightDown;
1448 child_event.m_middleDown = event.m_middleDown;
1449 child_event.m_controlDown = event.m_controlDown;
1450 child_event.m_shiftDown = event.m_shiftDown;
1451 child_event.m_altDown = event.m_altDown;
1452 child_event.m_metaDown = event.m_metaDown;
1453 m_lastMouse->ProcessEvent( child_event );
1454
1455 m_lastMouse = (wxCanvasObject*) NULL;
1456 return;
1457 }
1458 }
1459 else
1460 {
1461 if (m_captureMouse) //no matter what go to this one
1462 {
1463 wxMouseEvent child_event( event.GetEventType() );
1464 child_event.SetEventObject(m_captureMouse);
1465 child_event.m_x = x - m_captureMouse->GetX();
1466 child_event.m_y = y - m_captureMouse->GetY();
1467 child_event.m_leftDown = event.m_leftDown;
1468 child_event.m_rightDown = event.m_rightDown;
1469 child_event.m_middleDown = event.m_middleDown;
1470 child_event.m_controlDown = event.m_controlDown;
1471 child_event.m_shiftDown = event.m_shiftDown;
1472 child_event.m_altDown = event.m_altDown;
1473 child_event.m_metaDown = event.m_metaDown;
1474 m_captureMouse->ProcessEvent( child_event );
1475 }
1476 else
1477 {
1478 wxCanvasObject *obj = m_root->IsHitObject(x,y,0);
1479
1480 if (obj && !obj->IsControl())
1481 {
1482 wxMouseEvent child_event( event.GetEventType() );
1483 child_event.SetEventObject( obj );
1484 child_event.m_x = x - obj->GetX();
1485 child_event.m_y = y - obj->GetY();
1486 child_event.m_leftDown = event.m_leftDown;
1487 child_event.m_rightDown = event.m_rightDown;
1488 child_event.m_middleDown = event.m_middleDown;
1489 child_event.m_controlDown = event.m_controlDown;
1490 child_event.m_shiftDown = event.m_shiftDown;
1491 child_event.m_altDown = event.m_altDown;
1492 child_event.m_metaDown = event.m_metaDown;
1493
1494 obj->ProcessEvent( child_event );
1495 return;
1496 }
1497 }
1498 }
1499
1500 event.Skip();
1501 }
1502
1503 void wxCanvas::OnSize(wxSizeEvent &event)
1504 {
1505 int w,h;
1506 GetClientSize( &w, &h );
1507 #if IMAGE_CANVAS
1508 m_buffer = wxImage( w, h );
1509 #else
1510 m_buffer = wxBitmap( w, h );
1511 #endif
1512
1513 CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
1514
1515 wxNode *node = m_updateRects.First();
1516 while (node)
1517 {
1518 wxRect *rect = (wxRect*) node->Data();
1519 delete rect;
1520 m_updateRects.DeleteNode( node );
1521 node = m_updateRects.First();
1522 }
1523
1524 m_frozen = FALSE;
1525
1526 Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
1527
1528 event.Skip();
1529 }
1530
1531 void wxCanvas::OnIdle(wxIdleEvent &event)
1532 {
1533 UpdateNow();
1534 event.Skip();
1535 }
1536
1537 void wxCanvas::OnSetFocus(wxFocusEvent &event)
1538 {
1539 }
1540
1541 void wxCanvas::OnKillFocus(wxFocusEvent &event)
1542 {
1543 }
1544
1545 void wxCanvas::OnChar(wxKeyEvent &event)
1546 {
1547 event.Skip();
1548 }
1549
1550 void wxCanvas::OnEraseBackground(wxEraseEvent &event)
1551 {
1552 }
1553
1554 //--------------------------------------------------------------------
1555 // wxCanvasModule
1556 //--------------------------------------------------------------------
1557
1558 class wxCanvasModule : public wxModule
1559 {
1560 public:
1561 virtual bool OnInit();
1562 virtual void OnExit();
1563
1564 private:
1565 DECLARE_DYNAMIC_CLASS(wxCanvasModule)
1566 };
1567
1568 IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule)
1569
1570 bool wxCanvasModule::OnInit()
1571 {
1572 #if wxUSE_FREETYPE
1573 int error = FT_Init_FreeType( &g_freetypeLibrary );
1574 if (error) return FALSE;
1575 #endif
1576
1577 return TRUE;
1578 }
1579
1580 void wxCanvasModule::OnExit()
1581 {
1582 #if wxUSE_FREETYPE
1583 FT_Done_FreeType( g_freetypeLibrary );
1584 #endif
1585 }