#include "pdf-document.h"
#include "ev-ps-exporter.h"
#include "ev-document-find.h"
+#include "ev-document-misc.h"
#include "gpdf-g-switch.h"
-#include "ev-document-bookmarks.h"
+#include "ev-document-links.h"
+#include "ev-document-security.h"
#include "ev-document-thumbnails.h"
#include "GlobalParams.h"
#include "GDKSplashOutputDev.h"
+#include "SplashBitmap.h"
#include "PDFDoc.h"
#include "Outline.h"
+#include "ErrorCodes.h"
#include "UnicodeMap.h"
#include "GlobalParams.h"
#include "GfxState.h"
/* full results are only possible for the rendered current page */
int current_page;
GArray *current_page_results;
- guchar *other_page_flags; /* length n_pages + 1, first element ignored */
+ int *other_page_flags; /* length n_pages + 1, first element ignored */
int start_page; /* skip this one as we iterate, since we did it first */
int search_page; /* the page we're searching now */
TextOutputDev *output_dev;
GDKSplashOutputDev *out;
PSOutputDev *ps_out;
PDFDoc *doc;
+ Links *links;
UnicodeMap *umap;
- gboolean page_valid;
+ gchar *password;
PdfDocumentSearch *search;
};
-static void pdf_document_document_bookmarks_iface_init (EvDocumentBookmarksIface *iface);
+static void pdf_document_document_links_iface_init (EvDocumentLinksIface *iface);
static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *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);
-static void pdf_document_search_free (PdfDocumentSearch *search);
-static void pdf_document_search_page_changed (PdfDocumentSearch *search);
+static void pdf_document_ps_exporter_iface_init (EvPSExporterIface *iface);
+static void pdf_document_find_iface_init (EvDocumentFindIface *iface);
+static void pdf_document_security_iface_init (EvDocumentSecurityIface *iface);
+static void pdf_document_search_free (PdfDocumentSearch *search);
+static void pdf_document_search_page_changed (PdfDocumentSearch *search);
+
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_BOOKMARKS,
- pdf_document_document_bookmarks_iface_init);
+ G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
+ pdf_document_document_links_iface_init);
G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
pdf_document_document_thumbnails_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);
+ G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
+ pdf_document_security_iface_init);
});
-static gboolean
-document_validate_page (PdfDocument *pdf_document)
+static void
+document_init_links (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;
-
- /* Update the search results available to the app since
- * we only provide full results on the current page
- */
- if (pdf_document->search)
- pdf_document_search_page_changed (pdf_document->search);
+ Page *page;
+ Object obj;
+
+ if (pdf_document->links) {
+ delete pdf_document->links;
}
+ page = pdf_document->doc->getCatalog ()->getPage (pdf_document->page);
+ pdf_document->links = new Links (page->getAnnots (&obj),
+ pdf_document->doc->getCatalog ()->getBaseURI ());
+ obj.free ();
+}
+
+static void
+document_display_page (PdfDocument *pdf_document)
+{
+ pdf_document->doc->displayPage (pdf_document->out, pdf_document->page,
+ 72 * pdf_document->scale,
+ 72 * pdf_document->scale,
+ 0, gTrue, gTrue);
+
+ document_init_links (pdf_document);
- return pdf_document->page_valid;
+ /* Update the search results available to the app since
+ * we only provide full results on the current page
+ */
+ if (pdf_document->search)
+ pdf_document_search_page_changed (pdf_document->search);
}
static gboolean
g_free (filename);
// open the PDF file, assumes ownership of filename_g
- newDoc = new PDFDoc(filename_g, 0, 0);
+ GString *password = NULL;
+ if (pdf_document->password)
+ password = new GString (pdf_document->password);
+ newDoc = new PDFDoc(filename_g, password, password);
+ if (password)
+ delete password;
if (!newDoc->isOk()) {
err = newDoc->getErrorCode();
delete newDoc;
-
- /* FIXME: Add a real error enum to EvDocument */
- g_set_error (error, G_FILE_ERROR,
- G_FILE_ERROR_FAILED,
- "Failed to load document (error %d) '%s'\n",
- err,
- uri);
+ if (err == errEncrypted) {
+ g_set_error (error, EV_DOCUMENT_ERROR,
+ EV_DOCUMENT_ERROR_ENCRYPTED,
+ "Document is encrypted.");
+ } else {
+ g_set_error (error, G_FILE_ERROR,
+ G_FILE_ERROR_FAILED,
+ "Failed to load document (error %d) '%s'\n",
+ err,
+ uri);
+ }
return FALSE;
}
if (pdf_document->out)
pdf_document->out->startDoc(pdf_document->doc->getXRef());
- pdf_document->page_valid = FALSE;
-
g_object_notify (G_OBJECT (pdf_document), "title");
return TRUE;
}
+static gboolean
+pdf_document_save (EvDocument *document,
+ const char *uri,
+ GError **error)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ char *filename;
+ gboolean retval = FALSE;
+
+ filename = g_filename_from_uri (uri, NULL, error);
+ if (filename != NULL) {
+ GString *fname = new GString (filename);
+
+ retval = pdf_document->doc->saveAs (fname);
+ }
+
+ return retval;
+}
+
static int
pdf_document_get_n_pages (EvDocument *document)
{
if (page != pdf_document->page) {
pdf_document->page = page;
- pdf_document->page_valid = FALSE;
+ document_display_page (pdf_document);
+ ev_document_page_changed (EV_DOCUMENT (pdf_document));
}
-
- ev_document_changed (document);
}
static int
}
- pdf_document->page_valid = FALSE;
+ document_display_page (pdf_document);
}
}
if (pdf_document->scale != scale) {
pdf_document->scale = scale;
- pdf_document->page_valid = FALSE;
+ document_display_page (pdf_document);
+ ev_document_scale_changed (EV_DOCUMENT (pdf_document));
}
}
static void
pdf_document_get_page_size (EvDocument *document,
+ int page,
int *width,
int *height)
{
PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ Page *the_page;
- 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;
+ /* set some default values */
+ if (width)
+ *width = 1;
+ if (height)
+ *height = 1;
+
+ if (page == -1)
+ page = pdf_document->page;
+
+ the_page = pdf_document->doc->getCatalog ()->getPage (page);
+ if (the_page) {
+ *width = (int) ((the_page->getWidth () * pdf_document->scale) + 0.5);
+ *height = (int) ((the_page->getHeight () * pdf_document->scale) + 0.5);
}
}
GdkRectangle page;
GdkRectangle draw;
- if (!document_validate_page (pdf_document) || !pdf_document->target)
+ if (!pdf_document->target)
return;
page.x = pdf_document->page_x_offset;
draw.width, draw.height);
}
-static void
-pdf_document_search_emit_found (PdfDocumentSearch *search)
+double
+pdf_document_find_get_progress (EvDocumentFind *document_find)
{
- PdfDocument *pdf_document = search->document;
- int n_pages;
- int pages_done;
- GArray *tmp_results;
- int i;
+ PdfDocumentSearch *search;
+ int n_pages, pages_done;
- n_pages = ev_document_get_n_pages (EV_DOCUMENT (search->document));
- if (search->search_page > search->start_page) {
- pages_done = search->search_page - search->start_page;
- } else if (search->search_page == search->start_page) {
- pages_done = n_pages;
- } else {
- pages_done = n_pages - search->start_page + search->search_page;
- }
+ search = PDF_DOCUMENT (document_find)->search;
- tmp_results = g_array_new (FALSE, FALSE, sizeof (EvFindResult));
- g_array_append_vals (tmp_results,
- search->current_page_results->data,
- search->current_page_results->len);
+ if (search == NULL) {
+ return 0;
+ }
- /* Now append a bogus element for each page that has a result in it,
- * that is not the current page
- */
- i = 1;
- while (i <= n_pages) {
- if (i != pdf_document->page &&
- search->other_page_flags[i]) {
- EvFindResult result;
-
- result.page_num = i;
-
- /* Use bogus coordinates, again we can't get coordinates
- * until this is the current page because TextOutputDev
- * isn't good enough
- */
- result.highlight_area.x = -1;
- result.highlight_area.y = -1;
- result.highlight_area.width = 1;
- result.highlight_area.height = 1;
-
- g_array_append_val (tmp_results, result);
- }
+ n_pages = ev_document_get_n_pages (EV_DOCUMENT (document_find));
+ if (search->search_page > search->start_page) {
+ pages_done = search->search_page - search->start_page + 1;
+ } else if (search->search_page == search->start_page) {
+ pages_done = n_pages;
+ } else {
+ pages_done = n_pages - search->start_page + search->search_page;
+ }
- ++i;
- }
+ return pages_done / (double) n_pages;
+}
- ev_document_find_found (EV_DOCUMENT_FIND (pdf_document),
- (EvFindResult*) tmp_results->data,
- tmp_results->len,
- pages_done / (double) n_pages);
+int
+pdf_document_find_page_has_results (EvDocumentFind *document_find,
+ int page)
+{
+ PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
+
+ g_return_val_if_fail (search != NULL, FALSE);
+
+ return search->other_page_flags[page];
+}
+
+int
+pdf_document_find_get_n_results (EvDocumentFind *document_find)
+{
+ PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
- g_array_free (tmp_results, TRUE);
+ if (search) {
+ return search->current_page_results->len;
+ } else {
+ return 0;
+ }
+}
+
+gboolean
+pdf_document_find_get_result (EvDocumentFind *document_find,
+ int n_result,
+ GdkRectangle *rectangle)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
+ PdfDocumentSearch *search = pdf_document->search;
+ GdkRectangle r;
+
+ if (search != NULL &&
+ n_result < search->current_page_results->len) {
+ r = g_array_index (search->current_page_results,
+ GdkRectangle, n_result);
+
+ rectangle->x = r.x + pdf_document->page_x_offset;
+ rectangle->y = r.y + pdf_document->page_y_offset;
+ rectangle->width = r.width;
+ rectangle->height = r.height;
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
static void
{
PdfDocument *pdf_document = search->document;
int current_page;
- EvFindResult result;
+ GdkRectangle result;
int xMin, yMin, xMax, yMax;
current_page = pdf_document->page;
- if (!pdf_document->page_valid) {
- /* we can't do anything until displayPage() */
- search->current_page = -1;
- return;
- }
-
if (search->current_page == current_page)
return;
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;
+ result.x = xMin;
+ result.y = yMin;
+ result.width = xMax - xMin;
+ result.height = yMax - yMin;
g_array_append_val (search->current_page_results, result);
/* Now find further results */
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;
+ result.x = xMin;
+ result.y = yMin;
+ result.width = xMax - xMin;
+ result.height = yMax - yMin;
g_array_append_val (search->current_page_results, result);
}
}
-
- /* needed for the initial current page since we don't search
- * it in the idle
- */
- search->other_page_flags[current_page] =
- search->current_page_results->len > 0;
-
- pdf_document_search_emit_found (search);
}
static gboolean
{
PdfDocumentSearch *search = (PdfDocumentSearch*) data;
PdfDocument *pdf_document = search->document;
- int n_pages;
+ int n_pages, changed_page;
double xMin, yMin, xMax, yMax;
/* Note that PDF page count is 1 through n_pages INCLUSIVE
*/
n_pages = ev_document_get_n_pages (EV_DOCUMENT (search->document));
- if (search->search_page == search->start_page) {
- goto end_search;
- }
-
if (search->output_dev == 0) {
/* First time through here... */
search->output_dev = new TextOutputDev (NULL, gTrue, gFalse, gFalse);
gFalse, gFalse, // startAtLast, stopAtLast
&xMin, &yMin, &xMax, &yMax)) {
/* This page has results */
- search->other_page_flags[search->search_page] = TRUE;
- }
+ search->other_page_flags[search->search_page] = 1;
+ } else {
+ search->other_page_flags[search->search_page] = 0;
+ }
+
+ changed_page = search->start_page;
search->search_page += 1;
if (search->search_page > n_pages) {
search->search_page = 1;
}
- /* We do this even if nothing was found, to update the percent complete */
- pdf_document_search_emit_found (search);
-
- return TRUE;
+ if (search->search_page != search->start_page) {
+ ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
+ changed_page);
+ return TRUE;
+ }
- end_search:
+end_search:
/* We're done. */
search->idle = 0; /* will return FALSE to remove */
return FALSE;
{
PdfDocument *pdf_document = PDF_DOCUMENT (document);
PdfDocumentSearch *search;
- int n_pages;
+ int n_pages, i;
gunichar *ucs4;
glong ucs4_len;
search->current_page_results = g_array_new (FALSE,
FALSE,
- sizeof (EvFindResult));
+ sizeof (GdkRectangle));
n_pages = ev_document_get_n_pages (EV_DOCUMENT (document));
- /* This is an array of bool; with the first value ignored
- * so we can index by the based-at-1 page numbers
- */
- search->other_page_flags = g_new0 (guchar, n_pages + 1);
+ search->other_page_flags = g_new0 (int, n_pages + 1);
+ for (i = 0; i <= n_pages; i++) {
+ search->other_page_flags[i] = -1;
+ }
search->document = pdf_document;
search->output_dev = 0;
search->start_page = pdf_document->page;
- search->search_page = search->start_page + 1;
- if (search->search_page > n_pages)
- search->search_page = 1;
+ search->search_page = search->start_page;
search->current_page = -1;
}
static void
-pdf_document_find_cancel (EvDocumentFind *document)
+pdf_document_find_cancel (EvDocumentFind *document)
{
PdfDocument *pdf_document = PDF_DOCUMENT (document);
g_free (search);
}
+static gboolean
+pdf_document_has_document_security (EvDocumentSecurity *document_security)
+{
+ /* FIXME: do we really need to have this? */
+ return FALSE;
+}
+
+static void
+pdf_document_set_password (EvDocumentSecurity *document_security,
+ const char *password)
+{
+ PdfDocument *document = PDF_DOCUMENT (document_security);
+
+ if (document->password)
+ g_free (document->password);
+
+ document->password = g_strdup (password);
+}
+
static void
pdf_document_ps_export_begin (EvPSExporter *exporter, const char *filename)
{
}
-/* EvDocumentBookmarks Implementation */
+/* EvDocumentLinks Implementation */
typedef struct
{
/* goo GList, not glib */
GList *items;
int index;
int level;
-} BookmarksIter;
+} LinksIter;
static gchar *
unicode_to_char (OutlineItem *outline_item,
static gboolean
-pdf_document_bookmarks_has_document_bookmarks (EvDocumentBookmarks *document_bookmarks)
+pdf_document_links_has_document_links (EvDocumentLinks *document_links)
{
- PdfDocument *pdf_document = PDF_DOCUMENT (document_bookmarks);
+ PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
Outline *outline;
- g_return_val_if_fail (PDF_IS_DOCUMENT (document_bookmarks), FALSE);
+ g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
outline = pdf_document->doc->getOutline();
if (outline->getItems() != NULL &&
return FALSE;
}
-static EvDocumentBookmarksIter *
-pdf_document_bookmarks_begin_read (EvDocumentBookmarks *document_bookmarks)
+static EvDocumentLinksIter *
+pdf_document_links_begin_read (EvDocumentLinks *document_links)
{
- PdfDocument *pdf_document = PDF_DOCUMENT (document_bookmarks);
+ PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
Outline *outline;
- BookmarksIter *iter;
+ LinksIter *iter;
GList *items;
- g_return_val_if_fail (PDF_IS_DOCUMENT (document_bookmarks), NULL);
+ g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
outline = pdf_document->doc->getOutline();
items = outline->getItems();
if (! items)
return NULL;
- iter = g_new0 (BookmarksIter, 1);
+ iter = g_new0 (LinksIter, 1);
iter->items = items;
iter->index = 0;
iter->level = 0;
- return (EvDocumentBookmarksIter *) iter;
+ return (EvDocumentLinksIter *) iter;
}
-static gboolean
-pdf_document_bookmarks_get_values (EvDocumentBookmarks *document_bookmarks,
- EvDocumentBookmarksIter *bookmarks_iter,
- char **title,
- EvDocumentBookmarksType *type,
- gint *page)
+static EvLink *
+build_link_from_action (PdfDocument *pdf_document,
+ LinkAction *link_action,
+ const char *title)
{
- PdfDocument *pdf_document = PDF_DOCUMENT (document_bookmarks);
- BookmarksIter *iter = (BookmarksIter *)bookmarks_iter;
+ EvLink *link = NULL;
+
+ if (link_action == NULL) {
+ link = ev_link_new_title (title);
+ } else if (link_action->getKind () == actionGoToR) {
+ g_warning ("actionGoToR links not implemented");
+ } else if (link_action->getKind () == actionLaunch) {
+ g_warning ("actionLaunch links not implemented");
+ } else if (link_action->getKind () == actionNamed) {
+ g_warning ("actionNamed links not implemented");
+ } else if (link_action->getKind () == actionMovie) {
+ g_warning ("actionMovie links not implemented");
+ } else if (link_action->getKind () == actionGoTo) {
+ LinkDest *link_dest;
+ LinkGoTo *link_goto;
+ Ref page_ref;
+ gint page_num = 0;
+ GString *named_dest;
+
+ link_goto = dynamic_cast <LinkGoTo *> (link_action);
+ link_dest = link_goto->getDest ();
+ named_dest = link_goto->getNamedDest ();
+
+ /* Wow! This seems excessively slow on large
+ * documents. I need to investigate more... -jrb */
+ if (link_dest != NULL) {
+ link_dest = link_dest->copy ();
+ } else if (named_dest != NULL) {
+ named_dest = named_dest->copy ();
+ link_dest = pdf_document->doc->findDest (named_dest);
+ delete named_dest;
+ }
+ if (link_dest != NULL) {
+ if (link_dest->isPageRef ()) {
+ page_ref = link_dest->getPageRef ();
+ page_num = pdf_document->doc->findPage (page_ref.num, page_ref.gen);
+ } else {
+ page_num = link_dest->getPageNum ();
+ }
+ delete link_dest;
+ }
+
+ link = ev_link_new_page (title, page_num);
+ } else if (link_action->getKind () == actionURI) {
+ LinkURI *link_uri;
+
+ link_uri = dynamic_cast <LinkURI *> (link_action);
+ link = ev_link_new_external
+ (title, link_uri->getURI()->getCString());
+ } else if (link_action->getKind () == actionUnknown) {
+ LinkUnknown *link_unknown;
+
+ link_unknown = dynamic_cast <LinkUnknown *> (link_action);
+
+ g_warning ("Unknown link type %s",
+ link_unknown->getAction()->getCString());
+ }
+
+ return link;
+}
+
+/* FIXME This returns a new object every time, probably we should cache it
+ in the iter */
+static EvLink *
+pdf_document_links_get_link (EvDocumentLinks *document_links,
+ EvDocumentLinksIter *links_iter)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
+ LinksIter *iter = (LinksIter *)links_iter;
OutlineItem *anItem;
LinkAction *link_action;
- LinkDest *link_dest = NULL;
- LinkURI *link_uri = NULL;
- LinkGoTo *link_goto = NULL;
- GString *named_dest;
Unicode *link_title;
- Ref page_ref;
- gint page_num = -1;
+ const char *title;
- g_return_val_if_fail (PDF_IS_DOCUMENT (document_bookmarks), FALSE);
+ g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (title != NULL, FALSE);
- g_return_val_if_fail (type != NULL, FALSE);
- g_return_val_if_fail (page != NULL, FALSE);
anItem = (OutlineItem *)iter->items->get(iter->index);
link_action = anItem->getAction ();
link_title = anItem->getTitle ();
+ title = unicode_to_char (anItem, pdf_document->umap);
- if (link_action) {
- switch (link_action->getKind ()) {
-
- case actionGoTo:
- link_goto = dynamic_cast <LinkGoTo *> (link_action);
- link_dest = link_goto->getDest ();
- named_dest = link_goto->getNamedDest ();
-
- /* Wow! This seems excessively slow on large
- * documents. I need to investigate more... -jrb */
- if (link_dest != NULL) {
- link_dest = link_dest->copy ();
- } else if (named_dest != NULL) {
- named_dest = named_dest->copy ();
- link_dest = pdf_document->doc->findDest (named_dest);
- delete named_dest;
- }
- if (link_dest != NULL) {
- if (link_dest->isPageRef ()) {
- page_ref = link_dest->getPageRef ();
- page_num = pdf_document->doc->findPage (page_ref.num, page_ref.gen);
- } else {
- page_num = link_dest->getPageNum ();
- }
-
- delete link_dest;
- }
-
- break;
- case actionURI:
- link_uri = dynamic_cast <LinkURI *> (link_action);
- break;
-
- case actionNamed:
- /*Skip, for now */
- default:
- g_warning ("Unknown link action type: %d", link_action->getKind ());
- }
-
- *title = g_strdup (unicode_to_char (anItem, pdf_document->umap));
- } else if (link_title) {
- *title = g_strdup (unicode_to_char (anItem, pdf_document->umap));
- }
-
- *type = EV_DOCUMENT_BOOKMARKS_TYPE_LINK;
- *page = page_num;
-
- return TRUE;
+ return build_link_from_action (pdf_document, link_action, title);
}
-static EvDocumentBookmarksIter *
-pdf_document_bookmarks_get_child (EvDocumentBookmarks *document_bookmarks,
- EvDocumentBookmarksIter *bookmarks_iter)
+static EvDocumentLinksIter *
+pdf_document_links_get_child (EvDocumentLinks *document_links,
+ EvDocumentLinksIter *links_iter)
{
- BookmarksIter *iter = (BookmarksIter *)bookmarks_iter;
- BookmarksIter *child_iter;
+ LinksIter *iter = (LinksIter *)links_iter;
+ LinksIter *child_iter;
OutlineItem *anItem;
- g_return_val_if_fail (PDF_IS_DOCUMENT (document_bookmarks), FALSE);
+ g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
anItem = (OutlineItem *)iter->items->get(iter->index);
anItem->open ();
if (! (anItem->hasKids() && anItem->getKids()) )
return NULL;
- child_iter = g_new0 (BookmarksIter, 1);
+ child_iter = g_new0 (LinksIter, 1);
child_iter->index = 0;
child_iter->level = iter->level + 1;
child_iter->items = anItem->getKids ();
g_assert (child_iter->items);
- return (EvDocumentBookmarksIter *) child_iter;
+ return (EvDocumentLinksIter *) child_iter;
}
static gboolean
-pdf_document_bookmarks_next (EvDocumentBookmarks *document_bookmarks,
- EvDocumentBookmarksIter *bookmarks_iter)
+pdf_document_links_next (EvDocumentLinks *document_links,
+ EvDocumentLinksIter *links_iter)
{
- BookmarksIter *iter = (BookmarksIter *) bookmarks_iter;
+ LinksIter *iter = (LinksIter *) links_iter;
- g_return_val_if_fail (PDF_IS_DOCUMENT (document_bookmarks), FALSE);
+ g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
iter->index++;
if (iter->index >= iter->items->getLength())
}
static void
-pdf_document_bookmarks_free_iter (EvDocumentBookmarks *document_bookmarks,
- EvDocumentBookmarksIter *iter)
+pdf_document_links_free_iter (EvDocumentLinks *document_links,
+ EvDocumentLinksIter *iter)
{
- g_return_if_fail (PDF_IS_DOCUMENT (document_bookmarks));
+ g_return_if_fail (PDF_IS_DOCUMENT (document_links));
g_return_if_fail (iter != NULL);
/* FIXME: Should I close all the nodes?? Free them? */
{
PdfDocument *pdf_document = PDF_DOCUMENT (object);
+ if (pdf_document->links) {
+ delete pdf_document->links;
+ }
+
if (pdf_document->umap) {
pdf_document->umap->decRefCnt ();
pdf_document->umap = NULL;
if (!info_dict->lookup ((gchar *)key, &obj)->isString ()) {
obj.free ();
- return g_strdup (_("Unknown"));
+ return NULL;
}
value = obj.getString ();
char *title = NULL;
Object info;
+ if (pdf_document->doc == NULL)
+ return NULL;
pdf_document->doc->getDocInfo (&info);
if (info.isDict ()) {
return title;
}
+static char *
+pdf_document_get_text (EvDocument *document, GdkRectangle *rect)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ GString *sel_text = new GString;
+ const char *text;
+ int x1, y1, x2, y2;
+
+ x1 = rect->x - pdf_document->page_x_offset;
+ y1 = rect->y - pdf_document->page_y_offset;
+ x2 = x1 + rect->width;
+ y2 = y1 + rect->height;
+
+ sel_text = pdf_document->out->getText (x1, y1, x2, y2);
+ text = sel_text->getCString ();
+
+ return text ? g_strdup (text) : NULL;
+}
+
+static EvLink *
+pdf_document_get_link (EvDocument *document, int x, int y)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document);
+ LinkAction *action;
+ double link_x, link_y;
+
+ if (pdf_document->links == NULL) {
+ return NULL;
+ }
+
+ /* Offset */
+ link_x = x - pdf_document->page_x_offset;
+ link_y = y - pdf_document->page_y_offset;
+
+ /* Inverse y */
+ link_y = pdf_document->out->getBitmapHeight() - link_y;
+
+ /* Zoom */
+ link_x = link_x / pdf_document->scale;
+ link_y = link_y / pdf_document->scale;
+
+ action = pdf_document->links->find (link_x, link_y);
+
+ if (action) {
+ return build_link_from_action (pdf_document, action, "");
+ } else {
+ return NULL;
+ }
+}
+
static void
pdf_document_get_property (GObject *object,
guint prop_id,
pdf_document_document_iface_init (EvDocumentIface *iface)
{
iface->load = pdf_document_load;
+ iface->save = pdf_document_save;
+ iface->get_text = pdf_document_get_text;
+ iface->get_link = pdf_document_get_link;
iface->get_n_pages = pdf_document_get_n_pages;
iface->set_page = pdf_document_set_page;
iface->get_page = pdf_document_get_page;
pdf_document_find_iface_init (EvDocumentFindIface *iface)
{
iface->begin = pdf_document_find_begin;
+ iface->get_n_results = pdf_document_find_get_n_results;
+ iface->get_result = pdf_document_find_get_result;
+ iface->page_has_results = pdf_document_find_page_has_results;
+ iface->get_progress = pdf_document_find_get_progress;
iface->cancel = pdf_document_find_cancel;
}
static void
-pdf_document_document_bookmarks_iface_init (EvDocumentBookmarksIface *iface)
+pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
+{
+ iface->has_document_security = pdf_document_has_document_security;
+ iface->set_password = pdf_document_set_password;
+}
+
+static void
+pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
{
- iface->has_document_bookmarks = pdf_document_bookmarks_has_document_bookmarks;
- iface->begin_read = pdf_document_bookmarks_begin_read;
- iface->get_values = pdf_document_bookmarks_get_values;
- iface->get_child = pdf_document_bookmarks_get_child;
- iface->next = pdf_document_bookmarks_next;
- iface->free_iter = pdf_document_bookmarks_free_iter;
+ iface->has_document_links = pdf_document_links_has_document_links;
+ iface->begin_read = pdf_document_links_begin_read;
+ iface->get_link = pdf_document_links_get_link;
+ iface->get_child = pdf_document_links_get_child;
+ iface->next = pdf_document_links_next;
+ iface->free_iter = pdf_document_links_free_iter;
}
/* Thumbnails */
+
+static GdkPixbuf *
+bitmap_to_pixbuf (SplashBitmap *bitmap,
+ GdkPixbuf *target,
+ gint x_offset,
+ gint y_offset)
+{
+ gint width;
+ gint height;
+ SplashColorPtr dataPtr;
+ int x, y;
+
+ gboolean target_has_alpha;
+ gint target_rowstride;
+ guchar *target_data;
+
+ width = bitmap->getWidth ();
+ height = bitmap->getHeight ();
+
+ if (width + x_offset > gdk_pixbuf_get_width (target))
+ width = gdk_pixbuf_get_width (target) - x_offset;
+ if (height + y_offset > gdk_pixbuf_get_height (target))
+ height = gdk_pixbuf_get_height (target) - x_offset;
+
+ target_has_alpha = gdk_pixbuf_get_has_alpha (target);
+ target_rowstride = gdk_pixbuf_get_rowstride (target);
+ target_data = gdk_pixbuf_get_pixels (target);
+
+ dataPtr = bitmap->getDataPtr ();
+
+ for (y = 0; y < height; y++) {
+ SplashRGB8 *p;
+ SplashRGB8 rgb;
+ guchar *q;
+
+ p = dataPtr.rgb8 + y * width;
+ q = target_data + ((y + y_offset) * target_rowstride +
+ x_offset * (target_has_alpha?4:3));
+ for (x = 0; x < width; x++) {
+ rgb = *p++;
+
+ *q++ = splashRGB8R (rgb);
+ *q++ = splashRGB8G (rgb);
+ *q++ = splashRGB8B (rgb);
+
+ if (target_has_alpha)
+ q++;
+ }
+ }
+
+ return target;
+}
+
+
static GdkPixbuf *
pdf_document_thumbnails_get_page_pixbuf (PdfDocument *pdf_document,
gdouble scale_factor,
gint width,
gint height)
{
- GdkPixmap *pixmap;
- GDKSplashOutputDev *output;
+ SplashOutputDev *output;
GdkPixbuf *pixbuf;
+ SplashColor color;
- pixmap = gdk_pixmap_new (pdf_document->target,
- width, height, -1);
+ color.rgb8 = splashMakeRGB8 (255, 255, 255);
- output = new GDKSplashOutputDev (gdk_drawable_get_screen (pdf_document->target),
- NULL, NULL);
+ output = new SplashOutputDev (splashModeRGB8, gFalse, color);
output->startDoc (pdf_document->doc->getXRef());
pdf_document->doc->displayPage (output,
page_num + 1,
72*scale_factor,
72*scale_factor,
0, gTrue, gFalse);
- output->redraw (0, 0,
- pixmap,
- 0, 0,
- width, height);
- pixbuf = gdk_pixbuf_get_from_drawable (NULL,
- pixmap,
- NULL,
- 0, 0,
- 0, 0,
- width, height);
- gdk_drawable_unref (pixmap);
+
+ pixbuf = ev_document_misc_get_thumbnail_frame (output->getBitmap()->getWidth(),
+ output->getBitmap()->getHeight(),
+ NULL);
+ bitmap_to_pixbuf (output->getBitmap(), pixbuf, 1, 1);
delete output;
+
return pixbuf;
}
+static void
+pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
+ gint page,
+ gint suggested_width,
+ gint *width,
+ gint *height)
+{
+ PdfDocument *pdf_document = PDF_DOCUMENT (document_thumbnails);
+ Page *the_page;
+ Object the_thumb;
+ Thumb *thumb = NULL;
+ gdouble page_ratio;
+
+ the_page = pdf_document->doc->getCatalog ()->getPage (page);
+ the_page->getThumb (&the_thumb);
+
+ if (!(the_thumb.isNull () || the_thumb.isNone())) {
+ /* Build the thumbnail object */
+ thumb = new Thumb(pdf_document->doc->getXRef (),
+ &the_thumb);
+
+ *width = thumb->getWidth ();
+ *height = thumb->getHeight ();
+ } else {
+ page_ratio = the_page->getHeight () / the_page->getWidth ();
+ *width = suggested_width;
+ *height = (gint) (suggested_width * page_ratio);
+ }
+}
+
static GdkPixbuf *
pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
gint page,
Object the_thumb;
Thumb *thumb = NULL;
gboolean have_ethumbs = FALSE;
+ gdouble page_ratio;
+ gint dest_height;
/* getPage seems to want page + 1 for some reason; */
the_page = pdf_document->doc->getCatalog ()->getPage (page + 1);
the_page->getThumb(&the_thumb);
+ page_ratio = the_page->getHeight () / the_page->getWidth ();
+ dest_height = (gint) (width * page_ratio);
+
+
if (!(the_thumb.isNull () || the_thumb.isNone())) {
/* Build the thumbnail object */
thumb = new Thumb(pdf_document->doc->getXRef (),
GdkPixbuf *tmp_pixbuf;
data = thumb->getPixbufData();
- /* FISME: scale the image if it's not an appropriate size */
tmp_pixbuf = gdk_pixbuf_new_from_data (data,
GDK_COLORSPACE_RGB,
FALSE,
thumb->getHeight (),
thumb->getWidth () * 3,
NULL, NULL);
-
- thumbnail = tmp_pixbuf;
+ /* FIXME: do we want to check that the thumb's size isn't ridiculous?? */
+ thumbnail = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
+ g_object_unref (tmp_pixbuf);
} else {
- gdouble page_ratio;
gdouble scale_factor;
- gint dest_height;
- page_ratio = the_page->getHeight () / the_page->getWidth ();
scale_factor = (gdouble)width / the_page->getWidth ();
- dest_height = (gint) (width * page_ratio);
thumbnail = pdf_document_thumbnails_get_page_pixbuf (pdf_document,
scale_factor,
page,
width,
dest_height);
-
- /* FIXME: Actually get the image... */
}
return thumbnail;
pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
{
iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
+ iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
}
pdf_document->page_y_offset = 0;
pdf_document->scale = 1.;
- pdf_document->page_valid = FALSE;
+ pdf_document->password = NULL;
}