From a11196f4e47c312ff787d3990e0aa8edefa3e395 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 17 Oct 2011 22:13:51 +0100 Subject: New slide redraw logic This way is much more straightforward, and allows rendering in many different sizes --- src/mainwindow.c | 52 ++++++++++++++++++++++++++------------------ src/objects.c | 3 +-- src/presentation.c | 21 ++++++++++++------ src/presentation.h | 43 ++++++++++++++++++++++++++----------- src/slide_render.c | 63 +++++++++++++++++++++++++++++++++++++++++------------- src/slide_render.h | 3 +-- src/slideshow.c | 28 ++++++++++++++---------- src/tool_image.c | 5 ++--- src/tool_select.c | 6 ++---- src/tool_text.c | 15 ++++++------- 10 files changed, 152 insertions(+), 87 deletions(-) diff --git a/src/mainwindow.c b/src/mainwindow.c index 56b0e0c..3a3ee1c 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -228,6 +228,7 @@ static gint about_sig(GtkWidget *widget, struct presentation *p) static void update_toolbar(struct presentation *p) { GtkWidget *d; + int cur_slide_number; d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/first"); gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); @@ -238,7 +239,8 @@ static void update_toolbar(struct presentation *p) d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/last"); gtk_widget_set_sensitive(GTK_WIDGET(d), TRUE); - if ( p->view_slide_number == 0 ) { + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == 0 ) { d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/first"); @@ -249,7 +251,7 @@ static void update_toolbar(struct presentation *p) } - if ( p->view_slide_number == p->num_slides-1 ) { + if ( cur_slide_number == p->num_slides-1 ) { d = gtk_ui_manager_get_widget(p->ui, "/ui/displaywindowtoolbar/next"); @@ -296,10 +298,12 @@ void notify_slide_update(struct presentation *p) static gint add_slide_sig(GtkWidget *widget, struct presentation *p) { struct slide *new; + int cur_slide_number; - new = add_slide(p, p->view_slide_number); - p->view_slide = new; - p->view_slide_number++; + cur_slide_number = slide_number(p, p->cur_edit_slide); + + new = add_slide(p, cur_slide_number); + p->cur_edit_slide = new; notify_slide_changed(p); return FALSE; @@ -308,8 +312,7 @@ static gint add_slide_sig(GtkWidget *widget, struct presentation *p) static gint first_slide_sig(GtkWidget *widget, struct presentation *p) { - p->view_slide_number = 0; - p->view_slide = p->slides[0]; + p->cur_edit_slide = p->slides[0]; notify_slide_changed(p); return FALSE; @@ -318,10 +321,12 @@ static gint first_slide_sig(GtkWidget *widget, struct presentation *p) static gint prev_slide_sig(GtkWidget *widget, struct presentation *p) { - if ( p->view_slide_number == 0 ) return FALSE; + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == 0 ) return FALSE; - p->view_slide_number--; - p->view_slide = p->slides[p->view_slide_number]; + p->cur_edit_slide = p->slides[cur_slide_number-1]; notify_slide_changed(p); return FALSE; @@ -330,10 +335,12 @@ static gint prev_slide_sig(GtkWidget *widget, struct presentation *p) static gint next_slide_sig(GtkWidget *widget, struct presentation *p) { - if ( p->view_slide_number == p->num_slides-1 ) return FALSE; + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_edit_slide); + if ( cur_slide_number == p->num_slides-1 ) return FALSE; - p->view_slide_number++; - p->view_slide = p->slides[p->view_slide_number]; + p->cur_edit_slide = p->slides[cur_slide_number+1]; notify_slide_changed(p); return FALSE; @@ -342,8 +349,7 @@ static gint next_slide_sig(GtkWidget *widget, struct presentation *p) static gint last_slide_sig(GtkWidget *widget, struct presentation *p) { - p->view_slide_number = p->num_slides-1; - p->view_slide = p->slides[p->view_slide_number]; + p->cur_edit_slide = p->slides[p->num_slides-1]; notify_slide_changed(p); return FALSE; @@ -628,7 +634,7 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, x = event->x - p->border_offs_x; y = event->y - p->border_offs_y; - clicked = find_object_at_position(p->view_slide, x, y); + clicked = find_object_at_position(p->cur_edit_slide, x, y); if ( clicked == NULL ) { @@ -814,8 +820,6 @@ static gboolean expose_sig(GtkWidget *da, GdkEventExpose *event, GtkAllocation allocation; double xoff, yoff; - check_redraw_slide(p->view_slide); - cr = gdk_cairo_create(da->window); /* Overall background */ @@ -837,7 +841,8 @@ static gboolean expose_sig(GtkWidget *da, GdkEventExpose *event, /* Draw the slide from the cache */ cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); - cairo_set_source_surface(cr, p->view_slide->render_cache, xoff, yoff); + cairo_set_source_surface(cr, p->cur_edit_slide->rendered_edit, + xoff, yoff); cairo_fill(cr); cairo_translate(cr, xoff, yoff); @@ -1010,7 +1015,7 @@ static void dnd_receive(GtkWidget *widget, GdkDragContext *drag_context, gtk_drag_finish(drag_context, TRUE, FALSE, time); chomp(filename); - o = add_image_object(p->view_slide, + o = add_image_object(p->cur_edit_slide, p->start_corner_x, p->start_corner_y, p->import_width, p->import_height, @@ -1131,10 +1136,15 @@ int open_mainwindow(struct presentation *p) gtk_window_set_resizable(GTK_WINDOW(p->window), TRUE); assert(p->num_slides > 0); - check_redraw_slide(p->view_slide); gtk_widget_grab_focus(GTK_WIDGET(p->drawingarea)); gtk_widget_show_all(window); + + p->edit_slide_width = 1024; + p->proj_slide_width = 2048; + p->thumb_slide_width = 320; /* FIXME: Completely made up */ + redraw_slide(p->cur_edit_slide); + return 0; } diff --git a/src/objects.c b/src/objects.c index be92262..d7ad8a3 100644 --- a/src/objects.c +++ b/src/objects.c @@ -152,8 +152,7 @@ void notify_style_update(struct presentation *p, struct style *sty) if ( s->objects[j]->style != sty ) continue; s->objects[j]->update_object(s->objects[j]); - s->object_seq++; - if ( p->view_slide == s ) changed = 1; + if ( p->cur_edit_slide == s ) changed = 1; break; } diff --git a/src/presentation.c b/src/presentation.c index 68c87c1..1bc5689 100644 --- a/src/presentation.c +++ b/src/presentation.c @@ -41,20 +41,19 @@ struct slide *add_slide(struct presentation *p, int pos) struct slide *new; int i; - new = malloc(sizeof(struct slide)); + new = calloc(1, sizeof(struct slide)); if ( new == NULL ) return NULL; /* No objects to start with */ new->num_objects = 0; - new->object_seq = 0; new->objects = NULL; p->completely_empty = 0; new->parent = p; - new->render_cache_seq = 0; - new->render_cache = NULL; - render_slide(new); /* Render nothing, just to make the surface exist */ + new->rendered_edit = NULL; + new->rendered_proj = NULL; + new->rendered_thumb = NULL; try = realloc(p->slides, (1+p->num_slides)*sizeof(struct slide *)); if ( try == NULL ) { @@ -63,6 +62,7 @@ struct slide *add_slide(struct presentation *p, int pos) } p->slides = try; + /* Insert into list. Yuk yuk yuk etc. */ if ( (p->num_slides>1) && (posnum_slides-1) ) { for ( i=p->num_slides; i>pos+1; i-- ) { @@ -194,6 +194,13 @@ static void update_titlebar(struct presentation *p) } +int slide_number(struct presentation *p, struct slide *s) +{ + /* FIXME: Implement this */ + return 0; +} + + struct presentation *new_presentation() { struct presentation *new; @@ -215,8 +222,8 @@ struct presentation *new_presentation() /* Add one blank slide and view it */ new->num_slides = 0; new->slides = NULL; - new->view_slide = add_slide(new, 0); - new->view_slide_number = 0; + new->cur_edit_slide = add_slide(new, 0); + new->cur_proj_slide = NULL; new->editing_object = NULL; new->completely_empty = 1; diff --git a/src/presentation.h b/src/presentation.h index ed962a8..fdf36b3 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -37,12 +37,15 @@ struct slide { struct presentation *parent; - cairo_surface_t *render_cache; - int render_cache_seq; + /* Any of these may be NULL */ + cairo_surface_t *rendered_proj; + cairo_surface_t *rendered_edit; + + /* This should always be present (and up to date). */ + cairo_surface_t *rendered_thumb; int num_objects; struct object **objects; - int object_seq; }; @@ -108,6 +111,28 @@ struct presentation GtkIMContext *im_context; GtkWidget *tbox; + /* Pointers to the current "editing" and "projection" slides */ + struct slide *cur_edit_slide; + struct slide *cur_proj_slide; + + /* This is the "native" size of the slide. It only exists to give + * font size some meaning in the context of a somewhat arbitrary DPI */ + double slide_width; + double slide_height; + + /* Width of a slide in the editor, projector or thumbnail (pixels) */ + int edit_slide_width; + int proj_slide_width; + int thumb_slide_width; + + /* This is just to help with rendering the slides within the + * editing window. */ + double border_offs_x; + double border_offs_y; + + /* FIXME: Might have more than one object selected at a time. */ + struct object *editing_object; + /* Stylesheet */ StyleSheet *ss; struct style *default_style; @@ -122,16 +147,6 @@ struct presentation int ss_blank; char ss_geom[256]; - double slide_width; - double slide_height; - double border_offs_x; - double border_offs_y; - - /* The slide currently being displayed */ - unsigned int view_slide_number; - struct slide *view_slide; - struct object *editing_object; - /* Tool status */ struct toolinfo *cur_tool; @@ -166,4 +181,6 @@ extern void remove_object_from_slide(struct slide *s, struct object *o); extern struct object *find_object_at_position(struct slide *s, double x, double y); +extern int slide_number(struct presentation *p, struct slide *s); + #endif /* PRESENTATION_H */ diff --git a/src/slide_render.c b/src/slide_render.c index e68499a..c0734df 100644 --- a/src/slide_render.c +++ b/src/slide_render.c @@ -35,23 +35,22 @@ #include "stylesheet.h" -int render_slide(struct slide *s) +static cairo_surface_t *render_slide(struct slide *s, int w, int h) { cairo_surface_t *surf; cairo_t *cr; int i; - surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - s->parent->slide_width, - s->parent->slide_height); + surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); cr = cairo_create(surf); - cairo_rectangle(cr, 0.0, 0.0, - s->parent->slide_width, s->parent->slide_height); + cairo_rectangle(cr, 0.0, 0.0, w, h); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_fill(cr); + /* FIXME: Set scale such that nominal size fits */ + for ( i=0; inum_objects; i++ ) { struct object *o = s->objects[i]; @@ -62,20 +61,54 @@ int render_slide(struct slide *s) cairo_destroy(cr); - if ( s->render_cache != NULL ) cairo_surface_destroy(s->render_cache); - s->render_cache = surf; - s->render_cache_seq = s->object_seq; - - return 0; + return surf; } -void check_redraw_slide(struct slide *s) +void redraw_slide(struct slide *s) { - /* Update necessary? */ - if ( s->object_seq <= s->render_cache_seq ) return; + int w, h; + + if ( s->rendered_thumb != NULL ) { + cairo_surface_destroy(s->rendered_thumb); + } + + w = s->parent->thumb_slide_width; + h = (s->parent->slide_height/s->parent->slide_width) * w; + s->rendered_thumb = render_slide(s, w, h); + /* FIXME: Request redraw for slide sorter if open */ + + /* Is this slide currently open in the editor? */ + if ( s == s->parent->cur_edit_slide ) { + + if ( s->rendered_edit != NULL ) { + cairo_surface_destroy(s->rendered_edit); + } + + w = s->parent->edit_slide_width; + h = (s->parent->slide_height/s->parent->slide_width) * w; + s->rendered_edit = render_slide(s, w, h); - render_slide(s); + gdk_window_invalidate_rect(s->parent->drawingarea->window, + NULL, FALSE); + + } + + /* Is this slide currently being displayed on the projector? */ + if ( s == s->parent->cur_proj_slide ) { + + if ( s->rendered_proj != NULL ) { + cairo_surface_destroy(s->rendered_proj); + } + + w = s->parent->proj_slide_width; + h = (s->parent->slide_height/s->parent->slide_width) * w; + s->rendered_proj = render_slide(s, w, h); + + gdk_window_invalidate_rect(s->parent->ss_drawingarea->window, + NULL, FALSE); + + } } diff --git a/src/slide_render.h b/src/slide_render.h index 9b1cb02..ac3674d 100644 --- a/src/slide_render.h +++ b/src/slide_render.h @@ -30,8 +30,7 @@ #include "presentation.h" -extern int render_slide(struct slide *s); -extern void check_redraw_slide(struct slide *s); +extern void redraw_slide(struct slide *s); extern void draw_editing_box(cairo_t *cr, double xmin, double ymin, double width, double height); diff --git a/src/slideshow.c b/src/slideshow.c index f5e2fd1..d702513 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -51,8 +51,6 @@ static gboolean ss_expose_sig(GtkWidget *da, GdkEventExpose *event, GtkAllocation allocation; double xoff, yoff; - check_redraw_slide(p->view_slide); - cr = gdk_cairo_create(da->window); /* Overall background */ @@ -71,7 +69,7 @@ static gboolean ss_expose_sig(GtkWidget *da, GdkEventExpose *event, /* Draw the slide from the cache */ cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); - cairo_set_source_surface(cr, p->view_slide->render_cache, + cairo_set_source_surface(cr, p->cur_proj_slide->rendered_proj, xoff, yoff); cairo_fill(cr); @@ -91,14 +89,16 @@ void notify_slideshow_slide_changed(struct presentation *p) static gint prev_slide_sig(GtkWidget *widget, struct presentation *p) { - if ( p->view_slide_number == 0 ) return FALSE; + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_proj_slide); + + if ( cur_slide_number == 0 ) return FALSE; - p->view_slide_number--; p->ss_blank = 0; - p->view_slide = p->slides[p->view_slide_number]; + p->cur_proj_slide = p->slides[cur_slide_number-1]; notify_slideshow_slide_changed(p); - notify_slide_changed(p); return FALSE; } @@ -106,14 +106,16 @@ static gint prev_slide_sig(GtkWidget *widget, struct presentation *p) static gint next_slide_sig(GtkWidget *widget, struct presentation *p) { - if ( p->view_slide_number == p->num_slides-1 ) return FALSE; + int cur_slide_number; + + cur_slide_number = slide_number(p, p->cur_proj_slide); + + if ( cur_slide_number == p->num_slides-1 ) return FALSE; - p->view_slide_number++; p->ss_blank = 0; - p->view_slide = p->slides[p->view_slide_number]; + p->cur_proj_slide = p->slides[cur_slide_number+1]; notify_slideshow_slide_changed(p); - notify_slide_changed(p); return FALSE; } @@ -124,6 +126,7 @@ void end_slideshow(struct presentation *p) gtk_widget_destroy(p->ss_drawingarea); gtk_widget_destroy(p->slideshow); p->slideshow = NULL; + p->cur_proj_slide = NULL; notify_slide_changed(p); } @@ -214,4 +217,7 @@ void try_start_slideshow(struct presentation *p) p->slideshow = n; gtk_window_fullscreen(GTK_WINDOW(n)); gtk_widget_show_all(GTK_WIDGET(n)); + + p->cur_proj_slide = p->cur_edit_slide; + redraw_slide(p->cur_proj_slide); } diff --git a/src/tool_image.c b/src/tool_image.c index 09cc641..2baf7c3 100644 --- a/src/tool_image.c +++ b/src/tool_image.c @@ -86,6 +86,8 @@ static void update_image(struct image_object *o) o->scaled_pb = gdk_pixbuf_scale_simple(i->pb, w, h, GDK_INTERP_BILINEAR); } /* else the size didn't change */ + + redraw_slide(((struct object *)o)->parent); } @@ -153,7 +155,6 @@ struct object *add_image_object(struct slide *s, double x, double y, free(new); return NULL; } - s->object_seq++; update_image(new); @@ -228,10 +229,8 @@ static void end_drag(struct toolinfo *tip, struct presentation *p, o->bb_width = ti->box_width; o->bb_height = ti->box_height; update_image((struct image_object *)o); - o->parent->object_seq++; ti->drag_reason = IMAGE_DRAG_REASON_NONE; - redraw_overlay(p); } diff --git a/src/tool_select.c b/src/tool_select.c index 2327d0d..1fb66c7 100644 --- a/src/tool_select.c +++ b/src/tool_select.c @@ -76,10 +76,8 @@ static void drag(struct toolinfo *tip, struct presentation *p, if ( o->x+o->bb_width > eright ) o->x = eright - o->bb_width; if ( o->y+o->bb_height > ebottom ) o->y = ebottom - o->bb_height; - o->update_object(o); - p->view_slide->object_seq++; - - gdk_window_invalidate_rect(p->drawingarea->window, NULL, FALSE); + o->update_object(o); /* Object method is responsible for requesting + * a redraw */ } diff --git a/src/tool_text.c b/src/tool_text.c index 44a477b..8f18c7c 100644 --- a/src/tool_text.c +++ b/src/tool_text.c @@ -222,6 +222,8 @@ static void update_text(struct text_object *o) if ( o->furniture ) { calculate_position_from_style(o, eright, ebottom, mw, mh); } + + redraw_slide(((struct object *)o)->parent); } @@ -268,7 +270,6 @@ void insert_text(struct object *op, char *t) update_text(o); o->insertion_point += tlen; - o->base.parent->object_seq++; o->base.empty = 0; } @@ -322,9 +323,6 @@ void handle_text_backspace(struct object *op) if ( strlen(o->text) == 0 ) o->base.empty = 1; update_text(o); - o->base.parent->object_seq++; - - redraw_overlay(op->parent->parent); } @@ -431,7 +429,8 @@ static struct object *add_text_object(struct slide *s, double x, double y, delete_object((struct object *)new); return NULL; } - s->object_seq++; + + redraw_slide(((struct object *)new)->parent); return (struct object *)new; } @@ -516,10 +515,8 @@ static void end_drag(struct toolinfo *tip, struct presentation *p, o->bb_width = ti->box_width; o->bb_height = ti->box_height; update_text((struct text_object *)o); - o->parent->object_seq++; ti->drag_reason = TEXT_DRAG_REASON_NONE; - redraw_overlay(p); } @@ -530,7 +527,7 @@ static void create_default(struct presentation *p, struct style *sty, struct text_object *o; struct text_toolinfo *ti = (struct text_toolinfo *)tip; - n = add_text_object(p->view_slide, 0.0, 0.0, sty, ti); + n = add_text_object(p->cur_edit_slide, 0.0, 0.0, sty, ti); o = (struct text_object *)n; o->furniture = 1; update_text(o); @@ -545,7 +542,7 @@ static void create_region(struct toolinfo *tip, struct presentation *p, struct text_toolinfo *ti = (struct text_toolinfo *)tip; struct text_object *o; - n = add_text_object(p->view_slide, 0.0, 0.0, p->ss->styles[0], ti); + n = add_text_object(p->cur_edit_slide, 0.0, 0.0, p->ss->styles[0], ti); n->x = x1y = y1bb_width = fabs(x1-x2); -- cgit v1.2.3