]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/pdf-document.cc
display an error if the document doesn't support find (better ideas?)
[evince.git] / pdf / xpdf / pdf-document.cc
index 9a9d022e5f2974a3f1782ec1a4528180611293cf..efee46252083820896f1df2af0f8cc61f174b9a9 100644 (file)
@@ -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.
  *
 
 #include "gpdf-g-switch.h"
 #include "pdf-document.h"
+#include "ev-ps-exporter.h"
+#include "ev-document-find.h"
 #include "gpdf-g-switch.h"
 
 #include "GlobalParams.h"
 #include "GDKSplashOutputDev.h"
 #include "PDFDoc.h"
+#include "PSOutputDev.h"
 
 typedef struct _PdfDocumentClass PdfDocumentClass;
 
@@ -46,16 +50,25 @@ struct _PdfDocument
        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_document_iface_init    (EvDocumentIface     *iface);
+static void pdf_document_ps_exporter_iface_init (EvPSExporterIface   *iface);
+static void pdf_document_find_iface_init        (EvDocumentFindIface *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);
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
+                                                       pdf_document_find_iface_init);
+                        });
 
 static gboolean
 document_validate_page (PdfDocument *pdf_document)
@@ -83,7 +96,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);
@@ -141,6 +154,8 @@ pdf_document_set_page (EvDocument  *document,
 {
        PdfDocument *pdf_document = PDF_DOCUMENT (document);
 
+       page = CLAMP (page, 1, ev_document_get_n_pages (document));
+
        if (page != pdf_document->page) {
                pdf_document->page = page;
                pdf_document->page_valid = FALSE;
@@ -148,6 +163,14 @@ pdf_document_set_page (EvDocument  *document,
 
 }
 
+static int
+pdf_document_get_page (EvDocument  *document)
+{
+       PdfDocument *pdf_document = PDF_DOCUMENT (document);
+
+       return pdf_document->page;
+}
+
 static void
 redraw_callback (void *data)
 {
@@ -261,6 +284,116 @@ pdf_document_render (EvDocument  *document,
                                           draw.width, draw.height);
 }
 
+static void
+pdf_document_find_begin (EvDocumentFind   *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_find_found (document,
+                               (EvFindResult*) results->data,
+                               results->len,
+                               1.0);
+
+        g_array_free (results, TRUE);
+}
+
+static void
+pdf_document_find_cancel (EvDocumentFind   *document)
+{
+        PdfDocument *pdf_document = PDF_DOCUMENT (document);
+
+        /* FIXME this will do something once begin_find queues
+         * an incremental find
+         */
+}
+
+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)
 {
@@ -271,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;
 
@@ -290,6 +425,7 @@ 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_offset = pdf_document_set_page_offset;
@@ -297,6 +433,22 @@ pdf_document_document_iface_init (EvDocumentIface *iface)
        iface->render = pdf_document_render;
 }
 
+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_find_iface_init (EvDocumentFindIface *iface)
+{
+        iface->begin = pdf_document_find_begin;
+        iface->cancel = pdf_document_find_cancel;
+}
+
 static void
 pdf_document_init (PdfDocument *pdf_document)
 {