summaryrefslogtreecommitdiff
path: root/libview/ev-pixbuf-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libview/ev-pixbuf-cache.c')
-rw-r--r--libview/ev-pixbuf-cache.c123
1 files changed, 98 insertions, 25 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)