X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fcanvas.C;h=e3e1b0f3381d2d826fe1a16f7b3aa7ce0df1ce05;hp=6b3f65085c920ea3994a224e8007287b4eb59b7a;hb=b78b166faf60a1c7357f990b1e2fb0e70be29fee;hpb=47f71d004db08fb289428240fb87ce97c64382d2 diff --git a/cinelerra-5.1/cinelerra/canvas.C b/cinelerra-5.1/cinelerra/canvas.C index 6b3f6508..e3e1b0f3 100644 --- a/cinelerra-5.1/cinelerra/canvas.C +++ b/cinelerra-5.1/cinelerra/canvas.C @@ -36,20 +36,15 @@ -Canvas::Canvas(MWindow *mwindow, - BC_WindowBase *subwindow, - int x, - int y, - int w, - int h, - int output_w, - int output_h, +Canvas::Canvas(MWindow *mwindow, BC_WindowBase *subwindow, + int x, int y, int w, int h, int output_w, int output_h, int use_scrollbars) { reset(); - if(w < 10) w = 10; - if(h < 10) h = 10; + int xs10 = xS(10), ys10 = yS(10); + if(w < xs10) w = xs10; + if(h < ys10) h = ys10; this->mwindow = mwindow; this->subwindow = subwindow; this->x = x; @@ -63,7 +58,7 @@ Canvas::Canvas(MWindow *mwindow, this->scr_w0 = subwindow->get_screen_w(0, 0); this->root_w = subwindow->get_root_w(0); this->root_h = subwindow->get_root_h(0); - canvas_lock = new Mutex("Canvas::canvas_lock", 1); + canvas_lock = new Condition(1, "Canvas::canvas_lock", 1); } Canvas::~Canvas() @@ -88,25 +83,25 @@ void Canvas::reset() canvas_subwindow = 0; canvas_fullscreen = 0; is_processing = 0; + is_fullscreen = 0; cursor_inside = 0; } -void Canvas::lock_canvas(const char *location) +BC_WindowBase *Canvas::lock_canvas(const char *loc) { - canvas_lock->lock(location); + canvas_lock->lock(loc); + BC_WindowBase *wdw = get_canvas(); + if( wdw ) wdw->lock_window(loc); + return wdw; } void Canvas::unlock_canvas() { + BC_WindowBase *wdw = get_canvas(); + if( wdw ) wdw->unlock_window(); canvas_lock->unlock(); } -int Canvas::is_locked() -{ - return canvas_lock->is_locked(); -} - - BC_WindowBase* Canvas::get_canvas() { if(get_fullscreen() && canvas_fullscreen) @@ -135,107 +130,52 @@ void Canvas::use_vwindow() canvas_menu->use_vwindow(); } +int Canvas::get_fullscreen() +{ + return is_fullscreen; +} + // Get dimensions given a zoom void Canvas::calculate_sizes(float aspect_ratio, - int output_w, - int output_h, - float zoom, - int &w, - int &h) + int output_w, int output_h, float zoom, + int &w, int &h) { // Horizontal stretch - if((float)output_w / output_h <= aspect_ratio) - { - w = (int)((float)output_h * aspect_ratio * zoom); - h = (int)((float)output_h * zoom); + if( (float)output_w/output_h <= aspect_ratio ) { + w = (float)output_h * aspect_ratio * zoom; + h = (float)output_h * zoom; } - else + else { // Vertical stretch - { - h = (int)((float)output_w / aspect_ratio * zoom); - w = (int)((float)output_w * zoom); + h = (float)output_w / aspect_ratio * zoom; + w = (float)output_w * zoom; } } -float Canvas::get_x_offset(EDL *edl, - int single_channel, - float zoom_x, - float conformed_w, - float conformed_h) +float Canvas::get_x_offset(EDL *edl, int single_channel, + float zoom_x, float conformed_w, float conformed_h) { - if(use_scrollbars) - { - if(xscroll) - { -// If the projection is smaller than the canvas, this forces it in the center. -// if(conformed_w < w_visible) -// return -(float)(w_visible - conformed_w) / 2; - - return (float)get_xscroll(); - } - else - return ((float)-get_canvas()->get_w() / zoom_x + - edl->session->output_w) / 2; - } - else - { - int out_w, out_h; - int canvas_w = get_canvas()->get_w(); - int canvas_h = get_canvas()->get_h(); - out_w = canvas_w; - out_h = canvas_h; - - if((float)out_w / out_h > conformed_w / conformed_h) - { - out_w = (int)(out_h * conformed_w / conformed_h + 0.5); - } - - if(out_w < canvas_w) - return -(canvas_w - out_w) / 2 / zoom_x; - } - - return 0; + if( use_scrollbars ) return get_xscroll(); + int canvas_w = get_canvas()->get_w(), out_w = canvas_w; + int canvas_h = get_canvas()->get_h(), out_h = canvas_h; + float conformed_ratio = conformed_w/conformed_h; + if( (float)out_w/out_h > conformed_ratio ) + out_w = out_h * conformed_ratio + 0.5f; + float ret = out_w >= canvas_w ? 0 : -0.5f*(canvas_w - out_w) / zoom_x; + return ret; } -float Canvas::get_y_offset(EDL *edl, - int single_channel, - float zoom_y, - float conformed_w, - float conformed_h) +float Canvas::get_y_offset(EDL *edl, int single_channel, + float zoom_y, float conformed_w, float conformed_h) { - if(use_scrollbars) - { - if(yscroll) - { -// If the projection is smaller than the canvas, this forces it in the center. -// if(conformed_h < h_visible) -// return -(float)(h_visible - conformed_h) / 2; - - return (float)get_yscroll(); - } - else - return ((float)-get_canvas()->get_h() / zoom_y + - edl->session->output_h) / 2; - } - else - { - int out_w, out_h; - int canvas_w = get_canvas()->get_w(); - int canvas_h = get_canvas()->get_h(); - out_w = canvas_w; - out_h = canvas_h; - - if((float)out_w / out_h <= conformed_w / conformed_h) - { - out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5); - } - -//printf("Canvas::get_y_offset 1 %d %d %f\n", out_h, canvas_h, -((float)canvas_h - out_h) / 2); - if(out_h < canvas_h) - return -((float)canvas_h - out_h) / 2 / zoom_y; - } - - return 0; + if( use_scrollbars ) return get_yscroll(); + int canvas_w = get_canvas()->get_w(), out_w = canvas_w; + int canvas_h = get_canvas()->get_h(), out_h = canvas_h; + float conformed_ratio = conformed_w/conformed_h; + if( (float)out_w/out_h <= conformed_ratio ) + out_h = out_w / conformed_ratio + 0.5f; + float ret = out_h >= canvas_h ? 0 : -0.5f*(canvas_h - out_h) / zoom_y; + return ret; } // This may not be used anymore @@ -248,59 +188,73 @@ void Canvas::check_boundaries(EDL *edl, int &x, int &y, float &zoom) if(y < 0) y = 0; } -void Canvas::update_scrollbars(int flush) +void Canvas::update_scrollbars(EDL *edl, int flush) { - if(use_scrollbars) - { - if(xscroll) xscroll->update_length(w_needed, get_xscroll(), w_visible, flush); - if(yscroll) yscroll->update_length(h_needed, get_yscroll(), h_visible, flush); + if( edl ) + get_scrollbars(edl); + if( use_scrollbars ) { + if( xscroll ) xscroll->update_length(w_needed, get_xscroll(), w_visible, flush); + if( yscroll ) yscroll->update_length(h_needed, get_yscroll(), h_visible, flush); } } -void Canvas::get_zooms(EDL *edl, - int single_channel, - float &zoom_x, - float &zoom_y, - float &conformed_w, - float &conformed_h) +float Canvas::get_auto_zoom(EDL *edl) { - edl->calculate_conformed_dimensions(single_channel, - conformed_w, - conformed_h); + float conformed_w, conformed_h; + edl->calculate_conformed_dimensions(0, conformed_w, conformed_h); + BC_WindowBase *window = get_canvas(); + int window_w = window ? window->get_w() : w; + int window_h = window ? window->get_h() : h; + float zoom_x = window_w / conformed_w; + float zoom_y = window_h / conformed_h; + return zoom_x < zoom_y ? zoom_x : zoom_y; +} +void Canvas::zoom_auto() +{ + use_scrollbars = 0; +} - if(use_scrollbars) - { - zoom_x = get_zoom() * - conformed_w / - edl->session->output_w; - zoom_y = get_zoom() * - conformed_h / - edl->session->output_h; - } - else - { - int out_w, out_h; - int canvas_w = get_canvas()->get_w(); - int canvas_h = get_canvas()->get_h(); +void Canvas::get_zooms(EDL *edl, int single_channel, + float &zoom_x, float &zoom_y, + float &conformed_w, float &conformed_h) +{ + edl->calculate_conformed_dimensions(single_channel, + conformed_w, conformed_h); - out_w = canvas_w; - out_h = canvas_h; + float zoom = get_zoom(); + if( !use_scrollbars || !zoom ) zoom = get_auto_zoom(edl); + zoom_x = zoom * conformed_w / get_output_w(edl); + zoom_y = zoom * conformed_h / get_output_h(edl); +} - if((float)out_w / out_h > conformed_w / conformed_h) - { - out_w = (int)((float)out_h * conformed_w / conformed_h + 0.5); - } - else - { - out_h = (int)((float)out_w / (conformed_w / conformed_h) + 0.5); - } +void Canvas::set_zoom(EDL *edl, float zoom) +{ + BC_WindowBase *window = get_canvas(); + int cw = window ? window->get_w() : w; + int ch = window ? window->get_h() : h; + float cx = 0.5f * cw, cy = 0.5f * ch; + set_zoom(edl, zoom, cx, cy); +} - zoom_x = (float)out_w / edl->session->output_w; - zoom_y = (float)out_h / edl->session->output_h; -//printf("get zooms 2 %d %d %f %f\n", canvas_w, canvas_h, conformed_w, conformed_h); +void Canvas::set_zoom(EDL *edl, float zoom, float cx, float cy) +{ + float output_x = cx, output_y = cy; + canvas_to_output(edl, 0, output_x, output_y); + update_zoom(0, 0, zoom); + float zoom_x, zoom_y, conformed_w, conformed_h; + get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h); + if( zoom ) { + output_x -= cx / zoom_x; + output_y -= cy / zoom_y; } + else { + output_x = get_x_offset(edl, 0, zoom_x, conformed_w, conformed_h); + output_y = get_y_offset(edl, 0, zoom_y, conformed_w, conformed_h); + } + update_zoom(output_x, output_y, zoom); } + // Convert a coordinate on the canvas to a coordinate on the output void Canvas::canvas_to_output(EDL *edl, int single_channel, float &x, float &y) { @@ -335,245 +289,150 @@ void Canvas::get_transfers(EDL *edl, //printf("Canvas::get_transfers %d canvas_w=%d canvas_h=%d\n", // __LINE__, canvas_w, canvas_h); // automatic canvas size detection - if(canvas_w < 0) canvas_w = get_canvas()->get_w(); - if(canvas_h < 0) canvas_h = get_canvas()->get_h(); - -// Canvas is zoomed to a portion of the output frame - if(use_scrollbars) - { - float in_x1, in_y1, in_x2, in_y2; - float out_x1, out_y1, out_x2, out_y2; - float zoom_x, zoom_y, conformed_w, conformed_h; - - get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h); - out_x1 = 0; - out_y1 = 0; - out_x2 = canvas_w; - out_y2 = canvas_h; - in_x1 = 0; - in_y1 = 0; - in_x2 = canvas_w; - in_y2 = canvas_h; - - canvas_to_output(edl, 0, in_x1, in_y1); - canvas_to_output(edl, 0, in_x2, in_y2); - -//printf("Canvas::get_transfers 1 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n", -//in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); - - if(in_x1 < 0) - { - out_x1 += -in_x1 * zoom_x; - in_x1 = 0; - } + if( canvas_w < 0 ) canvas_w = get_canvas()->get_w(); + if( canvas_h < 0 ) canvas_h = get_canvas()->get_h(); - if(in_y1 < 0) - { - out_y1 += -in_y1 * zoom_y; - in_y1 = 0; - } + float in_x1, in_y1, in_x2, in_y2; + float out_x1, out_y1, out_x2, out_y2; + float zoom_x, zoom_y, conformed_w, conformed_h; - int output_w = get_output_w(edl); - int output_h = get_output_h(edl); + get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h); + out_x1 = 0; out_x2 = canvas_w; + out_y1 = 0; out_y2 = canvas_h; + in_x1 = 0; in_x2 = canvas_w; + in_y1 = 0; in_y2 = canvas_h; + canvas_to_output(edl, 0, in_x1, in_y1); + canvas_to_output(edl, 0, in_x2, in_y2); - if(in_x2 > output_w) - { - out_x2 -= (in_x2 - output_w) * zoom_x; - in_x2 = output_w; - } + if( in_x1 < 0 ) { + out_x1 += -in_x1 * zoom_x; + in_x1 = 0; + } - if(in_y2 > output_h) - { - out_y2 -= (in_y2 - output_h) * zoom_y; - in_y2 = output_h; - } -// printf("Canvas::get_transfers 2 %.0f %.0f %.0f %.0f -> %.0f %.0f %.0f %.0f\n", -// in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); - - output_x1 = in_x1; - output_y1 = in_y1; - output_x2 = in_x2; - output_y2 = in_y2; - canvas_x1 = out_x1; - canvas_y1 = out_y1; - canvas_x2 = out_x2; - canvas_y2 = out_y2; - -// Center on canvas -// if(!scrollbars_exist()) -// { -// out_x = canvas_w / 2 - out_w / 2; -// out_y = canvas_h / 2 - out_h / 2; -// } + if( in_y1 < 0 ) { + out_y1 += -in_y1 * zoom_y; + in_y1 = 0; + } + int output_w = get_output_w(edl); + int output_h = get_output_h(edl); + if( in_x2 > output_w ) { + out_x2 -= (in_x2 - output_w) * zoom_x; + in_x2 = output_w; } - else -// The output frame is normalized to the canvas - { -// Default canvas coords fill the entire canvas - canvas_x1 = 0; - canvas_y1 = 0; - canvas_x2 = canvas_w; - canvas_y2 = canvas_h; - - if(edl) - { -// Use EDL aspect ratio to shrink one of the canvas dimensions - float out_w = canvas_x2 - canvas_x1; - float out_h = canvas_y2 - canvas_y1; - if(out_w / out_h > edl->get_aspect_ratio()) - { - out_w = (int)(out_h * edl->get_aspect_ratio() + 0.5); - canvas_x1 = canvas_w / 2 - out_w / 2; - } - else - { - out_h = (int)(out_w / edl->get_aspect_ratio() + 0.5); - canvas_y1 = canvas_h / 2 - out_h / 2; -// printf("Canvas::get_transfers %d canvas_h=%d out_h=%f canvas_y1=%f\n", -// __LINE__, -// canvas_h, -// out_h, -// canvas_y1); - } - canvas_x2 = canvas_x1 + out_w; - canvas_y2 = canvas_y1 + out_h; - -// Get output frame coords from EDL - output_x1 = 0; - output_y1 = 0; - output_x2 = get_output_w(edl); - output_y2 = get_output_h(edl); - } - else -// No EDL to get aspect ratio or output frame coords from - { - output_x1 = 0; - output_y1 = 0; - output_x2 = this->output_w; - output_y2 = this->output_h; - } + + if( in_y2 > output_h ) { + out_y2 -= (in_y2 - output_h) * zoom_y; + in_y2 = output_h; } + output_x1 = in_x1; output_x2 = in_x2; + output_y1 = in_y1; output_y2 = in_y2; + canvas_x1 = out_x1; canvas_x2 = out_x2; + canvas_y1 = out_y1; canvas_y2 = out_y2; + // Clamp to minimum value - output_x1 = MAX(0, output_x1); - output_y1 = MAX(0, output_y1); - output_x2 = MAX(output_x1, output_x2); - output_y2 = MAX(output_y1, output_y2); - canvas_x1 = MAX(0, canvas_x1); - canvas_y1 = MAX(0, canvas_y1); - canvas_x2 = MAX(canvas_x1, canvas_x2); - canvas_y2 = MAX(canvas_y1, canvas_y2); -// printf("Canvas::get_transfers %d %f,%f %f,%f -> %f,%f %f,%f\n", -// __LINE__, -// output_x1, -// output_y1, -// output_x2, -// output_y2, -// canvas_x1, -// canvas_y1, -// canvas_x2, -// canvas_y2); + if( output_x1 < 0 ) output_x1 = 0; + if( output_x2 < output_x1 ) output_x2 = output_x1; + if( canvas_x1 < 0 ) canvas_x1 = 0; + if( canvas_x2 < canvas_x1 ) canvas_x2 = canvas_x1; +// printf("Canvas::get_transfers %d %f,%f %f,%f -> %f,%f %f,%f\n", __LINE__, +// output_x1, output_y1, output_x2, output_y2, +// canvas_x1, canvas_y1, canvas_x2, canvas_y2); } int Canvas::scrollbars_exist() { - return(use_scrollbars && (xscroll || yscroll)); + return use_scrollbars && (xscroll || yscroll); } int Canvas::get_output_w(EDL *edl) { - return !edl ? 0 : edl->session->output_w; + return edl->session->output_w; } int Canvas::get_output_h(EDL *edl) { - return !edl ? 0 : edl->session->output_h; + return edl->session->output_h; } - -void Canvas::get_scrollbars(EDL *edl, - int &canvas_x, - int &canvas_y, - int &canvas_w, - int &canvas_h) +int Canvas::get_scrollbars(EDL *edl) { - int need_xscroll = 0; - int need_yscroll = 0; -// int done = 0; - float zoom_x, zoom_y, conformed_w, conformed_h; + int ret = 0; + BC_WindowBase *window = get_canvas(); + if( !window ) use_scrollbars = 0; + int canvas_w = w, canvas_h = h; - if(edl) - { - w_needed = edl->session->output_w; - h_needed = edl->session->output_h; - w_visible = w_needed; - h_visible = h_needed; - } -//printf("Canvas::get_scrollbars 1 %d %d\n", get_xscroll(), get_yscroll()); + w_needed = w_visible = edl ? edl->session->output_w : view_w; + h_needed = h_visible = edl ? edl->session->output_h : view_h; - if( use_scrollbars ) { - w_needed = edl->session->output_w; - h_needed = edl->session->output_h; + int need_xscroll = 0, need_yscroll = 0; + if( edl && use_scrollbars ) { + float zoom_x, zoom_y, conformed_w, conformed_h; get_zooms(edl, 0, zoom_x, zoom_y, conformed_w, conformed_h); -//printf("Canvas::get_scrollbars 2 %d %d\n", get_xscroll(), get_yscroll()); - - w_visible = (int)(canvas_w / zoom_x); - h_visible = (int)(canvas_h / zoom_y); - if( w_needed > w_visible ) { - need_xscroll = 1; + w_visible = canvas_w / zoom_x; + h_visible = canvas_h / zoom_y; + float output_x = 0, output_y = 0; + output_to_canvas(edl, 0, output_x, output_y); + if( output_x < 0 ) need_xscroll = 1; + if( output_y < 0 ) need_yscroll = 1; + output_x = w_needed, output_y = h_needed; + output_to_canvas(edl, 0, output_x, output_y); + if( output_x > canvas_w ) need_xscroll = 1; + if( output_y > canvas_h ) need_yscroll = 1; + if( need_xscroll ) { canvas_h -= BC_ScrollBar::get_span(SCROLL_HORIZ); + h_visible = canvas_h / zoom_y; } - - if( h_needed > h_visible ) { - need_yscroll = 1; + if( need_yscroll ) { canvas_w -= BC_ScrollBar::get_span(SCROLL_VERT); + w_visible = canvas_w / zoom_x; } -//printf("Canvas::get_scrollbars %d %d %d %d %d %d\n", canvas_w, canvas_h, w_needed, h_needed, w_visible, h_visible); -//printf("Canvas::get_scrollbars 3 %d %d\n", get_xscroll(), get_yscroll()); - - w_visible = (int)(canvas_w / zoom_x); - h_visible = (int)(canvas_h / zoom_y); + view_w = canvas_w; + view_h = canvas_h; } if( need_xscroll ) { if( !xscroll ) { - xscroll = new CanvasXScroll(edl, this, canvas_x, canvas_y + canvas_h, - w_needed, get_xscroll(), w_visible, canvas_w); + xscroll = new CanvasXScroll(edl, this, view_x, view_y + view_h, + w_needed, get_xscroll(), w_visible, view_w); subwindow->add_subwindow(xscroll); xscroll->show_window(0); } else - xscroll->reposition_window(canvas_x, canvas_y + canvas_h, canvas_w); + xscroll->reposition_window(view_x, view_y + view_h, view_w); if( xscroll->get_length() != w_needed || xscroll->get_handlelength() != w_visible ) xscroll->update_length(w_needed, get_xscroll(), w_visible, 0); + ret = 1; } else if( xscroll ) { delete xscroll; xscroll = 0; + ret = 1; } -//printf("Canvas::get_scrollbars 4 %d %d\n", get_xscroll(), get_yscroll()); if( need_yscroll ) { if( !yscroll ) { - yscroll = new CanvasYScroll(edl, this, canvas_x + canvas_w, canvas_y, - h_needed, get_yscroll(), h_visible, canvas_h); + yscroll = new CanvasYScroll(edl, this, view_x + view_w, view_y, + h_needed, get_yscroll(), h_visible, view_h); subwindow->add_subwindow(yscroll); yscroll->show_window(0); } else - yscroll->reposition_window(canvas_x + canvas_w, canvas_y, canvas_h); + yscroll->reposition_window(view_x + view_w, view_y, view_h); if( yscroll->get_length() != edl->session->output_h || yscroll->get_handlelength() != h_visible ) yscroll->update_length(h_needed, get_yscroll(), h_visible, 0); + ret = 1; } else if( yscroll ) { delete yscroll; yscroll = 0; + ret = 1; } -//printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll()); + return ret; } @@ -581,15 +440,12 @@ void Canvas::update_geometry(EDL *edl, int x, int y, int w, int h) { int redraw = 0; if( this->x != x || this->y != y || - this->w != w || this->h != h ) redraw = 1; - if( !redraw ) { - int vx = x, vy = y, vw = w, vh = h; - get_scrollbars(edl, vx, vy, vw, vh); - if( vx != view_x || vy != view_y || - vw != view_w || vh != view_h ) redraw = 1; - } - if( !redraw ) return; - reposition_window(edl, x, y, w, y); + this->w != w || this->h != h ) + redraw = 1; + if( !redraw ) + redraw = get_scrollbars(edl); + if( redraw ) + reposition_window(edl, x, y, w, h); } void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h) @@ -597,22 +453,37 @@ void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h) this->x = view_x = x; this->y = view_y = y; this->w = view_w = w; this->h = view_h = h; //printf("Canvas::reposition_window 1\n"); - get_scrollbars(edl, view_x, view_y, view_w, view_h); + get_scrollbars(edl); //printf("Canvas::reposition_window %d %d %d %d\n", view_x, view_y, view_w, view_h); - if(canvas_subwindow) - { + if( canvas_subwindow ) { canvas_subwindow->reposition_window(view_x, view_y, view_w, view_h); // Need to clear out the garbage in the back - if(canvas_subwindow->get_video_on()) - { - canvas_subwindow->set_color(BLACK); - canvas_subwindow->draw_box(0, 0, - get_canvas()->get_w(), get_canvas()->get_h()); - canvas_subwindow->flash(0); - } + if( canvas_subwindow->get_video_on() ) + clear_borders(edl); } - draw_refresh(0); + refresh(0); +} + +// must hold window lock +int Canvas::refresh(int flush) +{ + BC_WindowBase *window = get_canvas(); + if( !window ) return 0; +// relock in lock order to prevent deadlock + window->unlock_window(); + lock_canvas("Canvas::refresh"); + draw_refresh(flush); + canvas_lock->unlock(); + return 1; +} +// must not hold locks +int Canvas::redraw(int flush) +{ + lock_canvas("Canvas::redraw"); + draw_refresh(flush); + unlock_canvas(); + return 1; } void Canvas::set_cursor(int cursor) @@ -638,11 +509,9 @@ int Canvas::get_buttonpress() void Canvas::create_objects(EDL *edl) { - view_x = x; - view_y = y; - view_w = w; - view_h = h; - get_scrollbars(edl, view_x, view_y, view_w, view_h); + view_x = x; view_y = y; + view_w = w; view_h = h; + get_scrollbars(edl); subwindow->unlock_window(); create_canvas(); @@ -702,62 +571,68 @@ void Canvas::stop_video() } } +int Canvas::set_fullscreen(int on, int unlock) +{ + int ret = 0; + BC_WindowBase *window = get_canvas(); + if( unlock ) + window->unlock_window(); + if( on && !get_fullscreen() ) { + start_fullscreen(); + ret = 1; + } + if( !on && get_fullscreen() ) { + stop_fullscreen(); + ret = 1; + } + if( unlock ) + window->lock_window("Canvas::set_fullscreen"); + return ret; +} void Canvas::start_fullscreen() { - set_fullscreen(1); + is_fullscreen = 1; create_canvas(); } void Canvas::stop_fullscreen() { - set_fullscreen(0); + is_fullscreen = 0; create_canvas(); } void Canvas::create_canvas() { + canvas_lock->lock("Canvas::create_canvas"); int video_on = 0; - lock_canvas("Canvas::create_canvas"); - - - if(!get_fullscreen()) + BC_WindowBase *wdw = 0; + if( !get_fullscreen() ) { // Enter windowed - { - if(canvas_fullscreen) - { + if( canvas_fullscreen ) { + canvas_fullscreen->lock_window("Canvas::create_canvas 1"); video_on = canvas_fullscreen->get_video_on(); - canvas_fullscreen->stop_video(); - canvas_fullscreen->lock_window("Canvas::create_canvas 2"); + if( video_on ) canvas_fullscreen->stop_video(); canvas_fullscreen->hide_window(); canvas_fullscreen->unlock_window(); } - - if(!canvas_auxwindow && !canvas_subwindow) - { + if( !canvas_auxwindow && !canvas_subwindow ) { subwindow->add_subwindow(canvas_subwindow = new CanvasOutput(this, - view_x, - view_y, - view_w, - view_h)); + view_x, view_y, view_w, view_h)); } + wdw = get_canvas(); + wdw->lock_window("Canvas::create_canvas 2"); } - else + else { // Enter fullscreen - { - BC_WindowBase *wdw = canvas_auxwindow ? - canvas_auxwindow : canvas_subwindow; - if(wdw) - { - video_on = wdw->get_video_on(); - wdw->stop_video(); - } - + wdw = canvas_auxwindow ? canvas_auxwindow : canvas_subwindow; + wdw->lock_window("Canvas::create_canvas 3"); + video_on = wdw->get_video_on(); + if( video_on ) wdw->stop_video(); int x, y, w, h; wdw->get_fullscreen_geometry(x, y, w, h); - - if( canvas_fullscreen ) - { + wdw->unlock_window(); + if( canvas_fullscreen ) { if( x != canvas_fullscreen->get_x() || y != canvas_fullscreen->get_y() || w != canvas_fullscreen->get_w() || @@ -766,36 +641,26 @@ void Canvas::create_canvas() canvas_fullscreen = 0; } } - if(!canvas_fullscreen) - { + if( !canvas_fullscreen ) canvas_fullscreen = new CanvasFullScreen(this, w, h); - } - else - { - canvas_fullscreen->reposition_window(x, y); - canvas_fullscreen->show_window(); - } - } - - - if(!video_on) - { - get_canvas()->lock_window("Canvas::create_canvas 1"); - draw_refresh(); - get_canvas()->unlock_window(); + wdw = canvas_fullscreen; + wdw->lock_window("Canvas::create_canvas 4"); + wdw->show_window(); + wdw->sync_display(); + wdw->reposition_window(x, y); } - if(video_on) get_canvas()->start_video(); - - get_canvas()->lock_window("Canvas::create_canvas 2"); - get_canvas()->focus(); - get_canvas()->unlock_window(); + if( video_on ) + wdw->start_video(); + else + draw_refresh(1); - unlock_canvas(); + wdw->focus(); + wdw->unlock_window(); + canvas_lock->unlock(); } - int Canvas::cursor_leave_event_base(BC_WindowBase *caller) { int result = 0; @@ -827,24 +692,19 @@ int Canvas::button_press_event_base(BC_WindowBase *caller) int Canvas::keypress_event(BC_WindowBase *caller) { int key = caller->get_keypress(); + int on = -1; switch( key ) { case 'f': - caller->unlock_window(); - if(get_fullscreen()) - stop_fullscreen(); - else - start_fullscreen(); - caller->lock_window("Canvas::keypress_event 1"); + on = get_fullscreen() ? 0 : 1; break; case ESC: - caller->unlock_window(); - if(get_fullscreen()) - stop_fullscreen(); - caller->lock_window("Canvas::keypress_event 2"); + on = 0; break; default: return 0; } + if( on >= 0 ) + set_fullscreen(on); return 1; } @@ -884,37 +744,77 @@ void Canvas::update_refresh(VideoDevice *device, VFrame *output_frame) } if( use_opengl ) { - get_canvas()->unlock_window(); unlock_canvas(); - mwindow->playback_3d->copy_from(this, refresh_frame, output_frame, 0); - lock_canvas(" Canvas::output_refresh"); - get_canvas()->lock_window(" Canvas::output_refresh"); + lock_canvas("Canvas::update_refresh"); } else refresh_frame->transfer_from(output_frame, -1); } - -void Canvas::clear(int flush) +void Canvas::clear(int flash) { - if( refresh_frame ) - refresh_frame->clear_frame(); - BC_WindowBase *wdw = get_canvas(); - if( !wdw ) return; - wdw->set_bg_color(BLACK); - wdw->clear_box(0,0, wdw->get_w(), wdw->get_h()); - wdw->flash(flush); + BC_WindowBase *window = get_canvas(); + if( !window ) return; + window->set_bg_color(get_clear_color()); + window->clear_box(0,0, window->get_w(), window->get_h()); + if( flash ) window->flash(); } +void Canvas::clear_borders(EDL *edl) +{ + BC_WindowBase *window = get_canvas(); + if( !window ) return; + int window_w = window->get_w(); + int window_h = window->get_h(); + int color = get_clear_color(); + window->set_color(color); + + if( !edl ) { + window->draw_box(0, 0, window_w, window_h); + window->flash(0); + return; + } + + float output_x1,output_y1, output_x2,output_y2; + float canvas_x1,canvas_y1, canvas_x2,canvas_y2; + get_transfers(edl, + output_x1, output_y1, output_x2, output_y2, + canvas_x1, canvas_y1, canvas_x2, canvas_y2); + + if( canvas_y1 > 0 ) { + window->draw_box(0, 0, window_w, canvas_y1); + window->flash(0, 0, window_w, canvas_y1); + } + + if( canvas_y2 < window_h ) { + window->draw_box(0, canvas_y2, window_w, window_h-canvas_y2); + window->flash(0, canvas_y2, window_w, window_h-canvas_y2); + } + + if( canvas_x1 > 0 ) { + window->draw_box(0, canvas_y1, canvas_x1, canvas_y2-canvas_y1); + window->flash(0, canvas_y1, canvas_x1, canvas_y2-canvas_y1); + } + + if( canvas_x2 < window_w ) { + window->draw_box(canvas_x2, canvas_y1, + window_w-canvas_x2, canvas_y2-canvas_y1); + window->flash(canvas_x2, canvas_y1, + window_w-canvas_x2, canvas_y2-canvas_y1); + } +} +int Canvas::get_clear_color() +{ + BC_WindowBase *cwdw = get_canvas(); + if( !cwdw ) return 0; + return cwdw->get_bg_color(); +} CanvasOutput::CanvasOutput(Canvas *canvas, - int x, - int y, - int w, - int h) - : BC_SubWindow(x, y, w, h, BLACK) + int x, int y, int w, int h) + : BC_SubWindow(x, y, w, h, canvas->get_clear_color()) { this->canvas = canvas; } @@ -956,7 +856,7 @@ int CanvasOutput::keypress_event() CanvasFullScreen::CanvasFullScreen(Canvas *canvas, int w, int h) - : BC_FullScreen(canvas->subwindow, w, h, BLACK, 0, 0, 0) + : BC_FullScreen(canvas->subwindow, w, h, canvas->get_clear_color(), 0, 0, 0) { this->canvas = canvas; } @@ -979,10 +879,9 @@ CanvasXScroll::~CanvasXScroll() int CanvasXScroll::handle_event() { -//printf("CanvasXScroll::handle_event %d %d %d\n", get_length(), get_value(), get_handlelength()); - canvas->update_zoom(get_value(), canvas->get_yscroll(), canvas->get_zoom()); - canvas->draw_refresh(); - return 1; + canvas->update_zoom(get_value(), canvas->get_yscroll(), + canvas->get_zoom()); + return canvas->refresh(1); } @@ -999,10 +898,9 @@ CanvasYScroll::~CanvasYScroll() int CanvasYScroll::handle_event() { -//printf("CanvasYScroll::handle_event %d %d\n", get_value(), get_length()); - canvas->update_zoom(canvas->get_xscroll(), get_value(), canvas->get_zoom()); - canvas->draw_refresh(); - return 1; + canvas->update_zoom(canvas->get_xscroll(), get_value(), + canvas->get_zoom()); + return canvas->refresh(1); } @@ -1033,9 +931,7 @@ int CanvasSubWindowItem::handle_event() { // It isn't a problem to delete the canvas from in here because the event // dispatcher is the canvas subwindow. - canvas->subwindow->unlock_window(); - canvas->stop_fullscreen(); - canvas->subwindow->lock_window("CanvasSubWindowItem::handle_event"); + canvas->set_fullscreen(0); return 1; } @@ -1132,7 +1028,6 @@ int CanvasPopupSize::handle_event() } - CanvasPopupResetCamera::CanvasPopupResetCamera(Canvas *canvas) : BC_MenuItem(_("Reset camera"), _("F11"), KEY_F11) { @@ -1209,18 +1104,10 @@ int CanvasToggleControls::handle_event() char* CanvasToggleControls::calculate_text(int cwindow_controls) { - if(!cwindow_controls) - return _("Show controls"); - else - return _("Hide controls"); + return !cwindow_controls ? _("Show controls") : _("Hide controls"); } - - - - - CanvasFullScreenItem::CanvasFullScreenItem(Canvas *canvas) : BC_MenuItem(_("Fullscreen"), "f", 'f') { @@ -1228,20 +1115,11 @@ CanvasFullScreenItem::CanvasFullScreenItem(Canvas *canvas) } int CanvasFullScreenItem::handle_event() { - canvas->subwindow->unlock_window(); - canvas->start_fullscreen(); - canvas->subwindow->lock_window("CanvasFullScreenItem::handle_event"); + canvas->set_fullscreen(1); return 1; } - - - - - - - CanvasPopupRemoveSource::CanvasPopupRemoveSource(Canvas *canvas) : BC_MenuItem(_("Close source")) {