X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=pdf%2Fxpdf%2Fpdf-document.cc;h=fa7c7fcfa4dd380718e47aa77e0b6b04d56283f3;hb=f36af012943a93a0c8e1f2d36c4f5b9e1ac1b8e5;hp=8558c822f1faa6a9dee786c955cf746bd8876f7f;hpb=484bd6fc379965a3ad83e758135691d84d595f87;p=evince.git diff --git a/pdf/xpdf/pdf-document.cc b/pdf/xpdf/pdf-document.cc index 8558c822..fa7c7fcf 100644 --- a/pdf/xpdf/pdf-document.cc +++ b/pdf/xpdf/pdf-document.cc @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ /* pdfdocument.h: Implementation of EvDocument for PDF * Copyright (C) 2004, Red Hat, Inc. * @@ -40,12 +41,15 @@ struct _PdfDocument GObject parent_instance; int page; - GdkRectangle page_rect; + int page_x_offset; + int page_y_offset; + double scale; GdkDrawable *target; GDKSplashOutputDev *out; PDFDoc *doc; - + + gboolean page_valid; }; static void pdf_document_document_iface_init (EvDocumentIface *iface); @@ -54,6 +58,18 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, pdf_document_document_iface_init) }); +static gboolean +document_validate_page (PdfDocument *pdf_document) +{ + if (!pdf_document->page_valid) { + pdf_document->doc->displayPage (pdf_document->out, pdf_document->page, + 72 * pdf_document->scale, + 72 * pdf_document->scale, + 0, gTrue, gTrue); + + pdf_document->page_valid = TRUE; + } +} static gboolean pdf_document_load (EvDocument *document, @@ -68,7 +84,7 @@ pdf_document_load (EvDocument *document, if (!globalParams) { globalParams = new GlobalParams("/etc/xpdfrc"); - globalParams->setupBaseFonts(NULL); + globalParams->setupBaseFontsFc(NULL); } filename = g_filename_from_uri (uri, NULL, error); @@ -99,10 +115,12 @@ pdf_document_load (EvDocument *document, delete pdf_document->doc; pdf_document->doc = newDoc; - if (pdf_document->out) { + pdf_document->page = 1; + + if (pdf_document->out) pdf_document->out->startDoc(pdf_document->doc->getXRef()); - pdf_document->doc->displayPage (pdf_document->out, 1, 72, 72, 0, gTrue, gTrue); - } + + pdf_document->page_valid = FALSE; return TRUE; } @@ -124,7 +142,21 @@ pdf_document_set_page (EvDocument *document, { PdfDocument *pdf_document = PDF_DOCUMENT (document); - pdf_document->page = page; + page = CLAMP (page, 1, ev_document_get_n_pages (document)); + + if (page != pdf_document->page) { + pdf_document->page = page; + pdf_document->page_valid = FALSE; + } + +} + +static int +pdf_document_get_page (EvDocument *document) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + return pdf_document->page; } static void @@ -148,34 +180,65 @@ pdf_document_set_target (EvDocument *document, if (pdf_document->target) g_object_ref (pdf_document->target); - if (pdf_document->out) + if (pdf_document->out) { delete pdf_document->out; + pdf_document->out = NULL; + } if (pdf_document->target) { pdf_document->out = new GDKSplashOutputDev (gdk_drawable_get_screen (pdf_document->target), redraw_callback, (void*) document); - if (pdf_document->doc) { + if (pdf_document->doc) pdf_document->out->startDoc(pdf_document->doc->getXRef()); - pdf_document->doc->displayPage (pdf_document->out, 1, 72, 72, 0, gTrue, gTrue); - } + } + + pdf_document->page_valid = FALSE; } } static void -pdf_document_set_page_rect (EvDocument *document, - int x, - int y, - int width, - int height) +pdf_document_set_scale (EvDocument *document, + double scale) { PdfDocument *pdf_document = PDF_DOCUMENT (document); - pdf_document->page_rect.x = x; - pdf_document->page_rect.y = y; - pdf_document->page_rect.width = width; - pdf_document->page_rect.height = height; + if (pdf_document->scale != scale) { + pdf_document->scale = scale; + pdf_document->page_valid = FALSE; + } +} + +static void +pdf_document_set_page_offset (EvDocument *document, + int x, + int y) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + pdf_document->page_x_offset = x; + pdf_document->page_y_offset = y; +} + +static void +pdf_document_get_page_size (EvDocument *document, + int *width, + int *height) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + if (document_validate_page (pdf_document)) { + if (width) + *width = pdf_document->out->getBitmapWidth(); + if (height) + *height = pdf_document->out->getBitmapHeight(); + } else { + if (width) + *width = 1; + if (height) + *height = 1; + } } static void @@ -189,11 +252,11 @@ pdf_document_render (EvDocument *document, GdkRectangle page; GdkRectangle draw; - if (!pdf_document->target) + if (!document_validate_page (pdf_document) || !pdf_document->target) return; - page.x = 0; - page.y = 0; + page.x = pdf_document->page_x_offset; + page.y = pdf_document->page_y_offset; page.width = pdf_document->out->getBitmapWidth(); page.height = pdf_document->out->getBitmapHeight(); @@ -203,12 +266,94 @@ pdf_document_render (EvDocument *document, draw.height = clip_height; if (gdk_rectangle_intersect (&page, &draw, &draw)) - pdf_document->out->redraw (draw.x, draw.y, + pdf_document->out->redraw (draw.x - page.x, draw.y - page.y, pdf_document->target, draw.x, draw.y, draw.width, draw.height); } +void +pdf_document_begin_find (EvDocument *document, + const char *search_string, + gboolean case_sensitive) +{ + /* FIXME make this incremental (idle handler) and multi-page */ + /* Right now it's fully synchronous plus only does the current page */ + + PdfDocument *pdf_document = PDF_DOCUMENT (document); + gunichar *ucs4; + glong ucs4_len; + int xMin, yMin, xMax, yMax; + GArray *results; + EvFindResult result; + + /* FIXME case_sensitive (right now XPDF + * code is always case insensitive for ASCII + * and case sensitive for all other languaages) + */ + + g_assert (sizeof (gunichar) == sizeof (Unicode)); + ucs4 = g_utf8_to_ucs4_fast (search_string, -1, + &ucs4_len); + + results = g_array_new (FALSE, + FALSE, + sizeof (EvFindResult)); + + if (pdf_document->out->findText (ucs4, ucs4_len, + gTrue, gTrue, // startAtTop, stopAtBottom + gFalse, gFalse, // startAtLast, stopAtLast + &xMin, &yMin, &xMax, &yMax)) { + + result.page_num = pdf_document->page; + + result.highlight_area.x = xMin; + result.highlight_area.y = yMin; + result.highlight_area.width = xMax - xMin; + result.highlight_area.height = yMax - yMin; + + g_array_append_val (results, result); + + /* Now find further results */ + + while (pdf_document->out->findText (ucs4, ucs4_len, + gFalse, gTrue, + gTrue, gFalse, + &xMin, &yMin, &xMax, &yMax)) { + + result.page_num = pdf_document->page; + + result.highlight_area.x = xMin; + result.highlight_area.y = yMin; + result.highlight_area.width = xMax - xMin; + result.highlight_area.height = yMax - yMin; + + g_array_append_val (results, result); + } + } + + ev_document_found (document, + (EvFindResult*) results->data, + results->len, + 1.0); + + g_array_free (results, TRUE); +} + +void +pdf_document_end_find (EvDocument *document) +{ + PdfDocument *pdf_document = PDF_DOCUMENT (document); + + /* FIXME this will do something once begin_find queues + * an incremental find + */ + + // this should probably be shared among EvDocument + // implementations somehow? + ev_document_found (document, NULL, 0, 1.0); +} + static void pdf_document_finalize (GObject *object) { @@ -238,13 +383,24 @@ pdf_document_document_iface_init (EvDocumentIface *iface) iface->load = pdf_document_load; iface->get_n_pages = pdf_document_get_n_pages; iface->set_page = pdf_document_set_page; + iface->get_page = pdf_document_get_page; + iface->set_scale = pdf_document_set_scale; iface->set_target = pdf_document_set_target; - iface->set_page_rect = pdf_document_set_page_rect; + iface->set_page_offset = pdf_document_set_page_offset; + iface->get_page_size = pdf_document_get_page_size; iface->render = pdf_document_render; + iface->begin_find = pdf_document_begin_find; + iface->end_find = pdf_document_end_find; } static void -pdf_document_init (PdfDocument *document) +pdf_document_init (PdfDocument *pdf_document) { + pdf_document->page = 1; + pdf_document->page_x_offset = 0; + pdf_document->page_y_offset = 0; + pdf_document->scale = 1.; + + pdf_document->page_valid = FALSE; }