r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / canvas.C
blobf001ac32a317d3d986a601231af25598ce045697
1 #include "canvas.h"
2 #include "clip.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "vframe.h"
7 #include <libintl.h>
8 #define _(String) gettext(String)
9 #define gettext_noop(String) String
10 #define N_(String) gettext_noop (String)
13 Canvas::Canvas(BC_WindowBase *subwindow, 
14         int x, 
15         int y, 
16         int w, 
17         int h,
18         int output_w,
19         int output_h,
20         int use_scrollbars,
21         int use_cwindow,
22         int use_rwindow,
23         int use_vwindow)
25         reset();
26         this->subwindow = subwindow;
27         this->x = x;
28         this->y = y;
29         this->w = w;
30         this->h = h;
31         this->output_w = output_w;
32         this->output_h = output_h;
33         this->use_scrollbars = use_scrollbars;
34         this->use_cwindow = use_cwindow;
35         this->use_rwindow = use_rwindow;
36         this->use_vwindow = use_vwindow;
39 Canvas::~Canvas()
41         if(refresh_frame) delete refresh_frame;
42         delete canvas_menu;
43         if(yscroll) delete yscroll;
44         if(xscroll) delete xscroll;
47 void Canvas::reset()
49         use_scrollbars = 0;
50         output_w = 0;
51         output_h = 0;
52     xscroll = 0;
53     yscroll = 0;
54         refresh_frame = 0;
57 // Get dimensions given a zoom
58 void Canvas::calculate_sizes(float aspect_ratio, 
59         int output_w, 
60         int output_h, 
61         float zoom, 
62         int &w, 
63         int &h)
65 // Horizontal stretch
66         if((float)output_w / output_h <= aspect_ratio)
67         {
68                 w = (int)((float)output_h * aspect_ratio * zoom + 1);
69                 h = (int)((float)output_h * zoom + 1);
70         }
71         else
72 // Vertical stretch
73         {
74                 h = (int)((float)output_w / aspect_ratio * zoom + 1);
75                 w = (int)((float)output_w * zoom + 1);
76         }
79 float Canvas::get_x_offset(EDL *edl, 
80         int single_channel, 
81         float zoom_x, 
82         float conformed_w,
83         float conformed_h)
85         if(use_scrollbars)
86         {
87                 if(xscroll) 
88                 {
89                         if(conformed_w < w_visible)
90                                 return -(float)(w_visible - conformed_w) / 2;
92                         return (float)get_xscroll();
93                 }
94                 else
95                         return ((float)-canvas->get_w() / zoom_x + 
96                                 edl->calculate_output_w(single_channel)) / 2;
97         }
98         else
99         {
100                 int out_w, out_h;
101                 int canvas_w = canvas->get_w();
102                 int canvas_h = canvas->get_h();
103                 out_w = canvas_w;
104                 out_h = canvas_h;
105                 
106                 if((float)out_w / out_h > conformed_w / conformed_h)
107                 {
108                         out_w = (int)(out_h * conformed_w / conformed_h + 0.5);
109                 }
110                 
111                 if(out_w < canvas_w)
112                         return -(canvas_w - out_w) / 2 / zoom_x;
113         }
115         return 0;
118 float Canvas::get_y_offset(EDL *edl, 
119         int single_channel, 
120         float zoom_y, 
121         float conformed_w,
122         float conformed_h)
124         if(use_scrollbars)
125         {
126                 if(yscroll)
127                 {
128                         if(conformed_h < h_visible)
129                                 return -(float)(h_visible - conformed_h) / 2;
131                         return (float)get_yscroll();
132                 }
133                 else
134                         return ((float)-canvas->get_h() / zoom_y + 
135                                 edl->calculate_output_h(single_channel)) / 2;
136         }
137         else
138         {
139                 int out_w, out_h;
140                 int canvas_w = canvas->get_w();
141                 int canvas_h = canvas->get_h();
142                 out_w = canvas_w;
143                 out_h = canvas_h;
145                 if((float)out_w / out_h <= conformed_w / conformed_h)
146                 {
147                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
148                 }
150 //printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2);
151                 if(out_h < canvas_h)
152                         return -((float)canvas_h - out_h) / 2 / zoom_y;
153         }
155         return 0;
158 // This may not be used anymore
159 void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom)
161         if(x + w_visible > w_needed) x = w_needed - w_visible;
162         if(y + h_visible > h_needed) y = h_needed - h_visible;
164         if(x < 0) x = 0;
165         if(y < 0) y = 0;
168 void Canvas::update_scrollbars()
170         if(use_scrollbars)
171         {
172                 if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible);
173                 if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible);
174         }
177 void Canvas::get_zooms(EDL *edl, 
178         int single_channel, 
179         float &zoom_x, 
180         float &zoom_y,
181         float &conformed_w,
182         float &conformed_h)
184         edl->calculate_conformed_dimensions(single_channel, 
185                 conformed_w, 
186                 conformed_h);
188         if(use_scrollbars)
189         {
190                 zoom_x = get_zoom() * 
191                         conformed_w / 
192                         edl->calculate_output_w(single_channel);
193                 zoom_y = get_zoom() * 
194                         conformed_h / 
195                         edl->calculate_output_h(single_channel);
196         }
197         else
198         {
199                 int out_w, out_h;
200                 int canvas_w = canvas->get_w();
201                 int canvas_h = canvas->get_h();
202         
203                 out_w = canvas_w;
204                 out_h = canvas_h;
206                 if((float)out_w / out_h > conformed_w / conformed_h)
207                 {
208                         out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5);
209                 }
210                 else
211                 {
212                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
213                 }
215                 zoom_x = (float)out_w / edl->calculate_output_w(single_channel);
216                 zoom_y = (float)out_h / edl->calculate_output_h(single_channel);
217 //printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h);
218         }
221 // Convert a coordinate on the canvas to a coordinate on the output
222 void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y)
224         float zoom_x, zoom_y, conformed_w, conformed_h;
225         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
227 //printf("Canvas::canvas_to_output y=%f zoom_y=%f y_offset=%f\n", 
228 //      y, zoom_y, get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
230         x = (float)x / zoom_x + get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h);
231         y = (float)y / zoom_y + get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h);
234 void Canvas::output_to_canvas(EDL *edl, int single_channel, float &x, float &y)
236         float zoom_x, zoom_y, conformed_w, conformed_h;
237         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
239 //printf("Canvas::output_to_canvas x=%f zoom_x=%f x_offset=%f\n", x, zoom_x, get_x_offset(edl, single_channel, zoom_x, conformed_w));
241         x = (float)zoom_x * (x - get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h));
242         y = (float)zoom_y * (y - get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
247 void Canvas::get_transfers(EDL *edl, 
248         int &in_x, 
249         int &in_y, 
250         int &in_w, 
251         int &in_h,
252         int &out_x, 
253         int &out_y, 
254         int &out_w, 
255         int &out_h,
256         int canvas_w,
257         int canvas_h)
259 // printf("Canvas::get_transfers %d %d\n", canvas_w, 
260 //              canvas_h);
261         if(canvas_w < 0) canvas_w = canvas->get_w();
262         if(canvas_h < 0) canvas_h = canvas->get_h();
264         if(use_scrollbars)
265         {
266                 float in_x1, in_y1, in_x2, in_y2;
267                 float out_x1, out_y1, out_x2, out_y2;
268                 float zoom_x, zoom_y, conformed_w, conformed_h;
270                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
271                 out_x1 = 0;
272                 out_y1 = 0;
273                 out_x2 = canvas_w;
274                 out_y2 = canvas_h;
275                 in_x1 = 0;
276                 in_y1 = 0;
277                 in_x2 = canvas_w;
278                 in_y2 = canvas_h;
280                 canvas_to_output(edl, 0, in_x1, in_y1);
281                 canvas_to_output(edl, 0, in_x2, in_y2);
283 // printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
284 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
286                 if(in_x1 < 0)
287                 {
288                         out_x1 += -in_x1 * zoom_x;
289                         in_x1 = 0;
290                 }
292                 if(in_y1 < 0)
293                 {
294                         out_y1 += -in_y1 * zoom_y;
295                         in_y1 = 0;
296                 }
298                 int output_w = get_output_w(edl);
299                 int output_h = get_output_h(edl);
301                 if(in_x2 > output_w)
302                 {
303                         out_x2 -= (in_x2 - output_w) * zoom_x;
304                         in_x2 = output_w;
305                 }
307                 if(in_y2 > output_h)
308                 {
309                         out_y2 -= (in_y2 - output_h) * zoom_y;
310                         in_y2 = output_h;
311                 }
312 // printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
313 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
315                 in_x = (int)in_x1;
316                 in_y = (int)in_y1;
317                 in_w = (int)(in_x2 - in_x1);
318                 in_h = (int)(in_y2 - in_y1);
319                 out_x = (int)out_x1;
320                 out_y = (int)out_y1;
321                 out_w = (int)(out_x2 - out_x1);
322                 out_h = (int)(out_y2 - out_y1);
324 // Center on canvas
325 //              if(!scrollbars_exist())
326 //              {
327 //                      out_x = canvas_w / 2 - out_w / 2;
328 //                      out_y = canvas_h / 2 - out_h / 2;
329 //              }
331 // printf("Canvas::get_transfers 2 %d %d %d %d -> %d %d %d %d\n",in_x, 
332 //                      in_y, 
333 //                      in_w, 
334 //                      in_h,
335 //                      out_x, 
336 //                      out_y, 
337 //                      out_w, 
338 //                      out_h);
339         }
340         else
341         {
342                 out_x = 0;
343                 out_y = 0;
344                 out_w = canvas_w;
345                 out_h = canvas_h;
347                 if(edl)
348                 {
349                         if((float)out_w / out_h > edl->get_aspect_ratio())
350                         {
351                                 out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5);
352                                 out_x = canvas_w / 2 - out_w / 2;
353                         }
354                         else
355                         {
356                                 out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
357                                 out_y = canvas_h / 2 - out_h / 2;
358                         }
359                         in_x = 0;
360                         in_y = 0;
361                         in_w = get_output_w(edl);
362                         in_h = get_output_h(edl);
363                 }
364                 else
365                 {
366                         in_x = 0;
367                         in_y = 0;
368                         in_w = this->output_w;
369                         in_h = this->output_h;
370                 }
371         }
373         in_x = MAX(0, in_x);
374         in_y = MAX(0, in_y);
375         in_w = MAX(0, in_w);
376         in_h = MAX(0, in_h);
377         out_x = MAX(0, out_x);
378         out_y = MAX(0, out_y);
379         out_w = MAX(0, out_w);
380         out_h = MAX(0, out_h);
383 int Canvas::scrollbars_exist()
385         return(use_scrollbars && (xscroll || yscroll));
388 int Canvas::get_output_w(EDL *edl)
390         if(use_scrollbars)
391                 return edl->calculate_output_w(0);
392         else
393                 return edl->session->output_w;
396 int Canvas::get_output_h(EDL *edl)
398         if(edl)
399         {
400                 if(use_scrollbars)
401                         return edl->calculate_output_h(0);
402                 else
403                         return edl->session->output_h;
404         }
409 void Canvas::get_scrollbars(EDL *edl, 
410         int &canvas_x, 
411         int &canvas_y, 
412         int &canvas_w, 
413         int &canvas_h)
415         int need_xscroll = 0;
416         int need_yscroll = 0;
417 //      int done = 0;
418         float zoom_x, zoom_y, conformed_w, conformed_h;
420         if(edl)
421         {
422                 w_needed = edl->calculate_output_w(0);
423                 h_needed = edl->calculate_output_h(0);
424                 w_visible = w_needed;
425                 h_visible = h_needed;
426         }
427 //printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll());
429         if(use_scrollbars)
430         {
431                 w_needed = edl->calculate_output_w(0);
432                 h_needed = edl->calculate_output_h(0);
433                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
434 //printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll());
436 //              while(!done)
437 //              {
438                         w_visible = (int)(canvas_w / zoom_x);
439                         h_visible = (int)(canvas_h / zoom_y);
440 //                      done = 1;
442 //                      if(w_needed > w_visible)
443                         if(1)
444                         {
445                                 if(!need_xscroll)
446                                 {
447                                         need_xscroll = 1;
448                                         canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ);
449 //                                      done = 0;
450                                 }
451                         }
452                         else
453                                 need_xscroll = 0;
455 //                      if(h_needed > h_visible)
456                         if(1)
457                         {
458                                 if(!need_yscroll)
459                                 {
460                                         need_yscroll = 1;
461                                         canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT);
462 //                                      done = 0;
463                                 }
464                         }
465                         else
466                                 need_yscroll = 0;
467 //              }
468 //printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible);
469 //printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll());
471                 w_visible = (int)(canvas_w / zoom_x);
472                 h_visible = (int)(canvas_h / zoom_y);
473         }
475         if(need_xscroll)
476         {
477                 if(!xscroll)
478                         subwindow->add_subwindow(xscroll = new CanvasXScroll(edl, 
479                                 this, 
480                 canvas_x,
481                 canvas_y + canvas_h,
482                                 w_needed,
483                                 get_xscroll(),
484                                 w_visible,
485                                 canvas_w));
486                 else
487                         xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w);
489                 if(xscroll->get_length() != w_needed ||
490                         xscroll->get_handlelength() != w_visible)
491                         xscroll->update_length(w_needed, get_xscroll(), w_visible);
492         }
493         else
494         {
495                 if(xscroll) delete xscroll;
496                 xscroll = 0;
497         }
498 //printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll());
500         if(need_yscroll)
501         {
502                 if(!yscroll)
503                         subwindow->add_subwindow(yscroll = new CanvasYScroll(edl, 
504                                 this,
505                 canvas_x + canvas_w,
506                 canvas_y,
507                                 h_needed,
508                                 get_yscroll(),
509                                 h_visible,
510                                 canvas_h));
511                 else
512                         yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h);
514                 if(yscroll->get_length() != edl->calculate_output_h(0) ||
515                         yscroll->get_handlelength() != h_visible)
516                         yscroll->update_length(h_needed, get_yscroll(), h_visible);
517         }
518         else
519         {
520                 if(yscroll) delete yscroll;
521                 yscroll = 0;
522         }
523 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
526 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
528         this->x = x;
529         this->y = y;
530         this->w = w;
531         this->h = h;
532         int view_x = x, view_y = y, view_w = w, view_h = h;
533 //printf("Canvas::reposition_window 1\n");
534         get_scrollbars(edl, view_x, view_y, view_w, view_h);
535 //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h);
536         canvas->reposition_window(view_x, view_y, view_w, view_h);
537         draw_refresh();
538 //printf("Canvas::reposition_window 2\n");
541 void Canvas::set_cursor(int cursor)
543         canvas->set_cursor(cursor);
546 int Canvas::get_cursor_x()
548         return canvas->get_cursor_x();
551 int Canvas::get_cursor_y()
553         return canvas->get_cursor_y();
556 int Canvas::get_buttonpress()
558         return canvas->get_buttonpress();
562 int Canvas::create_objects(EDL *edl)
564         int view_x = x, view_y = y, view_w = w, view_h = h;
565         get_scrollbars(edl, view_x, view_y, view_w, view_h);
567         subwindow->add_subwindow(canvas = new CanvasOutput(edl, 
568                 this, 
569                 view_x, 
570                 view_y, 
571                 view_w, 
572                 view_h));
574         subwindow->add_subwindow(canvas_menu = new CanvasPopup(this));
575         canvas_menu->create_objects();
577         return 0;
580 int Canvas::button_press_event()
582         int result = 0;
584         if(canvas->get_buttonpress() == 3)
585         {
586                 canvas_menu->activate_menu();
587                 result = 1;
588         }
589         
590         return result;
596 CanvasOutput::CanvasOutput(EDL *edl, 
597         Canvas *canvas,
598     int x,
599     int y,
600     int w,
601     int h)
602  : BC_SubWindow(x, y, w, h, BLACK)
604         this->canvas = canvas;
605         cursor_inside = 0;
608 CanvasOutput::~CanvasOutput()
612 int CanvasOutput::handle_event()
614         return 1;
617 int CanvasOutput::cursor_leave_event()
619         int result = 0;
620         if(cursor_inside) result = canvas->cursor_leave_event();
621         cursor_inside = 0;
622         return result;
625 int CanvasOutput::cursor_enter_event()
627         int result = 0;
628         if(is_event_win() && BC_WindowBase::cursor_inside())
629         {
630                 cursor_inside = 1;
631                 result = canvas->cursor_enter_event();
632         }
633         return result;
636 int CanvasOutput::button_press_event()
638         if(is_event_win() && BC_WindowBase::cursor_inside())
639         {
640                 return canvas->button_press_event();
641         }
642         return 0;
645 int CanvasOutput::button_release_event()
647         return canvas->button_release_event();
650 int CanvasOutput::cursor_motion_event()
652         return canvas->cursor_motion_event();
657 CanvasXScroll::CanvasXScroll(EDL *edl, 
658         Canvas *canvas, 
659     int x, 
660     int y, 
661         int length, 
662         int position, 
663         int handle_length,
664     int pixels)
665  : BC_ScrollBar(x, 
666                 y, 
667                 SCROLL_HORIZ, 
668                 pixels, 
669                 length, 
670                 position, 
671                 handle_length)
673         this->canvas = canvas;
676 CanvasXScroll::~CanvasXScroll()
680 int CanvasXScroll::handle_event()
682 //printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
683         canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
684         canvas->draw_refresh();
685         return 1;
693 CanvasYScroll::CanvasYScroll(EDL *edl, 
694         Canvas *canvas, 
695     int x, 
696     int y, 
697         int length, 
698         int position, 
699         int handle_length,
700     int pixels)
701  : BC_ScrollBar(x, 
702                 y, 
703                 SCROLL_VERT, 
704                 pixels, 
705                 length, 
706                 position, 
707                 handle_length)
709         this->canvas = canvas;
712 CanvasYScroll::~CanvasYScroll()
716 int CanvasYScroll::handle_event()
718 //printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
719         canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
720         canvas->draw_refresh();
721         return 1;
727 CanvasPopup::CanvasPopup(Canvas *canvas)
728  : BC_PopupMenu(0, 
729                 0, 
730                 0, 
731                 "", 
732                 0)
734         this->canvas = canvas;
737 CanvasPopup::~CanvasPopup()
741 void CanvasPopup::create_objects()
743         add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
744         add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
745         add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
746         add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
747         if(canvas->use_cwindow)
748         {
749                 add_item(new CanvasPopupResetCamera(canvas));
750                 add_item(new CanvasPopupResetProjector(canvas));
751         }
752         if(canvas->use_rwindow)
753         {
754                 add_item(new CanvasPopupResetTranslation(canvas));
755         }
756         if(canvas->use_vwindow)
757         {
758                 add_item(new CanvasPopupRemoveSource(canvas));
759         }
764 CanvasPopupSize::CanvasPopupSize(Canvas *canvas, char *text, float percentage)
765  : BC_MenuItem(text)
767         this->canvas = canvas;
768         this->percentage = percentage;
770 CanvasPopupSize::~CanvasPopupSize()
773 int CanvasPopupSize::handle_event()
775         canvas->zoom_resize_window(percentage);
776         return 1;
781 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
782  : BC_MenuItem(_("Reset camera"))
784         this->canvas = canvas;
786 int CanvasPopupResetCamera::handle_event()
788         canvas->reset_camera();
789         return 1;
794 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
795  : BC_MenuItem(_("Reset projector"))
797         this->canvas = canvas;
799 int CanvasPopupResetProjector::handle_event()
801         canvas->reset_projector();
802         return 1;
807 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
808  : BC_MenuItem(_("Reset translation"))
810         this->canvas = canvas;
812 int CanvasPopupResetTranslation::handle_event()
814         canvas->reset_translation();
815         return 1;
821 CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas)
822  : BC_MenuItem(_("Close source"))
824         this->canvas = canvas;
826 int CanvasPopupRemoveSource::handle_event()
828         canvas->close_source();
829         return 1;