# HG changeset patch
# User Thomas Liebetraut <thomas@tommie-lie.de>
# Date 1396178635 -7200
#      Sun Mar 30 13:23:55 2014 +0200
# Node ID b57f18696badeb88f1032db9e2dd2b577d606b0d
# Parent  b8bcc5b4217c48ebe222ef43e53d93be1e617818
Add support for interactive areas in annotations.

Some annotation types do not have a rectangular shape
and require non-rectangular boundary checks to determine
if the user clicked on them.

A new method ev_annotation_is_location_in_area() is added
that determines whether a point location is actually
inside the annotation's interactive area.

diff -r b8bcc5b4217c -r b57f18696bad libdocument/ev-annotation.c
--- a/libdocument/ev-annotation.c	Sun Mar 30 13:23:55 2014 +0200
+++ b/libdocument/ev-annotation.c	Sun Mar 30 13:23:55 2014 +0200
@@ -40,6 +40,10 @@
 
 struct _EvAnnotationClass {
 	GObjectClass parent_class;
+
+	gboolean (* is_location_in_area) (EvAnnotation *annot,
+			                  gdouble       x,
+			                  gdouble       y);
 };
 
 struct _EvAnnotationMarkupInterface {
@@ -152,6 +156,26 @@
 	annot->type = EV_ANNOTATION_TYPE_UNKNOWN;
 }
 
+static gboolean
+ev_annotation_impl_is_location_in_area (EvAnnotation *annot,
+				   gdouble       x,
+				   gdouble       y)
+{
+        g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
+
+        /* fall back to bound rectangle */
+	EvRectangle rect;
+	ev_annotation_get_bounding_rectangle (annot, &rect);
+	if ((x >= rect.x1) &&
+	    (x <= rect.x2) &&
+	    (y >= rect.y1) &&
+	    (y <= rect.y2)) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 static void
 ev_annotation_set_property (GObject      *object,
 			    guint         prop_id,
@@ -228,6 +252,8 @@
 {
 	GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
 
+	klass->is_location_in_area = ev_annotation_impl_is_location_in_area;
+
 	g_object_class->finalize = ev_annotation_finalize;
 	g_object_class->set_property = ev_annotation_set_property;
 	g_object_class->get_property = ev_annotation_get_property;
@@ -684,6 +710,19 @@
         return TRUE;
 }
 
+gboolean
+ev_annotation_is_location_in_area (EvAnnotation *annot,
+				   gdouble       x,
+				   gdouble       y)
+{
+	g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
+
+	EvAnnotationClass *klass = EV_ANNOTATION_GET_CLASS (annot);
+
+	return klass->is_location_in_area (annot, x, y);
+}
+
+
 /* EvAnnotationMarkup */
 typedef struct {
 	gchar   *label;
diff -r b8bcc5b4217c -r b57f18696bad libdocument/ev-annotation.h
--- a/libdocument/ev-annotation.h	Sun Mar 30 13:23:55 2014 +0200
+++ b/libdocument/ev-annotation.h	Sun Mar 30 13:23:55 2014 +0200
@@ -129,6 +129,9 @@
                                                               EvRectangle            *rect);
 gboolean             ev_annotation_set_bounding_rectangle    (EvAnnotation           *annot,
                                                               const EvRectangle      *rect);
+gboolean             ev_annotation_is_location_in_area       (EvAnnotation           *annot,
+                                                              gdouble                 x,
+                                                              gdouble                 y);
 
 /* EvAnnotationMarkup */
 GType                ev_annotation_markup_get_type           (void) G_GNUC_CONST;
diff -r b8bcc5b4217c -r b57f18696bad libdocument/ev-mapping-list.c
--- a/libdocument/ev-mapping-list.c	Sun Mar 30 13:23:55 2014 +0200
+++ b/libdocument/ev-mapping-list.c	Sun Mar 30 13:23:55 2014 +0200
@@ -19,6 +19,7 @@
  */
 
 #include "ev-mapping-list.h"
+#include "ev-annotation.h"
 
 /**
  * SECTION: ev-mapping-list
@@ -121,10 +122,15 @@
 	for (list = mapping_list->list; list; list = list->next) {
 		EvMapping *mapping = list->data;
 
-		if ((x >= mapping->area.x1) &&
-		    (y >= mapping->area.y1) &&
-		    (x <= mapping->area.x2) &&
-		    (y <= mapping->area.y2)) {
+		if (EV_IS_ANNOTATION(mapping->data)) {
+			if (ev_annotation_is_location_in_area (
+					EV_ANNOTATION(mapping->data), x, y)) {
+				return mapping;
+			}
+		} else if ((x >= mapping->area.x1) &&
+			   (y >= mapping->area.y1) &&
+			   (x <= mapping->area.x2) &&
+			   (y <= mapping->area.y2)) {
 			return mapping;
 		}
 	}
