diff options
-rw-r--r-- | libview/ev-pixbuf-cache.c | 123 | ||||
-rw-r--r-- | libview/ev-pixbuf-cache.h | 6 | ||||
-rw-r--r-- | libview/ev-view.c | 18 |
3 files changed, 111 insertions, 36 deletions
diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c index 4c890030..542775d0 100644 --- a/libview/ev-pixbuf-cache.c +++ b/libview/ev-pixbuf-cache.c @@ -20,14 +20,17 @@ typedef struct _CacheJobInfo /* Selection data. * Selection_points are the coordinates encapsulated in selection. * target_points is the target selection size. */ - EvRectangle selection_points; EvRectangle target_points; EvSelectionStyle selection_style; gboolean points_set; cairo_surface_t *selection; - cairo_region_t *selection_region; gdouble selection_scale; + EvRectangle selection_points; + + cairo_region_t *selection_region; + gdouble selection_region_scale; + EvRectangle selection_region_points; } CacheJobInfo; struct _EvPixbufCache @@ -286,11 +289,15 @@ copy_job_to_job_info (EvJobRender *job_render, } job_info->selection_points = job_render->selection_points; - job_info->selection_region = cairo_region_reference (job_render->selection_region); job_info->selection = cairo_surface_reference (job_render->selection); job_info->selection_scale = job_render->scale; set_device_scale_on_surface (job_info->selection, job_info->device_scale); g_assert (job_info->selection_points.x1 >= 0); + + job_info->selection_region_points = job_render->selection_points; + job_info->selection_region = cairo_region_reference (job_render->selection_region); + job_info->selection_region_scale = job_render->scale; + job_info->points_set = TRUE; } @@ -868,11 +875,22 @@ new_selection_surface_needed (EvPixbufCache *pixbuf_cache, return FALSE; } +static gboolean +new_selection_region_needed (EvPixbufCache *pixbuf_cache, + CacheJobInfo *job_info, + gint page, + gfloat scale) +{ + if (job_info->selection_region || job_info->points_set) + return job_info->selection_region_scale != scale; + return FALSE; +} + static void -clear_selection_if_needed (EvPixbufCache *pixbuf_cache, - CacheJobInfo *job_info, - gint page, - gfloat scale) +clear_selection_surface_if_needed (EvPixbufCache *pixbuf_cache, + CacheJobInfo *job_info, + gint page, + gfloat scale) { if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) { if (job_info->selection) @@ -882,6 +900,20 @@ clear_selection_if_needed (EvPixbufCache *pixbuf_cache, } } +static void +clear_selection_region_if_needed (EvPixbufCache *pixbuf_cache, + CacheJobInfo *job_info, + gint page, + gfloat scale) +{ + if (new_selection_region_needed (pixbuf_cache, job_info, page, scale)) { + if (job_info->selection_region) + cairo_region_destroy (job_info->selection_region); + job_info->selection_region = NULL; + job_info->selection_region_points.x1 = -1; + } +} + /* Clears the cache of jobs and pixbufs. */ void @@ -944,9 +976,8 @@ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache) cairo_surface_t * ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, - gint page, - gfloat scale, - cairo_region_t **region) + gint page, + gfloat scale) { CacheJobInfo *job_info; @@ -965,15 +996,12 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, /* If we have a running job, we just return what we have under the * assumption that it'll be updated later and we can scale it as need * be */ - if (job_info->job && EV_JOB_RENDER (job_info->job)->include_selection) { - if (region) - *region = job_info->selection_region; + if (job_info->job && EV_JOB_RENDER (job_info->job)->include_selection) return job_info->selection; - } /* Now, lets see if we need to resize the image. If we do, we clear the * old one. */ - clear_selection_if_needed (pixbuf_cache, job_info, page, scale * job_info->device_scale); + clear_selection_surface_if_needed (pixbuf_cache, job_info, page, scale); /* Finally, we see if the two scales are the same, and get a new pixbuf * if needed. We do this synchronously for now. At some point, we @@ -999,15 +1027,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, rc = ev_render_context_new (ev_page, 0, scale * job_info->device_scale); g_object_unref (ev_page); - if (job_info->selection_region) - cairo_region_destroy (job_info->selection_region); - job_info->selection_region = - ev_selection_get_selection_region (EV_SELECTION (pixbuf_cache->document), - rc, job_info->selection_style, - &(job_info->target_points)); - get_selection_colors (EV_VIEW (pixbuf_cache->view), &text, &base); - ev_selection_render_selection (EV_SELECTION (pixbuf_cache->document), rc, &(job_info->selection), &(job_info->target_points), @@ -1020,11 +1040,64 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, g_object_unref (rc); ev_document_doc_mutex_unlock (); } - if (region) - *region = job_info->selection_region; return job_info->selection; } +cairo_region_t * +ev_pixbuf_cache_get_selection_region (EvPixbufCache *pixbuf_cache, + gint page, + gfloat scale) +{ + CacheJobInfo *job_info; + + /* the document does not implement the selection interface */ + if (!EV_IS_SELECTION (pixbuf_cache->document)) + return NULL; + + job_info = find_job_cache (pixbuf_cache, page); + if (job_info == NULL) + return NULL; + + /* No selection on this page */ + if (!job_info->points_set) + return NULL; + + /* If we have a running job, we just return what we have under the + * assumption that it'll be updated later and we can scale it as need + * be */ + if (job_info->job && EV_JOB_RENDER (job_info->job)->include_selection) + return job_info->selection_region; + + /* Now, lets see if we need to resize the region. If we do, we clear the + * old one. */ + clear_selection_region_if_needed (pixbuf_cache, job_info, page, scale); + + /* Finally, we see if the two scales are the same, and get a new region + * if needed. + */ + if (ev_rect_cmp (&(job_info->target_points), &(job_info->selection_region_points))) { + EvRenderContext *rc; + EvPage *ev_page; + + ev_document_doc_mutex_lock (); + ev_page = ev_document_get_page (pixbuf_cache->document, page); + rc = ev_render_context_new (ev_page, 0, scale); + g_object_unref (ev_page); + + if (job_info->selection_region) + cairo_region_destroy (job_info->selection_region); + job_info->selection_region = + ev_selection_get_selection_region (EV_SELECTION (pixbuf_cache->document), + rc, job_info->selection_style, + &(job_info->target_points)); + job_info->selection_region_points = job_info->target_points; + job_info->selection_region_scale = scale; + g_object_unref (rc); + ev_document_doc_mutex_unlock (); + } + return job_info->selection_region; +} + static void update_job_selection (CacheJobInfo *job_info, EvViewSelection *selection) diff --git a/libview/ev-pixbuf-cache.h b/libview/ev-pixbuf-cache.h index a20b7518..5617ca9b 100644 --- a/libview/ev-pixbuf-cache.h +++ b/libview/ev-pixbuf-cache.h @@ -78,8 +78,10 @@ void ev_pixbuf_cache_set_inverted_colors (EvPixbufCache *pixbuf_cache /* Selection */ cairo_surface_t *ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, gint page, - gfloat scale, - cairo_region_t **region); + gfloat scale); +cairo_region_t *ev_pixbuf_cache_get_selection_region (EvPixbufCache *pixbuf_cache, + gint page, + gfloat scale); void ev_pixbuf_cache_set_selection_list (EvPixbufCache *pixbuf_cache, GList *selection_list); GList *ev_pixbuf_cache_get_selection_list (EvPixbufCache *pixbuf_cache); diff --git a/libview/ev-view.c b/libview/ev-view.c index 99604221..e4a351f8 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -5581,15 +5581,17 @@ draw_one_page (EvView *view, return; selection_surface = ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache, - page, - view->scale, - ®ion); + page, + view->scale); if (selection_surface) { draw_surface (cr, selection_surface, overlap.x, overlap.y, offset_x, offset_y, width, height); return; } + region = ev_pixbuf_cache_get_selection_region (view->pixbuf_cache, + page, + view->scale); if (region) { double scale_x, scale_y; GdkRGBA color; @@ -7362,13 +7364,11 @@ merge_selection_region (EvView *view, /* seed the cache with a new page. We are going to need the new * region too. */ if (new_sel) { - cairo_region_t *tmp_region = NULL; - - ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache, - cur_page, - view->scale, - &tmp_region); + cairo_region_t *tmp_region; + tmp_region = ev_pixbuf_cache_get_selection_region (view->pixbuf_cache, + cur_page, + view->scale); if (tmp_region && !cairo_region_is_empty (tmp_region)) { new_sel->covered_region = cairo_region_reference (tmp_region); } |