diff options
author | Jason Crain <[email protected]> | 2013-06-15 10:43:08 -0500 |
---|---|---|
committer | raveit65 <[email protected]> | 2017-09-06 18:25:34 +0200 |
commit | d758271a60f8d081d1a0701b48d68981dcad9804 (patch) | |
tree | 69fad9b6afab351b7a7dbf358cec0226be8e5c12 | |
parent | b062ae0ca9eeb927a111a92bb9d41f3a77630f71 (diff) | |
download | atril-d758271a60f8d081d1a0701b48d68981dcad9804.tar.bz2 atril-d758271a60f8d081d1a0701b48d68981dcad9804.tar.xz |
libview: Draw selection highlight from region
Allows a fallback for backends which can implement get_selection_region
but not render_selection. Changes ev-pixbuf-cache so a redraw is only
done when the scale changes.
https://bugzilla.gnome.org/show_bug.cgi?id=669022
origin commit:
https://git.gnome.org/browse/evince/commit/?h=gnome-3-10&id=9e89fb1
-rw-r--r-- | libview/ev-pixbuf-cache.c | 47 | ||||
-rw-r--r-- | libview/ev-view-private.h | 3 | ||||
-rw-r--r-- | libview/ev-view.c | 71 |
3 files changed, 81 insertions, 40 deletions
diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c index 506d1316..4c890030 100644 --- a/libview/ev-pixbuf-cache.c +++ b/libview/ev-pixbuf-cache.c @@ -27,6 +27,7 @@ typedef struct _CacheJobInfo cairo_surface_t *selection; cairo_region_t *selection_region; + gdouble selection_scale; } CacheJobInfo; struct _EvPixbufCache @@ -287,6 +288,7 @@ 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->points_set = TRUE; @@ -632,21 +634,17 @@ ev_pixbuf_cache_clear_job_sizes (EvPixbufCache *pixbuf_cache, } static void -get_selection_colors (GtkWidget *widget, GdkColor *text, GdkColor *base) +get_selection_colors (EvView *view, GdkColor *text, GdkColor *base) { - GtkStyleContext *context = gtk_widget_get_style_context (widget); - GtkStateFlags state = 0; - GdkRGBA fg, bg; + GdkRGBA fg, bg; - state |= gtk_widget_has_focus (widget) ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_ACTIVE; + _ev_view_get_selection_colors (view, &bg, &fg); - gtk_style_context_get_color (context, state, &fg); text->pixel = 0; text->red = CLAMP ((guint) (fg.red * 65535), 0, 65535); text->green = CLAMP ((guint) (fg.green * 65535), 0, 65535); text->blue = CLAMP ((guint) (fg.blue * 65535), 0, 65535); - gtk_style_context_get_background_color (context, state, &bg); base->pixel = 0; base->red = CLAMP ((guint) (bg.red * 65535), 0, 65535); base->green = CLAMP ((guint) (bg.green * 65535), 0, 65535); @@ -679,7 +677,8 @@ add_job (EvPixbufCache *pixbuf_cache, if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) { GdkColor text, base; - get_selection_colors (pixbuf_cache->view, &text, &base); + + get_selection_colors (EV_VIEW (pixbuf_cache->view), &text, &base); ev_job_render_set_selection_info (EV_JOB_RENDER (job_info->job), &(job_info->target_points), job_info->selection_style, @@ -864,24 +863,8 @@ new_selection_surface_needed (EvPixbufCache *pixbuf_cache, gint page, gfloat scale) { - if (job_info->selection) { - gint width, height; - gint selection_width, selection_height; - - _get_page_size_for_scale_and_rotation (pixbuf_cache->document, - page, scale, 0, - &width, &height); - - selection_width = cairo_image_surface_get_width (job_info->selection); - selection_height = cairo_image_surface_get_height (job_info->selection); - - if (width != selection_width || height != selection_height) - return TRUE; - } else { - if (job_info->points_set) - return TRUE; - } - + if (job_info->selection || job_info->points_set) + return job_info->selection_scale != scale; return FALSE; } @@ -936,12 +919,14 @@ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache) if (job_info->selection) { cairo_surface_destroy (job_info->selection); job_info->selection = NULL; + job_info->selection_points.x1 = -1; } job_info = pixbuf_cache->next_job + i; if (job_info->selection) { cairo_surface_destroy (job_info->selection); job_info->selection = NULL; + job_info->selection_points.x1 = -1; } } @@ -952,6 +937,7 @@ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache) if (job_info->selection) { cairo_surface_destroy (job_info->selection); job_info->selection = NULL; + job_info->selection_points.x1 = -1; } } } @@ -979,8 +965,11 @@ 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 (job_info->job && EV_JOB_RENDER (job_info->job)->include_selection) { + if (region) + *region = job_info->selection_region; return job_info->selection; + } /* Now, lets see if we need to resize the image. If we do, we clear the * old one. */ @@ -1003,7 +992,6 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, g_assert (job_info->selection == NULL); old_points = NULL; } else { - g_assert (job_info->selection != NULL); old_points = &(job_info->selection_points); } @@ -1018,7 +1006,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, rc, job_info->selection_style, &(job_info->target_points)); - get_selection_colors (pixbuf_cache->view, &text, &base); + get_selection_colors (EV_VIEW (pixbuf_cache->view), &text, &base); ev_selection_render_selection (EV_SELECTION (pixbuf_cache->document), rc, &(job_info->selection), @@ -1028,6 +1016,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache, &text, &base); set_device_scale_on_surface (job_info->selection, job_info->device_scale); job_info->selection_points = job_info->target_points; + job_info->selection_scale = scale; g_object_unref (rc); ev_document_doc_mutex_unlock (); } diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index abdd43b7..3ec1f790 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -278,6 +278,9 @@ void _ev_view_transform_doc_rect_to_view_rect (EvView *view, int page, EvRectangle *doc_rect, GdkRectangle *view_rect); +void _ev_view_get_selection_colors (EvView *view, + GdkRGBA *bg_color, + GdkRGBA *fg_color); void _ev_view_set_focused_element (EvView *view, EvMapping *element_mapping, diff --git a/libview/ev-view.c b/libview/ev-view.c index 50838662..99604221 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -5469,6 +5469,45 @@ draw_surface (cairo_t *cr, cairo_restore (cr); } +void +_ev_view_get_selection_colors (EvView *view, + GdkRGBA *bg_color, + GdkRGBA *fg_color) +{ + GtkWidget *widget = GTK_WIDGET (view); + GtkStateFlags state; + GtkStyleContext *context; + + state = gtk_widget_has_focus (widget) ? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_ACTIVE; + context = gtk_widget_get_style_context (widget); + + if (bg_color) + gtk_style_context_get_background_color (context, state, bg_color); + + if (fg_color) + gtk_style_context_get_color (context, state, fg_color); +} + +static void +draw_selection_region (cairo_t *cr, + cairo_region_t *region, + GdkRGBA *color, + gint x, + gint y, + gdouble scale_x, + gdouble scale_y) +{ + cairo_save (cr); + cairo_translate (cr, x, y); + cairo_scale (cr, scale_x, scale_y); + gdk_cairo_region (cr, region); + cairo_set_source_rgb (cr, color->red, color->green, color->blue); + cairo_set_operator (cr, CAIRO_OPERATOR_MULTIPLY); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + cairo_fill (cr); + cairo_restore (cr); +} + static void draw_one_page (EvView *view, gint page, @@ -5510,6 +5549,7 @@ draw_one_page (EvView *view, cairo_surface_t *page_surface = NULL; cairo_surface_t *selection_surface = NULL; gint offset_x, offset_y; + cairo_region_t *region = NULL; double device_scale_x = 1, device_scale_y = 1; page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page); @@ -5535,22 +5575,31 @@ draw_one_page (EvView *view, offset_y = overlap.y - real_page_area.y; draw_surface (cr, page_surface, overlap.x, overlap.y, offset_x, offset_y, width, height); - + /* Get the selection pixbuf iff we have something to draw */ - if (find_selection_for_page (view, page) && - view->selection_mode == EV_VIEW_SELECTION_TEXT) { - selection_surface = - ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache, - page, - view->scale, - NULL); - } + if (!find_selection_for_page (view, page)) + return; - if (!selection_surface) { + selection_surface = ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache, + page, + view->scale, + ®ion); + if (selection_surface) { + draw_surface (cr, selection_surface, overlap.x, overlap.y, offset_x, offset_y, + width, height); return; } - draw_surface (cr, selection_surface, overlap.x, overlap.y, offset_x, offset_y, width, height); + if (region) { + double scale_x, scale_y; + GdkRGBA color; + + scale_x = (gdouble)width / cairo_image_surface_get_width (page_surface); + scale_y = (gdouble)height / cairo_image_surface_get_height (page_surface); + _ev_view_get_selection_colors (view, &color, NULL); + draw_selection_region (cr, region, &color, real_page_area.x, real_page_area.y, + scale_x, scale_y); + } } } |