[evince/BUG_tooltip_annots] pdf: support 'de facto' tooltip feature
- From: Nelson Benítez León <nbenitez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/BUG_tooltip_annots] pdf: support 'de facto' tooltip feature
- Date: Sun, 8 Mar 2020 23:48:04 +0000 (UTC)
commit 2d2eb2debe1632111de543a5a6a66ebc202bcaec
Author: Nelson Benítez León <nbenitezl gmail com>
Date: Sun Mar 8 17:56:07 2020 -0400
pdf: support 'de facto' tooltip feature
Most pdf readers implement a tooltip feature by
showing the string content of 'TU' field of a
widget annotation that is not linked to any
form field.
Normally, widget annotations carry a reference to a
form field which are used together to implement the
different form widgets. But, the PDF spec does not
forbid standalone (i.e. not linked to any form field)
widget annotations, and the fact is they're been used
by most pdf readers to show a tooltip when the area
of that AnnotWidget is hovered.
According to issue reported files, 'pdfTeX' seems to
be one of the pdf producers incorporating this tooltip
feature.
The support for this feature has been recently been
added to poppler-glib with following api:
gchar *poppler_annot_get_alternate_name (PopplerAnnot *annot)
gboolean poppler_annot_set_alternate_name (PopplerAnnot *annot,
const gchar *name)
so this commit uses only the "read" part of that api
to show tooltips on pdf's that carry them. For that
we created a new EvAnnotationTooltip type. This new
annot type is not shown on the annotations sidebar
list as part of the rest of annotations, instead it's
just been used to show the tooltips when the annot
area is hovered.
Evince issue #842
Poppler issue:
https://gitlab.freedesktop.org/poppler/poppler/issues/34
backend/pdf/ev-poppler.cc | 17 +++++++--
libdocument/ev-annotation.c | 85 +++++++++++++++++++++++++++++++++++++++++++++
libdocument/ev-annotation.h | 21 ++++++++++-
libview/ev-view.c | 8 +++++
4 files changed, 128 insertions(+), 3 deletions(-)
---
diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc
index a6383a15..1a85b5a2 100644
--- a/backend/pdf/ev-poppler.cc
+++ b/backend/pdf/ev-poppler.cc
@@ -3204,10 +3204,23 @@ ev_annot_from_poppler_annot (PopplerAnnot *poppler_annot,
case POPPLER_ANNOT_SQUIGGLY:
ev_annot = ev_annotation_text_markup_squiggly_new (page);
break;
- case POPPLER_ANNOT_LINK:
case POPPLER_ANNOT_WIDGET:
+ gchar *tooltip = NULL;
+
+#if POPPLER_CHECK_VERSION(0, 87, 0)
+ tooltip = poppler_annot_get_alternate_name (poppler_annot);
+#endif
+ /* Widget annots with no form field associated (i.e. standalone) are
+ * used by pdf readers/producers to show tooltips. If that's the case
+ * then poppler_annot_get_alternate_name() will return non null. */
+ if (tooltip) {
+ ev_annot = ev_annotation_tooltip_new (page);
+ ev_annotation_tooltip_take_text (EV_ANNOTATION_TOOLTIP (ev_annot), tooltip);
+ }
+ break;
+ case POPPLER_ANNOT_LINK:
case POPPLER_ANNOT_MOVIE:
- /* Ignore link, widgets and movie annots since they are already handled */
+ /* Ignore link and movie annots since they are already handled */
break;
case POPPLER_ANNOT_SCREEN: {
PopplerAction *action;
diff --git a/libdocument/ev-annotation.c b/libdocument/ev-annotation.c
index 058a999b..b9115ec7 100644
--- a/libdocument/ev-annotation.c
+++ b/libdocument/ev-annotation.c
@@ -77,6 +77,16 @@ struct _EvAnnotationTextMarkupClass {
EvAnnotationClass parent_class;
};
+struct _EvAnnotationTooltip {
+ EvAnnotation parent;
+
+ gchar *tooltip;
+};
+
+struct _EvAnnotationTooltipClass {
+ 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);
@@ -138,6 +148,7 @@ G_DEFINE_TYPE_WITH_CODE (EvAnnotationTextMarkup, ev_annotation_text_markup, EV_T
G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
ev_annotation_text_markup_markup_iface_init);
});
+G_DEFINE_TYPE (EvAnnotationTooltip, ev_annotation_tooltip, EV_TYPE_ANNOTATION);
/* EvAnnotation */
static void
@@ -1506,3 +1517,77 @@ ev_annotation_text_markup_set_markup_type (EvAnnotationTextMarkup *annot,
return TRUE;
}
+
+/* EvAnnotationTooltip */
+EvAnnotation *
+ev_annotation_tooltip_new (EvPage *page)
+{
+ g_return_val_if_fail (EV_IS_PAGE (page), NULL);
+
+ return EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_TOOLTIP,
+ "page", page,
+ NULL));
+}
+
+static void
+ev_annotation_tooltip_init (EvAnnotationTooltip *annot)
+{
+ annot->tooltip = NULL;
+}
+
+static void
+ev_annotation_tooltip_finalize (GObject *object)
+{
+ EvAnnotationTooltip *annot = EV_ANNOTATION_TOOLTIP (object);
+
+ g_clear_pointer (&annot->tooltip, g_free);
+
+ G_OBJECT_CLASS (ev_annotation_tooltip_parent_class)->finalize (object);
+}
+
+static void
+ev_annotation_tooltip_class_init (EvAnnotationTooltipClass *klass)
+{
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+
+ g_object_class->finalize = ev_annotation_tooltip_finalize;
+}
+
+/**
+ * ev_annotation_tooltip_get_text:
+ * @annot: an #EvAnnotationTooltip
+ *
+ * Get the tooltip string of @annot .
+ *
+ * Returns: (transfer none): A string containing the tooltip text.
+ */
+const gchar *
+ev_annotation_tooltip_get_text (EvAnnotationTooltip *annot)
+{
+ g_return_val_if_fail (EV_IS_ANNOTATION_TOOLTIP (annot), NULL);
+
+ return annot->tooltip;
+}
+
+/**
+ * ev_annotation_tooltip_take_text:
+ * @annot: an #EvAnnotationTooltip
+ * @text: (transfer full): an allocated string containing the tooltip text.
+ *
+ * Set the tooltip string of @annot to be @text.
+ *
+ */
+void
+ev_annotation_tooltip_take_text (EvAnnotationTooltip *annot,
+ gchar *text)
+{
+ g_return_if_fail (EV_IS_ANNOTATION_TOOLTIP (annot));
+
+ if (annot->tooltip == text)
+ return;
+
+ if (annot->tooltip)
+ g_free (annot->tooltip);
+
+ annot->tooltip = text;
+}
diff --git a/libdocument/ev-annotation.h b/libdocument/ev-annotation.h
index 1fe98fe3..d436cccc 100644
--- a/libdocument/ev-annotation.h
+++ b/libdocument/ev-annotation.h
@@ -74,6 +74,14 @@ G_BEGIN_DECLS
#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))
+/* EvAnnotationTooltip */
+#define EV_TYPE_ANNOTATION_TOOLTIP (ev_annotation_tooltip_get_type())
+#define EV_ANNOTATION_TOOLTIP(object) (G_TYPE_CHECK_INSTANCE_CAST((object),
EV_TYPE_ANNOTATION_TOOLTIP, EvAnnotationTooltip))
+#define EV_ANNOTATION_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
EV_TYPE_ANNOTATION_TOOLTIP, EvAnnotationTooltipClass))
+#define EV_IS_ANNOTATION_TOOLTIP(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),
EV_TYPE_ANNOTATION_TOOLTIP))
+#define EV_IS_ANNOTATION_TOOLTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
EV_TYPE_ANNOTATION_TOOLTIP))
+#define EV_ANNOTATION_TOOLTIP_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object),
EV_TYPE_ANNOTATION_TOOLTIP, EvAnnotationTooltipClass))
+
typedef struct _EvAnnotation EvAnnotation;
typedef struct _EvAnnotationClass EvAnnotationClass;
@@ -89,11 +97,15 @@ typedef struct _EvAnnotationAttachmentClass EvAnnotationAttachmentClass;
typedef struct _EvAnnotationTextMarkup EvAnnotationTextMarkup;
typedef struct _EvAnnotationTextMarkupClass EvAnnotationTextMarkupClass;
+typedef struct _EvAnnotationTooltip EvAnnotationTooltip;
+typedef struct _EvAnnotationTooltipClass EvAnnotationTooltipClass;
+
typedef enum {
EV_ANNOTATION_TYPE_UNKNOWN,
EV_ANNOTATION_TYPE_TEXT,
EV_ANNOTATION_TYPE_ATTACHMENT,
- EV_ANNOTATION_TYPE_TEXT_MARKUP
+ EV_ANNOTATION_TYPE_TEXT_MARKUP,
+ EV_ANNOTATION_TYPE_TOOLTIP
} EvAnnotationType;
typedef enum {
@@ -197,6 +209,13 @@ EvAnnotationTextMarkupType ev_annotation_text_markup_get_markup_type (EvAnnotati
gboolean ev_annotation_text_markup_set_markup_type (EvAnnotationTextMarkup *annot,
EvAnnotationTextMarkupType
markup_type);
+/* EvAnnotationTooltip */
+GType ev_annotation_tooltip_get_type (void) G_GNUC_CONST;
+EvAnnotation *ev_annotation_tooltip_new (EvPage *page);
+const gchar *ev_annotation_tooltip_get_text (EvAnnotationTooltip *annot);
+void ev_annotation_tooltip_take_text (EvAnnotationTooltip *annot,
+ gchar *text);
+
G_END_DECLS
#endif /* EV_ANNOTATION_H */
diff --git a/libview/ev-view.c b/libview/ev-view.c
index ffbe1704..ec8d5f16 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -4926,9 +4926,17 @@ ev_view_query_tooltip (GtkWidget *widget,
annot = ev_view_get_annotation_at_location (view, x, y);
if (annot) {
const gchar *contents;
+ gboolean found = FALSE;
contents = ev_annotation_get_contents (annot);
if (contents && *contents != '\0') {
+ found = TRUE;
+ } else if (EV_IS_ANNOTATION_TOOLTIP (annot)) {
+ contents = ev_annotation_tooltip_get_text (EV_ANNOTATION_TOOLTIP (annot));
+ found = contents && *contents != '\0';
+ }
+
+ if (found) {
GdkRectangle annot_area;
get_annot_area (view, x, y, annot, &annot_area);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]