]>
Commit | Line | Data |
---|---|---|
6a2c1874 RR |
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 | ||
1e1af41e RR |
28 | #ifndef wxUSE_FREETYPE |
29 | #define wxUSE_FREETYPE 1 | |
30 | #endif | |
d1f9b206 | 31 | |
1e1af41e RR |
32 | #if wxUSE_FREETYPE |
33 | #include <freetype/freetype.h> | |
d1f9b206 RR |
34 | #endif |
35 | ||
36 | //---------------------------------------------------------------------------- | |
37 | // globals | |
38 | //---------------------------------------------------------------------------- | |
39 | ||
1e1af41e | 40 | #if wxUSE_FREETYPE |
d1f9b206 RR |
41 | FT_Library g_freetypeLibrary; |
42 | #endif | |
6a2c1874 RR |
43 | |
44 | //---------------------------------------------------------------------------- | |
45 | // wxCanvasObject | |
46 | //---------------------------------------------------------------------------- | |
47 | ||
4dbd4ee6 | 48 | wxCanvasObject::wxCanvasObject() |
6a2c1874 RR |
49 | { |
50 | m_owner = NULL; | |
4dbd4ee6 RR |
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 | { | |
6a2c1874 RR |
62 | m_area.x = x; |
63 | m_area.y = y; | |
64 | m_area.width = width; | |
65 | m_area.height = height; | |
4dbd4ee6 RR |
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; | |
6a2c1874 RR |
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; | |
5143c96b | 80 | |
6a2c1874 RR |
81 | m_area.x = x; |
82 | m_area.y = y; | |
dc16900b | 83 | |
6a2c1874 RR |
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 | ||
239c1f50 RR |
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 | ||
dc16900b KH |
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 | ||
fcbb6b37 | 117 | void wxCanvasObject::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) |
6a2c1874 RR |
118 | { |
119 | } | |
120 | ||
4dbd4ee6 | 121 | void wxCanvasObject::Recreate() |
1e1af41e RR |
122 | { |
123 | } | |
124 | ||
125 | void wxCanvasObject::WriteSVG( wxTextOutputStream &stream ) | |
6a2c1874 RR |
126 | { |
127 | } | |
128 | ||
fcbb6b37 KH |
129 | //---------------------------------------------------------------------------- |
130 | // wxCanvasObjectGroup | |
131 | //---------------------------------------------------------------------------- | |
132 | ||
133 | wxCanvasObjectGroup::wxCanvasObjectGroup() | |
134 | { | |
21840a6c RR |
135 | m_validbounds = FALSE; |
136 | } | |
137 | ||
138 | wxCanvasObjectGroup::~wxCanvasObjectGroup() | |
139 | { | |
fcbb6b37 KH |
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 | ||
5143c96b | 156 | void wxCanvasObjectGroup::ExtendArea(double x, double y) |
fcbb6b37 | 157 | { |
21840a6c RR |
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; | |
fcbb6b37 | 168 | |
21840a6c RR |
169 | m_minx = x; |
170 | m_miny = y; | |
171 | m_maxx = x; | |
172 | m_maxy = y; | |
173 | } | |
fcbb6b37 KH |
174 | } |
175 | ||
fcbb6b37 KH |
176 | void wxCanvasObjectGroup::DeleteContents( bool flag) |
177 | { | |
178 | m_objects.DeleteContents( flag ); | |
21840a6c | 179 | m_validbounds = FALSE; |
fcbb6b37 KH |
180 | } |
181 | ||
fcbb6b37 KH |
182 | void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj ) |
183 | { | |
184 | m_objects.Insert( obj ); | |
21840a6c | 185 | m_validbounds = FALSE; |
fcbb6b37 KH |
186 | } |
187 | ||
188 | void wxCanvasObjectGroup::Append( wxCanvasObject* obj ) | |
189 | { | |
190 | m_objects.Append( obj ); | |
21840a6c | 191 | m_validbounds = FALSE; |
fcbb6b37 KH |
192 | } |
193 | ||
194 | void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj ) | |
195 | { | |
196 | m_objects.Insert( before, obj ); | |
21840a6c | 197 | m_validbounds = FALSE; |
fcbb6b37 KH |
198 | } |
199 | ||
200 | void wxCanvasObjectGroup::Remove( wxCanvasObject* obj ) | |
201 | { | |
202 | m_objects.DeleteObject( obj ); | |
21840a6c | 203 | m_validbounds = FALSE; |
fcbb6b37 KH |
204 | } |
205 | ||
206 | void wxCanvasObjectGroup::Recreate() | |
207 | { | |
21840a6c | 208 | m_validbounds = FALSE; |
fcbb6b37 KH |
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 | { | |
fcbb6b37 KH |
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 | { | |
33ebcd80 | 287 | return TRUE; |
fcbb6b37 KH |
288 | } |
289 | } | |
290 | node = node->Previous(); | |
291 | } | |
33ebcd80 | 292 | return FALSE; |
fcbb6b37 KH |
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 | } | |
5143c96b | 312 | |
21840a6c | 313 | return (wxCanvasObject*) NULL; |
fcbb6b37 KH |
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; | |
33ebcd80 RR |
325 | m_validbounds = FALSE; |
326 | m_group = group; | |
fcbb6b37 KH |
327 | } |
328 | ||
329 | void wxCanvasObjectGroupRef::SetOwner(wxCanvas* canvas) | |
330 | { | |
33ebcd80 | 331 | m_owner = canvas; |
fcbb6b37 KH |
332 | m_group->SetOwner(canvas); |
333 | } | |
334 | ||
5143c96b | 335 | void wxCanvasObjectGroupRef::ExtendArea(double x, double y) |
fcbb6b37 | 336 | { |
33ebcd80 RR |
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; | |
fcbb6b37 | 347 | |
33ebcd80 RR |
348 | m_minx = x; |
349 | m_miny = y; | |
350 | m_maxx = x; | |
351 | m_maxy = y; | |
352 | } | |
fcbb6b37 KH |
353 | } |
354 | ||
355 | void wxCanvasObjectGroupRef::Recreate() | |
356 | { | |
33ebcd80 | 357 | m_validbounds = FALSE; |
fcbb6b37 KH |
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 | { | |
96f5fca9 RR |
371 | xabs += m_area.x; |
372 | yabs += m_area.y; | |
fcbb6b37 KH |
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 | { | |
fcbb6b37 KH |
423 | m_x = x; |
424 | m_y = y; | |
425 | ||
5143c96b KH |
426 | int old_area_x = m_area.x; |
427 | int old_area_y = m_area.y; | |
428 | ||
429 | m_area.x=m_owner->GetDeviceX( m_x + m_minx ); | |
430 | m_area.y=m_owner->GetDeviceY( m_y + m_miny ); | |
431 | ||
432 | int leftu,rightu,bottomu,topu ; | |
433 | leftu = wxMin (m_area.x, old_area_x ) ; | |
434 | rightu = wxMax (old_area_x + m_area.width, m_area.x + m_area.width) ; | |
435 | topu = wxMin (m_area.y,old_area_y) ; | |
436 | bottomu = wxMax (old_area_y + m_area.height, m_area.y + m_area.height) ; | |
437 | ||
438 | if ( rightu - leftu < 2*m_area.width && bottomu - topu < 2*m_area.height ) | |
fcbb6b37 | 439 | { |
5143c96b KH |
440 | m_owner->Update(leftu,topu,rightu - leftu,bottomu - topu); |
441 | } | |
442 | else | |
443 | { | |
444 | m_owner->Update(old_area_x, old_area_y, m_area.width, m_area.height ); | |
fcbb6b37 KH |
445 | m_owner->Update( m_area.x, m_area.y, m_area.width, m_area.height ); |
446 | } | |
447 | } | |
448 | ||
5143c96b KH |
449 | //---------------------------------------------------------------------------- |
450 | // wxCanvasPolyline | |
451 | //---------------------------------------------------------------------------- | |
452 | ||
453 | wxCanvasPolyline::wxCanvasPolyline( int n, wxPoint2DDouble points[]) | |
454 | : wxCanvasObject() | |
455 | { | |
456 | m_n = n; | |
457 | m_points = points; | |
27d1065d | 458 | m_pen = *wxBLACK_PEN; |
5143c96b KH |
459 | } |
460 | ||
461 | wxCanvasPolyline::~wxCanvasPolyline() | |
462 | { | |
463 | delete m_points; | |
464 | } | |
465 | ||
466 | void wxCanvasPolyline::ExtendArea(double x, double y) | |
467 | { | |
468 | if (m_validbounds) | |
469 | { | |
470 | if (x < m_minx) m_minx = x; | |
471 | if (y < m_miny) m_miny = y; | |
472 | if (x > m_maxx) m_maxx = x; | |
473 | if (y > m_maxy) m_maxy = y; | |
474 | } | |
475 | else | |
476 | { | |
477 | m_validbounds = TRUE; | |
478 | ||
479 | m_minx = x; | |
480 | m_miny = y; | |
481 | m_maxx = x; | |
482 | m_maxy = y; | |
483 | } | |
484 | } | |
485 | ||
486 | void wxCanvasPolyline::Recreate() | |
487 | { | |
488 | ||
489 | m_validbounds=FALSE; | |
490 | int i; | |
491 | for (i=0; i < m_n;i++) | |
492 | { | |
493 | ExtendArea(m_points[i].m_x,m_points[i].m_y); | |
494 | } | |
495 | ||
496 | //include the pen width also | |
497 | ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth()); | |
498 | ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2); | |
499 | ||
500 | //set the area in pixels relative to the parent | |
501 | SetArea( m_owner->GetDeviceX(m_minx ), | |
502 | m_owner->GetDeviceY(m_miny ), | |
503 | m_owner->GetDeviceWidth( m_maxx-m_minx ), | |
504 | m_owner->GetDeviceHeight( m_maxy-m_miny ) ); | |
505 | } | |
506 | ||
507 | void wxCanvasPolyline::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) | |
508 | { | |
509 | int buffer_x = m_owner->GetBufferX(); | |
510 | int buffer_y = m_owner->GetBufferY(); | |
511 | ||
512 | int start_y = clip_y - buffer_y; | |
513 | int end_y = clip_y+clip_height - buffer_y; | |
514 | ||
515 | int start_x = clip_x - buffer_x; | |
516 | int end_x = clip_x+clip_width - buffer_x; | |
517 | ||
518 | #if IMAGE_CANVAS | |
519 | #else | |
520 | wxPoint *cpoints = new wxPoint[m_n]; | |
521 | int i; | |
522 | for (i = 0; i < m_n; i++) | |
523 | { | |
524 | cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs); | |
525 | cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs); | |
526 | } | |
527 | wxMemoryDC *dc = m_owner->GetDC(); | |
528 | dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y); | |
529 | dc->SetPen(m_pen); | |
530 | dc->DrawLines(m_n, cpoints, 0,0); | |
531 | delete [] cpoints; | |
532 | dc->SetPen(wxNullPen); | |
533 | dc->DestroyClippingRegion(); | |
534 | #endif | |
535 | } | |
536 | ||
537 | void wxCanvasPolyline::WriteSVG( wxTextOutputStream &stream ) | |
538 | { | |
539 | } | |
540 | ||
541 | //---------------------------------------------------------------------------- | |
542 | // wxCanvasPolygon | |
543 | //---------------------------------------------------------------------------- | |
544 | ||
545 | wxCanvasPolygon::wxCanvasPolygon( int n, wxPoint2DDouble points[]) | |
546 | : wxCanvasObject() | |
547 | { | |
548 | m_n = n; | |
549 | m_points = points; | |
27d1065d RR |
550 | m_brush = *wxBLACK_BRUSH; |
551 | m_pen = *wxTRANSPARENT_PEN; | |
5143c96b KH |
552 | } |
553 | ||
554 | wxCanvasPolygon::~wxCanvasPolygon() | |
555 | { | |
556 | delete m_points; | |
557 | } | |
558 | ||
559 | void wxCanvasPolygon::ExtendArea(double x, double y) | |
560 | { | |
561 | if (m_validbounds) | |
562 | { | |
563 | if (x < m_minx) m_minx = x; | |
564 | if (y < m_miny) m_miny = y; | |
565 | if (x > m_maxx) m_maxx = x; | |
566 | if (y > m_maxy) m_maxy = y; | |
567 | } | |
568 | else | |
569 | { | |
570 | m_validbounds = TRUE; | |
571 | ||
572 | m_minx = x; | |
573 | m_miny = y; | |
574 | m_maxx = x; | |
575 | m_maxy = y; | |
576 | } | |
577 | } | |
578 | ||
579 | void wxCanvasPolygon::Recreate() | |
580 | { | |
581 | ||
582 | m_validbounds=FALSE; | |
583 | int i; | |
584 | for (i=0; i < m_n;i++) | |
585 | { | |
586 | ExtendArea(m_points[i].m_x,m_points[i].m_y); | |
587 | } | |
588 | ||
589 | //include the pen width also | |
590 | ExtendArea(m_minx -m_pen.GetWidth(),m_miny-m_pen.GetWidth()); | |
591 | ExtendArea(m_maxx+m_pen.GetWidth()*2,m_maxy+m_pen.GetWidth()*2); | |
592 | ||
593 | //set the area in pixels relative to the parent | |
594 | SetArea( m_owner->GetDeviceX( m_minx ), | |
595 | m_owner->GetDeviceY( m_miny ), | |
596 | m_owner->GetDeviceWidth( m_maxx-m_minx ), | |
597 | m_owner->GetDeviceHeight( m_maxy-m_miny ) ); | |
598 | } | |
599 | ||
600 | void wxCanvasPolygon::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) | |
601 | { | |
602 | int buffer_x = m_owner->GetBufferX(); | |
603 | int buffer_y = m_owner->GetBufferY(); | |
604 | ||
605 | int start_y = clip_y - buffer_y; | |
606 | int end_y = clip_y+clip_height - buffer_y; | |
607 | ||
608 | int start_x = clip_x - buffer_x; | |
609 | int end_x = clip_x+clip_width - buffer_x; | |
610 | ||
611 | #if IMAGE_CANVAS | |
612 | #else | |
613 | wxPoint *cpoints = new wxPoint[m_n]; | |
614 | int i; | |
615 | for (i = 0; i < m_n; i++) | |
616 | { | |
617 | cpoints[i].x = m_owner->GetDeviceX(m_points[i].m_x+xabs); | |
618 | cpoints[i].y = m_owner->GetDeviceY(m_points[i].m_y+yabs); | |
619 | } | |
620 | wxMemoryDC *dc = m_owner->GetDC(); | |
621 | dc->SetClippingRegion(start_x,start_y,end_x-start_x,end_y-start_y); | |
622 | dc->SetBrush(m_brush); | |
623 | dc->SetPen(m_pen); | |
624 | dc->DrawPolygon(m_n, cpoints, 0,0,wxWINDING_RULE); | |
625 | delete [] cpoints; | |
626 | dc->SetBrush(wxNullBrush); | |
627 | dc->SetPen(wxNullPen); | |
628 | dc->DestroyClippingRegion(); | |
629 | #endif | |
630 | } | |
631 | ||
632 | void wxCanvasPolygon::WriteSVG( wxTextOutputStream &stream ) | |
633 | { | |
634 | } | |
635 | ||
636 | ||
fcbb6b37 | 637 | |
21544859 RR |
638 | //---------------------------------------------------------------------------- |
639 | // wxCanvasRect | |
640 | //---------------------------------------------------------------------------- | |
641 | ||
27d1065d | 642 | wxCanvasRect::wxCanvasRect( double x, double y, double w, double h ) |
4dbd4ee6 | 643 | : wxCanvasObject() |
21544859 | 644 | { |
4dbd4ee6 RR |
645 | m_x = x; |
646 | m_y = y; | |
647 | m_width = w; | |
648 | m_height = h; | |
dc16900b | 649 | |
27d1065d RR |
650 | m_brush = *wxBLACK_BRUSH; |
651 | m_pen = *wxTRANSPARENT_PEN; | |
21544859 RR |
652 | } |
653 | ||
4dbd4ee6 RR |
654 | void wxCanvasRect::Recreate() |
655 | { | |
656 | SetArea( m_owner->GetDeviceX( m_x ), | |
657 | m_owner->GetDeviceY( m_y ), | |
658 | m_owner->GetDeviceWidth( m_width ), | |
659 | m_owner->GetDeviceHeight( m_height ) ); | |
660 | } | |
661 | ||
fcbb6b37 | 662 | void wxCanvasRect::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) |
21544859 | 663 | { |
41328253 RR |
664 | int buffer_x = m_owner->GetBufferX(); |
665 | int buffer_y = m_owner->GetBufferY(); | |
fcbb6b37 | 666 | |
33ebcd80 RR |
667 | #if IMAGE_CANVAS |
668 | wxImage *image = m_owner->GetBuffer(); | |
669 | ||
41328253 RR |
670 | int start_y = clip_y - buffer_y; |
671 | int end_y = clip_y+clip_height - buffer_y; | |
fcbb6b37 | 672 | |
41328253 RR |
673 | int start_x = clip_x - buffer_x; |
674 | int end_x = clip_x+clip_width - buffer_x; | |
fcbb6b37 | 675 | |
21544859 | 676 | // speed up later |
41328253 RR |
677 | for (int y = start_y; y < end_y; y++) |
678 | for (int x = start_x; x < end_x; x++) | |
21544859 | 679 | image->SetRGB( x, y, m_red, m_green, m_blue ); |
33ebcd80 RR |
680 | #else |
681 | wxMemoryDC *dc = m_owner->GetDC(); | |
27d1065d RR |
682 | dc->SetPen( m_pen ); |
683 | dc->SetBrush( m_brush ); | |
33ebcd80 RR |
684 | dc->DrawRectangle( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height ); |
685 | #endif | |
21544859 RR |
686 | } |
687 | ||
688 | void wxCanvasRect::WriteSVG( wxTextOutputStream &stream ) | |
689 | { | |
690 | } | |
691 | ||
239c1f50 RR |
692 | //---------------------------------------------------------------------------- |
693 | // wxCanvasLine | |
694 | //---------------------------------------------------------------------------- | |
695 | ||
27d1065d | 696 | wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2 ) |
4dbd4ee6 | 697 | : wxCanvasObject() |
239c1f50 | 698 | { |
4dbd4ee6 RR |
699 | m_x1 = x1; |
700 | m_y1 = y1; | |
701 | m_x2 = x2; | |
702 | m_y2 = y2; | |
703 | ||
27d1065d | 704 | m_pen = *wxBLACK_PEN; |
239c1f50 RR |
705 | } |
706 | ||
4dbd4ee6 RR |
707 | void wxCanvasLine::Recreate() |
708 | { | |
709 | int x1 = m_owner->GetDeviceX( m_x1 ); | |
710 | int y1 = m_owner->GetDeviceY( m_y1 ); | |
711 | int x2 = m_owner->GetDeviceX( m_x2 ); | |
712 | int y2 = m_owner->GetDeviceY( m_y2 ); | |
713 | if (x1 > x2) | |
714 | { | |
715 | int tmp = x1; | |
716 | x1 = x2; | |
717 | x2 = tmp; | |
718 | } | |
719 | if (y1 > y2) | |
720 | { | |
721 | int tmp = y1; | |
722 | y1 = y2; | |
723 | y2 = tmp; | |
724 | } | |
725 | SetArea( x1, y1, x2-x1+1, y2-y1+1 ); | |
726 | } | |
727 | ||
fcbb6b37 | 728 | void wxCanvasLine::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) |
239c1f50 | 729 | { |
41328253 RR |
730 | int buffer_x = m_owner->GetBufferX(); |
731 | int buffer_y = m_owner->GetBufferY(); | |
fcbb6b37 | 732 | |
33ebcd80 RR |
733 | int x1 = xabs + m_owner->GetDeviceX( m_x1 ); |
734 | int y1 = yabs + m_owner->GetDeviceY( m_y1 ); | |
735 | int x2 = xabs + m_owner->GetDeviceX( m_x2 ); | |
736 | int y2 = yabs + m_owner->GetDeviceY( m_y2 ); | |
5143c96b | 737 | |
33ebcd80 RR |
738 | #if IMAGE_CANVAS |
739 | wxImage *image = m_owner->GetBuffer(); | |
239c1f50 RR |
740 | if ((m_area.width == 0) && (m_area.height == 0)) |
741 | { | |
41328253 | 742 | image->SetRGB( m_area.x-buffer_x, m_area.y-buffer_y, m_red, m_green, m_blue ); |
239c1f50 RR |
743 | } |
744 | else | |
745 | { | |
239c1f50 RR |
746 | wxInt32 d, ii, jj, di, ai, si, dj, aj, sj; |
747 | di = x1 - x2; | |
748 | ai = abs(di) << 1; | |
749 | si = (di < 0)? -1 : 1; | |
750 | dj = y1 - y2; | |
751 | aj = abs(dj) << 1; | |
752 | sj = (dj < 0)? -1 : 1; | |
753 | ||
754 | ii = x2; | |
755 | jj = y2; | |
dc16900b | 756 | |
239c1f50 RR |
757 | if (ai > aj) |
758 | { | |
759 | // iterate over i | |
dc16900b KH |
760 | d = aj - (ai >> 1); |
761 | ||
239c1f50 RR |
762 | while (ii != x1) |
763 | { | |
61b64bd9 RR |
764 | if ((ii >= clip_x) && (ii < clip_x+clip_width) && |
765 | (jj >= clip_y) && (jj < clip_y+clip_height)) | |
239c1f50 | 766 | { |
41328253 | 767 | image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green ); |
239c1f50 RR |
768 | } |
769 | if (d >= 0) | |
770 | { | |
771 | jj += sj; | |
dc16900b | 772 | d -= ai; |
239c1f50 RR |
773 | } |
774 | ii += si; | |
775 | d += aj; | |
776 | } | |
777 | } | |
778 | else | |
779 | { | |
780 | // iterate over j | |
781 | d = ai - (aj >> 1); | |
782 | ||
783 | while (jj != y1) | |
784 | { | |
61b64bd9 RR |
785 | if ((ii >= clip_x) && (ii < clip_x+clip_width) && |
786 | (jj >= clip_y) && (jj < clip_y+clip_height)) | |
239c1f50 | 787 | { |
41328253 | 788 | image->SetRGB( ii-buffer_x, jj-buffer_y, m_red, m_blue, m_green ); |
239c1f50 RR |
789 | } |
790 | if (d >= 0) | |
791 | { | |
792 | ii += si; | |
dc16900b | 793 | d -= aj; |
239c1f50 RR |
794 | } |
795 | jj += sj; | |
796 | d += ai; | |
797 | } | |
798 | } | |
799 | } | |
33ebcd80 RR |
800 | #else |
801 | wxMemoryDC *dc = m_owner->GetDC(); | |
802 | dc->SetClippingRegion( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height ); | |
27d1065d | 803 | dc->SetPen( m_pen ); |
33ebcd80 | 804 | dc->DrawLine( x1-buffer_x, y1-buffer_y, x2-buffer_x, y2-buffer_y ); |
5143c96b | 805 | |
33ebcd80 RR |
806 | dc->DestroyClippingRegion(); |
807 | #endif | |
239c1f50 RR |
808 | } |
809 | ||
810 | void wxCanvasLine::WriteSVG( wxTextOutputStream &stream ) | |
811 | { | |
1e1af41e | 812 | // no idea |
239c1f50 RR |
813 | } |
814 | ||
6a2c1874 RR |
815 | //---------------------------------------------------------------------------- |
816 | // wxCanvasImage | |
817 | //---------------------------------------------------------------------------- | |
818 | ||
4dbd4ee6 RR |
819 | wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w, double h ) |
820 | : wxCanvasObject() | |
6a2c1874 | 821 | { |
4dbd4ee6 RR |
822 | m_x = x; |
823 | m_y = y; | |
824 | m_width = w; | |
825 | m_height = h; | |
dc16900b | 826 | |
6a2c1874 RR |
827 | m_image = image; |
828 | m_isImage = TRUE; | |
829 | } | |
830 | ||
4dbd4ee6 RR |
831 | void wxCanvasImage::Recreate() |
832 | { | |
833 | SetArea( m_owner->GetDeviceX( m_x ), | |
834 | m_owner->GetDeviceY( m_y ), | |
835 | m_owner->GetDeviceWidth( m_width ), | |
836 | m_owner->GetDeviceHeight( m_height ) ); | |
dc16900b | 837 | |
33ebcd80 | 838 | #if IMAGE_CANVAS |
4dbd4ee6 RR |
839 | if ((m_area.width == m_image.GetWidth()) && |
840 | (m_area.width == m_image.GetWidth())) | |
33ebcd80 | 841 | { |
4dbd4ee6 | 842 | m_tmp = m_image; |
33ebcd80 | 843 | } |
4dbd4ee6 | 844 | else |
33ebcd80 | 845 | { |
4dbd4ee6 | 846 | m_tmp = m_image.Scale( m_area.width, m_area.height ); |
33ebcd80 RR |
847 | } |
848 | #else | |
849 | if ((m_area.width == m_image.GetWidth()) && | |
850 | (m_area.width == m_image.GetWidth())) | |
851 | { | |
852 | m_tmp = m_image.ConvertToBitmap(); | |
853 | } | |
854 | else | |
855 | { | |
856 | wxImage tmp( m_image.Scale( m_area.width, m_area.height ) ); | |
857 | m_tmp = tmp.ConvertToBitmap(); | |
858 | } | |
859 | #endif | |
4dbd4ee6 RR |
860 | } |
861 | ||
fcbb6b37 | 862 | void wxCanvasImage::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) |
6a2c1874 | 863 | { |
41328253 RR |
864 | int buffer_x = m_owner->GetBufferX(); |
865 | int buffer_y = m_owner->GetBufferY(); | |
fcbb6b37 | 866 | |
33ebcd80 | 867 | #if IMAGE_CANVAS |
fcbb6b37 KH |
868 | if ((clip_x == xabs + m_area.x) && |
869 | (clip_y == yabs + m_area.y) && | |
21544859 RR |
870 | (clip_width == m_area.width) && |
871 | (clip_height == m_area.height)) | |
d1f9b206 | 872 | { |
41328253 | 873 | m_owner->GetBuffer()->Paste( m_tmp, clip_x-buffer_x, clip_y-buffer_y ); |
d1f9b206 RR |
874 | } |
875 | else | |
876 | { | |
21544859 | 877 | // local coordinates |
fcbb6b37 KH |
878 | int start_x = clip_x - (xabs + m_area.x); |
879 | int start_y = clip_y - (yabs + m_area.y); | |
dc16900b | 880 | |
21544859 | 881 | wxRect rect( start_x, start_y, clip_width, clip_height ); |
4dbd4ee6 | 882 | wxImage sub_image( m_tmp.GetSubImage( rect ) ); |
41328253 | 883 | m_owner->GetBuffer()->Paste( sub_image, clip_x-buffer_x, clip_y-buffer_y ); |
d1f9b206 | 884 | } |
33ebcd80 RR |
885 | #else |
886 | wxMemoryDC *dc = m_owner->GetDC(); | |
5143c96b | 887 | |
33ebcd80 RR |
888 | if ((clip_x == xabs + m_area.x) && |
889 | (clip_y == yabs + m_area.y) && | |
890 | (clip_width == m_area.width) && | |
891 | (clip_height == m_area.height)) | |
892 | { | |
893 | dc->DrawBitmap( m_tmp, clip_x-buffer_x, clip_y-buffer_y, TRUE ); | |
894 | } | |
895 | else | |
896 | { | |
897 | // local coordinates | |
898 | int start_x = clip_x - (xabs + m_area.x); | |
899 | int start_y = clip_y - (yabs + m_area.y); | |
5143c96b | 900 | |
33ebcd80 RR |
901 | // Clipping region faster ? |
902 | wxRect rect( start_x, start_y, clip_width, clip_height ); | |
903 | wxBitmap sub_bitmap( m_tmp.GetSubBitmap( rect ) ); | |
904 | dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y, TRUE ); | |
905 | } | |
906 | #endif | |
6a2c1874 RR |
907 | } |
908 | ||
909 | void wxCanvasImage::WriteSVG( wxTextOutputStream &stream ) | |
910 | { | |
911 | // no idea | |
912 | } | |
913 | ||
3b111dbe RR |
914 | //---------------------------------------------------------------------------- |
915 | // wxCanvasCtrl | |
916 | //---------------------------------------------------------------------------- | |
917 | ||
918 | wxCanvasControl::wxCanvasControl( wxWindow *control ) | |
4dbd4ee6 | 919 | : wxCanvasObject() |
3b111dbe | 920 | { |
21544859 | 921 | m_isControl = TRUE; |
3b111dbe | 922 | m_control = control; |
3b111dbe RR |
923 | } |
924 | ||
925 | wxCanvasControl::~wxCanvasControl() | |
926 | { | |
927 | m_control->Destroy(); | |
928 | } | |
929 | ||
4dbd4ee6 | 930 | void wxCanvasControl::Recreate() |
3b111dbe | 931 | { |
4dbd4ee6 RR |
932 | m_control->GetSize( &m_area.width, &m_area.height ); |
933 | m_control->GetPosition( &m_area.x, &m_area.y ); | |
3b111dbe RR |
934 | } |
935 | ||
4dbd4ee6 | 936 | void wxCanvasControl::Move( int x, int y ) |
3b111dbe | 937 | { |
4dbd4ee6 | 938 | m_control->Move( x, y ); |
3b111dbe RR |
939 | } |
940 | ||
d1f9b206 RR |
941 | //---------------------------------------------------------------------------- |
942 | // wxCanvasText | |
943 | //---------------------------------------------------------------------------- | |
944 | ||
945 | class wxFaceData | |
946 | { | |
947 | public: | |
1e1af41e | 948 | #if wxUSE_FREETYPE |
d1f9b206 RR |
949 | FT_Face m_face; |
950 | #else | |
951 | void *m_dummy; | |
dc16900b | 952 | #endif |
d1f9b206 RR |
953 | }; |
954 | ||
4dbd4ee6 RR |
955 | wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size ) |
956 | : wxCanvasObject() | |
d1f9b206 RR |
957 | { |
958 | m_text = text; | |
cb281cfc RR |
959 | m_fontFileName = fontFile; |
960 | m_size = size; | |
dc16900b | 961 | |
cb281cfc | 962 | m_red = 0; |
d1f9b206 RR |
963 | m_green = 0; |
964 | m_blue = 0; | |
dc16900b | 965 | |
4dbd4ee6 | 966 | m_alpha = NULL; |
dc16900b | 967 | |
4dbd4ee6 RR |
968 | m_x = x; |
969 | m_y = y; | |
dc16900b KH |
970 | |
971 | #if wxUSE_FREETYPE | |
d1f9b206 RR |
972 | wxFaceData *data = new wxFaceData; |
973 | m_faceData = data; | |
dc16900b | 974 | |
d1f9b206 | 975 | int error = FT_New_Face( g_freetypeLibrary, |
cb281cfc | 976 | m_fontFileName, |
d1f9b206 RR |
977 | 0, |
978 | &(data->m_face) ); | |
5143c96b | 979 | |
d1f9b206 RR |
980 | error = FT_Set_Char_Size( data->m_face, |
981 | 0, | |
cb281cfc RR |
982 | m_size*64, |
983 | 96, // screen dpi | |
d1f9b206 RR |
984 | 96 ); |
985 | #endif | |
986 | } | |
987 | ||
988 | wxCanvasText::~wxCanvasText() | |
989 | { | |
fcbb6b37 | 990 | #if wxUSE_FREETYPE |
d1f9b206 RR |
991 | wxFaceData *data = (wxFaceData*) m_faceData; |
992 | delete data; | |
993 | #endif | |
994 | ||
995 | if (m_alpha) delete [] m_alpha; | |
996 | } | |
997 | ||
998 | void wxCanvasText::SetRGB( unsigned char red, unsigned char green, unsigned char blue ) | |
999 | { | |
1000 | m_red = red; | |
1001 | m_green = green; | |
1002 | m_blue = blue; | |
1003 | } | |
1004 | ||
1005 | void wxCanvasText::SetFlag( int flag ) | |
1006 | { | |
1007 | m_flag = flag; | |
1008 | } | |
1009 | ||
fcbb6b37 | 1010 | void wxCanvasText::Render(int xabs, int yabs, int clip_x, int clip_y, int clip_width, int clip_height ) |
d1f9b206 RR |
1011 | { |
1012 | if (!m_alpha) return; | |
fcbb6b37 | 1013 | |
41328253 RR |
1014 | int buffer_x = m_owner->GetBufferX(); |
1015 | int buffer_y = m_owner->GetBufferY(); | |
96f5fca9 RR |
1016 | |
1017 | #if IMAGE_CANVAS | |
1018 | wxImage *image = m_owner->GetBuffer(); | |
d1f9b206 | 1019 | |
21544859 RR |
1020 | // local coordinates |
1021 | int start_x = clip_x - m_area.x; | |
1022 | int end_x = clip_width + start_x; | |
1023 | int start_y = clip_y - m_area.y; | |
1024 | int end_y = clip_height + start_y; | |
fcbb6b37 | 1025 | |
d1f9b206 RR |
1026 | for (int y = start_y; y < end_y; y++) |
1027 | for (int x = start_x; x < end_x; x++) | |
1028 | { | |
1029 | int alpha = m_alpha[y*m_area.width + x]; | |
1030 | if (alpha) | |
1031 | { | |
41328253 RR |
1032 | int image_x = m_area.x+x - buffer_x; |
1033 | int image_y = m_area.y+y - buffer_y; | |
cb281cfc | 1034 | if (alpha == 255) |
d1f9b206 RR |
1035 | { |
1036 | image->SetRGB( image_x, image_y, m_red, m_green, m_blue ); | |
1037 | continue; | |
1038 | } | |
cb281cfc RR |
1039 | int red1 = (m_red * alpha) / 255; |
1040 | int green1 = (m_green * alpha) / 255; | |
1041 | int blue1 = (m_blue * alpha) / 255; | |
dc16900b | 1042 | |
cb281cfc | 1043 | alpha = 255-alpha; |
d1f9b206 RR |
1044 | int red2 = image->GetRed( image_x, image_y ); |
1045 | int green2 = image->GetGreen( image_x, image_y ); | |
1046 | int blue2 = image->GetBlue( image_x, image_y ); | |
cb281cfc RR |
1047 | red2 = (red2 * alpha) / 255; |
1048 | green2 = (green2 * alpha) / 255; | |
1049 | blue2 = (blue2 * alpha) / 255; | |
fcbb6b37 | 1050 | |
d1f9b206 RR |
1051 | image->SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 ); |
1052 | } | |
1053 | } | |
96f5fca9 RR |
1054 | #else |
1055 | wxBitmap *bitmap = m_owner->GetBuffer(); | |
1056 | wxRect sub_rect( clip_x-buffer_x, clip_y-buffer_y, clip_width, clip_height ); | |
1057 | wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) ); | |
1058 | ||
1059 | wxImage image( sub_bitmap ); | |
1060 | ||
1061 | // local coordinates | |
1062 | int start_x = clip_x - m_area.x; | |
1063 | int end_x = clip_width + start_x; | |
1064 | int start_y = clip_y - m_area.y; | |
1065 | int end_y = clip_height + start_y; | |
1066 | ||
1067 | for (int y = start_y; y < end_y; y++) | |
1068 | for (int x = start_x; x < end_x; x++) | |
1069 | { | |
1070 | int alpha = m_alpha[y*m_area.width + x]; | |
1071 | if (alpha) | |
1072 | { | |
1073 | int image_x = x - start_x; | |
1074 | int image_y = y - start_y; | |
1075 | if (alpha == 255) | |
1076 | { | |
1077 | image.SetRGB( image_x, image_y, m_red, m_green, m_blue ); | |
1078 | continue; | |
1079 | } | |
1080 | int red1 = (m_red * alpha) / 255; | |
1081 | int green1 = (m_green * alpha) / 255; | |
1082 | int blue1 = (m_blue * alpha) / 255; | |
1083 | ||
1084 | alpha = 255-alpha; | |
1085 | int red2 = image.GetRed( image_x, image_y ); | |
1086 | int green2 = image.GetGreen( image_x, image_y ); | |
1087 | int blue2 = image.GetBlue( image_x, image_y ); | |
1088 | red2 = (red2 * alpha) / 255; | |
1089 | green2 = (green2 * alpha) / 255; | |
1090 | blue2 = (blue2 * alpha) / 255; | |
1091 | ||
1092 | image.SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 ); | |
1093 | } | |
1094 | } | |
1095 | ||
1096 | sub_bitmap = image.ConvertToBitmap(); | |
1097 | ||
1098 | wxMemoryDC *dc = m_owner->GetDC(); | |
1099 | dc->DrawBitmap( sub_bitmap, clip_x-buffer_x, clip_y-buffer_y ); | |
33ebcd80 | 1100 | #endif |
d1f9b206 RR |
1101 | } |
1102 | ||
1103 | void wxCanvasText::WriteSVG( wxTextOutputStream &stream ) | |
1104 | { | |
1105 | } | |
1106 | ||
4dbd4ee6 | 1107 | void wxCanvasText::Recreate() |
d1f9b206 | 1108 | { |
4dbd4ee6 | 1109 | if (m_alpha) delete [] m_alpha; |
dc16900b | 1110 | |
4dbd4ee6 RR |
1111 | m_area.x = m_owner->GetDeviceX( m_x ); |
1112 | m_area.y = m_owner->GetDeviceY( m_y ); | |
dc16900b | 1113 | |
96f5fca9 RR |
1114 | m_area.width = 100; // TODO calculate length |
1115 | m_area.height = m_size + (m_size/2); // TODO space for sub-baseline (pgypq) | |
1116 | m_alpha = new unsigned char[m_area.width*m_area.height]; | |
4dbd4ee6 | 1117 | memset( m_alpha, 0, m_area.width*m_area.height ); |
fcbb6b37 KH |
1118 | |
1119 | #if wxUSE_FREETYPE | |
d1f9b206 RR |
1120 | FT_Face face = ((wxFaceData*)m_faceData)->m_face; |
1121 | FT_GlyphSlot slot = face->glyph; | |
1122 | int pen_x = 0; | |
cb281cfc | 1123 | int pen_y = m_size; |
fcbb6b37 | 1124 | |
cb281cfc | 1125 | for (int n = 0; n < (int)m_text.Len(); n++) |
d1f9b206 RR |
1126 | { |
1127 | FT_UInt index = FT_Get_Char_Index( face, m_text[n] ); | |
dc16900b | 1128 | |
d1f9b206 RR |
1129 | int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); |
1130 | if (error) continue; | |
fcbb6b37 | 1131 | |
cb281cfc | 1132 | error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); |
d1f9b206 | 1133 | if (error) continue; |
fcbb6b37 | 1134 | |
cb281cfc RR |
1135 | FT_Bitmap *bitmap = &slot->bitmap; |
1136 | unsigned char* buffer = bitmap->buffer; | |
1137 | for (int y = 0; y < bitmap->rows; y++) | |
1138 | for (int x = 0; x < bitmap->width; x++) | |
1139 | { | |
1140 | unsigned char alpha = buffer[ y*bitmap->pitch + x ]; | |
1141 | if (alpha == 0) continue; | |
dc16900b | 1142 | |
cb281cfc RR |
1143 | int xx = pen_x + slot->bitmap_left + x; |
1144 | int yy = pen_y - slot->bitmap_top + y; | |
1145 | m_alpha[ yy * m_area.width + xx ] = alpha; | |
1146 | } | |
fcbb6b37 | 1147 | |
d1f9b206 RR |
1148 | pen_x += slot->advance.x >> 6; |
1149 | pen_y += slot->advance.y >> 6; | |
fcbb6b37 | 1150 | } |
d1f9b206 RR |
1151 | #endif |
1152 | } | |
1153 | ||
6a2c1874 RR |
1154 | //---------------------------------------------------------------------------- |
1155 | // wxCanvas | |
1156 | //---------------------------------------------------------------------------- | |
1157 | ||
1158 | IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow) | |
1159 | ||
1160 | BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow) | |
1161 | EVT_CHAR( wxCanvas::OnChar ) | |
1162 | EVT_PAINT( wxCanvas::OnPaint ) | |
1163 | EVT_SIZE( wxCanvas::OnSize ) | |
1164 | EVT_IDLE( wxCanvas::OnIdle ) | |
1165 | EVT_MOUSE_EVENTS( wxCanvas::OnMouse ) | |
1166 | EVT_SET_FOCUS( wxCanvas::OnSetFocus ) | |
1167 | EVT_KILL_FOCUS( wxCanvas::OnKillFocus ) | |
61b64bd9 | 1168 | EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground ) |
6a2c1874 RR |
1169 | END_EVENT_TABLE() |
1170 | ||
1171 | wxCanvas::wxCanvas( wxWindow *parent, wxWindowID id, | |
1172 | const wxPoint &position, const wxSize& size, long style ) : | |
1173 | wxScrolledWindow( parent, id, position, size, style ) | |
1174 | { | |
41328253 RR |
1175 | m_bufferX = 0; |
1176 | m_bufferY = 0; | |
6a2c1874 | 1177 | m_needUpdate = FALSE; |
cb281cfc RR |
1178 | m_red = 0; |
1179 | m_green = 0; | |
1180 | m_blue = 0; | |
239c1f50 | 1181 | m_lastMouse = (wxCanvasObject*)NULL; |
4dbd4ee6 | 1182 | m_captureMouse = (wxCanvasObject*)NULL; |
41328253 | 1183 | m_frozen = TRUE; |
27d1065d RR |
1184 | m_oldDeviceX = 0; |
1185 | m_oldDeviceY = 0; | |
1186 | ||
fcbb6b37 KH |
1187 | //root group always at 0,0 |
1188 | m_root = new wxCanvasObjectGroup(); | |
1189 | m_root->DeleteContents( TRUE ); | |
1190 | m_root->SetOwner(this); | |
6a2c1874 RR |
1191 | } |
1192 | ||
1193 | wxCanvas::~wxCanvas() | |
1194 | { | |
1195 | wxNode *node = m_updateRects.First(); | |
1196 | while (node) | |
1197 | { | |
1198 | wxRect *rect = (wxRect*) node->Data(); | |
1199 | delete rect; | |
1200 | m_updateRects.DeleteNode( node ); | |
1201 | node = m_updateRects.First(); | |
1202 | } | |
1203 | } | |
1204 | ||
1205 | void wxCanvas::SetArea( int width, int height ) | |
1206 | { | |
6a2c1874 RR |
1207 | SetScrollbars( 10, 10, width/10, height/10 ); |
1208 | } | |
1209 | ||
cb281cfc RR |
1210 | void wxCanvas::SetColour( unsigned char red, unsigned char green, unsigned char blue ) |
1211 | { | |
1212 | m_red = red; | |
1213 | m_green = green; | |
1214 | m_blue = blue; | |
dc16900b | 1215 | |
61b64bd9 RR |
1216 | SetBackgroundColour( wxColour( red, green, blue ) ); |
1217 | ||
239c1f50 | 1218 | if (m_frozen) return; |
dc16900b | 1219 | |
33ebcd80 | 1220 | #if IMAGE_CANVAS |
cb281cfc | 1221 | unsigned char *data = m_buffer.GetData(); |
dc16900b | 1222 | |
cb281cfc RR |
1223 | for (int y = 0; y < m_buffer.GetHeight(); y++) |
1224 | for (int x = 0; x < m_buffer.GetWidth(); x++) | |
1225 | { | |
1226 | data[0] = red; | |
1227 | data++; | |
1228 | data[0] = green; | |
1229 | data++; | |
1230 | data[0] = blue; | |
1231 | data++; | |
1232 | } | |
33ebcd80 RR |
1233 | #else |
1234 | wxMemoryDC dc; | |
1235 | dc.SelectObject( m_buffer ); | |
1236 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
1237 | wxBrush brush( wxColour( red,green,blue), wxSOLID ); | |
1238 | dc.SetBrush( brush ); | |
1239 | dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() ); | |
1240 | dc.SelectObject( wxNullBitmap ); | |
1241 | #endif | |
cb281cfc RR |
1242 | } |
1243 | ||
dc16900b | 1244 | void wxCanvas::SetCaptureMouse( wxCanvasObject *obj ) |
4dbd4ee6 | 1245 | { |
dc16900b KH |
1246 | if (obj) |
1247 | { | |
1248 | wxWindow::CaptureMouse(); | |
1249 | m_captureMouse = obj; | |
1250 | } | |
1251 | else | |
1252 | { | |
1253 | wxWindow::ReleaseMouse(); | |
1254 | m_captureMouse = NULL; | |
1255 | } | |
4dbd4ee6 RR |
1256 | } |
1257 | ||
239c1f50 RR |
1258 | void wxCanvas::Freeze() |
1259 | { | |
1260 | m_frozen = TRUE; | |
1261 | } | |
1262 | ||
1263 | void wxCanvas::Thaw() | |
1264 | { | |
1265 | wxNode *node = m_updateRects.First(); | |
1266 | while (node) | |
1267 | { | |
1268 | wxRect *rect = (wxRect*) node->Data(); | |
1269 | delete rect; | |
1270 | m_updateRects.DeleteNode( node ); | |
1271 | node = m_updateRects.First(); | |
1272 | } | |
dc16900b | 1273 | |
239c1f50 | 1274 | m_frozen = FALSE; |
dc16900b | 1275 | |
41328253 RR |
1276 | if (m_buffer.Ok()) |
1277 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight() ); | |
239c1f50 RR |
1278 | } |
1279 | ||
41328253 | 1280 | void wxCanvas::Update( int x, int y, int width, int height, bool blit ) |
6a2c1874 | 1281 | { |
27d1065d RR |
1282 | CalcScrolledPosition( 0, 0, &m_oldDeviceX, &m_oldDeviceY ); |
1283 | ||
239c1f50 | 1284 | if (m_frozen) return; |
fcbb6b37 | 1285 | |
21544859 | 1286 | // clip to buffer |
41328253 | 1287 | if (x < m_bufferX) |
21544859 | 1288 | { |
41328253 RR |
1289 | width -= m_bufferX-x; |
1290 | x = m_bufferX; | |
21544859 | 1291 | } |
33ebcd80 | 1292 | if (width <= 0) return; |
dc16900b | 1293 | |
41328253 | 1294 | if (y < m_bufferY) |
21544859 | 1295 | { |
41328253 RR |
1296 | height -= m_bufferY-y; |
1297 | y = m_bufferY; | |
21544859 | 1298 | } |
33ebcd80 | 1299 | if (height <= 0) return; |
dc16900b | 1300 | |
41328253 | 1301 | if (x+width > m_bufferX+m_buffer.GetWidth()) |
21544859 | 1302 | { |
41328253 | 1303 | width = m_bufferX+m_buffer.GetWidth() - x; |
21544859 | 1304 | } |
33ebcd80 | 1305 | if (width <= 0) return; |
dc16900b | 1306 | |
41328253 | 1307 | if (y+height > m_bufferY+m_buffer.GetHeight()) |
21544859 | 1308 | { |
41328253 | 1309 | height = m_bufferY+m_buffer.GetHeight() - y; |
21544859 | 1310 | } |
33ebcd80 | 1311 | if (height <= 0) return; |
dc16900b | 1312 | |
21544859 | 1313 | // update is within the buffer |
6a2c1874 | 1314 | m_needUpdate = TRUE; |
dc16900b | 1315 | |
21544859 | 1316 | // has to be blitted to screen later |
41328253 RR |
1317 | if (blit) |
1318 | { | |
1319 | m_updateRects.Append( | |
1320 | (wxObject*) new wxRect( x,y,width,height ) ); | |
1321 | } | |
dc16900b | 1322 | |
33ebcd80 | 1323 | #if IMAGE_CANVAS |
21544859 | 1324 | // speed up with direct access, maybe add wxImage::Clear(x,y,w,h,r,g,b) |
41328253 RR |
1325 | int start_y = y - m_bufferY; |
1326 | int end_y = y+height - m_bufferY; | |
1327 | int start_x = x - m_bufferX; | |
1328 | int end_x = x+width - m_bufferX; | |
1329 | for (int yy = start_y; yy < end_y; yy++) | |
1330 | for (int xx = start_x; xx < end_x; xx++) | |
cb281cfc | 1331 | m_buffer.SetRGB( xx, yy, m_red, m_green, m_blue ); |
5143c96b | 1332 | |
fcbb6b37 | 1333 | m_root->Render(0,0, x, y, width, height ); |
33ebcd80 RR |
1334 | #else |
1335 | wxMemoryDC dc; | |
1336 | dc.SelectObject( m_buffer ); | |
1337 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
1338 | wxBrush brush( wxColour( m_red,m_green,m_blue), wxSOLID ); | |
1339 | dc.SetBrush( brush ); | |
1340 | dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height ); | |
1341 | ||
1342 | m_renderDC = &dc; | |
1343 | m_root->Render(0,0, x, y, width, height ); | |
5143c96b | 1344 | |
33ebcd80 RR |
1345 | dc.SelectObject( wxNullBitmap ); |
1346 | #endif | |
6a2c1874 RR |
1347 | } |
1348 | ||
3b111dbe | 1349 | void wxCanvas::BlitBuffer( wxDC &dc ) |
6a2c1874 | 1350 | { |
6a2c1874 RR |
1351 | wxNode *node = m_updateRects.First(); |
1352 | while (node) | |
1353 | { | |
1354 | wxRect *rect = (wxRect*) node->Data(); | |
6a2c1874 | 1355 | |
41328253 RR |
1356 | wxRect sub_rect( *rect ); |
1357 | sub_rect.x -= m_bufferX; | |
1358 | sub_rect.y -= m_bufferY; | |
fcbb6b37 | 1359 | |
33ebcd80 | 1360 | #if IMAGE_CANVAS |
6a2c1874 | 1361 | |
33ebcd80 | 1362 | wxImage sub_image( m_buffer.GetSubImage( sub_rect ) ); |
6a2c1874 | 1363 | #ifdef __WXGTK__ |
dc16900b | 1364 | int bpp = wxDisplayDepth(); |
6a2c1874 RR |
1365 | if (bpp > 8) |
1366 | { | |
1367 | // the init code is doubled in wxImage | |
1368 | static bool s_hasInitialized = FALSE; | |
1369 | ||
1370 | if (!s_hasInitialized) | |
1371 | { | |
1372 | gdk_rgb_init(); | |
1373 | s_hasInitialized = TRUE; | |
1374 | } | |
dc16900b | 1375 | |
6a2c1874 RR |
1376 | gdk_draw_rgb_image( GTK_PIZZA(m_wxwindow)->bin_window, |
1377 | m_wxwindow->style->black_gc, | |
41328253 | 1378 | sub_rect.x, sub_rect.y, |
6a2c1874 RR |
1379 | sub_image.GetWidth(), sub_image.GetHeight(), |
1380 | GDK_RGB_DITHER_NONE, | |
1381 | sub_image.GetData(), | |
1382 | sub_image.GetWidth()*3 ); | |
1383 | } | |
1384 | else | |
1385 | { | |
1386 | wxBitmap bitmap( sub_image.ConvertToBitmap() ); | |
1387 | dc.DrawBitmap( bitmap, rect->x, rect->y ); | |
1388 | } | |
33ebcd80 | 1389 | #else |
6a2c1874 RR |
1390 | wxBitmap bitmap( sub_image.ConvertToBitmap() ); |
1391 | dc.DrawBitmap( bitmap, rect->x, rect->y ); | |
1392 | #endif | |
dc16900b | 1393 | |
33ebcd80 RR |
1394 | #else // IMAGE_CANVAS |
1395 | ||
1396 | // Maybe clipping use SetClipping() is faster than | |
1397 | // getting the subrect first and drawing it then? | |
1398 | wxBitmap sub_bitmap( m_buffer.GetSubBitmap( sub_rect ) ); | |
1399 | dc.DrawBitmap( sub_bitmap, rect->x, rect->y ); | |
5143c96b | 1400 | |
33ebcd80 | 1401 | #endif |
6a2c1874 RR |
1402 | delete rect; |
1403 | m_updateRects.DeleteNode( node ); | |
1404 | node = m_updateRects.First(); | |
1405 | } | |
dc16900b | 1406 | |
3b111dbe RR |
1407 | m_needUpdate = FALSE; |
1408 | } | |
1409 | ||
1410 | void wxCanvas::UpdateNow() | |
1411 | { | |
61b64bd9 RR |
1412 | if (m_frozen) return; |
1413 | ||
3b111dbe | 1414 | if (!m_needUpdate) return; |
dc16900b | 1415 | |
3b111dbe RR |
1416 | wxClientDC dc( this ); |
1417 | PrepareDC( dc ); | |
dc16900b | 1418 | |
3b111dbe | 1419 | BlitBuffer( dc ); |
6a2c1874 RR |
1420 | } |
1421 | ||
4dbd4ee6 RR |
1422 | int wxCanvas::GetDeviceX( double x ) |
1423 | { | |
1424 | return (int) x; | |
1425 | } | |
1426 | ||
1427 | int wxCanvas::GetDeviceY( double y ) | |
1428 | { | |
1429 | return (int) y; | |
1430 | } | |
1431 | ||
1432 | int wxCanvas::GetDeviceWidth( double width ) | |
1433 | { | |
1434 | return (int) width; | |
1435 | } | |
1436 | ||
1437 | int wxCanvas::GetDeviceHeight( double height ) | |
1438 | { | |
1439 | return (int) height; | |
1440 | } | |
1441 | ||
1442 | void wxCanvas::Recreate() | |
1443 | { | |
fcbb6b37 | 1444 | m_root->Recreate(); |
4dbd4ee6 RR |
1445 | } |
1446 | ||
6a2c1874 RR |
1447 | void wxCanvas::Prepend( wxCanvasObject* obj ) |
1448 | { | |
fcbb6b37 KH |
1449 | m_root->Prepend( obj ); |
1450 | obj->SetOwner(this); | |
dc16900b | 1451 | |
fcbb6b37 | 1452 | m_root->Recreate(); |
dc16900b | 1453 | |
6a2c1874 RR |
1454 | if (!obj->IsControl()) |
1455 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
1456 | } | |
1457 | ||
1458 | void wxCanvas::Append( wxCanvasObject* obj ) | |
1459 | { | |
fcbb6b37 KH |
1460 | m_root->Append( obj ); |
1461 | obj->SetOwner(this); | |
dc16900b | 1462 | |
fcbb6b37 | 1463 | m_root->Recreate(); |
dc16900b | 1464 | |
6a2c1874 RR |
1465 | if (!obj->IsControl()) |
1466 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
1467 | } | |
1468 | ||
1469 | void wxCanvas::Insert( size_t before, wxCanvasObject* obj ) | |
1470 | { | |
fcbb6b37 KH |
1471 | m_root->Insert( before, obj ); |
1472 | obj->SetOwner(this); | |
dc16900b | 1473 | |
fcbb6b37 | 1474 | m_root->Recreate(); |
dc16900b | 1475 | |
6a2c1874 RR |
1476 | if (!obj->IsControl()) |
1477 | Update( obj->GetX(), obj->GetY(), obj->GetWidth(), obj->GetHeight() ); | |
1478 | } | |
1479 | ||
1480 | void wxCanvas::Remove( wxCanvasObject* obj ) | |
1481 | { | |
1482 | int x = obj->GetX(); | |
1483 | int y = obj->GetY(); | |
1484 | int w = obj->GetWidth(); | |
1485 | int h = obj->GetHeight(); | |
1486 | bool ic = obj->IsControl(); | |
dc16900b | 1487 | |
fcbb6b37 | 1488 | m_root->Remove( obj ); |
dc16900b | 1489 | |
6a2c1874 RR |
1490 | if (!ic) |
1491 | Update( x, y, w, h ); | |
1492 | } | |
1493 | ||
1494 | void wxCanvas::OnPaint(wxPaintEvent &event) | |
1495 | { | |
6a2c1874 | 1496 | wxPaintDC dc(this); |
3b111dbe | 1497 | PrepareDC( dc ); |
dc16900b | 1498 | |
41328253 | 1499 | if (!m_buffer.Ok()) return; |
fcbb6b37 | 1500 | |
b85cfb6f | 1501 | if (m_frozen) return; |
41328253 | 1502 | |
6a2c1874 RR |
1503 | m_needUpdate = TRUE; |
1504 | ||
1505 | wxRegionIterator it( GetUpdateRegion() ); | |
1506 | while (it) | |
1507 | { | |
1508 | int x = it.GetX(); | |
1509 | int y = it.GetY(); | |
dc16900b | 1510 | |
6a2c1874 RR |
1511 | int w = it.GetWidth(); |
1512 | int h = it.GetHeight(); | |
dc16900b | 1513 | |
21544859 RR |
1514 | if (x+w > m_buffer.GetWidth()) |
1515 | w = m_buffer.GetWidth() - x; | |
1516 | if (y+h > m_buffer.GetHeight()) | |
1517 | h = m_buffer.GetHeight() - y; | |
dc16900b | 1518 | |
21544859 | 1519 | if ((w > 0) && (h > 0)) |
41328253 RR |
1520 | { |
1521 | CalcUnscrolledPosition( x, y, &x, &y ); | |
21544859 | 1522 | m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) ); |
41328253 | 1523 | } |
dc16900b | 1524 | |
6a2c1874 RR |
1525 | it++; |
1526 | } | |
dc16900b | 1527 | |
3b111dbe | 1528 | BlitBuffer( dc ); |
6a2c1874 RR |
1529 | } |
1530 | ||
41328253 RR |
1531 | void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect ) |
1532 | { | |
61b64bd9 | 1533 | // If any updates are pending, do them now since they will |
27d1065d RR |
1534 | // expect the previous m_bufferX and m_bufferY as well as |
1535 | // the previous device origin values. | |
1536 | wxClientDC dc( this ); | |
1537 | dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY ); | |
1538 | BlitBuffer( dc ); | |
41328253 | 1539 | |
61b64bd9 RR |
1540 | // The buffer always starts at the top left corner of the |
1541 | // client area. Indeed, it is the client area. | |
41328253 RR |
1542 | CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); |
1543 | ||
33ebcd80 | 1544 | #if IMAGE_CANVAS |
41328253 | 1545 | unsigned char* data = m_buffer.GetData(); |
fcbb6b37 | 1546 | |
41328253 RR |
1547 | if (dy != 0) |
1548 | { | |
1549 | if (dy > 0) | |
1550 | { | |
1551 | unsigned char *source = data; | |
1552 | unsigned char *dest = data + (dy * m_buffer.GetWidth() * 3); | |
1553 | size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()-dy)); | |
1554 | memmove( dest, source, count ); | |
fcbb6b37 | 1555 | |
61b64bd9 RR |
1556 | // We update the new buffer area, but there is no need to |
1557 | // blit (last param FALSE) since the ensuing paint event will | |
1558 | // do that anyway. | |
41328253 RR |
1559 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), dy, FALSE ); |
1560 | } | |
1561 | else | |
1562 | { | |
1563 | unsigned char *dest = data; | |
1564 | unsigned char *source = data + (-dy * m_buffer.GetWidth() * 3); | |
1565 | size_t count = (size_t) (m_buffer.GetWidth() * 3 * (m_buffer.GetHeight()+dy)); | |
1566 | memmove( dest, source, count ); | |
fcbb6b37 | 1567 | |
61b64bd9 RR |
1568 | // We update the new buffer area, but there is no need to |
1569 | // blit (last param FALSE) since the ensuing paint event will | |
1570 | // do that anyway. | |
41328253 RR |
1571 | Update( m_bufferX, m_bufferY+m_buffer.GetHeight()+dy, m_buffer.GetWidth(), -dy, FALSE ); |
1572 | } | |
1573 | } | |
fcbb6b37 | 1574 | |
41328253 RR |
1575 | if (dx != 0) |
1576 | { | |
61b64bd9 RR |
1577 | if (dx > 0) |
1578 | { | |
1579 | unsigned char *source = data; | |
1580 | for (int y = 0; y < m_buffer.GetHeight(); y++) | |
1581 | { | |
1582 | unsigned char *dest = source + dx*3; | |
1583 | memmove( dest, source, (m_buffer.GetWidth()-dx) * 3 ); | |
1584 | source += m_buffer.GetWidth()*3; | |
1585 | } | |
fcbb6b37 | 1586 | |
61b64bd9 RR |
1587 | // We update the new buffer area, but there is no need to |
1588 | // blit (last param FALSE) since the ensuing paint event will | |
1589 | // do that anyway. | |
1590 | Update( m_bufferX, m_bufferY, dx, m_buffer.GetHeight(), FALSE ); | |
1591 | } | |
1592 | else | |
1593 | { | |
1594 | unsigned char *dest = data; | |
1595 | for (int y = 0; y < m_buffer.GetHeight(); y++) | |
1596 | { | |
1597 | unsigned char *source = dest - dx*3; | |
1598 | memmove( dest, source, (m_buffer.GetWidth()+dx) * 3 ); | |
1599 | dest += m_buffer.GetWidth()*3; | |
1600 | } | |
fcbb6b37 | 1601 | |
61b64bd9 RR |
1602 | // We update the new buffer area, but there is no need to |
1603 | // blit (last param FALSE) since the ensuing paint event will | |
1604 | // do that anyway. | |
1605 | Update( m_bufferX+m_buffer.GetWidth()+dx, m_bufferY, -dx, m_buffer.GetHeight(), FALSE ); | |
1606 | } | |
41328253 | 1607 | } |
33ebcd80 RR |
1608 | #else |
1609 | // Update everything, TODO: scrolling | |
1610 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); | |
1611 | #endif | |
41328253 RR |
1612 | |
1613 | wxWindow::ScrollWindow( dx, dy, rect ); | |
1614 | } | |
1615 | ||
6a2c1874 RR |
1616 | void wxCanvas::OnMouse(wxMouseEvent &event) |
1617 | { | |
239c1f50 RR |
1618 | int x = event.GetX(); |
1619 | int y = event.GetY(); | |
1620 | CalcUnscrolledPosition( x, y, &x, &y ); | |
dc16900b | 1621 | |
239c1f50 RR |
1622 | if (event.GetEventType() == wxEVT_MOTION) |
1623 | { | |
dc16900b | 1624 | if (m_captureMouse) //no matter what go to this one |
239c1f50 | 1625 | { |
dc16900b KH |
1626 | wxMouseEvent child_event( wxEVT_MOTION ); |
1627 | child_event.SetEventObject(m_captureMouse); | |
1628 | child_event.m_x = x - m_captureMouse->GetX(); | |
1629 | child_event.m_y = y - m_captureMouse->GetY(); | |
1630 | child_event.m_leftDown = event.m_leftDown; | |
1631 | child_event.m_rightDown = event.m_rightDown; | |
1632 | child_event.m_middleDown = event.m_middleDown; | |
1633 | child_event.m_controlDown = event.m_controlDown; | |
1634 | child_event.m_shiftDown = event.m_shiftDown; | |
1635 | child_event.m_altDown = event.m_altDown; | |
1636 | child_event.m_metaDown = event.m_metaDown; | |
872f1044 | 1637 | |
dc16900b | 1638 | m_captureMouse->ProcessEvent( child_event ); |
872f1044 | 1639 | return; |
dc16900b KH |
1640 | } |
1641 | else | |
1642 | { | |
fcbb6b37 | 1643 | wxCanvasObject *obj = m_root->IsHitObject(x,y,0); |
dc16900b | 1644 | |
fcbb6b37 KH |
1645 | if (obj && !obj->IsControl()) |
1646 | { | |
1647 | wxMouseEvent child_event( wxEVT_MOTION ); | |
1648 | child_event.SetEventObject( obj ); | |
1649 | child_event.m_x = x - obj->GetX(); | |
1650 | child_event.m_y = y - obj->GetY(); | |
1651 | child_event.m_leftDown = event.m_leftDown; | |
1652 | child_event.m_rightDown = event.m_rightDown; | |
1653 | child_event.m_middleDown = event.m_middleDown; | |
1654 | child_event.m_controlDown = event.m_controlDown; | |
1655 | child_event.m_shiftDown = event.m_shiftDown; | |
1656 | child_event.m_altDown = event.m_altDown; | |
1657 | child_event.m_metaDown = event.m_metaDown; | |
1658 | ||
1659 | if ((obj != m_lastMouse) && (m_lastMouse != NULL)) | |
239c1f50 | 1660 | { |
fcbb6b37 KH |
1661 | child_event.SetEventType( wxEVT_LEAVE_WINDOW ); |
1662 | child_event.SetEventObject( m_lastMouse ); | |
1663 | child_event.m_x = x - m_lastMouse->GetX(); | |
1664 | child_event.m_y = y - m_lastMouse->GetY(); | |
1665 | m_lastMouse->ProcessEvent( child_event ); | |
1666 | ||
1667 | m_lastMouse = obj; | |
1668 | child_event.SetEventType( wxEVT_ENTER_WINDOW ); | |
1669 | child_event.SetEventObject( m_lastMouse ); | |
1670 | child_event.m_x = x - m_lastMouse->GetX(); | |
1671 | child_event.m_y = y - m_lastMouse->GetY(); | |
1672 | m_lastMouse->ProcessEvent( child_event ); | |
1673 | ||
1674 | child_event.SetEventType( wxEVT_MOTION ); | |
1675 | child_event.SetEventObject( obj ); | |
239c1f50 | 1676 | } |
872f1044 | 1677 | |
fcbb6b37 KH |
1678 | obj->ProcessEvent( child_event ); |
1679 | return; | |
239c1f50 | 1680 | } |
239c1f50 RR |
1681 | } |
1682 | if (m_lastMouse) | |
1683 | { | |
1684 | wxMouseEvent child_event( wxEVT_LEAVE_WINDOW ); | |
1685 | child_event.SetEventObject( m_lastMouse ); | |
1e1af41e RR |
1686 | child_event.m_x = x - m_lastMouse->GetX(); |
1687 | child_event.m_y = y - m_lastMouse->GetY(); | |
239c1f50 RR |
1688 | child_event.m_leftDown = event.m_leftDown; |
1689 | child_event.m_rightDown = event.m_rightDown; | |
1690 | child_event.m_middleDown = event.m_middleDown; | |
1691 | child_event.m_controlDown = event.m_controlDown; | |
1692 | child_event.m_shiftDown = event.m_shiftDown; | |
1693 | child_event.m_altDown = event.m_altDown; | |
1694 | child_event.m_metaDown = event.m_metaDown; | |
1695 | m_lastMouse->ProcessEvent( child_event ); | |
dc16900b | 1696 | |
239c1f50 RR |
1697 | m_lastMouse = (wxCanvasObject*) NULL; |
1698 | return; | |
1699 | } | |
1700 | } | |
872f1044 RR |
1701 | else |
1702 | { | |
1703 | if (m_captureMouse) //no matter what go to this one | |
1704 | { | |
1705 | wxMouseEvent child_event( event.GetEventType() ); | |
1706 | child_event.SetEventObject(m_captureMouse); | |
1707 | child_event.m_x = x - m_captureMouse->GetX(); | |
1708 | child_event.m_y = y - m_captureMouse->GetY(); | |
1709 | child_event.m_leftDown = event.m_leftDown; | |
1710 | child_event.m_rightDown = event.m_rightDown; | |
1711 | child_event.m_middleDown = event.m_middleDown; | |
1712 | child_event.m_controlDown = event.m_controlDown; | |
1713 | child_event.m_shiftDown = event.m_shiftDown; | |
1714 | child_event.m_altDown = event.m_altDown; | |
1715 | child_event.m_metaDown = event.m_metaDown; | |
1716 | m_captureMouse->ProcessEvent( child_event ); | |
1717 | } | |
1718 | else | |
1719 | { | |
1720 | wxCanvasObject *obj = m_root->IsHitObject(x,y,0); | |
1721 | ||
1722 | if (obj && !obj->IsControl()) | |
1723 | { | |
1724 | wxMouseEvent child_event( event.GetEventType() ); | |
1725 | child_event.SetEventObject( obj ); | |
1726 | child_event.m_x = x - obj->GetX(); | |
1727 | child_event.m_y = y - obj->GetY(); | |
1728 | child_event.m_leftDown = event.m_leftDown; | |
1729 | child_event.m_rightDown = event.m_rightDown; | |
1730 | child_event.m_middleDown = event.m_middleDown; | |
1731 | child_event.m_controlDown = event.m_controlDown; | |
1732 | child_event.m_shiftDown = event.m_shiftDown; | |
1733 | child_event.m_altDown = event.m_altDown; | |
1734 | child_event.m_metaDown = event.m_metaDown; | |
1735 | ||
1736 | obj->ProcessEvent( child_event ); | |
1737 | return; | |
1738 | } | |
1739 | } | |
1740 | } | |
fcbb6b37 | 1741 | |
239c1f50 | 1742 | event.Skip(); |
6a2c1874 RR |
1743 | } |
1744 | ||
1745 | void wxCanvas::OnSize(wxSizeEvent &event) | |
1746 | { | |
b85cfb6f RR |
1747 | int w,h; |
1748 | GetClientSize( &w, &h ); | |
33ebcd80 | 1749 | #if IMAGE_CANVAS |
b85cfb6f | 1750 | m_buffer = wxImage( w, h ); |
33ebcd80 RR |
1751 | #else |
1752 | m_buffer = wxBitmap( w, h ); | |
1753 | #endif | |
fcbb6b37 | 1754 | |
b85cfb6f | 1755 | CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY ); |
fcbb6b37 | 1756 | |
b85cfb6f RR |
1757 | wxNode *node = m_updateRects.First(); |
1758 | while (node) | |
1759 | { | |
1760 | wxRect *rect = (wxRect*) node->Data(); | |
1761 | delete rect; | |
1762 | m_updateRects.DeleteNode( node ); | |
1763 | node = m_updateRects.First(); | |
1764 | } | |
1765 | ||
1766 | m_frozen = FALSE; | |
1767 | ||
1768 | Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE ); | |
41328253 | 1769 | |
6a2c1874 RR |
1770 | event.Skip(); |
1771 | } | |
1772 | ||
1773 | void wxCanvas::OnIdle(wxIdleEvent &event) | |
1774 | { | |
1775 | UpdateNow(); | |
1776 | event.Skip(); | |
1777 | } | |
1778 | ||
1779 | void wxCanvas::OnSetFocus(wxFocusEvent &event) | |
1780 | { | |
1781 | } | |
1782 | ||
1783 | void wxCanvas::OnKillFocus(wxFocusEvent &event) | |
1784 | { | |
1785 | } | |
1786 | ||
1787 | void wxCanvas::OnChar(wxKeyEvent &event) | |
1788 | { | |
1789 | event.Skip(); | |
1790 | } | |
1791 | ||
61b64bd9 RR |
1792 | void wxCanvas::OnEraseBackground(wxEraseEvent &event) |
1793 | { | |
1794 | } | |
1795 | ||
d1f9b206 RR |
1796 | //-------------------------------------------------------------------- |
1797 | // wxCanvasModule | |
1798 | //-------------------------------------------------------------------- | |
1799 | ||
1800 | class wxCanvasModule : public wxModule | |
1801 | { | |
1802 | public: | |
1803 | virtual bool OnInit(); | |
1804 | virtual void OnExit(); | |
1805 | ||
1806 | private: | |
1807 | DECLARE_DYNAMIC_CLASS(wxCanvasModule) | |
1808 | }; | |
1809 | ||
1810 | IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule) | |
6a2c1874 | 1811 | |
d1f9b206 RR |
1812 | bool wxCanvasModule::OnInit() |
1813 | { | |
1e1af41e | 1814 | #if wxUSE_FREETYPE |
d1f9b206 RR |
1815 | int error = FT_Init_FreeType( &g_freetypeLibrary ); |
1816 | if (error) return FALSE; | |
1817 | #endif | |
1818 | ||
1819 | return TRUE; | |
1820 | } | |
1821 | ||
1822 | void wxCanvasModule::OnExit() | |
1823 | { | |
1e1af41e | 1824 | #if wxUSE_FREETYPE |
cb281cfc | 1825 | FT_Done_FreeType( g_freetypeLibrary ); |
d1f9b206 RR |
1826 | #endif |
1827 | } |