# HG changeset patch # User Thomas Liebetraut # Date 1396195767 -7200 # Sun Mar 30 18:09:27 2014 +0200 # Node ID 48de07d940ed928d89b67b4d47bc53b8adb65622 # Parent eee239b048d4aca26cf7b59bba4a5cafd4dfb3a4 Add EvAnnotationTextMarkup class. This base class should be used for all text markup annotations like text highlighting, underlining, etc. diff -r eee239b048d4 -r 48de07d940ed 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 18:09:27 2014 +0200 @@ -71,9 +71,20 @@ EvAnnotationClass parent_class; }; -static void ev_annotation_markup_default_init (EvAnnotationMarkupInterface *iface); -static void ev_annotation_text_markup_iface_init (EvAnnotationMarkupInterface *iface); -static void ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface); +struct _EvAnnotationTextMarkup { + EvAnnotation parent; + + GArray *quadrilaterals; +}; + +struct _EvAnnotationTextMarkupClass { + EvAnnotationClass parent_class; +}; + +static void ev_annotation_markup_default_init (EvAnnotationMarkupInterface *iface); +static void ev_annotation_text_markup_iface_init (EvAnnotationMarkupInterface *iface); +static void ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface); +static void ev_annotation_text_markup_markup_iface_init (EvAnnotationMarkupInterface *iface); /* EvAnnotation */ enum { @@ -108,6 +119,11 @@ PROP_ATTACHMENT_ATTACHMENT = PROP_MARKUP_POPUP_IS_OPEN + 1 }; +/* EvAnnotationTextMarkup */ +enum { + PROP_TEXT_MARKUP_QUADRILATERALS = PROP_MARKUP_POPUP_IS_OPEN + 1 +}; + G_DEFINE_ABSTRACT_TYPE (EvAnnotation, ev_annotation, G_TYPE_OBJECT) G_DEFINE_INTERFACE (EvAnnotationMarkup, ev_annotation_markup, EV_TYPE_ANNOTATION) G_DEFINE_TYPE_WITH_CODE (EvAnnotationText, ev_annotation_text, EV_TYPE_ANNOTATION, @@ -121,6 +137,12 @@ ev_annotation_attachment_markup_iface_init); }); +G_DEFINE_TYPE_WITH_CODE (EvAnnotationTextMarkup, ev_annotation_text_markup, EV_TYPE_ANNOTATION, + { + G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP, + ev_annotation_text_markup_markup_iface_init); + }); + /* EvAnnotation */ static void ev_annotation_finalize (GObject *object) @@ -1350,3 +1372,182 @@ { g_free (quad); } + +/* EvAnnotationTextMarkup */ +static void +ev_annotation_text_markup_finalize (GObject *object) +{ + EvAnnotationTextMarkup *annot = EV_ANNOTATION_TEXT_MARKUP (object); + + if (annot->quadrilaterals) { + g_object_unref(annot->quadrilaterals); + annot->quadrilaterals = NULL; + } +} + +static void +ev_annotation_text_markup_init (EvAnnotationTextMarkup *annot) +{ + annot->quadrilaterals = g_array_new(FALSE, TRUE, sizeof(EvQuadrilateral)); +} + +static gboolean +ev_annotation_text_markup_impl_is_location_in_area (EvAnnotation *annot, + gdouble x, + gdouble y) +{ + EvAnnotationTextMarkup *tm_annot = EV_ANNOTATION_TEXT_MARKUP (annot); + EvAnnotationClass *p_class; + gboolean in_bounding_rect = FALSE; + GArray *quadrilaterals = NULL; + + p_class = EV_ANNOTATION_CLASS (ev_annotation_text_markup_parent_class); + in_bounding_rect = p_class->is_location_in_area (annot, x, y); + if (!in_bounding_rect) { + return FALSE; + } + + quadrilaterals = tm_annot->quadrilaterals; + if (quadrilaterals->len == 0) { + return TRUE; + } else { + int i; + for (i = 0; i < quadrilaterals->len; ++i) { + EvQuadrilateral quad = g_array_index(quadrilaterals, + EvQuadrilateral, + i); + /* + * This only works for convex quadrilaterals! + * + * The coordinates within a quadrilateral are + * defined counter-clockwise. + * If the point x,y is on the left of each edge of + * the quadrilateral, the point is inside the + * quadrilateral. + * + * To test if the point P is left of a line from + * A to B, first translate A and B by -P (to make + * P the new point of origin). + * Then consider the angle alpha between A and B: + * if sin(alpha) >= 0 then the point/origin is + * left of the line AB. + * + * 0 <= sin(alpha) = -cos(alpha + pi/2) ~ -dotP(A',B'') + * where A'=A-P, B'=B-P and B''=B' rotated by pi/2. + * + * Note that for these calculations evince's + * coordinate system is flipped vertically + * (y-axis downwards)! + */ + if (((quad.p2.x - x) * (quad.p1.y - y) - (quad.p1.x - x) * (quad.p2.y - y) >= 0) && + ((quad.p3.x - x) * (quad.p2.y - y) - (quad.p2.x - x) * (quad.p3.y - y) >= 0) && + ((quad.p4.x - x) * (quad.p3.y - y) - (quad.p3.x - x) * (quad.p4.y - y) >= 0) && + ((quad.p1.x - x) * (quad.p4.y - y) - (quad.p4.x - x) * (quad.p1.y - y) >= 0)) { + return TRUE; + } + } + } + return FALSE; +} + +static void +ev_annotation_text_markup_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EvAnnotationTextMarkup *annot = EV_ANNOTATION_TEXT_MARKUP (object); + + if (prop_id < PROP_TEXT_MARKUP_QUADRILATERALS) { + ev_annotation_markup_set_property (object, prop_id, value, pspec); + return; + } + + switch (prop_id) { + case PROP_TEXT_MARKUP_QUADRILATERALS: + ev_annotation_text_markup_set_quadrilaterals (annot, + g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +ev_annotation_text_markup_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EvAnnotationTextMarkup *annot = EV_ANNOTATION_TEXT_MARKUP (object); + + if (prop_id < PROP_TEXT_MARKUP_QUADRILATERALS) { + ev_annotation_markup_get_property (object, prop_id, value, pspec); + return; + } + + switch (prop_id) { + case PROP_TEXT_MARKUP_QUADRILATERALS: + g_value_take_boxed(value, ev_annotation_text_markup_get_quadrilaterals(annot)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +ev_annotation_text_markup_class_init (EvAnnotationTextMarkupClass *klass) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); + EvAnnotationClass *ev_annotation_class = EV_ANNOTATION_CLASS (klass); + + ev_annotation_markup_class_install_properties (g_object_class); + + g_object_class->finalize = ev_annotation_text_markup_finalize; + g_object_class->set_property = ev_annotation_text_markup_set_property; + g_object_class->get_property = ev_annotation_text_markup_get_property; + + ev_annotation_class->is_location_in_area = ev_annotation_text_markup_impl_is_location_in_area; + + g_object_class_install_property (g_object_class, + PROP_TEXT_MARKUP_QUADRILATERALS, + g_param_spec_boxed ("quadrilaterals", + "Quadrilaterlas", + "The quadrilaterals of the annotation", + G_TYPE_ARRAY, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +ev_annotation_text_markup_markup_iface_init (EvAnnotationMarkupInterface *iface) +{ +} + +GArray* +ev_annotation_text_markup_get_quadrilaterals (EvAnnotationTextMarkup* annot) +{ + GArray *result = g_array_sized_new (FALSE, FALSE, + sizeof(EvQuadrilateral), + annot->quadrilaterals->len); + g_array_append_vals (result, annot->quadrilaterals->data, + annot->quadrilaterals->len); + + return result; +} + +gboolean +ev_annotation_text_markup_set_quadrilaterals (EvAnnotationTextMarkup *annot, + GArray *arr) +{ + g_return_val_if_fail(arr != NULL, FALSE); + g_return_val_if_fail(arr->len > 0, FALSE); + + if (annot->quadrilaterals->len) + g_array_remove_range (annot->quadrilaterals, 0, annot->quadrilaterals->len); + + g_array_append_vals (annot->quadrilaterals, arr->data, arr->len); + + return TRUE; +} + diff -r eee239b048d4 -r 48de07d940ed 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 18:09:27 2014 +0200 @@ -85,6 +85,15 @@ #define EV_IS_ANNOTATION_ATTACHMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_ANNOTATION_ATTACHMENT)) #define EV_ANNOTATION_ATTACHMENT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_ANNOTATION_ATTACHMENT, EvAnnotationAttachmentClass)) +/* EvAnnotationTextMarkup */ +#define EV_TYPE_ANNOTATION_TEXT_MARKUP (ev_annotation_text_markup_get_type()) +#define EV_ANNOTATION_TEXT_MARKUP(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_ANNOTATION_TEXT_MARKUP, EvAnnotationTextMarkup)) +#define EV_ANNOTATION_TEXT_MARKUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_ANNOTATION_TEXT_MARKUP, EvAnnotationTextMarkupClass)) +#define EV_IS_ANNOTATION_TEXT_MARKUP(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_ANNOTATION_TEXT_MARKUP)) +#define EV_IS_ANNOTATION_TEXT_MARKUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_ANNOTATION_TEXT_MARKUP)) +#define EV_ANNOTATION_TEXT_MARKUP_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_ANNOTATION_TEXT_MARKUP, EvAnnotationTextMarkupClass)) + + typedef struct _EvAnnotation EvAnnotation; typedef struct _EvAnnotationClass EvAnnotationClass; @@ -97,6 +106,9 @@ typedef struct _EvAnnotationAttachment EvAnnotationAttachment; typedef struct _EvAnnotationAttachmentClass EvAnnotationAttachmentClass; +typedef struct _EvAnnotationTextMarkup EvAnnotationTextMarkup; +typedef struct _EvAnnotationTextMarkupClass EvAnnotationTextMarkupClass; + typedef enum { EV_ANNOTATION_TYPE_UNKNOWN, EV_ANNOTATION_TYPE_TEXT, @@ -188,6 +200,12 @@ EvAttachment *ev_annotation_attachment_get_attachment (EvAnnotationAttachment *annot); gboolean ev_annotation_attachment_set_attachment (EvAnnotationAttachment *annot, EvAttachment *attachment); +/* EvAnnotationTextMarkup */ +GType ev_annotation_text_markup_get_type (void) G_GNUC_CONST; +GArray *ev_annotation_text_markup_get_quadrilaterals (EvAnnotationTextMarkup *annot); +gboolean ev_annotation_text_markup_set_quadrilaterals (EvAnnotationTextMarkup *annot, + GArray *arr); + G_END_DECLS