[evince] debug: Add support for drawing different debug borders in EvView



commit f95607dd4b4be7174950f57c6c8f99d67aa0e019
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Thu Jul 11 15:33:18 2013 +0200

    debug: Add support for drawing different debug borders in EvView
    
    When evince is built with debug support, the env variable
    EV_DEBUG_SHOW_BORDERS can be used to draw different debug borders in
    EvView using different colors. Depending on the value of the env
    variable and and the features supported by the current backend, it can
    draw bounding boxes of characters, links, images, form fields,
    annotations and selection region.

 libdocument/ev-debug.c |   54 ++++++++++++++
 libdocument/ev-debug.h |   18 ++++-
 libview/ev-view.c      |  185 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 255 insertions(+), 2 deletions(-)
---
diff --git a/libdocument/ev-debug.c b/libdocument/ev-debug.c
index 344510f..475f612 100644
--- a/libdocument/ev-debug.c
+++ b/libdocument/ev-debug.c
@@ -37,15 +37,60 @@
 #endif
 
 #include <stdio.h>
+#include <string.h>
 
 #include "ev-debug.h"
 
 #ifdef EV_ENABLE_DEBUG
 static EvDebugSection ev_debug = EV_NO_DEBUG;
 static EvProfileSection ev_profile = EV_NO_PROFILE;
+static EvDebugBorders ev_debug_borders = EV_DEBUG_BORDER_NONE;
 
 static GHashTable *timers = NULL;
 
