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=8323ebe380677bfc646cf4f6abe92d2b8cce787f;hb=6c3ca0cf2c626fce12897ea0937c07f2d7863d2f;hp=6078f96297ebb81a9cd4ac6585d0a45b5b02d0e1;hpb=1e247284337090fd8f65e4c191652647d95a36ac;p=evince.git diff --git a/pdf/xpdf/pdf-document.cc b/pdf/xpdf/pdf-document.cc index 6078f962..8323ebe3 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. * @@ -18,11 +19,13 @@ #include "gpdf-g-switch.h" #include "pdf-document.h" +#include "ev-ps-exporter.h" #include "gpdf-g-switch.h" #include "GlobalParams.h" #include "GDKSplashOutputDev.h" #include "PDFDoc.h" +#include "PSOutputDev.h" typedef struct _PdfDocumentClass PdfDocumentClass; @@ -40,20 +43,41 @@ struct _PdfDocument GObject parent_instance; int page; - GdkRectangle page_rect; + int page_x_offset; + int page_y_offset; + double scale; GdkDrawable *target; GDKSplashOutputDev *out; + PSOutputDev *ps_out; PDFDoc *doc; - + + gboolean page_valid; }; static void pdf_document_document_iface_init (EvDocumentIface *iface); +static void pdf_document_ps_exporter_iface_init (EvPSExporterIface *iface); G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT, - { G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, - pdf_document_document_iface_init) }); + { + G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT, + pdf_document_document_iface_init); + G_IMPLEMENT_INTERFACE (EV_TYPE_PS_EXPORTER, + pdf_document_ps_exporter_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 +92,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); @@ -78,11 +102,9 @@ pdf_document_load (EvDocument *document, filename_g = new GString (filename); g_free (filename); - // open the PDF file + // open the PDF file, assumes ownership of filename_g newDoc = new PDFDoc(filename_g, 0, 0); - delete filename_g; - if (!newDoc->isOk()) { err = newDoc->getErrorCode(); delete newDoc; @@ -101,10 +123,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; } @@ -126,7 +150,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 @@ -150,34 +188,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 @@ -191,11 +260,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(); @@ -205,12 +274,126 @@ 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); } +static 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); +} + +static 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_ps_export_begin (EvPSExporter *exporter, const char *filename) +{ + PdfDocument *document = PDF_DOCUMENT (exporter); + + if (document->ps_out) + delete document->ps_out; + + document->ps_out = new PSOutputDev ((char *)filename, document->doc->getXRef(), + document->doc->getCatalog(), 1, + ev_document_get_n_pages (EV_DOCUMENT (document)), + psModePS); +} + +static void +pdf_document_ps_export_do_page (EvPSExporter *exporter, int page) +{ + PdfDocument *document = PDF_DOCUMENT (exporter); + + document->doc->displayPage (document->ps_out, page, + 72.0, 72.0, 0, gTrue, gFalse); +} + +static void +pdf_document_ps_export_end (EvPSExporter *exporter) +{ + PdfDocument *document = PDF_DOCUMENT (exporter); + + delete document->ps_out; + document->ps_out = NULL; +} + static void pdf_document_finalize (GObject *object) { @@ -221,6 +404,8 @@ pdf_document_finalize (GObject *object) if (pdf_document->out) delete pdf_document->out; + if (pdf_document->ps_out) + delete pdf_document->ps_out; if (pdf_document->doc) delete pdf_document->doc; @@ -240,13 +425,32 @@ 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_ps_exporter_iface_init (EvPSExporterIface *iface) +{ + iface->begin = pdf_document_ps_export_begin; + iface->do_page = pdf_document_ps_export_do_page; + iface->end = pdf_document_ps_export_end; } 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; }