summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libview/ev-pixbuf-cache.c123
-rw-r--r--libview/ev-pixbuf-cache.h6
-rw-r--r--libview/ev-view.c18
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,
- &region);
+ 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);
}