diff --git a/ChangeLog b/ChangeLog index 9d9e353f..a8775f57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2021-02-25 Jay Berkenbilt + * 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 diff --git a/examples/pdf-custom-filter.cc b/examples/pdf-custom-filter.cc index 1426e5fc..55ace6e2 100644 --- a/examples/pdf-custom-filter.cc +++ b/examples/pdf-custom-filter.cc @@ -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 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()) diff --git a/examples/pdf-invert-images.cc b/examples/pdf-invert-images.cc index 72a15f2c..bb8541e3 100644 --- a/examples/pdf-invert-images.cc +++ b/examples/pdf-invert-images.cc @@ -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 self); private: - QPDF other; - // Map og in original to copied image std::map 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