+static gboolean
+ev_debug_parse_show_borders (const gchar *show_debug_borders)
+{
+        gchar **items;
+        guint   i;
+
+        if (!show_debug_borders)
+                return FALSE;
+
+        items = g_strsplit (show_debug_borders, ",", -1);
+        if (!items)
+                return FALSE;
+
+        for (i = 0; items[i]; i++) {
+                if (g_strcmp0 (items[i], "all") == 0) {
+                        ev_debug_borders = EV_DEBUG_BORDER_ALL;
+                        break;
+                }
+
+                if (g_strcmp0 (items[i], "none") == 0) {
+                        ev_debug_borders = EV_DEBUG_BORDER_NONE;
+                        break;
+                }
+
+                if (strcmp (items[i], "chars") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_CHARS;
+                if (strcmp (items[i], "links") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_LINKS;
+                if (strcmp (items[i], "forms") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_FORMS;
+                if (strcmp (items[i], "annots") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_ANNOTS;
+                if (strcmp (items[i], "images") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_IMAGES;
+                if (strcmp (items[i], "selections") == 0)
+                        ev_debug_borders |= EV_DEBUG_BORDER_SELECTIONS;
+        }
+
+        g_strfreev (items);
+
+        return ev_debug_borders != EV_DEBUG_BORDER_NONE;
+}
+
 static void
 debug_init (void)
 {
@@ -57,6 +102,9 @@ debug_init (void)
 
        if (g_getenv ("EV_DEBUG_JOBS") != NULL)
                ev_debug |= EV_DEBUG_JOBS;
+
+        if (ev_debug_parse_show_borders (g_getenv ("EV_DEBUG_SHOW_BORDERS")))
+                ev_debug |= EV_DEBUG_SHOW_BORDERS;
 }
 
 static void
@@ -174,4 +222,10 @@ ev_profiler_stop (EvProfileSection section,
        }
 }
 
+EvDebugBorders
+ev_debug_get_debug_borders (void)
+{
+        return ev_debug_borders;
+}
+
 #endif /* EV_ENABLE_DEBUG */
diff --git a/libdocument/ev-debug.h b/libdocument/ev-debug.h
index cf25243..dff1028 100644
--- a/libdocument/ev-debug.h
+++ b/libdocument/ev-debug.h
@@ -71,10 +71,22 @@ G_BEGIN_DECLS
  * sections.
  */
 typedef enum {
-       EV_NO_DEBUG          = 0,
-       EV_DEBUG_JOBS        = 1 << 0
+       EV_NO_DEBUG           = 0,
+       EV_DEBUG_JOBS         = 1 << 0,
+        EV_DEBUG_SHOW_BORDERS = 1 << 1
 } EvDebugSection;
 
+typedef enum {
+        EV_DEBUG_BORDER_NONE       = 0,
+        EV_DEBUG_BORDER_CHARS      = 1 << 0,
+        EV_DEBUG_BORDER_LINKS      = 1 << 1,
+        EV_DEBUG_BORDER_FORMS      = 1 << 2,
+        EV_DEBUG_BORDER_ANNOTS     = 1 << 3,
+        EV_DEBUG_BORDER_IMAGES     = 1 << 4,
+        EV_DEBUG_BORDER_SELECTIONS = 1 << 5,
+        EV_DEBUG_BORDER_ALL        = (1 << 6) - 1
+} EvDebugBorders;
+
 #define DEBUG_JOBS      EV_DEBUG_JOBS,    __FILE__, __LINE__, G_STRFUNC
 
 /*
@@ -100,6 +112,8 @@ void ev_profiler_start (EvProfileSection section,
 void ev_profiler_stop  (EvProfileSection section,
                        const gchar     *format, ...) G_GNUC_PRINTF(2, 3);
 
+EvDebugBorders ev_debug_get_debug_borders (void);
+
 G_END_DECLS
 
 #endif /* EV_ENABLE_DEBUG */
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 60381f6..6c8d2d9 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -43,6 +43,7 @@
 #include "ev-view-accessible.h"
 #include "ev-view-private.h"
 #include "ev-view-type-builtins.h"
+#include "ev-debug.h"
 
 #define EV_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
 #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW))
@@ -3817,6 +3818,186 @@ should_draw_caret_cursor (EvView  *view,
                !ev_pixbuf_cache_get_selection_region (view->pixbuf_cache, page, view->scale));
 }
 
+#ifdef EV_ENABLE_DEBUG
+static void
+stroke_view_rect (cairo_t      *cr,
+                 GdkRectangle *clip,
+                 GdkRectangle *view_rect)
+{
+       GdkRectangle intersect;
+
+       if (gdk_rectangle_intersect (view_rect, clip, &intersect)) {
+               cairo_rectangle (cr,
+                                intersect.x, intersect.y,
+                                intersect.width, intersect.height);
+               cairo_stroke (cr);
+       }
+}
+
+static void
+stroke_doc_rect (EvView       *view,
+                cairo_t      *cr,
+                gint          page,
+                GdkRectangle *clip,
+                EvRectangle  *doc_rect)
+{
+       GdkRectangle view_rect;
+
+       _ev_view_transform_doc_rect_to_view_rect (view, page, doc_rect, &view_rect);
+       view_rect.x -= view->scroll_x;
+       view_rect.y -= view->scroll_y;
+       stroke_view_rect (cr, clip, &view_rect);
+}
+
+static void
+show_chars_border (EvView       *view,
+                  cairo_t      *cr,
+                  gint          page,
+                  GdkRectangle *clip)
+{
+       EvRectangle *areas = NULL;
+       guint        n_areas = 0;
+       guint        i;
+
+       ev_page_cache_get_text_layout (view->page_cache, page, &areas, &n_areas);
+       if (!areas)
+               return;
+
+       cairo_set_source_rgb (cr, 1., 0., 0.);
+
+       for (i = 0; i < n_areas; i++) {
+               EvRectangle  *doc_rect = areas + i;
+
+               stroke_doc_rect (view, cr, page, clip, doc_rect);
+       }
+}
+
+static void
+show_mapping_list_border (EvView        *view,
+                         cairo_t       *cr,
+                         gint           page,
+                         GdkRectangle  *clip,
+                         EvMappingList *mapping_list)
+{
+       GList *l;
+
+       for (l = ev_mapping_list_get_list (mapping_list); l; l = g_list_next (l)) {
+               EvMapping *mapping = (EvMapping *)l->data;
+
+               stroke_doc_rect (view, cr, page, clip, &mapping->area);
+       }
+}
+
+static void
+show_links_border (EvView       *view,
+                  cairo_t      *cr,
+                  gint          page,
+                  GdkRectangle *clip)
+{
+       cairo_set_source_rgb (cr, 0., 0., 1.);
+       show_mapping_list_border (view,cr, page, clip,
+                                 ev_page_cache_get_link_mapping (view->page_cache, page));
+}
+
+static void
+show_forms_border (EvView       *view,
+                  cairo_t      *cr,
+                  gint          page,
+                  GdkRectangle *clip)
+{
+       cairo_set_source_rgb (cr, 0., 1., 0.);
+       show_mapping_list_border (view, cr, page, clip,
+                                 ev_page_cache_get_form_field_mapping (view->page_cache, page));
+}
+
+static void
+show_annots_border (EvView       *view,
+                   cairo_t      *cr,
+                   gint          page,
+                   GdkRectangle *clip)
+{
+       cairo_set_source_rgb (cr, 0., 1., 1.);
+       show_mapping_list_border (view, cr, page, clip,
+                                 ev_page_cache_get_annot_mapping (view->page_cache, page));
+}
+
+static void
+show_images_border (EvView       *view,
+                   cairo_t      *cr,
+                   gint          page,
+                   GdkRectangle *clip)
+{
+       cairo_set_source_rgb (cr, 1., 0., 1.);
+       show_mapping_list_border (view, cr, page, clip,
+                                 ev_page_cache_get_image_mapping (view->page_cache, page));
+}
+
+static void
+show_selections_border (EvView       *view,
+                       cairo_t      *cr,
+                       gint          page,
+                       GdkRectangle *clip)
+{
+       cairo_region_t *region;
+       guint           i, n_rects;
+       GdkRectangle    page_area;
+       GtkBorder       border;
+
+       region = ev_page_cache_get_text_mapping (view->page_cache, page);
+       if (!region)
+               return;
+
+       cairo_set_source_rgb (cr, 0.75, 0.50, 0.25);
+
+       ev_view_get_page_extents (view, page, &page_area, &border);
+
+       region = cairo_region_copy (region);
+       cairo_region_intersect_rectangle (region, clip);
+       n_rects = cairo_region_num_rectangles (region);
+       for (i = 0; i < n_rects; i++) {
+               GdkRectangle view_rect;
+
+               cairo_region_get_rectangle (region, i, &view_rect);
+               view_rect.x = (gint)(view_rect.x * view->scale + 0.5);
+               view_rect.y = (gint)(view_rect.y * view->scale + 0.5);
+               view_rect.width = (gint)(view_rect.width * view->scale + 0.5);
+               view_rect.height = (gint)(view_rect.height * view->scale + 0.5);
+
+               view_rect.x += page_area.x + border.left - view->scroll_x;
+               view_rect.y += page_area.y + border.right - view->scroll_y;
+               stroke_view_rect (cr, clip, &view_rect);
+       }
+       cairo_region_destroy (region);
+}
+
+static void
+draw_debug_borders (EvView       *view,
+                   cairo_t      *cr,
+                   gint          page,
+                   GdkRectangle *clip)
+{
+       EvDebugBorders borders = ev_debug_get_debug_borders();
+
+       cairo_save (cr);
+       cairo_set_line_width (cr, 0.5);
+
+       if (borders & EV_DEBUG_BORDER_CHARS)
+               show_chars_border (view, cr, page, clip);
+       if (borders & EV_DEBUG_BORDER_LINKS)
+               show_links_border (view, cr, page, clip);
+       if (borders & EV_DEBUG_BORDER_FORMS)
+               show_forms_border (view, cr, page, clip);
+       if (borders & EV_DEBUG_BORDER_ANNOTS)
+               show_annots_border (view, cr, page, clip);
+       if (borders & EV_DEBUG_BORDER_IMAGES)
+               show_images_border (view, cr, page, clip);
+       if (borders & EV_DEBUG_BORDER_SELECTIONS)
+               show_selections_border (view, cr, page, clip);
+
+       cairo_restore (cr);
+}
+#endif
+
 static gboolean
 ev_view_draw (GtkWidget *widget,
               cairo_t   *cr)
@@ -3860,6 +4041,10 @@ ev_view_draw (GtkWidget *widget,
                         focus_annotation (view, cr, i, &clip_rect);
                if (page_ready && view->synctex_result)
                        highlight_forward_search_results (view, cr, i);
+#ifdef EV_ENABLE_DEBUG
+               if (page_ready)
+                       draw_debug_borders (view, cr, i, &clip_rect);
+#endif
        }
 
         if (GTK_WIDGET_CLASS (ev_view_parent_class)->draw)


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