[evince] djvu: enable selection highlighting
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] djvu: enable selection highlighting
- Date: Sat, 29 Jun 2013 08:34:15 +0000 (UTC)
commit 32232115a832b3d4f0bd73d82894b75f1cc7e9aa
Author: Jonas Danielsson <jonas threetimestwo org>
Date: Thu May 23 12:07:57 2013 +0200
djvu: enable selection highlighting
https://bugzilla.gnome.org/show_bug.cgi?id=448739
backend/djvu/djvu-document.c | 100 +++++++++++++++++++++++++++--
backend/djvu/djvu-text-page.c | 141 ++++++++++++++++++++++++++++++-----------
backend/djvu/djvu-text-page.h | 23 +++++---
3 files changed, 212 insertions(+), 52 deletions(-)
---
diff --git a/backend/djvu/djvu-document.c b/backend/djvu/djvu-document.c
index 57af7dd..c4b50c4 100644
--- a/backend/djvu/djvu-document.c
+++ b/backend/djvu/djvu-document.c
@@ -537,6 +537,95 @@ djvu_text_copy (DjvuDocument *djvu_document,
return text;
}
+static void
+djvu_convert_to_doc_rect (EvRectangle *dest,
+ EvRectangle *source,
+ gdouble height,
+ gdouble dpi)
+{
+ dest->x1 = source->x1 * dpi / 72;
+ dest->x2 = source->x2 * dpi / 72;
+ dest->y1 = (height - source->y2) * dpi / 72;
+ dest->y2 = (height - source->y1) * dpi / 72;
+}
+
+static GList *
+djvu_selection_get_selection_rects (DjvuDocument *djvu_document,
+ gint page,
+ EvRectangle *points,
+ gdouble height,
+ gdouble dpi)
+{
+ miniexp_t page_text;
+ EvRectangle rectangle;
+ GList *rects = NULL;
+
+ djvu_convert_to_doc_rect (&rectangle, points, height, dpi);
+
+ while ((page_text = ddjvu_document_get_pagetext (djvu_document->d_document,
+ page, "char")) == miniexp_dummy)
+ djvu_handle_events (djvu_document, TRUE, NULL);
+
+ if (page_text != miniexp_nil) {
+ DjvuTextPage *tpage = djvu_text_page_new (page_text);
+
+ rects = djvu_text_page_get_selection_region (tpage, &rectangle);
+ djvu_text_page_free (tpage);
+ ddjvu_miniexp_release (djvu_document->d_document, page_text);
+ }
+
+ return rects;
+}
+
+static cairo_region_t *
+djvu_get_selection_region (DjvuDocument *djvu_document,
+ gint page,
+ gdouble scale,
+ EvRectangle *points)
+{
+ double height, dpi;
+ GList *rects = NULL, *l;
+ cairo_region_t *region;
+
+ document_get_page_size (djvu_document, page, NULL, &height, &dpi);
+ rects = djvu_selection_get_selection_rects (djvu_document, page, points,
+ height, dpi);
+ region = cairo_region_create ();
+ for (l = rects; l && l->data; l = g_list_next (l)) {
+ cairo_rectangle_int_t rect;
+ EvRectangle *r = (EvRectangle *)l->data;
+ gdouble tmp;
+
+ tmp = r->y1;
+ r->x1 *= 72 / dpi;
+ r->x2 *= 72 / dpi;
+ r->y1 = height - r->y2 * 72 / dpi;
+ r->y2 = height - tmp * 72 / dpi;
+
+ rect.x = (gint) ((r->x1 * scale) + 0.5);
+ rect.y = (gint) ((r->y1 * scale) + 0.5);
+ rect.width = (gint) (((r->x2 - r->x1) * scale) + 0.5);
+ rect.height = (gint) (((r->y2 - r->y1) * scale) + 0.5);
+ cairo_region_union_rectangle (region, &rect);
+ ev_rectangle_free (r);
+ }
+ g_list_free (l);
+
+ return region;
+}
+
+static cairo_region_t *
+djvu_selection_get_selection_region (EvSelection *selection,
+ EvRenderContext *rc,
+ EvSelectionStyle style,
+ EvRectangle *points)
+{
+ DjvuDocument *djvu_document = DJVU_DOCUMENT (selection);
+
+ return djvu_get_selection_region (djvu_document, rc->page->index,
+ rc->scale, points);
+}
+
static gchar *
djvu_selection_get_selected_text (EvSelection *selection,
EvPage *page,
@@ -544,16 +633,12 @@ djvu_selection_get_selected_text (EvSelection *selection,
EvRectangle *points)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (selection);
- double width, height, dpi;
+ double height, dpi;
EvRectangle rectangle;
gchar *text;
- document_get_page_size (djvu_document, page->index, &width, &height, &dpi);
- rectangle.x1 = points->x1 * dpi / 72.0;
- rectangle.y1 = (height - points->y2) * dpi / 72.0;
- rectangle.x2 = points->x2 * dpi / 72.0;
- rectangle.y2 = (height - points->y1) * dpi / 72.0;
-
+ document_get_page_size (djvu_document, page->index, NULL, &height, &dpi);
+ djvu_convert_to_doc_rect (&rectangle, points, height, dpi);
text = djvu_text_copy (djvu_document, page->index, &rectangle);
if (text == NULL)
@@ -566,6 +651,7 @@ static void
djvu_selection_iface_init (EvSelectionInterface *iface)
{
iface->get_selected_text = djvu_selection_get_selected_text;
+ iface->get_selection_region = djvu_selection_get_selection_region;
}
/* EvFileExporterIface */
diff --git a/backend/djvu/djvu-text-page.c b/backend/djvu/djvu-text-page.c
index 3f171d1..6e04e94 100644
--- a/backend/djvu/djvu-text-page.c
+++ b/backend/djvu/djvu-text-page.c
@@ -25,7 +25,68 @@
/**
- * djvu_text_page_selection_process:
+ * djvu_text_page_union:
+ * @target: first rectangle and result
+ * @source: second rectangle
+ *
+ * Calculates the bounding box of two rectangles and stores the result
+ * in the first.
+ */
+static void
+djvu_text_page_union (EvRectangle *target,
+ EvRectangle *source)
+{
+ if (source->x1 < target->x1)
+ target->x1 = source->x1;
+ if (source->x2 > target->x2)
+ target->x2 = source->x2;
+ if (source->y1 < target->y1)
+ target->y1 = source->y1;
+ if (source->y2 > target->y2)
+ target->y2 = source->y2;
+}
+
+/**
+ * djvu_text_page_selection_process_box:
+ * @page: #DjvuTextPage instance
+ * @p: s-expression to append bounding box of
+ * @delimit: character/word/... delimiter
+ *
+ * Appends bounding box of the line containing miniexp_t to page->results
+ *
+ * Returns: whether the end was not reached in this s-expression
+ */
+static gboolean
+djvu_text_page_selection_process_box (DjvuTextPage *page,
+ miniexp_t p,
+ int delimit)
+{
+ if (page->results || p == page->start) {
+ EvRectangle box;
+
+ box.x1 = miniexp_to_int (miniexp_nth (1, p));
+ box.y1 = miniexp_to_int (miniexp_nth (2, p));
+ box.x2 = miniexp_to_int (miniexp_nth (3, p));
+ box.y2 = miniexp_to_int (miniexp_nth (4, p));
+
+ if (!(delimit & 2) && page->results != NULL) {
+ EvRectangle *union_box = (EvRectangle *)page->results->data;
+
+ /* If still on the same line, add box to union */
+ djvu_text_page_union (union_box, &box);
+ } else {
+ /* A new line, a new box */
+ page->results = g_list_prepend (page->results, ev_rectangle_copy (&box));
+ }
+
+ if (p == page->end)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * djvu_text_page_selection_process_text:
* @page: #DjvuTextPage instance
* @p: s-expression to append
* @delimit: character/word/... delimiter
@@ -35,9 +96,9 @@
* Returns: whether the end was not reached in this s-expression
*/
static gboolean
-djvu_text_page_selection_process (DjvuTextPage *page,
- miniexp_t p,
- int delimit)
+djvu_text_page_selection_process_text (DjvuTextPage *page,
+ miniexp_t p,
+ int delimit)
{
if (page->text || p == page->start) {
char *token_text = (char *) miniexp_to_str (miniexp_nth (5, p));
@@ -63,16 +124,17 @@ djvu_text_page_selection_process (DjvuTextPage *page,
* @p: tree to append
* @delimit: character/word/... delimiter
*
- * Walks the tree in @p and appends the text with
- * djvu_text_page_selection_process() for all s-expressions
+ * Walks the tree in @p and appends the text or bounding boxes with
+ * djvu_text_page_selection_process_{text|box}() for all s-expressions
* between the start and end fields.
*
* Returns: whether the end was not reached in this subtree
*/
static gboolean
-djvu_text_page_selection (DjvuTextPage *page,
- miniexp_t p,
- int delimit)
+djvu_text_page_selection (DjvuSelectionType type,
+ DjvuTextPage *page,
+ miniexp_t p,
+ int delimit)
{
g_return_val_if_fail (miniexp_consp (p) && miniexp_symbolp
(miniexp_car (p)), FALSE);
@@ -84,12 +146,15 @@ djvu_text_page_selection (DjvuTextPage *page,
while (deeper != miniexp_nil) {
miniexp_t str = miniexp_car (deeper);
if (miniexp_stringp (str)) {
- if (!djvu_text_page_selection_process
- (page, p, delimit))
- return FALSE;
+ if (type == DJVU_SELECTION_TEXT) {
+ if (!djvu_text_page_selection_process_text (page, p, delimit))
+ return FALSE;
+ } else {
+ if (!djvu_text_page_selection_process_box (page, p, delimit))
+ return FALSE;
+ }
} else {
- if (!djvu_text_page_selection
- (page, str, delimit))
+ if (!djvu_text_page_selection (type, page, str, delimit))
return FALSE;
}
delimit = 0;
@@ -138,6 +203,29 @@ djvu_text_page_limits (DjvuTextPage *page,
}
}
+/**
+ * djvu_text_page_get_selection:
+ * @page: #DjvuTextPage instance
+ * @rectangle: #EvRectangle of the selection
+ *
+ * Returns: The bounding boxes of the selection
+ */
+GList *
+djvu_text_page_get_selection_region (DjvuTextPage *page,
+ EvRectangle *rectangle)
+{
+ page->start = miniexp_nil;
+ page->end = miniexp_nil;
+
+ /* Get page->start and page->end filled from selection rectangle */
+ djvu_text_page_limits (page, page->text_structure, rectangle);
+ /* Fills page->results with the bouding boxes */
+ djvu_text_page_selection (DJVU_SELECTION_BOX,
+ page, page->text_structure, 0);
+
+ return g_list_reverse (page->results);
+}
+
char *
djvu_text_page_copy (DjvuTextPage *page,
EvRectangle *rectangle)
@@ -147,7 +235,8 @@ djvu_text_page_copy (DjvuTextPage *page,
page->start = miniexp_nil;
page->end = miniexp_nil;
djvu_text_page_limits (page, page->text_structure, rectangle);
- djvu_text_page_selection (page, page->text_structure, 0);
+ djvu_text_page_selection (DJVU_SELECTION_TEXT, page,
+ page->text_structure, 0);
/* Do not free the string */
text = page->text;
@@ -194,28 +283,6 @@ djvu_text_page_position (DjvuTextPage *page,
}
/**
- * djvu_text_page_union:
- * @target: first rectangle and result
- * @source: second rectangle
- *
- * Calculates the bounding box of two rectangles and stores the reuslt
- * in the first.
- */
-static void
-djvu_text_page_union (EvRectangle *target,
- EvRectangle *source)
-{
- if (source->x1 < target->x1)
- target->x1 = source->x1;
- if (source->x2 > target->x2)
- target->x2 = source->x2;
- if (source->y1 < target->y1)
- target->y1 = source->y1;
- if (source->y2 > target->y2)
- target->y2 = source->y2;
-}
-
-/**
* djvu_text_page_sexpr_process:
* @page: #DjvuTextPage instance
* @p: s-expression to append
diff --git a/backend/djvu/djvu-text-page.h b/backend/djvu/djvu-text-page.h
index 6e16f25..4f1b1f8 100644
--- a/backend/djvu/djvu-text-page.h
+++ b/backend/djvu/djvu-text-page.h
@@ -46,14 +46,21 @@ struct _DjvuTextLink {
miniexp_t pair;
};
-char * djvu_text_page_copy (DjvuTextPage *page,
- EvRectangle *rectangle);
-void djvu_text_page_prepare_search (DjvuTextPage *page,
- gboolean case_sensitive);
-void djvu_text_page_search (DjvuTextPage *page,
- const char *text);
-DjvuTextPage* djvu_text_page_new (miniexp_t text);
-void djvu_text_page_free (DjvuTextPage *page);
+typedef enum {
+ DJVU_SELECTION_TEXT,
+ DJVU_SELECTION_BOX,
+} DjvuSelectionType;
+
+GList *djvu_text_page_get_selection_region (DjvuTextPage *page,
+ EvRectangle *rectangle);
+char *djvu_text_page_copy (DjvuTextPage *page,
+ EvRectangle *rectangle);
+void djvu_text_page_prepare_search (DjvuTextPage *page,
+ gboolean case_sensitive);
+void djvu_text_page_search (DjvuTextPage *page,
+ const char *text);
+DjvuTextPage *djvu_text_page_new (miniexp_t text);
+void djvu_text_page_free (DjvuTextPage *page);
#endif /* __DJVU_TEXT_PAGE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]