mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add QPDFWriter::getFinalVersion (fixes #266)
This commit is contained in:
parent
837dcf8fc2
commit
16fd6e64f9
@ -1,5 +1,10 @@
|
||||
2019-01-04 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Add new method QPDFWriter::getFinalVersion, which returns the
|
||||
PDF version that will ultimately be written to the final file. See
|
||||
comments in QPDFWriter.hh for some restrictions on its use. Fixes
|
||||
#266.
|
||||
|
||||
* When unexpected errors are found while checking linearization
|
||||
data, print an error message instead of calling assert, which
|
||||
cause the program to crash. Fixes #209, #231.
|
||||
|
@ -404,6 +404,18 @@ class QPDFWriter
|
||||
QPDF_DLL
|
||||
void registerProgressReporter(PointerHolder<ProgressReporter>);
|
||||
|
||||
// Return the PDF version that will be written into the header.
|
||||
// Calling this method does all the preparation for writing, so it
|
||||
// is an error to call any methods that may cause a change to the
|
||||
// version. Adding new objects to the original file after calling
|
||||
// this may also cause problems. It is safe to update existing
|
||||
// objects or stream contents after calling this method, e.g., to
|
||||
// include the final version number in metadata.
|
||||
QPDF_DLL
|
||||
std::string getFinalVersion();
|
||||
|
||||
// Write the final file. There is no expectation of being able to
|
||||
// call write() more than once.
|
||||
QPDF_DLL
|
||||
void write();
|
||||
|
||||
@ -473,6 +485,7 @@ class QPDFWriter
|
||||
void writeLinearized();
|
||||
void enqueuePart(std::vector<QPDFObjectHandle>& part);
|
||||
void writeEncryptionDictionary();
|
||||
void doWriteSetup();
|
||||
void writeHeader();
|
||||
void writeHintStream(int hint_id);
|
||||
qpdf_offset_t writeXRefTable(
|
||||
@ -598,6 +611,7 @@ class QPDFWriter
|
||||
bool deterministic_id;
|
||||
Pl_MD5* md5_pipeline;
|
||||
std::string deterministic_id_data;
|
||||
bool did_write_setup;
|
||||
|
||||
// For linearization only
|
||||
std::string lin_pass1_filename;
|
||||
|
@ -63,6 +63,7 @@ QPDFWriter::Members::Members(QPDF& pdf) :
|
||||
max_ostream_index(0),
|
||||
deterministic_id(false),
|
||||
md5_pipeline(0),
|
||||
did_write_setup(false),
|
||||
events_expected(0),
|
||||
events_seen(0),
|
||||
next_progress_report(0)
|
||||
@ -2358,8 +2359,14 @@ QPDFWriter::prepareFileForWrite()
|
||||
}
|
||||
|
||||
void
|
||||
QPDFWriter::write()
|
||||
QPDFWriter::doWriteSetup()
|
||||
{
|
||||
if (this->m->did_write_setup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->m->did_write_setup = true;
|
||||
|
||||
// Do preliminary setup
|
||||
|
||||
if (this->m->linearized)
|
||||
@ -2507,6 +2514,23 @@ QPDFWriter::write()
|
||||
setMinimumPDFVersion("1.5");
|
||||
}
|
||||
|
||||
setMinimumPDFVersion(this->m->pdf.getPDFVersion(),
|
||||
this->m->pdf.getExtensionLevel());
|
||||
this->m->final_pdf_version = this->m->min_pdf_version;
|
||||
this->m->final_extension_level = this->m->min_extension_level;
|
||||
if (! this->m->forced_pdf_version.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFWriter using forced PDF version");
|
||||
this->m->final_pdf_version = this->m->forced_pdf_version;
|
||||
this->m->final_extension_level = this->m->forced_extension_level;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFWriter::write()
|
||||
{
|
||||
doWriteSetup();
|
||||
|
||||
// Set up progress reporting. We spent about equal amounts of time
|
||||
// preparing and writing one pass. To get a rough estimate of
|
||||
// progress, we track handling of indirect objects. For linearized
|
||||
@ -2569,20 +2593,16 @@ QPDFWriter::writeEncryptionDictionary()
|
||||
closeObject(this->m->encryption_dict_objid);
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFWriter::getFinalVersion()
|
||||
{
|
||||
doWriteSetup();
|
||||
return this->m->final_pdf_version;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFWriter::writeHeader()
|
||||
{
|
||||
setMinimumPDFVersion(this->m->pdf.getPDFVersion(),
|
||||
this->m->pdf.getExtensionLevel());
|
||||
this->m->final_pdf_version = this->m->min_pdf_version;
|
||||
this->m->final_extension_level = this->m->min_extension_level;
|
||||
if (! this->m->forced_pdf_version.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFWriter using forced PDF version");
|
||||
this->m->final_pdf_version = this->m->forced_pdf_version;
|
||||
this->m->final_extension_level = this->m->forced_extension_level;
|
||||
}
|
||||
|
||||
writeString("%PDF-");
|
||||
writeString(this->m->final_pdf_version);
|
||||
if (this->m->pclm)
|
||||
|
@ -173,6 +173,16 @@ $td->runtest("\@file exists and file doesn't",
|
||||
{$td->FILE => "check-at-file.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Final Version ---");
|
||||
$n_tests += 1;
|
||||
|
||||
$td->runtest("check final version",
|
||||
{$td->COMMAND => "test_driver 54 minimal.pdf"},
|
||||
{$td->STRING => "test 54 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Dangling Refs ---");
|
||||
|
@ -1865,6 +1865,18 @@ void runtest(int n, char const* filename1, char const* arg2)
|
||||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 54)
|
||||
{
|
||||
// Test getFinalVersion. This must be invoked with a file
|
||||
// whose final version is not 1.5.
|
||||
QPDFWriter w(pdf, "a.pdf");
|
||||
assert(pdf.getPDFVersion() != "1.5");
|
||||
w.setObjectStreamMode(qpdf_o_generate);
|
||||
if (w.getFinalVersion() != "1.5")
|
||||
{
|
||||
std::cout << "oops: " << w.getFinalVersion() << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
|
Loading…
Reference in New Issue
Block a user