r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / canvas.C
blob6c5cda5621e615604c72cb41552d4776dc026f9f
1 #include "canvas.h"
2 #include "clip.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "language.h"
6 #include "vframe.h"
10 Canvas::Canvas(BC_WindowBase *subwindow, 
11         int x, 
12         int y, 
13         int w, 
14         int h,
15         int output_w,
16         int output_h,
17         int use_scrollbars,
18         int use_cwindow,
19         int use_rwindow,
20         int use_vwindow)
22         reset();
23         this->subwindow = subwindow;
24         this->x = x;
25         this->y = y;
26         this->w = w;
27         this->h = h;
28         this->output_w = output_w;
29         this->output_h = output_h;
30         this->use_scrollbars = use_scrollbars;
31         this->use_cwindow = use_cwindow;
32         this->use_rwindow = use_rwindow;
33         this->use_vwindow = use_vwindow;
36 Canvas::~Canvas()
38         if(refresh_frame) delete refresh_frame;
39         delete canvas_menu;
40         if(yscroll) delete yscroll;
41         if(xscroll) delete xscroll;
44 void Canvas::reset()
46         use_scrollbars = 0;
47         output_w = 0;
48         output_h = 0;
49     xscroll = 0;
50     yscroll = 0;
51         refresh_frame = 0;
54 // Get dimensions given a zoom
55 void Canvas::calculate_sizes(float aspect_ratio, 
56         int output_w, 
57         int output_h, 
58         float zoom, 
59         int &w, 
60         int &h)
62 // Horizontal stretch
63         if((float)output_w / output_h <= aspect_ratio)
64         {
65                 w = (int)((float)output_h * aspect_ratio * zoom + 1);
66                 h = (int)((float)output_h * zoom + 1);
67         }
68         else
69 // Vertical stretch
70         {
71                 h = (int)((float)output_w / aspect_ratio * zoom + 1);
72                 w = (int)((float)output_w * zoom + 1);
73         }
76 float Canvas::get_x_offset(EDL *edl, 
77         int single_channel, 
78         float zoom_x, 
79         float conformed_w,
80         float conformed_h)
82         if(use_scrollbars)
83         {
84                 if(xscroll) 
85                 {
86                         if(conformed_w < w_visible)
87                                 return -(float)(w_visible - conformed_w) / 2;
89                         return (float)get_xscroll();
90                 }
91                 else
92                         return ((float)-canvas->get_w() / zoom_x + 
93                                 edl->calculate_output_w(single_channel)) / 2;
94         }
95         else
96         {
97                 int out_w, out_h;
98                 int canvas_w = canvas->get_w();
99                 int canvas_h = canvas->get_h();
100                 out_w = canvas_w;
101                 out_h = canvas_h;
102                 
103                 if((float)out_w / out_h > conformed_w / conformed_h)
104                 {
105                         out_w = (int)(out_h * conformed_w / conformed_h + 0.5);
106                 }
107                 
108                 if(out_w < canvas_w)
109                         return -(canvas_w - out_w) / 2 / zoom_x;
110         }
112         return 0;
115 float Canvas::get_y_offset(EDL *edl, 
116         int single_channel, 
117         float zoom_y, 
118         float conformed_w,
119         float conformed_h)
121         if(use_scrollbars)
122         {
123                 if(yscroll)
124                 {
125                         if(conformed_h < h_visible)
126                                 return -(float)(h_visible - conformed_h) / 2;
128                         return (float)get_yscroll();
129                 }
130                 else
131                         return ((float)-canvas->get_h() / zoom_y + 
132                                 edl->calculate_output_h(single_channel)) / 2;
133         }
134         else
135         {
136                 int out_w, out_h;
137                 int canvas_w = canvas->get_w();
138                 int canvas_h = canvas->get_h();
139                 out_w = canvas_w;
140                 out_h = canvas_h;
142                 if((float)out_w / out_h <= conformed_w / conformed_h)
143                 {
144                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
145                 }
147 //printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2);
148                 if(out_h < canvas_h)
149                         return -((float)canvas_h - out_h) / 2 / zoom_y;
150         }
152         return 0;
155 // This may not be used anymore
156 void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom)
158         if(x + w_visible > w_needed) x = w_needed - w_visible;
159         if(y + h_visible > h_needed) y = h_needed - h_visible;
161         if(x < 0) x = 0;
162         if(y < 0) y = 0;
165 void Canvas::update_scrollbars()
167         if(use_scrollbars)
168         {
169                 if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible);
170                 if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible);
171         }
174 void Canvas::get_zooms(EDL *edl, 
175         int single_channel, 
176         float &zoom_x, 
177         float &zoom_y,
178         float &conformed_w,
179         float &conformed_h)
181         edl->calculate_conformed_dimensions(single_channel, 
182                 conformed_w, 
183                 conformed_h);
185         if(use_scrollbars)
186         {
187                 zoom_x = get_zoom() * 
188                         conformed_w / 
189                         edl->calculate_output_w(single_channel);
190                 zoom_y = get_zoom() * 
191                         conformed_h / 
192                         edl->calculate_output_h(single_channel);
193         }
194         else
195         {
196                 int out_w, out_h;
197                 int canvas_w = canvas->get_w();
198                 int canvas_h = canvas->get_h();
199         
200                 out_w = canvas_w;
201                 out_h = canvas_h;
203                 if((float)out_w / out_h > conformed_w / conformed_h)
204                 {
205                         out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5);
206                 }
207                 else
208                 {
209                         out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5);
210                 }
212                 zoom_x = (float)out_w / edl->calculate_output_w(single_channel);
213                 zoom_y = (float)out_h / edl->calculate_output_h(single_channel);
214 //printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h);
215         }
218 // Convert a coordinate on the canvas to a coordinate on the output
219 void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y)
221         float zoom_x, zoom_y, conformed_w, conformed_h;
222         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
224 //printf("Canvas::canvas_to_output y=%f zoom_y=%f y_offset=%f\n", 
225 //      y, zoom_y, get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
227         x = (float)x / zoom_x + get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h);
228         y = (float)y / zoom_y + get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h);
231 void Canvas::output_to_canvas(EDL *edl, int single_channel, float &x, float &y)
233         float zoom_x, zoom_y, conformed_w, conformed_h;
234         get_zooms(edl, single_channel, zoom_x, zoom_y, conformed_w, conformed_h);
236 //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));
238         x = (float)zoom_x * (x - get_x_offset(edl, single_channel, zoom_x, conformed_w, conformed_h));
239         y = (float)zoom_y * (y - get_y_offset(edl, single_channel, zoom_y, conformed_w, conformed_h));
244 void Canvas::get_transfers(EDL *edl, 
245         int &in_x, 
246         int &in_y, 
247         int &in_w, 
248         int &in_h,
249         int &out_x, 
250         int &out_y, 
251         int &out_w, 
252         int &out_h,
253         int canvas_w,
254         int canvas_h)
256 // printf("Canvas::get_transfers %d %d\n", canvas_w, 
257 //              canvas_h);
258         if(canvas_w < 0) canvas_w = canvas->get_w();
259         if(canvas_h < 0) canvas_h = canvas->get_h();
261         if(use_scrollbars)
262         {
263                 float in_x1, in_y1, in_x2, in_y2;
264                 float out_x1, out_y1, out_x2, out_y2;
265                 float zoom_x, zoom_y, conformed_w, conformed_h;
267                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
268                 out_x1 = 0;
269                 out_y1 = 0;
270                 out_x2 = canvas_w;
271                 out_y2 = canvas_h;
272                 in_x1 = 0;
273                 in_y1 = 0;
274                 in_x2 = canvas_w;
275                 in_y2 = canvas_h;
277                 canvas_to_output(edl, 0, in_x1, in_y1);
278                 canvas_to_output(edl, 0, in_x2, in_y2);
280 // printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
281 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
283                 if(in_x1 < 0)
284                 {
285                         out_x1 += -in_x1 * zoom_x;
286                         in_x1 = 0;
287                 }
289                 if(in_y1 < 0)
290                 {
291                         out_y1 += -in_y1 * zoom_y;
292                         in_y1 = 0;
293                 }
295                 int output_w = get_output_w(edl);
296                 int output_h = get_output_h(edl);
298                 if(in_x2 > output_w)
299                 {
300                         out_x2 -= (in_x2 - output_w) * zoom_x;
301                         in_x2 = output_w;
302                 }
304                 if(in_y2 > output_h)
305                 {
306                         out_y2 -= (in_y2 - output_h) * zoom_y;
307                         in_y2 = output_h;
308                 }
309 // printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n",
310 //                      in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2);
312                 in_x = (int)in_x1;
313                 in_y = (int)in_y1;
314                 in_w = (int)(in_x2 - in_x1);
315                 in_h = (int)(in_y2 - in_y1);
316                 out_x = (int)out_x1;
317                 out_y = (int)out_y1;
318                 out_w = (int)(out_x2 - out_x1);
319                 out_h = (int)(out_y2 - out_y1);
321 // Center on canvas
322 //              if(!scrollbars_exist())
323 //              {
324 //                      out_x = canvas_w / 2 - out_w / 2;
325 //                      out_y = canvas_h / 2 - out_h / 2;
326 //              }
328 // printf("Canvas::get_transfers 2 %d %d %d %d -> %d %d %d %d\n",in_x, 
329 //                      in_y, 
330 //                      in_w, 
331 //                      in_h,
332 //                      out_x, 
333 //                      out_y, 
334 //                      out_w, 
335 //                      out_h);
336         }
337         else
338         {
339                 out_x = 0;
340                 out_y = 0;
341                 out_w = canvas_w;
342                 out_h = canvas_h;
344                 if(edl)
345                 {
346                         if((float)out_w / out_h > edl->get_aspect_ratio())
347                         {
348                                 out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5);
349                                 out_x = canvas_w / 2 - out_w / 2;
350                         }
351                         else
352                         {
353                                 out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5);
354                                 out_y = canvas_h / 2 - out_h / 2;
355                         }
356                         in_x = 0;
357                         in_y = 0;
358                         in_w = get_output_w(edl);
359                         in_h = get_output_h(edl);
360                 }
361                 else
362                 {
363                         in_x = 0;
364                         in_y = 0;
365                         in_w = this->output_w;
366                         in_h = this->output_h;
367                 }
368         }
370         in_x = MAX(0, in_x);
371         in_y = MAX(0, in_y);
372         in_w = MAX(0, in_w);
373         in_h = MAX(0, in_h);
374         out_x = MAX(0, out_x);
375         out_y = MAX(0, out_y);
376         out_w = MAX(0, out_w);
377         out_h = MAX(0, out_h);
380 int Canvas::scrollbars_exist()
382         return(use_scrollbars && (xscroll || yscroll));
385 int Canvas::get_output_w(EDL *edl)
387         if(use_scrollbars)
388                 return edl->calculate_output_w(0);
389         else
390                 return edl->session->output_w;
393 int Canvas::get_output_h(EDL *edl)
395         if(edl)
396         {
397                 if(use_scrollbars)
398                         return edl->calculate_output_h(0);
399                 else
400                         return edl->session->output_h;
401         }
406 void Canvas::get_scrollbars(EDL *edl, 
407         int &canvas_x, 
408         int &canvas_y, 
409         int &canvas_w, 
410         int &canvas_h)
412         int need_xscroll = 0;
413         int need_yscroll = 0;
414 //      int done = 0;
415         float zoom_x, zoom_y, conformed_w, conformed_h;
417         if(edl)
418         {
419                 w_needed = edl->calculate_output_w(0);
420                 h_needed = edl->calculate_output_h(0);
421                 w_visible = w_needed;
422                 h_visible = h_needed;
423         }
424 //printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll());
426         if(use_scrollbars)
427         {
428                 w_needed = edl->calculate_output_w(0);
429                 h_needed = edl->calculate_output_h(0);
430                 get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h);
431 //printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll());
433 //              while(!done)
434 //              {
435                         w_visible = (int)(canvas_w / zoom_x);
436                         h_visible = (int)(canvas_h / zoom_y);
437 //                      done = 1;
439 //                      if(w_needed > w_visible)
440                         if(1)
441                         {
442                                 if(!need_xscroll)
443                                 {
444                                         need_xscroll = 1;
445                                         canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ);
446 //                                      done = 0;
447                                 }
448                         }
449                         else
450                                 need_xscroll = 0;
452 //                      if(h_needed > h_visible)
453                         if(1)
454                         {
455                                 if(!need_yscroll)
456                                 {
457                                         need_yscroll = 1;
458                                         canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT);
459 //                                      done = 0;
460                                 }
461                         }
462                         else
463                                 need_yscroll = 0;
464 //              }
465 //printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible);
466 //printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll());
468                 w_visible = (int)(canvas_w / zoom_x);
469                 h_visible = (int)(canvas_h / zoom_y);
470         }
472         if(need_xscroll)
473         {
474                 if(!xscroll)
475                         subwindow->add_subwindow(xscroll = new CanvasXScroll(edl, 
476                                 this, 
477                 canvas_x,
478                 canvas_y + canvas_h,
479                                 w_needed,
480                                 get_xscroll(),
481                                 w_visible,
482                                 canvas_w));
483                 else
484                         xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w);
486                 if(xscroll->get_length() != w_needed ||
487                         xscroll->get_handlelength() != w_visible)
488                         xscroll->update_length(w_needed, get_xscroll(), w_visible);
489         }
490         else
491         {
492                 if(xscroll) delete xscroll;
493                 xscroll = 0;
494         }
495 //printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll());
497         if(need_yscroll)
498         {
499                 if(!yscroll)
500                         subwindow->add_subwindow(yscroll = new CanvasYScroll(edl, 
501                                 this,
502                 canvas_x + canvas_w,
503                 canvas_y,
504                                 h_needed,
505                                 get_yscroll(),
506                                 h_visible,
507                                 canvas_h));
508                 else
509                         yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h);
511                 if(yscroll->get_length() != edl->calculate_output_h(0) ||
512                         yscroll->get_handlelength() != h_visible)
513                         yscroll->update_length(h_needed, get_yscroll(), h_visible);
514         }
515         else
516         {
517                 if(yscroll) delete yscroll;
518                 yscroll = 0;
519         }
520 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
523 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
525         this->x = x;
526         this->y = y;
527         this->w = w;
528         this->h = h;
529         int view_x = x, view_y = y, view_w = w, view_h = h;
530 //printf("Canvas::reposition_window 1\n");
531         get_scrollbars(edl, view_x, view_y, view_w, view_h);
532 //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h);
533         canvas->reposition_window(view_x, view_y, view_w, view_h);
534         draw_refresh();
535 //printf("Canvas::reposition_window 2\n");
538 void Canvas::set_cursor(int cursor)
540         canvas->set_cursor(cursor);
543 int Canvas::get_cursor_x()
545         return canvas->get_cursor_x();
548 int Canvas::get_cursor_y()
550         return canvas->get_cursor_y();
553 int Canvas::get_buttonpress()
555         return canvas->get_buttonpress();
559 int Canvas::create_objects(EDL *edl)
561         int view_x = x, view_y = y, view_w = w, view_h = h;
562         get_scrollbars(edl, view_x, view_y, view_w, view_h);
564         subwindow->add_subwindow(canvas = new CanvasOutput(edl, 
565                 this, 
566                 view_x, 
567                 view_y, 
568                 view_w, 
569                 view_h));
571         subwindow->add_subwindow(canvas_menu = new CanvasPopup(this));
572         canvas_menu->create_objects();
574         return 0;
577 int Canvas::button_press_event()
579         int result = 0;
581         if(canvas->get_buttonpress() == 3)
582         {
583                 canvas_menu->activate_menu();
584                 result = 1;
585         }
586         
587         return result;
593 CanvasOutput::CanvasOutput(EDL *edl, 
594         Canvas *canvas,
595     int x,
596     int y,
597     int w,
598     int h)
599  : BC_SubWindow(x, y, w, h, BLACK)
601         this->canvas = canvas;
602         cursor_inside = 0;
605 CanvasOutput::~CanvasOutput()
609 int CanvasOutput::handle_event()
611         return 1;
614 int CanvasOutput::cursor_leave_event()
616         int result = 0;
617         if(cursor_inside) result = canvas->cursor_leave_event();
618         cursor_inside = 0;
619         return result;
622 int CanvasOutput::cursor_enter_event()
624         int result = 0;
625         if(is_event_win() && BC_WindowBase::cursor_inside())
626         {
627                 cursor_inside = 1;
628                 result = canvas->cursor_enter_event();
629         }
630         return result;
633 int CanvasOutput::button_press_event()
635         if(is_event_win() && BC_WindowBase::cursor_inside())
636         {
637                 return canvas->button_press_event();
638         }
639         return 0;
642 int CanvasOutput::button_release_event()
644         return canvas->button_release_event();
647 int CanvasOutput::cursor_motion_event()
649         return canvas->cursor_motion_event();
654 CanvasXScroll::CanvasXScroll(EDL *edl, 
655         Canvas *canvas, 
656     int x, 
657     int y, 
658         int length, 
659         int position, 
660         int handle_length,
661     int pixels)
662  : BC_ScrollBar(x, 
663                 y, 
664                 SCROLL_HORIZ, 
665                 pixels, 
666                 length, 
667                 position, 
668                 handle_length)
670         this->canvas = canvas;
673 CanvasXScroll::~CanvasXScroll()
677 int CanvasXScroll::handle_event()
679 //printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength());
680         canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom());
681         canvas->draw_refresh();
682         return 1;
690 CanvasYScroll::CanvasYScroll(EDL *edl, 
691         Canvas *canvas, 
692     int x, 
693     int y, 
694         int length, 
695         int position, 
696         int handle_length,
697     int pixels)
698  : BC_ScrollBar(x, 
699                 y, 
700                 SCROLL_VERT, 
701                 pixels, 
702                 length, 
703                 position, 
704                 handle_length)
706         this->canvas = canvas;
709 CanvasYScroll::~CanvasYScroll()
713 int CanvasYScroll::handle_event()
715 //printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length());
716         canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom());
717         canvas->draw_refresh();
718         return 1;
724 CanvasPopup::CanvasPopup(Canvas *canvas)
725  : BC_PopupMenu(0, 
726                 0, 
727                 0, 
728                 "", 
729                 0)
731         this->canvas = canvas;
734 CanvasPopup::~CanvasPopup()
738 void CanvasPopup::create_objects()
740         add_item(new CanvasPopupSize(canvas, _("Zoom 25%"), 0.25));
741         add_item(new CanvasPopupSize(canvas, _("Zoom 50%"), 0.5));
742         add_item(new CanvasPopupSize(canvas, _("Zoom 100%"), 1.0));
743         add_item(new CanvasPopupSize(canvas, _("Zoom 200%"), 2.0));
744         if(canvas->use_cwindow)
745         {
746                 add_item(new CanvasPopupResetCamera(canvas));
747                 add_item(new CanvasPopupResetProjector(canvas));
748         }
749         if(canvas->use_rwindow)
750         {
751                 add_item(new CanvasPopupResetTranslation(canvas));
752         }
753         if(canvas->use_vwindow)
754         {
755                 add_item(new CanvasPopupRemoveSource(canvas));
756         }
761 CanvasPopupSize::CanvasPopupSize(Canvas *canvas, char *text, float percentage)
762  : BC_MenuItem(text)
764         this->canvas = canvas;
765         this->percentage = percentage;
767 CanvasPopupSize::~CanvasPopupSize()
770 int CanvasPopupSize::handle_event()
772         canvas->zoom_resize_window(percentage);
773         return 1;
778 CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas)
779  : BC_MenuItem(_("Reset camera"))
781         this->canvas = canvas;
783 int CanvasPopupResetCamera::handle_event()
785         canvas->reset_camera();
786         return 1;
791 CanvasPopupResetProjector::CanvasPopupResetProjector(Canvas *canvas)
792  : BC_MenuItem(_("Reset projector"))
794         this->canvas = canvas;
796 int CanvasPopupResetProjector::handle_event()
798         canvas->reset_projector();
799         return 1;
804 CanvasPopupResetTranslation::CanvasPopupResetTranslation(Canvas *canvas)
805  : BC_MenuItem(_("Reset translation"))
807         this->canvas = canvas;
809 int CanvasPopupResetTranslation::handle_event()
811         canvas->reset_translation();
812         return 1;
818 CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas)
819  : BC_MenuItem(_("Close source"))
821         this->canvas = canvas;
823 int CanvasPopupRemoveSource::handle_event()
825         canvas->close_source();
826         return 1;