mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
Allow propagation of errors and retry through StreamDataProvider
StreamDataProvider::provideStreamData now has a rich enough API for it to effectively proxy to pipeStreamData.
This commit is contained in:
parent
a5367003c3
commit
893d38b87e
15
ChangeLog
15
ChangeLog
@ -1,5 +1,20 @@
|
|||||||
2020-04-04 Jay Berkenbilt <ejb@ql.org>
|
2020-04-04 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* Add a new provideStreamData method for StreamDataProvider that
|
||||||
|
allows a success code to be returned and that accepts the
|
||||||
|
suppress_warnings and will_retry methods. This makes it possible
|
||||||
|
to have a StreamDataProvider call pipeStreamData and propagate its
|
||||||
|
results back. This change allows better error handling and
|
||||||
|
recovery when objects are copied from other files and when
|
||||||
|
"immediate copy from" is enabled.
|
||||||
|
|
||||||
|
* Add a new version of QPDFObjectHandle::pipeStreamData whose
|
||||||
|
return value indicates overall success or failure rather than
|
||||||
|
whether nor not filtering was attempted. It should have always
|
||||||
|
been this way. This change was done in a backward-compatible
|
||||||
|
fashion. Previously existing pipeStreamData methods' return values
|
||||||
|
mean the same as always.
|
||||||
|
|
||||||
* Add "objectinfo" section to json output. In this release,
|
* Add "objectinfo" section to json output. In this release,
|
||||||
information about whether each object is a stream or not is
|
information about whether each object is a stream or not is
|
||||||
provided. There's otherwise no way to tell conclusively from the
|
provided. There's otherwise no way to tell conclusively from the
|
||||||
|
12
TODO
12
TODO
@ -20,18 +20,6 @@ ABI Changes
|
|||||||
This is a list of changes to make next time there is an ABI change.
|
This is a list of changes to make next time there is an ABI change.
|
||||||
Comments appear in the code prefixed by "ABI"
|
Comments appear in the code prefixed by "ABI"
|
||||||
|
|
||||||
* (Source compatibility) As somewhat discussed in issue 219, the
|
|
||||||
original pipeStreamData in QPDF_Stream has various logic for
|
|
||||||
reporting warnings and letting the caller retry. This logic is not
|
|
||||||
implemented for stream data providers. When copying foreign streams,
|
|
||||||
qpdf uses a stream data provider (QPDF::CopiedStreamDataProvider) to
|
|
||||||
read the stream data from the original file. While a warning is
|
|
||||||
issued for that case, there is no way to actually propagate failure
|
|
||||||
information back through because
|
|
||||||
StreamDataProvider::provideStreamData doesn't take the
|
|
||||||
suppress_warnings or will_retry options, and adding them would break
|
|
||||||
source compatibility.
|
|
||||||
|
|
||||||
C++-11
|
C++-11
|
||||||
======
|
======
|
||||||
|
|
||||||
|
@ -813,8 +813,9 @@ class QPDF
|
|||||||
virtual ~CopiedStreamDataProvider()
|
virtual ~CopiedStreamDataProvider()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual bool provideStreamData(
|
||||||
Pipeline* pipeline);
|
int objid, int generation, Pipeline* pipeline,
|
||||||
|
bool suppress_warnings, bool will_retry) override;
|
||||||
void registerForeignStream(QPDFObjGen const& local_og,
|
void registerForeignStream(QPDFObjGen const& local_og,
|
||||||
QPDFObjectHandle foreign_stream);
|
QPDFObjectHandle foreign_stream);
|
||||||
void registerForeignStream(QPDFObjGen const& local_og,
|
void registerForeignStream(QPDFObjGen const& local_og,
|
||||||
@ -909,9 +910,7 @@ class QPDF
|
|||||||
bool will_retry);
|
bool will_retry);
|
||||||
bool pipeForeignStreamData(
|
bool pipeForeignStreamData(
|
||||||
PointerHolder<ForeignStreamData>,
|
PointerHolder<ForeignStreamData>,
|
||||||
Pipeline*,
|
Pipeline*, bool suppress_warnings, bool will_retry);
|
||||||
int encode_flags,
|
|
||||||
qpdf_stream_decode_level_e decode_level);
|
|
||||||
static bool pipeStreamData(PointerHolder<QPDF::EncryptionParameters> encp,
|
static bool pipeStreamData(PointerHolder<QPDF::EncryptionParameters> encp,
|
||||||
PointerHolder<InputSource> file,
|
PointerHolder<InputSource> file,
|
||||||
QPDF& qpdf_for_warning,
|
QPDF& qpdf_for_warning,
|
||||||
|
@ -57,6 +57,9 @@ class QPDFObjectHandle
|
|||||||
class QPDF_DLL_CLASS StreamDataProvider
|
class QPDF_DLL_CLASS StreamDataProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
QPDF_DLL
|
||||||
|
StreamDataProvider(bool supports_retry = false);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~StreamDataProvider()
|
virtual ~StreamDataProvider()
|
||||||
{
|
{
|
||||||
@ -74,8 +77,30 @@ class QPDFObjectHandle
|
|||||||
// information is made available just to make it more
|
// information is made available just to make it more
|
||||||
// convenient to use a single StreamDataProvider object to
|
// convenient to use a single StreamDataProvider object to
|
||||||
// provide data for multiple streams.
|
// provide data for multiple streams.
|
||||||
|
|
||||||
|
// Prior to qpdf 10.0.0, it was not possible to handle errors
|
||||||
|
// the way pipeStreamData does or to pass back success.
|
||||||
|
// Starting in qpdf 10.0.0, those capabilities have been added
|
||||||
|
// by allowing an alternative provideStreamData to be
|
||||||
|
// implemented. You must implement at least one of the
|
||||||
|
// versions of provideStreamData below. If you implement the
|
||||||
|
// version that supports retry and returns a value, you should
|
||||||
|
// pass true as the value of supports_retry in the base class
|
||||||
|
// constructor. This will cause the library to call that
|
||||||
|
// version of the method, which should also return a boolean
|
||||||
|
// indicating whether it ran without errors.
|
||||||
|
QPDF_DLL
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual void provideStreamData(int objid, int generation,
|
||||||
Pipeline* pipeline) = 0;
|
Pipeline* pipeline);
|
||||||
|
QPDF_DLL
|
||||||
|
virtual bool provideStreamData(
|
||||||
|
int objid, int generation, Pipeline* pipeline,
|
||||||
|
bool suppress_warnings, bool will_retry);
|
||||||
|
QPDF_DLL
|
||||||
|
bool supportsRetry();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool supports_retry;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The TokenFilter class provides a way to filter content streams
|
// The TokenFilter class provides a way to filter content streams
|
||||||
@ -779,18 +804,39 @@ class QPDFObjectHandle
|
|||||||
// we determine that we know how to apply all requested filters,
|
// we determine that we know how to apply all requested filters,
|
||||||
// do so and return true if we are successful.
|
// do so and return true if we are successful.
|
||||||
//
|
//
|
||||||
// In all cases, a return value of true means that filtered data
|
// The exact meaning of the return value differs the different
|
||||||
// has been written successfully. If filtering is requested but
|
// versions of this function, but for any version, the meaning has
|
||||||
// this method returns false, it means there was some error in the
|
// been the same. For the main version, added in qpdf 10, the
|
||||||
// filtering, in which case the resulting data is likely partially
|
// return value indicates whether the overall operation succeeded.
|
||||||
// filtered and/or incomplete and may not be consistent with the
|
// The filter parameter, if specified, will be set to whether or
|
||||||
// configured filters. QPDFWriter handles this by attempting to
|
// not filtering was attempted. If filtering was not requested,
|
||||||
// get the stream data without filtering, but callers should
|
// this value will be false even if the overall operation
|
||||||
// consider a false return value when decode_level is not
|
// succeeded.
|
||||||
// qpdf_dl_none to be a potential loss of data. If you intend to
|
//
|
||||||
// retry in that case, pass true as the value of will_retry. This
|
// If filtering is requested but this method returns false, it
|
||||||
// changes the warning issued by the library to indicate that the
|
// means there was some error in the filtering, in which case the
|
||||||
// operation will be retried without filtering to avoid data loss.
|
// resulting data is likely partially filtered and/or incomplete
|
||||||
|
// and may not be consistent with the configured filters.
|
||||||
|
// QPDFWriter handles this by attempting to get the stream data
|
||||||
|
// without filtering, but callers should consider a false return
|
||||||
|
// value when decode_level is not qpdf_dl_none to be a potential
|
||||||
|
// loss of data. If you intend to retry in that case, pass true as
|
||||||
|
// the value of will_retry. This changes the warning issued by the
|
||||||
|
// library to indicate that the operation will be retried without
|
||||||
|
// filtering to avoid data loss.
|
||||||
|
|
||||||
|
// Return value is overall success, even if filtering is not
|
||||||
|
// requested.
|
||||||
|
QPDF_DLL
|
||||||
|
bool pipeStreamData(Pipeline*, bool* filtering_attempted,
|
||||||
|
int encode_flags,
|
||||||
|
qpdf_stream_decode_level_e decode_level,
|
||||||
|
bool suppress_warnings = false,
|
||||||
|
bool will_retry = false);
|
||||||
|
|
||||||
|
// Legacy version. Return value is whether filtering was
|
||||||
|
// attempted. There is no way to determine success if filtering
|
||||||
|
// was not attempted.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool pipeStreamData(Pipeline*,
|
bool pipeStreamData(Pipeline*,
|
||||||
int encode_flags,
|
int encode_flags,
|
||||||
@ -804,6 +850,7 @@ class QPDFObjectHandle
|
|||||||
// filter = true -> decode_level = qpdf_dl_generalized
|
// filter = true -> decode_level = qpdf_dl_generalized
|
||||||
// normalize = true -> encode_flags |= qpdf_sf_normalize
|
// normalize = true -> encode_flags |= qpdf_sf_normalize
|
||||||
// compress = true -> encode_flags |= qpdf_sf_compress
|
// compress = true -> encode_flags |= qpdf_sf_compress
|
||||||
|
// Return value is whether filtering was attempted.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool pipeStreamData(Pipeline*, bool filter,
|
bool pipeStreamData(Pipeline*, bool filter,
|
||||||
bool normalize, bool compress);
|
bool normalize, bool compress);
|
||||||
|
@ -68,27 +68,37 @@ QPDF::ForeignStreamData::ForeignStreamData(
|
|||||||
|
|
||||||
QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
|
QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
|
||||||
QPDF& destination_qpdf) :
|
QPDF& destination_qpdf) :
|
||||||
|
QPDFObjectHandle::StreamDataProvider(true),
|
||||||
destination_qpdf(destination_qpdf)
|
destination_qpdf(destination_qpdf)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
QPDF::CopiedStreamDataProvider::provideStreamData(
|
QPDF::CopiedStreamDataProvider::provideStreamData(
|
||||||
int objid, int generation, Pipeline* pipeline)
|
int objid, int generation, Pipeline* pipeline,
|
||||||
|
bool suppress_warnings, bool will_retry)
|
||||||
{
|
{
|
||||||
PointerHolder<ForeignStreamData> foreign_data =
|
PointerHolder<ForeignStreamData> foreign_data =
|
||||||
this->foreign_stream_data[QPDFObjGen(objid, generation)];
|
this->foreign_stream_data[QPDFObjGen(objid, generation)];
|
||||||
|
bool result = false;
|
||||||
if (foreign_data.getPointer())
|
if (foreign_data.getPointer())
|
||||||
{
|
{
|
||||||
destination_qpdf.pipeForeignStreamData(
|
result = destination_qpdf.pipeForeignStreamData(
|
||||||
foreign_data, pipeline, 0, qpdf_dl_none);
|
foreign_data, pipeline, suppress_warnings, will_retry);
|
||||||
|
QTC::TC("qpdf", "QPDF copy foreign with data",
|
||||||
|
result ? 0 : 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QPDFObjectHandle foreign_stream =
|
QPDFObjectHandle foreign_stream =
|
||||||
this->foreign_streams[QPDFObjGen(objid, generation)];
|
this->foreign_streams[QPDFObjGen(objid, generation)];
|
||||||
foreign_stream.pipeStreamData(pipeline, 0, qpdf_dl_none);
|
result = foreign_stream.pipeStreamData(
|
||||||
|
pipeline, nullptr, 0, qpdf_dl_none,
|
||||||
|
suppress_warnings, will_retry);
|
||||||
|
QTC::TC("qpdf", "QPDF copy foreign with foreign_stream",
|
||||||
|
result ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2851,8 +2861,7 @@ bool
|
|||||||
QPDF::pipeForeignStreamData(
|
QPDF::pipeForeignStreamData(
|
||||||
PointerHolder<ForeignStreamData> foreign,
|
PointerHolder<ForeignStreamData> foreign,
|
||||||
Pipeline* pipeline,
|
Pipeline* pipeline,
|
||||||
int encode_flags,
|
bool suppress_warnings, bool will_retry)
|
||||||
qpdf_stream_decode_level_e decode_level)
|
|
||||||
{
|
{
|
||||||
if (foreign->encp->encrypted)
|
if (foreign->encp->encrypted)
|
||||||
{
|
{
|
||||||
@ -2863,7 +2872,7 @@ QPDF::pipeForeignStreamData(
|
|||||||
foreign->foreign_objid, foreign->foreign_generation,
|
foreign->foreign_objid, foreign->foreign_generation,
|
||||||
foreign->offset, foreign->length,
|
foreign->offset, foreign->length,
|
||||||
foreign->local_dict, foreign->is_attachment_stream,
|
foreign->local_dict, foreign->is_attachment_stream,
|
||||||
pipeline, false, false);
|
pipeline, suppress_warnings, will_retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -36,6 +36,36 @@ class TerminateParsing
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QPDFObjectHandle::StreamDataProvider::StreamDataProvider(
|
||||||
|
bool supports_retry) :
|
||||||
|
supports_retry(supports_retry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
||||||
|
int objid, int generation, Pipeline* pipeline)
|
||||||
|
{
|
||||||
|
throw std::logic_error(
|
||||||
|
"you must override provideStreamData -- see QPDFObjectHandle.hh");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
||||||
|
int objid, int generation, Pipeline* pipeline,
|
||||||
|
bool suppress_warnings, bool will_retry)
|
||||||
|
{
|
||||||
|
throw std::logic_error(
|
||||||
|
"you must override provideStreamData -- see QPDFObjectHandle.hh");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
QPDFObjectHandle::StreamDataProvider::supportsRetry()
|
||||||
|
{
|
||||||
|
return this->supports_retry;
|
||||||
|
}
|
||||||
|
|
||||||
class CoalesceProvider: public QPDFObjectHandle::StreamDataProvider
|
class CoalesceProvider: public QPDFObjectHandle::StreamDataProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1135,14 +1165,29 @@ QPDFObjectHandle::getRawStreamData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
QPDFObjectHandle::pipeStreamData(Pipeline* p,
|
QPDFObjectHandle::pipeStreamData(Pipeline* p, bool* filtering_attempted,
|
||||||
int encode_flags,
|
int encode_flags,
|
||||||
qpdf_stream_decode_level_e decode_level,
|
qpdf_stream_decode_level_e decode_level,
|
||||||
bool suppress_warnings, bool will_retry)
|
bool suppress_warnings, bool will_retry)
|
||||||
{
|
{
|
||||||
assertStream();
|
assertStream();
|
||||||
return dynamic_cast<QPDF_Stream*>(obj.getPointer())->pipeStreamData(
|
return dynamic_cast<QPDF_Stream*>(obj.getPointer())->pipeStreamData(
|
||||||
p, encode_flags, decode_level, suppress_warnings, will_retry);
|
p, filtering_attempted, encode_flags, decode_level,
|
||||||
|
suppress_warnings, will_retry);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
QPDFObjectHandle::pipeStreamData(Pipeline* p,
|
||||||
|
int encode_flags,
|
||||||
|
qpdf_stream_decode_level_e decode_level,
|
||||||
|
bool suppress_warnings, bool will_retry)
|
||||||
|
{
|
||||||
|
assertStream();
|
||||||
|
bool filtering_attempted;
|
||||||
|
dynamic_cast<QPDF_Stream*>(obj.getPointer())->pipeStreamData(
|
||||||
|
p, &filtering_attempted, encode_flags, decode_level,
|
||||||
|
suppress_warnings, will_retry);
|
||||||
|
return filtering_attempted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -163,7 +163,7 @@ PointerHolder<Buffer>
|
|||||||
QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
|
QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
|
||||||
{
|
{
|
||||||
Pl_Buffer buf("stream data buffer");
|
Pl_Buffer buf("stream data buffer");
|
||||||
if (! pipeStreamData(&buf, 0, decode_level, false, false))
|
if (! pipeStreamData(&buf, nullptr, 0, decode_level, false, false))
|
||||||
{
|
{
|
||||||
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||||
"", this->offset,
|
"", this->offset,
|
||||||
@ -177,7 +177,12 @@ PointerHolder<Buffer>
|
|||||||
QPDF_Stream::getRawStreamData()
|
QPDF_Stream::getRawStreamData()
|
||||||
{
|
{
|
||||||
Pl_Buffer buf("stream data buffer");
|
Pl_Buffer buf("stream data buffer");
|
||||||
pipeStreamData(&buf, 0, qpdf_dl_none, false, false);
|
if (! pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false))
|
||||||
|
{
|
||||||
|
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||||
|
"", this->offset,
|
||||||
|
"error getting raw stream data");
|
||||||
|
}
|
||||||
QTC::TC("qpdf", "QPDF_Stream getRawStreamData");
|
QTC::TC("qpdf", "QPDF_Stream getRawStreamData");
|
||||||
return buf.getBuffer();
|
return buf.getBuffer();
|
||||||
}
|
}
|
||||||
@ -467,7 +472,7 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||||
int encode_flags,
|
int encode_flags,
|
||||||
qpdf_stream_decode_level_e decode_level,
|
qpdf_stream_decode_level_e decode_level,
|
||||||
bool suppress_warnings, bool will_retry)
|
bool suppress_warnings, bool will_retry)
|
||||||
@ -480,7 +485,14 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
|||||||
bool early_code_change = true;
|
bool early_code_change = true;
|
||||||
bool specialized_compression = false;
|
bool specialized_compression = false;
|
||||||
bool lossy_compression = false;
|
bool lossy_compression = false;
|
||||||
bool filter = (! ((encode_flags == 0) && (decode_level == qpdf_dl_none)));
|
bool ignored;
|
||||||
|
if (filterp == nullptr)
|
||||||
|
{
|
||||||
|
filterp = &ignored;
|
||||||
|
}
|
||||||
|
bool& filter = *filterp;
|
||||||
|
filter = (! ((encode_flags == 0) && (decode_level == qpdf_dl_none)));
|
||||||
|
bool success = true;
|
||||||
if (filter)
|
if (filter)
|
||||||
{
|
{
|
||||||
filter = filterable(filters, specialized_compression, lossy_compression,
|
filter = filterable(filters, specialized_compression, lossy_compression,
|
||||||
@ -505,6 +517,7 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
|||||||
if (pipeline == 0)
|
if (pipeline == 0)
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "QPDF_Stream pipeStreamData with null pipeline");
|
QTC::TC("qpdf", "QPDF_Stream pipeStreamData with null pipeline");
|
||||||
|
// Return value is whether we can filter in this case.
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,8 +638,21 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
|||||||
else if (this->stream_provider.getPointer())
|
else if (this->stream_provider.getPointer())
|
||||||
{
|
{
|
||||||
Pl_Count count("stream provider count", pipeline);
|
Pl_Count count("stream provider count", pipeline);
|
||||||
|
if (this->stream_provider->supportsRetry())
|
||||||
|
{
|
||||||
|
if (! this->stream_provider->provideStreamData(
|
||||||
|
this->objid, this->generation, &count,
|
||||||
|
suppress_warnings, will_retry))
|
||||||
|
{
|
||||||
|
filter = false;
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
this->stream_provider->provideStreamData(
|
this->stream_provider->provideStreamData(
|
||||||
this->objid, this->generation, &count);
|
this->objid, this->generation, &count);
|
||||||
|
}
|
||||||
qpdf_offset_t actual_length = count.getCount();
|
qpdf_offset_t actual_length = count.getCount();
|
||||||
qpdf_offset_t desired_length = 0;
|
qpdf_offset_t desired_length = 0;
|
||||||
if (this->stream_dict.hasKey("/Length"))
|
if (this->stream_dict.hasKey("/Length"))
|
||||||
@ -674,6 +700,7 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
|||||||
will_retry))
|
will_retry))
|
||||||
{
|
{
|
||||||
filter = false;
|
filter = false;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +731,7 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
|
|||||||
" for content normalization in the manual."));
|
" for content normalization in the manual."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return filter;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -31,7 +31,7 @@ class QPDF_Stream: public QPDFObject
|
|||||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> getStreamDataProvider() const;
|
PointerHolder<QPDFObjectHandle::StreamDataProvider> getStreamDataProvider() const;
|
||||||
|
|
||||||
// See comments in QPDFObjectHandle.hh for these methods.
|
// See comments in QPDFObjectHandle.hh for these methods.
|
||||||
bool pipeStreamData(Pipeline*,
|
bool pipeStreamData(Pipeline*, bool* tried_filtering,
|
||||||
int encode_flags,
|
int encode_flags,
|
||||||
qpdf_stream_decode_level_e decode_level,
|
qpdf_stream_decode_level_e decode_level,
|
||||||
bool suppress_warnings, bool will_retry);
|
bool suppress_warnings, bool will_retry);
|
||||||
|
@ -453,3 +453,5 @@ QPDFPageObjectHelper filter form xobject 0
|
|||||||
qpdf found resources in non-leaf 0
|
qpdf found resources in non-leaf 0
|
||||||
qpdf found shared resources in leaf 0
|
qpdf found shared resources in leaf 0
|
||||||
qpdf found shared xobject in leaf 0
|
qpdf found shared xobject in leaf 0
|
||||||
|
QPDF copy foreign with data 1
|
||||||
|
QPDF copy foreign with foreign_stream 1
|
||||||
|
@ -1698,6 +1698,8 @@ my @sp_cases = (
|
|||||||
[11, '%d in middle', '--encrypt u o 128 --', 'a-%d-split-out.zdf'],
|
[11, '%d in middle', '--encrypt u o 128 --', 'a-%d-split-out.zdf'],
|
||||||
[11, 'pdf extension', '', 'split-out.Pdf'],
|
[11, 'pdf extension', '', 'split-out.Pdf'],
|
||||||
[4, 'fallback', '--pages 11-pages.pdf 1-3 minimal.pdf --', 'split-out'],
|
[4, 'fallback', '--pages 11-pages.pdf 1-3 minimal.pdf --', 'split-out'],
|
||||||
|
[1, 'broken data', '--pages broken-lzw.pdf --', 'split-out.pdf',
|
||||||
|
{$td->FILE => "broken-lzw.out", $td->EXIT_STATUS => 3}],
|
||||||
);
|
);
|
||||||
$n_tests += 35;
|
$n_tests += 35;
|
||||||
$n_compare_pdfs += 1;
|
$n_compare_pdfs += 1;
|
||||||
@ -1761,12 +1763,17 @@ foreach my $i (qw(01-10 11-20 21-30))
|
|||||||
|
|
||||||
foreach my $d (@sp_cases)
|
foreach my $d (@sp_cases)
|
||||||
{
|
{
|
||||||
my ($n, $description, $xargs, $out) = @$d;
|
my ($n, $description, $xargs, $out, $exp) = @$d;
|
||||||
|
if (! defined $exp)
|
||||||
|
{
|
||||||
|
$exp = {$td->STRING => "", $td->EXIT_STATUS => 0};
|
||||||
|
}
|
||||||
$td->runtest("split pages " . $description,
|
$td->runtest("split pages " . $description,
|
||||||
{$td->COMMAND =>
|
{$td->COMMAND =>
|
||||||
"qpdf --static-id --split-pages 11-pages.pdf" .
|
"qpdf --static-id --split-pages 11-pages.pdf" .
|
||||||
" $xargs $out"},
|
" $xargs $out"},
|
||||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
$exp,
|
||||||
|
$td->NORMALIZE_NEWLINES);
|
||||||
my $pattern = $out;
|
my $pattern = $out;
|
||||||
my $nlen = length($n);
|
my $nlen = length($n);
|
||||||
if ($pattern =~ m/\%d/)
|
if ($pattern =~ m/\%d/)
|
||||||
@ -1786,7 +1793,7 @@ foreach my $d (@sp_cases)
|
|||||||
my $actual = sprintf($pattern, $i);
|
my $actual = sprintf($pattern, $i);
|
||||||
my $expected = $actual;
|
my $expected = $actual;
|
||||||
$expected =~ s/split-out/split-exp/;
|
$expected =~ s/split-out/split-exp/;
|
||||||
$td->runtest("checkout output page $i",
|
$td->runtest("check output page $i ($description)",
|
||||||
{$td->FILE => $actual},
|
{$td->FILE => $actual},
|
||||||
{$td->FILE => $expected});
|
{$td->FILE => $expected});
|
||||||
}
|
}
|
||||||
@ -2390,7 +2397,8 @@ foreach my $d ([25, 1], [26, 2], [27, 3])
|
|||||||
$td->runtest("copy objects $outn",
|
$td->runtest("copy objects $outn",
|
||||||
{$td->COMMAND => "test_driver $testn" .
|
{$td->COMMAND => "test_driver $testn" .
|
||||||
" minimal.pdf copy-foreign-objects-in.pdf"},
|
" minimal.pdf copy-foreign-objects-in.pdf"},
|
||||||
{$td->STRING => "test $testn done\n", $td->EXIT_STATUS => 0},
|
{$td->FILE => "copy-foreign-objects-$testn.out",
|
||||||
|
$td->EXIT_STATUS => 0},
|
||||||
$td->NORMALIZE_NEWLINES);
|
$td->NORMALIZE_NEWLINES);
|
||||||
$td->runtest("check output",
|
$td->runtest("check output",
|
||||||
{$td->FILE => "a.pdf"},
|
{$td->FILE => "a.pdf"},
|
||||||
|
3
qpdf/qtest/qpdf/broken-lzw.out
Normal file
3
qpdf/qtest/qpdf/broken-lzw.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
WARNING: broken-lzw.pdf (offset 444): error decoding stream data for object 4 0: LZWDecoder: bad code received
|
||||||
|
WARNING: broken-lzw.pdf (offset 444): stream will be re-processed without filtering to avoid data loss
|
||||||
|
qpdf: operation succeeded with warnings; resulting file may have some problems
|
108
qpdf/qtest/qpdf/broken-lzw.pdf
Normal file
108
qpdf/qtest/qpdf/broken-lzw.pdf
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
%PDF-1.3
|
||||||
|
%¿÷¢þ
|
||||||
|
%QDF-1.0
|
||||||
|
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Pages 2 0 R
|
||||||
|
/Type /Catalog
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Count 1
|
||||||
|
/Kids [
|
||||||
|
3 0 R
|
||||||
|
]
|
||||||
|
/Type /Pages
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Page 1
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Contents [ 4 0 R 6 0 R ]
|
||||||
|
/MediaBox [
|
||||||
|
0
|
||||||
|
0
|
||||||
|
612
|
||||||
|
792
|
||||||
|
]
|
||||||
|
/Parent 2 0 R
|
||||||
|
/Resources <<
|
||||||
|
/Font <<
|
||||||
|
/F1 8 0 R
|
||||||
|
>>
|
||||||
|
/ProcSet 9 0 R
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Contents for page 1
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Filter /LZWDecode
|
||||||
|
/Length 5 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Not really compressed.
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
5 0 obj
|
||||||
|
23
|
||||||
|
endobj
|
||||||
|
|
||||||
|
%% Contents for page 1
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/Length 7 0 R
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Really compressed.
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
7 0 obj
|
||||||
|
19
|
||||||
|
endobj
|
||||||
|
|
||||||
|
8 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /Helvetica
|
||||||
|
/Encoding /WinAnsiEncoding
|
||||||
|
/Name /F1
|
||||||
|
/Subtype /Type1
|
||||||
|
/Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
9 0 obj
|
||||||
|
[
|
||||||
|
/PDF
|
||||||
|
/Text
|
||||||
|
]
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 10
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000025 00000 n
|
||||||
|
0000000079 00000 n
|
||||||
|
0000000161 00000 n
|
||||||
|
0000000386 00000 n
|
||||||
|
0000000485 00000 n
|
||||||
|
0000000527 00000 n
|
||||||
|
0000000601 00000 n
|
||||||
|
0000000620 00000 n
|
||||||
|
0000000738 00000 n
|
||||||
|
trailer <<
|
||||||
|
/Root 1 0 R
|
||||||
|
/Size 10
|
||||||
|
/ID [<8b40e25fc6409c63043ed789f3ae4a4b><8b40e25fc6409c63043ed789f3ae4a4b>]
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
773
|
||||||
|
%%EOF
|
1
qpdf/qtest/qpdf/copy-foreign-objects-25.out
Normal file
1
qpdf/qtest/qpdf/copy-foreign-objects-25.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
test 25 done
|
1
qpdf/qtest/qpdf/copy-foreign-objects-26.out
Normal file
1
qpdf/qtest/qpdf/copy-foreign-objects-26.out
Normal file
@ -0,0 +1 @@
|
|||||||
|
test 26 done
|
3
qpdf/qtest/qpdf/copy-foreign-objects-27.out
Normal file
3
qpdf/qtest/qpdf/copy-foreign-objects-27.out
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
WARNING: copy-foreign-objects-in.pdf (offset 3627): error decoding stream data for object 26 0: LZWDecoder: bad code received
|
||||||
|
WARNING: copy-foreign-objects-in.pdf (offset 3627): stream will be re-processed without filtering to avoid data loss
|
||||||
|
test 27 done
|
@ -7,12 +7,13 @@
|
|||||||
% file.
|
% file.
|
||||||
|
|
||||||
% The /QTest key in trailer has pointers to several indirect objects:
|
% The /QTest key in trailer has pointers to several indirect objects:
|
||||||
% O1, O2, O3 where O1 is an array that contains a dictionary that has
|
% O1, O2, O3, O4 where O1 is an array that contains a dictionary that
|
||||||
% a key that points to O2, O2 is a dictionary that contains an array
|
% has a key that points to O2, O2 is a dictionary that contains an
|
||||||
% that points to O1, and O3 is a page object that inherits some
|
% array that points to O1, O3 is a page object that inherits some
|
||||||
% resource from its parent /Pages and also points to some other page.
|
% resource from its parent /Pages and also points to some other page,
|
||||||
% O1 also points to a stream whose dictionary has a key that points to
|
% and O4 is a stream with invalid compressed data. O1 also points to a
|
||||||
% another stream whose dictionary points back to the first stream.
|
% stream whose dictionary has a key that points to another stream
|
||||||
|
% whose dictionary points back to the first stream.
|
||||||
|
|
||||||
1 0 obj
|
1 0 obj
|
||||||
<<
|
<<
|
||||||
@ -293,43 +294,59 @@ endobj
|
|||||||
|
|
||||||
% QTest
|
% QTest
|
||||||
25 0 obj
|
25 0 obj
|
||||||
<< /This-is-QTest true /O1 19 0 R /O2 20 0 R /O3 5 0 R >>
|
<< /This-is-QTest true /O1 19 0 R /O2 20 0 R /O3 5 0 R /O4 26 0 R >>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
26 0 obj
|
||||||
|
<<
|
||||||
|
/Length 27 0 R
|
||||||
|
/Filter /LZWDecode
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Not really compresed.
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
27 0 obj
|
||||||
|
22
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
xref
|
xref
|
||||||
0 26
|
0 28
|
||||||
0000000000 65535 f
|
0000000000 65535 f
|
||||||
0000000655 00000 n
|
0000000706 00000 n
|
||||||
0000000709 00000 n
|
0000000760 00000 n
|
||||||
0000000845 00000 n
|
0000000896 00000 n
|
||||||
0000001073 00000 n
|
0000001124 00000 n
|
||||||
0000001313 00000 n
|
0000001364 00000 n
|
||||||
0000001580 00000 n
|
0000001631 00000 n
|
||||||
0000001839 00000 n
|
0000001890 00000 n
|
||||||
0000002081 00000 n
|
0000002132 00000 n
|
||||||
0000002183 00000 n
|
0000002234 00000 n
|
||||||
0000002202 00000 n
|
0000002253 00000 n
|
||||||
0000002334 00000 n
|
0000002385 00000 n
|
||||||
0000002438 00000 n
|
0000002489 00000 n
|
||||||
0000002481 00000 n
|
0000002532 00000 n
|
||||||
0000002585 00000 n
|
0000002636 00000 n
|
||||||
0000002628 00000 n
|
0000002679 00000 n
|
||||||
0000002732 00000 n
|
0000002783 00000 n
|
||||||
0000002775 00000 n
|
0000002826 00000 n
|
||||||
0000002879 00000 n
|
0000002930 00000 n
|
||||||
0000002904 00000 n
|
0000002955 00000 n
|
||||||
0000003042 00000 n
|
0000003093 00000 n
|
||||||
0000003138 00000 n
|
0000003189 00000 n
|
||||||
0000003255 00000 n
|
0000003306 00000 n
|
||||||
0000003285 00000 n
|
0000003336 00000 n
|
||||||
0000003402 00000 n
|
0000003453 00000 n
|
||||||
0000003430 00000 n
|
0000003481 00000 n
|
||||||
|
0000003567 00000 n
|
||||||
|
0000003667 00000 n
|
||||||
trailer <<
|
trailer <<
|
||||||
/Root 1 0 R
|
/Root 1 0 R
|
||||||
/Size 26
|
/Size 28
|
||||||
/QTest 25 0 R
|
/QTest 25 0 R
|
||||||
/ID [<d15f7aca3be584a96c1c94adb0931e71><9adb6b2fdb22e857340f7103917b16e4>]
|
/ID [<d15f7aca3be584a96c1c94adb0931e71><9adb6b2fdb22e857340f7103917b16e4>]
|
||||||
>>
|
>>
|
||||||
startxref
|
startxref
|
||||||
3505
|
3687
|
||||||
%%EOF
|
%%EOF
|
||||||
|
@ -4,27 +4,33 @@
|
|||||||
<< /Pages 3 0 R /Type /Catalog >>
|
<< /Pages 3 0 R /Type /Catalog >>
|
||||||
endobj
|
endobj
|
||||||
2 0 obj
|
2 0 obj
|
||||||
<< /O1 4 0 R /O2 5 0 R /This-is-QTest true >>
|
<< /O1 4 0 R /O2 5 0 R /O4 6 0 R /This-is-QTest true >>
|
||||||
endobj
|
endobj
|
||||||
3 0 obj
|
3 0 obj
|
||||||
<< /Count 1 /Kids [ 6 0 R ] /Type /Pages >>
|
<< /Count 1 /Kids [ 7 0 R ] /Type /Pages >>
|
||||||
endobj
|
endobj
|
||||||
4 0 obj
|
4 0 obj
|
||||||
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 5 0 R >> 2.17828 ] >> /salad /O2 5 0 R /Stream1 7 0 R ]
|
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 5 0 R >> 2.17828 ] >> /salad /O2 5 0 R /Stream1 8 0 R ]
|
||||||
endobj
|
endobj
|
||||||
5 0 obj
|
5 0 obj
|
||||||
<< /K1 [ 2.236 /O1 4 0 R 1.732 ] /O1 4 0 R /This-is-O2 true >>
|
<< /K1 [ 2.236 /O1 4 0 R 1.732 ] /O1 4 0 R /This-is-O2 true >>
|
||||||
endobj
|
endobj
|
||||||
6 0 obj
|
6 0 obj
|
||||||
<< /Contents 8 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 9 0 R >> /ProcSet 10 0 R >> /Type /Page >>
|
<< /Filter /LZWDecode /Length 22 >>
|
||||||
|
stream
|
||||||
|
Not really compresed.
|
||||||
|
endstream
|
||||||
endobj
|
endobj
|
||||||
7 0 obj
|
7 0 obj
|
||||||
<< /Stream2 11 0 R /This-is-Stream1 true /Length 18 >>
|
<< /Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet 11 0 R >> /Type /Page >>
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
<< /Stream2 12 0 R /This-is-Stream1 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 1.
|
This is stream 1.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
8 0 obj
|
9 0 obj
|
||||||
<< /Length 44 >>
|
<< /Length 44 >>
|
||||||
stream
|
stream
|
||||||
BT
|
BT
|
||||||
@ -34,33 +40,34 @@ BT
|
|||||||
ET
|
ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
9 0 obj
|
10 0 obj
|
||||||
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
||||||
endobj
|
endobj
|
||||||
10 0 obj
|
11 0 obj
|
||||||
[ /PDF /Text ]
|
[ /PDF /Text ]
|
||||||
endobj
|
endobj
|
||||||
11 0 obj
|
12 0 obj
|
||||||
<< /Stream1 7 0 R /This-is-Stream2 true /Length 18 >>
|
<< /Stream1 8 0 R /This-is-Stream2 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 2.
|
This is stream 2.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
xref
|
xref
|
||||||
0 12
|
0 13
|
||||||
0000000000 65535 f
|
0000000000 65535 f
|
||||||
0000000015 00000 n
|
0000000015 00000 n
|
||||||
0000000064 00000 n
|
0000000064 00000 n
|
||||||
0000000125 00000 n
|
0000000135 00000 n
|
||||||
0000000184 00000 n
|
0000000194 00000 n
|
||||||
0000000301 00000 n
|
0000000311 00000 n
|
||||||
0000000379 00000 n
|
0000000389 00000 n
|
||||||
0000000523 00000 n
|
0000000479 00000 n
|
||||||
0000000628 00000 n
|
0000000624 00000 n
|
||||||
0000000721 00000 n
|
0000000729 00000 n
|
||||||
0000000828 00000 n
|
0000000822 00000 n
|
||||||
0000000859 00000 n
|
0000000930 00000 n
|
||||||
trailer << /QTest 2 0 R /Root 1 0 R /Size 12 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
0000000961 00000 n
|
||||||
|
trailer << /QTest 2 0 R /Root 1 0 R /Size 13 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
||||||
startxref
|
startxref
|
||||||
964
|
1066
|
||||||
%%EOF
|
%%EOF
|
||||||
|
@ -4,39 +4,45 @@
|
|||||||
<< /Pages 3 0 R /Type /Catalog >>
|
<< /Pages 3 0 R /Type /Catalog >>
|
||||||
endobj
|
endobj
|
||||||
2 0 obj
|
2 0 obj
|
||||||
<< /O1 4 0 R /O2 5 0 R /O3 6 0 R /This-is-QTest true >>
|
<< /O1 4 0 R /O2 5 0 R /O3 6 0 R /O4 7 0 R /This-is-QTest true >>
|
||||||
endobj
|
endobj
|
||||||
3 0 obj
|
3 0 obj
|
||||||
<< /Count 2 /Kids [ 7 0 R 6 0 R ] /Type /Pages >>
|
<< /Count 2 /Kids [ 8 0 R 6 0 R ] /Type /Pages >>
|
||||||
endobj
|
endobj
|
||||||
4 0 obj
|
4 0 obj
|
||||||
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 5 0 R >> 2.17828 ] >> /salad /O2 5 0 R /Stream1 8 0 R ]
|
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 5 0 R >> 2.17828 ] >> /salad /O2 5 0 R /Stream1 9 0 R ]
|
||||||
endobj
|
endobj
|
||||||
5 0 obj
|
5 0 obj
|
||||||
<< /K1 [ 2.236 /O1 4 0 R 1.732 ] /O1 4 0 R /This-is-O2 true >>
|
<< /K1 [ 2.236 /O1 4 0 R 1.732 ] /O1 4 0 R /This-is-O2 true >>
|
||||||
endobj
|
endobj
|
||||||
6 0 obj
|
6 0 obj
|
||||||
<< /Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >>
|
<< /Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 11 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >>
|
||||||
endobj
|
endobj
|
||||||
7 0 obj
|
7 0 obj
|
||||||
<< /Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 12 0 R >> /ProcSet 13 0 R >> /Type /Page >>
|
<< /Filter /LZWDecode /Length 22 >>
|
||||||
|
stream
|
||||||
|
Not really compresed.
|
||||||
|
endstream
|
||||||
endobj
|
endobj
|
||||||
8 0 obj
|
8 0 obj
|
||||||
<< /Stream2 14 0 R /This-is-Stream1 true /Length 18 >>
|
<< /Contents 12 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 13 0 R >> /ProcSet 14 0 R >> /Type /Page >>
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<< /Stream2 15 0 R /This-is-Stream1 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 1.
|
This is stream 1.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
9 0 obj
|
10 0 obj
|
||||||
<< /Length 47 >>
|
<< /Length 47 >>
|
||||||
stream
|
stream
|
||||||
BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
|
BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
10 0 obj
|
11 0 obj
|
||||||
<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
|
<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
|
||||||
endobj
|
endobj
|
||||||
11 0 obj
|
12 0 obj
|
||||||
<< /Length 44 >>
|
<< /Length 44 >>
|
||||||
stream
|
stream
|
||||||
BT
|
BT
|
||||||
@ -46,36 +52,37 @@ BT
|
|||||||
ET
|
ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
12 0 obj
|
13 0 obj
|
||||||
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
||||||
endobj
|
endobj
|
||||||
13 0 obj
|
14 0 obj
|
||||||
[ /PDF /Text ]
|
[ /PDF /Text ]
|
||||||
endobj
|
endobj
|
||||||
14 0 obj
|
15 0 obj
|
||||||
<< /Stream1 8 0 R /This-is-Stream2 true /Length 18 >>
|
<< /Stream1 9 0 R /This-is-Stream2 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 2.
|
This is stream 2.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
xref
|
xref
|
||||||
0 15
|
0 16
|
||||||
0000000000 65535 f
|
0000000000 65535 f
|
||||||
0000000015 00000 n
|
0000000015 00000 n
|
||||||
0000000064 00000 n
|
0000000064 00000 n
|
||||||
0000000135 00000 n
|
0000000145 00000 n
|
||||||
0000000200 00000 n
|
0000000210 00000 n
|
||||||
0000000317 00000 n
|
0000000327 00000 n
|
||||||
0000000395 00000 n
|
0000000405 00000 n
|
||||||
0000000577 00000 n
|
0000000588 00000 n
|
||||||
0000000723 00000 n
|
0000000678 00000 n
|
||||||
0000000828 00000 n
|
0000000824 00000 n
|
||||||
0000000924 00000 n
|
0000000929 00000 n
|
||||||
0000001024 00000 n
|
0000001026 00000 n
|
||||||
0000001118 00000 n
|
0000001126 00000 n
|
||||||
0000001226 00000 n
|
0000001220 00000 n
|
||||||
0000001257 00000 n
|
0000001328 00000 n
|
||||||
trailer << /QTest 2 0 R /Root 1 0 R /Size 15 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
0000001359 00000 n
|
||||||
|
trailer << /QTest 2 0 R /Root 1 0 R /Size 16 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
||||||
startxref
|
startxref
|
||||||
1362
|
1464
|
||||||
%%EOF
|
%%EOF
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<< /Pages 6 0 R /Type /Catalog >>
|
<< /Pages 6 0 R /Type /Catalog >>
|
||||||
endobj
|
endobj
|
||||||
2 0 obj
|
2 0 obj
|
||||||
<< /O1 7 0 R /O2 8 0 R /O3 9 0 R /This-is-QTest true >>
|
<< /O1 7 0 R /O2 8 0 R /O3 9 0 R /O4 10 0 R /This-is-QTest true >>
|
||||||
endobj
|
endobj
|
||||||
3 0 obj
|
3 0 obj
|
||||||
<< /Length 20 >>
|
<< /Length 20 >>
|
||||||
@ -25,39 +25,45 @@ more data for stream
|
|||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
6 0 obj
|
6 0 obj
|
||||||
<< /Count 3 /Kids [ 10 0 R 11 0 R 9 0 R ] /Type /Pages >>
|
<< /Count 3 /Kids [ 11 0 R 12 0 R 9 0 R ] /Type /Pages >>
|
||||||
endobj
|
endobj
|
||||||
7 0 obj
|
7 0 obj
|
||||||
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 8 0 R >> 2.17828 ] >> /salad /O2 8 0 R /Stream1 12 0 R ]
|
[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 8 0 R >> 2.17828 ] >> /salad /O2 8 0 R /Stream1 13 0 R ]
|
||||||
endobj
|
endobj
|
||||||
8 0 obj
|
8 0 obj
|
||||||
<< /K1 [ 2.236 /O1 7 0 R 1.732 ] /O1 7 0 R /This-is-O2 true >>
|
<< /K1 [ 2.236 /O1 7 0 R 1.732 ] /O1 7 0 R /This-is-O2 true >>
|
||||||
endobj
|
endobj
|
||||||
9 0 obj
|
9 0 obj
|
||||||
<< /Contents 13 0 R /MediaBox [ 0 0 612 792 ] /OtherPage 11 0 R /Parent 6 0 R /Resources << /Font << /F1 14 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >>
|
<< /Contents 14 0 R /MediaBox [ 0 0 612 792 ] /OtherPage 12 0 R /Parent 6 0 R /Resources << /Font << /F1 15 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >>
|
||||||
endobj
|
endobj
|
||||||
10 0 obj
|
10 0 obj
|
||||||
<< /Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet 17 0 R >> /Type /Page >>
|
<< /Filter /LZWDecode /Length 22 >>
|
||||||
|
stream
|
||||||
|
Not really compresed.
|
||||||
|
endstream
|
||||||
endobj
|
endobj
|
||||||
11 0 obj
|
11 0 obj
|
||||||
<< /Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources << /Font << /F1 14 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3-other-page true /Type /Page >>
|
<< /Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources << /Font << /F1 17 0 R >> /ProcSet 18 0 R >> /Type /Page >>
|
||||||
endobj
|
endobj
|
||||||
12 0 obj
|
12 0 obj
|
||||||
<< /Stream2 19 0 R /This-is-Stream1 true /Length 18 >>
|
<< /Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 6 0 R /Resources << /Font << /F1 15 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3-other-page true /Type /Page >>
|
||||||
|
endobj
|
||||||
|
13 0 obj
|
||||||
|
<< /Stream2 20 0 R /This-is-Stream1 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 1.
|
This is stream 1.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
13 0 obj
|
14 0 obj
|
||||||
<< /Length 47 >>
|
<< /Length 47 >>
|
||||||
stream
|
stream
|
||||||
BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
|
BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
14 0 obj
|
15 0 obj
|
||||||
<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
|
<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
|
||||||
endobj
|
endobj
|
||||||
15 0 obj
|
16 0 obj
|
||||||
<< /Length 44 >>
|
<< /Length 44 >>
|
||||||
stream
|
stream
|
||||||
BT
|
BT
|
||||||
@ -67,47 +73,48 @@ BT
|
|||||||
ET
|
ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
16 0 obj
|
17 0 obj
|
||||||
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
|
||||||
endobj
|
endobj
|
||||||
17 0 obj
|
18 0 obj
|
||||||
[ /PDF /Text ]
|
[ /PDF /Text ]
|
||||||
endobj
|
endobj
|
||||||
18 0 obj
|
19 0 obj
|
||||||
<< /Length 47 >>
|
<< /Length 47 >>
|
||||||
stream
|
stream
|
||||||
BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
|
BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
19 0 obj
|
20 0 obj
|
||||||
<< /Stream1 12 0 R /This-is-Stream2 true /Length 18 >>
|
<< /Stream1 13 0 R /This-is-Stream2 true /Length 18 >>
|
||||||
stream
|
stream
|
||||||
This is stream 2.
|
This is stream 2.
|
||||||
endstream
|
endstream
|
||||||
endobj
|
endobj
|
||||||
xref
|
xref
|
||||||
0 20
|
0 21
|
||||||
0000000000 65535 f
|
0000000000 65535 f
|
||||||
0000000015 00000 n
|
0000000015 00000 n
|
||||||
0000000064 00000 n
|
0000000064 00000 n
|
||||||
0000000135 00000 n
|
0000000146 00000 n
|
||||||
0000000204 00000 n
|
0000000215 00000 n
|
||||||
0000000259 00000 n
|
0000000270 00000 n
|
||||||
0000000329 00000 n
|
0000000340 00000 n
|
||||||
0000000402 00000 n
|
0000000413 00000 n
|
||||||
0000000520 00000 n
|
0000000531 00000 n
|
||||||
0000000598 00000 n
|
0000000609 00000 n
|
||||||
0000000799 00000 n
|
0000000810 00000 n
|
||||||
0000000946 00000 n
|
0000000901 00000 n
|
||||||
0000001141 00000 n
|
0000001048 00000 n
|
||||||
0000001247 00000 n
|
0000001243 00000 n
|
||||||
0000001344 00000 n
|
0000001349 00000 n
|
||||||
0000001444 00000 n
|
0000001446 00000 n
|
||||||
0000001538 00000 n
|
0000001546 00000 n
|
||||||
0000001646 00000 n
|
0000001640 00000 n
|
||||||
0000001677 00000 n
|
0000001748 00000 n
|
||||||
0000001774 00000 n
|
0000001779 00000 n
|
||||||
trailer << /QTest 2 0 R /QTest2 [ 3 0 R 4 0 R 5 0 R ] /Root 1 0 R /Size 20 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
0000001876 00000 n
|
||||||
|
trailer << /QTest 2 0 R /QTest2 [ 3 0 R 4 0 R 5 0 R ] /Root 1 0 R /Size 21 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
|
||||||
startxref
|
startxref
|
||||||
1880
|
1982
|
||||||
%%EOF
|
%%EOF
|
||||||
|
BIN
qpdf/qtest/qpdf/split-exp-1.pdf
Normal file
BIN
qpdf/qtest/qpdf/split-exp-1.pdf
Normal file
Binary file not shown.
@ -1210,7 +1210,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||||||
|
|
||||||
QPDFWriter w(pdf, "a.pdf");
|
QPDFWriter w(pdf, "a.pdf");
|
||||||
w.setStaticID(true);
|
w.setStaticID(true);
|
||||||
w.setStreamDataMode(qpdf_s_preserve);
|
w.setCompressStreams(false);
|
||||||
|
w.setDecodeLevel(qpdf_dl_generalized);
|
||||||
w.write();
|
w.write();
|
||||||
}
|
}
|
||||||
else if (n == 28)
|
else if (n == 28)
|
||||||
|
Loading…
Reference in New Issue
Block a user