glib/poppler-document.cc | 347 ++++++++++++++++++++++++++---------- glib/poppler-document.h | 18 + glib/reference/poppler-docs.sgml | 4 glib/reference/poppler-sections.txt | 8 poppler/Object.h | 7 poppler/PDFDoc.cc | 79 +++++++- poppler/PDFDoc.h | 41 ++++ poppler/XRef.cc | 39 ++++ poppler/XRef.h | 14 + 9 files changed, 456 insertions(+), 101 deletions(-)
New commits: commit 82476b0d6967ce5e61dce4666fe556edd63c16e6 Author: Jakub Kucharski <[email protected]> Date: Mon Jun 6 22:17:57 2016 +0200 glib: Added document property setters & simplified getters https://bugs.freedesktop.org/show_bug.cgi?id=36653 diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 61d92e8..63eae7c 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -1,6 +1,8 @@ /* poppler-document.cc: glib wrapper for poppler * Copyright (C) 2005, Red Hat, Inc. * + * Copyright (C) 2016 Jakub Kucharski <[email protected]> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -22,6 +24,7 @@ #ifndef __GI_SCANNER__ #include <goo/GooList.h> #include <splash/SplashBitmap.h> +#include <DateInfo.h> #include <GlobalParams.h> #include <PDFDoc.h> #include <Outline.h> @@ -711,6 +714,10 @@ poppler_document_find_dest (PopplerDocument *document, char *_poppler_goo_string_to_utf8(GooString *s) { + if (s == NULL) { + return NULL; + } + char *result; if (s->hasUnicodeMarker()) { @@ -737,40 +744,28 @@ char *_poppler_goo_string_to_utf8(GooString *s) return result; } -static gchar * -info_dict_get_string (Dict *info_dict, const gchar *key) +static GooString * +_poppler_goo_string_from_utf8(const gchar *src) { - Object obj; - GooString *goo_value; - gchar *result; - - if (!info_dict->lookup ((gchar *)key, &obj)->isString ()) { - obj.free (); + if (src == NULL) { return NULL; } - goo_value = obj.getString (); - result = _poppler_goo_string_to_utf8(goo_value); - obj.free (); + gsize outlen; - return result; -} + gchar *utf16 = g_convert (src, -1, "UTF-16BE", "UTF-8", NULL, &outlen, NULL); + if (utf16 == NULL) { + return NULL; + } -static time_t -info_dict_get_date (Dict *info_dict, const gchar *key) -{ - Object obj; - time_t result; + GooString *result = new GooString (utf16, outlen); + g_free (utf16); - if (!info_dict->lookup ((gchar *)key, &obj)->isString ()) { - obj.free (); - return (time_t)-1; + if (!result->hasUnicodeMarker()) { + result->insert(0, 0xff); + result->insert(0, 0xfe); } - if (!_poppler_convert_pdf_date_to_gtime (obj.getString (), &result)) - result = (time_t)-1; - obj.free (); - return result; } @@ -879,17 +874,39 @@ poppler_document_get_pdf_version (PopplerDocument *document, gchar * poppler_document_get_title (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Title"); - obj.free (); + GooString *goo_title = document->doc->getDocInfoTitle(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_title); + delete goo_title; - return retval; + return utf8; +} + +/** + * poppler_document_set_title: + * @document: A #PopplerDocument + * @title: A new title + * + * Sets the document's title. If @title is %NULL, Title entry + * is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_title (PopplerDocument *document, const gchar *title) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_title; + if (!title) { + goo_title = NULL; + } else { + goo_title = _poppler_goo_string_from_utf8(title); + if (!goo_title) + return; + } + document->doc->setDocInfoTitle(goo_title); } /** @@ -906,17 +923,39 @@ poppler_document_get_title (PopplerDocument *document) gchar * poppler_document_get_author (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Author"); - obj.free (); + GooString *goo_author = document->doc->getDocInfoAuthor(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_author); + delete goo_author; - return retval; + return utf8; +} + +/** + * poppler_document_set_author: + * @document: A #PopplerDocument + * @author: A new author + * + * Sets the document's author. If @author is %NULL, Author + * entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_author (PopplerDocument *document, const gchar *author) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_author; + if (!author) { + goo_author = NULL; + } else { + goo_author = _poppler_goo_string_from_utf8(author); + if (!goo_author) + return; + } + document->doc->setDocInfoAuthor(goo_author); } /** @@ -933,17 +972,39 @@ poppler_document_get_author (PopplerDocument *document) gchar * poppler_document_get_subject (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Subject"); - obj.free (); + GooString *goo_subject = document->doc->getDocInfoSubject(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_subject); + delete goo_subject; - return retval; + return utf8; +} + +/** + * poppler_document_set_subject: + * @document: A #PopplerDocument + * @subject: A new subject + * + * Sets the document's subject. If @subject is %NULL, Subject + * entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_subject (PopplerDocument *document, const gchar *subject) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_subject; + if (!subject) { + goo_subject = NULL; + } else { + goo_subject = _poppler_goo_string_from_utf8(subject); + if (!goo_subject) + return; + } + document->doc->setDocInfoSubject(goo_subject); } /** @@ -960,17 +1021,39 @@ poppler_document_get_subject (PopplerDocument *document) gchar * poppler_document_get_keywords (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Keywords"); - obj.free (); + GooString *goo_keywords = document->doc->getDocInfoKeywords(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_keywords); + delete goo_keywords; - return retval; + return utf8; +} + +/** + * poppler_document_set_keywords: + * @document: A #PopplerDocument + * @keywords: New keywords + * + * Sets the document's keywords. If @keywords is %NULL, + * Keywords entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_keywords (PopplerDocument *document, const gchar *keywords) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_keywords; + if (!keywords) { + goo_keywords = NULL; + } else { + goo_keywords = _poppler_goo_string_from_utf8(keywords); + if (!goo_keywords) + return; + } + document->doc->setDocInfoKeywords(goo_keywords); } /** @@ -989,17 +1072,39 @@ poppler_document_get_keywords (PopplerDocument *document) gchar * poppler_document_get_creator (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Creator"); - obj.free (); + GooString *goo_creator = document->doc->getDocInfoCreator(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_creator); + delete goo_creator; - return retval; + return utf8; +} + +/** + * poppler_document_set_creator: + * @document: A #PopplerDocument + * @creator: A new creator + * + * Sets the document's creator. If @creator is %NULL, Creator + * entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_creator (PopplerDocument *document, const gchar *creator) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_creator; + if (!creator) { + goo_creator = NULL; + } else { + goo_creator = _poppler_goo_string_from_utf8(creator); + if (!goo_creator) + return; + } + document->doc->setDocInfoCreator(goo_creator); } /** @@ -1018,17 +1123,39 @@ poppler_document_get_creator (PopplerDocument *document) gchar * poppler_document_get_producer (PopplerDocument *document) { - Object obj; - gchar *retval = NULL; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_string (obj.getDict(), "Producer"); - obj.free (); + GooString *goo_producer = document->doc->getDocInfoProducer(); + gchar *utf8 = _poppler_goo_string_to_utf8(goo_producer); + delete goo_producer; - return retval; + return utf8; +} + +/** + * poppler_document_set_producer: + * @document: A #PopplerDocument + * @producer: A new producer + * + * Sets the document's producer. If @producer is %NULL, + * Producer entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_producer (PopplerDocument *document, const gchar *producer) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *goo_producer; + if (!producer) { + goo_producer = NULL; + } else { + goo_producer = _poppler_goo_string_from_utf8(producer); + if (!goo_producer) + return; + } + document->doc->setDocInfoProducer(goo_producer); } /** @@ -1044,17 +1171,38 @@ poppler_document_get_producer (PopplerDocument *document) time_t poppler_document_get_creation_date (PopplerDocument *document) { - Object obj; - time_t retval = (time_t)-1; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), (time_t)-1); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_date (obj.getDict(), "CreationDate"); - obj.free (); + GooString *str = document->doc->getDocInfoCreatDate(); + if (str == NULL) { + return (time_t)-1; + } - return retval; + time_t date; + gboolean success = _poppler_convert_pdf_date_to_gtime (str, &date); + delete str; + + return (success) ? date : (time_t)-1; +} + +/** + * poppler_document_set_creation_date: + * @document: A #PopplerDocument + * @creation_date: A new creation date + * + * Sets the document's creation date. If @creation_date is -1, CreationDate + * entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_creation_date (PopplerDocument *document, + time_t creation_date) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *str = creation_date == (time_t)-1 ? NULL : timeToDateString (&creation_date); + document->doc->setDocInfoCreatDate (str); } /** @@ -1070,17 +1218,38 @@ poppler_document_get_creation_date (PopplerDocument *document) time_t poppler_document_get_modification_date (PopplerDocument *document) { - Object obj; - time_t retval = (time_t)-1; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), (time_t)-1); - document->doc->getDocInfo (&obj); - if (obj.isDict ()) - retval = info_dict_get_date (obj.getDict(), "ModDate"); - obj.free (); + GooString *str = document->doc->getDocInfoModDate(); + if (str == NULL) { + return (time_t)-1; + } + + time_t date; + gboolean success = _poppler_convert_pdf_date_to_gtime (str, &date); + delete str; - return retval; + return (success) ? date : (time_t)-1; +} + +/** + * poppler_document_set_modification_date: + * @document: A #PopplerDocument + * @modification_date: A new modification date + * + * Sets the document's modification date. If @modification_date is -1, ModDate + * entry is removed from the document's Info dictionary. + * + * Since: 0.46 + **/ +void +poppler_document_set_modification_date (PopplerDocument *document, + time_t modification_date) +{ + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + GooString *str = modification_date == (time_t)-1 ? NULL : timeToDateString (&modification_date); + document->doc->setDocInfoModDate (str); } /** diff --git a/glib/poppler-document.h b/glib/poppler-document.h index a34e88c..fb0ac72 100644 --- a/glib/poppler-document.h +++ b/glib/poppler-document.h @@ -1,6 +1,8 @@ /* poppler-document.h: glib interface to poppler * Copyright (C) 2004, Red Hat, Inc. * + * Copyright (C) 2016 Jakub Kucharski <[email protected]> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -201,13 +203,29 @@ void poppler_document_get_pdf_version (PopplerDocument *doc guint *major_version, guint *minor_version); gchar *poppler_document_get_title (PopplerDocument *document); +void poppler_document_set_title (PopplerDocument *document, + const gchar *title); gchar *poppler_document_get_author (PopplerDocument *document); +void poppler_document_set_author (PopplerDocument *document, + const gchar *author); gchar *poppler_document_get_subject (PopplerDocument *document); +void poppler_document_set_subject (PopplerDocument *document, + const gchar *subject); gchar *poppler_document_get_keywords (PopplerDocument *document); +void poppler_document_set_keywords (PopplerDocument *document, + const gchar *keywords); gchar *poppler_document_get_creator (PopplerDocument *document); +void poppler_document_set_creator (PopplerDocument *document, + const gchar *creator); gchar *poppler_document_get_producer (PopplerDocument *document); +void poppler_document_set_producer (PopplerDocument *document, + const gchar *producer); time_t poppler_document_get_creation_date (PopplerDocument *document); +void poppler_document_set_creation_date (PopplerDocument *document, + time_t creation_date); time_t poppler_document_get_modification_date (PopplerDocument *document); +void poppler_document_set_modification_date (PopplerDocument *document, + time_t modification_date); gboolean poppler_document_is_linearized (PopplerDocument *document); PopplerPageLayout poppler_document_get_page_layout (PopplerDocument *document); PopplerPageMode poppler_document_get_page_mode (PopplerDocument *document); diff --git a/glib/reference/poppler-docs.sgml b/glib/reference/poppler-docs.sgml index ec8a3eb..5db818f 100644 --- a/glib/reference/poppler-docs.sgml +++ b/glib/reference/poppler-docs.sgml @@ -69,6 +69,10 @@ <title>Index of new symbols in 0.33</title> <xi:include href="xml/api-index-0.33.xml"><xi:fallback /></xi:include> </index> + <index id="api-index-0-46"> + <title>Index of new symbols in 0.46</title> + <xi:include href="xml/api-index-0.46.xml"><xi:fallback /></xi:include> + </index> <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> </book> diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index 92bf432..d597c2d 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -134,13 +134,21 @@ poppler_document_get_id poppler_document_get_pdf_version_string poppler_document_get_pdf_version poppler_document_get_title +poppler_document_set_title poppler_document_get_author +poppler_document_set_author poppler_document_get_subject +poppler_document_set_subject poppler_document_get_keywords +poppler_document_set_keywords poppler_document_get_creator +poppler_document_set_creator poppler_document_get_producer +poppler_document_set_producer poppler_document_get_creation_date +poppler_document_set_creation_date poppler_document_get_modification_date +poppler_document_set_modification_date poppler_document_get_page_layout poppler_document_get_page_mode poppler_document_get_permissions commit 4f7c67b59b9c55b9b896378d3adbecbb73f6eb63 Author: Jakub Kucharski <[email protected]> Date: Tue Feb 23 16:46:43 2016 +0100 Added DocInfo setters & getters https://bugs.freedesktop.org/show_bug.cgi?id=36653 diff --git a/poppler/Object.h b/poppler/Object.h index b9cae28..0c7767c 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -21,6 +21,7 @@ // Copyright (C) 2013 Thomas Freitag <[email protected]> // Copyright (C) 2013 Adrian Johnson <[email protected]> // Copyright (C) 2013 Adrian Perez de Castro <[email protected]> +// Copyright (C) 2016 Jakub Kucharski <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -235,6 +236,7 @@ public: int dictGetLength(); void dictAdd(char *key, Object *val); void dictSet(const char *key, Object *val); + void dictRemove(const char *key); GBool dictIs(const char *dictType); Object *dictLookup(const char *key, Object *obj, int recursion = 0); Object *dictLookupNF(const char *key, Object *obj); @@ -318,7 +320,10 @@ inline void Object::dictAdd(char *key, Object *val) { OBJECT_TYPE_CHECK(objDict); dict->add(key, val); } inline void Object::dictSet(const char *key, Object *val) - { OBJECT_TYPE_CHECK(objDict); dict->set(key, val); } + { OBJECT_TYPE_CHECK(objDict); dict->set(key, val); } + +inline void Object::dictRemove(const char *key) + { OBJECT_TYPE_CHECK(objDict); dict->remove(key); } inline GBool Object::dictIs(const char *dictType) { OBJECT_TYPE_CHECK(objDict); return dict->is(dictType); } diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index 703a4fd..c91d6e4 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -34,6 +34,7 @@ // Copyright (C) 2015 Li Junling <[email protected]> // Copyright (C) 2015 André Guerreiro <[email protected]> // Copyright (C) 2015 André Esser <[email protected]> +// Copyright (C) 2016 Jakub Kucharski <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -600,6 +601,72 @@ GBool PDFDoc::isLinearized(GBool tryingToReconstruct) { } } +void PDFDoc::setDocInfoModified(Object *infoObj) +{ + Object infoObjRef; + getDocInfoNF(&infoObjRef); + xref->setModifiedObject(infoObj, infoObjRef.getRef()); + infoObjRef.free(); +} + +void PDFDoc::setDocInfoStringEntry(const char *key, GooString *value) +{ + GBool removeEntry = !value || value->getLength() == 0; + + Object infoObj; + getDocInfo(&infoObj); + + if (infoObj.isNull() && removeEntry) { + // No info dictionary, so no entry to remove. + return; + } + + createDocInfoIfNoneExists(&infoObj); + + Object gooStrObj; + if (removeEntry) { + gooStrObj.initNull(); + } else { + gooStrObj.initString(value); + } + + // gooStrObj is set to value or null by now. The latter will cause a removal. + infoObj.dictSet(key, &gooStrObj); + + if (infoObj.dictGetLength() == 0) { + // Info dictionary is empty. Remove it altogether. + removeDocInfo(); + } else { + setDocInfoModified(&infoObj); + } + + infoObj.free(); +} + +GooString *PDFDoc::getDocInfoStringEntry(const char *key) { + Object infoObj; + getDocInfo(&infoObj); + if (infoObj.isNull()) { + return NULL; + } + + Object entryObj; + infoObj.dictLookup(key, &entryObj); + + GooString *result; + + if (entryObj.isString()) { + result = entryObj.takeString(); + } else { + result = NULL; + } + + entryObj.free(); + infoObj.free(); + + return result; +} + static GBool get_id (GooString *encodedidstring, GooString *id) { const char *encodedid = encodedidstring->getCString(); diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h index 3a65ecb..daff3f4 100644 --- a/poppler/PDFDoc.h +++ b/poppler/PDFDoc.h @@ -29,6 +29,7 @@ // Copyright (C) 2013 Adrian Perez de Castro <[email protected]> // Copyright (C) 2015 André Guerreiro <[email protected]> // Copyright (C) 2015 André Esser <[email protected]> +// Copyright (C) 2016 Jakub Kucharski <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -231,6 +232,43 @@ public: Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); } Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); } + // Create and return the document's Info dictionary if none exists. + // Otherwise return the existing one. + Object *createDocInfoIfNoneExists(Object *obj) { return xref->createDocInfoIfNoneExists(obj); } + + // Remove the document's Info dictionary and update the trailer dictionary. + void removeDocInfo() { xref->removeDocInfo(); } + + // Set doc info string entry. NULL or empty value will cause a removal. + // Takes ownership of value. + void setDocInfoStringEntry(const char *key, GooString *value); + + // Set document's properties in document's Info dictionary. + // NULL or empty value will cause a removal. + // Takes ownership of value. + void setDocInfoTitle(GooString *title) { setDocInfoStringEntry("Title", title); } + void setDocInfoAuthor(GooString *author) { setDocInfoStringEntry("Author", author); } + void setDocInfoSubject(GooString *subject) { setDocInfoStringEntry("Subject", subject); } + void setDocInfoKeywords(GooString *keywords) { setDocInfoStringEntry("Keywords", keywords); } + void setDocInfoCreator(GooString *creator) { setDocInfoStringEntry("Creator", creator); } + void setDocInfoProducer(GooString *producer) { setDocInfoStringEntry("Producer", producer); } + void setDocInfoCreatDate(GooString *creatDate) { setDocInfoStringEntry("CreationDate", creatDate); } + void setDocInfoModDate(GooString *modDate) { setDocInfoStringEntry("ModDate", modDate); } + + // Get document's properties from document's Info dictionary. + // Returns NULL on fail. + // Returned GooStrings should be freed by the caller. + GooString *getDocInfoStringEntry(const char *key); + + GooString *getDocInfoTitle() { return getDocInfoStringEntry("Title"); } + GooString *getDocInfoAuthor() { return getDocInfoStringEntry("Author"); } + GooString *getDocInfoSubject() { return getDocInfoStringEntry("Subject"); } + GooString *getDocInfoKeywords() { return getDocInfoStringEntry("Keywords"); } + GooString *getDocInfoCreator() { return getDocInfoStringEntry("Creator"); } + GooString *getDocInfoProducer() { return getDocInfoStringEntry("Producer"); } + GooString *getDocInfoCreatDate() { return getDocInfoStringEntry("CreationDate"); } + GooString *getDocInfoModDate() { return getDocInfoStringEntry("ModDate"); } + // Return the PDF version specified by the file. int getPDFMajorVersion() { return pdfMajorVersion; } int getPDFMinorVersion() { return pdfMinorVersion; } @@ -315,6 +353,9 @@ private: Goffset getMainXRefEntriesOffset(GBool tryingToReconstruct = gFalse); long long strToLongLong(char *s); + // Mark the document's Info dictionary as modified. + void setDocInfoModified(Object *infoObj); + GooString *fileName; #ifdef _WIN32 wchar_t *fileNameU; diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 8570819..f88c632 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -1292,6 +1292,40 @@ Object *XRef::getDocInfoNF(Object *obj) { return trailerDict.dictLookupNF("Info", obj); } +Object *XRef::createDocInfoIfNoneExists(Object *obj) { + getDocInfo(obj); + + if (!obj->isNull()) { + return obj; + } + + obj->initDict(this); + + Ref ref = addIndirectObject(obj); + + Object objRef; + objRef.initRef(ref.num, ref.gen); + + trailerDict.dictSet("Info", &objRef); + + objRef.free(); + + return obj; +} + +void XRef::removeDocInfo() { + Object infoObjRef; + getDocInfoNF(&infoObjRef); + if (infoObjRef.isNull()) { + return; + } + + trailerDict.dictRemove("Info"); + + removeIndirectObject(infoObjRef.getRef()); + infoObjRef.free(); +} + GBool XRef::getStreamEnd(Goffset streamStart, Goffset *streamEnd) { int a, b, m; diff --git a/poppler/XRef.h b/poppler/XRef.h index 739b537..245b14b 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -150,6 +150,13 @@ public: Object *getDocInfo(Object *obj); Object *getDocInfoNF(Object *obj); + // Create and return the document's Info dictionary if none exists. + // Otherwise return the existing one. + Object *createDocInfoIfNoneExists(Object *obj); + + // Remove the document's Info dictionary and update the trailer dictionary. + void removeDocInfo(); + // Return the number of objects in the xref table. int getNumObjects() { return size; } commit e2851dd8166fa5a1df0518959ad71c9d81bd9152 Author: Jakub Kucharski <[email protected]> Date: Tue Feb 23 15:36:43 2016 +0100 Added XRef modification flag https://bugs.freedesktop.org/show_bug.cgi?id=36653 diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index 9fc43e5..703a4fd 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -865,17 +865,7 @@ int PDFDoc::saveAs(GooString *name, PDFWriteMode mode) { } int PDFDoc::saveAs(OutStream *outStr, PDFWriteMode mode) { - - // find if we have updated objects - GBool updated = gFalse; - for(int i=0; i<xref->getNumObjects(); i++) { - if (xref->getEntry(i)->getFlag(XRefEntry::Updated)) { - updated = gTrue; - break; - } - } - - if (!updated && mode == writeStandard) { + if (!xref->isModified() && mode == writeStandard) { // simply copy the original file saveWithoutChangesAs (outStr); } else if (mode == writeForceRewrite) { diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 3d032bc..8570819 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -24,6 +24,7 @@ // Copyright (C) 2012, 2013 Fabio D'Urso <[email protected]> // Copyright (C) 2013, 2014 Adrian Johnson <[email protected]> // Copyright (C) 2013 Pino Toscano <[email protected]> +// Copyright (C) 2016 Jakub Kucharski <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -286,6 +287,7 @@ void XRef::init() { entries = NULL; capacity = 0; size = 0; + modified = gFalse; streamEnds = NULL; streamEndsLen = 0; objStrs = new PopplerCache(5); @@ -1373,6 +1375,7 @@ void XRef::setModifiedObject (Object* o, Ref r) { e->obj.free(); o->copy(&(e->obj)); e->setFlag(XRefEntry::Updated, gTrue); + setModified(); } Ref XRef::addIndirectObject (Object* o) { @@ -1398,6 +1401,7 @@ Ref XRef::addIndirectObject (Object* o) { e->type = xrefEntryUncompressed; o->copy(&e->obj); e->setFlag(XRefEntry::Updated, gTrue); + setModified(); Ref r; r.num = entryIndexToUse; @@ -1419,6 +1423,7 @@ void XRef::removeIndirectObject(Ref r) { e->type = xrefEntryFree; e->gen++; e->setFlag(XRefEntry::Updated, gTrue); + setModified(); } void XRef::writeXRef(XRef::XRefWriter *writer, GBool writeAllEntries) { diff --git a/poppler/XRef.h b/poppler/XRef.h index 8748cb4..739b537 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -22,6 +22,7 @@ // Copyright (C) 2012, 2013, 2016 Thomas Freitag <[email protected]> // Copyright (C) 2012, 2013 Fabio D'Urso <[email protected]> // Copyright (C) 2013 Adrian Johnson <[email protected]> +// Copyright (C) 2016 Jakub Kucharski <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -175,6 +176,11 @@ public: XRefEntry *getEntry(int i, GBool complainIfMissing = gTrue); Object *getTrailerDict() { return &trailerDict; } + // Was the XRef modified? + GBool isModified() { return modified; } + // Set the modification flag for XRef to true. + void setModified() { modified = gTrue; } + // Write access void setModifiedObject(Object* o, Ref r); Ref addIndirectObject (Object* o); @@ -203,6 +209,7 @@ private: int errCode; // error code (if <ok> is false) GBool xrefReconstructed; // marker, true if xref was already reconstructed Object trailerDict; // trailer dictionary + GBool modified; Goffset *streamEnds; // 'endstream' positions - only used in // damaged files int streamEndsLen; // number of valid entries in streamEnds
_______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
