2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-29 00:10:54 +00:00

QPDFWriter: Add setPCLm() and writePCLm() methods

* Add support for PCLm using setPCLm() and writePCLm() methods in
  QPDFWriter.hh and QPDFWriter.cc
* Add a function writePCLmHeader() for PCLm header in QPDFWriter
This commit is contained in:
Sahil Arora 2017-08-01 17:46:24 +05:30 committed by Jay Berkenbilt
parent 3b170ab062
commit b19210fa7d
2 changed files with 134 additions and 0 deletions

View File

@ -353,6 +353,11 @@ class QPDFWriter
QPDF_DLL
void setLinearization(bool);
// Create PCLm output. Enables writing unreferenced objects,
// set PCLm header and writes pages before file catalog and page tree.
QPDF_DLL
void setPCLm(bool);
QPDF_DLL
void write();
@ -417,9 +422,11 @@ class QPDFWriter
void prepareFileForWrite();
void writeStandard();
void writeLinearized();
void writePCLm();
void enqueuePart(std::vector<QPDFObjectHandle>& part);
void writeEncryptionDictionary();
void writeHeader();
void writePCLmHeader();
void writeHintStream(int hint_id);
qpdf_offset_t writeXRefTable(
trailer_e which, int first, int last, int size);
@ -492,6 +499,7 @@ class QPDFWriter
bool encrypted;
bool preserve_encryption;
bool linearized;
bool pclm;
qpdf_object_stream_e object_stream_mode;
std::string encryption_key;
bool encrypt_metadata;

View File

@ -67,6 +67,7 @@ QPDFWriter::init()
encrypted = false;
preserve_encryption = true;
linearized = false;
pclm = false;
object_stream_mode = qpdf_o_preserve;
encrypt_metadata = true;
encrypt_use_aes = false;
@ -347,6 +348,20 @@ void
QPDFWriter::setLinearization(bool val)
{
this->linearized = val;
if (val)
{
this->pclm = false;
}
}
void
QPDFWriter::setPCLm(bool val)
{
this->pclm = val;
if (val)
{
this->linearized = false;
}
}
void
@ -2290,6 +2305,12 @@ QPDFWriter::write()
this->qdf_mode = false;
}
if (this->pclm)
{
setStreamDataMode(qpdf_s_preserve);
this->encrypted = false;
}
if (this->qdf_mode)
{
if (! this->normalize_content_set)
@ -2428,6 +2449,10 @@ QPDFWriter::write()
{
writeLinearized();
}
else if (this->pclm)
{
writePCLm();
}
else
{
writeStandard();
@ -2501,6 +2526,26 @@ QPDFWriter::writeHeader()
// linearization parameter dictionary.
}
void
QPDFWriter::writePCLmHeader()
{
setMinimumPDFVersion(pdf.getPDFVersion(), pdf.getExtensionLevel());
this->final_pdf_version = this->min_pdf_version;
this->final_extension_level = this->min_extension_level;
if (! this->forced_pdf_version.empty())
{
QTC::TC("qpdf", "QPDFWriter using forced PDF version");
this->final_pdf_version = this->forced_pdf_version;
this->final_extension_level = this->forced_extension_level;
}
writeString("%PDF-");
writeString(this->final_pdf_version);
// PCLm version
writeString("\n%PCLm 1.0\n");
writeStringQDF("%QDF-1.0\n\n");
}
void
QPDFWriter::writeHintStream(int hint_id)
{
@ -3205,3 +3250,84 @@ QPDFWriter::writeStandard()
assert(this->md5_pipeline == 0);
}
}
void
QPDFWriter::writePCLm()
{
if (this->deterministic_id)
{
pushMD5Pipeline();
}
// Start writing
writePCLmHeader();
writeString(this->extra_header_text);
// Image transform stream content for page strip images.
// Each of this new stream has to come after every page image
// strip written in the pclm file.
std::string image_transform_content = "q /image Do Q\n";
// enqueue all pages first
std::vector<QPDFObjectHandle> all = this->pdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter = all.begin();
iter != all.end(); ++iter)
{
// enqueue page
enqueueObject(*iter);
// enqueue page contents stream
enqueueObject((*iter).getKey("/Contents"));
// enqueue all the strips for each page
QPDFObjectHandle strips =
(*iter).getKey("/Resources").getKey("/XObject");
std::set<std::string> keys = strips.getKeys();
for (std::set<std::string>::iterator image = keys.begin();
image != keys.end(); ++image)
{
enqueueObject(strips.getKey(*image));
enqueueObject(QPDFObjectHandle::newStream(
&pdf, image_transform_content));
}
}
// Put root in queue.
QPDFObjectHandle trailer = getTrimmedTrailer();
enqueueObject(trailer.getKey("/Root"));
// Now start walking queue, output each object
while (this->object_queue.size())
{
QPDFObjectHandle cur_object = this->object_queue.front();
this->object_queue.pop_front();
writeObject(cur_object);
}
// Now write out xref. next_objid is now the number of objects.
qpdf_offset_t xref_offset = this->pipeline->getCount();
if (this->object_stream_to_objects.empty())
{
// Write regular cross-reference table
writeXRefTable(t_normal, 0, this->next_objid - 1, this->next_objid);
}
else
{
// Write cross-reference stream.
int xref_id = this->next_objid++;
writeXRefStream(xref_id, xref_id, xref_offset, t_normal,
0, this->next_objid - 1, this->next_objid);
}
writeString("startxref\n");
writeString(QUtil::int_to_string(xref_offset));
writeString("\n%%EOF\n");
if (this->deterministic_id)
{
QTC::TC("qpdf", "QPDFWriter standard deterministic ID",
this->object_stream_to_objects.empty() ? 0 : 1);
popPipelineStack();
assert(this->md5_pipeline == 0);
}
}