Update examples to use copyStream()

This commit is contained in:
Jay Berkenbilt 2021-02-25 12:32:45 -05:00
parent 0f0f60109b
commit 3bdefb4c2d
3 changed files with 16 additions and 28 deletions

View File

@ -1,5 +1,10 @@
2021-02-25 Jay Berkenbilt <ejb@ql.org>
* Update StreamDataProvider examples to use copyStream() when they
want to get to the original stream data from the provider. Prior
to 10.2.0, we had to copy the stream to another QPDF, but now we
can just use copyStream().
* Bug fix/behavior change: when QPDF::replaceObject or
QPDF::swapObjects is called, existing QPDFObjectHandle instances
will now notice the change. This removes a long-standing source of

View File

@ -198,8 +198,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
// original stream data is no longer directly accessible. Trying
// to retrieve the stream data would be an infinite loop because
// it would just end up calling provideStreamData again. This is
// why maybeReplace uses a stashed copy of the original stream
// from the "other" QPDF object.
// why maybeReplace uses a stashed copy of the original stream.
// Additional explanation can be found in the method
// implementations.
@ -223,11 +222,6 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
// we are replacing. We need this to create a new stream.
QPDF* pdf;
// This second QPDF instance gives us a place to copy streams to
// so that we can access the original stream data of the streams
// whose data we are replacing.
QPDF other;
// Map the object/generation in original file to the copied stream
// in "other". We use this to retrieve the original data.
std::map<QPDFObjGen, QPDFObjectHandle> copied_streams;
@ -241,10 +235,6 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
StreamReplacer::StreamReplacer(QPDF* pdf) :
pdf(pdf)
{
// Our "other" QPDF is just a place to stash streams. It doesn't
// have to be a valid PDF with pages, etc. We are never going to
// write this out.
this->other.emptyPDF();
}
bool
@ -375,9 +365,11 @@ StreamReplacer::registerStream(
if (should_replace)
{
// Copy the stream to another QPDF object so we can get to the
// original data from the stream data provider.
this->copied_streams[og] = this->other.copyForeignObject(stream);
// Copy the stream so we can get to the original data from the
// stream data provider. This doesn't actually copy any data,
// but the copy retains the original stream data after the
// original one is modified.
this->copied_streams[og] = stream.copyStream();
// Update the stream dictionary with any changes.
auto dict = stream.getDict();
for (auto const& k: dict_updates.getKeys())

View File

@ -25,15 +25,13 @@ void usage()
// allocate memory up front for the objects. We want to replace the
// stream data with a function of the original stream data. In order
// to do this without actually holding all the images in memory, we
// create another QPDF object and copy the streams. Copying the
// streams doesn't actually copy the data. Internally, the qpdf
// library is holding onto the location of the stream data in the
// original file, which makes it possible for the StreamDataProvider
// to access it when it needs it.
// create copies of the streams. Copying the streams doesn't actually
// copy the data. Internally, the qpdf library is holding onto the
// location of the original stream data, which makes it possible for
// the StreamDataProvider to access it when it needs it.
class ImageInverter: public QPDFObjectHandle::StreamDataProvider
{
public:
ImageInverter();
virtual ~ImageInverter()
{
}
@ -45,16 +43,9 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
PointerHolder<QPDFObjectHandle::StreamDataProvider> self);
private:
QPDF other;
// Map og in original to copied image
std::map<QPDFObjGen, QPDFObjectHandle> copied_images;
};
ImageInverter::ImageInverter()
{
this->other.emptyPDF();
}
void
ImageInverter::registerImage(
QPDFObjectHandle image,
@ -77,7 +68,7 @@ ImageInverter::registerImage(
{
return;
}
this->copied_images[og] = this->other.copyForeignObject(image);
this->copied_images[og] = image.copyStream();
// Register our stream data provider for this stream. Future calls
// to getStreamData or pipeStreamData will use the new