]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/pdf-document.cc
add GnomePrintJob to EvPrintJob constructor arguments.
[evince.git] / pdf / xpdf / pdf-document.cc
index 6078f96297ebb81a9cd4ac6585d0a45b5b02d0e1..8323ebe380677bfc646cf4f6abe92d2b8cce787f 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.
  *
 /* pdfdocument.h: Implementation of EvDocument for PDF
  * Copyright (C) 2004, Red Hat, Inc.
  *
 
 #include "gpdf-g-switch.h"
 #include "pdf-document.h"
 
 #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 "gpdf-g-switch.h"
 
 #include "GlobalParams.h"
 #include "GDKSplashOutputDev.h"
 #include "PDFDoc.h"
+#include "PSOutputDev.h"
 
 typedef struct _PdfDocumentClass PdfDocumentClass;
 
 
 typedef struct _PdfDocumentClass PdfDocumentClass;
 
@@ -40,20 +43,41 @@ struct _PdfDocument
        GObject parent_instance;
 
        int page;
        GObject parent_instance;
 
        int page;
-       GdkRectangle page_rect;
+       int page_x_offset;
+       int page_y_offset;
+       double scale;
        GdkDrawable *target;
 
        GDKSplashOutputDev *out;
        GdkDrawable *target;
 
        GDKSplashOutputDev *out;
+       PSOutputDev *ps_out;
        PDFDoc *doc;
        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);
 
 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
 
 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,
 
 static gboolean
 pdf_document_load (EvDocument  *document,
@@ -68,7 +92,7 @@ pdf_document_load (EvDocument  *document,
        
        if (!globalParams) {
                globalParams = new GlobalParams("/etc/xpdfrc");
        
        if (!globalParams) {
                globalParams = new GlobalParams("/etc/xpdfrc");
-               globalParams->setupBaseFonts(NULL);
+               globalParams->setupBaseFontsFc(NULL);
        }
 
        filename = g_filename_from_uri (uri, NULL, error);
        }
 
        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);
 
        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);
 
        newDoc = new PDFDoc(filename_g, 0, 0);
 
-       delete filename_g;
-  
        if (!newDoc->isOk()) {
                err = newDoc->getErrorCode();
                delete newDoc;
        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;
 
                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->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;
 }
        
        return TRUE;
 }
@@ -126,7 +150,21 @@ pdf_document_set_page (EvDocument  *document,
 {
        PdfDocument *pdf_document = PDF_DOCUMENT (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
 }
 
 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->target)
                        g_object_ref (pdf_document->target);
 
-               if (pdf_document->out)
+               if (pdf_document->out) {
                        delete 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->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->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
        }
 }
 
 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);
        
 {
        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
 }
 
 static void
@@ -191,11 +260,11 @@ pdf_document_render (EvDocument  *document,
        GdkRectangle page;
        GdkRectangle draw;
 
        GdkRectangle page;
        GdkRectangle draw;
 
-       if (!pdf_document->target)
+       if (!document_validate_page (pdf_document) || !pdf_document->target)
                return;
        
                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();
 
        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))
        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);
 }
 
                                           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)
 {
 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->out)
                delete pdf_document->out;
+       if (pdf_document->ps_out)
+               delete pdf_document->ps_out;
        if (pdf_document->doc)
                delete pdf_document->doc;
 
        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->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_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->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
 }
 
 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;
 }
 
 }