[evince] libview: Draw selection highlight from region



commit 9e89fb122fd02abcb1a9f5b57d92ea20e325f1ad
Author: Jason Crain <jason aquaticape us>
Date:   Sat Jun 15 10:43:08 2013 -0500

    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

 libview/ev-pixbuf-cache.c |   46 +++++++++++------------------
 libview/ev-view-private.h |    3 ++
 libview/ev-view.c         |   71 ++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 80 insertions(+), 40 deletions(-)
---
diff --git a/libview/ev-pixbuf-cache.c b/libview/ev-pixbuf-cache.c
index 98719a3..8f81481 100644
--- a/libview/ev-pixbuf-cache.c
+++ b/libview/ev-pixbuf-cache.c
@@ -24,6 +24,7 @@ typedef struct _CacheJobInfo
        
        cairo_surface_t *selection;
        cairo_region_t  *selection_region;
+       gdouble          selection_scale;
 } CacheJobInfo;
 
 struct _EvPixbufCache
@@ -262,6 +263,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;
                g_assert (job_info->selection_points.x1 >= 0);
                job_info->points_set = TRUE;
        }
@@ -602,21 +604,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);
@@ -647,7 +645,7 @@ 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,
@@ -830,24 +828,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;
 }
 
@@ -902,12 +884,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;
                }
        }
 
@@ -918,6 +902,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;
                }
        }
 }
@@ -945,8 +930,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. */
@@ -969,7 +957,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);
                }
 
@@ -984,7 +971,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),
@@ -993,6 +980,7 @@ ev_pixbuf_cache_get_selection_surface (EvPixbufCache   *pixbuf_cache,
                                               job_info->selection_style,
                                               &text, &base);
                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 ebf6a0a..45d1079 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -260,6 +260,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);
 
 #endif  /* __EV_VIEW_PRIVATE_H__ */
 
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 8b3d794..6c99038 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -5183,6 +5183,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,
@@ -5231,6 +5270,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;
 
                page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
 
@@ -5251,22 +5291,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,
+                                                                          &region);
+               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);
+               }
        }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]